diff --git a/Documentation/arm/ep93xx/config.txt b/Documentation/arm/ep93xx/config.txt
new file mode 100644
index 0000000..9d13a15
--- /dev/null
+++ b/Documentation/arm/ep93xx/config.txt
@@ -0,0 +1,207 @@
+-------------------------------------------------------------------------
+config.txt
+
+Information on configuration options in the Linux kernel for the Cirrus
+EP93xx.
+
+Note to developers:  Let's stick to the essentials on "how to turn things
+on in the Linux build."  This information is presented from the standpoint
+of someone doing a build, looking at a make menuconfig screen.  If what you
+are describing doesn't fit here, it should get its own document to go into
+the level of detail you feel is most practicle.
+-------------------------------------------------------------------------
+
+All options configured as built-in drivers, not loadable modules.
+So on options that are selected by < >, select <*>, not <M>.  To
+do this either hit 'y' or hit the space bar twice.
+
+
+----------------
+Audio
+----------------
+Needed by:
+Needs: DMA Support, dev fs.
+
+Ac97 and I2S audio are currently mutually exclusive.
+
+To enable Ac97 Audio:
+	Go into "Sound --->"
+	Enable "Sound Support"
+	Enable "OSS sound modules"
+	Select "Ac97" for "Cirrus EP93xx Sound Support"
+
+To enable I2S Audio:
+	Go into "Sound --->"
+	Enable "Sound Support"
+	Enable "OSS sound modules"
+	Select "I2S" for "Cirrus EP93xx Sound Support"
+	If you have an EDB9312 board, select "CS4228A" for "Cirrus I2S Codec Support"
+	If you have an EDB9301 board, select "CS4271" for "Cirrus I2S Codec Support"
+
+
+----------------
+Dev Fs
+----------------
+	DEVFS support is no longer available.
+	Please consider using udev or create device nodes manually instead.
+	You might also need to adapt your startup scripts and userspace
+	apps.
+
+----------------
+DMA
+----------------
+Needed by: Audio, IDE/DMA
+Needs:
+
+To enable DMA:
+	Go into "System Type --->"
+	Go into "EP93XX Options --->"
+	Enable "EP93XX Internal DMA Support"
+
+
+----------------
+IDE
+----------------
+Needed by:
+Needs:
+	To Turn on IDE support for the platform, you need to enable
+General IDE support first - CONFIG_BLK_DEV_IDE, CONFIG_BLK_DEV_IDEDISK,
+CONFIG_BLK_DEV_IDECD.
+
+	If multiword DMA and ultra DMA support is needed, general DMA support for
+the platform must be enabled first.  See DMA section of this document for
+options to enable DMA for the platform.
+
+	If CDROM support is enabled, ISO9660 file system support should be enabled.
+If a DVD support is needed, UDF file system support should be enabled.
+
+To enable CONFIG_BLK_DEV_IDE:
+	Go into "ATA /ATAPI/MFM/RLL support --->"
+	Enable "ATA/ATAPI/MFM/RLL support"
+	Go into "IDE, ATA, and ATAPI Block devices --->"
+	Enable "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support"
+
+To enable CONFIG_BLK_DEV_IDEDISK:
+	Go into "ATA /ATAPI/MFM/RLL support --->"
+	Go into "IDE, ATA, and ATAPI Block devices --->"
+	Enable "Include IDE/ATA-2 DISK support"
+
+To enable CONFIG_BLK_DEV_IDECD:
+	Go into "ATA /ATAPI/MFM/RLL support --->"
+	Go into "IDE, ATA, and ATAPI Block devices --->"
+	Enable "Include IDE/ATAPI CDROM support"
+
+To enable EP93XX IDE (PIO mode only):
+	Go into "ATA /ATAPI/MFM/RLL support --->"
+	Go into "IDE, ATA, and ATAPI Block devices --->"
+	Enable "EP93XX IDE Support"
+
+To enable EP93XX IDE DMA (mdma and udma modes):
+	Go into "ATA /ATAPI/MFM/RLL support --->"
+	Go into "IDE, ATA, and ATAPI Block devices --->"
+	Enable "EP93XX IDE DMA support"
+
+To enabled ISO 9660 file system support:
+	Go into "File systems --->"
+	Enable "ISo 9660 CDROM file system support"
+	Enable "Microsoft Joliet CDROM extensions"
+
+To enable UDF file system support:
+	Go into "File systems --->"
+	Enable "UDF file system support (read only)"
+
+See also /Documentation/arm/ep93xx/ide-hard-drive-support.txt for information
+on configuring the hard drive.
+
+----------------
+IrDA
+----------------
+Described in /Documentation/arm/ep93xx/irda.txt
+
+
+----------------
+NFS
+----------------
+Described in /Documentation/arm/ep93xx/nfs.txt
+
+
+----------------
+Serial Terminal
+----------------
+To enable serial terminal:
+	Go into "Character devices --->"
+	Turn off "Support for console on virtual terminal"
+	Turn off "Virtual terminal"
+	Go into "Serial drivers --->"
+	Turn on "Cirrus EP93xx ARM AMBA serial port support"
+	Turn on "Support for console on EP93xx serial port"
+
+Serial terminal is the bottom jack of J7.
+Format is 57600,8N1, flow control: "none".
+
+
+----------------
+Touchscreen
+----------------
+To enable touchscreen driver:
+	Go into "Character devices --->"
+	Go into "Mice --->"
+	Enable "Mouse Support (not serial and bus mice)"
+	Disable "PS/2 Mouse (aka "auxiliary device") support
+	Enable "EP93xx touch screen support"
+
+
+----------------
+USB
+----------------
+The order of all of the following statements is critical as some options enable
+other options.
+
+To enable basic USB support(required for all devices listed below):
+   Go into "USB support --->"
+   Enable "Support for USB"
+   Enable "Preliminary USB device filesystem" (optional)
+   Enable "EP93XX OHCI-compatible host interface support"
+
+To enable support for USB mouse:
+   Go into "Input core support --->"
+   Enable "Input core support"
+   Enable "Mouse support"
+
+   Go back to the top level of menuconfig
+
+   Go into "USB support --->"
+   Enable "USB Human Interface Device (full HID) support"
+   Enable "HID input layer support"
+
+To enable support for USB Keyboard:
+   Go into "Input core support --->"
+   Enable "Input core support"
+   Enable "Keyboard support"
+
+   Go back to the top level of menuconfig
+
+   Go into "USB support --->"
+   Enable "USB Human Interface Device (full HID) support"
+   Enable "HID input layer support"
+
+   Go back to the top level of menuconfig
+   Go into "Character devices --->"
+   Set EP93xx Keyboard Support to "USB"
+
+To enable USB Mass Storage support:
+   Go into "SCSI Support --->"
+   Enable "SCSI Support"
+   Enable "SCSI disk support"
+
+   Go back to the top level of menuconfig
+
+   Go into "USB support --->"
+   Enable "USB Mass Storage support"
+
+   Go back to the top level of menuconfig
+
+(optional - Do this if you want to mount a USB flash drive)
+   Go into "File systems --->"
+   Enable "DOS FAT fs support"
+   Enable "VFAT (Windows-95) fs support"
diff --git a/Documentation/arm/ep93xx/dma.txt b/Documentation/arm/ep93xx/dma.txt
new file mode 100644
index 0000000..e7fc1bb
--- /dev/null
+++ b/Documentation/arm/ep93xx/dma.txt
@@ -0,0 +1,300 @@
+Support Functions for the Cirrus Logic ep93xx Internal DMA controller.
+==============================================================================
+
+State diagram
+
+States:
+Uninitialized (!pause & !xfer_enable)
+Stopped (pause & !xfer_enable)
+Transferring (!pause & xfer_enable)
+Stopped by starvation (pause & xfer_enable)
+
+                                    _______________
+               request ----------> |               | <------- free -----------
+                                   | Uninitialized |                        /\
+                                   |_______________|                        ||
+                                                                            ||
+                                        ||                                  ||
+                                  init  ||   ------------------------------>||
+                                        ||   /\                             ||
+                                        \/   ||                             ||
+                                      _________                             ||
+  ||<-- start && new_buffers <= 1 -- |         | <----- flush <---------    ||
+  ||                                 | Stopped |                      /\    ||
+  ||         ---------> pause------> |_________| -------------------->||    ||
+  ||         /\                                                             ||
+  ||         ||                        ||                                   ||
+  ||         ||                        || start && new_buffers > 1          ||
+  ||         ||                        ||                                   ||
+  ||         ||                        \/                                   ||
+  ||         ||                   ______________                            ||
+  ||         ||                  |              | ------------------------->||
+  ||         ||<---------------- | Transferring | ------------------->||    ||
+  ||         ||                  |______________|                     ||    ||
+  ||         ||                                                       ||    ||
+  ||         ||                             ||                        ||    ||
+  ||         ||                             || new_buffers = 0        ||    ||
+  ||         ||                       /\    ||                        ||    ||
+  ||         ||                       ||    \/                        ||    ||
+  ||         ||       new_buffers > 1 ||                              ||    ||
+  ||         ||                       ||                              ||    ||
+  ||         ||                 _______________________               ||    ||
+  ||         ||<-------------- |                       |              ||    ||
+  \/                           | Stopped by starvation | ------------>||    ||
+  ---------------------------> |_______________________|              ||    ||
+                                                                      ||    ||
+                                ||    /\                              ||    ||
+                                ||    ||                              ||    ||
+                                ||    ||<-------- flush <---------------    ||
+                                ||                                          ||
+                                ------------------------------------------->||
+
+
+------------------------------------------------------------------------------
+EP93XX DMA API Functions
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_request(int * handle, const char * device_id,
+                           ep93xx_dma_dev_t device)
+
+This function will allocate a DMA channel for a particular hardware
+peripheral.  Before initiating  a transfer on the allocated channel, the
+channel has to be setup, and buffers have to be added to the channel.
+
+Parameters:
+    int * handle                A pointer which is filled in with a unique
+                                integer value, or handle. The handle is used
+                                to verify the validity of each call to
+                                access the dma channel.
+
+    const char * device_id      string which is the name of the device
+                                attached to the dma channel.
+
+    ep93xx_dma_dev_t device     hardware port to attach to the dma channel
+
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_free(int handle)
+
+This function disables and powers down the dma channel, and releases it
+for future requests. Buffers queued up for the specified channel are
+released without transferring.
+
+Parameters:
+    int handle              A unique integer value, assigned
+                            during open, used to verify the validity of
+                            this call to access a DMA channel.
+
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_add_buffer(int handle, unsigned int source,
+                              unsigned int dest, unsigned int size
+                              unsigned int last, unsigned int buf_id)
+
+This function adds a buffer entry to the DMA buffer queue.  If the channel is
+in the active transfer state, the buffer is immediately transferred,
+otherwise the buffer is not transferred until a start or resume
+command is issued. A -1 is returned if an error occurs, otherwise
+a 0 is returned.
+
+Parameter:
+    int handle                  A unique integer value, assigned
+                                during open, used to verify the validity of
+                                this call to access a dma channel.
+
+    unsigned int source         physical address for the start of this
+                                buffer.
+
+    unsigned int source         physical address destination of the data.
+
+    unsigned int size           buffer size in bytes
+
+    unsigned int last           1 if this is the last buffer in the transfer.
+                                If 1, disable the NFBint so we aren't
+                                interrupted for another buffer
+                                when we know there won't be another.
+
+    unsigned int buf_id         Unique value used to identify this buffer.
+
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_remove_buffer(int handle, unsigned int * address,
+                                 unsigned int * size)
+
+This function removes a buffer entry from the DMA buffer queue. If a buffer
+was removed successfully, a 0 is returned, otherwise -1 is returned.
+
+Parameter:
+    int handle                  A unique integer value, assigned
+                                during open, used to verify the validity of
+                                this call to access a dma channel.
+
+    unsigned int * buf_id       Pointer to an integer which is filled in
+                                with the buffer id..
+
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_queue_full(int handle)
+
+This function queries to determine if the buffer queue for the specified
+channel is full. A return value of 1 indicates the queue is not full, and a
+0 indicates the queue is full.
+
+Parameters:
+    int handle              A unique integer value, assigned
+                            during open, used to verify the validity of
+                            this call to access a dma channel.
+
+------------------------------------------------------------------------------
+
+	int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
+                                unsigned int * total)
+
+This function fills in the buffer ID of the current buffer and fills in the
+total bytes transferred on the channel. If no buffer is active on the channel,
+buf_id is filled in with a -1, otherwise it is the active buffer.
+
+Parameter:
+    int handle              A unique integer value, assigned
+                            during open, used to verify the validity of
+                            this call to access a dma channel.
+
+    unsigned int * buf_id   pointer to an integer which is filled in with
+                            buffer ID of the buffer currently
+                            transferring.
+
+    unsigned int * total    pointer to an integer which is filled in
+                            with the total bytes transferred on the channel.
+
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_config(int handle, unsigned int flags_m2m,
+                          unsigned int flags_m2p, dma_callback callback,
+                          unsigned int user_data)
+
+This function configures the DMA channel registers and installs a dma
+callback function into the DMA instance.  The DMA callback function is
+defined by the driver which is using this DMA channel. It is called in
+response to DMA interrupts, at the end of the DMA channel's interrupt
+handler.  A -1 is returned if an error occurs, otherwise a 0 is returned.
+
+Parameter:
+    int handle              A unique integer value, assigned
+                            during open, used to verify the validity of
+                            this call to access a dma channel.
+
+    unsigned int flags_m2m  Flags used for M2M channel configuration.
+
+    unsigned int flags_m2p  Flags used for M2P/P2M channel
+                            configuration.
+
+    dma_callback callback   Pointer to the callback function which will
+                            be called at the end of the dma interrupt
+                            service routine.
+
+    unsigned int user_data  Data defined by the driver installing the
+                            callback function.  This piece of data will
+                            be returned to the driver when the callback
+                            function is called.
+
+Callback function prototype:
+
+    void (* dma_callback)(ep93xx_dma_int_t interrupt,
+                          ep93xx_dma_dev_t device, unsigned int user_data)
+
+    Parameters:
+        ep93xx_dma_int_t interrupt
+            used by the DMA driver to inform the DMA callback
+            function of the type of DMA interrupt that happened.
+
+        ep93xx_dma_dev_t device
+            hardware port attached to the dma channel.
+
+        unsigned int user_data
+            is a value defined and passed in by the driver which
+            registered the callback function.
+
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_start(int handle, unsigned int channels,
+                         unsigned int * handles
+
+This function enables the DMA channel, and initiates the transfer.  If the
+peripheral interface calls for it, multiple DMA channels can be started
+with one call to this IOCTL.    A -1 is returned if an error occurs,
+otherwise a 0 is returned.
+
+Parameter:
+    int handle              A unique integer value, assigned
+                            during open, used to verify the validity of
+                            this call to access a dma channel.  For a start
+                            multiple, this handle can be the handle
+                            for any of the channels to be started.
+
+    unsigned int channels   Number of channels to start for this transfer.
+                            Specifically this applies to an audio interface
+                            where you can have up to 3 dma channels
+                            servicing a 6 audio channel output, in which case
+                            you need to initiate transfers on all 3 dma
+                            channels as closely together as possible. For
+                            the case of only one channel to be started, this
+                            field should be a 1.
+
+    unsigned int * handles  Pointer to an array of handles, one for
+                            each channel which is to be started.  If only one
+                            channel is to be started, this field should be
+                            NULL.
+
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_pause(int handle, unsigned int channels,
+                         unsigned int * handles)
+
+This function disables the DMA channel, pausing the transfer.  The
+position within the currently transferring buffer is saved, and restored upon
+restarting the transfer on this channel. If the peripheral interface calls
+for it, multiple DMA channels can be paused with one call to this IOCTL.
+A -1 is returned if an error occurs, otherwise a 0 is returned.
+
+Parameter:
+    int handle              A unique integer value, assigned
+                            during open, used to verify the validity of
+                            this call to access a dma channel.
+
+    unsigned int channels   Number of channels to pause for this
+                            transfer.  Specifically this applies to
+                            an audio interface where you can have
+                            up to 3 dma channels servicing a 6
+                            audio channel output, in which case you
+                            need to pause transfers on all 3 dma
+                            channels as closely together as possible.
+
+    unsigned int * handles  Pointer to an array of handles, one for
+                            each channel which is to be paused.
+
+NOTE: There is another way to pause the DMA channel - starve it.
+When the dma channel reaches the point where there are no buffers in
+the queue, but the interface has not been paused, then the dma instance
+will indicate that the channel is in the transfer state, but the
+channel itself is disabled until a new buffer is added to the queue
+If the channel is stopped via this method, a resume command is not
+required to restart a transfer.  A transfer is started immediately
+after two new buffers are added to the queue.  The reason for two is
+so that both channel buffer descriptors can be programmed with valid
+buffers
+
+------------------------------------------------------------------------------
+
+    int ep93xx_dma_flush(int handle)
+
+This function completely flushes all queued buffers and any on going
+DMA transfers on a given channel.  If the dma channel is in the
+active transfer state, once two buffers are added to the queue, the
+channel will begin transferring data right away.  If in the stop
+state, a start command must be issued before any new buffers are
+processed. A -1 is returned if an error occurs, otherwise a 0 is returned.
+
+Parameters:
+    int handle      A unique integer value, assigned
+                    during open, used to verify the validity of
+                    this call to access a dma channel.
diff --git a/Documentation/arm/ep93xx/status.txt b/Documentation/arm/ep93xx/status.txt
new file mode 100644
index 0000000..082c2dd
--- /dev/null
+++ b/Documentation/arm/ep93xx/status.txt
@@ -0,0 +1,288 @@
+#
+#   EP93xx driver support status
+#
+
+======================================================================
+(I) Introduction
+======================================================================
+
+The EP93xx are embedded System On Chip (SOC) processors produced
+by Cirrus (www.cirrus.com). They provided support based on 2.4.21-rmk1
+kernels, and they said that there might be 2.6.x support some day.
+Meanwhile they've released a 2.6.8.1 based kernel called "ursus".
+
+Currently we still have got a communication problem with cirrus,
+for some reason it seems to be impossible to directly talk to their
+developers. Hope this will change some day, but we really cannot afford
+to just sit down and wait.
+
+The purpose of this file is to document success and todo's.
+
+  - Section II describes hardware support, organized according to the
+    EP9315 datasheet.  Other device datasheets are ordered similarly,
+    though section numbers may vary.
+
+  - Section III contains other miscellaneous information.
+
+The latest version of this document may be found at:
+
+  linux/Documentation/arm/ep93xx/status.txt
+
+projects homepage can be found at:
+
+  http://members.inode.at/m.burian/ep93xx/index.html
+
+
+======================================================================
+(II)   Hardware Support
+======================================================================
+
+These section numbers mirror the EP9315 datasheet.
+
+1. Introduction
+---------------
+N/A
+
+2. ARM920T Core and Advanced High-Speed Bus (AHB)
+-------------------------------------------------
+We have standard Linux 2.6 support for ARM920T Core. Thumb support
+is pretty shaky, as most people do not seem to use Thumb in the
+kernel. Address translation uses 16K small pages exclusively (FIXME:
+is this true?)
+
+3. MaverickCrunch Coprocessor
+-----------------------------
+People have started with forward porting. Note that there's more
+to it than just kernel support. You also need to have a toolchain
+supporting it. We're in need of a comprehensive HOWTO that explains kernel,
+toolchain and userspace aspects to a point where average developers can use it
+
+
+4. Boot ROM
+-----------
+Well, not really kernel related, most people start with redboot. Make
+sure to use a version that passes the correct machine type.  Some
+people also started porting blob / uboot.
+
+If any support is added for this device, it will likely be a simple
+char device that allows you to read the contents of the boot rom
+for interests sake.
+
+5. System Controller
+--------------------
+System Controllers registers are set by startup code and by individual
+drivers as needed, we try to keep the processor dependent stuff to
+a minimum.
+
+Ray really wants to overhaul the system configuration stuff and move
+towards something like the SA1100 people are doing. It should make
+things a lot cleaner for drivers that share physical pins, or for
+multifunctional blocks that require several drivers (eg: UART2 with
+IrDA support)
+
+There is currently no dynamic clock control support.  We'll probably
+want to tie into the CPUfreq code at some point.
+
+There is no support for querying the system boot configuration or
+last reset source.
+
+There is no power management support.  Individual drivers may power
+up silicon blocks as required. Some research is needed to map the
+EP93xx power states onto the ACPI or PCI states that everyone seems
+to use.
+
+There is no support for the TICK and WATCHDOGEXPIRED interrupts
+generated by this block.
+
+There is no support for the AHB bus arbiter priority settings.
+
+6. Vectored Interrupt Controller
+--------------------------------
+Since we can boot this can't be done dead wrong. Standard level-triggered
+interrupt support is present.
+
+No FIQ interrupts are supported.
+
+Support for demultiplexing GPIO IRQs is available.
+
+
+7. Raster Engine With Analog/LCD Integrated Timing and Interface
+----------------------------------------------------------------
+
+Michael has rewritten large parts of the framebuffer driver based on
+skeleton.c. You need to adapt this in case you can't live with
+the standard display(s) that are included. Framebuffer is fixed
+size, you can change some settings at compile time, though.
+TODO: clean ups, different resolutions, etc
+
+
+8. Graphics Accelerator
+-----------------------
+not available yet, will be done after the framebuffer code has been
+cleaned up.
+
+
+9. 1/10/100 Mbps Ethernet LAN Controller
+----------------------------------------
+Supported. Driver has been reviewed and cleaned up.
+Uses generic mii routines now. It might be possible
+to use DMA - but in that case we'd need to find a
+workaround to get around the fact that it can only
+transfer 32bit aligned data, while we'd need to transfer
+data that's only 16 bit aligned.
+
+NICE-TO-HAVE: Could be ported to use NAPI.
+
+10. DMA Controller
+------------------
+There is some code and documentation ported forward from the Cirrus
+2.4 port.
+
+11. Universal Serial Bus Host Controller
+----------------------------------------
+Ray has written some glue code to plug the OHCI host controller into
+the Linux 2.6 USB stack.  This has been tested on an EDB9301 board with
+a single port populated.  A serial dongle worked fine, and several
+different flash keys seem to work okay with the USB mass storage
+driver using SCSI disk emulation.  This hasn't really been stress tested
+yet, but initial results look very encouraging.
+
+12. Static Memory Controller
+----------------------------
+Not sure how much kernel support is required here. Flash and memory
+timing needs to be setup by the bootloader, so there's not much
+that needs to be done here.
+
+No support for PCMCIA at this time.
+
+13. SDRAM, SyncROM, and SyncFLASH Controller
+--------------------------------------------
+Again, this is probably the bootloaders problem.
+
+There is an errata about system instability when suspending with
+an SDRAM bus speed over 50 MHz.  May need to tweak this if we start
+doing power management modes.
+
+14. UART1 With HDLC and Modem Control Signals
+---------------------------------------------
+We've got a driver to use this one as UART. No DMA support. FIFO support
+works. No HDLC support.  Needs some syscon support to cleanly handle
+HDLC and some modem signals.
+
+15. UART2
+---------
+We've got a driver to use this one as UART. No DMA support. FIFO support
+works. No IrDA SIR support.  Needs some syscon support to cleanly handle
+IrDA SIR.
+
+16. UART3 With HDLC Encoder
+---------------------------
+We've got a driver to use this one as UART. No DMA support. FIFO support
+works. No HDLC or RS-485 support.  Needs some syscon support to cleanly
+handle HDLC and RS-485.
+
+17. IRDA
+--------
+There is some code and documentation ported forward from the Cirrus
+2.4 port.  No idea how well this works, if at all.
+
+18. TIMERS
+----------
+Timer1 is used at 508 kHz with a reload value of 5080 to provide a 100 Hz
+tick signal to drive the kernel.
+
+Timer 2 and 3 are not currently used, nor is the debug timer 4.
+
+
+19. WATCHDOG Timer
+------------------
+Ray has some initial experimental code written (not pushed) to drive this.
+The onboard watchdog seems to have a 250 ms (!) timeout, while most PC
+dogs seem to have timeouts on the order of one minute or more. The standard
+approach of having a user level process open the watchdog device and
+kick it every so often seems like a bad idea here... a momentary system
+load spike could easily delay the monitor from being scheduled, and the
+system would reboot.
+
+Test out a watchdog monitor running at a high scheduling priority, or else
+design a kernel watchdog that kicks the dog every timer tick and exports
+a more reasonable timeout value to userspace.
+
+20. Real Time Clock With Software Trim
+--------------------------------------
+We did not bother to write a driver yet, it would require a design
+that ensures CPU is always powered on, and always have at least
+a 32kHz clock running. Most people prefer to use and external RTC.
+We've got support for the DS1337 RTC that seems to be popular on
+ep93xx based boards.
+
+21. I2S Controller
+------------------
+No support yet.  Klaus is working on it.
+
+22. AC97 Controller
+-------------------
+Supported but could need some testing.
+
+23. Synchronous Serial Port
+---------------------------
+Two driver are available, a forward port from the cirrus driver and
+another driver from Ray.
+
+24. Pulse Width Modulator
+-------------------------
+No support yet.
+
+25. Analog Touch Screen Interface
+---------------------------------
+People already played with this, AFAIK one would need a silicon
+revision > D1 (November 2004) for this to work properly.
+
+26. Keypad Interface
+--------------------
+We've got a driver for the 8x8 keypad. Chances are that you might
+want to create a custom keymap. There's also support for mobile
+phone like input (key 1 becomes -> A -> B -> C) if pressed repeatedly
+within half a second.
+
+27. IDE interface
+-----------------
+We've got IDE working in polling only, no DMA support so far.
+It needs to be cleaned up, too.
+
+28. GPIO
+--------
+Standard LED support for red and green leds is present.
+
+Michael has written an I2C bus driver using the new Linux device driver model.
+It supports an external DS1337 RTC device on the EECLK/EEDAT pins.
+
+Need some syscon support to cleanly handle the multi-function GPIO pins.
+
+Demultiplexing of GPIO interrupts is possible now.
+
+29. Security
+------------
+No information available on this, so support is unlikely in the near future.
+
+30. Glossary
+------------
+N/A
+
+
+======================================================================
+(III) Stuff not found in the datasheet
+======================================================================
+
+1. printascii hack has been removed from our tree.
+
+2. I2C driver
+We've got a bit banging I2C driver
+
+3. External RTC (DS1337)
+Setting and getting the time works
+TODO: advanced features, such as alarm, timer for /dev/rtc
+
+4. Controller Area Network (CAN)
+We have got a character device based driver for the OKI ML9620 CAN Controller.
+
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4b15f5f..f23341e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -103,6 +103,17 @@ config ARCH_EBSA110
 	  Ethernet interface, two PCMCIA sockets, two serial ports and a
 	  parallel port.
 
+config ARCH_EP93XX
+	bool "EP93xx"
+	select ARM_AMBA
+	help
+	  Say Y here to enable support for the Cirrus EP93xx CPU family
+	  and choose your specific CPU below.
+
+	  See the Cirrus web page for details.
+
+	  <http://www.cirrus.com/>
+
 config ARCH_CAMELOT
 	bool "Epxa10db"
 	help
@@ -219,6 +230,8 @@ endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
 
+source "arch/arm/mach-ep93xx/Kconfig"
+
 source "arch/arm/mach-epxa10db/Kconfig"
 
 source "arch/arm/mach-footbridge/Kconfig"
@@ -403,7 +416,7 @@ config NO_IDLE_HZ
 
 config ARCH_DISCONTIGMEM_ENABLE
 	bool
-	default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
+	default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) || ARCH_EP93XX
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)
@@ -415,7 +428,7 @@ source "mm/Kconfig"
 config LEDS
 	bool "Timer and CPU usage LEDs"
 	depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \
-		   ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \
+		   ARCH_EBSA285 || ARCH_EP93XX || ARCH_IMX || ARCH_INTEGRATOR || \
 		   ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
 		   ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
 		   ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE
@@ -432,7 +445,7 @@ config LEDS
 
 config LEDS_TIMER
 	bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
-			    MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
+			     MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
 	depends on LEDS
 	default y if ARCH_EBSA110
 	help
@@ -702,9 +715,10 @@ source "drivers/block/Kconfig"
 
 source "drivers/acorn/block/Kconfig"
 
-if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
-	|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
-	|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
+if PCMCIA || ARCH_CLPS7500 || ARCH_EP9312 || ARCH_EP9315 \
+	|| ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X \
+	|| ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK \
+	|| FOOTBRIDGE
 source "drivers/ide/Kconfig"
 endif
 
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 81bd219..924d31f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -92,6 +92,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET)   := 0x
  machine-$(CONFIG_ARCH_IOP3XX)	   := iop3xx
  machine-$(CONFIG_ARCH_IXP4XX)	   := ixp4xx
  machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
+ machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
  machine-$(CONFIG_ARCH_OMAP1)	   := omap1
  machine-$(CONFIG_ARCH_OMAP2)	   := omap2
   incdir-$(CONFIG_ARCH_OMAP)	   := omap
diff --git a/arch/arm/configs/adssphere_defconfig b/arch/arm/configs/adssphere_defconfig
new file mode 100644
index 0000000..195d80e
--- /dev/null
+++ b/arch/arm/configs/adssphere_defconfig
@@ -0,0 +1,1240 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12.2
+# Wed Jul  6 13:49:08 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+
+#
+# EP93xx
+#
+# CONFIG_ARCH_EP9301 is not set
+# CONFIG_ARCH_EP9302 is not set
+# CONFIG_ARCH_EP9312 is not set
+CONFIG_ARCH_EP9315=y
+# CONFIG_MACH_EDB9315 is not set
+CONFIG_MACH_ADSSPHERE=y
+# CONFIG_MACH_ZEFEERDZQ is not set
+CONFIG_EP93XX_DMA=y
+# CONFIG_ARCH_EP93XX_IDE is not set
+# CONFIG_EP93XX_SSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_EP93XX=y
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyAM0,38400 rw root=/dev/ram initrd=0x00600000,5m ramdisk_size=12288 rootfstype=ext2 mtdparts=flash:256k(boot),256k(bootvars),1536k(zImage),5m(ramdisk.gz),-(flashfs1) SERIALGETTY=ttyAM0 SERIALBAUD=38400"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# 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
+# CONFIG_INFTL 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_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 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_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_ADSFLASH=y
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE 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_IDE_GENERIC=y
+CONFIG_BLK_DEV_EP93XX=y
+# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
+CONFIG_IDE_ARM=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+# CONFIG_BT_SCO is not set
+# CONFIG_BT_RFCOMM is not set
+CONFIG_BT_BNEP=y
+# CONFIG_BT_BNEP_MC_FILTER is not set
+# CONFIG_BT_BNEP_PROTO_FILTER is not set
+# CONFIG_BT_HIDP is not set
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=y
+# CONFIG_BT_HCIUSB_SCO is not set
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIDTL1 is not set
+# CONFIG_BT_HCIBT3C is not set
+# CONFIG_BT_HCIBLUECARD is not set
+# CONFIG_BT_HCIBTUART is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=y
+CONFIG_ATMEL=y
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=y
+CONFIG_AIRO_CS=y
+CONFIG_PCMCIA_ATMEL=y
+CONFIG_PCMCIA_WL3501=y
+CONFIG_NET_WIRELESS=y
+
+#
+# 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_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_TSDEV=y
+CONFIG_INPUT_TSDEV_SCREEN_X=640
+CONFIG_INPUT_TSDEV_SCREEN_Y=480
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_EP93XX is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_EP93XX=y
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_EP93XX_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+CONFIG_SENSORS_DS1307=y
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_CX25871_I2C is not set
+CONFIG_FB_EP93XX=y
+# CONFIG_FB_CRT_EP93XX is not set
+# CONFIG_FB_LCD_EP93XX is not set
+# CONFIG_FB_LCD_EP93XX_SHARP is not set
+CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343=y
+# CONFIG_FB_CX25871 is not set
+# CONFIG_FB_EP93XX_8BPP is not set
+CONFIG_FB_EP93XX_16BPP_565=y
+# CONFIG_FB_EP93XX_24BPP is not set
+# CONFIG_FB_EP93XX_32BPP is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 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_OSS=y
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_EP93XX_AC97=y
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# 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_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+CONFIG_USB_OV511=y
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=y
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_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_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS 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=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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# 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_ASCII 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=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/dma03_defconfig b/arch/arm/configs/dma03_defconfig
new file mode 100644
index 0000000..59b677c
--- /dev/null
+++ b/arch/arm/configs/dma03_defconfig
@@ -0,0 +1,1281 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-rc4
+# Fri Dec  9 21:21:27 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# EP93xx
+#
+# CONFIG_ARCH_EP9301 is not set
+# CONFIG_ARCH_EP9302 is not set
+# CONFIG_ARCH_EP9312 is not set
+CONFIG_ARCH_EP9315=y
+# CONFIG_MACH_EDB9315 is not set
+# CONFIG_MACH_ADSSPHERE is not set
+# CONFIG_MACH_ZEFEERDZQ is not set
+CONFIG_MACH_DMA03=y
+CONFIG_ARCH_EP93XX_GPIO_IRQ=y
+CONFIG_EP93XX_DMA=y
+CONFIG_EP93XX_SSP=y
+CONFIG_EP93XX_SSP_CIRRUS=y
+# CONFIG_EP93XX_SSP_LINUX is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/hda1 slram=sram,0x20000000,0x2010000 parport=0xD0000020,74 lp=parport0"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+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_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# 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
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 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=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_ABSENT=y
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x60000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=y
+CONFIG_MTD_PHRAM=y
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=12288
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# 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_IDE_GENERIC=y
+CONFIG_BLK_DEV_EP93XX=y
+# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
+CONFIG_IDE_ARM=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_EP93XX=y
+CONFIG_KEYBOARD_EP93XX_SPI=y
+CONFIG_KEYBOARD_EP93XX_8X8=y
+CONFIG_KEYBOARD_EP93XX_8X8_CYCLING=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_EP93XX=y
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+# CONFIG_TIPAR is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_EP93XX_RTC is not set
+CONFIG_DS1337_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# CAN bus devices
+#
+CONFIG_CAN_BUS=y
+CONFIG_OKI_CAN_ML9620=y
+# CONFIG_OKI_CAN_ML9620_MICRO9 is not set
+CONFIG_OKI_CAN_ML9620_GASSNER=y
+CONFIG_OKI_CAN_ML9620_2DEV=y
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_DS1307 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_CX25871_I2C is not set
+CONFIG_FB_EP93XX=y
+# CONFIG_FB_CRT_EP93XX is not set
+# CONFIG_FB_LCD_EP93XX is not set
+CONFIG_FB_LCD_EP93XX_SHARP=y
+# CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343 is not set
+# CONFIG_FB_CX25871 is not set
+# CONFIG_FB_LCD_TX09D50VM1CCA is not set
+# CONFIG_FB_EP93XX_8BPP is not set
+# CONFIG_FB_EP93XX_16BPP_565 is not set
+# CONFIG_FB_EP93XX_24BPP is not set
+CONFIG_FB_EP93XX_32BPP=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_6x11=y
+CONFIG_FONT_7x14=y
+CONFIG_FONT_PEARL_8x8=y
+CONFIG_FONT_ACORN_8x8=y
+CONFIG_FONT_MINI_4x6=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+CONFIG_FONT_10x18=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OBSOLETE_OSS_DRIVER is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_EP93XX_AC97=m
+CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297=y
+# CONFIG_SOUND_EP93XX_AUDIO_PIO is not set
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_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_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# 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_ASCII=y
+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=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/edb9301_defconfig b/arch/arm/configs/edb9301_defconfig
new file mode 100644
index 0000000..e105976
--- /dev/null
+++ b/arch/arm/configs/edb9301_defconfig
@@ -0,0 +1,965 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-ep93xx
+# Mon Nov  8 16:32:53 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+
+#
+# EP93xx
+#
+CONFIG_ARCH_EP9301=y
+# CONFIG_ARCH_EP9302 is not set
+# CONFIG_ARCH_EP9312 is not set
+# CONFIG_ARCH_EP9315 is not set
+CONFIG_MACH_EDB9301=y
+# CONFIG_MACH_TTML is not set
+CONFIG_EP93XX_DMA=y
+CONFIG_EP93XX_SSP=y
+CONFIG_EP93XX_SSP_CIRRUS=y
+# CONFIG_EP93XX_SSP_LINUX is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# General setup
+#
+CONFIG_DISCONTIGMEM=y
+CONFIG_ARM_AMBA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/nfs ip=dhcp"
+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_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# 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
+# CONFIG_INFTL 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_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# 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_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x60000000
+CONFIG_MTD_PHYSMAP_LEN=0x01000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_EP93XX_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_EP93XX is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+CONFIG_I2C_DEBUG_CORE=y
+CONFIG_I2C_DEBUG_ALGO=y
+CONFIG_I2C_DEBUG_BUS=y
+CONFIG_I2C_DEBUG_CHIP=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_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_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS 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=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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# 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_ASCII 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+# CONFIG_FB_CX25871_I2C is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_MEMORY=y
+CONFIG_SND_DEBUG_DETECT=y
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=y
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+
+#
+# ALSA USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811HS is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM 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_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=y
+# CONFIG_USB_SERIAL_CONSOLE 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_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=y
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_WAITQ=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_LL_PRINTK_HACK is not set
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/edb9312_defconfig b/arch/arm/configs/edb9312_defconfig
new file mode 100644
index 0000000..1a0aa51
--- /dev/null
+++ b/arch/arm/configs/edb9312_defconfig
@@ -0,0 +1,920 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-ep93xx
+# Mon Nov  8 16:40:30 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+
+#
+# EP93xx
+#
+# CONFIG_ARCH_EP9301 is not set
+# CONFIG_ARCH_EP9302 is not set
+CONFIG_ARCH_EP9312=y
+# CONFIG_ARCH_EP9315 is not set
+CONFIG_MACH_EDB9312=y
+# CONFIG_MACH_ACC is not set
+CONFIG_EP93XX_DMA=y
+CONFIG_ARCH_EP93XX_IDE=y
+CONFIG_EP93XX_SSP=y
+CONFIG_EP93XX_SSP_CIRRUS=y
+# CONFIG_EP93XX_SSP_LINUX is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# General setup
+#
+CONFIG_DISCONTIGMEM=y
+CONFIG_ARM_AMBA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# 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_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/hda1"
+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=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=y
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 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=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_ABSENT=y
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x60000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=y
+CONFIG_MTD_PHRAM=y
+CONFIG_MTD_MTDRAM=y
+CONFIG_MTDRAM_TOTAL_SIZE=512
+CONFIG_MTDRAM_ERASE_SIZE=1
+CONFIG_MTDRAM_ABS_POS=0x20000000
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=12288
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# 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_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_EP93XX=y
+# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
+CONFIG_IDE_ARM=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_EP93XX=y
+CONFIG_KEYBOARD_EP93XX_SPI=y
+CONFIG_KEYBOARD_EP93XX_8X8=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+CONFIG_TOUCHSCREEN_EP93XX=y
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_EP93XX_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_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_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS 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=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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# 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_ASCII=y
+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=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_CX25871_I2C is not set
+CONFIG_FB_EP93XX=y
+# CONFIG_FB_CRT_EP93XX is not set
+CONFIG_FB_LCD_EP93XX=y
+# CONFIG_FB_LCD_EP93XX_SHARP is not set
+# CONFIG_FB_CX25871 is not set
+# CONFIG_FB_EP93XX_8BPP is not set
+# CONFIG_FB_EP93XX_16BPP_565 is not set
+# CONFIG_FB_EP93XX_24BPP is not set
+CONFIG_FB_EP93XX_32BPP=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_6x11=y
+CONFIG_FONT_PEARL_8x8=y
+CONFIG_FONT_ACORN_8x8=y
+# CONFIG_FONT_MINI_4x6 is not set
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 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_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_PRINTK_HACK=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/edb9315_defconfig b/arch/arm/configs/edb9315_defconfig
new file mode 100644
index 0000000..3e6033b
--- /dev/null
+++ b/arch/arm/configs/edb9315_defconfig
@@ -0,0 +1,954 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-ep93xx
+# Mon Nov  8 17:01:50 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+
+#
+# EP93xx
+#
+# CONFIG_ARCH_EP9301 is not set
+# CONFIG_ARCH_EP9302 is not set
+# CONFIG_ARCH_EP9312 is not set
+CONFIG_ARCH_EP9315=y
+CONFIG_MACH_EDB9315=y
+CONFIG_EP93XX_DMA=y
+# CONFIG_ARCH_EP93XX_IDE is not set
+CONFIG_EP93XX_SSP=y
+CONFIG_EP93XX_SSP_CIRRUS=y
+# CONFIG_EP93XX_SSP_LINUX is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# General setup
+#
+CONFIG_DISCONTIGMEM=y
+CONFIG_ARM_AMBA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# 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_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyCL0 map=mtd6,0x30000000,+0x200000 root=/dev/nfs nfsroot=192.168.1.224:/nfsarm_grma video=ep93xxfb ip=192.168.1.220:192.168.1.224:192.168.1.2:255.255.255.0::eth0:"
+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=y
+CONFIG_MTD_DEBUG_VERBOSE=3
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=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
+# CONFIG_INFTL 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_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 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_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x60000000
+CONFIG_MTD_PHYSMAP_LEN=0x2000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=y
+CONFIG_MTDRAM_TOTAL_SIZE=512
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTDRAM_ABS_POS=0x20000000
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# 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_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_EP93XX=y
+# CONFIG_KEYBOARD_EP93XX_SPI is not set
+# CONFIG_KEYBOARD_EP93XX_8X8 is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+CONFIG_TOUCHSCREEN_EP93XX=y
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_EP93XX_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+CONFIG_I2C_DEBUG_CORE=y
+CONFIG_I2C_DEBUG_ALGO=y
+CONFIG_I2C_DEBUG_BUS=y
+CONFIG_I2C_DEBUG_CHIP=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=2
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS 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=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=y
+# CONFIG_LDM_DEBUG is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# 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_ASCII 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=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_CX25871_I2C is not set
+CONFIG_FB_EP93XX=y
+# CONFIG_FB_CRT_EP93XX is not set
+CONFIG_FB_LCD_EP93XX=y
+# CONFIG_FB_LCD_EP93XX_SHARP is not set
+# CONFIG_FB_CX25871 is not set
+# CONFIG_FB_EP93XX_8BPP is not set
+CONFIG_FB_EP93XX_16BPP_565=y
+# CONFIG_FB_EP93XX_24BPP is not set
+# CONFIG_FB_EP93XX_32BPP is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811HS is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM 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_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_LL_PRINTK_HACK is not set
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/ttml_defconfig b/arch/arm/configs/ttml_defconfig
new file mode 100644
index 0000000..e0b96ae
--- /dev/null
+++ b/arch/arm/configs/ttml_defconfig
@@ -0,0 +1,1052 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13
+# Thu Sep  8 16:54:14 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# EP93xx
+#
+CONFIG_ARCH_EP9301=y
+# CONFIG_ARCH_EP9302 is not set
+# CONFIG_ARCH_EP9312 is not set
+# CONFIG_ARCH_EP9315 is not set
+# CONFIG_MACH_EDB9301 is not set
+CONFIG_MACH_TTML=y
+# CONFIG_ARCH_EP93XX_GPIO_IRQ is not set
+CONFIG_EP93XX_DMA=y
+CONFIG_EP93XX_SSP=y
+# CONFIG_EP93XX_SSP_CIRRUS is not set
+CONFIG_EP93XX_SSP_LINUX=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="ip=off root=1f02 rootfstype=jffs2"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# 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
+# CONFIG_INFTL 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_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x60000000
+CONFIG_MTD_PHYSMAP_LEN=0x01000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTML_DEVICES=y
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_EP93XX_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# CAN bus devices
+#
+# CONFIG_CAN_BUS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_EP93XX is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_DS1307 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+CONFIG_I2C_DEBUG_CORE=y
+CONFIG_I2C_DEBUG_ALGO=y
+CONFIG_I2C_DEBUG_BUS=y
+CONFIG_I2C_DEBUG_CHIP=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+# CONFIG_FB_CX25871_I2C is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=y
+# CONFIG_USB_SERIAL_CONSOLE is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRPRIME 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_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 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_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=y
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_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_WRITEBUFFER=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS 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=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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# 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_ASCII 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/zefeerdzb_defconfig b/arch/arm/configs/zefeerdzb_defconfig
new file mode 100644
index 0000000..39aefdd
--- /dev/null
+++ b/arch/arm/configs/zefeerdzb_defconfig
@@ -0,0 +1,961 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-ep93xx
+# Fri Jan  7 11:19:19 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+
+#
+# EP93xx
+#
+# CONFIG_ARCH_EP9301 is not set
+CONFIG_ARCH_EP9302=y
+# CONFIG_ARCH_EP9312 is not set
+# CONFIG_ARCH_EP9315 is not set
+# CONFIG_MACH_EDB9302 is not set
+CONFIG_MACH_ZEFEERDZB=y
+CONFIG_ARCH_EP93XX_GPIO_IRQ=y
+CONFIG_EP93XX_DMA=y
+# CONFIG_EP93XX_SSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# General setup
+#
+CONFIG_DISCONTIGMEM=y
+CONFIG_ARM_AMBA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/nfs ip=dhcp"
+# CONFIG_LEDS is not set
+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_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# 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
+# CONFIG_INFTL 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_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# 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_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+CONFIG_MTD_ZEFEERDZB=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_ZEFEEREVB=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_EP93XX=y
+# CONFIG_KEYBOARD_EP93XX_SPI is not set
+# CONFIG_KEYBOARD_EP93XX_8X8 is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_EP93XX_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
+CONFIG_I2C_DEBUG_CORE=y
+CONFIG_I2C_DEBUG_ALGO=y
+CONFIG_I2C_DEBUG_BUS=y
+CONFIG_I2C_DEBUG_CHIP=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_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=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS 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=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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# 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_ASCII 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+# CONFIG_FB_CX25871_I2C is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_MEMORY=y
+CONFIG_SND_DEBUG_DETECT=y
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=y
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+
+#
+# ALSA USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811HS is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM 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_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_WAITQ=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_DONT_REORDER_CODE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_LL_PRINTK_HACK is not set
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/zefeerdzq_defconfig b/arch/arm/configs/zefeerdzq_defconfig
new file mode 100644
index 0000000..8314eee
--- /dev/null
+++ b/arch/arm/configs/zefeerdzq_defconfig
@@ -0,0 +1,1174 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13
+# Tue Oct  4 10:04:06 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# EP93xx
+#
+# CONFIG_ARCH_EP9301 is not set
+# CONFIG_ARCH_EP9302 is not set
+# CONFIG_ARCH_EP9312 is not set
+CONFIG_ARCH_EP9315=y
+# CONFIG_MACH_EDB9315 is not set
+# CONFIG_MACH_ADSSPHERE is not set
+CONFIG_MACH_ZEFEERDZQ=y
+# CONFIG_MACH_DMA03 is not set
+# CONFIG_ARCH_EP93XX_GPIO_IRQ is not set
+CONFIG_EP93XX_DMA=y
+# CONFIG_ARCH_EP93XX_IDE is not set
+# CONFIG_EP93XX_SSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+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_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# 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
+# CONFIG_INFTL 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_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# 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_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
+CONFIG_MTD_ZEFEERDZQ=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_ZEFEEREVB=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=12288
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# 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_IDE_GENERIC=y
+CONFIG_BLK_DEV_EP93XX=y
+# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
+CONFIG_IDE_ARM=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_EP93XX=y
+# CONFIG_KEYBOARD_EP93XX_SPI is not set
+# CONFIG_KEYBOARD_EP93XX_8X8 is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_EP93XX_RTC is not set
+# CONFIG_DS1337_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# CAN bus devices
+#
+# CONFIG_CAN_BUS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_DS1307 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_CX25871_I2C is not set
+CONFIG_FB_EP93XX=y
+# CONFIG_FB_CRT_EP93XX is not set
+# CONFIG_FB_LCD_EP93XX is not set
+# CONFIG_FB_LCD_EP93XX_SHARP is not set
+# CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343 is not set
+# CONFIG_FB_CX25871 is not set
+CONFIG_FB_LCD_TX09D50VM1CCA=y
+# CONFIG_FB_EP93XX_8BPP is not set
+# CONFIG_FB_EP93XX_16BPP_565 is not set
+CONFIG_FB_EP93XX_24BPP=y
+# CONFIG_FB_EP93XX_32BPP is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+CONFIG_FONT_SUN8x16=y
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# 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_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_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_WRITEBUFFER=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS 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=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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# 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_ASCII 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=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_DONT_REORDER_CODE=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
new file mode 100644
index 0000000..2b5c2d6
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -0,0 +1,193 @@
+
+menu "EP93xx"
+	depends on ARCH_EP93XX
+
+choice
+	prompt "EP93xx CPU Type"
+	default EP9312
+	help
+	  There are several types of EP93xx CPUs available.
+	  Choosing the right one here enables you to select
+	  model specific drivers later.
+
+config ARCH_EP9301
+	bool "EP9301"
+	help
+	  Say Y here if you have intend to run this kernel on a EP9301 CPU.
+
+config ARCH_EP9302
+	bool "EP9302"
+	help
+	  Say Y here if you have intend to run this kernel on a EP9302 CPU.
+
+config ARCH_EP9312
+	bool "EP9312"
+	help
+	  Say Y here if you intend to run this kernel on a EP9312 CPU.
+
+
+config ARCH_EP9315
+	bool "EP9315"
+	help
+	  Say Y here if you intend to run this kernel on a EP9315 CPU.
+endchoice
+
+choice
+	prompt "EP9301 Boards"
+	depends on ARCH_EP9301
+	default EDB9301
+	help
+	  There are several EP9301-based boards available.
+	  Choosing the right one here enables various board-
+	  specific options.
+
+config MACH_EDB9301
+	bool "Cirrus Logic EDB9301"
+	select MTD
+	select MTD_PHYSMAP
+	help
+	  Say Y here if you intend to run this kernel on an EDB9301.
+
+config MACH_TTML
+	bool "TTML TripDawg"
+	help
+	  Say Y here if you intend to run this kernel on an TTML TripDawg.
+
+endchoice
+
+choice
+	prompt "EP9302 Boards"
+	depends on ARCH_EP9302
+	default EDB9302
+	help
+	  There are several EP9302-based boards available.
+	  Choosing the right one here enables various board-
+	  specific options.
+
+config MACH_EDB9302
+	bool "Cirrus Logic EDB9302"
+	select MTD
+	select MTD_PHYSMAP
+	help
+	  Say Y here if you intend to run this kernel on an EDB9302.
+
+config MACH_ZEFEERDZB
+	bool "Dave Zefeer DZB on ZefeerEVB-L"
+	select MTD
+	help
+	  Say Y here if you intend to run this kernel on an Zefeer DZB.
+	  pluggend onto ZefeerEVB-L board.
+
+config MACH_ZEFEER_EVBL_107
+	bool " Dave ZefeerEVB-L - version 1.0.7 (PCB CS044404)"
+	depends on MACH_ZEFEERDZB
+	default n
+	help
+	  Say Y here if you intend to run this kernel on an ZefeerEVB-L
+	  version 1.0.7.
+
+endchoice
+
+choice
+	prompt "EP9312 Boards"
+	depends on ARCH_EP9312
+	default EDB9312
+	help
+	  There are several EP9312-based boards available.
+	  Choosing the right one here enables various board-
+	  specific options.
+
+config MACH_EDB9312
+	bool "Cirrus Logic EDB9312"
+	select MTD
+	select MTD_PHYSMAP
+	help
+	  Say Y here if you intend to run this kernel on an EDB9312.
+
+
+config MACH_ACC
+	bool "HiFish ACC"
+	help
+	  Say Y here if you are using the HiFish Audio Control Center"
+
+endchoice
+
+choice
+	prompt "EP9315 Boards"
+	depends on ARCH_EP9315
+	default EDB9315
+	help
+	  There are several EP9315-based boards available.
+	  Choosing the right one here enables various board-
+	  specific options.
+
+config MACH_EDB9315
+	bool "Cirrus Logic EDB9315"
+	select MTD
+	select MTD_PHYSMAP
+	help
+	  Say Y here if you intend to run this kernel on an EDB9315.
+
+config MACH_ADSSPHERE
+	bool "Applied Data Systems Sphere"
+	select MTD
+	help
+	  Say Y here if you intend to run this kernel on an ADSSPHERE.
+
+config MACH_ZEFEERDZQ
+	bool "Dave Zefeer DZQ on ZefeerEVB (L or H)"
+	select MTD
+	help
+	  Say Y here if you intend to run this kernel on an Zefeer DZQ.
+	  Both evaluation board are supported (ZefeerEVB-L/ZefeerEVB-H).
+
+config MACH_DMA03
+	bool "Gassner DMA03"
+	select MTD
+	select MTD_PHYSMAP
+	help
+	  Say Y here if you intend to run this kernel on an DMA03.
+
+endchoice
+
+config ARCH_EP93XX_GPIO_IRQ
+	bool " EP93xx GPIO IRQ demux"
+	depends on ARCH_EP93XX
+	help
+	  Say Y here if you want to expand the IRQ number to GPIO IRQ.
+
+config EP93XX_DMA
+	bool " EP93xx Internal DMA Support"
+	default y
+	help
+	  Say Y here if you want to enable DMA Support for EP93XX family
+	  CPUs.
+
+config EP93XX_SSP
+	bool "SSP support"
+	help
+	  If you require SSP support, there are two SSP drivers
+	  available to choose from.
+
+choice
+	prompt "SSP driver"
+	depends on EP93XX_SSP
+	default EP93XX_SSP_LINUX
+
+config EP93XX_SSP_CIRRUS
+	tristate "Cirrus Logic SSP driver"
+	depends on EP93XX_SSP
+	help
+	  Say Y here for the Cirrus-supplied SSP driver. It is
+	  quite specific to the EDB93xx evaluation boards.
+
+config EP93XX_SSP_LINUX
+	tristate "Linux SSP driver"
+	depends on EP93XX_SSP
+	help
+	  Say Y here for an SSP driver which is heavily based on the
+	  SA-1100 and PXA2xx SSP drivers.
+
+endchoice
+
+endmenu
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
new file mode 100644
index 0000000..19c56b3
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -0,0 +1,17 @@
+obj-y				+= ep93xx.o irq.o time.o
+
+obj-$(CONFIG_MACH_ACC)		+= mach-acc.o
+obj-$(CONFIG_MACH_EDB9301)	+= mach-edb9301.o
+obj-$(CONFIG_MACH_EDB9302)	+= mach-edb9302.o
+obj-$(CONFIG_MACH_EDB9312)	+= mach-edb9312.o
+obj-$(CONFIG_MACH_EDB9315)	+= mach-edb9315.o
+obj-$(CONFIG_MACH_ADSSPHERE)	+= mach-adssphere.o
+obj-$(CONFIG_MACH_TTML)		+= mach-ttml.o
+obj-$(CONFIG_MACH_ZEFEERDZB)	+= mach-zefeerdzb.o
+obj-$(CONFIG_MACH_ZEFEERDZQ)	+= mach-zefeerdzq.o
+obj-$(CONFIG_MACH_DMA03)	+= mach-dma03.o
+
+obj-$(CONFIG_EP93XX_DMA)	+= dma_ep93xx.o
+
+obj-$(CONFIG_EP93XX_SSP_LINUX)	+= ssp.o ssp2.o
+obj-$(CONFIG_EP93XX_SSP_CIRRUS)	+= ssp-cirrus.o
diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot
new file mode 100644
index 0000000..c87653e
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Makefile.boot
@@ -0,0 +1,6 @@
+   zreladdr-y   := 0x00008000
+params_phys-y   := 0x00000100
+   zreladdr-$(CONFIG_MACH_ZEFEERDZB)    := 0xD0008000
+params_phys-$(CONFIG_MACH_ZEFEERDZB)    := 0xD0000100
+   zreladdr-$(CONFIG_MACH_ZEFEERDZQ)    := 0xD0008000
+params_phys-$(CONFIG_MACH_ZEFEERDZQ)    := 0xD0000100
diff --git a/arch/arm/mach-ep93xx/dma_ep93xx.c b/arch/arm/mach-ep93xx/dma_ep93xx.c
new file mode 100644
index 0000000..817de48
--- /dev/null
+++ b/arch/arm/mach-ep93xx/dma_ep93xx.c
@@ -0,0 +1,3346 @@
+/******************************************************************************
+ * arch/arm/mach-ep9312/dma_ep93xx.c
+ *
+ * Support functions for the ep93xx internal DMA channels.
+ * (see also Documentation/arm/ep93xx/dma.txt)
+ *
+ * Copyright (C) 2003  Cirrus Logic
+ *
+ * A large portion of this file is based on the dma api implemented by
+ * Nicolas Pitre, dma-sa1100.c, copyrighted 2000.
+ *
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/mach/dma.h>
+#include "dma_ep93xx.h"
+
+/*****************************************************************************
+ *
+ * Debugging macros
+ *
+ ****************************************************************************/
+#undef DEBUG
+/*#define DEBUG   1 */
+#ifdef DEBUG
+#define DPRINTK( x... )  printk( ##x )
+#else
+#define DPRINTK( x... )
+#endif
+
+/*****************************************************************************
+ *
+ * static global variables
+ *
+ ****************************************************************************/
+ep93xx_dma_t dma_chan[MAX_EP93XX_DMA_CHANNELS];
+
+/*
+ *  Maximum physical DMA buffer size
+ */
+#define MAX_DMA_SIZE        0xffff
+#define MAX_DMA_ORDER       12
+
+/*
+ *  lock used to protect the list of dma channels while searching for a free
+ *  channel during dma_request.
+ */
+static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED;
+
+/*****************************************************************************
+ *
+ *  Internal DMA processing functions.
+ *
+ ****************************************************************************/
+/*****************************************************************************
+ *
+ *  get_dma_channel_from_handle()
+ *
+ *  If Handle is valid, returns the DMA channel # (0 to 9 for channels 1-10)
+ *  If Handle is not valid, returns -1.
+ *
+ ****************************************************************************/
+static int dma_get_channel_from_handle(int handle)
+{
+	int channel;
+
+	/*
+	 *  Get the DMA channel # from the handle.
+	 */
+	channel = ((int)handle & DMA_HANDLE_SPECIFIER_MASK) >> 28;
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (dma_chan[channel].last_valid_handle != (int)handle) {
+		DPRINTK("DMA ERROR - invalid handle 0x%x \n", handle);
+		/*
+		 *  Fail, invalid handle
+		 */
+		return (-1);
+	}
+
+	/*
+	 *  See if this instance is still open
+	 */
+	if (!dma_chan[channel].ref_count) {
+		/*
+		 *  Fail, instance closed
+		 */
+		return (-1);
+	}
+
+	return (channel);
+}
+
+/*****************************************************************************
+ *
+ * dma_m2m_irq_handler
+ *
+ * TODO: need to add support for M2M interrupt handling!!!
+ *
+ ****************************************************************************/
+static irqreturn_t
+dma_m2m_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id;
+	unsigned int M2M_reg_base = dma->reg_base;
+	ep93xx_dma_dev_t dma_int = UNDEF_INT;
+	unsigned int read_back, loop, uiCONTROL, uiINTERRUPT;
+
+	loop = readl(M2M_reg_base + M2M_OFFSET_INTERRUPT);
+
+	/*
+	 *  Determine what kind of dma interrupt this is.
+	 */
+	if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
+	    INTERRUPT_M2M_STALLINT)
+		dma_int = STALL;
+	else if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
+		 INTERRUPT_M2M_NFBINT)
+		dma_int = NFB;
+	else if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
+		 INTERRUPT_M2M_DONEINT)
+		dma_int = DONE;
+
+	DPRINTK("IRQ: b=%#x st=%#x\n", (int)dma->current_buffer->source,
+		dma_int);
+
+	/*
+	 * Stall Interrupt: The Channel is stalled, meaning nothing is
+	 * programmed to transfer right now.  So, we're back to the
+	 * beginnning.  If there's a buffer to transfer, program it into
+	 * max and base 0 registers.
+	 */
+	if (dma_int == STALL) {
+		DPRINTK("1  ");
+
+		if (dma->total_buffers) {
+
+			if (readl(M2M_reg_base + M2M_OFFSET_BCR0) !=
+			    0) {
+				writel(0x0, M2M_reg_base + M2M_OFFSET_INTERRUPT);
+				return IRQ_HANDLED;
+
+			}
+
+			/*
+			 *  The current_buffer has already been tranfered, so add the
+			 *  byte count to the total_bytes field.
+			 */
+			dma->total_bytes = dma->total_bytes +
+			    dma->buffer_queue[dma->current_buffer].size;
+
+			/*
+			 *  Mark the current_buffer as used.
+			 */
+			dma->buffer_queue[dma->current_buffer].used = TRUE;
+
+			/*
+			 *  Increment the used buffer counter
+			 */
+			dma->used_buffers++;
+
+			DPRINTK("#%d", dma->current_buffer);
+
+			/*
+			 *  Increment the current_buffer
+			 */
+			dma->current_buffer = (dma->current_buffer + 1) %
+			    MAX_EP93XX_DMA_BUFFERS;
+
+			/*
+			 *  check if there's a new buffer to transfer.
+			 */
+			if (dma->new_buffers && dma->xfer_enable) {
+				/*
+				 *  We have a new buffer to transfer so program in the buffer
+				 *  values.  Since a STALL interrupt was triggered, we
+				 *  program the buffer descriptor 0
+				 *
+				 *  Set the SAR_BASE/DAR_BASE/BCR registers with values from the
+				 *  next buffer in the queue.
+				 */
+				writel(dma->buffer_queue[dma->current_buffer].
+				       source,
+				       M2M_reg_base + M2M_OFFSET_SAR_BASE0);
+				writel(dma->buffer_queue[dma->current_buffer].
+				       dest,
+				       M2M_reg_base + M2M_OFFSET_DAR_BASE0);
+				writel(dma->buffer_queue[dma->current_buffer].
+				       size,
+				       M2M_reg_base + M2M_OFFSET_BCR0);
+
+				/*
+				 *  Decrement the new buffer counter
+				 */
+				dma->new_buffers--;
+
+				/*
+				 *  If there's a second new buffer, we program the second
+				 *  buffer descriptor.
+				 */
+#if 0
+				if (dma->new_buffers) {
+					DPRINTK("A  ");
+
+					/*
+					 *  Set the SAR_BASE/DAR_BASE/BCR registers with values from the
+					 *  next buffer in the queue.
+					 */
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       source,
+					       M2M_reg_base + M2M_OFFSET_SAR_BASE1);
+
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       dest,
+					       M2M_reg_base + M2M_OFFSET_DAR_BASE0);
+
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       size,
+					       M2M_reg_base + M2M_OFFSET_BCR0);
+
+					/*
+					 *  Decrement the new buffer counter
+					 */
+					dma->new_buffers--;
+
+					/*
+					 *  Enable the NFB Interrupt.
+					 */
+					uiCONTROL =
+					    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+					uiCONTROL |= CONTROL_M2M_NFBINTEN;
+					writel(uiCONTROL,
+					       M2M_reg_base + M2M_OFFSET_CONTROL);
+				}
+#endif
+			}
+			/*
+			 *  Read my lips.  No new buffers.
+			 */
+			else {
+				DPRINTK("2 \n");
+				/*
+				 *  There's a chance we setup both buffer descriptors, but
+				 *  didn't service the NFB quickly enough, causing the channel
+				 *  to transfer both buffers, then enter the stall state.
+				 *  So, we need to be able to process the second buffer.
+				 */
+				if ((dma->used_buffers + dma->new_buffers) <
+				    dma->total_buffers) {
+					DPRINTK("3 ");
+
+					/*
+					 *  The current_buffer has already been tranfered, so add the
+					 *  byte count to the total_bytes field.
+					 */
+					dma->total_bytes = dma->total_bytes +
+					    dma->buffer_queue[dma->
+							      current_buffer].
+					    size;
+
+					/*
+					 *  Mark the current_buffer as used.
+					 */
+					dma->buffer_queue[dma->current_buffer].
+					    used = TRUE;
+
+					/*
+					 *  Increment the used buffer counter
+					 */
+					dma->used_buffers++;
+
+					DPRINTK("#%d", dma->current_buffer);
+
+					/*
+					 *  Increment the current buffer pointer.
+					 */
+					dma->current_buffer =
+					    (dma->current_buffer +
+					     1) % MAX_EP93XX_DMA_BUFFERS;
+
+				}
+
+				/*
+				 *  No new buffers to transfer, so disable the channel.
+				 */
+				uiCONTROL =
+				    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+				uiCONTROL &= ~CONTROL_M2M_ENABLE;
+				writel(uiCONTROL,
+				       M2M_reg_base + M2M_OFFSET_CONTROL);
+
+				/*
+				 *  Indicate that this channel is in the pause by starvation
+				 *  state by setting the pause bit to true.
+				 */
+				dma->pause = TRUE;
+
+				DPRINTK("End of stall handling. \n");
+				DPRINTK("STATUS - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_STATUS));
+				DPRINTK("CONTROL - 0x%x \n",
+					readl(M2M_reg_base + M2M_CONTROL.Value));
+				DPRINTK("REMAIN - 0x%x \n",
+					readl(M2M_reg_base + M2M_REMAIN.Value));
+				DPRINTK("PPALLOC - 0x%x \n",
+					readl(M2M_reg_base + M2M_PPALLOC.Value));
+				DPRINTK("BASE0 - 0x%x \n",
+					readl(M2M_reg_base + M2M_BASE0.Value));
+				DPRINTK("MAXCNT0 - 0x%x \n",
+					readl(M2M_reg_base + M2M_MAXCNT0.Value));
+				DPRINTK("CURRENT0 - 0x%x \n",
+					readl(M2M_reg_base + M2M_CURRENT0.Value));
+				DPRINTK("BASE1 - 0x%x \n",
+					readl(M2M_reg_base + M2M_BASE1.Value));
+				DPRINTK("MAXCNT1 - 0x%x \n",
+					readl(M2M_reg_base + M2M_MAXCNT1.Value));
+				DPRINTK("CURRENT1 - 0x%x \n",
+					readl(M2M_reg_base + M2M_CURRENT1.Value));
+
+				DPRINTK
+				    ("Buffer    buf_id     source       size       last       used \n");
+				for (loop = 0; loop < 32; loop++) {
+					DPRINTK
+					    ("%d        0x%x        0x%x         0x%x        %d         %d \n",
+					     loop,
+					     dma->buffer_queue[loop].buf_id,
+					     dma->buffer_queue[loop].source,
+					     dma->buffer_queue[loop].size,
+					     dma->buffer_queue[loop].last,
+					     dma->buffer_queue[loop].used);
+				}
+				DPRINTK("Pause - %d \n", dma->pause);
+				DPRINTK("xfer_enable - %d \n",
+					dma->xfer_enable);
+				DPRINTK("total bytes - 0x%x \n",
+					dma->total_bytes);
+				DPRINTK("total buffer - %d \n",
+					dma->total_buffers);
+				DPRINTK("new buffers - %d \n",
+					dma->new_buffers);
+				DPRINTK("current buffer - %d \n",
+					dma->current_buffer);
+				DPRINTK("last buffer - %d \n",
+					dma->last_buffer);
+				DPRINTK("used buffers - %d \n",
+					dma->used_buffers);
+				DPRINTK("callback addr - 0x%x \n",
+					dma->callback);
+			}
+		}
+		/*
+		 *  Total number of buffers in the queue is 0.
+		 */
+		else {
+			/*
+			 *  No buffers to transfer, or old buffers to mark as used,
+			 *  so Disable the channel
+			 */
+			uiCONTROL =
+			    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+			uiCONTROL &= ~CONTROL_M2M_ENABLE;
+			writel(uiCONTROL,
+			       M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			/*
+			 *  Must read the control register back after a write.
+			 */
+			read_back =
+			    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			/*
+			 *  Indicate that this channel is in the pause by
+			 *  starvation state by setting the pause bit to true.
+			 */
+			dma->pause = TRUE;
+		}
+	}
+	/*
+	 *  Next Frame Buffer Interrupt.  If there's a new buffer program it
+	 *  Check if this is the last buffer in the transfer,
+	 *  and if it is, disable the NFB int to prevent being
+	 *  interrupted for another buffer when we know there won't be
+	 *  another.
+	 */
+	if (dma_int == NFB) {
+		DPRINTK("5  ");
+
+		if (dma->total_buffers) {
+			DPRINTK("6  ");
+			/*
+			 *  The iCurrentBuffer has already been transfered.  so add the
+			 *  byte count from the current buffer to the total byte count.
+			 */
+			dma->total_bytes = dma->total_bytes +
+			    dma->buffer_queue[dma->current_buffer].size;
+
+			/*
+			 *  Mark the Current Buffer as used.
+			 */
+			dma->buffer_queue[dma->current_buffer].used = TRUE;
+
+			/*
+			 *  Increment the used buffer counter
+			 */
+			dma->used_buffers++;
+
+			DPRINTK("#%d", dma->current_buffer);
+
+			if ((dma->buffer_queue[(dma->current_buffer +
+						1) %
+					       MAX_EP93XX_DMA_BUFFERS].last)
+			    || (dma->new_buffers == 0)
+			    || (dma->xfer_enable == FALSE)) {
+				DPRINTK("7  ");
+
+				/*
+				 *  This is the last Buffer in this transaction, so disable
+				 *  the NFB interrupt.  We shouldn't get an NFB int when the
+				 *  FSM moves to the ON state where it would typically get the
+				 *  NFB int indicating a new buffer can be programmed.
+				 *  Instead, once in the ON state, the DMA will just proceed
+				 *  to complet the transfer of the current buffer, move the
+				 *  FSB directly to the STALL state where a STALL interrupt
+				 *  will be generated.
+				 */
+				uiCONTROL =
+				    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+				uiCONTROL &= ~CONTROL_M2M_NFBINTEN;
+				writel(uiCONTROL,
+				       M2M_reg_base + M2M_OFFSET_CONTROL);
+
+				/*
+				 *  The current buffer has been transferred, so increment
+				 *  the current buffer counter to reflect this.
+				 */
+				dma->current_buffer =
+				    (dma->current_buffer +
+				     1) % MAX_EP93XX_DMA_BUFFERS;
+
+				DPRINTK("End of NFB handling. \n");
+				DPRINTK("STATUS - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_STATUS));
+				DPRINTK("CONTROL - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_CONTROL));
+				DPRINTK("REMAIN - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_REMAIN));
+				DPRINTK("PPALLOC - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_PPALLOC));
+				DPRINTK("BASE0 - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_BASE0));
+				DPRINTK("MAXCNT0 - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_MAXCNT0));
+				DPRINTK("CURRENT0 - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_CURRENT0));
+				DPRINTK("BASE1 - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_BASE1));
+				DPRINTK("MAXCNT1 - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_MAXCNT1));
+				DPRINTK("CURRENT1 - 0x%x \n",
+					readl(M2M_reg_base + M2M_OFFSET_CURRENT1));
+
+				DPRINTK
+				    ("Buffer    buf_id     source       size       last       used \n");
+				for (loop = 0; loop < 32; loop++) {
+					DPRINTK
+					    ("%d        0x%x        0x%x         0x%x        %d         %d \n",
+					     loop,
+					     dma->buffer_queue[loop].buf_id,
+					     dma->buffer_queue[loop].source,
+					     dma->buffer_queue[loop].size,
+					     dma->buffer_queue[loop].last,
+					     dma->buffer_queue[loop].used);
+				}
+				DPRINTK
+				    ("pause     0x%x        0x%x         0x%x        %d         %d \n",
+				     dma->pause_buf.buf_id,
+				     dma->pause_buf.source, dma->pause_buf.size,
+				     dma->pause_buf.last, dma->pause_buf.used);
+
+				DPRINTK("Pause - %d \n", dma->pause);
+				DPRINTK("xfer_enable - %d \n",
+					dma->xfer_enable);
+				DPRINTK("total bytes - 0x%x \n",
+					dma->total_bytes);
+				DPRINTK("total buffer - %d \n",
+					dma->total_buffers);
+				DPRINTK("new buffers - %d \n",
+					dma->new_buffers);
+				DPRINTK("current buffer - %d \n",
+					dma->current_buffer);
+				DPRINTK("last buffer - %d \n",
+					dma->last_buffer);
+				DPRINTK("used buffers - %d \n",
+					dma->used_buffers);
+				DPRINTK("callback addr - 0x%x \n",
+					dma->callback);
+
+			} else if (dma->new_buffers) {
+				DPRINTK("8  ");
+				/*
+				 *  we have a new buffer, so increment the current buffer to
+				 *  point to the next buffer, which is already programmed into
+				 *  the DMA. Next time around, it'll be pointing to the
+				 *  current buffer.
+				 */
+				dma->current_buffer =
+				    (dma->current_buffer +
+				     1) % MAX_EP93XX_DMA_BUFFERS;
+
+				/*
+				 *  we know we have a new buffer to program as the next
+				 *  buffer, so check which set of SAR_BASE/DAR_BASE/BCR registers
+				 *  to program.
+				 */
+				if (readl(M2M_reg_base + M2M_OFFSET_STATUS) & STATUS_M2M_NB) {
+					/*
+					 *  Set the SAR_BASE1/DAR_BASE1/BCR1 registers with values from the
+					 *  next buffer in the queue.
+					 */
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       source,
+					       M2M_reg_base + M2M_OFFSET_SAR_BASE1);
+
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       dest,
+					       M2M_reg_base + M2M_OFFSET_DAR_BASE1);
+
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       size,
+					       M2M_reg_base + M2M_OFFSET_BCR1);
+				} else {
+					/*
+					 *  Set the SAR_BASE0/DAR_BASE0/BCR0 registers with values from the
+					 *  next buffer in the queue.
+					 */
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       source,
+					       M2M_reg_base + M2M_OFFSET_SAR_BASE0);
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       dest,
+					       M2M_reg_base + M2M_OFFSET_DAR_BASE0);
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       size,
+					       M2M_reg_base + M2M_OFFSET_BCR0);
+				}
+
+				/*
+				 *  Decrement the new buffers counter
+				 */
+				dma->new_buffers--;
+			}
+		}
+		/*
+		 *  Total number of buffers is 0 - really we should never get here,
+		 *  but just in case.
+		 */
+		else {
+			DPRINTK("9 \n");
+
+			/*
+			 *  No new buffers to transfer, so Disable the channel
+			 */
+			uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+			uiCONTROL &= ~CONTROL_M2M_ENABLE;
+			writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			/*
+			 *  Indicate that the channel is paused by starvation.
+			 */
+			dma->pause = 1;
+		}
+	}
+
+	/*
+	 *  Done interrupt generated, indicating that the transfer is complete.
+	 */
+	if (dma_int == DONE) {
+#if 0
+		/*  The current_buffer has already been tranfered, so add the
+		 *  byte count to the total_bytes field.
+		 */
+		dma->total_bytes = dma->total_bytes +
+		    dma->buffer_queue[dma->current_buffer].size;
+
+		/*
+		 *  Mark the current_buffer as used.
+		 */
+		dma->buffer_queue[dma->current_buffer].used = TRUE;
+
+		/*
+		 *  Increment the used buffer counter
+		 */
+		dma->used_buffers++;
+
+		/*
+		 *  Increment the current_buffer
+		 */
+		dma->current_buffer = (dma->current_buffer + 1) %
+		    MAX_EP93XX_DMA_BUFFERS;
+#endif
+		/*
+		 *  Clear the interrupt.
+		 */
+		uiINTERRUPT =
+		    readl(M2M_reg_base + M2M_OFFSET_INTERRUPT);
+		uiINTERRUPT &= ~INTERRUPT_M2M_DONEINT;
+		writel(uiINTERRUPT,
+		       M2M_reg_base + M2M_OFFSET_INTERRUPT);
+
+		DPRINTK("STATUS - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_STATUS));
+		DPRINTK("CONTROL - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_CONTROL));
+		DPRINTK("SAR_BASE0 - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_SAR_BASE0));
+		DPRINTK("DAR_BASE0 - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_DAR_BASE0));
+		DPRINTK("SAR_CURRENT0 - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_SAR_CURRENT0));
+		DPRINTK("DAR_CURRENT0 - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_DAR_CURRENT0));
+		DPRINTK("BCR0 - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_BCR0));
+		DPRINTK("SAR_BASE1 - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_SAR_BASE1));
+		DPRINTK("DAR_BASE1 - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_DAR_BASE1));
+		DPRINTK("BCR1 - 0x%x \n",
+			readl(M2M_reg_base + M2M_OFFSET_BCR1));
+
+		/*
+		 *  Disable the channel.
+		 */
+		uiCONTROL =
+		    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+		uiCONTROL &= ~CONTROL_M2M_ENABLE;
+		writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+		/*
+		 *  Indicate that we're in the stopped mode.
+		 */
+		dma->pause = 1;
+		dma->xfer_enable = 0;
+	}
+
+	/*
+	 *  Make sure the interrupt was valid, and if it was, then check
+	 *  if a callback function was installed for this DMA channel.  If a
+	 *  callback was installed call it.
+	 */
+	if ((dma_int != UNDEF_INT) && dma->callback) {
+		dma->callback(dma_int, dma->device, dma->user_data);
+	}
+	return IRQ_HANDLED;
+}
+
+/*****************************************************************************
+ *
+ * dma_m2p_irq_handler
+ *
+ *
+ *
+ ****************************************************************************/
+static irqreturn_t
+dma_m2p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id;
+	unsigned int M2P_reg_base = dma->reg_base;
+	unsigned int read_back;
+	ep93xx_dma_dev_t dma_int = UNDEF_INT;
+	unsigned int loop, uiCONTROL, uiINTERRUPT;
+
+	/*
+	 *  Determine what kind of dma interrupt this is.
+	 */
+	if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
+	    INTERRUPT_M2P_STALLINT)
+		dma_int = STALL;
+	else if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
+		 INTERRUPT_M2P_NFBINT)
+		dma_int = NFB;
+	else if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
+		 INTERRUPT_M2P_CHERRORINT)
+		dma_int = CHERROR;
+
+	/*
+	 *  Stall Interrupt: The Channel is stalled, meaning nothing is
+	 *  programmed to transfer right now.  So, we're back to the
+	 *  beginnning.  If there's a buffer to transfer, program it into
+	 *  max and base 0 registers.
+	 */
+	if (dma_int == STALL) {
+		DPRINTK("1  ");
+
+		if (dma->total_buffers) {
+			/*
+			 *  The current_buffer has already been tranfered, so add the
+			 *  byte count to the total_bytes field.
+			 */
+			dma->total_bytes = dma->total_bytes +
+			    dma->buffer_queue[dma->current_buffer].size;
+
+			/*
+			 *  Mark the current_buffer as used.
+			 */
+			dma->buffer_queue[dma->current_buffer].used = TRUE;
+
+			/*
+			 *  Increment the used buffer counter
+			 */
+			dma->used_buffers++;
+
+			DPRINTK("#%d", dma->current_buffer);
+
+			/*
+			 *  Increment the current_buffer
+			 */
+			dma->current_buffer = (dma->current_buffer + 1) %
+			    MAX_EP93XX_DMA_BUFFERS;
+
+			/*
+			 *  check if there's a new buffer to transfer.
+			 */
+			if (dma->new_buffers && dma->xfer_enable) {
+				/*
+				 *  We have a new buffer to transfer so program in the buffer
+				 *  values.  Since a STALL interrupt was triggered, we
+				 *  program the base0 and maxcnt0
+				 *
+				 *  Set the MAXCNT0 register with the buffer size
+				 */
+				writel(dma->buffer_queue[dma->current_buffer].size,
+					 M2P_reg_base + M2P_OFFSET_MAXCNT0);
+
+				/*
+				 *  Set the BASE0 register with the buffer base address
+				 */
+				writel(dma->buffer_queue[dma->current_buffer].source,
+					M2P_reg_base + M2P_OFFSET_BASE0);
+
+				/*
+				 *  Decrement the new buffer counter
+				 */
+				dma->new_buffers--;
+
+				if (dma->new_buffers) {
+					DPRINTK("A  ");
+					/*
+					 *  Set the MAXCNT1 register with the buffer size
+					 */
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       size,
+					       M2P_reg_base + M2P_OFFSET_MAXCNT1);
+
+					/*
+					 *  Set the BASE1 register with the buffer base address
+					 */
+					writel(dma->
+					       buffer_queue[dma->
+							    current_buffer +
+							    1 %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       source,
+					       M2P_reg_base + M2P_OFFSET_BASE1);
+
+					/*
+					 *  Decrement the new buffer counter
+					 */
+					dma->new_buffers--;
+
+					/*
+					 *  Enable the NFB Interrupt.
+					 */
+					uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+					uiCONTROL |= CONTROL_M2P_NFBINTEN;
+					writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+				}
+			}
+			/*
+			 *  No new buffers.
+			 */
+			else {
+				DPRINTK("2 \n");
+				/*
+				 *  There's a chance we setup both buffer descriptors, but
+				 *  didn't service the NFB quickly enough, causing the channel
+				 *  to transfer both buffers, then enter the stall state.
+				 *  So, we need to be able to process the second buffer.
+				 */
+				if ((dma->used_buffers + dma->new_buffers) <
+				    dma->total_buffers) {
+					DPRINTK("3 ");
+
+					/*
+					 *  The current_buffer has already been tranfered, so add the
+					 *  byte count to the total_bytes field.
+					 */
+					dma->total_bytes = dma->total_bytes +
+					    dma->buffer_queue[dma->
+							      current_buffer].
+					    size;
+
+					/*
+					 *  Mark the current_buffer as used.
+					 */
+					dma->buffer_queue[dma->current_buffer].
+					    used = TRUE;
+
+					/*
+					 *  Increment the used buffer counter
+					 */
+					dma->used_buffers++;
+
+					DPRINTK("#%d", dma->current_buffer);
+
+					/*
+					 *  Increment the current buffer pointer.
+					 */
+					dma->current_buffer =
+					    (dma->current_buffer +
+					     1) % MAX_EP93XX_DMA_BUFFERS;
+
+				}
+
+				/*
+				 *  No new buffers to transfer, so disable the channel.
+				 */
+				/* go dma_regs->CONTROL.Field.ENABLE = 0; */
+				uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+				uiCONTROL &= ~CONTROL_M2P_ENABLE;
+				writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+
+				/*
+				 *  Indicate that this channel is in the pause by starvation
+				 *  state by setting the pause bit to true.
+				 */
+				dma->pause = TRUE;
+
+				DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
+				DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
+				DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
+				DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
+				DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
+				DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
+				DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
+				DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
+				DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
+				DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
+
+				DPRINTK
+				    ("Buffer    buf_id     source       size       last       used \n");
+				for (loop = 0; loop < 32; loop++) {
+					DPRINTK
+					    ("%d        0x%x        0x%x         0x%x        %d         %d \n",
+					     loop,
+					     dma->buffer_queue[loop].buf_id,
+					     dma->buffer_queue[loop].source,
+					     dma->buffer_queue[loop].size,
+					     dma->buffer_queue[loop].last,
+					     dma->buffer_queue[loop].used);
+				}
+				DPRINTK
+				    ("pause     0x%x        0x%x         0x%x        %d         %d \n",
+				     dma->pause_buf.buf_id,
+				     dma->pause_buf.source, dma->pause_buf.size,
+				     dma->pause_buf.last, dma->pause_buf.used);
+
+				DPRINTK("Pause - %d \n", dma->pause);
+				DPRINTK("xfer_enable - %d \n",
+					dma->xfer_enable);
+				DPRINTK("total bytes - 0x%x \n",
+					dma->total_bytes);
+				DPRINTK("total buffer - %d \n",
+					dma->total_buffers);
+				DPRINTK("new buffers - %d \n",
+					dma->new_buffers);
+				DPRINTK("current buffer - %d \n",
+					dma->current_buffer);
+				DPRINTK("last buffer - %d \n",
+					dma->last_buffer);
+				DPRINTK("used buffers - %d \n",
+					dma->used_buffers);
+				DPRINTK("callback addr - 0x%x \n",
+					dma->callback);
+			}
+		}
+		/*
+		 *  Total number of buffers in the queue is 0.
+		 */
+		else {
+			/*
+			 *  No buffers to transfer, or old buffers to mark as used,
+			 *  so Disable the channel
+			 */
+			uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+			uiCONTROL &= ~CONTROL_M2P_ENABLE;
+			writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+
+			/*
+			 *  Must read the control register back after a write.
+			 */
+			read_back = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+
+			/*
+			 *  Indicate that this channel is in the pause by
+			 *  starvation state by setting the pause bit to true.
+			 */
+			dma->pause = TRUE;
+		}
+	}
+	/*
+	 *  Next Frame Buffer Interrupt.  If there's a new buffer program it
+	 *  Check if this is the last buffer in the transfer,
+	 *  and if it is, disable the NFB int to prevent being
+	 *  interrupted for another buffer when we know there won't be
+	 *  another.
+	 */
+	if (dma_int == NFB) {
+		DPRINTK("5  ");
+
+		if (dma->total_buffers) {
+			DPRINTK("6  ");
+			/*
+			 *  The iCurrentBuffer has already been transfered.  so add the
+			 *  byte count from the current buffer to the total byte count.
+			 */
+			dma->total_bytes = dma->total_bytes +
+			    dma->buffer_queue[dma->current_buffer].size;
+
+			/*
+			 *  Mark the Current Buffer as used.
+			 */
+			dma->buffer_queue[dma->current_buffer].used = TRUE;
+
+			/*
+			 *  Increment the used buffer counter
+			 */
+			dma->used_buffers++;
+
+			DPRINTK("#%d", dma->current_buffer);
+
+			if ((dma->buffer_queue[(dma->current_buffer +
+						1) %
+					       MAX_EP93XX_DMA_BUFFERS].last)
+			    || (dma->new_buffers == 0)
+			    || (dma->xfer_enable == FALSE)) {
+				DPRINTK("7  ");
+
+				/*
+				 *  This is the last Buffer in this transaction, so disable
+				 *  the NFB interrupt.  We shouldn't get an NFB int when the
+				 *  FSM moves to the ON state where it would typically get the
+				 *  NFB int indicating a new buffer can be programmed.
+				 *  Instead, once in the ON state, the DMA will just proceed
+				 *  to complet the transfer of the current buffer, move the
+				 *  FSB directly to the STALL state where a STALL interrupt
+				 *  will be generated.
+				 */
+				uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+				uiCONTROL &= ~CONTROL_M2P_NFBINTEN;
+				writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+
+				/*
+				 *  The current buffer has been transferred, so increment
+				 *  the current buffer counter to reflect this.
+				 */
+				dma->current_buffer =
+				    (dma->current_buffer +
+				     1) % MAX_EP93XX_DMA_BUFFERS;
+
+				DPRINTK("End of NFB handling. \n");
+				DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
+				DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
+				DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
+				DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
+				DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
+				DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
+				DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
+				DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
+				DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
+				DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
+
+				DPRINTK
+				    ("Buffer    buf_id     source       size       last       used \n");
+				for (loop = 0; loop < 32; loop++) {
+					DPRINTK
+					    ("%d        0x%x        0x%x         0x%x        %d         %d \n",
+					     loop,
+					     dma->buffer_queue[loop].buf_id,
+					     dma->buffer_queue[loop].source,
+					     dma->buffer_queue[loop].size,
+					     dma->buffer_queue[loop].last,
+					     dma->buffer_queue[loop].used);
+				}
+				DPRINTK
+				    ("pause     0x%x        0x%x         0x%x        %d         %d \n",
+				     dma->pause_buf.buf_id,
+				     dma->pause_buf.source, dma->pause_buf.size,
+				     dma->pause_buf.last, dma->pause_buf.used);
+
+				DPRINTK("Pause - %d \n", dma->pause);
+				DPRINTK("xfer_enable - %d \n",
+					dma->xfer_enable);
+				DPRINTK("total bytes - 0x%x \n",
+					dma->total_bytes);
+				DPRINTK("total buffer - %d \n",
+					dma->total_buffers);
+				DPRINTK("new buffers - %d \n",
+					dma->new_buffers);
+				DPRINTK("current buffer - %d \n",
+					dma->current_buffer);
+				DPRINTK("last buffer - %d \n",
+					dma->last_buffer);
+				DPRINTK("used buffers - %d \n",
+					dma->used_buffers);
+				DPRINTK("callback addr - 0x%x \n",
+					dma->callback);
+
+			} else if (dma->new_buffers) {
+				DPRINTK("8  ");
+				/*
+				 *  we have a new buffer, so increment the current buffer to
+				 *  point to the next buffer, which is already programmed into
+				 *  the DMA. Next time around, it'll be pointing to the
+				 *  current buffer.
+				 */
+				dma->current_buffer =
+				    (dma->current_buffer +
+				     1) % MAX_EP93XX_DMA_BUFFERS;
+
+				/*
+				 *  we know we have a new buffer to program as the next
+				 *  buffer, so check which set of MAXCNT and BASE registers
+				 *  to program.
+				 */
+				if (readl(M2P_reg_base + M2P_OFFSET_STATUS) &
+				    STATUS_M2P_NEXTBUFFER) {
+					/*
+					 *  Set the MAXCNT1 register with the buffer size
+					 */
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       size,
+					       M2P_reg_base + M2P_OFFSET_MAXCNT1);
+
+					/*
+					 *  Set the BASE1 register with the buffer base address
+					 */
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       source,
+					       M2P_reg_base + M2P_OFFSET_BASE1);
+				} else {
+					/*
+					 *  Set the MAXCNT0 register with the buffer size
+					 */
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       size,
+					       M2P_reg_base + M2P_OFFSET_MAXCNT0);
+
+					/*
+					 *  Set the BASE0 register with the buffer base address
+					 */
+					writel(dma->
+					       buffer_queue[(dma->
+							     current_buffer +
+							     1) %
+							    MAX_EP93XX_DMA_BUFFERS].
+					       source,
+					       M2P_reg_base + M2P_OFFSET_BASE0);
+				}
+
+				/*
+				 *  Decrement the new buffers counter
+				 */
+				dma->new_buffers--;
+			}
+		}
+		/*
+		 *  Total number of buffers is 0 - really we should never get here,
+		 *  but just in case.
+		 */
+		else {
+			DPRINTK("9 \n");
+
+			/*
+			 *  No new buffers to transfer, so Disable the channel
+			 */
+			uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+			uiCONTROL &= ~CONTROL_M2P_ENABLE;
+			writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+		}
+	}
+	/*
+	 *  Channel Error Interrupt, or perhipheral interrupt, specific to the
+	 *  memory to/from peripheral channels.
+	 */
+	if (dma_int == CHERROR) {
+		/*
+		 *  just clear the interrupt, it's really up to the peripheral
+		 *  driver to determine if any further action is necessary.
+		 */
+		uiINTERRUPT =
+		    readl(M2P_reg_base + M2P_OFFSET_INTERRUPT);
+		uiINTERRUPT &= ~INTERRUPT_M2P_CHERRORINT;
+		writel(uiINTERRUPT, M2P_reg_base + M2P_OFFSET_INTERRUPT);
+	}
+
+	/*
+	 *  Make sure the interrupt was valid, and if it was, then check
+	 *  if a callback function was installed for this DMA channel.  If a
+	 *  callback was installed call it.
+	 */
+	if ((dma_int != UNDEF_INT) && dma->callback) {
+		dma->callback(dma_int, dma->device, dma->user_data);
+	}
+	return IRQ_HANDLED;
+}
+
+/*****************************************************************************
+ *
+ * ep9312_dma_open_m2p(int device)
+ *
+ * Description: This function will attempt to open a M2P/P2M DMA channel.
+ *              If the open is successful, the channel number is returned,
+ *              otherwise a negative number is returned.
+ *
+ * Parameters:
+ *  device:     device for which the dma channel is requested.
+ *
+ ****************************************************************************/
+static int dma_open_m2p(int device)
+{
+	int channel = -1;
+	unsigned int loop;
+	unsigned int M2P_reg_base;
+	unsigned int uiPWRCNT;
+
+	DPRINTK("DMA Open M2P with hw dev %d\n", device);
+
+	/*
+	 *  Lock the dma channel list.
+	 */
+	spin_lock(&dma_list_lock);
+	DPRINTK("1\n");
+	/*
+	 * Verify that the device requesting DMA isn't already using a DMA channel
+	 */
+	if (device >= 10) {
+		loop = 1;	/* Rx transfer requested */
+	} else {
+		loop = 0;	/* Tx transfer requested */
+	}
+
+	for (; loop < 10; loop = loop + 2) {
+		/*
+		 *  Before checking for a matching device, check that the
+		 *  channel is in use, otherwise the device field is
+		 *  invalid.
+		 */
+		if (dma_chan[loop].ref_count) {
+			if (device == dma_chan[loop].device) {
+				DPRINTK("DMA Open M2P - Error\n");
+				/*
+				 *  Fail.
+				 */
+				return (-1);
+			}
+		}
+	}
+
+	/*
+	 *  Get a DMA channel instance for the given hardware device.
+	 *  If this is a TX look for even numbered channels, else look for
+	 *  odd numbered channels
+	 */
+	if (device >= 10) {
+		loop = 1;	/* Rx transfer requested */
+	} else {
+		loop = 0;	/* Tx transfer requested */
+	}
+
+	for (; loop < 10; loop = loop + 2) {
+		if (!dma_chan[loop].ref_count) {
+			/*
+			 *  Capture the channel and increment the reference count.
+			 */
+			channel = loop;
+			dma_chan[channel].ref_count++;
+			break;
+		}
+	}
+
+	/*
+	 *  Unlock the dma channel list.
+	 */
+	spin_unlock(&dma_list_lock);
+
+	/*
+	 *  See if we got a valid channel.
+	 */
+	if (channel < 0) {
+		/*
+		 *  Fail.
+		 */
+		return (-1);
+	}
+
+	/*
+	 *  Point regs to the correct dma channel register base.
+	 */
+	M2P_reg_base = dma_chan[channel].reg_base;
+
+	/*
+	 *  Turn on the clock for the specified DMA channel
+	 *  TODO: need to use the correct register name for the
+	 *  power control register.
+	 */
+	uiPWRCNT = readl(SYSCON_PWRCNT);
+	switch (channel) {
+	case 0:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH0;
+			break;
+		}
+
+	case 1:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH1;
+			break;
+		}
+
+	case 2:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH2;
+			break;
+		}
+
+	case 3:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH3;
+			break;
+		}
+
+	case 4:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH4;
+			break;
+		}
+
+	case 5:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH5;
+			break;
+		}
+
+	case 6:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH6;
+			break;
+		}
+
+	case 7:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH7;
+			break;
+		}
+	case 8:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH8;
+			break;
+		}
+	case 9:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH9;
+			break;
+		}
+
+	default:
+		{
+			return (-1);
+		}
+	}
+	writel(uiPWRCNT, SYSCON_PWRCNT);
+
+	/*
+	 *  Clear out the control register before any further setup.
+	 */
+	writel(0, M2P_reg_base + M2P_OFFSET_CONTROL);
+
+	/*
+	 *  Setup the peripheral port value in the DMA channel registers.
+	 */
+	if (device < 10) {
+		writel((unsigned int)device,
+		       M2P_reg_base + M2P_OFFSET_PPALLOC);
+	} else {
+		writel((unsigned int)(device - 10),
+		       M2P_reg_base + M2P_OFFSET_PPALLOC);
+	}
+
+	/*
+	 *  Let's hold on to the value of the Hw device for comparison later.
+	 */
+	dma_chan[channel].device = device;
+
+	/*
+	 *  Success.
+	 */
+	return (channel);
+}
+
+/*****************************************************************************
+ *
+ * dma_open_m2m(int device)
+ *
+ * Description: This function will attempt to open a M2M DMA channel.
+ *              If the open is successful, the channel number is returned,
+ *              otherwise a negative number is returned.
+ *
+ * Parameters:
+ *  device:     device for which the dma channel is requested.
+ *
+ ****************************************************************************/
+static int dma_open_m2m(int device)
+{
+	int channel = -1;
+	unsigned int loop;
+	unsigned int M2M_reg_base;
+	unsigned int uiPWRCNT, uiCONTROL;
+
+	DPRINTK("DMA Open M2M with hw dev %d\n", device);
+
+	/*
+	 *  Lock the dma channel list.
+	 */
+	spin_lock(&dma_list_lock);
+	DPRINTK("1\n");
+
+	/*
+	 *  Check if this device is already allocated a channel.
+	 *  TODO: can one M2M device be allocated multiple channels?
+	 */
+	for (loop = DMA_MEMORY; loop < UNDEF; loop++) {
+		/*
+		 *  Before checking for a matching device, check that the
+		 *  channel is in use, otherwise the device field is
+		 *  invalid.
+		 */
+		if (dma_chan[loop].ref_count) {
+			if (device == dma_chan[loop].device) {
+				DPRINTK
+				    ("Error - dma_open_m2m - already allocated channel\n");
+
+				/*
+				 *  Unlock the dma channel list.
+				 */
+				spin_unlock(&dma_list_lock);
+
+				/*
+				 *  Fail.
+				 */
+				return (-1);
+			}
+		}
+	}
+
+	/*
+	 *  Get a DMA channel instance for the given hardware device.
+	 */
+	for (loop = 10; loop < 12; loop++) {
+		if (!dma_chan[loop].ref_count) {
+			/*
+			 *  Capture the channel and increment the reference count.
+			 */
+			channel = loop;
+			dma_chan[channel].ref_count++;
+			break;
+		}
+	}
+
+	/*
+	 *  Unlock the dma channel list.
+	 */
+	spin_unlock(&dma_list_lock);
+
+	/*
+	 *  See if we got a valid channel.
+	 */
+	if (channel < 0) {
+		/*
+		 *  Fail.
+		 */
+		return (-1);
+	}
+
+	/*
+	 *  Point regs to the correct dma channel register base.
+	 */
+	M2M_reg_base = dma_chan[channel].reg_base;
+
+	/*
+	 *  Turn on the clock for the specified DMA channel
+	 *  TODO: need to use the correct register name for the
+	 *  power control register.
+	 */
+	uiPWRCNT = readl(SYSCON_PWRCNT);
+	switch (channel) {
+	case 10:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH0;
+			break;
+		}
+
+	case 11:
+		{
+			uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH1;
+			break;
+		}
+
+	default:
+		{
+			return (-1);
+		}
+	}
+	writel(uiPWRCNT, SYSCON_PWRCNT);
+
+	DPRINTK("DMA Open - power control: 0x%x \n",
+		readl(SYSCON_PWRCNT));
+
+	/*
+	 *  Clear out the control register before any further setup.
+	 */
+	writel(0, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+	/*
+	 *  Setup the transfer mode and the request source selection within
+	 *  the DMA M2M channel registers.
+	 */
+	switch (device) {
+	case DMA_MEMORY:
+		{
+			/*
+			 * Clear TM field, set RSS field to 0
+			 */
+			uiCONTROL =
+			    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+			uiCONTROL &=
+			    ~(CONTROL_M2M_TM_MASK | CONTROL_M2M_RSS_MASK);
+			writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			break;
+		}
+
+	case DMA_IDE:
+		{
+			/*
+			 * Set RSS field to 3, Set NO_HDSK, Set PW field to 1
+			 */
+			uiCONTROL =
+			    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+			uiCONTROL &=
+			    ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_PW_MASK);
+			uiCONTROL |=
+			    (3 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
+			    (2 << CONTROL_M2M_PW_SHIFT);
+
+			uiCONTROL &= ~(CONTROL_M2M_ETDP_MASK);
+			uiCONTROL &= ~(CONTROL_M2M_DACKP);
+			uiCONTROL &= ~(CONTROL_M2M_DREQP_MASK);
+
+			writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			break;
+		}
+
+	case DMARx_SSP:
+		{
+			/*
+			 * Set RSS field to 1, Set NO_HDSK, Set TM field to 2
+			 */
+			uiCONTROL =
+			    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+			uiCONTROL &=
+			    ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
+			uiCONTROL |=
+			    (1 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
+			    (2 << CONTROL_M2M_TM_SHIFT);
+			writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			break;
+		}
+
+	case DMATx_SSP:
+		{
+			/*
+			 * Set RSS field to 2, Set NO_HDSK, Set TM field to 1
+			 */
+			uiCONTROL =
+			    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+			uiCONTROL &=
+			    ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
+			uiCONTROL |=
+			    (2 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
+			    (1 << CONTROL_M2M_TM_SHIFT);
+			writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			break;
+		}
+
+	case DMATx_EXT_DREQ:
+		{
+			/*
+			 * Set TM field to 2, set RSS field to 0
+			 */
+			uiCONTROL =
+			    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+			uiCONTROL &=
+			    ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
+			uiCONTROL |= 1 << CONTROL_M2M_TM_SHIFT;
+			writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			break;
+		}
+
+	case DMARx_EXT_DREQ:
+		{
+
+			/*
+			 * Set TM field to 2, set RSS field to 0
+			 */
+			uiCONTROL =
+			    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+			uiCONTROL &=
+			    ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
+			uiCONTROL |= 2 << CONTROL_M2M_TM_SHIFT;
+			writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+			break;
+		}
+
+	default:
+		{
+			return -1;
+		}
+	}
+
+	/*
+	 *  Let's hold on to the value of the Hw device for comparison later.
+	 */
+	dma_chan[channel].device = device;
+
+	/*
+	 *  Success.
+	 */
+	return (channel);
+}
+
+/*****************************************************************************
+ *
+ *  int dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m,
+ *               dma_callback callback, unsigned int user_data)
+ *
+ *  Description: Configure the DMA channel and install a callback function.
+ *               This function will have to be called for every transfer
+ *
+ *  dma:        Pointer to the dma instance data for the M2M channel to
+ *              configure.
+ *  flags_m2m   Flags used to configure an M2M dma channel and determine
+ *              if a callback function and user_data information are included
+ *              in this call.
+ *  callback    function pointer which is called near the end of the
+ *              dma channel's irq handler.
+ *  user_data   defined by the calling driver.
+ *
+ ****************************************************************************/
+static int
+dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m,
+	       dma_callback callback, unsigned int user_data)
+{
+	unsigned long flags;
+	unsigned int M2M_reg_base, uiCONTROL;
+
+	/*
+	 *  Make sure the channel is disabled before configuring the channel.
+	 *
+	 *  TODO: Is this correct??   Making a big change here...
+	 */
+	/* if(!dma->pause || (!dma->pause && dma->xfer_enable)) */
+	if (dma->xfer_enable) {
+		/*
+		 *  DMA channel is not paused, so we can't configure it.
+		 */
+		DPRINTK("DMA channel not paused, so can't configure! \n");
+		return (-1);
+	}
+
+	/*
+	 *  Mask interrupts.
+	 */
+	local_irq_save(flags);
+
+	/*
+	 *  Setup a pointer into the dma channel's register set.
+	 */
+	M2M_reg_base = dma->reg_base;
+
+	/*
+	 *  By default we enable the stall interrupt.
+	 */
+	uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+	uiCONTROL |= CONTROL_M2M_STALLINTEN;
+	writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+	/*
+	 *  By default we enable the done interrupt.
+	 */
+	uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+	uiCONTROL &= ~CONTROL_M2M_DONEINTEN;
+	writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+	/*
+	 *  Set up the transfer control fields based on values passed in
+	 *  the flags_m2m field.
+	 */
+	uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+
+	if (flags_m2m & DESTINATION_HOLD) {
+		uiCONTROL |= CONTROL_M2M_DAH;
+	} else {
+		uiCONTROL &= ~CONTROL_M2M_DAH;
+	}
+
+	if (flags_m2m & SOURCE_HOLD) {
+		uiCONTROL |= CONTROL_M2M_SAH;
+	} else {
+		uiCONTROL &= ~CONTROL_M2M_SAH;
+	}
+
+	uiCONTROL &= ~CONTROL_M2M_TM_MASK;
+	uiCONTROL |=
+	    (((flags_m2m & TRANSFER_MODE_MASK) >> TRANSFER_MODE_SHIFT) <<
+	     CONTROL_M2M_TM_SHIFT) & CONTROL_M2M_TM_MASK;
+
+	uiCONTROL &= ~CONTROL_M2M_PWSC_MASK;
+	uiCONTROL |= (((flags_m2m & WAIT_STATES_MASK) >> WAIT_STATES_SHIFT) <<
+		      CONTROL_M2M_PWSC_SHIFT) & CONTROL_M2M_PWSC_MASK;
+
+	writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+	/*
+	 *  Save the callback function in the dma instance for this channel.
+	 */
+	dma->callback = callback;
+
+	/*
+	 *  Save the user data in the the dma instance for this channel.
+	 */
+	dma->user_data = user_data;
+
+	/*
+	 *  Put the dma instance into the pause state by setting the
+	 *  pause bit to true.
+	 */
+	dma->pause = TRUE;
+
+	local_irq_restore(flags);
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ *  int dma_start(int handle, unsigned int channels, unsigned int * handles)
+ *
+ *  Description: Initiate a transfer on up to 3 channels.
+ *
+ *  handle:     handle for the channel to initiate transfer on.
+ *  channels:   number of channels to initiate transfers on.
+ *  handles:    pointer to an array of handles, one for each channel which
+ *               is to be started.
+ *
+ ****************************************************************************/
+static int dma_start_m2m(int channel, ep93xx_dma_t * dma)
+{
+	unsigned long flags;
+	unsigned int M2M_reg_base = dma->reg_base;
+	unsigned int uiCONTROL;
+
+	/*
+	 *  Mask interrupts while we get this started.
+	 */
+	local_irq_save(flags);
+
+	/*
+	 *  Make sure the channel has at least one buffer in the queue.
+	 */
+	if (dma->new_buffers < 1) {
+		/*
+		 *  Unmask irqs
+		 */
+		local_irq_restore(flags);
+
+		DPRINTK("DMA Start: Channel starved.\n");
+
+		/*
+		 *  This channel does not have enough buffers queued up,
+		 *  so enter the pause by starvation state.
+		 */
+		dma->xfer_enable = TRUE;
+		dma->pause = TRUE;
+
+		/*
+		 *  Success.
+		 */
+		return (0);
+	}
+
+	/*
+	 *  Clear any pending interrupts.
+	 */
+	writel(0x0, M2M_reg_base + M2M_OFFSET_INTERRUPT);
+
+	/*
+	 *  Set up one or both buffer descriptors with values from the next one or
+	 *  two buffers in the queue.  By default enable the next frame buffer
+	 *  interrupt on the channel.
+	 */
+	uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+	uiCONTROL &= ~CONTROL_M2M_NFBINTEN;
+	writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+	/*
+	 * enable the stall interrupt.
+	 */
+	uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+	uiCONTROL |= CONTROL_M2M_STALLINTEN;
+	writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+	/*
+	 *  Update the dma channel instance transfer state.
+	 */
+	dma->xfer_enable = TRUE;
+	dma->pause = FALSE;
+
+	/*
+	 *  Decrement the new buffers counter.
+	 */
+	dma->new_buffers--;
+
+	/*
+	 *  Program up the first buffer descriptor with a source and destination
+	 *  and a byte count.
+	 */
+	writel(dma->buffer_queue[dma->current_buffer].source,
+	       M2M_reg_base + M2M_OFFSET_SAR_BASE0);
+
+	writel(dma->buffer_queue[dma->current_buffer].dest,
+	       M2M_reg_base + M2M_OFFSET_DAR_BASE0);
+
+	writel(dma->buffer_queue[dma->current_buffer].size,
+	       M2M_reg_base + M2M_OFFSET_BCR0);
+
+	/*
+	 *  Now we enable the channel.  This initiates the transfer.
+	 */
+	uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+	uiCONTROL |= CONTROL_M2M_ENABLE;
+	writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+	writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+
+	/*
+	 *  Before restoring irqs set up the second buffer descriptor
+	 *  with a second buffer if we have a second buffer.
+	 */
+	/* if(dma->new_buffers)
+	   {
+	   outl( dma->buffer_queue[(dma->current_buffer + 1) %
+	   MAX_EP93XX_DMA_BUFFERS].source,
+	   M2M_reg_base+M2M_OFFSET_SAR_BASE1 );
+
+	   outl( dma->buffer_queue[(dma->current_buffer + 1) %
+	   MAX_EP93XX_DMA_BUFFERS].dest,
+	   M2M_reg_base+M2M_OFFSET_DAR_BASE1 );
+
+	   outl( dma->buffer_queue[(dma->current_buffer + 1) %
+	   MAX_EP93XX_DMA_BUFFERS].size,
+	   M2M_reg_base+M2M_OFFSET_BCR1 );
+	   }  */
+
+	/*
+	 *  If this is a memory to memory transfer, we need to s/w trigger the
+	 *  transfer by setting the start bit within the control register.
+	 */
+	if (dma->device == DMA_MEMORY) {
+		uiCONTROL =
+		    readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+		uiCONTROL |= CONTROL_M2M_START;
+		writel(uiCONTROL,
+		       M2M_reg_base + M2M_OFFSET_CONTROL);
+	}
+
+	DPRINTK("DMA - It's been started!!");
+	DPRINTK("STATUS - 0x%x \n",	readl(M2M_reg_base + M2M_OFFSET_STATUS));
+	DPRINTK("CONTROL - 0x%x \n", readl(M2M_reg_base + M2M_CONTROL.Value));
+	DPRINTK("REMAIN - 0x%x \n", readl(M2M_reg_base + M2M_REMAIN.Value));
+	DPRINTK("PPALLOC - 0x%x \n", readl(M2M_reg_base + M2M_PPALLOC.Value));
+	DPRINTK("BASE0 - 0x%x \n", readl(M2M_reg_base + M2M_BASE0.Value));
+	DPRINTK("MAXCNT0 - 0x%x \n", readl(M2M_reg_base + M2M_MAXCNT0.Value));
+	DPRINTK("CURRENT0 - 0x%x \n", readl(M2M_reg_base + M2M_CURRENT0.Value));
+	DPRINTK("BASE1 - 0x%x \n", readl(M2M_reg_base + M2M_BASE1.Value));
+	DPRINTK("MAXCNT1 - 0x%x \n", readl(M2M_reg_base + M2M_MAXCNT1.Value));
+	DPRINTK("CURRENT1 - 0x%x \n", readl(M2M_reg_base + M2M_CURRENT1.Value));
+
+	DPRINTK("Pause - %d \n", dma_pointers[0]->pause);
+	DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable);
+	DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes);
+	DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers);
+	DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers);
+	DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer);
+	DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer);
+	DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers);
+
+	/*
+	 *  Unmask irqs
+	 */
+	local_irq_restore(flags);
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ *  DMA interface functions
+ *
+ ****************************************************************************/
+
+/*****************************************************************************
+ *
+ *  int dma_init(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
+ *               dma_callback callback, unsigned int user_data)
+ *
+ *  Description: Configure the DMA channel and install a callback function.
+ *
+ *  handle:     Handle unique the each instance of the dma interface, used
+ *              to verify this call.
+ *  flags_m2p   Flags used to configure an M2P/P2M dma channel and determine
+ *              if a callback function and user_data information are included
+ *              in this call. This field should be NULL if handle represents
+ *              an M2M channel.
+ *  flags_m2m   Flags used to configure an M2M dma channel and determine
+ *              if a callback function and user_data information are included
+ *              in this call. This field should be NULL if handle represents
+ *              an M2P/P2M channel.
+ *  callback    function pointer which is called near the end of the
+ *              dma channel's irq handler.
+ *  user_data   defined by the calling driver.
+ *
+ ****************************************************************************/
+int
+ep93xx_dma_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
+		  dma_callback callback, unsigned int user_data)
+{
+	int channel;
+	ep93xx_dma_t *dma;
+	unsigned long flags;
+	unsigned int M2P_reg_base, uiCONTROL;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Config: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	DPRINTK("DMA Config \n");
+
+	dma = &dma_chan[channel];
+
+	local_irq_save(flags);
+
+	/*
+	 *  Check if the channel is currently transferring.
+	 */
+	if (dma->xfer_enable) {
+		local_irq_restore(flags);
+
+		/*
+		 *  Already transferring, invalid command.
+		 */
+		return (-EINVAL);
+	}
+
+	/*
+	 *  Check if this is an m2m function.
+	 */
+	if (channel >= 10) {
+		local_irq_restore(flags);
+
+		/*
+		 *  Call another function to handle m2m config.
+		 */
+		return (dma_config_m2m(dma, flags_m2m, callback, user_data));
+	}
+
+	/*
+	 *  Setup a pointer into the dma channel's register set.
+	 */
+	M2P_reg_base = dma->reg_base;
+
+	/*
+	 *  By default we enable the stall interrupt.
+	 */
+	uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+	uiCONTROL |= CONTROL_M2P_STALLINTEN;
+	writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+
+	/*
+	 *  Configure the channel for an error from the peripheral.
+	 */
+	uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+	if (flags_m2p && CHANNEL_ERROR_INT_ENABLE)
+		uiCONTROL |= CONTROL_M2P_CHERRORINTEN;
+	else
+		uiCONTROL &= ~CONTROL_M2P_CHERRORINTEN;
+	writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+
+	uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+	if (flags_m2p && EP93XX_DMA_ABORT)
+		uiCONTROL |= CONTROL_M2P_ABRT;
+	else
+		uiCONTROL &= ~CONTROL_M2P_ABRT;
+	writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+
+	uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+	if (flags_m2p && IGNORE_CHANNEL_ERROR)
+		uiCONTROL |= CONTROL_M2P_ICE;
+	else
+		uiCONTROL &= ~CONTROL_M2P_ICE;
+	writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+
+	/*
+	 *  Save the callback function in the dma instance for this channel.
+	 */
+	dma->callback = callback;
+
+	/*
+	 *  Save the user data in the the dma instance for this channel.
+	 */
+	dma->user_data = user_data;
+
+	/*
+	 *  Put the dma instance into the pause state by setting the
+	 *  pause bit to true.
+	 */
+	dma->pause = TRUE;
+
+	local_irq_restore(flags);
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ *  int dma_start(int handle, unsigned int channels, unsigned int * handles)
+ *
+ *  Description: Initiate a transfer on up to 3 channels.
+ *
+ *  handle:     handle for the channel to initiate transfer on.
+ *  channels:   number of channels to initiate transfers on.
+ *  handles:    pointer to an array of handles, one for each channel which
+ *               is to be started.
+ *
+ ****************************************************************************/
+int ep93xx_dma_start(int handle, unsigned int channels, unsigned int *handles)
+{
+	ep93xx_dma_t *dma_pointers[3];
+	unsigned int M2P_reg_bases[3];
+	unsigned int loop, uiCONTROL;
+	unsigned long flags;
+	int channel;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Start: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	if (channels < 1) {
+		printk(KERN_ERR "DMA Start: Invalid parameter.\n");
+
+		return (-EINVAL);
+	}
+
+	DPRINTK("DMA Start \n");
+
+	/*
+	 *  Mask off registers.
+	 */
+	local_irq_save(flags);
+
+	/*
+	 *  Check if this is a start multiple.
+	 */
+	if (channels > 1) {
+		DPRINTK
+		    ("DMA ERROR: Start, multiple start not supported yet \n");
+		return (-1);
+	}
+	/*
+	 *  Only one channel
+	 */
+	else {
+		/*
+		 *  Check if this channel is already transferring.
+		 */
+		if (dma_chan[channel].xfer_enable && !dma_chan[channel].pause) {
+			printk(KERN_ERR
+			       "DMA Start: Invalid command for channel %d.\n",
+			       channel);
+			DPRINTK("DMA Start: Invalid command for channel %d.\n",
+				channel);
+
+			/*
+			 *  Unmask irqs
+			 */
+			local_irq_restore(flags);
+
+			/*
+			 *  This channel is already transferring, so return an error.
+			 */
+			return (-EINVAL);
+		}
+
+		/*
+		 *  If this is an M2M channel, call a different function.
+		 */
+		if (channel >= 10) {
+			/*
+			 *  Unmask irqs
+			 */
+			local_irq_restore(flags);
+
+			/*
+			 *  Call the m2m start function.  Only start one channel.
+			 */
+			return (dma_start_m2m(channel, &dma_chan[channel]));
+		}
+
+		/*
+		 *  Make sure the channel has at least one buffer in the queue.
+		 */
+		if (dma_chan[channel].new_buffers < 1) {
+			DPRINTK("DMA Start: Channel starved.\n");
+
+			/*
+			 *  This channel does not have enough buffers queued up,
+			 *  so enter the pause by starvation state.
+			 */
+			dma_chan[channel].xfer_enable = TRUE;
+			dma_chan[channel].pause = TRUE;
+
+			/*
+			 *  Unmask irqs
+			 */
+			local_irq_restore(flags);
+
+			/*
+			 *  Success.
+			 */
+			return (0);
+		}
+
+		/*
+		 *  Set up a dma instance pointer for this dma channel.
+		 */
+		dma_pointers[0] = &dma_chan[channel];
+
+		/*
+		 * Set up a pointer to the register set for this channel.
+		 */
+		M2P_reg_bases[0] = dma_pointers[0]->reg_base;
+	}
+
+	/*
+	 *  Setup both MAXCNT registers with values from the next two buffers
+	 *  in the queue, and enable the next frame buffer interrupt on the channel.
+	 */
+	for (loop = 0; loop < channels; loop++) {
+		/*
+		 *  By default we enable the next frame buffer interrupt.
+		 */
+		uiCONTROL = readl(M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
+		uiCONTROL |= CONTROL_M2P_NFBINTEN;
+		writel(uiCONTROL, M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
+
+		/*
+		 *  Check if we need to restore a paused transfer.
+		 */
+		if (dma_pointers[loop]->pause_buf.buf_id != -1) {
+			writel(dma_pointers[loop]->pause_buf.size,
+			       M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT0);
+		} else {
+			writel(dma_pointers[loop]->
+			       buffer_queue[dma_pointers[loop]->current_buffer].
+			       size,
+			       M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT0);
+		}
+	}
+
+	for (loop = 0; loop < channels; loop++) {
+		/*
+		 *  Enable the specified dma channels.
+		 */
+		uiCONTROL =
+		    readl(M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
+		uiCONTROL |= CONTROL_M2P_ENABLE;
+		writel(uiCONTROL,
+		       M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
+
+		/*
+		 *  Update the dma channel instance transfer state.
+		 */
+		dma_pointers[loop]->xfer_enable = TRUE;
+		dma_pointers[loop]->pause = FALSE;
+
+		if (dma_pointers[loop]->pause_buf.buf_id == -1) {
+			dma_pointers[loop]->new_buffers--;
+		}
+	}
+
+	/*
+	 *  Program up the BASE0 registers for all specified channels, this
+	 *  will initiate transfers on all specified channels.
+	 */
+	for (loop = 0; loop < channels; loop++) {
+		/*
+		 *  Check if we need to restore a paused transfer.
+		 */
+		if (dma_pointers[loop]->pause_buf.buf_id != -1) {
+			writel(dma_pointers[loop]->pause_buf.source,
+			       M2P_reg_bases[loop] + M2P_OFFSET_BASE0);
+
+			/*
+			 *  Set the pause buffer to NULL
+			 */
+			dma_pointers[loop]->pause_buf.buf_id = -1;
+			dma_pointers[loop]->pause_buf.size = 0;
+		} else {
+			writel(dma_pointers[loop]->
+			       buffer_queue[dma_pointers[loop]->current_buffer].
+			       source,
+			       M2P_reg_bases[loop] + M2P_OFFSET_BASE0);
+		}
+	}
+
+	/*
+	 *  Before restoring irqs setup the second MAXCNT/BASE
+	 *  register with a second buffer.
+	 */
+	for (loop = 0; loop < channels; loop++) {
+		if (dma_pointers[loop]->new_buffers) {
+			writel(dma_pointers[loop]->
+			       buffer_queue[(dma_pointers[loop]->
+					     current_buffer +
+					     1) % MAX_EP93XX_DMA_BUFFERS].size,
+			       M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT1);
+			writel(dma_pointers[loop]->
+			       buffer_queue[(dma_pointers[loop]->
+					     current_buffer +
+					     1) %
+					    MAX_EP93XX_DMA_BUFFERS].source,
+			       M2P_reg_bases[loop] + M2P_OFFSET_BASE1);
+		}
+	}
+
+/*
+    DPRINTK("DMA - It's been started!!");
+    DPRINTK("STATUS - 0x%x \n",     readl(M2P_reg_base+M2P_OFFSET_STATUS)));
+    DPRINTK("CONTROL - 0x%x \n",    readl(M2P_reg_base+M2P_OFFSET_CONTROL)));
+    DPRINTK("REMAIN - 0x%x \n",     readl(M2P_reg_base+M2P_OFFSET_REMAIN)));
+    DPRINTK("PPALLOC - 0x%x \n",    readl(M2P_reg_base+M2P_OFFSET_PPALLOC)));
+    DPRINTK("BASE0 - 0x%x \n",      readl(M2P_reg_base+M2P_OFFSET_BASE0)));
+    DPRINTK("MAXCNT0 - 0x%x \n",    readl(M2P_reg_base+M2P_OFFSET_MAXCNT0)));
+    DPRINTK("CURRENT0 - 0x%x \n",   readl(M2P_reg_base+M2P_OFFSET_CURRENT0)));
+    DPRINTK("BASE1 - 0x%x \n",      readl(M2P_reg_base+M2P_OFFSET_BASE1)));
+    DPRINTK("MAXCNT1 - 0x%x \n",    readl(M2P_reg_base+M2P_OFFSET_MAXCNT1)));
+    DPRINTK("CURRENT1 - 0x%x \n",   readl(M2P_reg_base+M2P_OFFSET_CURRENT1)));
+
+    DPRINTK("Pause - %d \n", dma_pointers[0]->pause);
+    DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable);
+    DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes);
+    DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers);
+    DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers);
+    DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer);
+    DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer);
+    DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers);
+*/
+	/*
+	 *  Unmask irqs
+	 */
+	local_irq_restore(flags);
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ *  int ep93xx_dma_add_buffer(int handle, unsigned int * address,
+ *                         unsigned int size, unsigned int last)
+ *
+ *  Description: Add a buffer entry to the DMA buffer queue.
+ *
+ *  handle:     handle for the channel to add this buffer to.
+ *  address:    Pointer to an integer which is the start address of the
+ *              buffer which is to be added to the queue.
+ *  size:       size of the buffer in bytes.
+ *  last:       1 if this is the last buffer in this stream, 0 otherwise.
+ *
+ ****************************************************************************/
+int
+ep93xx_dma_add_buffer(int handle, unsigned int source, unsigned int dest,
+		      unsigned int size, unsigned int last, unsigned int buf_id)
+{
+	unsigned long flags;
+	ep93xx_dma_t *dma;
+	int channel;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Add Buffer: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	/*
+	 *  Get a pointer to the dma instance.
+	 */
+	dma = &dma_chan[channel];
+
+	/*
+	 *  Mask interrupts and hold on to the original state.
+	 */
+	local_irq_save(flags);
+
+	/*
+	 *  If the buffer queue is full, last_buffer is the same as current_buffer and
+	 *  we're not tranfering, or last_buffer is pointing to a used buffer, then exit.
+	 *  TODO: do I need to do any more checks?
+	 */
+	if (dma->total_buffers >= MAX_EP93XX_DMA_BUFFERS) {
+		/*
+		 *  Restore the state of the irqs
+		 */
+		local_irq_restore(flags);
+
+		/*
+		 *  Fail.
+		 */
+		return (-1);
+	}
+
+	/*
+	 *  Add this buffer to the queue
+	 */
+	dma->buffer_queue[dma->last_buffer].source = source;
+	dma->buffer_queue[dma->last_buffer].dest = dest;
+	dma->buffer_queue[dma->last_buffer].size = size;
+	dma->buffer_queue[dma->last_buffer].last = last;
+	dma->buffer_queue[dma->last_buffer].buf_id = buf_id;
+
+	/*
+	 *  Reset the used field of the buffer structure.
+	 */
+	dma->buffer_queue[dma->last_buffer].used = FALSE;
+
+	/*
+	 *  Increment the End Item Pointer.
+	 */
+	dma->last_buffer = (dma->last_buffer + 1) % MAX_EP93XX_DMA_BUFFERS;
+
+	/*
+	 *  Increment the new buffers counter and the total buffers counter
+	 */
+	dma->new_buffers++;
+	dma->total_buffers++;
+
+	/*
+	 *  restore the interrupt state.
+	 */
+	local_irq_restore(flags);
+
+	/*
+	 *  Check if the channel was starved into a stopped state.
+	 */
+	if (dma->pause && dma->xfer_enable) {
+		if (dma->new_buffers >= 1) {
+			DPRINTK
+			    ("DMA - calling start from add after starve. \n");
+
+			/*
+			 *  The channel was starved into a stopped state, and we've got
+			 *  2 new buffers, so start tranferring again.
+			 */
+			ep93xx_dma_start(handle, 1, NULL);
+		}
+	}
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ *  int ep93xx_dma_remove_buffer(int handle, unsigned int * address,
+ *                                unsigned int * size)
+ *
+ *  Description: Remove a buffer entry from the DMA buffer queue. If
+ *               buffer was removed successfully, return 0, otherwise
+ *               return -1.
+ *
+ *  handle:     handle for the channel to remove a buffer from.
+ *  address:    Pointer to an integer which is filled in with the start
+ *              address of the removed buffer.
+ *  size:       Pointer to an integer which is filled in with the size in
+ *              bytes of the removed buffer.
+ *
+ ****************************************************************************/
+int ep93xx_dma_remove_buffer(int handle, unsigned int *buf_id)
+{
+	unsigned int test;
+	unsigned int loop;
+	int return_val = -1;
+	unsigned long flags;
+	ep93xx_dma_t *dma;
+	int channel;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Remove Buffer: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	dma = &dma_chan[channel];
+
+	/*
+	 *  Mask interrupts and hold on to the original state.
+	 */
+	local_irq_save(flags);
+
+	/*
+	 *  Make sure there are used buffers to be returned.
+	 */
+	if (dma->used_buffers) {
+		test = dma->last_buffer;
+
+		for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
+			if (dma->buffer_queue[test].used
+			    && (dma->buffer_queue[test].buf_id != -1)) {
+				/*DPRINTK("buffer %d used \n", test); */
+
+				/*
+				 *  This is a used buffer, fill in the buf_id pointer
+				 *  with the buf_id for this buffer.
+				 */
+				*buf_id = dma->buffer_queue[test].buf_id;
+
+				/*
+				 *  Reset this buffer structure
+				 */
+				dma->buffer_queue[test].buf_id = -1;
+
+				/*
+				 *  Decrement the used buffer counter, and the total buffer counter.
+				 */
+				dma->used_buffers--;
+				dma->total_buffers--;
+
+				/*
+				 *  Successful removal of a buffer, so set the return
+				 *  value to 0, then exit this loop.
+				 */
+				return_val = 0;
+				break;
+			}
+
+			/*
+			 *  This buffer isn't used, let's see if the next one is.
+			 */
+			test = (test + 1) % MAX_EP93XX_DMA_BUFFERS;
+		}
+	}
+
+	/*
+	 *  Restore interrupts.
+	 */
+	local_irq_restore(flags);
+
+	/*
+	 *  Success.
+	 */
+	return (return_val);
+}
+
+/*****************************************************************************
+ *
+ *  int ep93xx_dma_pause(int handle, unsigned int channels,
+ *                       unsigned int * handles)
+ *
+ *  Description: Disable any ongoing transfer for the given channel, retaining
+ *               the state of the current buffer transaction so that upon
+ *               resume, the dma will continue where it left off.
+ *
+ *  handle:     Handle for the channel to be paused.  If this is a pause for
+ *              for multiple channels, handle is a valid handle for one of
+ *              the channels to be paused.
+ *  channels:   number of channel to pause transfers on.
+ *  handles:    Pointer to an array of handles, one for each channel which
+ *              to be paused.  If this pause is intended only for one
+ *              channel, this field should be set to NULL.
+ *
+ ****************************************************************************/
+int ep93xx_dma_pause(int handle, unsigned int channels, unsigned int *handles)
+{
+	unsigned long flags;
+	ep93xx_dma_t *dma;
+	int channel;
+	unsigned int M2M_reg_base, M2P_reg_base;
+
+	DPRINTK("ep93xx_dma_pause \n");
+
+	/*
+	 *  Mask interrupts and hold on to the original state.
+	 */
+	local_irq_save(flags);
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		/*
+		 *  restore interrupts.
+		 */
+		local_irq_restore(flags);
+
+		printk(KERN_ERR "DMA Pause: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	DPRINTK("DMA %d: pause \n", channel);
+
+	/*
+	 *  Set up a pointer to the dma instance data.
+	 */
+	dma = &dma_chan[channel];
+
+	/*
+	 *  Set a pointer to the dma channel registers.
+	 */
+	if (channel < 10) {
+		M2P_reg_base = dma->reg_base;
+	} else {
+		M2M_reg_base = dma->reg_base;
+	}
+
+	/*
+	 *  Check if we're already paused.
+	 */
+	if (dma->pause) {
+		/*
+		 *  We're paused, but are we stopped?
+		 */
+		if (dma->xfer_enable) {
+			/*
+			 *  Put the channel in the stopped state.
+			 */
+			dma->xfer_enable = FALSE;
+		}
+
+		DPRINTK("DMA Pause - already paused.");
+	} else {
+		/*
+		 *  Put the channel into the stopped state.
+		 */
+		dma->xfer_enable = FALSE;
+		dma->pause = TRUE;
+	}
+
+	/*
+	 *  restore interrupts.
+	 */
+	local_irq_restore(flags);
+
+	/*
+	 *  Already paused, so exit.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ *  void ep93xx_dma_flush(int handle)
+ *
+ *  Description: Flushes all queued buffers and transfers in progress
+ *               for the given channel.  Return the buffer entries
+ *               to the calling function.
+ *
+ *  handle:     handle for the channel for which the flush is intended.
+ *
+ ****************************************************************************/
+int ep93xx_dma_flush(int handle)
+{
+	unsigned int loop;
+	unsigned long flags;
+	ep93xx_dma_t *dma;
+	int channel;
+	unsigned int M2P_reg_base;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Flush: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	DPRINTK("DMA %d: flush \n", channel);
+
+	/*
+	 *  Set up a pointer to the dma instance data for this channel
+	 */
+	dma = &dma_chan[channel];
+
+	/*
+	 *  Mask interrupts and hold on to the original state.
+	 */
+	local_irq_save(flags);
+
+	for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
+		dma->buffer_queue[loop].buf_id = -1;
+	}
+
+	/*
+	 *  Set the Current and Last item to zero.
+	 */
+	dma->current_buffer = 0;
+	dma->last_buffer = 0;
+
+	/*
+	 *  Reset the Buffer counters
+	 */
+	dma->used_buffers = 0;
+	dma->new_buffers = 0;
+	dma->total_buffers = 0;
+
+	/*
+	 *  reset the Total bytes counter.
+	 */
+	dma->total_bytes = 0;
+
+	M2P_reg_base = dma_chan[channel].reg_base;
+
+	/*
+	 *  restore interrupts.
+	 */
+	local_irq_restore(flags);
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ *  int ep93xx_dma_queue_full(int handle)
+ *
+ *  Description: Query to determine if the DMA queue of buffers for
+ *              a given channel is full.
+ *              0 = queue is full
+ *              1 = queue is not full
+ *
+ *  handle:     handle for the channel to query.
+ *
+ ****************************************************************************/
+int ep93xx_dma_queue_full(int handle)
+{
+	int list_full = 0;
+	unsigned long flags;
+	int channel;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Queue Full: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	DPRINTK("DMA %d: queue full \n", channel);
+
+	/*
+	 *  Mask interrupts and hold on to the original state.
+	 */
+	local_irq_save(flags);
+
+	/*
+	 *  If the last item is equal to the used item then
+	 *  the queue is full.
+	 */
+	if (dma_chan[channel].total_buffers < MAX_EP93XX_DMA_BUFFERS) {
+		list_full = FALSE;
+	} else {
+		list_full = TRUE;
+	}
+
+	/*
+	 *  restore interrupts.
+	 */
+	local_irq_restore(flags);
+
+	return (list_full);
+}
+
+
+/*****************************************************************************
+ *
+ *  int ep93xx_dma_get_position()
+ *
+ *  Description:  Takes two integer pointers and fills them with the start
+ *                and current address of the buffer currently transferring
+ *                on the specified DMA channel.
+ *
+ *  handle         handle for the channel to query.
+ *  *buf_id        buffer id for the current buffer transferring on the
+ *                 dma channel.
+ *  *total         total bytes transferred on the channel.  Only counts
+ *                 whole buffers transferred.
+ *  *current_frac  number of bytes transferred so far in the current buffer.
+ ****************************************************************************/
+int
+ep93xx_dma_get_position(int handle, unsigned int * buf_id,
+                        unsigned int * total, unsigned int * current_frac )
+{
+	int  channel;
+	ep93xx_dma_t * dma;
+	unsigned int buf_id1, total1, current_frac1, buf_id2, total2;
+	unsigned int Status, NextBuffer, StateIsBufNext, M2P_reg_base=0;
+	unsigned int pause1, pause2;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.  See if this is a
+	 *  valid handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n");
+		return(-EINVAL);
+	}
+
+	dma = &dma_chan[channel];
+
+	/*
+	 * If DMA moves to a new buffer in the middle of us grabbing the
+	 * buffer info, then do it over again.
+	 */
+	do{
+		buf_id1 = dma->buffer_queue[dma->current_buffer].buf_id;
+		total1  = dma->total_bytes;
+		pause1  = dma->pause;
+
+		if (channel < 10) {
+			/* M2P */
+			M2P_reg_base = dma->reg_base;
+
+			Status = inl(M2P_reg_base+M2P_OFFSET_STATUS);
+
+			NextBuffer = ((Status & STATUS_M2P_NEXTBUFFER) != 0);
+
+			StateIsBufNext = ((Status & STATUS_M2P_CURRENT_MASK) ==
+			                  STATUS_M2P_DMA_BUF_NEXT);
+
+			if( NextBuffer ^ StateIsBufNext )
+				current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT1) -
+				                inl(M2P_reg_base+M2P_OFFSET_BASE1);
+			else
+				current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT0) -
+				                inl(M2P_reg_base+M2P_OFFSET_BASE0);
+
+		} else {
+			/* M2M - TODO implement this for M2M */
+			current_frac1 = 0;
+		}
+
+		buf_id2 = dma->buffer_queue[dma->current_buffer].buf_id;
+		total2 = dma->total_bytes;
+		pause2  = dma->pause;
+
+	} while ( (buf_id1 != buf_id2) || (total1 != total2) || (pause1 != pause2) );
+
+	if (pause1)
+		current_frac1 = 0;
+
+	if (buf_id)
+		*buf_id = buf_id1;
+
+	if (total)
+		*total  = total1;
+
+	if (current_frac)
+		*current_frac = current_frac1;
+
+	/*
+	 *  Success.
+	 */
+	return(0);
+}
+
+/*  changed for AC97 port from Virgo 1-4-3 */
+#if 0
+/*****************************************************************************
+ *
+ *  int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
+                                unsigned int * total)
+ *
+ *  Description:    Takes two integer pointers and fills them with the start
+ *                  and current address of the buffer currently transferring
+ *                  on the specified DMA channel.
+ *
+ *  handle:         handle for the channel to query.
+ *  buf_id:         pointer which is filled in with the buffer id for the
+ *                  current buffer transferring on the dma channel.
+ *                  buffer being transferred.
+ *  total  :        pointer which is filled in with the total bytes
+ *                  transferred on the channel.
+ ****************************************************************************/
+int
+ep93xx_dma_get_position(int handle, unsigned int *buf_id, unsigned int *total)
+{
+	int channel;
+	ep93xx_dma_t *dma;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	dma = &dma_chan[channel];
+
+	/*
+	 *  TODO: should irqs be disabled here?
+	 */
+
+	*buf_id = dma->buffer_queue[dma->current_buffer].buf_id;
+
+	*total = dma->total_bytes;
+
+	DPRINTK("DMA buf_id %d, total %d\n", *buf_id, *total);
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+#endif
+
+
+
+/*****************************************************************************
+ *
+ *  int ep93xx_dma_get_total(int handle)
+ *
+ *  Description:    Returns the total number of bytes transferred on the
+ *                  specified channel since the channel was requested.
+ *
+ *  handle:     handle for the channel to query.
+ *
+ ****************************************************************************/
+int ep93xx_dma_get_total(int handle)
+{
+	int channel;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Get Total: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	DPRINTK("DMA %d: total: %d \n", channel, dma_chan[channel].total_bytes);
+
+	/*
+	 *  Return the total number of bytes transferred on this channel since
+	 *  it was requested.
+	 */
+	return (dma_chan[channel].total_bytes);
+}
+
+/*****************************************************************************
+ * ep93xx_dma_request
+ *
+ * Description: This function will allocate a DMA channel for a particular
+ * hardware peripheral.  Before initiating a transfer on the allocated
+ * channel, the channel must be set up and buffers have to queued up.
+ *
+ *  handle:     pointer to an integer which is filled in with a unique
+ *              handle for this instance of the dma interface.
+ *  device_id   string with the device name, primarily used by /proc.
+ *  device      hardware device ID for which the requested dma channel will
+ *              transfer data.
+ *
+ ****************************************************************************/
+int
+ep93xx_dma_request(int *handle, const char *device_id, ep93xx_dma_dev_t device)
+{
+	ep93xx_dma_t *dma = NULL;
+	int channel;
+	unsigned int error = 0;
+	unsigned int loop;
+	unsigned int M2P_reg_base;
+
+	/*
+	 *  Check if the device requesting a DMA channel is a valid device.
+	 */
+	if ((device >= UNDEF) || (device < 0)) {
+		/*
+		 *  Invalid device, so return an error.
+		 */
+		return (-ENODEV);
+	}
+
+	/*
+	 *  We've got a valid hardware device requesting a DMA channel.
+	 *  Now check if the device should open an M2P or M2M channel
+	 */
+	if (device < 20) {
+		channel = dma_open_m2p(device);
+	} else {
+		channel = dma_open_m2m(device);
+	}
+
+	/*
+	 *  Check if we successfully opened a DMA channel
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR
+		       "%s: Could not open dma channel for this device.\n",
+		       device_id);
+
+		/*
+		 *  Fail.
+		 */
+		return (-EBUSY);
+	}
+
+	dma = &dma_chan[channel];
+
+	/*
+	 *  Request the appropriate IRQ for the specified channel
+	 */
+	if (channel < 10) {
+		error = request_irq(dma->irq, dma_m2p_irq_handler, SA_INTERRUPT,
+				    device_id, (void *)dma);
+	} else {
+		error =
+		    request_irq(dma->irq, &dma_m2m_irq_handler, SA_INTERRUPT,
+				device_id, (void *)dma);
+	}
+
+	/*
+	 *  Check for any errors during the irq request
+	 */
+	if (error) {
+		printk(KERN_ERR
+		       "%s: unable to request IRQ %d for DMA channel\n",
+		       device_id, dma->irq);
+		/*
+		 *  Fail.
+		 */
+		return (error);
+	}
+
+	/*
+	 *  Generate a valid handle and exit.
+	 *
+	 *  Increment the last valid handle.
+	 *  Check for wraparound (unlikely, but we like to be complete).
+	 */
+	dma->last_valid_handle++;
+
+	if ((dma->last_valid_handle & DMA_HANDLE_SPECIFIER_MASK) !=
+	    (channel << 28)) {
+		/*
+		 *  If we wrapped around start over.
+		 */
+		dma->last_valid_handle = (channel << 28) + 1;
+	}
+
+	/*
+	 *  Fill in the handle pointer with a valid handle for
+	 *  this dma channel instance.
+	 */
+	*handle = dma->last_valid_handle;
+
+	DPRINTK("Handle for channel %d: 0x%x\n", channel, *handle);
+
+	/*
+	 * Save the device ID and device name.
+	 */
+	dma->device = device;
+	dma->device_id = device_id;
+
+	/*
+	 *  Init all fields within the dma instance.
+	 */
+	for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
+		dma->buffer_queue[loop].buf_id = -1;
+	}
+
+	/*
+	 *  Initialize all buffer queue variables.
+	 */
+	dma->current_buffer = 0;
+	dma->last_buffer = 0;
+
+	dma->new_buffers = 0;
+	dma->used_buffers = 0;
+	dma->total_buffers = 0;
+
+	/*
+	 *  Initialize the total bytes variable
+	 */
+	dma->total_bytes = 0;
+
+	/*
+	 *  Initialize the transfer and pause state variables to 0.
+	 */
+	dma->xfer_enable = 0;
+
+	dma->pause = 0;
+
+	/*
+	 *  Initialize the pause buffer structure.
+	 */
+	dma->pause_buf.buf_id = -1;
+
+	/*
+	 *  Initialize the callback function and user data fields.
+	 */
+	dma->callback = NULL;
+
+	/*
+	 * User data used as a parameter for the Callback function.  The user
+	 * sets up the data and sends it with the callback function.
+	 */
+	dma->user_data = 0;
+
+	M2P_reg_base = dma_chan[channel].reg_base;
+
+	/*
+	 *  Debugging message.
+	 */
+	DPRINTK("Successfully requested dma channel %d\n", channel);
+	DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
+	DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
+	DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
+	DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
+	DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
+	DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
+	DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
+	DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
+	DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
+	DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
+
+	DPRINTK("Buffer    source       size       last       used \n");
+	for (loop = 0; loop < 5; loop++) {
+		DPRINTK("%d        0x%x         0x%x        %d         %d \n",
+			loop, dma->buffer_queue[loop].source,
+			dma->buffer_queue[loop].size,
+			dma->buffer_queue[loop].last,
+			dma->buffer_queue[loop].used);
+	}
+	DPRINTK("pause     0x%x         0x%x        %d         %d \n",
+		dma->pause_buf.source, dma->pause_buf.size,
+		dma->pause_buf.last, dma->pause_buf.used);
+
+	DPRINTK("Pause - %d \n", dma->pause);
+	DPRINTK("xfer_enable - %d \n", dma->xfer_enable);
+	DPRINTK("total bytes - 0x%x \n", dma->total_bytes);
+	DPRINTK("total buffer - %d \n", dma->total_buffers);
+	DPRINTK("new buffers - %d \n", dma->new_buffers);
+	DPRINTK("current buffer - %d \n", dma->current_buffer);
+	DPRINTK("last buffer - %d \n", dma->last_buffer);
+	DPRINTK("used buffers - %d \n", dma->used_buffers);
+
+	DPRINTK("CURRENT1 - 0x%x \n",
+		readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
+	DPRINTK("VIC0IRQSTATUS - 0x%x, VIC0INTENABLE - 0x%x \n",
+		*(unsigned int *)(VIC0IRQSTATUS),
+		*(unsigned int *)(VIC0INTENABLE));
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_dma_free
+ *
+ * Description: This function will free the dma channel for future requests.
+ *
+ *  handle:     handle for the channel to be freed.
+ *
+ ****************************************************************************/
+int ep93xx_dma_free(int handle)
+{
+	ep93xx_dma_t *dma;
+	unsigned int M2M_reg_base, M2P_reg_base, uiCONTROL;
+	int channel;
+
+	/*
+	 *  Get the DMA hw channel # from the handle.
+	 */
+	channel = dma_get_channel_from_handle(handle);
+
+	/*
+	 *  See if this is a valid handle.
+	 */
+	if (channel < 0) {
+		printk(KERN_ERR "DMA Free: Invalid dma handle.\n");
+
+		/*
+		 *  Fail.
+		 */
+		return (-EINVAL);
+	}
+
+	/*
+	 *  Get a pointer to the dma instance.
+	 */
+	dma = &dma_chan[channel];
+
+	/*
+	 *  Disable the dma channel
+	 */
+	if (channel < 10) {
+		/*
+		 *  M2P channel
+		 */
+		M2P_reg_base = dma->reg_base;
+
+		uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
+		uiCONTROL &= ~CONTROL_M2P_ENABLE;
+		writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
+	} else {
+		/*
+		 *  M2M channel
+		 */
+		M2M_reg_base = dma->reg_base;
+
+		uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
+		uiCONTROL &= ~CONTROL_M2M_ENABLE;
+		writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
+	}
+
+	/*
+	 *  Free the interrupt servicing this dma channel
+	 */
+	free_irq(dma->irq, (void *)dma);
+
+	/*
+	 *  Decrement the reference count for this instance of the dma interface
+	 */
+	dma->ref_count--;
+
+	/*
+	 *  Set the transfer and pause state variables to 0
+	 *  (unititialized state).
+	 */
+	dma->xfer_enable = 0;
+	dma->pause = 0;
+
+	/*
+	 *  Debugging message.
+	 */
+	DPRINTK("Successfully freed dma channel %d\n", channel);
+
+	/*
+	 *  Success.
+	 */
+	return (0);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_dma_init(void)
+ *
+ * Description: This function is called during system initialization to
+ * setup the interrupt number and register set base address for each DMA
+ * channel.
+ *
+ ****************************************************************************/
+static int __init ep93xx_dma_init(void)
+{
+	int channel;
+
+	/*
+	 * Init some values in each dma instance.
+	 */
+	for (channel = 0; channel < MAX_EP93XX_DMA_CHANNELS; channel++) {
+		/*
+		 *  IRQ for the specified dma channel.
+		 */
+		dma_chan[channel].irq = IRQ_DMAM2P0 + channel;
+
+		/*
+		 *  Initial value of the dma channel handle.
+		 */
+		dma_chan[channel].last_valid_handle = channel << 28;
+
+		/*
+		 *  Give the instance a pointer to the dma channel register
+		 *  base.
+		 */
+		if (channel < 10) {
+			dma_chan[channel].reg_base = DMAM2PChannelBase[channel];
+		} else {
+			dma_chan[channel].reg_base =
+			    DMAM2MChannelBase[channel - 10];
+		}
+
+		/*
+		 *  Initialize the reference count for this channel.
+		 */
+		dma_chan[channel].ref_count = 0;
+	}
+
+	DPRINTK("DMA Interface intitialization complete\n");
+
+	/*
+	 * Success
+	 */
+	return 0;
+}
+
+__initcall(ep93xx_dma_init);
+
+EXPORT_SYMBOL(ep93xx_dma_add_buffer);
+EXPORT_SYMBOL(ep93xx_dma_config);
+EXPORT_SYMBOL(ep93xx_dma_flush);
+EXPORT_SYMBOL(ep93xx_dma_free);
+EXPORT_SYMBOL(ep93xx_dma_get_position);
+EXPORT_SYMBOL(ep93xx_dma_get_total);
+EXPORT_SYMBOL(ep93xx_dma_init);
+EXPORT_SYMBOL(ep93xx_dma_pause);
+EXPORT_SYMBOL(ep93xx_dma_queue_full);
+EXPORT_SYMBOL(ep93xx_dma_remove_buffer);
+EXPORT_SYMBOL(ep93xx_dma_request);
+EXPORT_SYMBOL(ep93xx_dma_start);
+
diff --git a/arch/arm/mach-ep93xx/dma_ep93xx.h b/arch/arm/mach-ep93xx/dma_ep93xx.h
new file mode 100644
index 0000000..3ec0b0d
--- /dev/null
+++ b/arch/arm/mach-ep93xx/dma_ep93xx.h
@@ -0,0 +1,194 @@
+/*****************************************************************************
+ *
+ * arch/arm/mach-ep93xx/dma_ep93xx.h
+ *
+ * DESCRIPTION:    93XX DMA controller API private defintions.
+ *
+ * Copyright Cirrus Logic Corporation, 2003.  All rights reserved
+ *
+ * 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
+ *
+ ****************************************************************************/
+#ifndef _EP93XX_DMA_H_
+#define _EP93XX_DMA_H_
+
+#define MAX_EP93XX_DMA_BUFFERS      32
+
+#ifndef TRUE
+#define TRUE                        1
+#endif
+
+#ifndef FALSE
+#define FALSE                       0
+#endif
+
+#ifndef NULL
+#define NULL                        0
+#endif
+
+/*****************************************************************************
+ *
+ * DMA buffer structure type.
+ *
+ ****************************************************************************/
+typedef struct ep93xx_dma_buffer_s {
+	unsigned int source;	/* buffer physical source address.          */
+	unsigned int dest;	/* buffer physical destination address,     */
+	/* only used with the 2 M2M channels.       */
+	unsigned int size;	/* buffer size in bytes                     */
+	unsigned int last;	/* 1 if this is the last buffer             */
+	/* in this transaction.  If 1,              */
+	/* disable the NFBint so we aren't          */
+	/* interrupted for another buffer           */
+	/* when we know there won't be another.     */
+	unsigned int used;	/* This field is set to 1 by the DMA        */
+	/* interface after the buffer is transferred */
+	int buf_id;		/* unique identifyer specified by the       */
+	/* the driver which requested the dma       */
+} ep93xx_dma_buffer_t;
+
+typedef ep93xx_dma_buffer_t *ep93xx_dma_buffer_p;
+
+/*****************************************************************************
+ *
+ * Instance definition for the DMA interface.
+ *
+ ****************************************************************************/
+typedef struct ep7312_dma_s {
+	/*
+	 *  This 1 when the instance is in use, and 0 when it's not.
+	 */
+	unsigned int ref_count;
+
+	/*
+	 * This is the last valid handle for this instance.  When giving out a
+	 * new handle this will be incremented and given out.
+	 */
+	int last_valid_handle;
+
+	/*
+	 * device specifies one of the 20 DMA hardware ports this
+	 * DMA channel will service.
+	 */
+	ep93xx_dma_dev_t device;
+
+	/*
+	 * DMABufferQueue is the queue of buffer structure pointers which the
+	 * dma channel will use to setup transfers.
+	 */
+	ep93xx_dma_buffer_t buffer_queue[MAX_EP93XX_DMA_BUFFERS];
+
+	/*
+	 * currnt_buffer : This is the buffer currently being transfered on
+	 *                 this channel.
+	 * last_buffer : This is the last buffer for this transfer.
+	 * Note: current_buffer + 1 is already programmed into the dma
+	 *       channel as the next buffer to transfer. Don't write
+	 *       over either entry.
+	 */
+	int current_buffer;
+	int last_buffer;
+
+	/*
+	 * The following 3 fields are buffer counters.
+	 *
+	 * iNewBuffers: Buffers in the queue which have not been transfered.
+	 * iUsedBuffers: Buffers in the queue which have have been tranferred,
+	 *               and are waiting to be returned.
+	 * iTotalBuffers: Total number of buffers in the queue.
+	 */
+	int new_buffers;
+	int used_buffers;
+	int total_buffers;
+
+	/*
+	 * uiTotalBytes has the total bytes transfered on the channel since the
+	 * last flush.  This value does not include the bytes tranfered in the
+	 * current buffer.  A byte count is only added after a complete buffer
+	 * is tranfered.
+	 */
+	unsigned int total_bytes;
+
+	/*
+	 *  Interrupt number for this channel
+	 */
+	unsigned int irq;
+
+	/*
+	 * Indicates whether or not the channel is currently enabled to transfer
+	 * data.
+	 */
+	unsigned int xfer_enable;
+
+	/*
+	 * pause indicates if the dma channel was paused by calling the pause
+	 * ioctl.
+	 */
+	unsigned int pause;
+
+	/*
+	 *  buffer structure used during a pause to capture the current
+	 *  address and remaining bytes for the buffer actively being transferred
+	 *  on the channel. This buffer will be used to reprogram the dma
+	 *  channel upon a resume.
+	 */
+	ep93xx_dma_buffer_t pause_buf;
+
+	/*
+	 * DMACallback is a function pointer which the calling application can
+	 * use install a function to.  this fuction can be used to notify the
+	 * calling application of an interrupt.
+	 */
+	dma_callback callback;
+
+	/*
+	 * User data used as a parameter for the Callback function.  The user
+	 * sets up the data and sends it with the callback function.
+	 */
+	unsigned int user_data;
+
+	/*
+	 * A string representation of the device attached to the channel.
+	 */
+	const char *device_id;
+
+	/*
+	 * The register base address for this dma channel.
+	 */
+	unsigned int reg_base;
+
+} ep93xx_dma_t;
+
+/*****************************************************************************
+ *
+ * DMA macros
+ *
+ ****************************************************************************/
+#define DMA_HANDLE_SPECIFIER_MASK   0xF0000000
+#define DMA_CH0_HANDLE_SPECIFIER    0x00000000
+#define DMA_CH1_HANDLE_SPECIFIER    0x10000000
+#define DMA_CH2_HANDLE_SPECIFIER    0x20000000
+#define DMA_CH3_HANDLE_SPECIFIER    0x30000000
+#define DMA_CH4_HANDLE_SPECIFIER    0x40000000
+#define DMA_CH5_HANDLE_SPECIFIER    0x50000000
+#define DMA_CH6_HANDLE_SPECIFIER    0x60000000
+#define DMA_CH7_HANDLE_SPECIFIER    0x70000000
+#define DMA_CH8_HANDLE_SPECIFIER    0x80000000
+#define DMA_CH9_HANDLE_SPECIFIER    0x90000000
+#define DMA_CH10_HANDLE_SPECIFIER   0xA0000000
+#define DMA_CH11_HANDLE_SPECIFIER   0xB0000000
+
+#endif
+
diff --git a/arch/arm/mach-ep93xx/ep93xx.c b/arch/arm/mach-ep93xx/ep93xx.c
new file mode 100644
index 0000000..a565f14
--- /dev/null
+++ b/arch/arm/mach-ep93xx/ep93xx.c
@@ -0,0 +1,571 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/ep93xx.c
+ *
+ *  Copyright (C) 2000-2003 Deep Blue Solutions Ltd
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *  Copyright (C) 2005 Michael Burian
+ *
+ * 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/device.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/hardware/amba.h>
+#include <asm/mach/time.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+
+static __init void check_model(void)
+{
+	unsigned long x;
+	char *model;
+	char *rev;
+
+	printk(KERN_INFO "CPU model: ");
+
+	x = readl(USRFLG);
+	switch (x) {
+	case 0:
+		model = "15";
+		break;
+	case 2:
+		model = "12";
+		break;
+	case 4:
+		model = "01";
+		break;
+	default:
+		printk("(unknown model %ld) ", x);
+		model = "xx";
+		break;
+	}
+
+	x = readl(SYSCON_SYSCFG) >> 28;
+	switch (x) {
+	case 0:
+		rev = "A";
+		break;
+	case 1:
+		rev = "B";
+		break;
+	case 2:
+		rev = "C";
+		break;
+	case 3:
+		rev = "D0";
+		break;
+	case 4:
+		rev = "D1";
+		break;
+	case 5:
+		rev = "E";
+		break;
+	default:
+		printk("(unknown revision %ld) ", x);
+		rev = "unknown";
+		break;
+	}
+
+	printk("Cirrus Logic EP93%s, silicon rev %s\n", model, rev);
+}
+
+static struct amba_device dma_device = {
+	.dev = {
+		.bus_id = "0x80000000:dma",
+		},
+	.res = {
+		.start = DMA_BASE,
+		.end = DMA_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80000000,
+};
+
+static struct amba_device mac_device = {
+	.dev = {
+		.bus_id = "0x80010000:mac",
+		},
+	.res = {
+		.start = MAC_BASE,
+		.end = MAC_BASE + SZ_64K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80010000,
+};
+
+static struct amba_device usb_device = {
+	.dev = {
+		.bus_id = "0x80020000:usb",
+		.coherent_dma_mask = 0xffffffff,
+		},
+	.res = {
+		.start = USB_BASE,
+		.end = USB_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_USH, NO_IRQ},
+	.periphid = 0x80020000,
+};
+
+#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
+static struct amba_device raster_device = {
+	.dev = {
+		.bus_id = "0x80030000:raster",
+		},
+	.res = {
+		.start = RASTER_BASE,
+		.end = RASTER_BASE + SZ_8K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80030000,
+};
+#endif
+
+static struct amba_device sdram_device = {
+	.dev = {
+		.bus_id = "0x80060000:sdram",
+		},
+	.res = {
+		.start = SDRAM_BASE,
+		.end = SDRAM_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80060000,
+};
+
+static struct amba_device smc_device = {
+	.dev = {
+		.bus_id = "0x80080000:smc",
+		},
+	.res = {
+		.start = SMC_BASE,
+		.end = SMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80080000,
+};
+
+static struct amba_device boot_device = {
+	.dev = {
+		.bus_id = "0x80090000:boot",
+		},
+	.res = {
+		.start = BOOT_BASE,
+		.end = BOOT_BASE + SZ_16K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80090000,
+};
+
+#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
+static struct amba_device ide_device = {
+	.dev = {
+		.bus_id = "0x800a0000:ide",
+		},
+	.res = {
+		.start = IDE_BASE,
+		.end = IDE_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x800a0000,
+};
+#endif
+
+static struct amba_device vic1_device = {
+	.dev = {
+		.bus_id = "0x800b0000:vic1",
+		},
+	.res = {
+		.start = VIC0_BASE,
+		.end = VIC0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x800b0000,
+};
+
+static struct amba_device vic2_device = {
+	.dev = {
+		.bus_id = "0x800c0000:vic2",
+		},
+	.res = {
+		.start = VIC1_BASE,
+		.end = VIC1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x800c0000,
+};
+
+static struct amba_device timer_device = {
+	.dev = {
+		.bus_id = "0x80810000:timer",
+		},
+	.res = {
+		.start = TIMERS_BASE,
+		.end = TIMERS_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80810000,
+};
+
+static struct amba_device i2s_device = {
+	.dev = {
+		.bus_id = "0x80820000:i2s",
+		},
+	.res = {
+		.start = I2S_BASE,
+		.end = I2S_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80820000,
+};
+
+static struct amba_device security_device = {
+	.dev = {
+		.bus_id = "0x80830000:security",
+		},
+	.res = {
+		.start = SECURITY_BASE,
+		.end = SECURITY_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80830000,
+};
+
+static struct amba_device gpio_device = {
+	.dev = {
+		.bus_id = "0x80840000:gpio",
+		},
+	.res = {
+		.start = GPIO_BASE,
+		.end = GPIO_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80840000,
+};
+
+static struct amba_device ac97_device = {
+	.dev = {
+		.bus_id = "0x80880000:ac97",
+		},
+	.res = {
+		.start = AC97_BASE,
+		.end = AC97_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80880000,
+};
+
+static struct amba_device ssp_device = {
+	.dev = {
+		.bus_id = "0x808a0000:ssp",
+		},
+	.res = {
+		.start = SSP_BASE,
+		.end = SSP_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x808a0000,
+};
+
+static struct amba_device irda_device = {
+	.dev = {
+		.bus_id = "0x808b0000:irda",
+		},
+	.res = {
+		.start = IRDA_BASE,
+		.end = IRDA_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x808b0000,
+};
+
+static struct amba_device uart1_device = {
+	.dev = {
+		.bus_id = "0x808c0000:uart1",
+		},
+	.res = {
+		.start = UART1_BASE,
+		.end = UART1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_UART1, NO_IRQ},
+	.periphid = 0x808c0000,
+};
+
+static struct amba_device uart2_device = {
+	.dev = {
+		.bus_id = "0x808d0000:uart2",
+		},
+	.res = {
+		.start = UART2_BASE,
+		.end = UART2_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_UART2, NO_IRQ},
+	.periphid = 0x808d0000,
+};
+
+#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
+static struct amba_device uart3_device = {
+	.dev = {
+		.bus_id = "0x808e0000:uart3",
+		},
+	.res = {
+		.start = UART3_BASE,
+		.end = UART3_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_UART3, NO_IRQ},
+	.periphid = 0x808e0000,
+};
+
+static struct amba_device key_device = {
+	.dev = {
+		.bus_id = "0x808f0000:key",
+		},
+	.res = {
+		.start = KEY_BASE,
+		.end = KEY_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x808f0000,
+};
+
+static struct amba_device touch_device = {
+	.dev = {
+		.bus_id = "0x80900000:touch",
+		},
+	.res = {
+		.start = TOUCH_BASE,
+		.end = TOUCH_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80900000,
+};
+
+static struct amba_device pwm_device = {
+	.dev = {
+		.bus_id = "0x80910000:pwm",
+		},
+	.res = {
+		.start = PWM_BASE,
+		.end = PWM_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80910000,
+};
+#endif
+
+static struct amba_device rtc_device = {
+	.dev = {
+		.bus_id = "0x80920000:rtc",
+		},
+	.res = {
+		.start = RTC_BASE,
+		.end = RTC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_RTC, NO_IRQ},
+	.periphid = 0x80920000,
+};
+
+static struct amba_device syscon_device = {
+	.dev = {
+		.bus_id = "0x80930000:syscon",
+		},
+	.res = {
+		.start = SYSCON_BASE,
+		.end = SYSCON_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80930000,
+};
+
+static struct amba_device watchdog_device = {
+	.dev = {
+		.bus_id = "0x80940000:watchdog",
+		},
+	.res = {
+		.start = WATCHDOG_BASE,
+		.end = WATCHDOG_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {NO_IRQ, NO_IRQ},
+	.periphid = 0x80940000,
+};
+
+static struct amba_device *amba_devs[] __initdata = {
+	/* AHB devices */
+	&dma_device,
+	&mac_device,
+	&usb_device,
+#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
+	&raster_device,
+#endif
+	&sdram_device,
+	&smc_device,
+	&boot_device,
+#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
+	&ide_device,
+#endif
+	&vic1_device,
+	&vic2_device,
+
+	/* APB devices */
+	&timer_device,
+	&i2s_device,
+	&security_device,
+	&gpio_device,
+	&ac97_device,
+	&ssp_device,
+	&irda_device,
+	&uart1_device,
+	&uart2_device,
+#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
+	&uart3_device,
+	&key_device,
+	&touch_device,
+	&pwm_device,
+#endif
+	&rtc_device,
+	&syscon_device,
+	&watchdog_device,
+};
+
+static int __init ep93xx_init(void)
+{
+	int i;
+
+	check_model();
+
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		amba_device_register(d, &iomem_resource);
+	}
+
+	return 0;
+}
+
+arch_initcall(ep93xx_init);
+
+#define TIMER_INTERVAL	(508 * mSEC_10 / 1000)
+#define TICKS2USECS(x)	((x) * 1000 / 508)
+
+static unsigned long timer_reload;
+
+/*
+ * Returns number of ms since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long ep93xx_gettimeoffset(void)
+{
+	unsigned long ticks1, ticks2, status;
+
+	/*
+	 * Get the current number of ticks.  Note that there is a race
+	 * condition between us reading the timer and checking for
+	 * an interrupt.  We get around this by ensuring that the
+	 * counter has not reloaded between our two reads.
+	 */
+	ticks2 = readl(TIMER1VALUE) & 0xffff;
+	do {
+		ticks1 = ticks2;
+		status = readl(VIC0RAWINTR);
+		ticks2 = readl(TIMER1VALUE) & 0xffff;
+	} while (ticks2 > ticks1);
+
+	/*
+	 * Number of ticks since last interrupt.
+	 */
+	ticks1 = timer_reload - ticks2;
+
+	/*
+	 * Interrupt pending?  If so, we've reloaded once already.
+	 */
+	if (status & (1 << IRQ_TIMER1))
+		ticks1 += timer_reload;
+
+	return TICKS2USECS(ticks1);
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* ...clear the interrupt */
+	writel(1, TIMER1CLEAR);
+
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction ep93xx_timer_irq = {
+	.name = "timer",
+	.flags = SA_INTERRUPT,
+	.handler = ep93xx_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt
+ */
+static void __init __ep93xx_init_timer(unsigned long reload, unsigned int ctrl)
+{
+	unsigned int timer_ctrl = 0x80 | 0x40 | 0x08;	/* periodic at 508 kHz */
+
+	timer_reload = reload;
+	timer_ctrl |= ctrl;
+
+	/*
+	 * Initialise to a known state (all timers off)
+	 */
+
+	writel(0, TIMER1CONTROL);
+	writel(0, TIMER2CONTROL);
+	writel(0, TIMER3CONTROL);
+
+	writel(timer_reload, TIMER1LOAD);
+	writel(timer_reload, TIMER1VALUE);
+	writel(timer_ctrl, TIMER1CONTROL);
+
+	setup_irq(IRQ_TIMER1, &ep93xx_timer_irq);
+}
+
+static void __init ep93xx_init_timer(void)
+{
+	/* 10 ms interval on a 508 kHz clock */
+	__ep93xx_init_timer(5080, 0);
+}
+
+struct sys_timer ep93xx_timer = {
+	.init = ep93xx_init_timer,
+	.offset = ep93xx_gettimeoffset,
+};
diff --git a/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h b/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
new file mode 100644
index 0000000..d396e96
--- /dev/null
+++ b/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
@@ -0,0 +1,41 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
+ *
+ *  Copyright (C) 2004 Contec Steuerungstechnik & Automation GmbH
+ *	               Manfred Gruber <manfred.gruber@contec.at>
+ *
+ * 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
+ */
+
+/*
+ * configuration struct for GPIO IRQs
+ *
+ * enable = 1 --> this EGIO is a irq
+ * enable = 0 --> this EGIO is a GPIO
+ * flags can be		IRQT_RISING
+ *			IRQT_FALLING
+ *			IRQT_LOW
+ *			IRQT_HIGH
+ *			IRQT_PROBE
+ *
+ * On IRQT_PROBE nothing is done in setup irq code
+ */
+
+struct ep93xx_egpio_irq
+{
+	unsigned int enable;
+	unsigned int flags;
+};
+
diff --git a/arch/arm/mach-ep93xx/irq.c b/arch/arm/mach-ep93xx/irq.c
new file mode 100644
index 0000000..578c783
--- /dev/null
+++ b/arch/arm/mach-ep93xx/irq.c
@@ -0,0 +1,601 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/irq.c
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA.  All rights reserved.
+ *
+ *  Copyright (C) 2002-2003 Cirrus Logic, Inc.
+ *
+ * Demux IRQ 59 by
+ * Copyright (C) 2004 Contec Steuerungstechnik & Automation GmbH
+ *	               Manfred Gruber <manfred.gruber@contec.at>
+ *
+ * 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
+ *
+ *
+ * Modified by Stefano Lena <stefano.lena@dave-tech.it>, DAVE s.r.l.
+ * for Cirrus Logic EP93xx series
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+
+#include <asm/arch/irqs.h>
+
+#include <asm/mach/irq.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+#include <asm/arch/regmap.h>
+#include <linux/errno.h>
+#include "ep93xx_gpio_irq.h"
+extern struct ep93xx_egpio_irq egpio_irqs[];
+
+/* GPIO Port A/B debug messages */
+/* #define DEBUG_GPIO */
+#ifdef DEBUG_GPIO
+#define IRQDBG(args...) printk(args)
+#else
+#define IRQDBG(args...) do {} while(0)
+#endif
+#endif
+/********************************************************************
+ *	Interrupt functions are defined as machine specific here.
+ *
+ *	Note:
+ *		1.  Only normal interrupts are defined here.
+ *		FIQs are a separate class of interrupts and would
+ *		be slowed down if handled like normal interrupts.
+ *
+ *		2.  TBD Invalid interrupt numbers are not checked.
+ *		Some interrupt inputs are tied to GND, which means
+ *		they will immediately activate when unmasked.
+ *		Which may be useful for some devices.
+ *
+ *		3.  TBD Edge triggered interrupts are not specially
+ *		handled.  The architecture should provide a way to
+ *		set up the edge trigger features and then a way to
+ *		control the acknowledge to the interrupt.
+ *
+ ************************************************************************/
+
+ /********************************************************************
+ *	demux interrupt handler for GPIO Port A and B on ep93xx
+ *
+ *	Note:
+	That IRQs from 64 to 79 defined as GPIO_IRQ0 - GPIO_IRQ15
+ *	GPIO IRQs on port F are as the are defined as IRQ_GPIOX
+ *	which are NOT handled in demux interrupt handler !!!!!
+ *
+ *	Default in mach-xy file a struct ep93xx_egpio_irq
+ *	can be set up, there you can configure which gpio
+ *	of Port A/B should be used as interrupt on startup.
+ *	Setting up this IRQs in your driver direct not on startup
+ *	you have to do a set_irq_type(GPIO_IRQX, flags) before
+ *	calling request irq. Possible Flags are:
+ *	IRQT_RISING, IRQT_FALLING, IRQT_LOW, IRQT_HIGH, IRQT_PROBE, IRQ_DB, IRQ_NOTDB
+ * 	On IRQT_PROBE nothing is done.
+ ************************************************************************/
+
+ /********************************************************************
+ *	TODO:
+ *
+ *	Configure ack, mask, unsmask to use the right
+ *	Port F GPIO registers.
+ *
+************************************************************************/
+
+static void ep93xx_vic1_mask(unsigned int irq)
+{
+	writel((1 << irq), VIC0INTENCLEAR);
+}
+
+static void ep93xx_vic1_unmask(unsigned int irq)
+{
+	writel((1 << irq), VIC0INTENABLE);
+}
+
+static struct irqchip vic1_chip = {
+	.ack = ep93xx_vic1_mask,
+	.mask = ep93xx_vic1_mask,
+	.unmask = ep93xx_vic1_unmask,
+};
+
+static void ep93xx_vic2_mask(unsigned int irq)
+{
+	writel((1 << (irq - 32)), VIC1INTENCLEAR);
+}
+
+static void ep93xx_vic2_unmask(unsigned int irq)
+{
+	writel((1 << (irq - 32)), VIC1INTENABLE);
+}
+
+static struct irqchip vic2_chip = {
+	.ack = ep93xx_vic2_mask,
+	.mask = ep93xx_vic2_mask,
+	.unmask = ep93xx_vic2_unmask,
+};
+
+static void ep93xx_rtc_ack(unsigned int irq)
+{
+}
+
+static struct irqchip rtc_chip = {
+	.ack = ep93xx_rtc_ack,
+	.mask = ep93xx_vic2_mask,
+	.unmask = ep93xx_vic2_unmask,
+};
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+/*
+ * ack EGPIO irq's
+ * Ack only for edge triggered int's valid
+ */
+static void inline ep93xx_ack_gpio_irq(u32 irq)
+{
+	u32 irq_status;
+	u32 bit = IRQ_TO_BIT(irq);
+
+	IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
+
+	/* Port A */
+	if(bit & 0xFF) {
+		irq_status = readl(GPIO_INTSTATUSA);
+		if(irq_status & bit)
+			writel(bit, GPIO_AEOI);
+	}
+
+	/* Port B */
+	if(bit & 0xFF00) {
+		irq_status = readl(GPIO_INTSTATUSB);
+		if(irq_status & (bit >> 8))
+			writel((bit >> 8), GPIO_BEOI);
+
+	}
+}
+
+/*
+ * unmask EGPIO irq's (enable)
+ */
+static void inline ep93xx_unmask_gpio_irq(u32 irq)
+{
+	u32 irq_status;
+	u32 bit = IRQ_TO_BIT(irq);
+
+	IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
+
+	/* Port A */
+	if(bit & 0xFF) {
+		irq_status = readl(GPIO_AINTEN);
+		irq_status |=  bit;
+		writel(irq_status, GPIO_AINTEN);
+	}
+
+	/* Port B */
+	if(bit & 0xFF00) {
+		irq_status = readl(GPIO_BINTEN);
+		irq_status |= (bit >> 8);
+		writel(irq_status, GPIO_BINTEN);
+	}
+}
+
+/*
+ * Enable debounce on EGPIO IRQ
+ */
+
+static void ep93xx_debounce_enable(u32 irq)
+{
+	u32 db_status;
+	u32 bit = IRQ_TO_BIT(irq);
+
+	IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
+
+	/* Port A */
+	if (bit & 0xFF) {
+		db_status = readl(GPIO_ADB);
+		db_status |= bit ;
+		writel(db_status, GPIO_ADB);
+	}
+
+	/* Port B */
+	if (bit & 0xFF00 ) {
+			db_status = readl(GPIO_BDB);
+			db_status |= (bit >> 8) ;
+			writel(db_status, GPIO_BDB);
+	}
+
+}
+
+/*
+ * Disable debounce on EGPIO IRQ
+ */
+static void ep93xx_debounce_disable(u32 irq)
+{
+	u32 db_status;
+	u32 bit = IRQ_TO_BIT(irq);
+
+	IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
+
+	/* Port A */
+	if (bit & 0xFF) {
+		db_status = readl(GPIO_ADB);
+		db_status &= ~bit ;
+		writel(db_status, GPIO_ADB);
+	}
+
+	/* Port B */
+	if (bit & 0xFF00 ) {
+			db_status = readl(GPIO_BDB);
+			db_status &= ~(bit >> 8) ;
+			writel(db_status, GPIO_BDB);
+	}
+
+}
+
+/*
+ * mask EGPIO irq's (disable)
+ */
+static void inline ep93xx_mask_gpio_irq(u32 irq)
+{
+	u32 irq_status;
+	u32 bit = IRQ_TO_BIT(irq);
+
+	IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
+
+	/* Port A */
+	if(bit & 0xFF) {
+		irq_status = readl(GPIO_AINTEN);
+		irq_status &= ~bit;
+		writel(irq_status, GPIO_AINTEN);
+	}
+
+	/* Port B */
+	if(bit & 0xFF00) {
+		irq_status = readl(GPIO_BINTEN);
+		irq_status &= ~(bit >> 8);
+		writel(irq_status, GPIO_BINTEN);
+	}
+}
+
+
+
+/*
+ * make a EGPIO to a irq input
+ */
+static int ep93xx_make_egio_to_irq(u32 bit,u32 irq)
+{
+	u32 irq_value;
+	int ret;
+
+	IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
+
+	if(bit & 0xFF) {
+		/* Set direction to input for EGPIOA */
+		irq_value = readl(GPIO_PADDR);
+		irq_value &= ~bit;
+		if((ret = writel(irq_value, GPIO_PADDR)) != irq_value) {
+			printk("%s irq: %d cannot set direction register(GPIO_PADDR) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
+			return -EFAULT;
+		}
+	}
+	/* Port B */
+	if(bit & 0xFF00) {
+		/* Set direction to input for EGPIOB */
+		irq_value = readl(GPIO_PBDDR);
+		irq_value &= ~(bit >> 8);
+		if((ret = writel(irq_value, GPIO_PBDDR)) != irq_value) {
+			printk("%s irq: %d cannot set direction register(GPIO_PBDDR) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * make a EGPIO edge/level sensitive
+ */
+static int ep93xx_make_egio_sensitive(u32 bit, unsigned int flags,u32 irq)
+{
+	u32 irq_value;
+	int ret;
+
+	/* PORT A */
+	if(bit & 0xFF) {
+		/* Enable edge/level sensitive IRQ on EGPIO PORT A */
+		irq_value = readl(GPIO_AINTTYPE1);
+		if(flags && 1)
+			irq_value |= bit;
+		else
+			irq_value &= ~bit;
+		if((ret = writel(irq_value, GPIO_AINTTYPE1)) != irq_value) {
+			printk("%s irq: %d cannot set IRQ parameter(GPIO_AINTYPE1) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
+			return -EFAULT;
+		}
+	}
+
+	/* Port B */
+	if(bit & 0xFF00) {
+		/* Enable edge/level sensitive IRQ on EGPIO PORT B */
+		irq_value = readl(GPIO_BINTTYPE1);
+		if(flags && 1)
+			irq_value |= (bit >> 8);
+		else
+			irq_value &= ~(bit >> 8);
+		if((ret = writel(irq_value, GPIO_BINTTYPE1)) != irq_value) {
+			/* printk("%s irq: %d cannot set IRQ parameter(GPIO_BINTYPE1) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); */
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * make a EGPIO high/low sensitive
+ */
+static int ep93xx_make_egio_high_low_sensitive(u32 bit, unsigned int flags,u32 irq)
+{
+	u32 irq_value;
+	int ret;
+
+	/* PORT A */
+	if(bit & 0xFF) {
+		/* Enable high/low sensitive IRQ on EGPIO PORT A */
+		irq_value = readl(GPIO_AINTTYPE2);
+		if(flags && 1)
+			irq_value |= bit;
+		else
+			irq_value &= ~bit;
+		if((ret = writel(irq_value, GPIO_AINTTYPE2)) != irq_value) {
+			printk("%s irq: %d cannot set IRQ parameter(GPIO_AINTTYPE2) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
+			return -EFAULT;
+		}
+	}
+
+	/* Port B */
+	if(bit & 0xFF00) {
+		/* Enable high/low sensitive IRQ on EGPIO PORT B */
+		irq_value = readl(GPIO_BINTTYPE2);
+		if(flags && 1)
+			irq_value |= (bit >> 8);
+		else
+			irq_value &= ~(bit >> 8);
+		if((ret = writel(irq_value, GPIO_BINTTYPE2)) != irq_value)
+		{
+			printk("%s irq: %d cannot set IRQ parameter(GPIO_BINTYPE2) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+
+
+
+/*
+ * type of GPIO irq's
+ */
+static int ep93xx_gpio_demux_handler_type(unsigned int irq, unsigned int flags)
+{
+	u32 bit = IRQ_TO_BIT(irq);
+	unsigned int debounce = 0;
+
+	IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
+
+	/*if (flags == IRQT_PROBE)
+		return 0;*/
+
+	if ((flags & __IRQT_RISEDGE) | (flags & __IRQT_FALEDGE) | (flags & __IRQT_LOWLVL) | (flags & __IRQT_HIGHLVL) | (flags & IRQT_DB) | (flags & IRQT_NOTDB)) {
+		if(0 != ep93xx_make_egio_to_irq(bit,irq)) {
+			printk("%s irq: %d cannot set direction register GPIO_PXDDR\n",__FUNCTION__,irq);
+			return -EINVAL;
+		} else {
+			if ((flags & IRQT_DB) | (flags & IRQT_NOTDB)) { /* 	To use switch structure extract debounce
+															   	flags from flags variable */
+				debounce = (flags & IRQT_DB) | (flags & IRQT_NOTDB);
+				flags &= ~debounce;
+			}
+			if((flags & __IRQT_RISEDGE) | (flags & __IRQT_FALEDGE)) {
+				/* Configure for edge IRQ */
+				if(0 == ep93xx_make_egio_sensitive(bit, 1,irq)) {
+					switch(flags) {
+					case __IRQT_RISEDGE:
+						if(0 != ep93xx_make_egio_high_low_sensitive(bit, 1,irq)) {
+							printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
+							return -EINVAL;
+						}
+					break;
+					case __IRQT_FALEDGE:
+						if(0 != ep93xx_make_egio_high_low_sensitive(bit, 0,irq)) {
+							printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
+							return -EINVAL;
+						}
+						break;
+					}
+
+					/* Now we set IRQ handler for edge */
+					/* set_irq_handler(irq, do_edge_IRQ); */
+				} else {
+					printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE1\n",__FUNCTION__,irq);
+					return -EINVAL;
+				}
+
+			} else {
+				if((flags & __IRQT_LOWLVL) | (flags & __IRQT_HIGHLVL)) {
+					/* Configure for level IRQ */
+					if(0 == ep93xx_make_egio_sensitive(bit, 0,irq)) {
+						switch(flags)
+						{
+							case __IRQT_HIGHLVL:
+								if(0 != ep93xx_make_egio_high_low_sensitive(bit, 1,irq))
+								{
+									printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
+									return -EINVAL;
+								}
+								break;
+							case __IRQT_LOWLVL:
+								if(0 != ep93xx_make_egio_high_low_sensitive(bit, 0,irq))
+								{
+									printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
+									return -EINVAL;
+								}
+								break;
+						}
+
+						/* Now we set IRQ handler level sensitive */
+						/* set_irq_handler(irq, do_level_IRQ); */
+					} else {
+						printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE1\n",__FUNCTION__,irq);
+						return -EINVAL;
+					}
+
+				}
+			}
+		}
+		/* For debounce flags handling */
+		if ((debounce & IRQT_DB) | (debounce & IRQT_NOTDB)) {
+			switch(debounce)
+			{
+				case IRQT_DB:
+					ep93xx_debounce_enable(irq);
+					break;
+				case IRQT_NOTDB:
+					ep93xx_debounce_disable(irq);
+					break;
+			}
+		}
+	} else {
+		printk("ep93xx_type_gpio_irq: IRQ:%d no flags defined\n",irq);
+		return -EINVAL;
+	}
+return 0;
+}
+
+/*
+ * GPIO call handler
+ */
+static void ep93xx_gpio_handler(unsigned int mask, unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+	IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
+
+	desc = irq_desc + irq;
+
+	while (mask) {
+		if (mask & 1) {
+			IRQDBG("handling irq %d\n", irq);
+			desc->handle(irq, desc, regs);
+		}
+		irq++;
+		desc++;
+		mask >>= 1;
+	}
+
+}
+
+/*
+ * GPIO dmux handler
+ */
+static void ep93xx_gpio_demux_handler(unsigned int irq_gpio, struct irqdesc *desc, struct pt_regs *regs)
+{
+	unsigned int mask;
+	unsigned int irq = IRQ_CHAINED_GPIO(0);
+
+	/*
+	 * Mask the parent IRQ.
+	 */
+	ep93xx_vic2_mask(irq_gpio);
+
+	mask = 	readl(GPIO_INTSTATUSA) | (readl(GPIO_INTSTATUSB) << 8);
+
+	irq = IRQ_CHAINED_GPIO(0);
+	IRQDBG("%s mask: 0x%x irq: %d\n",__FUNCTION__,mask,irq);
+	ep93xx_gpio_handler(mask, irq, desc, regs);
+
+	/*
+	 * Unmask the parent IRQ
+	 */
+	ep93xx_vic2_unmask(irq_gpio);
+}
+
+
+static struct irqchip ep93xx_gpio_irq = {
+	.ack		= ep93xx_ack_gpio_irq,
+	.mask		= ep93xx_mask_gpio_irq,
+	.unmask		= ep93xx_unmask_gpio_irq,
+	.set_type	= ep93xx_gpio_demux_handler_type,
+};
+
+#endif
+
+
+void __init ep93xx_init_irq(void)
+{
+	unsigned int i;
+
+	/* Interrupt bits 0 and 1 are unused  */
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+	for (i = 2; i < NR_GLBL_IRQS; i++) {
+#else
+	for (i = 2; i < NR_IRQS; i++) {
+#endif
+		if(i < 32){
+			/* Interrupts below 32 belong to VIC1 */
+			set_irq_handler(i, do_level_IRQ);
+			set_irq_chip(i, &vic1_chip);
+			set_irq_flags(i, IRQF_VALID);
+
+		} else {
+			if (i == IRQ_1HZ) {
+				/* 1 Hz int is edge trigered, and not ackable */
+				set_irq_handler(i, do_edge_IRQ);
+				set_irq_chip(i, &rtc_chip);
+				set_irq_flags(i, IRQF_VALID | IRQF_NOAUTOEN);
+			} else {
+				/* Interrupt 32 and above belong to VIC2 */
+				set_irq_handler(i, do_level_IRQ);
+				set_irq_chip(i, &vic2_chip);
+				set_irq_flags(i, IRQF_VALID);
+			}
+		}
+	}
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+	for (i = IRQ_CHAINED_GPIO(0) ; i <= IRQ_CHAINED_GPIO(15); i++) {
+
+		IRQDBG("%s irq: %d init \n",__FUNCTION__, i);
+
+		/* GPIO Interrupt is demux to 16 IRQs */
+		set_irq_chip(i, &ep93xx_gpio_irq);
+		set_irq_flags(i, IRQF_VALID);
+
+		if(egpio_irqs[i - NR_GLBL_IRQS].enable == 1) {
+			set_irq_handler(i, do_level_IRQ);
+			set_irq_type(i, egpio_irqs[i - NR_GLBL_IRQS].flags);
+		} else {
+			set_irq_handler(i, do_edge_IRQ);
+		}
+	}
+	set_irq_chained_handler(IRQ_GPIO, ep93xx_gpio_demux_handler);
+#endif
+}
diff --git a/arch/arm/mach-ep93xx/mach-acc.c b/arch/arm/mach-ep93xx/mach-acc.c
new file mode 100644
index 0000000..aa002ac
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-acc.c
@@ -0,0 +1,67 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/acc.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *  Copyright (C) 2004 Klaus Fetscher
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc acc_io_desc[] __initdata = {
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+};
+
+static void __init acc_map_io(void)
+{
+	iotable_init(acc_io_desc, ARRAY_SIZE(acc_io_desc));
+}
+
+static void __init acc_init(void)
+{
+}
+
+MACHINE_START(ACC, "acc")
+    /* Maintainer HiFish */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= acc_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= acc_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/mach-adssphere.c b/arch/arm/mach-ep93xx/mach-adssphere.c
new file mode 100644
index 0000000..2cbf5ca
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-adssphere.c
@@ -0,0 +1,281 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/adssphere.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *  Copyright (C) 2005 Robert Whaley, ADS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+
+#include <asm/arch/adssphere.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc adssphere_io_desc[] __initdata =
+{
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+	{ ADSSPHERE_BASE_VIRT,  ADSSPHERE_BASE_PHYS,  SZ_1M,  MT_DEVICE },
+};
+
+static void __init adssphere_map_io(void)
+{
+	iotable_init(adssphere_io_desc, ARRAY_SIZE(adssphere_io_desc));
+}
+
+/*
+ * Flash handling.
+ */
+
+static int flash_init(void)
+{
+	return 0;
+}
+
+static void flash_exit(void)
+{
+}
+
+static void flash_set_vpp(int on)
+{
+}
+
+static struct flash_platform_data flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 4,
+	.init		= flash_init,
+	.exit		= flash_exit,
+	.set_vpp	= flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+	.start		= 0x60000000,
+	.end		= 0x60000000 + SZ_32M - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name		= "flash",
+	.id		= 0,
+	.dev		= {
+			    .platform_data	= &flash_data,
+			  },
+	.num_resources	= 1,
+	.resource	= &cfi_flash_resource,
+};
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN)
+
+void adssphere_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		break;
+
+	case led_idle_end:
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		break;
+
+	case led_red_off:
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if  (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+	local_irq_restore(flags);
+}
+
+#endif
+
+#ifdef CONFIG_SOUND_EP93XX_AC97
+void adssphere_audio_power(int on)
+{
+	unsigned int tmp;
+
+	tmp = readb(ADSSPHERE_CR1);
+	if (on) {
+		tmp |=  ADSSPHERE_CR1_AMP_ON;
+		tmp &= ~ADSSPHERE_CR1_CDC_ON;
+	} else {
+		tmp &= ~ADSSPHERE_CR1_AMP_ON;
+		tmp |=  ADSSPHERE_CR1_CDC_ON;
+	}
+	writeb(tmp, ADSSPHERE_CR1);
+}
+
+#endif
+
+#ifdef CONFIG_FB_EP93XX
+void adssphere_blank(int blank_mode)
+{
+	unsigned int tmp;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		/* turn on backlight via enable and pwm */
+		/* enable fb signals */
+		tmp = readl(ADSSPHERE_CR1);
+		tmp &= ~ADSSPHERE_CR1_PNL_ON;
+		tmp |= ADSSPHERE_CR1_PNL_EN | ADSSPHERE_CR1_BL_ON;
+		writel(tmp, ADSSPHERE_CR1);
+
+		writel(100, PWM0_TC);
+		writel(99, PWM0_DC);
+		writel(1, PWM0_EN);
+
+		break;
+
+
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+
+		/* disable fb signals */
+		/* turn off backlight via enable and pwm */
+		tmp = readl(ADSSPHERE_CR1);
+		tmp |= ADSSPHERE_CR1_PNL_ON;
+		tmp &= ~(ADSSPHERE_CR1_PNL_EN | ADSSPHERE_CR1_BL_ON);
+		writel(tmp, ADSSPHERE_CR1);
+
+		writel(0, PWM0_EN);
+
+		break;
+	}
+}
+#endif
+
+static void __init adssphere_init (void)
+{
+#if 0
+	printk("physmap_configure\n");
+	physmap_configure(0x60000000, 0x02000000, 4, NULL);
+#endif
+	printk("platform_device_register\n");
+	platform_device_register(&cfi_flash_device);
+#ifdef CONFIG_LEDS
+	leds_event = adssphere_leds_event;
+#endif
+	leds_event(led_start);
+#ifdef CONFIG_SOUND_EP93XX_AC97
+	adssphere_audio_power(1);
+#endif
+}
+
+MACHINE_START(ADSSPHERE, "adssphere")
+	/* Maintainer: Applied Data Systems */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= adssphere_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= adssphere_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-ep93xx/mach-dma03.c b/arch/arm/mach-ep93xx/mach-dma03.c
new file mode 100644
index 0000000..2223f80
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-dma03.c
@@ -0,0 +1,343 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/mach-dma03.c
+ *  Copyright (C) 2005 Michael Burian
+ *
+ * based on arch/arm/mach-ep93xx/mach-edb9315.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_SERIAL_8250
+#include <linux/serial_8250.h>
+#endif 
+
+#ifdef CONFIG_PARPORT_PC
+#include <linux/parport.h>
+#endif
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+#ifdef CONFIG_SERIAL_8250
+#include <asm/serial.h>
+#endif
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+#include "ep93xx_gpio_irq.h"
+#endif
+
+
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc dma03_io_desc[] __initdata = {
+	{EP93XX_AHB_BASE, __phys_to_pfn(io_v2p(EP93XX_AHB_BASE)), SZ_1M, MT_DEVICE},
+	{EP93XX_APB_BASE, __phys_to_pfn(io_v2p(EP93XX_APB_BASE)), SZ_8M, MT_DEVICE},
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_PARPORT_PC)
+	{ 0xD0000000, __phys_to_pfn(0x70000000),  SZ_4K,  MT_DEVICE }, /* 2x UARTS, LPT; 16C552 */
+#endif
+};
+
+static void __init dma03_map_io(void)
+{
+	iotable_init(dma03_io_desc, ARRAY_SIZE(dma03_io_desc));
+}
+
+/*
+ * Flash handling.
+ */
+
+static int flash_init(void)
+{
+	return 0;
+}
+
+static void flash_exit(void)
+{
+}
+
+static void flash_set_vpp(int on)
+{
+}
+
+static struct flash_platform_data flash_data = {
+	.map_name = "cfi_probe",
+	.width = 4,
+	.init = flash_init,
+	.exit = flash_exit,
+	.set_vpp = flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+	.start = 0x60000000,
+	.end = 0x60000000 + SZ_32M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name = "flash",
+	.dev = {
+		.platform_data = &flash_data,
+		},
+	.num_resources = 1,
+	.resource = &cfi_flash_resource,
+};
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_RED		2
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN | LED_RED)
+
+void dma03_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~LED_RED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+
+	local_irq_restore(flags);
+}
+
+#endif
+
+
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+/* GPIO irq description
+ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
+ * flags can be		IRQT_RISING
+ *			IRQT_FALLING
+ *			IRQT_LOW
+ *			IRQT_HIGH
+ *			IRQT_PROBE
+ *
+ * On IRQT_PROBE nothing is done in setup irq code
+ */
+
+/* For IRQ Demux */
+
+#define DISABLED 0
+#define ENABLED 1
+struct ep93xx_egpio_irq egpio_irqs[] __initdata =
+{
+	/* EGPIO IRQ 0 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 1 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 2 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 3 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 4 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 5 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 6 */
+	{ ENABLED, IRQT_HIGH    },	/* OKI ML9620 CAN controller can0 */
+	/* EGPIO IRQ 7 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 8 */
+	{ ENABLED, IRQT_HIGH    },	/* 16C552 serial UART 1 */
+	/* EGPIO IRQ 9 */
+	{ ENABLED, IRQT_HIGH    },	/* 16C552 serial UART 2 */
+	/* EGPIO IRQ 10 */
+	{ ENABLED, IRQT_RISING  },	/* 16C552 parallel port 1 */
+	/* EGPIO IRQ 11 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 12 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 13 */
+	{ ENABLED, IRQT_HIGH    },	/* OKI ML9620 CAN controller can1 */
+	/* EGPIO IRQ 14 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 15 */
+	{ DISABLED, IRQT_PROBE  },
+};
+#endif
+
+#ifdef CONFIG_SERIAL_8250
+static struct plat_serial8250_port serial_platform_data[] = {
+        {
+		.mapbase        = 0x70000008,
+		.irq            = GPIO_IRQ8,
+		.flags          = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ,
+		.iotype         = UPIO_MEM,
+		.regshift       = 0,
+		.uartclk        = BASE_BAUD*16,
+         } , {
+		.mapbase        = 0x70000010,
+		.irq            = GPIO_IRQ9,
+		.flags          = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ,
+		.iotype         = UPIO_MEM,
+		.regshift       = 0,
+		.uartclk        = BASE_BAUD*16,
+        }, { },
+};
+
+static struct platform_device serial_device = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data  = serial_platform_data,
+	},
+};
+#endif
+
+static struct platform_device *devices[] __initdata = {
+	&cfi_flash_device,
+#ifdef CONFIG_SERIAL_8250
+	&serial_device,
+#endif
+};
+
+static void __init dma03_init(void)
+{
+	struct parport *port;
+	physmap_configure(0x60000000, 0x02000000, 4, NULL);
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+#ifdef CONFIG_PARPORT_PC
+	port = parport_pc_probe_port(0xD0000020, 0, GPIO_IRQ10, 0, NULL);
+// How to register that beast without crashing?
+//	if(port)
+//		port = parport_register_port(0xD0000020, GPIO_IRQ10, 0, NULL); // note that passing NULL as fops arg is a bad idea(tm)
+//	if(port)
+//		parport_announce_port(port);
+#endif
+
+#ifdef CONFIG_LEDS
+	leds_event = dma03_leds_event;
+#endif
+	leds_event(led_start);
+}
+
+MACHINE_START(DMA03, "dma03")
+	/* Maintainer: Michael Burian */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= dma03_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= dma03_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/mach-edb9301.c b/arch/arm/mach-ep93xx/mach-edb9301.c
new file mode 100644
index 0000000..68004e2
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-edb9301.c
@@ -0,0 +1,219 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/edb9301.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc edb9301_io_desc[] __initdata = {
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+};
+
+static void __init edb9301_map_io(void)
+{
+	iotable_init(edb9301_io_desc, ARRAY_SIZE(edb9301_io_desc));
+}
+
+/*
+ * Flash handling.
+ */
+
+static int flash_init(void)
+{
+	return 0;
+}
+
+static void flash_exit(void)
+{
+}
+
+static void flash_set_vpp(int on)
+{
+}
+
+static struct flash_platform_data flash_data = {
+	.map_name = "cfi_probe",
+	.width = 2,
+	.init = flash_init,
+	.exit = flash_exit,
+	.set_vpp = flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+	.start = 0x60000000,
+	.end = 0x60000000 + SZ_16M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name = "flash",
+	.dev = {
+		.platform_data = &flash_data,
+		},
+	.num_resources = 1,
+	.resource = &cfi_flash_resource,
+};
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_RED		2
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN | LED_RED)
+
+void edb9301_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~LED_RED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+
+	local_irq_restore(flags);
+}
+
+#endif
+
+static void __init edb9301_init(void)
+{
+	physmap_configure(0x60000000, 0x01000000, 2, NULL);
+	platform_device_register(&cfi_flash_device);
+#ifdef CONFIG_LEDS
+	leds_event = edb9301_leds_event;
+#endif
+	leds_event(led_start);
+}
+
+MACHINE_START(EDB9301, "edb9301")
+	/* Maintainer: Michael Burian */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= edb9301_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= edb9301_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/mach-edb9302.c b/arch/arm/mach-ep93xx/mach-edb9302.c
new file mode 100644
index 0000000..ac74a1e
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-edb9302.c
@@ -0,0 +1,362 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/edb9302.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+#include <asm/arch/mach-edb9302.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc edb9302_io_desc[] __initdata = {
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+};
+
+static void __init edb9302_map_io(void)
+{
+	iotable_init(edb9302_io_desc, ARRAY_SIZE(edb9302_io_desc));
+}
+
+/*
+ * Flash handling.
+ */
+
+static int flash_init(void)
+{
+	return 0;
+}
+
+static void flash_exit(void)
+{
+}
+
+static void flash_set_vpp(int on)
+{
+}
+
+static struct flash_platform_data flash_data = {
+	.map_name = "cfi_probe",
+	.width = 2,
+	.init = flash_init,
+	.exit = flash_exit,
+	.set_vpp = flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+	.start = 0x60000000,
+	.end = 0x60000000 + SZ_16M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name = "flash",
+	.dev = {
+		.platform_data = &flash_data,
+		},
+	.num_resources = 1,
+	.resource = &cfi_flash_resource,
+};
+
+/* SSP hackery */
+
+static void ssp_cs_flash(struct ssp_slave *s, int enable)
+{
+	unsigned long x = readl(GPIO_PADR);
+	if (enable)
+		x &= ~0x80;
+	else
+		x |= 0x80;
+	writel(x, GPIO_PADR);
+}
+
+struct ep93xx_ssp_slave ep93xx_ssp_flash = {
+	{
+	 LIST_HEAD_INIT(ep93xx_ssp_flash.slave.list),
+	 NULL,
+	 0,
+	 0,
+	 8,
+	 1,
+	 ssp_cs_flash},
+	((0 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_MOTOROLA << SSPCR0_FRF_SHIFT) |
+	 SSPCR0_SPO | SSPCR0_SPH | (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
+	(SSPC1_SSE | SSPC1_RORIE),
+	2
+};
+
+EXPORT_SYMBOL(ep93xx_ssp_flash);
+
+static void ssp_cs_codec(struct ssp_slave *s, int enable)
+{
+	unsigned long x = readl(GPIO_PADR);
+	if (enable)
+		x &= ~0x40;
+	else
+		x |= 0x40;
+	writel(x, GPIO_PADR);
+}
+
+struct ep93xx_ssp_slave ep93xx_ssp_codec = {
+	{
+	 LIST_HEAD_INIT(ep93xx_ssp_codec.slave.list),
+	 NULL,
+	 0,
+	 0,
+	 8,
+	 1,
+	 ssp_cs_codec},
+	((31 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_TI << SSPCR0_FRF_SHIFT) |
+	 (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
+	(SSPC1_SSE | SSPC1_RORIE),
+	48
+};
+
+EXPORT_SYMBOL(ep93xx_ssp_codec);
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_RED		2
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN | LED_RED)
+
+void edb9302_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~LED_RED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+
+	local_irq_restore(flags);
+}
+
+#endif
+
+static void __init edb9302_init_gpio(void)
+{
+	/* port A */
+	/* EGPIO0-7 */
+	writel(0xc2, GPIO_PADDR);
+	writel(0xc0, GPIO_PADR);
+
+	/* port B */
+	/* EGPIO8-15 */
+	writel(0x00, GPIO_PBDDR);
+	writel(0x00, GPIO_PBDR);
+
+	/* port C */
+	/* GPIO0 */
+	writel(0x00, GPIO_PCDDR);
+	writel(0x00, GPIO_PCDR);
+
+	/* port E */
+	/* RDLED, GRLED */
+	writel(0x03, GPIO_PEDDR);
+	writel(0x03, GPIO_PEDR);
+
+	/* port F */
+	/* GPIO5, GPIO6, GPIO7 */
+	writel(0x00, GPIO_PFDDR);
+	writel(0x00, GPIO_PFDR);
+
+	/* port G */
+	/* EECLK, EEDAT */
+	writel(0x00, GPIO_PGDDR);
+	writel(0x00, GPIO_PGDR);
+
+	/* port H */
+	/* GPIO1, GPIO2, GPIO3, GPIO4 */
+	writel(0x00, GPIO_PHDDR);
+	writel(0x00, GPIO_PHDR);
+}
+
+/* looks like this might be more generic than just edb9302... */
+int ssp_do_asymmetric(struct ep93xx_ssp_slave *ss, void *tx, int tlen, void *rx,
+		      int rlen)
+{
+	struct ssp_slave *s = (struct ssp_slave *)ss;
+	int err;
+
+	if ((err = ssp_start(s)) < 0)
+		goto out1;
+
+	ssp_select(s);
+
+	if ((err = ssp_post(s, tlen, tx, NULL)) < 0)
+		goto out2;
+
+	ssp_wait(s);
+
+	if ((err = ssp_post(s, rlen, NULL, rx)) < 0)
+		goto out2;
+
+	ssp_wait(s);
+
+      out2:
+	ssp_deselect(s);
+	ssp_finish(s);
+      out1:
+	return err;
+}
+
+/* start poking at the Atmel AT25F1024 flash chip */
+void poke_flash(void)
+{
+	unsigned char rdsr[1] = { 0x05 };
+	unsigned char rdid[1] = { 0x15 };
+	unsigned char rsp[10];
+
+	ssp_do_asymmetric(&ep93xx_ssp_flash, rdsr, 1, rsp, 1);
+	printk(KERN_WARNING "RDSR returns %02x\n", rsp[0]);
+
+	ssp_do_asymmetric(&ep93xx_ssp_flash, rdid, 1, rsp, 2);
+	printk(KERN_WARNING "RDID returns %02x:%02x\n", rsp[0], rsp[1]);
+}
+
+static void __init edb9302_init(void)
+{
+	physmap_configure(0x60000000, 0x01000000, 2, NULL);
+	platform_device_register(&cfi_flash_device);
+	edb9302_init_gpio();
+#ifdef CONFIG_LEDS
+	leds_event = edb9302_leds_event;
+#endif
+	leds_event(led_start);
+	if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_flash.slave) < 0)
+		printk(KERN_ERR "EDB9302: unable to add flash slave\n");
+	if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_codec.slave) < 0)
+		printk(KERN_ERR "EDB9302: unable to add codec slave\n");
+}
+
+MACHINE_START(EDB9302, "edb9302")
+	/* Maintainer: Michael Burian */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= edb9302_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= edb9302_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/mach-edb9312.c b/arch/arm/mach-ep93xx/mach-edb9312.c
new file mode 100644
index 0000000..e67b673
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-edb9312.c
@@ -0,0 +1,219 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/edb9312.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc edb9312_io_desc[] __initdata = {
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+};
+
+static void __init edb9312_map_io(void)
+{
+	iotable_init(edb9312_io_desc, ARRAY_SIZE(edb9312_io_desc));
+}
+
+/*
+ * Flash handling.
+ */
+
+static int flash_init(void)
+{
+	return 0;
+}
+
+static void flash_exit(void)
+{
+}
+
+static void flash_set_vpp(int on)
+{
+}
+
+static struct flash_platform_data flash_data = {
+	.map_name = "cfi_probe",
+	.width = 4,
+	.init = flash_init,
+	.exit = flash_exit,
+	.set_vpp = flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+	.start = 0x60000000,
+	.end = 0x60000000 + SZ_32M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name = "flash",
+	.dev = {
+		.platform_data = &flash_data,
+		},
+	.num_resources = 1,
+	.resource = &cfi_flash_resource,
+};
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_RED		2
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN | LED_RED)
+
+void edb9312_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~LED_RED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+
+	local_irq_restore(flags);
+}
+
+#endif
+
+static void __init edb9312_init(void)
+{
+	physmap_configure(0x60000000, 0x02000000, 4, NULL);
+	platform_device_register(&cfi_flash_device);
+#ifdef CONFIG_LEDS
+	leds_event = edb9312_leds_event;
+#endif
+	leds_event(led_start);
+}
+
+MACHINE_START(EDB9312, "edb9312")
+	/* Maintainer: Michael Burian */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= edb9312_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= edb9312_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/mach-edb9315.c b/arch/arm/mach-ep93xx/mach-edb9315.c
new file mode 100644
index 0000000..14c680a
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-edb9315.c
@@ -0,0 +1,219 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/edb9315.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc edb9315_io_desc[] __initdata = {
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+};
+
+static void __init edb9315_map_io(void)
+{
+	iotable_init(edb9315_io_desc, ARRAY_SIZE(edb9315_io_desc));
+}
+
+/*
+ * Flash handling.
+ */
+
+static int flash_init(void)
+{
+	return 0;
+}
+
+static void flash_exit(void)
+{
+}
+
+static void flash_set_vpp(int on)
+{
+}
+
+static struct flash_platform_data flash_data = {
+	.map_name = "cfi_probe",
+	.width = 4,
+	.init = flash_init,
+	.exit = flash_exit,
+	.set_vpp = flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+	.start = 0x60000000,
+	.end = 0x60000000 + SZ_32M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name = "flash",
+	.dev = {
+		.platform_data = &flash_data,
+		},
+	.num_resources = 1,
+	.resource = &cfi_flash_resource,
+};
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_RED		2
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN | LED_RED)
+
+void edb9315_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~LED_RED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+
+	local_irq_restore(flags);
+}
+
+#endif
+
+static void __init edb9315_init(void)
+{
+	physmap_configure(0x60000000, 0x02000000, 4, NULL);
+	platform_device_register(&cfi_flash_device);
+#ifdef CONFIG_LEDS
+	leds_event = edb9315_leds_event;
+#endif
+	leds_event(led_start);
+}
+
+MACHINE_START(EDB9315, "edb9315")
+	/* Maintainer: Michael Burian */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= edb9315_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= edb9315_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/mach-ttml.c b/arch/arm/mach-ep93xx/mach-ttml.c
new file mode 100644
index 0000000..872dd01
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-ttml.c
@@ -0,0 +1,369 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/mach-ttml.c
+ *
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+#include <asm/arch/mach-ttml.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc ttml_io_desc[] __initdata = {
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+};
+
+static void __init ttml_map_io(void)
+{
+	iotable_init(ttml_io_desc, ARRAY_SIZE(ttml_io_desc));
+}
+
+/*
+ * Flash handling.
+ */
+
+static int flash_init(void)
+{
+	return 0;
+}
+
+static void flash_exit(void)
+{
+}
+
+static void flash_set_vpp(int on)
+{
+}
+
+static struct flash_platform_data flash_data = {
+	.map_name = "cfi_probe",
+	.width = 2,
+	.init = flash_init,
+	.exit = flash_exit,
+	.set_vpp = flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+	.start = 0x60000000,
+	.end = 0x60000000 + SZ_16M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name = "flash",
+	.dev = {
+		.platform_data = &flash_data,
+		},
+	.num_resources = 1,
+	.resource = &cfi_flash_resource,
+};
+
+/* SSP hackery */
+
+static void ssp_cs_timicro(struct ssp_slave *s, int enable)
+{
+	unsigned long x = readl(GPIO_PBDR);
+	if (enable)
+		x &= ~0x10;
+	else
+		x |= 0x10;
+	writel(x, GPIO_PBDR);
+}
+
+struct ep93xx_ssp_slave ep93xx_ssp_micro = {
+	{
+	 LIST_HEAD_INIT(ep93xx_ssp_micro.slave.list),
+	 NULL,
+	 0,
+	 0,
+	 8,
+	 1,
+	 ssp_cs_timicro},
+	((31 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_TI << SSPCR0_FRF_SHIFT) |
+	 (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
+	(SSPC1_SSE | SSPC1_RORIE),
+	48
+};
+
+EXPORT_SYMBOL(ep93xx_ssp_micro);
+
+static void ssp_cs_expansion(struct ssp_slave *s, int enable)
+{
+	unsigned long x = readl(GPIO_PBDR);
+	if (enable)
+		x &= ~0x20;
+	else
+		x |= 0x20;
+	writel(x, GPIO_PBDR);
+}
+
+struct ep93xx_ssp_slave ep93xx_ssp_expansion = {
+	{
+	 LIST_HEAD_INIT(ep93xx_ssp_expansion.slave.list),
+	 NULL,
+	 0,
+	 0,
+	 8,
+	 1,
+	 ssp_cs_expansion},
+	0,
+	0,
+	0
+};
+
+EXPORT_SYMBOL(ep93xx_ssp_expansion);
+
+/**
+ * ssp_do_ttml - perform a single SSP transaction to the TTML micro
+ * @s: the slave
+ * @len: the number of words to transfer
+ * @tx: a buffer of @len words to clock out to slave
+ * @rx: a buffer of @len words to clock in from slave
+ *
+ * Use the SSP transaction interface to drive the TTML micro. The
+ * first byte back from the micro is the length of the reply, excluding
+ * the len and the csum bytes. @rlen and @rx had better be bigger
+ * than any reply the micro might generate.
+ */
+int ssp_do_ttml(struct ep93xx_ssp_slave *ss, void *tx, int tlen, void *rx,
+		int rlen)
+{
+	struct ssp_slave *s = (struct ssp_slave *)ss;
+	int len;
+	int err;
+
+	if ((err = ssp_start(s)) < 0)
+		goto out1;
+
+	ssp_select(s);
+
+	if ((err = ssp_post(s, tlen, tx, NULL)) < 0)
+		goto out2;
+
+	ssp_wait(s);
+
+	if ((err = ssp_post(s, 1, NULL, rx)) < 0)
+		goto out2;
+
+	ssp_wait(s);
+
+	{
+		char *b = rx;
+		len = ((b[0] >> 4) & 0x07) + 2;
+	}
+
+	if (len > rlen) {
+		printk(KERN_WARNING "SSP: rx buffer truncated\n");
+		len = rlen;
+	}
+
+	if ((err = ssp_post(s, len - 1, NULL, rx + 1)) < 0)
+		goto out2;
+
+	err = ssp_wait(s);
+
+      out2:
+	ssp_deselect(s);
+      out1:
+	ssp_finish(s);
+	return err;
+}
+
+EXPORT_SYMBOL(ssp_do_ttml);
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_RED		2
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN | LED_RED)
+
+void ttml_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~LED_RED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+
+	local_irq_restore(flags);
+}
+
+#endif
+
+static void __init ttml_init_gpio(void)
+{
+	/* port A */
+	writel(0x00, GPIO_PADDR);
+
+	/* port B */
+	writel(0xf1, GPIO_PBDDR);
+	writel(0xf1, GPIO_PBDR);
+
+	/* port C */
+	writel(0x01, GPIO_PCDDR);
+	writel(0x01, GPIO_PCDR);
+
+	/* port E */
+	writel(0x03, GPIO_PEDDR);
+	writel(0x03, GPIO_PEDR);
+
+	/* port F */
+	writel(0x00, GPIO_PFDDR);
+	writel(0x00, GPIO_PFDR);
+
+	/* port G */
+	writel(0x00, GPIO_PGDDR);
+	writel(0x00, GPIO_PGDR);
+
+	/* port H */
+	writel(0x04, GPIO_PHDDR);
+	writel(0x00, GPIO_PHDR);
+}
+
+static void __init ttml_init(void)
+{
+	physmap_configure(0x60000000, 0x01000000, 2, NULL);
+	platform_device_register(&cfi_flash_device);
+	ttml_init_gpio();
+#ifdef CONFIG_LEDS
+	leds_event = ttml_leds_event;
+#endif
+	leds_event(led_start);
+
+	if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_micro.slave) < 0)
+		printk(KERN_ERR "EP93XX: unable to add micro slave\n");
+
+	if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_expansion.slave) < 0)
+		printk(KERN_ERR "EP93XX: unable to add expansion slave\n");
+
+}
+
+MACHINE_START(EDB9301, "ttml")
+	/* Maintainer: Michael Burian */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= ttml_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= ttml_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/mach-zefeerdzb.c b/arch/arm/mach-ep93xx/mach-zefeerdzb.c
new file mode 100644
index 0000000..c224ca1
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-zefeerdzb.c
@@ -0,0 +1,237 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/zefeerdzb.c
+ *
+ *  Copyright (C) 2004, 2005 DAVE Srl <www.dave-tech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc zefeerdzb_io_desc[] __initdata = {
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+};
+
+static void __init zefeerdzb_map_io(void)
+{
+	iotable_init(zefeerdzb_io_desc, ARRAY_SIZE(zefeerdzb_io_desc));
+}
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_RED		2
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN | LED_RED)
+
+void zefeerdzb_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~LED_RED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+
+	local_irq_restore(flags);
+}
+
+#endif
+
+static void __init zefeerdzb_init(void)
+{
+	/*
+	   physmap_configure(0x60000000, 0x01000000, 2, NULL);
+	   platform_device_register(&cfi_flash_device);
+	 */
+
+#ifdef CONFIG_LEDS
+	leds_event = zefeerdzb_leds_event;
+#endif
+	leds_event(led_start);
+}
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+#include "ep93xx_gpio_irq.h"
+#endif
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+/* GPIO irq description
+ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
+ * flags can be		IRQT_RISING
+ *			IRQT_FALLING
+ *			IRQT_LOW
+ *			IRQT_HIGH
+ *			IRQT_PROBE
+ *
+ * On IRQT_PROBE nothing is done in setup irq code
+ */
+
+/* For IRQ Demux */
+
+#define DISABLED 0
+#define ENABLED 1
+struct ep93xx_egpio_irq egpio_irqs[] __initdata =
+{
+	/* EGPIO IRQ 0 */
+	{ DISABLED , IRQT_PROBE },
+	/* EGPIO IRQ 1 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 2 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 3 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 4 */
+	{ ENABLED, IRQT_LOW     },	/* CAN 0 GPIO IRQ */
+	/* EGPIO IRQ 5 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 6 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 7 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 8 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 9 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 10 */
+	{ ENABLED, IRQT_LOW     },	/* CAN 1 GPIO IRQ */
+	/* EGPIO IRQ 11 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 12 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 13 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 14 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 15 */
+	{ DISABLED, IRQT_PROBE  },
+};
+#endif
+
+MACHINE_START(ZEFEERDZB, "Zefeer DZB")
+	/* Maintainer: DAVE Srl <www.dave-tech.it> */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= zefeerdzb_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= zefeerdzb_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/mach-zefeerdzq.c b/arch/arm/mach-ep93xx/mach-zefeerdzq.c
new file mode 100644
index 0000000..4cae7a7
--- /dev/null
+++ b/arch/arm/mach-ep93xx/mach-zefeerdzq.c
@@ -0,0 +1,279 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/zefeerdzq.c
+ *
+ *  Copyright (C) 2004, 2005 DAVE Srl <www.dave-tech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/regmap.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+extern void ep93xx_init_irq(void);
+
+/* break this up into individual register blocks and map them in
+   the associated device drivers */
+
+static struct map_desc zefeerdzq_io_desc[] __initdata = {
+	{ EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
+	{ EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
+};
+
+static void __init zefeerdzq_map_io(void)
+{
+	iotable_init(zefeerdzq_io_desc, ARRAY_SIZE(zefeerdzq_io_desc));
+}
+
+/*
+ * Flash handling.
+ */
+
+/*
+static int flash_init(void)
+{
+	return 0;
+}
+
+static void flash_exit(void)
+{
+}
+
+static void flash_set_vpp(int on)
+{
+}
+
+static struct flash_platform_data flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 4,
+	.init		= flash_init,
+	.exit		= flash_exit,
+	.set_vpp	= flash_set_vpp,
+};
+
+static struct resource cfi_flash_resource = {
+	.start		= 0x60000000,
+	.end		= 0x60000000 + SZ_32M - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name		= "ZefeerDZQ Boot Flash",
+	.dev		= {
+			    .platform_data	= &flash_data,
+			  },
+	.num_resources	= 1,
+	.resource	= &cfi_flash_resource,
+};
+*/
+
+#ifdef CONFIG_LEDS
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+#define LED_RED		2
+#define LED_GREEN	1
+#define LED_MASK	(LED_GREEN | LED_RED)
+
+void zefeerdzq_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		led_state = LED_STATE_ENABLED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		hw_led_state = 0;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = LED_RED | LED_GREEN;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = 0;
+		break;
+
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= LED_GREEN;
+		break;
+
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~LED_RED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_GREEN;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= LED_RED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~LED_RED;
+		break;
+
+	default:
+		break;
+	}
+
+	writel(0x03, GPIO_PEDDR);
+
+	if (led_state & LED_STATE_ENABLED)
+		writel(hw_led_state, GPIO_PEDR);
+
+	local_irq_restore(flags);
+}
+
+#endif
+
+static void __init zefeerdzq_init(void)
+{
+	/*
+	   physmap_configure(0x60000000, 0x01000000, 2, NULL);
+	   platform_device_register(&cfi_flash_device);
+	 */
+
+#ifdef CONFIG_LEDS
+	leds_event = zefeerdzq_leds_event;
+#endif
+	leds_event(led_start);
+}
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+#include "ep93xx_gpio_irq.h"
+#endif
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+/* GPIO irq description
+ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
+ * flags can be		IRQT_RISING
+ *			IRQT_FALLING
+ *			IRQT_LOW
+ *			IRQT_HIGH
+ *			IRQT_PROBE
+ *
+ * On IRQT_PROBE nothing is done in setup irq code
+ */
+
+/* For IRQ Demux */
+
+#define DISABLED 0
+#define ENABLED 1
+struct ep93xx_egpio_irq egpio_irqs[] __initdata =
+{
+	/* EGPIO IRQ 0 */
+	{ DISABLED , IRQT_PROBE },
+	/* EGPIO IRQ 1 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 2 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 3 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 4 */
+	{ ENABLED, IRQT_LOW     },	/* CAN 0 GPIO IRQ */
+	/* EGPIO IRQ 5 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 6 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 7 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 8 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 9 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 10 */
+	{ ENABLED, IRQT_LOW     },	/* CAN 1 GPIO IRQ */
+	/* EGPIO IRQ 11 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 12 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 13 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 14 */
+	{ DISABLED, IRQT_PROBE  },
+	/* EGPIO IRQ 15 */
+	{ DISABLED, IRQT_PROBE  },
+};
+#endif
+
+MACHINE_START(ZEFEERDZQ, "Zefeer DZQ")
+	/* Maintainer: DAVE Srl <www.dave-tech.it> */
+	.phys_ram	= SDRAM_START,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
+	.boot_params	= (SDRAM_START + 0x00000100),
+
+	.map_io		= zefeerdzq_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_machine	= zefeerdzq_init,
+	.timer 		= &ep93xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/ssp-cirrus.c b/arch/arm/mach-ep93xx/ssp-cirrus.c
new file mode 100644
index 0000000..853c6c4
--- /dev/null
+++ b/arch/arm/mach-ep93xx/ssp-cirrus.c
@@ -0,0 +1,646 @@
+/*
+ *  FILE:			ssp.c
+ *
+ *  DESCRIPTION:	SSP Interface Driver Module implementation
+ *
+ *  Copyright Cirrus Logic Corporation, 2001-2003.  All rights reserved
+ *
+ * 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
+ */
+
+/*
+ *  This driver provides a way to read and write devices on the SSP
+ *  interface.
+ *
+ *  For Tx devices, EGPIO7 is used as an address pin:
+ *  I2S Codec CS4228        = EGPIO7 == 1
+ *  Serial Flash AT25F1024  = EGPIO7 == 0
+ */
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/ssp-cirrus.h>
+
+#undef DEBUG
+/* #define DEBUG 1 */
+#ifdef DEBUG
+#define DPRINTK( x... )  printk( ##x )
+#else
+#define DPRINTK( x... )
+#endif
+
+#define EP93XX_KEY_TIMER_PERIOD_MSEC 20
+
+static int SSP_Open(enum SSPDeviceType Device, SSPDataCallback Callback);
+static int SSP_Close(int Handle);
+static int SSP_Read(int Handle, unsigned int Addr, unsigned int *pValue);
+static int SSP_Write(int Handle, unsigned int Addr, unsigned int Value);
+static int CheckHandle(int Handle);
+
+static void SetSSPtoPS2(void);
+static void SetSSPtoI2S(void);
+static int ReadIntoBuffer(void);
+
+static int SSP_Write_I2SCodec(int Handle, unsigned int RegAddr,
+			      unsigned int RegValue);
+
+/*
+ * Key buffer...
+ */
+#define KEYBUF_SIZE 256
+static unsigned int uiKeyBuffer[KEYBUF_SIZE];
+
+static spinlock_t ssp_spinlock = SPIN_LOCK_UNLOCKED;
+
+enum SSPmodes {
+	SSP_MODE_UNKNOWN = 0,
+	SSP_MODE_PS2,
+	SSP_MODE_I2S,
+	SSP_MODE_FLASH,
+};
+
+static struct timer_list g_KbdTimer;
+static enum SSPmodes gSSPmode = SSP_MODE_UNKNOWN;
+static SSPDataCallback gKeyCallback = NULL;
+static int gHookedInterrupt = 0;
+
+/*
+ * Keep the last valid handle for SSP for kbd, i2s, and flash
+ */
+static int iLastValidHandle = -1;
+static int KeyboardHandle = 0;
+static int I2SHandle = 0;
+static int FlashHandle = 0;
+
+#define SSP_DEVICE_MASK    0xf0000000
+#define SSP_DEVICE_SHIFT	 28
+
+SSP_DRIVER_API SSPinstance = {
+	SSP_Open,
+	SSP_Read,
+	SSP_Write,
+	SSP_Close,
+};
+
+/*
+ * The only instance of this driver.
+ */
+SSP_DRIVER_API *SSPDriver = &SSPinstance;
+
+/**
+ * SSPIrqHandler - get all of the keys out of the SPI FIFO.
+ */
+irqreturn_t SSPIrqHandler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/*
+	 * Get key codes from SSP and send them to the keyboard callback.
+	 */
+	ReadIntoBuffer();
+
+	/*
+	 * Clear the interrupt.
+	 */
+	writel(0, SSPIIR);
+	return IRQ_HANDLED;
+}
+
+/**
+ * TimerRoutine
+ *
+ * This function is called periodically to make sure that no keys are stuck in
+ * the SPI FIFO.  This is necessary because the SPI only interrupts on half
+ * full FIFO which can leave up to one keyboard event in the FIFO until another
+ * key is pressed.
+ */
+static void TimerRoutine(unsigned long Data)
+{
+	int keycount;
+
+	/*
+	 * Get key codes from SSP and send them to the keyboard callback.
+	 */
+	keycount = ReadIntoBuffer();
+
+	/*
+	 * If no keys were received, call the Data callback anyway so it can
+	 * check for stuck keys.
+	 */
+	if ((keycount == 0) && gKeyCallback)
+		gKeyCallback(-1);
+
+	/*
+	 * Reschedule our timer in another 20 mSec.
+	 */
+	g_KbdTimer.expires =
+	    jiffies + MSECS_TO_JIFFIES(EP93XX_KEY_TIMER_PERIOD_MSEC);
+	add_timer(&g_KbdTimer);
+}
+
+/**
+ * HookInterrupt
+ *
+ * Requests SSP interrupt, sets up interrupt handler, sets up keyboard polling
+ * timer.
+ */
+static int HookInterrupt(void)
+{
+	if (gHookedInterrupt) {
+		printk(KERN_ERR "SSP driver interrupt already hooked\n");
+		return -1;
+	}
+
+	if (request_irq
+	    (IRQ_SSPRX, SSPIrqHandler, SA_INTERRUPT, "ep93xxsspd", NULL)) {
+		printk(KERN_ERR "SSP driver failed to get IRQ handler\n");
+		return -1;
+	}
+
+	gHookedInterrupt = 1;
+
+	/*
+	 * Initialize the timer that we will use to poll the SPI.
+	 */
+	init_timer(&g_KbdTimer);
+	g_KbdTimer.function = TimerRoutine;
+	g_KbdTimer.data = 1;
+	g_KbdTimer.expires =
+	    jiffies + MSECS_TO_JIFFIES(EP93XX_KEY_TIMER_PERIOD_MSEC);
+
+	add_timer(&g_KbdTimer);
+
+	return 0;
+}
+
+static int SSP_Open(enum SSPDeviceType Device, SSPDataCallback Callback)
+{
+	int Handle;
+
+	/*
+	 * Generate a handle and pass it back.
+	 *
+	 * Increment the last valid handle.
+	 * Check for wraparound (unlikely, but we like to be complete).
+	 */
+	iLastValidHandle++;
+
+	/*
+	 * If we wrapped around start over.  Unlikely.
+	 */
+	if ((iLastValidHandle & ~SSP_DEVICE_MASK) == 0)
+		iLastValidHandle = 1;
+
+	Handle = iLastValidHandle | (Device << SSP_DEVICE_SHIFT);
+
+	switch (Device) {
+	case PS2_KEYBOARD:
+		{
+			DPRINTK("SSP_Open - PS2_KEYBOARD\n");
+			if (KeyboardHandle)
+				return -1;
+
+			DPRINTK("Handle:%08x  Callback:%08x  -- Success\n",
+				Handle, (unsigned int)Callback);
+
+			KeyboardHandle = Handle;
+			/* Hook the interrupt if we have not yet. */
+			HookInterrupt();
+			SetSSPtoPS2();
+			gKeyCallback = Callback;
+
+			break;
+		}
+	case I2S_CODEC:
+		{
+			DPRINTK("SSP_Open - I2S_CODEC\n");
+			if (I2SHandle)
+				return -1;
+
+			DPRINTK("Handle:%08x  Callback:%08x  -- Success\n",
+				Handle, (unsigned int)Callback);
+
+			I2SHandle = Handle;
+			break;
+		}
+	case SERIAL_FLASH:
+		{
+			DPRINTK("SSP_Open - SERIAL_FLASH\n");
+			if (FlashHandle)
+				return -1;
+
+			DPRINTK("Handle:%08x  Callback:%08x  -- Success\n",
+				Handle, (unsigned int)Callback);
+
+			FlashHandle = Handle;
+			break;
+		}
+	default:
+		{
+			return -1;
+		}
+	}
+
+	return Handle;
+}
+
+/**
+ * SSP_Close
+ *
+ * Release that Handle!
+ */
+static int SSP_Close(int Handle)
+{
+	/*
+	 * Find out which device this API was called for.
+	 */
+	switch (CheckHandle(Handle)) {
+	case PS2_KEYBOARD:
+		{
+			DPRINTK("SSP_Open - PS2_KEYBOARD\n");
+			del_timer(&g_KbdTimer);
+			free_irq(IRQ_SSPRX, NULL);
+			gKeyCallback = NULL;
+			KeyboardHandle = 0;
+			gHookedInterrupt = 0;
+			break;
+		}
+	case I2S_CODEC:
+		{
+			DPRINTK("SSP_Open - I2S_CODEC\n");
+			I2SHandle = 0;
+			break;
+		}
+	case SERIAL_FLASH:
+		{
+			DPRINTK("SSP_Open - SERIAL_FLASH\n");
+			FlashHandle = 0;
+			break;
+		}
+	default:
+		{
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int SSP_Read(int Handle, unsigned int Addr, unsigned int *pValue)
+{
+	DPRINTK("SSP_Read\n");
+	return 0;
+}
+
+static int SSP_Write(int Handle, unsigned int Addr, unsigned int Value)
+{
+	int iRet = 0;
+	/* DPRINTK("SSP_Write - Handle:0x%08x  Addr:0x%08x  Value:0x%08x\n",
+	   Handle, Addr, Value ); */
+
+	/*
+	 * Find out which device this API was called for.
+	 */
+	switch (CheckHandle(Handle)) {
+	case PS2_KEYBOARD:
+		{
+			break;
+		}
+	case I2S_CODEC:
+		{
+			iRet = SSP_Write_I2SCodec(Handle, Addr, Value);
+			break;
+		}
+	case SERIAL_FLASH:
+		{
+			break;
+		}
+	default:
+		{
+			return -1;
+		}
+	}
+
+	return iRet;
+}
+
+static void SetSSPtoPS2(void)
+{
+	unsigned int uiRegTemp;
+
+	if (gSSPmode == SSP_MODE_PS2)
+		return;
+
+	/*
+	 * Disable the SSP, disable interrupts
+	 */
+	writel(0, SSPCR1);
+
+	/*
+	 * It takes almost a millisecond for a key to come in so
+	 * make sure we have completed all transactions.
+	 */
+	mdelay(1);
+
+	/*
+	 * Set EGPIO7 to disable EEPROM device on EDB9312.
+	 */
+	uiRegTemp = readl(GPIO_PADDR);
+	writel(uiRegTemp | 0x80, GPIO_PADDR);
+
+	uiRegTemp = readl(GPIO_PADR);
+	writel(uiRegTemp | 0x80, GPIO_PADR);
+
+	/*
+	 * Still haven't enabled the keyboard.  So anything in
+	 * the rx fifo is garbage.  Time to take out the trash.
+	 */
+	while (readl(SSPSR) & SSPSR_RNE) {
+		uiRegTemp = readl(SSPDR);
+	}
+
+	/*
+	 * SPICR0_SPO - SCLKOUT Polarity
+	 * SPICR0_SPH - SCLKOUT Phase
+	 * Motorola format, 11 bit, one start, 8 data, one bit for
+	 * parity, one stop bit.
+	 */
+	writel((SSPCR0_FRF_MOTOROLA | SSPCR0_SPH | SSPCR0_SPO |
+		SSPCR0_DSS_11BIT), SSPCR0);
+	/*
+	 * Configure the device as a slave, Clear FIFO overrun interrupts,
+	 * enable interrupts and reset the device.
+	 */
+	writel((SSPC1_MS | SSPC1_RIE | SSPC1_SOD), SSPCR1);
+	writel(0, SSPIIR);
+	writel((SSPC1_MS | SSPC1_RIE | SSPC1_SOD | SSPC1_SSE),
+	       SSPCR1);
+
+	/*
+	 * Configure EGPIO pins 12 and 14 as outputs because they are used
+	 * as buffer enables for the SPI interface to the ps2 keyboard.
+	 * Clear EGPIO pins 12 and 14, this will enable the SPI keyboard.
+	 */
+	uiRegTemp = readl(GPIO_PBDDR);
+	writel(uiRegTemp | 0x50, GPIO_PBDDR);
+
+	uiRegTemp = readl(GPIO_PBDR);
+	writel(uiRegTemp & ~0x50, GPIO_PBDR);
+
+	gSSPmode = SSP_MODE_PS2;
+}
+
+static void SetSSPtoI2S(void)
+{
+	unsigned int uiRegTemp;
+
+	if (gSSPmode == SSP_MODE_I2S)
+		return;
+
+	/*
+	 * Disable recieve interrupts.
+	 */
+	writel((SSPC1_MS | SSPC1_SSE), SSPCR1);
+
+	/*
+	 * Set GPIO pins 12 and 14, this will bring the clock line low
+	 * which signals to the keyboard to buffer keystrokes.
+	 * Note that EGPIO 14 is the clock line and EGPIO 12 is data line.
+	 */
+	uiRegTemp = readl(GPIO_PBDR);
+	writel(0x50 | uiRegTemp, GPIO_PBDR);
+
+	/*
+	 * It takes almost a millisecond for an partial keystrokes to come in.
+	 * Delay to make sure we have completed all transactions.
+	 */
+	mdelay(1);
+
+	/*
+	 * Anything we just recieved is garbage.  Time to take out the trash.
+	 */
+	while (readl(SSPSR) & SSPSR_RNE) {
+		uiRegTemp = readl(SSPDR);
+	}
+
+	/*
+	 * Disable the SSP and disable interrupts
+	 */
+	writel(0, SSPCR1);
+
+	/*
+	 * Clock will be 14.7 MHz divided by 4.
+	 */
+	writel(2, SSPCPSR);
+
+	/*
+	 * Configure EGPIO7 as an output and set it.  This selects
+	 * I2S codec as the device on the SSP output instead of
+	 * the serial flash.
+	 */
+	uiRegTemp = readl(GPIO_PADDR);
+	writel(uiRegTemp | 0x80, GPIO_PADDR);
+
+	uiRegTemp = readl(GPIO_PADR);
+	writel(uiRegTemp | 0x80, GPIO_PADR);
+
+	/*
+	 * Motorola format, 8 bit.
+	 */
+	writel((SSPCR0_SPO | SSPCR0_SPH | SSPCR0_FRF_MOTOROLA |
+		SSPCR0_DSS_8BIT), SSPCR0);
+
+	/*
+	 * Configure the device as master, reenable the device.
+	 */
+	writel(SSPC1_SSE, SSPCR1);
+
+	gSSPmode = SSP_MODE_I2S;
+
+	udelay(10);
+}
+
+/**
+ *  CheckHandle
+ *
+ *  If Handle is valid, returns 0.  Otherwise it returns -1.
+ */
+static int CheckHandle(int Handle)
+{
+	int iRet;
+
+	if ((Handle != KeyboardHandle) &&
+	    (Handle != I2SHandle) && (Handle != FlashHandle)) {
+		DPRINTK("OOPS! Invalid SSP Handle!\n");
+		return -1;
+	}
+
+	/*
+	 * Get the SSP driver instance number from the handle.
+	 */
+	iRet = (((int)Handle & SSP_DEVICE_MASK) >> SSP_DEVICE_SHIFT);
+
+#if 0
+	switch (iRet) {
+	case PS2_KEYBOARD:
+		DPRINTK("CheckHandle - valid - Keyboard\n");
+		break;
+
+	case I2S_CODEC:
+		DPRINTK("CheckHandle - valid - I2S\n");
+		break;
+
+	case SERIAL_FLASH:
+		DPRINTK("CheckHandle - valid - Keyboard\n");
+		break;
+	}
+#endif
+
+	return iRet;
+}
+
+/**
+ * ReadIntoBuffer
+ *
+ * Drains the SSP rx fifo into a buffer here.  If we overflow this buffer
+ * then something's wrong.
+ */
+static int ReadIntoBuffer(void)
+{
+	unsigned int count, index, saved_count, uiRegTemp;
+
+	count = 0;
+	index = 0;
+
+	if (gSSPmode != SSP_MODE_PS2)
+		return 0;
+
+	/*
+	 * This spinlock will prevent I2S from grabbing the SSP to do a
+	 * write while we are using the SSP for PS2.
+	 *
+	 * There is a slight chance that we are in the beginning phase
+	 * of doing an I2S write but the mode flag hadn't yet switched
+	 * to I2S.  If that happens we will end up waiting on I2S to
+	 * finish a write.  Not great.
+	 */
+	spin_lock(&ssp_spinlock);
+
+	while (readl(SSPSR) & SSPSR_RNE) {
+		/*
+		 * Read in the value from the SPI controller into
+		 * the partial key buffer.
+		 */
+		uiKeyBuffer[count] = readl(SSPDR);
+		if (((uiKeyBuffer[count] & 0x3fc) != 0x3e0) &&
+		    ((uiKeyBuffer[count] & 0x3fc) != 0x3c0)) {
+			/*
+			 * Set GPIO pins 12 and 14, this will bring the clock line low
+			 * which signals to the keyboard to buffer keystrokes.
+			 * Note that EGPIO 14 is the clock line and EGPIO 12 is data line.
+			 */
+			uiRegTemp = readl(GPIO_PBDR);
+			writel(0x50 | uiRegTemp, GPIO_PBDR);
+
+			writel(0, SSPCR1);
+			writel((SSPC1_MS | SSPC1_RIE | SSPC1_SSE),
+			       SSPCR1);
+
+			/*
+			 * Clear EGPIO pins 12 and 14, this will enable the SPI keyboard.
+			 */
+			uiRegTemp = readl(GPIO_PBDR);
+			writel(uiRegTemp & ~0x50, GPIO_PBDR);
+
+			count++;
+			break;
+		}
+		count++;
+	}
+
+	saved_count = count;
+	index = 0;
+	while (count) {
+		/*
+		 * No callback, dump data.
+		 */
+		if (gKeyCallback)
+			gKeyCallback(uiKeyBuffer[index++]);
+
+		count--;
+	}
+
+	spin_unlock(&ssp_spinlock);
+
+	return saved_count;
+}
+
+/**
+ * SSP_Write_I2SCodec
+ *
+ */
+static int SSP_Write_I2SCodec
+    (int Handle, unsigned int RegAddr, unsigned int RegValue) {
+	enum SSPmodes saved_mode;
+
+	DPRINTK("SSP_Write_I2SCodec\n");
+
+	spin_lock(&ssp_spinlock);
+
+	/*
+	 * Save the SSP mode.  Switch to I2S mode if we're not
+	 * already in I2S mode.
+	 */
+	saved_mode = gSSPmode;
+	SetSSPtoI2S();
+
+	/*
+	 * Let TX fifo clear out.  Poll the Transmit Fifo Empty bit.
+	 */
+	while (!(readl(SSPSR) & SSPSR_TFE)) ;
+
+	/*
+	 * Write the data out to the tx fifo.
+	 */
+	writel(0x20, SSPDR);	/* chip address for CS4228 */
+	writel((RegAddr & 0xff), SSPDR);
+	writel((RegValue & 0xff), SSPDR);
+
+	/*
+	 * Let TX fifo clear out.  Poll the Transmit Fifo Empty bit.
+	 */
+	while (!(readl(SSPSR) & SSPSR_TFE)) ;
+
+	/*
+	 * Delay to let stuff make it out of the SR before doing
+	 * anthing else to the SSP.  It takes 6.8 uSec to do a
+	 * I2S codec register write.
+	 */
+	udelay(10);
+
+	/*
+	 * If we were in PS2 mode, switch back to PS2 mode.
+	 * If we weren't in PS2 mode, that means we didn't compile in
+	 * the PS2 keyboard support, so no need to switch to PS2 mode.
+	 */
+	if (saved_mode == SSP_MODE_PS2)
+		SetSSPtoPS2();
+
+	spin_unlock(&ssp_spinlock);
+
+	return 0;
+}
diff --git a/arch/arm/mach-ep93xx/ssp.c b/arch/arm/mach-ep93xx/ssp.c
new file mode 100644
index 0000000..4e1b973
--- /dev/null
+++ b/arch/arm/mach-ep93xx/ssp.c
@@ -0,0 +1,246 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/ssp.c
+ *
+ *  Generic SSP driver. This provides shared access to the SSP
+ *  interface operating in master mode.
+ *
+ *  Copyright (C) 2004 Ray Lehtiniemi.
+ *  Copyright (C) 2004 Siconix, 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/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <asm/arch/ssp.h>
+
+/* ================================================================
+                       Front End Interface
+   ================================================================ */
+
+/***
+ * ssp_add_slave - register an ssp_slave with an ssp_master
+ * @m: the master
+ * @s: the slave
+ *
+ * Grabs the frontend lock and adds slave to list.
+ */
+int ssp_add_slave(struct ssp_master *m, struct ssp_slave *s)
+{
+	if (s->master != NULL)
+		return -EBUSY;
+	down(&m->sem);
+	list_add(&s->list, &m->slave);
+	s->master = m;
+	up(&m->sem);
+	return 0;
+}
+
+EXPORT_SYMBOL(ssp_add_slave);
+
+/***
+ * ssp_remove_slave - de-register an ssp_slave from its master
+ * @m: the master
+ * @s: the slave
+ *
+ * Grabs the frontend lock and removes slave from list.
+ */
+void ssp_remove_slave(struct ssp_master *m, struct ssp_slave *s)
+{
+	if (s->master != m)
+		return;
+	down(&m->sem);
+	list_del(&s->list);
+	s->master = NULL;
+	up(&m->sem);
+}
+
+EXPORT_SYMBOL(ssp_remove_slave);
+
+/***
+ * ssp_do - perform a single SSP transaction on the slave
+ * @s: the slave
+ * @len: the number of words to transfer
+ * @tx: a buffer of @len words to clock out to slave
+ * @rx: a buffer of @len words to clock in from slave
+ *
+ * Grabs the frontend lock, configures the ssp master as required
+ * by the slave, asserts the slave devices chip select line, and
+ * schedules the backend to perform the transfer.
+ *
+ * Once the backend signals completion, the chip select is negated
+ * and the frontend lock is released.
+ *
+ * The backend will transfer @len * @s->nbytes from @tx and
+ * into @rx.  Make sure your buffers are big enough! If @tx
+ * or @rx are null, then null data will be clocked in and/or out.
+ */
+int ssp_do(struct ssp_slave *s, int len, void *tx, void *rx)
+{
+	int err;
+
+	if ((err = ssp_start(s)) < 0)
+		goto out1;
+
+	ssp_select(s);
+
+	if ((err = ssp_post(s, len, tx, rx)) < 0)
+		goto out2;
+
+	err = ssp_wait(s);
+
+      out2:
+	ssp_deselect(s);
+	ssp_finish(s);
+      out1:
+	return err;
+}
+
+EXPORT_SYMBOL(ssp_do);
+
+/* ================================================================
+                       Transaction Interface
+   ================================================================ */
+
+static int __ssp_txn_start(struct ssp_slave *s);
+
+/***
+ * ssp_start - Grab and configure the SSP bus (blocking)
+ * @s: the slave
+ *
+ * This call will grab and initialize the SSP bus, blocking
+ * until the bus is ready.
+ */
+int ssp_start(struct ssp_slave *s)
+{
+	down(&s->master->sem);
+	return __ssp_txn_start(s);
+}
+
+EXPORT_SYMBOL(ssp_start);
+
+/***
+ * ssp_trystart - Grab and configure the SSP bus (non-blocking)
+ * @s: the slave
+ *
+ * This call will grab and initialize the SSP bus, returning
+ * with an error if the bus is not free.
+ */
+int ssp_trystart(struct ssp_slave *s)
+{
+	if (!down_trylock(&s->master->sem))
+		return -EBUSY;
+	return __ssp_txn_start(s);
+}
+
+EXPORT_SYMBOL(ssp_trystart);
+
+static int __ssp_txn_start(struct ssp_slave *s)
+{
+	return s->master->ops->configure(s);
+}
+
+/***
+ * ssp_select - assert the slave CS line
+ * @s: the slave
+ *
+ * assert the device-specific CS line
+ */
+void ssp_select(struct ssp_slave *s)
+{
+	s->chip_select(s, 1);
+}
+
+EXPORT_SYMBOL(ssp_select);
+
+/***
+ * ssp_post - start the backend for the slave's master
+ * @s: the slave
+ *
+ * Start the backend data transfer for this master.
+ */
+int ssp_post(struct ssp_slave *s, int len, void *tx, void *rx)
+{
+	struct ssp_transfer *t;
+
+	t = &s->master->transfer;
+
+	t->size = s->nbytes;
+	t->len = len;
+	t->rlen = len;
+	t->tx = tx;
+	t->rx = rx;
+	t->c = &s->master->completion;
+	init_completion(t->c);
+
+	return s->master->ops->enable(t);
+}
+
+EXPORT_SYMBOL(ssp_post);
+
+/***
+ * ssp_wait - block until the SP transfer is complete
+ * @s: the slave
+ *
+ * block until the SP transfer is complete.
+ */
+int ssp_wait(struct ssp_slave *s)
+{
+	wait_for_completion(&s->master->completion);
+	return s->master->ops->disable();
+}
+
+EXPORT_SYMBOL(ssp_wait);
+
+/***
+ * ssp_deselect - assert the slave CS line
+ * @s: the slave
+ *
+ * negate the device-specific CS line
+ */
+void ssp_deselect(struct ssp_slave *s)
+{
+	s->chip_select(s, 0);
+}
+
+EXPORT_SYMBOL(ssp_deselect);
+
+/***
+ * ssp_finish - release the ssp bus
+ * @s: the slave
+ *
+ * Releases the frontend lock.
+ */
+void ssp_finish(struct ssp_slave *s)
+{
+	up(&s->master->sem);
+}
+
+EXPORT_SYMBOL(ssp_finish);
+
+/* ================================================================
+                       Module Stuff
+   ================================================================ */
+
+int __init ssp_init(void)
+{
+	printk(KERN_INFO "Generic SSP Support version 0.1\n");
+	return 0;
+}
+
+void __exit ssp_exit(void)
+{
+}
+
+module_init(ssp_init);
+module_exit(ssp_exit);
+
+MODULE_AUTHOR("Ray Lehtiniemi");
+MODULE_DESCRIPTION("Generic SSP driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ep93xx/ssp2.c b/arch/arm/mach-ep93xx/ssp2.c
new file mode 100644
index 0000000..6a4ff10
--- /dev/null
+++ b/arch/arm/mach-ep93xx/ssp2.c
@@ -0,0 +1,354 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/ssp.c
+ *
+ *  EP93xx SSP driver. This provides shared access to the SSP
+ *  interface operating in master mode.
+ *
+ *  Copyright (C) 2004 Ray Lehtiniemi.
+ *  Copyright (C) 2004 Siconix, 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/ssp.h>
+#include <asm/arch/ssp2.h>
+
+/* print out all chars tx, rx, and dropped */
+#define _(x...)			/* printk(KERN_WARNING x); printk("\n") */
+
+/* the current transfer */
+static struct ssp_transfer *transfer;
+
+/* stupid SSP gives rx int only when rx fifo > half full :-P */
+static void do_rx_poll(void *x);
+static DECLARE_WORK(work, do_rx_poll, NULL);
+
+/* also implement a timeout in the worker, to prevent hard lockups
+   if something goes south... */
+static int timeout;
+
+/* serialize the rx irq and the work poller routines */
+static spinlock_t spinlock = SPIN_LOCK_UNLOCKED;
+
+/* ----------------- Hardware Control --------------------- */
+
+/* send a word */
+static __inline__ void x_ssp_send(__u16 dat)
+{
+	writel(dat, SSPDR);
+	_("\ttx %08x", dat);
+}
+
+/* send a word to clock the recv */
+static __inline__ void x_ssp_clock(void)
+{
+	writel(0, SSPDR);
+	_("\tt- --------");
+}
+
+/* recv a word */
+static __inline__ __u16 x_ssp_recv(void)
+{
+	unsigned long dat = readl(SSPDR);
+	_("\trx %08lx", dat);
+	return dat & 0xffff;
+}
+
+/* discard a word */
+static __inline__ void x_ssp_discard(void)
+{
+#if 1
+	unsigned long dat = readl(SSPDR);
+	_("\tr- %08lx  (discard)", dat);
+#else
+	(void)readl(SSPDR);
+	_("\tr- --------");
+#endif
+}
+
+/* are there chars in the rx fifo? */
+static __inline__ int x_ssp_available(void)
+{
+	return (readl(SSPSR) & SSPSR_RNE) ? 1 : 0;
+}
+
+/* is there room in the tx fifo? */
+static __inline__ int x_ssp_has_room(void)
+{
+	return (readl(SSPSR) & SSPSR_TNF) ? 1 : 0;
+}
+
+/* is the transmitter busy? */
+static __inline__ int x_ssp_busy(void)
+{
+	return (readl(SSPSR) & SSPSR_BSY) ? 1 : 0;
+}
+
+/* flush the RX and TX fifos */
+static void x_ssp_flush(void)
+{
+	do {
+		while (x_ssp_available())
+			x_ssp_discard();
+	} while (x_ssp_busy());
+
+	/* just in case there is a race... in any event, this should be harmless */
+	x_ssp_discard();
+}
+
+/* set up all regs as required by the slave */
+static void x_ssp_configure(struct ep93xx_ssp_slave *s)
+{
+	writel(s->cr1, SSPCR1);
+	writel(s->cr0, SSPCR0);
+	writel(s->cpsr, SSPCPSR);
+	writel(s->cr1 & ~SSPC1_SSE, SSPCR1);
+	writel(s->cr1, SSPCR1);
+}
+
+/* enable chip select and all ints */
+static __inline__ void x_ssp_enable(void)
+{
+	unsigned long x = readl(SSPCR1);
+	writel(x | SSPC1_TIE | SSPC1_RIE | SSPC1_RORIE, SSPCR1);
+}
+
+/* disable chip select and all ints */
+static __inline__ void x_ssp_disable(void)
+{
+	unsigned long x = readl(SSPCR1);
+	writel(x & ~(SSPC1_TIE | SSPC1_RIE | SSPC1_RORIE), SSPCR1);
+}
+
+/* disable tx int */
+static __inline__ void x_ssp_stop_tx(void)
+{
+	unsigned long x = readl(SSPCR1);
+	writel(x & ~SSPC1_TIE, SSPCR1);
+}
+
+/* ---------------------- Master Methods ------------------------- */
+
+static int ep93xx_ssp_configure(struct ssp_slave *ss)
+{
+	struct ep93xx_ssp_slave *s = (struct ep93xx_ssp_slave *)ss;
+	_("SSP transfer");
+	x_ssp_configure(s);
+	return 0;
+}
+
+static int ep93xx_ssp_enable(struct ssp_transfer *t)
+{
+	_("{");
+	transfer = t;
+	timeout = 0;
+	schedule_delayed_work(&work, 1);
+	x_ssp_enable();
+	return 0;
+}
+
+static int ep93xx_ssp_disable(void)
+{
+	x_ssp_disable();
+	cancel_delayed_work(&work);
+	transfer = NULL;
+	_("}");
+	return 0;
+}
+
+static struct ssp_master_ops my_ops = {
+	.configure = ep93xx_ssp_configure,
+	.enable = ep93xx_ssp_enable,
+	.disable = ep93xx_ssp_disable,
+};
+
+/* ----------------- Registration Stuff FIXME ------------- */
+
+#include <linux/completion.h>
+#include <asm/types.h>
+#include <asm/semaphore.h>
+
+struct ssp_master ep93xx_ssp_master = {
+	__MUTEX_INITIALIZER(ep93xx_ssp_master.sem),
+	COMPLETION_INITIALIZER(ep93xx_ssp_master.completion),
+	LIST_HEAD_INIT(ep93xx_ssp_master.slave),
+	{
+	 0,
+	 0,
+	 0,
+	 NULL,
+	 NULL,
+	 NULL},
+	&my_ops
+};
+
+EXPORT_SYMBOL(ep93xx_ssp_master);
+
+/* -------------------- Bottom Half ----------------------- */
+
+static void do_tx(void)
+{
+	if (transfer == NULL) {
+		printk(KERN_WARNING "Null tx transfer...\n");
+		return;
+	}
+
+	while (transfer->len != 0) {
+
+		if (!x_ssp_has_room())
+			return;
+
+		if (transfer->tx == NULL) {
+			x_ssp_clock();
+
+		} else if (transfer->size == 1) {
+			__u8 *t = transfer->tx;
+			x_ssp_send(*t);
+			transfer->tx += 1;
+
+		} else if (transfer->size == 2) {
+			__u16 *t = transfer->tx;
+			x_ssp_send(*t);
+			transfer->tx += 2;
+
+		} else if (transfer->size == 4) {
+			__u32 *t = transfer->tx;
+			x_ssp_send(*t);
+			transfer->tx += 4;
+		}
+
+		transfer->len--;
+	}
+
+	x_ssp_stop_tx();
+}
+
+static void __do_rx(void)
+{
+	if (transfer == NULL) {
+		printk(KERN_WARNING "Null rx transfer...\n");
+		return;
+	}
+
+	while (transfer->rlen != 0) {
+
+		if (!x_ssp_available())
+			return;
+
+		if (transfer->rx == NULL) {
+			x_ssp_discard();
+
+		} else if (transfer->size == 1) {
+			__u8 *t = transfer->rx;
+			*t = x_ssp_recv();
+			transfer->rx += 1;
+
+		} else if (transfer->size == 2) {
+			__u16 *t = transfer->rx;
+			*t = x_ssp_recv();
+			transfer->rx += 2;
+
+		} else if (transfer->size == 4) {
+			__u32 *t = transfer->rx;
+			*t = x_ssp_recv();
+			transfer->rx += 4;
+		}
+
+		transfer->rlen--;
+		timeout = 0;
+	}
+
+	complete(transfer->c);
+}
+
+static void do_rx(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&spinlock, flags);
+	__do_rx();
+	spin_unlock_irqrestore(&spinlock, flags);
+}
+
+static void do_rx_poll(void *x)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&spinlock, flags);
+	__do_rx();
+	timeout++;
+	if (timeout == 100) {
+		x_ssp_disable();
+		complete(transfer->c);
+	} else {
+		schedule_delayed_work(&work, 1);
+	}
+	spin_unlock_irqrestore(&spinlock, flags);
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int status = readl(SSPIIR);
+
+	if (transfer == NULL) {
+		printk(KERN_WARNING "SSP: no active transfer\n");
+		x_ssp_flush();
+		x_ssp_disable();
+	}
+
+	if (status & SSPIIR_RORIS)
+		printk(KERN_WARNING "SSP: receiver overrun\n");
+
+	if (status & SSPIIR_TIS)
+		do_tx();
+
+	if (status & SSPIIR_RIS)
+		do_rx();
+
+	writel(0, SSPICR);
+
+	return status ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/* -------------------- Module Stuff ---------------------- */
+
+int __init ep93xx_ssp_init(void)
+{
+	int i;
+
+	if (readl(SYSCON_DEVCFG) & SYSCON_DEVCFG_I2SonSSP)
+		return -ENODEV;
+
+	i = request_irq(IRQ_SSP, irq_handler, 0, "SSP", NULL);
+
+	if (i)
+		printk(KERN_ERR
+		       "EP93XX: unable to grab SSP interrupt, error %d\n", i);
+
+	printk(KERN_INFO "EP93xx SSP driver version 0.1\n");
+	return 0;
+}
+
+void __exit ep93xx_ssp_exit(void)
+{
+	free_irq(IRQ_SSP, NULL);
+}
+
+module_init(ep93xx_ssp_init);
+module_exit(ep93xx_ssp_exit);
+
+MODULE_AUTHOR("Ray Lehtiniemi");
+MODULE_DESCRIPTION("EP93xx SSP driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ep93xx/time.c b/arch/arm/mach-ep93xx/time.c
new file mode 100644
index 0000000..459a179
--- /dev/null
+++ b/arch/arm/mach-ep93xx/time.c
@@ -0,0 +1,40 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/time.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions
+ *
+ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA.  All rights reserved.
+ *  Copyright (C) 2002-2003 Cirrus Logic, 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/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+extern int (*set_rtc) (void);
+
+static int ep93xx_set_rtc(void)
+{
+	writel(xtime.tv_sec, RTCLR);
+	return 1;
+}
+
+static int ep93xx_rtc_init(void)
+{
+	writel(0, RTCCR);
+	writel(0, RTCEOI);
+
+	writel(xtime.tv_sec, RTCDR);
+
+	set_rtc = ep93xx_set_rtc;
+
+	return 0;
+}
+
+__initcall(ep93xx_rtc_init);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index e84fdde..85c90bf 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -62,8 +62,8 @@ config CPU_ARM720T
 # ARM920T
 config CPU_ARM920T
 	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
-	default y if ARCH_S3C2410
+	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000  || ARCH_EP93XX
+	default y if ARCH_S3C2410 || ARCH_EP93XX
 	select CPU_32v4
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 8b276ee..cc8aedb 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -212,6 +212,10 @@ static __init void reserve_node_zero(pg_
 	if (machine_is_integrator() || machine_is_cintegrator())
 		res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
 
+	/* TBD vector table and initial stack below pg_dir */
+	if (machine_is_edb9301() || machine_is_edb9312() || machine_is_edb9315() || machine_is_acc())
+		res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
+
 	/*
 	 * These should likewise go elsewhere.  They pre-reserve the
 	 * screen memory region at the start of main system memory.
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 84e68cd..c4a267b 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,6 +4,16 @@
 
 menu "Character devices"
 
+config TTML_DEVICES
+	tristate "TTML TripDawg system devices"
+	depends on MACH_TTML
+	default m
+	---help---
+	  If you say y or m here, you will get several character devices
+	  which allow you to use the LEDs, buzzer, speedometer, and so
+	  on. These devices are mapped into the 10,{240-254} range, which
+	  is reserved for local devices.
+
 config VT
 	bool "Virtual terminal" if EMBEDDED
 	select INPUT
@@ -762,6 +772,26 @@ config EFI_RTC
 	bool "EFI Real Time Clock Services"
 	depends on IA64
 
+config EP93XX_RTC
+	bool "Cirrus EP93xx Real Time Clock support"
+	depends on ARCH_EP93XX
+	help
+	  Provides EFI and legacy RTC support on the Cirrus EP93xx family of
+	  devices via the /dev/rtc character node (10/135).
+
+config DS1337_RTC
+	tristate "Dallas Semiconductor DS1337 Real Time Clock /dev/rtc interface"
+	depends on I2C && EXPERIMENTAL && !EP93XX_RTC
+	select SENSORS_DS1337
+	help
+	  Say Y here you have got a DS1337 real time clock on your I2C bus.
+	  This here is just an interface to access it via the /dev/rtc
+	  character node (10/135).  All the hard work will be done
+	  in the I2C driver (drivers/i2c/chips/ds1337.c).
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ds1337glue.
+
 config DS1302
 	tristate "DS1302 RTC support"
 	depends on M32R && (PLAT_M32700UT || PLAT_OPSPUT)
@@ -893,6 +923,8 @@ source "drivers/char/drm/Kconfig"
 
 source "drivers/char/pcmcia/Kconfig"
 
+source "drivers/char/can/Kconfig"
+
 config MWAVE
 	tristate "ACP Modem (Mwave) support"
 	depends on X86
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 4aeae68..579570d 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni
 
 obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
 
+obj-$(CONFIG_TTML_DEVICES)	+= ttml.o
 obj-$(CONFIG_LEGACY_PTYS)	+= pty.o
 obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
 obj-y				+= misc.o
@@ -65,6 +66,8 @@ obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
 obj-$(CONFIG_DS1302) += ds1302.o
 obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
 obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
+obj-$(CONFIG_EP93XX_RTC) += ep93xx-rtc.o
+obj-$(CONFIG_DS1337_RTC)	+= ds1337glue.o
 ifeq ($(CONFIG_GENERIC_NVRAM),y)
   obj-$(CONFIG_NVRAM) += generic_nvram.o
 else
@@ -119,3 +122,6 @@ $(obj)/defkeymap.c $(obj)/qtronixmap.c: 
 	rm $@.tmp
 
 endif
+
+obj-$(CONFIG_CAN_BUS) += can/
+
diff --git a/drivers/char/can/Kconfig b/drivers/char/can/Kconfig
new file mode 100644
index 0000000..9834c66
--- /dev/null
+++ b/drivers/char/can/Kconfig
@@ -0,0 +1,46 @@
+#
+# CAN bus character devices configuration
+#
+
+menu "CAN bus devices"
+
+config CAN_BUS
+	bool "CAN bus character devices"
+	help
+	  If you say y here, you will get support for CAN bus
+	  character device drivers.
+
+config OKI_CAN_ML9620
+	tristate "OKI ML9620 CAN BUS"
+	depends on CAN_BUS
+	help
+	  If you say y or m here, you will get support for OKI ML9620
+	  character device based CAN driver for one CAN bus.
+
+choice
+	prompt "OKI ML9620 configuration"
+	depends on OKI_CAN_ML9620
+	help
+	 Specific configuration for OKI ML9620 configuration.
+
+config OKI_CAN_ML9620_MICRO9
+	bool "OKI ML9620 Contec Hypercontrol Micro9 configuration"
+	depends on OKI_CAN_ML9620
+	help
+	 Select this if you have Contec Hypercontrol Micro9 board.
+
+config OKI_CAN_ML9620_GASSNER
+	bool "OKI ML9620 Gassner configuration"
+	help
+         Select this if you want to have Gassner specific changes.
+
+endchoice
+
+config OKI_CAN_ML9620_2DEV
+	bool "OKI ML9620 CAN BUS 2nd DEVICE"
+	depends on OKI_CAN_ML9620
+	help
+	 If you say y here, you will get support for a second
+	 OKI ML9620 CAN bus.
+
+endmenu
diff --git a/drivers/char/can/Makefile b/drivers/char/can/Makefile
new file mode 100644
index 0000000..f9bcf2a
--- /dev/null
+++ b/drivers/char/can/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for CAN BUS character devices
+#
+obj-$(CONFIG_OKI_CAN_ML9620) += oki_ml9620.o
diff --git a/drivers/char/can/oki_ml9620.c b/drivers/char/can/oki_ml9620.c
new file mode 100644
index 0000000..d60cca4
--- /dev/null
+++ b/drivers/char/can/oki_ml9620.c
@@ -0,0 +1,1006 @@
+/*
+ * drivers/char/can/oki_ml9620_core.c
+ *
+ * OKI ML9620 CAN Controler driver
+ *
+ * Author: Manfred Gruber <manfred.gruber@contec.at>
+ *
+ * Copyright 2004 (c) Manfred Gruber
+ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
+ * Kufstein/Austria   www.contec.at
+ *
+ * This driver was written for Contec Hypercontrol Micro9 Board:
+ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
+ * 2. CAN Controller is on Hypercontrol Micro9 Eval board
+ *
+ * Contec uses this driver on their Hypercontrol Micro9 boards based on
+ * Cirrus Logic EP93XX, we have changed Adr-/Databus timing to use OKI ML9620.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ */
+
+/*Versions:
+  - 0.01 Inital version Only worked CAN1
+  - 0.02 CAN1/CAN2 worked, EVAL-board and CPU-BOARD Micro9
+  - 0.03 changes from Michael Burian to correct:
+         errors, functions, adr/databus-problems - thanks a lot Michael
+         changed to correct name oki_ml9620_X and put in drivers/char/can/
+         deleted some wrong statements
+  - 0.04 Michael Burian: read/write expect/return count in bytes now, cleanups
+  - 0.05 Michael Burian: use mux'd IRQs for both devices now 
+  - 0.06 Michael Burian: only queue messages when /dev/can[01] is open
+  - 0.07 Michael Burian: implement non-blocking read
+  - 0.08 Michael Burian: replace completion with waitq, implement poll support
+*/
+
+/*Todo:
+  - Baudrate over /proc configure
+  - remove potential infinite loop in write / make write return immediately 
+    (no longer wait for hardware, do this in background)
+  - implement fsync to allow waiting till hardware has written, if desired
+  - implement poll for write
+  - implement buffered write
+  - use kfifo for buffering read
+  - use kfifo for buffering write
+  - look for a more elegant solution for 
+*/
+
+/* Enable for debugging */
+/*#define OKI_DEBUG */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/major.h>
+#include <linux/config.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/stddef.h>	/* offsetof(), etc. */
+#include <linux/completion.h>
+#include <linux/poll.h>
+#include <linux/can/oki_ml9620_ctrl.h>
+#include <asm/segment.h>
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/arch/regmap.h>
+#include "oki_ml9620.h"
+
+/* fops		        */
+static int oki_read(struct file *file, char *buf, size_t count,loff_t *ppos);
+static int oki_write(struct file *file, const char *buf, size_t count,loff_t *ppos);
+static int oki_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+static int oki_open(struct inode *inode, struct file *file);
+static int oki_release(struct inode *inode, struct file *file);
+static unsigned int oki_poll(struct file *file, poll_table *wait);
+
+/* IRQ  */
+static irqreturn_t oki_irqhandler(int irq, void *dev_id, struct pt_regs *regs);
+
+/* CAN */
+static void hw_init(struct can_device *c);
+static int set_baudrate(struct can_device *c, int baud);
+static int check_status(struct can_device *c);
+static int activate(struct can_device *c, unsigned char new_status);
+static void store_data_in_buffer(struct can_device *c, struct can_msg *data);
+
+void store_data_in_buffer(struct can_device *c, struct can_msg *data)
+{
+	/* No need to fill up the queue when nobody cares. */
+	if (atomic_read(&c->can_opened))
+		return;
+	
+	DBG_OKI(KERN_INFO, "DATA Stored: ID 0x%x dlc 0x%x rtr 0x%x ext 0x%x DATA: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",data->id,data->dlc,data->rtr,data->ext,data->data[0],data->data[1],data->data[2],data->data[3],data->data[4],data->data[5],data->data[6],data->data[7]);
+
+	if (memcpy(&c->tail->msg, data, sizeof(struct can_msg)) != NULL) {
+		c->tail->next = kmalloc(sizeof(struct recbuf), GFP_KERNEL);
+		if (c->tail->next != NULL) {
+			c->tail->next->prev = c->tail;
+			c->tail = c->tail->next;
+			/* up sema to allow read */
+			wake_up_interruptible(&c->rx_waitq);
+			return;
+		}
+	}
+}
+
+int set_baudrate(struct can_device *c, int baud)
+{
+	unsigned long v = (unsigned long)c->virt_addr_can;
+	int index = 0;
+
+	/* unlock hardware */
+	c->reg.cancont = readb(v + CANCONT);
+	c->reg.cancont |= CONT_FLAG_INIT;
+	writeb(c->reg.cancont, v + CANCONT);
+
+	c->reg.cancont = readb(v + CANCONT);
+	c->reg.cancont |= CONT_FLAG_CCE;
+	writeb(c->reg.cancont, v + CANCONT);
+
+	DBG_OUT(KERN_DEBUG, ": /dev/can%d set_baudrate %dkb\n", c->minor, baud);
+
+	/* Lookuptable baudrate => Timing array index */
+	switch (baud){
+	case 10:	index = 0; break;
+	case 20:	index = 1; break;
+	case 50:	index = 2; break;
+	case 100:	index = 3; break;
+	case 125:	index = 4; break;
+	case 250:	index = 5; break;
+	case 500:	index = 6; break;
+	case 800:	index = 7; break;
+	case 1000:	index = 8; break;
+	default:	index = 4; break;
+	}
+
+	/* set baudrate */
+	c->reg.canbitt[0] = bd_tbl[index].btiming0;
+	c->reg.canbitt[1] = bd_tbl[index].btiming1;
+	c->reg.canbpre = bd_tbl[index].bpre;
+	writeb(c->reg.canbitt[0], v + CANBITT0);
+	writeb(c->reg.canbitt[1], v + CANBITT1);
+	writeb(c->reg.canbpre, v + CANBPRE);
+
+	/* lock hardware */
+	c->reg.cancont = readb(v + CANCONT);
+	c->reg.cancont &= ~CONT_FLAG_CCE;
+	writeb(c->reg.cancont, v + CANCONT);
+
+	c->reg.cancont = readb(v + CANCONT);
+	c->reg.cancont &= ~CONT_FLAG_INIT;
+	writeb(c->reg.cancont, v + CANCONT);
+
+	return baud;
+}
+
+void hw_init(struct can_device *c)
+{
+	unsigned char i;
+	unsigned long v = (unsigned long)c->virt_addr_can;
+
+	spin_lock_init(&c->can_lock);
+
+	c->reg.cancont |= CONT_FLAG_INIT;
+	writeb(c->reg.cancont, v + CANCONT);
+
+	/* All Messages disabled with MsgVal = 0 */
+	c->reg.if1id[3] = 0x00;
+	writeb(c->reg.if1id[3], v + IF1ID3);
+
+	/* set, so that ID Register will get transfered */
+	c->reg.if1cmask = 0x38;
+	writeb(c->reg.if1cmask, v + IF1CMASK);
+
+	for (i = 1; i < (NUM_MSG + 1); i++) {
+		while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
+		c->reg.if1creq = i;
+		writeb(c->reg.if1creq, v + IF1CREQ);
+	}
+
+	for (i = CAN_STD_RX_BUFFER_START; i < (CAN_STD_RX_BUFFER_END + 1); i++) {
+		c->reg.if1id[3] = 0x80;
+		writeb(c->reg.if1id[3], v + IF1ID3);
+
+		c->reg.if1id[2] = 0x00;
+		writeb(c->reg.if1id[2], v + IF1ID2);
+
+		/*c->reg.if1mask[3] = 0x00; */
+		c->reg.if1mask[3] = 0x20;
+		writeb(c->reg.if1mask[3], v + IF1MASK3);
+
+		c->reg.if1mask[2] = 0x00;
+		writeb(c->reg.if1mask[2], v + IF1MASK2);
+
+		/* Transfer Controll u. ID bits */
+		c->reg.if1cmask = 0xF8;
+		writeb(c->reg.if1cmask, v + IF1CMASK);
+
+		if (i == CAN_STD_RX_BUFFER_END) {
+			c->reg.if1mcont[0] = 0x80;	/* FIFO END */
+			writeb(c->reg.if1mcont[0], v + IF1MCONT0);
+		} else {
+			c->reg.if1mcont[0] = 0x00;
+			writeb(c->reg.if1mcont[0], v + IF1MCONT0);
+		}
+
+		c->reg.if1mcont[1] = 0x14;	/* this MsgObj trig. Int on Rx */
+		writeb(c->reg.if1mcont[1], v + IF1MCONT1);
+
+		c->reg.if1creq = i;
+		writeb(c->reg.if1creq, v + IF1CREQ);
+
+		while ((c->reg.if1busy = readb(v + IF1BUSY) & 0x80)) ;
+	}
+
+	/* Extended Frames */
+	c->reg.if1id[3] = 0xC0;
+	writeb(c->reg.if1id[3], v + IF1ID3);
+
+	c->reg.if1id[2] = 0x00;
+	writeb(c->reg.if1id[2], v + IF1ID2);
+
+	c->reg.if1id[1] = 0x00;
+	writeb(c->reg.if1id[1], v + IF1ID1);
+
+	c->reg.if1id[0] = 0x00;
+	writeb(c->reg.if1id[0], v + IF1ID0);
+
+	c->reg.if1mask[3] = 0x00;
+	writeb(c->reg.if1mask[3], v + IF1MASK3);
+
+	c->reg.if1mask[2] = 0x00;
+	writeb(c->reg.if1mask[2], v + IF1MASK2);
+
+	c->reg.if1mask[1] = 0x00;
+	writeb(c->reg.if1mask[1], v + IF1MASK1);
+
+	c->reg.if1mask[0] = 0x00;
+	writeb(c->reg.if1mask[0], v + IF1MASK0);
+
+	/* Transfer Control and ID bits */
+	c->reg.if1cmask = 0xF8;
+	writeb(c->reg.if1cmask, v + IF1CMASK);
+
+	c->reg.if1mcont[0] = 0x80;	/* EOB = 1 */
+	writeb(c->reg.if1mcont[0], v + IF1MCONT0);
+
+	c->reg.if1mcont[1] = 0x14;	/* this MsgObj trig. Int on Rx */
+	writeb(c->reg.if1mcont[1], v + IF1MCONT1);
+
+	c->reg.if1creq = CAN_EXT_RX_BUFFER;
+	writeb(c->reg.if1creq, v + IF1CREQ);
+
+	/* Wait till everything has been written */
+	while ((c->reg.if1busy = readb(v + IF1BUSY) & 0x80)) ;
+
+	c->reg.cancont = readl(v + CANCONT);
+	c->reg.cancont |= CONT_FLAG_IE + CONT_FLAG_SIE + CONT_FLAG_EIE;
+	writeb(c->reg.cancont, v + CANCONT);
+
+	/*End Init */
+	c->reg.cancont = readb(v + CANCONT);
+	c->reg.cancont &= ~CONT_FLAG_INIT;
+	writeb(c->reg.cancont, v + CANCONT);
+
+	/* store baudrate default 125 kBit/sec */
+	c->baudrate = (unsigned short)set_baudrate(c, 125);
+
+	/* reset overrun counter */
+	c->overrun = 0;
+}
+
+static irqreturn_t oki_irqhandler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned short int_type = 0;
+	unsigned short i;
+	unsigned char stat_reg, k;
+	struct can_msg msg;
+	struct can_device *c = dev_id;
+	unsigned long v = (unsigned long)c->virt_addr_can;
+	int minor = c->minor;
+	unsigned long flags;
+	int irq_count = 0;
+
+	spin_lock_irqsave(&c->can_lock, flags);
+
+	/*
+	 * read can interrupt register1,
+	 * we only want to detect if it is a status interrupt!
+	 */
+	int_type += (readb(v + CANINT1) << 8);
+
+	DBG_OKI(KERN_ERR, ": /dev/can%d IRQ 0x%x occured, virt addr:0x%08x\n",minor,int_type,v);
+
+	/* STATUS IRQ    */
+	if (int_type & 0x8000) {
+		c->reg.canstat = stat_reg = readb(v + CANSTAT);
+		c->reg.canstat = 0x00;
+		writeb(c->reg.canstat, v + CANSTAT);
+
+		DBG_OKI(KERN_ERR, "/dev/can%d IRQ is STATUS IRQ BSTAT is 0x%x\n",minor,stat_reg);
+
+		/*if ((stat_reg & 0xE0) == 0xE0) */
+		/* changed back to get bus off state */
+		if ((stat_reg & 0x80) == 0x80) {
+			DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is BUS OFF\n",minor);
+			/* set "Bus off" flag  */
+			c->status |= CAN_STS_BUS_OFF;
+			/* clear flag */
+			c->status &= ~CAN_STS_TXOK;
+
+			c->last_error_code = 10;
+		} else {
+			/* clear "Bus off" flag  */
+			c->status &= ~CAN_STS_BUS_OFF;
+		}
+
+		if ((stat_reg & 0x60) == 0x60) {
+			DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS CAN_STS_WARNING %x \n",minor,(stat_reg & 0x7));
+			c->last_error_code = (stat_reg & 0x7);
+			/* set WARNING flag  */
+			c->status |= CAN_STS_WARNING;
+		} else {
+			/* clear WARNING flag  */
+			c->status &= ~CAN_STS_WARNING;
+		}
+
+		/* TXOK */
+		if ((stat_reg & 0x08) == 0x08) {
+			DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS TXOK\n",minor);
+
+			/* clear error */
+			c->last_error_code_write = 0;
+			/* clear error --> no error  */
+			c->last_error_code = 0;
+			/* clear error var for debug */
+			c->last_error_code_debug = 0;
+		}
+
+		/* ROK */
+		if ((stat_reg & 0x10) == 0x10) {
+			DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS IRQ RXOK\n",minor);
+
+			/* clear error --> no error  */
+			c->last_error_code = 0;
+			/* clear error var for debug */
+			c->last_error_code_debug = 0;
+		}
+
+		if((c->last_error_code >= 1 && c->last_error_code <= 7) || c->last_error_code == 10){
+			if(c->last_error_code < 10 && ((stat_reg & 0x80) == 0x80) && (c->last_error_code != c->last_error_code_debug)){
+				c->last_error_code_debug = 10;
+				DBG_OUT(KERN_ERR, ": /dev/can%d Error BUS OFF, do ioctl STATUS\n",minor);
+
+			}
+
+			if (c->last_error_code != c->last_error_code_debug) {
+				c->last_error_code_debug = c->last_error_code;
+				DBG_OUT(KERN_ERR, ": /dev/can%d %s\n",minor,err[c->last_error_code]);
+			}
+
+			if (c->last_error_code > 0) {
+				/* switch off controller, warning state is higher than 1 */
+				/* so CAN message has a form error or was not  */
+				/* acknwledged by other devices or we are in bus off state */
+				activate(c, CAN_STS_CNTRL_OFF);
+			}
+			goto out;
+		}
+
+		DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS IRQ END \n",minor);
+	}
+
+	/* read next IRQ */
+	/* only read can interrupt register0, we don't want detect a status interrupt here! */
+	int_type = readb(v + CANINT0);
+
+	while (int_type && (irq_count++ < OKI_CAN_MAX_IRQS)) {
+		switch (int_type) {
+		case CAN_TX_BUFFER:
+		case CAN_RTX_BUFFER:
+
+			DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_TX_BUFFER/CAN_RTX_BUFFER IRQ 0x%x\n",minor,int_type);
+			while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
+
+			/* Clear Int Pnd */
+			c->reg.if1cmask = 0x08;
+			writeb(c->reg.if1cmask, v + IF1CMASK);
+
+			c->reg.if1creq = (unsigned char)int_type;
+			writeb(c->reg.if1creq, v + IF1CREQ);
+
+			CAN_DEBUG(IF1CMASK,"CAN_TX_BUFFER/CAN_RTX_BUFFER IF1CMASK");
+			CAN_DEBUG(IF1CREQ,"CAN_TX_BUFFER/CAN_RTX_BUFFER IF1CREQ");
+
+			/* Wait till everything has been written */
+			while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
+			c->status |= CAN_STS_TXOK;
+			c->tx_in_progress = 0;
+			DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_TX_BUFFER/CAN_RTX_BUFFER IRQ 0x%x END\n",minor,int_type);
+			break;
+		case CAN_STD_RX_BUFFER_START:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case CAN_STD_RX_BUFFER_END:
+			DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_STD_RX_BUFFER_START/CAN_STD_RX_BUFFER_END IRQ 0x%x\n",minor,int_type);
+			do {
+				while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
+				/* Get all unsigned chars */
+				c->reg.if2cmask = 0x3F;
+				writeb(c->reg.if2cmask, v + IF2CMASK);
+				c->reg.if2creq = (unsigned char)int_type;
+				writeb(c->reg.if2creq, v + IF2CREQ);
+
+				/* Wait till everything has been written */
+				while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
+				/* is NewData set? */
+				if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x80) {
+					/* Extended Frame? */
+					if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x40)
+						msg.ext = 1;
+					else
+						msg.ext = 0;
+
+					msg.dlc = ((c->reg.if2mcont[0] = readb(v + IF2MCONT0)) & 0x0F);
+					msg.id = (((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x1F) << 6);
+					msg.id += ((c->reg.if2id[2] = readb(v + IF2ID2)) >> 2);
+
+					k = (unsigned char)((msg.dlc <= 8) ? (msg.dlc) : 8);
+					for (i = 0; i < k; i++)
+						msg.data[i] = c->reg.if2data[i] = readb(v + IF2DATA0 +i);
+
+					/* Is MsgLost set? */
+					if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x40)
+						c->status |= CAN_STS_OVERRUN;
+					else
+						c->status &= ~CAN_STS_OVERRUN;
+					/* is DIR set? */
+					if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x20)
+						msg.rtr = 1;
+					else
+						msg.rtr = 0;
+					/* clear MsgLst */
+					c->reg.if2mcont[1] &= 0xBF;
+					writeb(c->reg.if2mcont[1], v + IF2MCONT1);
+					c->reg.if2cmask = 0x10;
+					writeb(c->reg.if2cmask, v + IF2CMASK);
+					c->reg.if2creq = (unsigned char)int_type;
+					writeb(c->reg.if2creq, v + IF2CREQ);
+
+					/* Wait till everything has been written */
+					while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
+
+					/* Store Data */
+					store_data_in_buffer(c,&msg);
+				} else {
+					/* exit while loop */
+					break;
+				}
+				int_type++;
+			}
+			while (int_type <= CAN_STD_RX_BUFFER_END);
+			DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_STD_RX_BUFFER_START/CAN_STD_RX_BUFFER_END IRQ 0x%x\n",minor,int_type);
+			break;
+		/* Extended Frames */
+		case CAN_EXT_RX_BUFFER:
+			DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_EXT_RX_BUFFER IRQ 0x%x\n",minor,int_type);
+			while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
+			/* Get all unsigned chars */
+			c->reg.if2cmask = 0x3F;
+			writeb(c->reg.if2cmask, v + IF2CMASK);
+			c->reg.if2creq = (unsigned char)int_type;
+			writeb(c->reg.if2creq, v + IF2CREQ);
+			/* Wait till everything has been written */
+			while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80) ;
+			/* is NewData set? */
+			if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x80) {
+				/* Extended Frame? */
+				if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x40)
+					msg.ext = 1;
+				else
+					msg.ext = 0;
+
+				msg.dlc = ((c->reg.if2mcont[0] = readb(v + IF2MCONT0)) & 0x0F);
+				msg.id = c->reg.if2id[0] = readb(v + IF2ID0);
+				msg.id += ((c->reg.if2id[1] = readb(v + IF2ID1)) << 8);
+				msg.id += ((c->reg.if2id[2] = readb(v + IF2ID2)) << 16);
+				msg.id += (((c->reg.if2id[3] = readb(v + IF2ID2)) & 0x1F) << 24);
+
+				k = (unsigned char)((msg.dlc <= 8) ? (msg.dlc) : 8);
+				for (i = 0; i < k; i++)
+					msg.data[i] = c->reg.if2data[i] = readb(v + IF2DATA0 + i);
+				/* Is MsgLost set? */
+				if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x40)
+					c->status |= CAN_STS_OVERRUN;
+				else
+					c->status &= ~CAN_STS_OVERRUN;
+
+				/* clear MsgLst */
+				c->reg.if2mcont[1] &= 0xBF;
+				writeb(c->reg.if2mcont[1], v + IF2MCONT1);
+				c->reg.if2cmask = 0x10;
+				writeb(c->reg.if2cmask, v + IF2CMASK);
+				c->reg.if2creq = (unsigned char)int_type;
+				writeb(c->reg.if2creq, v + IF2CREQ);
+
+				/* Wait till everything has been written */
+				while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
+				/* Store Data */
+				store_data_in_buffer(c, &msg);
+			}
+		DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_EXT_RX_BUFFER IRQ 0x%x\n",minor,int_type);
+		break;
+		default:
+		DBG_OKI(KERN_ERR, " /dev/can%d IRQ is default 0x%x\n",minor,int_type);
+		goto out;
+		break;
+		}
+		/* read next IRQ */
+		/* only read can interrupt register0, we don't want detect a status interrupt here! */
+		int_type = readb(v + CANINT0);
+	}			/* while */
+out:
+	spin_unlock_irqrestore(&c->can_lock, flags);
+	return IRQ_HANDLED;
+}
+
+static struct file_operations oki_fops = {
+	.owner = THIS_MODULE,
+	.read = oki_read,
+	.write = oki_write,
+	.ioctl = oki_ioctl,
+	.open = oki_open,
+	.release = oki_release,
+	.poll = oki_poll,
+};
+
+int oki_read(struct file *file, char *buf, size_t count, loff_t * ppos)
+{
+	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	struct can_device *c = info_can[minor];
+	int ret = 0;
+	int i, tmp;
+
+	if (count < sizeof(struct can_msg))
+		return -EINVAL;
+
+	if ((c->head == c->tail) && (file->f_flags & O_NONBLOCK))
+		return  -EAGAIN;
+		
+	ret = wait_event_interruptible(c->rx_waitq, c->head != c->tail);
+	if (ret)
+		return -ERESTARTSYS;
+
+	for (i = 0; i < (count / sizeof(struct can_msg)); i++) {
+		if (c->head == c->tail)
+			break;
+
+		tmp = copy_to_user(buf, &c->head->msg, sizeof(struct can_msg));
+		if (tmp > 0) {
+			printk("copy_to_user could not copy %d bytes", ret);
+			ret = -EIO;
+		} else {
+			buf += sizeof(struct can_msg);
+			ret += sizeof(struct can_msg);
+		}
+
+		c->head = c->head->next;
+		kfree(c->head->prev);
+	}
+
+	return ret;
+}
+
+int oki_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
+{
+	unsigned char i;	/* counter, temp var */
+	unsigned char k;	/* counter */
+	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	struct can_device *c = info_can[minor];
+	unsigned long v = (unsigned long)c->virt_addr_can;
+	struct can_msg tmp;
+	struct can_msg *txbuf = &tmp;
+
+	if (!buf || !count)
+		return 0;
+
+	/* be stricter than in read here, require multiples of whole msgs */
+	if (count % sizeof(struct can_msg)) {
+		printk("count must be N * sizeof(struct can_msg)!\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * This can be removed as soon as we have implemented support for
+	 * writing multiple messages
+	 */
+	if (count != sizeof(struct can_msg)) {
+		printk("FIXME: support writing multiple messages at once!\n");
+		return -EINVAL;
+	}
+
+	if (0 != copy_from_user(txbuf, buf, count)) {
+		printk("%s: Error: copy from user failed!\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	DBG_OKI(KERN_ERR, ": WRITE minor %d\n", c->minor);
+	DBG_OKI(KERN_ERR, ": WRITE virt 0x%x\n", c->virt_addr_can);
+	DBG_OKI(KERN_ERR, ": WRITE id %d\n", txbuf->id);
+	DBG_OKI(KERN_ERR, ": WRITE dlc %d\n", txbuf->dlc);
+	DBG_OKI(KERN_ERR, ": WRITE rtr %d\n", txbuf->rtr);
+	DBG_OKI(KERN_ERR, ": WRITE ext %d\n", txbuf->ext);
+	for (i = 0; i < 8; i++)
+		DBG_OKI(KERN_ERR, ": WRITE data[%d] %d\n", i, txbuf->data[i]);
+
+	c->reg.cancont = readb(v + CANCONT);
+
+	CAN_DEBUG(CANCONT, "CANCONT");
+
+	if ((c->reg.cancont & CONT_FLAG_INIT) == CONT_FLAG_INIT) {
+		if (c->last_error_code_write < 1) {
+			c->last_error_code_write = 1;
+			DBG_OUT(KERN_ERR, ": /dev/can%d not initalised or switched off, do ioctl: COMMAND CAN_STS_CNTRL_ON \n",minor );
+		}
+		return -EAGAIN;
+	}
+
+	/* Check the status, so we can handle warning and bus off state */
+	check_status(c);
+
+	if (c->status == CAN_STS_WARNING) {
+		if (c->last_error_code_write < 2) {
+			c->last_error_code_write = 2;
+			DBG_OUT(KERN_ERR, ": /dev/can%d is in WARNING State, do ioctl STATUS\n",minor );
+		}
+		return -EAGAIN;
+	}
+
+	if (c->status == CAN_STS_BUS_OFF) {
+		if (c->last_error_code_write < 3) {
+			c->last_error_code_write = 3;
+			DBG_OUT(KERN_ERR, ": /dev/can%d is in BUS OFF State, do ioctl STATUS\n",minor );
+		}
+		return -EAGAIN;
+	}
+
+	c->status &= ~CAN_STS_TXOK;
+
+	/* Wait till everything has been written */
+	if (c->tx_in_progress) {
+		DBG_OKI(KERN_ERR, ": WRITE CAN%d BUSY\n", minor);
+		return -EBUSY;
+	} else {
+		c->tx_in_progress = 1;
+		CAN_DEBUG(IF1BUSY, " WRITE 2 for while IF1BUSY");
+		while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
+
+		/* set, so that ID Register will get transfered */
+		c->reg.if1cmask = 0xB7;
+		writeb(c->reg.if1cmask, v + IF1CMASK);
+		CAN_DEBUG(IF1CMASK, " WRITE 3 for while  IF1CMASK");
+	}
+
+	if (txbuf->ext == 0) {
+		/* DIR and WR */
+		c->reg.if1id[3] = 0xA0;
+		c->reg.if1id[3] |= (unsigned char)((txbuf->id >> 6) & 0x1F);
+		DBG_OKI(KERN_ERR, "WRITE c->reg.if1id[3] 0x%x\n",c->reg.if1id[3]);
+		writeb(c->reg.if1id[3], v + IF1ID3);
+		CAN_DEBUG(IF1ID3, " WRITE 4  IF1ID3");
+		c->reg.if1id[2] = (unsigned char)((txbuf->id << 2) & 0xFC);
+		DBG_OKI(KERN_ERR, "WRITE c->reg.if1id[2] 0x%x\n",c->reg.if1id[2]);
+		writeb(c->reg.if1id[2], v + IF1ID2);
+		CAN_DEBUG(IF1ID2, "WRITE 4  IF1ID2");
+	} else {
+		/* extended Frame */
+		c->reg.if1id[3] = 0xE0;
+		c->reg.if1id[3] += (unsigned char)((txbuf->id >> 24) & 0x1F);
+		c->reg.if1id[2] = (unsigned char)((txbuf->id >> 16) & 0xFF);
+		c->reg.if1id[1] = (unsigned char)((txbuf->id >> 8) & 0xFF);
+		c->reg.if1id[0] = (unsigned char)(txbuf->id & 0xFF);
+		writeb(c->reg.if1id[3], v + IF1ID3);
+		CAN_DEBUG(IF1ID3, "WRITE 4 IF1ID3");
+		writeb(c->reg.if1id[2], v + IF1ID2);
+		CAN_DEBUG(IF1ID2, "WRITE 4 IF1ID2");
+		writeb(c->reg.if1id[1], v + IF1ID1);
+		CAN_DEBUG(IF1ID1, "WRITE 4 IF1ID1");
+		writeb(c->reg.if1id[0], v + IF1ID0);
+		CAN_DEBUG(IF1ID1, "WRITE 4 IF1ID1");
+	}
+
+	k = (unsigned char)(((txbuf->dlc) <= 8) ? (txbuf->dlc) : 8);
+	for (i = 0; i < k; i++) {
+		c->reg.if1data[i] = txbuf->data[i];
+		writeb(c->reg.if1data[i], v + IF1DATA0 + i);
+		DBG_OKI(KERN_ERR, ": WRITE in for data[%d] %d\n",i,txbuf->data[i]);
+		CAN_DEBUG(IF1DATA0 + i, "WRITE 4   IF1DATA0 + i");
+	}
+	/* End of Buffer (EOB) */
+
+	c->reg.if1mcont[0] = 0x80 + (txbuf->dlc & 0x0F);
+	DBG_OKI(KERN_ERR, ": WRITE 5 if1mcont[0] 0x%x\n", c->reg.if1mcont[0]);
+	writeb(c->reg.if1mcont[0], v + IF1MCONT0);
+	CAN_DEBUG(IF1MCONT0, "WRITE 5   IF1MCONT0");
+
+	if (txbuf->rtr == 1) {
+		c->reg.if1id[3] &= 0xDF;
+		DBG_OKI(KERN_ERR, ": WRITE 6 if1id[3] 0x%x\n", c->reg.if1id[3]);
+		writeb(c->reg.if1id[3], v + IF1ID3);
+		CAN_DEBUG(IF1ID3, "WRITE 6   IF1ID3");
+		/* TXIE, TXRqst and RXIE */
+		c->reg.if1mcont[1] = 0x0D;
+		DBG_OKI(KERN_ERR, ": WRITE 6 if1mcont[1] 0x%x\n",c->reg.if1mcont[1]);
+		writeb(c->reg.if1mcont[1], v + IF1MCONT1);
+		CAN_DEBUG(IF1MCONT1, "WRITE 6   IF1MCONT1");
+		c->reg.if1creq = CAN_RTX_BUFFER;
+		DBG_OKI(KERN_ERR, ": WRITE 6 if1creq  0x%x\n", c->reg.if1creq);
+		writeb(c->reg.if1creq, v + IF1CREQ);
+		CAN_DEBUG(IF1CREQ, "WRITE 6   IF1CREQ");
+	} else {
+		c->reg.if1mcont[1] = 0x09;
+		DBG_OKI(KERN_ERR, ": WRITE 6 if1mcont[1] 0x%x\n",c->reg.if1mcont[1]);
+		writeb(c->reg.if1mcont[1], v + IF1MCONT1);
+		CAN_DEBUG(IF1MCONT1, "WRITE 6   IF1MCONT1");
+		c->reg.if1creq = CAN_TX_BUFFER;
+		DBG_OKI(KERN_ERR, ": WRITE 6 if1creq  0x%x\n", c->reg.if1creq);
+		writeb(c->reg.if1creq, v + IF1CREQ);
+		CAN_DEBUG(IF1CREQ, "WRITE 6   IF1CREQ");
+	}
+	return count;
+}
+
+int oki_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	unsigned int minor = iminor(inode);
+	struct can_device *c = info_can[minor];	/* better ideas than using globals anyone? */
+	int ret = -ENOIOCTLCMD;
+	int new_options = 0;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int cntr_ret;
+
+	switch (cmd) {
+	case COMMAND:
+		{
+			if (get_user(new_options, p) != 0)
+				return -EFAULT;
+
+			DBG_OKI(KERN_ERR, ": IOCTL COMMAND WITH %d\n", new_options);
+			cntr_ret = activate(c, new_options);
+			if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
+				return 0;
+			else
+				return ret;
+
+			break;
+		}
+	case CONFIG:
+		{
+			if (get_user(new_options, p) != 0)
+				return -EFAULT;
+
+			cntr_ret = set_baudrate(c, new_options);
+			if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
+				return 0;
+			else
+				return ret;
+
+			break;
+		}
+	case SEND:
+		break;
+	case RECEIVE:
+		break;
+	case STATUS:
+		{
+			int cntr_ret;
+			/* Check status */
+			cntr_ret = check_status(c);
+			if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
+				return 0;
+			else
+				return ret;
+			break;
+		}
+	default:
+		return -ENOIOCTLCMD;
+		break;
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static unsigned int oki_poll(struct file *file, poll_table * wait)
+{
+	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	struct can_device *c = info_can[minor];
+        unsigned int mask = 0;
+
+	poll_wait(file, &c->rx_waitq, wait);
+	if (c->head != c->tail)
+		mask |= POLLIN | POLLRDNORM;
+	return mask;
+}
+
+int check_status(struct can_device *c)
+{
+	int stat_reg;
+	unsigned long v = (unsigned long)c->virt_addr_can;
+
+	stat_reg = readb(v + CANSTAT);
+	DBG_OKI(KERN_DEBUG, "check_status canstat 0x%x\n", stat_reg);
+
+	/* Bus is in "Error Passive" state */
+	if ((stat_reg & 0x20) == 0) {
+		c->status &= ~CAN_STS_WARNING;
+		c->status &= ~CAN_STS_BUS_OFF;
+	}
+
+	if ((stat_reg & 0x60) == 0x60) {
+		if (c->last_error_code != (stat_reg & 0x7)) {
+			c->last_error_code = (stat_reg & 0x7);
+		}
+		c->status |= CAN_STS_WARNING;
+	}
+
+	if ((stat_reg & 0x80) == 0x80) {
+		if (c->last_error_code < 10) {
+			c->last_error_code = 10;
+		}
+		c->status |= CAN_STS_BUS_OFF;
+	}
+
+	/* clear overrun  */
+	c->status &= ~CAN_STS_OVERRUN;
+	return c->status;
+}
+
+int activate(struct can_device *c, unsigned char new_status)
+{
+	unsigned long v = (unsigned long)c->virt_addr_can;
+
+	switch (new_status) {
+	case CAN_STS_CNTRL_OFF:
+		do {
+			c->reg.cancont |= CONT_FLAG_INIT;
+			writeb(c->reg.cancont, v + CANCONT);
+		}
+		while (!((c->reg.cancont = readb(v + CANCONT)) & CONT_FLAG_INIT));
+
+		c->status |= CAN_STS_RESET;
+
+		DBG_OKI(KERN_DEBUG, " /dev/can%d activate CAN_STS_CNTRL_OFF CANCONT 0x%x\n",c->minor,c->reg.cancont);
+		break;
+	case CAN_STS_CNTRL_ON:
+		do {
+			c->reg.cancont &= ~CONT_FLAG_INIT;
+			writeb(c->reg.cancont, v + CANCONT);
+		}
+		while (((c->reg.cancont = readb(v + CANCONT)) & CONT_FLAG_INIT));
+
+		c->status &= ~CAN_STS_RESET;
+
+		DBG_OKI(KERN_DEBUG, " /dev/can%d activate CAN_STS_CNTRL_ON CANCONT 0x%x\n",c->minor,c->reg.cancont);
+		break;
+	case CAN_STS_CNTRL_SLEEP:
+		break;
+	case CAN_STS_CNTRL_AWAKE:
+		break;
+	default:
+		break;
+	}
+
+	return c->status;
+}
+
+int oki_open(struct inode *inode, struct file *file)
+{
+	unsigned int minor = iminor(inode);
+	struct can_device *c = info_can[minor];	/* better ideas than using globals anyone? */
+
+	if (!atomic_dec_and_test(&c->can_opened)) {
+		DBG_OUT(KERN_ERR, ": /dev/can%d already opened.\n", minor);
+		atomic_inc(&c->can_opened);
+		return -EBUSY;
+	}
+	return 0;
+}
+
+int oki_release(struct inode *inode, struct file *file)
+{
+	unsigned int minor = iminor(inode);
+	struct can_device *c = info_can[minor];	/* better ideas than using globals anyone? */
+
+	atomic_dec(&c->can_opened);
+	if (!atomic_inc_and_test(&c->can_opened)) {
+		DBG_OUT(KERN_ERR, ": /dev/can%d open, busy.\n", minor);
+		return -EBUSY;
+	}
+
+	atomic_inc(&c->can_opened);
+	return 0;
+}
+
+int can_register(struct can_device *c)
+{
+	atomic_set(&c->can_opened, 1);
+
+	/* map memory */
+	c->virt_addr_can = ioremap(c->phys_addr_can, c->phys_size_can);
+	if (!c->virt_addr_can) {
+		DBG_OUT(KERN_ERR, ": Unable to remap /dev/can%d memory.\n", c->minor);
+		return -ENOMEM;
+	}
+
+	DBG_OUT(KERN_INFO, ": remap /dev/can%d memory physical 0x%x to virtual 0x%x.\n",c->minor,c->phys_addr_can,c->virt_addr_can);
+
+	/* Message buffers */
+	c->tail = kzalloc(sizeof(struct recbuf), GFP_KERNEL);
+	c->head = c->tail;
+
+	/* CAN init */
+	hw_init(c);
+
+	/* waitq init */
+	init_waitqueue_head(&c->rx_waitq);
+
+	/* Install IRQ handler */
+	if(0 != request_irq(c->irq, oki_irqhandler, c->irq_flags, "OKI_CAN", (void *)c)){
+		DBG_OUT(KERN_ERR, ": /dev/can%d cannot install IRQ-handler\n",c->minor);
+		return -ENOMEM;
+	}
+
+	DBG_OUT(KERN_INFO, ": /dev/can%d IRQ-handler installed.\n", c->minor);
+
+	return 0;
+}
+
+int __init oki_init(void)
+{
+	can_register(info_can[0]);
+#ifdef CONFIG_OKI_CAN_ML9620_2DEV
+	can_register(info_can[1]);
+#endif
+
+	/* Register char device */
+	if (register_chrdev(OKI_CAN_CHAR_MAJOR, OKI_CAN_DEVICE_NAME, &oki_fops)) {
+		DBG_OUT(KERN_ERR, "Can't allocate major number %d for CAN driver.\n",OKI_CAN_CHAR_MAJOR);
+		return -EIO;
+	}
+
+	DBG_OUT(KERN_INFO, ": Version: " OKI_CAN_VERSION " registered successfully.\n");
+	/*DBG_OUT(KERN_INFO, "Installed %d IRQ handlers for %d CAN devices.\n",irq_nr,can_dev); */
+
+	printk(KERN_INFO "Contec Steuerungstechnik und Automation Ges.m.b.H\n");
+	printk(KERN_INFO "Waldeck 1 / 6330 Kufstein / Austria\n");
+
+	return 0;
+}
+
+module_init(oki_init);
+
+void unregister_can(struct can_device *c)
+{
+	DBG_OUT(KERN_INFO, ": unregister /dev/can%d  .\n", c->minor);
+	free_irq(c->irq, (void *)c);
+
+	if (c->virt_addr_can != NULL) {
+		iounmap(c->virt_addr_can);
+	} else {
+		DBG_OUT(KERN_ERR, ": /dev/can%d was not mapped, skipping iounmap!\n", c->minor);
+	}
+}
+
+void __exit oki_exit(void)
+{
+	unregister_can(info_can[0]);
+#ifdef CONFIG_OKI_CAN_ML9620_2DEV
+	unregister_can(info_can[1]);
+#endif
+	unregister_chrdev(OKI_CAN_CHAR_MAJOR, OKI_CAN_DEVICE_NAME);
+}
+
+module_exit(oki_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Manfred Gruber <manfred.gruber@contec.at>");
+MODULE_DESCRIPTION("OKI ML9620 CAN Driver");
diff --git a/drivers/char/can/oki_ml9620.h b/drivers/char/can/oki_ml9620.h
new file mode 100644
index 0000000..f8ece1e
--- /dev/null
+++ b/drivers/char/can/oki_ml9620.h
@@ -0,0 +1,397 @@
+/*
+ * drivers/char/can/oki_ml9620_core.h
+ *
+ * OKI ML9620 CAN Controler driver
+ *
+ * Author: Manfred Gruber <manfred.gruber@contec.at>
+ *
+ * Copyright 2004 (c) Manfred Gruber
+ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
+ * Kufstein/Austria   www.contec.at
+ *
+ * This driver was written for Contec Hypercontrol Micro9 Board:
+ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
+ * 2. CAN Controller is on Hypercontrol Micro9 Eval board
+ *
+ * Contec uses this driver on their Hypercontrol Micro9 boards based on
+ * Cirrus Logic EP93XX,we have changed Adr-/Databus timinig to use OKI ML9620.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ */
+
+#ifndef _OKI_ML9620_CORE_H_
+#define _OKI_ML9620_CORE_H_
+
+#include <linux/can/oki_ml9620_ctrl.h>
+#include <linux/kernel.h>
+
+#define OKI_CAN_CHAR_MAJOR 	91
+#define OKI_CAN_DEVICE_NAME 	"oki_ml9260"
+#define OKI_CAN_VERSION 	"0.08"
+
+#define OKI_CAN_MAX_IRQS  	20
+#define PHYS_SIZE_CAN 0x00000100
+
+/* Contec */
+#ifdef CONFIG_OKI_CAN_ML9620_MICRO9
+#define CAN_CLOCK_8MHZ
+#define PHYS_ADDR_CAN0 0x20000000
+#define PHYS_ADDR_CAN1 0x21000000
+#define IRQ_CAN0 GPIO_IRQ4
+#define IRQ_CAN1 GPIO_IRQ10
+#ifdef CONFIG_GENERIC_HARDIRQS
+#define IRQ_FLAGS_CAN0 (SA_INTERRUPT)
+#define IRQ_FLAGS_CAN1 (SA_INTERRUPT)
+#else
+#define IRQ_FLAGS_CAN0 (SA_INTERRUPT | SA_SHIRQ)
+#define IRQ_FLAGS_CAN1 (SA_INTERRUPT | SA_SHIRQ)
+#endif
+#endif				/* CONFIG_OKI_CAN_ML9620_MICRO9 */
+
+/* Gassner */
+#ifdef CONFIG_OKI_CAN_ML9620_GASSNER
+#define CAN_CLOCK_8MHZ
+#define PHYS_ADDR_CAN0 0x10000000
+#define PHYS_ADDR_CAN1 0x30000000
+#define IRQ_CAN0 GPIO_IRQ6	/* Line EGPIO6 (multiplexed) */
+#define IRQ_CAN1 GPIO_IRQ13	/* Line EGPIO13 (multiplexed) */
+#define IRQ_FLAGS_CAN0 (SA_INTERRUPT | SA_SHIRQ)
+#define IRQ_FLAGS_CAN1 (SA_INTERRUPT | SA_SHIRQ)
+#endif				/* CONFIG_OKI_CAN_ML9620_GASSNER */
+
+char *err[7] = {
+	"Warning 1, Stuff Error",
+	"Warning 2, Form Error",
+	"Warning 3, ACK Error",
+	"Warning 4, Bits 1 Error",
+	"Warning 5, Bits 0 Error",
+	"Warning 6, CRC Error",
+	"Warning 7, MCU has produced this Error",
+};
+
+#define DRIVER_MAX_MINOR 2
+
+struct CANML9620REG {
+	unsigned char cancont;
+	unsigned char reserve1;
+	unsigned char canstat;
+	unsigned char reserve2;
+	unsigned char cantxerrc;
+	unsigned char canrxerrc;
+	unsigned char canbitt[2];
+	unsigned char canint[2];
+	unsigned char canopt;
+	unsigned char reserve3;
+	unsigned char canbpre;
+	unsigned char reserve4[3];
+
+	unsigned char if1creq;
+	unsigned char if1busy;
+	unsigned char if1cmask;
+	unsigned char reserve5;
+	unsigned char if1mask[4];
+	unsigned char if1id[4];
+	unsigned char if1mcont[2];
+	unsigned char if1data[8];
+	unsigned char reserve6[26];
+
+	unsigned char if2creq;
+	unsigned char if2busy;
+	unsigned char if2cmask;
+	unsigned char reserve7;
+	unsigned char if2mask[4];
+	unsigned char if2id[4];
+	unsigned char if2mcont[2];
+	unsigned char if2data[8];
+	unsigned char reserve8[42];
+
+	unsigned char cantreq[4];
+	unsigned char reserve9[12];
+
+	unsigned char canndata[4];
+	unsigned char reserve10[12];
+
+	unsigned char canipend[4];
+	unsigned char reserve11[12];
+
+	unsigned char canmval[4];
+	unsigned char reserve12[12];
+
+	unsigned char canstby;
+	unsigned char reserve13[12];
+};
+
+#define CANCONT	0x0
+#define RESERVE1	0x1
+#define CANSTAT 	0x2
+#define RESERVE2 	0x3
+#define CANTXERRC 	0x4
+#define CANRXERRC	0x5
+#define CANBITT0 	0x6
+#define CANBITT1 	0x7
+#define CANINT0 	0x8
+#define CANINT1 	0x9
+#define CANOPT 	0xA
+
+#define CANBPRE	0xC
+
+#define IF1CREQ	0x10
+#define IF1BUSY	0x11
+#define IF1CMASK	0x12
+
+#define IF1MASK0	0x14
+#define IF1MASK1	0x15
+#define IF1MASK2	0x16
+#define IF1MASK3	0x17
+
+#define IF1ID0	0x18
+#define IF1ID1	0x19
+#define IF1ID2	0x1A
+#define IF1ID3	0x1B
+
+#define IF1MCONT0	0x1C
+#define IF1MCONT1	0x1D
+
+#define IF1DATA0	0x1E
+#define IF1DATA1	0x1F
+#define IF1DATA2	0x20
+#define IF1DATA3	0x21
+#define IF1DATA4	0x22
+#define IF1DATA5	0x23
+#define IF1DATA6	0x24
+#define IF1DATA7	0x25
+
+#define IF2CREQ	0x40
+#define IF2BUSY	0x41
+#define IF2CMASK	0x42
+
+#define IF2MASK0	0x44
+#define IF2MASK1	0x45
+#define IF2MASK2	0x46
+#define IF2MASK3	0x47
+
+#define IF2ID0	0x48
+#define IF2ID1	0x49
+#define IF2ID2	0x4A
+#define IF2ID3	0x4B
+
+#define IF2MCONT0	0x4C
+#define IF2MCONT1	0x4D
+
+#define IF2DATA0	0x4E
+#define IF2DATA1	0x4F
+#define IF2DATA2	0x50
+#define IF2DATA3	0x51
+#define IF2DATA4	0x52
+#define IF2DATA5	0x53
+#define IF2DATA6	0x54
+#define IF2DATA7	0x55
+
+#define CANTREQ0	0x80
+#define CANTREQ1	0x81
+#define CANTREQ2	0x82
+#define CANTREQ3	0x83
+
+#define CANNDATA0	0x90
+#define CANNDATA1	0x91
+#define CANNDATA2	0x92
+#define CANNDATA3	0x93
+
+#define CANIPEND0	0xA0
+#define CANIPEND1	0xA1
+#define CANIPEND2	0xA2
+#define CANIPEND3	0xA3
+
+#define CANMVAL0	0xB0
+#define CANMVAL1	0xB1
+#define CANMVAL2	0xB2
+#define CANMVAL3	0xB3
+
+#define CANSTBY	0xC0
+struct recbuf {
+	struct can_msg msg;
+	struct recbuf *next;
+	struct recbuf *prev;
+};
+
+struct can_device {
+	/* Phys addresses and size */
+	unsigned long phys_addr_can;
+	unsigned long phys_size_can;
+	/* IRQ */
+	unsigned int irq;
+	unsigned long irq_flags;
+
+	/* Device node */
+	int minor;
+
+	/* waitqueue for read, poll */
+	wait_queue_head_t rx_waitq;
+
+	atomic_t can_opened;
+
+	struct recbuf *tail;
+	struct recbuf *head;
+
+	/* Virt addresses size */
+	unsigned char __iomem *virt_addr_can;
+
+	/*  CAN-Baustein */
+	struct CANML9620REG reg;
+	unsigned short baudrate;	/* baudrate */
+	unsigned short overrun;	/* overrun counter */
+	struct can_msg msg;	/* CAN message buffer */
+	int status;		/* actual CAN status  */
+	int last_error_code_write;
+	unsigned char tx_in_progress;
+	unsigned char last_error_code;	/* LEC */
+	unsigned char last_error_code_debug;	/* LEC when printed out */
+	spinlock_t can_lock;
+};
+
+/* Global Device Struct can0 */
+static struct can_device info_can0 = {
+	.phys_addr_can = PHYS_ADDR_CAN0,
+	.phys_size_can = PHYS_SIZE_CAN,
+	.irq = IRQ_CAN0,
+	.minor = 0,
+	.irq_flags = IRQ_FLAGS_CAN0,
+	.can_opened = ATOMIC_INIT(1),
+	.status = CAN_STS_NORMAL,
+};
+
+/* Global Device Struct can1 */
+static struct can_device info_can1 = {
+	.phys_addr_can = PHYS_ADDR_CAN1,
+	.phys_size_can = PHYS_SIZE_CAN,
+	.irq = IRQ_CAN1,
+	.irq_flags = IRQ_FLAGS_CAN1,
+	.minor = 1,
+	.can_opened = ATOMIC_INIT(1),
+	.status = CAN_STS_NORMAL,
+};
+
+static struct can_device *info_can[] = { &info_can0, &info_can1 };
+
+#define NUM_MSG			32
+
+#define CONT_FLAG_INIT		0x01
+#define CONT_FLAG_IE		0x02
+#define CONT_FLAG_SIE		0x04
+#define CONT_FLAG_EIE		0x08
+#define CONT_FLAG_CCE		0x40
+
+/* message buffers */
+
+#define CAN_STD_RX_BUFFER_START  1	/* CAN standard receive buffer */
+#define CAN_STD_RX_BUFFER_END    12	/* CAN standard receive buffer */
+#define CAN_EXT_RX_BUFFER        13	/* CAN extended receive buffer */
+
+#define CAN_TX_BUFFER       	 14	/* CAN transmit buffer         */
+#define CAN_RTX_BUFFER      	 15	/* CAN remote frame transmit buffer */
+
+struct ML9620BDRATE {
+	unsigned char btiming0;
+	unsigned char btiming1;
+	unsigned char bpre;
+};
+
+const struct ML9620BDRATE bd_tbl[9] = {
+#ifdef CAN_CLOCK_16MHZ
+/* for 16 Mhz Quarz                */
+/* bus timing 0  | bus timing 1    */
+/* SJW PRESCALER | SAM TSEG1 TSEG2 */
+	{0x23, 0x1C},		/*  10K bit/s */
+	{0x31, 0x1C},		/*  20K bit/s */
+	{0x13, 0x1C},		/*  50K bit/s */
+	{0x09, 0x1C},		/* 100K bit/s */
+	{0x07, 0x1C},		/* 125K bit/s */
+	{0x03, 0x1C},		/* 250K bit/s */
+	{0x01, 0x1C},		/* 500K bit/s */
+	{0x01, 0x16},		/* 800K bit/s */
+	{0x01, 0x14}		/*   1M bit/s */
+#endif
+#ifdef CAN_CLOCK_8MHZ
+/* for 8 Mhz Quarz                */
+/* bus timing 0  | bus timing 1    */
+/* SJW PRESCALER | SAM TSEG1 TSEG2 | CANBRPE */
+	{0x31, 0x1C, 0x01},	/*  10K bit/s           */
+	{0x18, 0x1C, 0x00},	/*  20K bit/s           */
+	{0x09, 0x1C, 0x00},	/*  50K bit/s           */
+	{0x04, 0x1C, 0x00},	/* 100K bit/s           */
+	{0x03, 0x1C, 0x00},	/* 125K bit/s           */
+	{0x01, 0x1C, 0x00},	/* 250K bit/s           */
+	{0x00, 0x1C, 0x00},	/* 500K bit/s           */
+	{0x00, 0x16, 0x00},	/* 800K bit/s           */
+	{0x00, 0x14, 0x00}	/*   1M bit/s           */
+#endif
+};
+
+/* DEBUG STUFF */
+
+#ifdef OKI_DEBUG
+#define CAN_DEBUG(REG,string) 						\
+{									\
+	DBG_OUT(KERN_ERR, " %s 0x%x\n",string,readb(v+REG));		\
+}
+#else
+#define CAN_DEBUG(REG,string)
+#endif
+
+#ifdef OKI_DEBUG
+#define DBG_OKI DBG_OUT
+#else
+#define DBG_OKI(...)
+#endif
+
+int drv_dbg = 7;
+
+void DBG_OUT(const char *type, const char *dbg_msg, ...)
+{
+	va_list ap;
+	char buf[1024];
+	int len;
+	unsigned int level;
+
+	va_start(ap, dbg_msg);
+	len = vsprintf(buf, dbg_msg, ap);
+	va_end(ap);
+	buf[len] = '\0';
+
+	if (0 == sscanf(type, "<%i>", &level))
+		printk(KERN_ALERT "%s", buf);
+
+	if (level > drv_dbg)
+		return;
+
+	switch (level) {
+	case 0:
+		printk(KERN_EMERG OKI_CAN_DEVICE_NAME "EMERG: %s", buf);
+		break;
+	case 1:
+		printk(KERN_ALERT OKI_CAN_DEVICE_NAME "%s", buf);
+		break;
+	case 2:
+		printk(KERN_CRIT OKI_CAN_DEVICE_NAME "%s", buf);
+		break;
+	case 3:
+		printk(KERN_ERR OKI_CAN_DEVICE_NAME "%s", buf);
+		break;
+	case 4:
+		printk(KERN_WARNING OKI_CAN_DEVICE_NAME "%s", buf);
+		break;
+	case 5:
+		printk(KERN_NOTICE OKI_CAN_DEVICE_NAME "%s", buf);
+		break;
+	case 6:
+		printk(KERN_INFO OKI_CAN_DEVICE_NAME "%s", buf);
+		break;
+	case 7:
+		printk(KERN_DEBUG OKI_CAN_DEVICE_NAME "%s", buf);
+		break;
+	}
+}
+#endif				/* _OKI_ML9620_CORE_H_ */
diff --git a/drivers/char/ds1337glue.c b/drivers/char/ds1337glue.c
new file mode 100644
index 0000000..c7d168b
--- /dev/null
+++ b/drivers/char/ds1337glue.c
@@ -0,0 +1,69 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/ds1337glue.c
+ *
+ *  Copyright (C) 2005 Michael Burian
+ *
+ * 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.
+ *
+ * /dev/rtc interface for Dallas Semiconductor DS133[79]RTC I2C driver
+ *
+ * Also see "drivers/i2c/chips/ds1337.c"
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+
+#include <asm/rtc.h>
+
+/* FIXME BEGIN: include this from "ds1337.h" as soon as there exists one */
+#warning FIXME: no official ds1337 interface available, hardcoding defaults.
+#define DS1337_GET_DATE         0
+#define DS1337_SET_DATE         1
+extern int ds1337_do_command(int bus, int cmd, void *arg);
+/* FIXME END */
+
+static int rtc_read_time(struct rtc_time *tm)
+{
+	return ds1337_do_command(0, DS1337_GET_DATE, (void*)(tm));
+}
+
+static int rtc_set_time(struct rtc_time *tm)
+{
+	return ds1337_do_command(0, DS1337_SET_DATE, (void*)(tm));
+}
+
+static struct rtc_ops dma03_rtc_ops = {
+	.owner = THIS_MODULE,
+	.read_time = rtc_read_time,
+	.set_time = rtc_set_time,
+};
+
+static int __init rtc_interface_init(void)
+{
+	int err;
+	printk(KERN_INFO "registering /dev/rtc interface for DS133[79]\n");
+
+	err = register_rtc(&dma03_rtc_ops);
+	if(err)
+		printk(KERN_ERR "could not register DS1337 /dev/rtc interface:"
+							" error=%d!\n",err);
+
+	return err;
+}
+
+static void __exit rtc_interface_exit(void)
+{
+	unregister_rtc(&dma03_rtc_ops);
+}
+
+MODULE_AUTHOR("Michael Burian");
+MODULE_DESCRIPTION("/dev/rtc interface for ds1337.c");
+MODULE_LICENSE("GPL");
+
+module_init(rtc_interface_init);
+module_exit(rtc_interface_exit);
diff --git a/drivers/char/ep93xx-rtc.c b/drivers/char/ep93xx-rtc.c
new file mode 100644
index 0000000..399d0b0
--- /dev/null
+++ b/drivers/char/ep93xx-rtc.c
@@ -0,0 +1,376 @@
+/*
+ *      Real Time Clock for Cirrus EP93xx
+ *
+ *      Copyright (C) 2004 Ray Lehtiniemi
+ *
+ *      Support for realtime clock device on the Cirrus
+ *      EP93xx family of devices.
+ *
+ *      Based on rtc.c, and other rtc drivers.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sysctl.h>
+#include <linux/rtc.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+
+#include <asm/io.h>
+#include <asm/arch/regmap.h>
+
+#define RTC_VERSION "0.01"
+
+#define RTC_IS_OPEN	     0x01	/* means /dev/rtc is in use     */
+
+extern spinlock_t rtc_lock;	/* seems to be only present in older rtc header? */
+static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED;
+static rtc_task_t *rtc_callback = NULL;
+static unsigned long rtc_status = 0;
+static unsigned long rtc_irq_data = 0;
+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
+
+/*
+ *      the 1 Hz real time interrupt
+ */
+
+irqreturn_t interrupt_1hz(int irq, void *dev_id, struct pt_regs *regs)
+{
+	static unsigned long x = 0;
+	static int i = 0;
+
+	rtc_irq_data += 0x100;
+	rtc_irq_data &= ~0xff;
+
+	wake_up_interruptible(&rtc_wait);
+
+	printk(KERN_ERR);
+	printk(" delta: %04ld", jiffies - x);
+	printk("  data: %08x", readl(RTCDR));
+	printk(" match: %08x", readl(RTCMR));
+	printk("  stat: %08x", readl(RTCSTAT));
+	printk("  load: %08x", readl(RTCLR));
+	printk("  ctrl: %08x", readl(RTCCR));
+	printk("  comp: %08x", readl(RTCSCOMP));
+	printk("\n");
+
+	x = jiffies;
+	i++;
+
+	if ((i & 0x7) == 0) {
+		writel(i << 5, RTCLR);
+		printk(KERN_ERR "NEW LOAD VALUE: %08x\n", i << 5);
+	}
+
+	writel(0, RTCEOI);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ *      the RTC match interrupt
+ */
+
+irqreturn_t interrupt_match(int irq, void *dev_id, struct pt_regs * regs)
+{
+	return IRQ_HANDLED;
+}
+
+/*
+ *      the bulk of the usr interface is done here
+ */
+
+static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+{
+	return -ENOSYS;
+}
+
+/*
+ *      file operations for character device node
+ */
+
+static ssize_t rtc_read(struct file *file, char __user * buf, size_t count,
+			loff_t * ppos)
+{
+	unsigned long data;
+	ssize_t retval;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (count < sizeof(unsigned int))
+		return -EINVAL;
+
+	add_wait_queue(&rtc_wait, &wait);
+
+	do {
+		__set_current_state(TASK_INTERRUPTIBLE);
+
+		spin_lock_irq(&rtc_lock);
+		data = rtc_irq_data;
+		rtc_irq_data = 0;
+		spin_unlock_irq(&rtc_lock);
+
+		if (data != 0)
+			break;
+
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto out;
+		}
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+
+		schedule();
+	} while (1);
+
+	if (count < sizeof(unsigned long))
+		retval =
+		    put_user(data, (unsigned int __user *)buf) ? : sizeof(int);
+	else
+		retval =
+		    put_user(data,
+			     (unsigned long __user *)buf) ? : sizeof(long);
+
+      out:
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&rtc_wait, &wait);
+
+	return retval;
+}
+
+static unsigned int rtc_poll(struct file *file, poll_table * wait)
+{
+	return -ENOSYS;
+}
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg)
+{
+	return rtc_do_ioctl(cmd, arg, 0);
+}
+
+static int rtc_open(struct inode *inode, struct file *file)
+{
+	spin_lock_irq(&rtc_lock);
+
+	if (rtc_status & RTC_IS_OPEN) {
+		spin_unlock_irq(&rtc_lock);
+		return -EBUSY;
+	}
+
+	rtc_status |= RTC_IS_OPEN;
+	rtc_irq_data = 0;
+	enable_irq(IRQ_1HZ);
+
+	spin_unlock_irq(&rtc_lock);
+	return 0;
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+	spin_lock_irq(&rtc_lock);
+
+	disable_irq(IRQ_1HZ);
+	rtc_irq_data = 0;
+	rtc_status &= ~RTC_IS_OPEN;
+
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+static int rtc_fasync(int fd, struct file *filp, int on)
+{
+	return -ENOSYS;
+}
+
+static struct file_operations rtc_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.read = rtc_read,
+	.poll = rtc_poll,
+	.ioctl = rtc_ioctl,
+	.open = rtc_open,
+	.release = rtc_release,
+	.fasync = rtc_fasync,
+};
+
+static struct miscdevice rtc_dev = {
+	RTC_MINOR,
+	"rtc",
+	&rtc_fops
+};
+
+/*
+ *      sysctl-tuning infrastructure.
+ */
+
+int no_proc(ctl_table * table, int write, struct file *filp,
+	    void __user * buffer, size_t * lenp, loff_t * ppos)
+{
+	return -ENOSYS;
+}
+
+static ctl_table rtc_table[] = {
+	{
+	 .ctl_name = 1,
+	 .procname = "max-user-freq",
+	 .data = NULL,
+	 .maxlen = sizeof(int),
+	 .mode = 0644,
+	 .proc_handler = &no_proc,
+	 },
+	{.ctl_name = 0}
+};
+
+static ctl_table rtc_root[] = {
+	{
+	 .ctl_name = 1,
+	 .procname = "rtc",
+	 .maxlen = 0,
+	 .mode = 0555,
+	 .child = rtc_table,
+	 },
+	{.ctl_name = 0}
+};
+
+static ctl_table dev_root[] = {
+	{
+	 .ctl_name = CTL_DEV,
+	 .procname = "dev",
+	 .maxlen = 0,
+	 .mode = 0555,
+	 .child = rtc_root,
+	 },
+	{.ctl_name = 0}
+};
+
+static struct ctl_table_header *sysctl_header;
+
+static int __init init_sysctl(void)
+{
+	sysctl_header = register_sysctl_table(dev_root, 0);
+	return 0;
+}
+
+static void __exit cleanup_sysctl(void)
+{
+	unregister_sysctl_table(sysctl_header);
+}
+
+/*
+ *      Public functions from rtc.h
+ */
+
+EXPORT_SYMBOL(rtc_register);
+EXPORT_SYMBOL(rtc_unregister);
+EXPORT_SYMBOL(rtc_control);
+
+int rtc_register(rtc_task_t * task)
+{
+	if (task == NULL || task->func == NULL)
+		return -EINVAL;
+
+	spin_lock_irq(&rtc_lock);
+
+	if (rtc_status & RTC_IS_OPEN) {
+		spin_unlock_irq(&rtc_lock);
+		return -EBUSY;
+	}
+
+	spin_lock(&rtc_task_lock);
+
+	if (rtc_callback) {
+		spin_unlock(&rtc_task_lock);
+		spin_unlock_irq(&rtc_lock);
+		return -EBUSY;
+	}
+
+	rtc_status |= RTC_IS_OPEN;
+	rtc_callback = task;
+
+	spin_unlock(&rtc_task_lock);
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+int rtc_unregister(rtc_task_t * task)
+{
+	spin_lock_irq(&rtc_lock);
+	spin_lock(&rtc_task_lock);
+
+	if (rtc_callback != task) {
+		spin_unlock(&rtc_task_lock);
+		spin_unlock_irq(&rtc_lock);
+		return -ENXIO;
+	}
+
+	/* disable PIE/AIE/UIE interrupts */
+
+	rtc_status &= ~RTC_IS_OPEN;
+	rtc_callback = NULL;
+
+	spin_unlock(&rtc_task_lock);
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+int rtc_control(rtc_task_t * task, unsigned int cmd, unsigned long arg)
+{
+	spin_lock_irq(&rtc_task_lock);
+
+	if (rtc_callback != task) {
+		spin_unlock_irq(&rtc_task_lock);
+		return -ENXIO;
+	}
+
+	spin_unlock_irq(&rtc_task_lock);
+
+	return rtc_do_ioctl(cmd, arg, 1);
+}
+
+void rtc_get_rtc_time(struct rtc_time *rtc_tm)
+{
+}
+
+/*
+ *      Module init/exit
+ */
+
+static int __init rtc_init(void)
+{
+	if (request_irq(IRQ_1HZ, interrupt_1hz, SA_INTERRUPT, "rtc-1hz", NULL)) {
+		printk(KERN_ERR "rtc: IRQ %d is not free.\n", IRQ_1HZ);
+		return -EIO;
+	}
+
+	if (misc_register(&rtc_dev)) {
+		free_irq(IRQ_1HZ, NULL);
+		return -ENODEV;
+	}
+
+	init_sysctl();
+
+	printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n");
+	return 0;
+}
+
+static void __exit rtc_exit(void)
+{
+	cleanup_sysctl();
+	misc_deregister(&rtc_dev);
+	free_irq(IRQ_1HZ, NULL);
+}
+
+module_init(rtc_init);
+module_exit(rtc_exit);
+
+MODULE_AUTHOR("Ray Lehtiniemi");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/ttml.c b/drivers/char/ttml.c
new file mode 100644
index 0000000..ba2cb8e
--- /dev/null
+++ b/drivers/char/ttml.c
@@ -0,0 +1,643 @@
+/*
+ * linux/drivers/char/ttml.c
+ *
+ * TTML TripDawg system devices.
+ *
+ * Copyright 2004, Ray Lehtiniemi
+ * Copyright 2004, Siconix, Inc
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+
+#include <linux/spinlock.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/major.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/ttml.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <asm/arch/regmap.h>
+#include <asm/arch/ssp.h>
+#include <asm/arch/ssp2.h>
+#include <asm/arch/mach-ttml.h>
+
+/* device open/release stuff */
+static DECLARE_MUTEX(mutex);
+static struct cdev ttml_cdev;
+static struct class *ttml_class;
+static int is_open[MAX_TTML_MINORS];
+
+#define minor_get(minor) is_open[(minor)-TTML_MINOR_LED] = 1
+#define minor_put(minor) is_open[(minor)-TTML_MINOR_LED] = 0
+#define minor_busy(minor) (is_open[(minor)-TTML_MINOR_LED] != 0)
+
+static struct {
+	int minor;
+	char *name;
+} devlist[] = {
+	{
+	TTML_MINOR_LED, "led"}, {
+	TTML_MINOR_BUZZER, "buzzer"}, {
+	TTML_MINOR_SPEEDO, "speedo"}, {
+	TTML_MINOR_GPIO, "gpio"}, {
+	TTML_MINOR_BUTTON, "button"}, {
+TTML_MINOR_WD, "wd"},};
+
+/* button and gpio event handling */
+static kmem_cache_t *event_cachep;
+static spinlock_t event_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(button_events);
+static LIST_HEAD(gpio_events);
+static DECLARE_WAIT_QUEUE_HEAD(button_wait);
+static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);
+
+enum ttml_events {
+	TTML_BUTTON_PRESS,
+	TTML_BUTTON_RELEASE,
+	TTML_PTO_RISE,
+	TTML_PTO_FALL,
+	TTML_IGNITION_RISE,
+	TTML_IGNITION_FALL,
+	TTML_SPARE_RISE,
+	TTML_SPARE_FALL,
+};
+
+struct ttml_event {
+	struct list_head l;
+	struct timeval t;
+	enum ttml_events e;
+};
+
+/*  Button and GPIO event monitoring timer */
+
+static struct timer_list monitor_timer;
+static void handle_timer(unsigned long);
+
+static void setup_timer(void)
+{
+	monitor_timer.expires = jiffies + 1;
+	monitor_timer.data = 0;
+	monitor_timer.function = handle_timer;
+	add_timer(&monitor_timer);
+}
+
+static void handle_timer_button(void)
+{
+	static int state = 0;
+	int portf = readl(GPIO_PFDR);
+	int new = (portf & 0x04) ? 0 : 1;
+
+	if (state ^ new) {
+		struct ttml_event *b =
+		    kmem_cache_alloc(event_cachep, GFP_KERNEL);
+		if (b != NULL) {
+			do_gettimeofday(&b->t);
+			b->t.tv_usec |=
+			    ((new ? TTML_BUTTON_PRESS : TTML_BUTTON_RELEASE) <<
+			     24);
+			list_add(&b->l, &button_events);
+			wake_up_interruptible(&button_wait);
+		}
+		state = new;
+	}
+}
+
+static void handle_timer_pto(void)
+{
+	static int state = 0;
+	int portf = readl(GPIO_PFDR);
+	int new = (portf & 0x08) ? 1 : 0;
+
+	if (state ^ new) {
+		struct ttml_event *b =
+		    kmem_cache_alloc(event_cachep, GFP_KERNEL);
+		if (b != NULL) {
+			do_gettimeofday(&b->t);
+			b->t.tv_usec |=
+			    ((new ? TTML_PTO_RISE : TTML_PTO_FALL) << 24);
+			list_add(&b->l, &gpio_events);
+			wake_up_interruptible(&gpio_wait);
+		}
+		state = new;
+	}
+}
+
+static void handle_timer_ignition(void)
+{
+	static int state = 0;
+	int portf = readl(GPIO_PFDR);
+	int new = (portf & 0x02) ? 1 : 0;
+
+	if (state ^ new) {
+		struct ttml_event *b =
+		    kmem_cache_alloc(event_cachep, GFP_KERNEL);
+		if (b != NULL) {
+			do_gettimeofday(&b->t);
+			b->t.tv_usec |=
+			    ((new ? TTML_IGNITION_RISE : TTML_IGNITION_FALL) <<
+			     24);
+			list_add(&b->l, &gpio_events);
+			wake_up_interruptible(&gpio_wait);
+		}
+		state = new;
+	}
+}
+
+static void handle_timer_spare(void)
+{
+	static int state = 0;
+	int porta = readl(GPIO_PADR);
+	int new = (porta & 0x08) ? 1 : 0;
+
+	if (state ^ new) {
+		struct ttml_event *b =
+		    kmem_cache_alloc(event_cachep, GFP_KERNEL);
+		if (b != NULL) {
+			do_gettimeofday(&b->t);
+			b->t.tv_usec |=
+			    ((new ? TTML_SPARE_RISE : TTML_SPARE_FALL) << 24);
+			list_add(&b->l, &gpio_events);
+			wake_up_interruptible(&gpio_wait);
+		}
+		state = new;
+	}
+}
+
+static void handle_timer(unsigned long foo)
+{
+	handle_timer_button();
+	handle_timer_pto();
+	handle_timer_ignition();
+	handle_timer_spare();
+	setup_timer();
+}
+
+static int ttml_read_gpio(struct file *filp, char __user * buf, size_t size,
+			  loff_t * off);
+static int ttml_read_button(struct file *filp, char __user * buf, size_t size,
+			    loff_t * off);
+static unsigned int ttml_poll_gpio(struct file *filp,
+				   struct poll_table_struct *poll);
+static unsigned int ttml_poll_button(struct file *filp,
+				     struct poll_table_struct *poll);
+static int ttml_ioctl(struct inode *inode, struct file *filp,
+		      unsigned int command, unsigned long arg);
+static int ttml_open(struct inode *inode, struct file *filp);
+static int ttml_release(struct inode *inode, struct file *filp);
+
+static struct file_operations ttml_fops = {
+	.owner = THIS_MODULE,
+	.ioctl = ttml_ioctl,
+	.open = ttml_open,
+	.release = ttml_release,
+};
+
+static struct file_operations ttml_fops_gpio = {
+	.owner = THIS_MODULE,
+	.read = ttml_read_gpio,
+	.poll = ttml_poll_gpio,
+	.ioctl = ttml_ioctl,
+	.open = ttml_open,
+	.release = ttml_release,
+};
+
+static struct file_operations ttml_fops_button = {
+	.owner = THIS_MODULE,
+	.read = ttml_read_button,
+	.poll = ttml_poll_button,
+	.ioctl = ttml_ioctl,
+	.open = ttml_open,
+	.release = ttml_release,
+};
+
+static int do_get_led(void __user * arg)
+{
+	struct ttml_ioctl_led a;
+	int porte = readl(GPIO_PEDR);
+	int portb = readl(GPIO_PBDR);
+
+	a.blue = (portb & 0x01) ? 1 : 0;
+	a.red = (porte & 0x02) ? 1 : 0;
+	a.yellow = (porte & 0x01) ? 1 : 0;
+
+	return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
+}
+
+static int do_get_buzzer(void __user * arg)
+{
+	struct ttml_ioctl_buzzer a;
+
+	a.buzzer1 = 0;		/* FIXME */
+
+	return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
+}
+
+static int do_get_speedo(void __user * arg)
+{
+	struct ttml_ioctl_speedo a;
+	unsigned char msg[3] = { 0xaa, 0x82, 0xd7 };
+	unsigned char reply[10];
+	int err;
+
+	err = ssp_do_ttml(&ep93xx_ssp_micro, msg, 3, reply, 10);
+
+	if (err != 0)
+		return err;
+
+	a.instant = 0;		/* FIXME */
+	a.average = (reply[1] << 8) | (reply[2]);
+
+	return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
+}
+
+static int do_get_gpio(void __user * arg)
+{
+	struct ttml_ioctl_gpio a;
+	int porta = readl(GPIO_PADR);
+	int portf = readl(GPIO_PFDR);
+
+	a.pto = (portf & 0x08) ? 0 : 1;
+	a.ignition = (portf & 0x02) ? 0 : 1;
+	a.spare = (porta & 0x08) ? 0 : 1;
+
+	return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
+}
+
+static int do_get_button(void __user * arg)
+{
+	struct ttml_ioctl_button a;
+	int portf = readl(GPIO_PFDR);
+
+	a.button1 = (portf & 0x04) ? 0 : 1;
+
+	return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
+}
+
+static int do_set_led(void __user * arg)
+{
+	struct ttml_ioctl_led a;
+	int porte = readl(GPIO_PEDR);
+	int portb = readl(GPIO_PBDR);
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EIO;
+
+	if (a.yellow)
+		porte |= 0x01;
+	else
+		porte &= ~0x01;
+
+	if (a.red)
+		porte |= 0x02;
+	else
+		porte &= ~0x02;
+
+	if (a.blue)
+		portb |= 0x01;
+	else
+		portb &= ~0x01;
+
+	writel(porte, GPIO_PEDR);
+	writel(portb, GPIO_PBDR);
+
+	return 0;
+}
+
+static int do_set_buzzer(void __user * arg)
+{
+	struct ttml_ioctl_buzzer a;
+	unsigned char msg0[4] = { 0xaa, 0x93, 0x00, 0xc6 };
+	unsigned char msg1[4] = { 0xaa, 0x93, 0x01, 0xc7 };
+	unsigned char reply[10];
+	int err = 0;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EIO;
+
+	if (a.buzzer1)
+		err = ssp_do_ttml(&ep93xx_ssp_micro, msg1, 4, reply, 10);
+	else
+		err = ssp_do_ttml(&ep93xx_ssp_micro, msg0, 4, reply, 10);
+
+	return err;
+}
+
+static int ttml_read_gpio(struct file *filp, char __user * buf, size_t size,
+			  loff_t * off)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct ttml_event *g = NULL;
+	int retval = -EINVAL;
+
+	if (size != sizeof(struct timeval))
+		return -EINVAL;
+
+	add_wait_queue(&gpio_wait, &wait);
+
+	while (1) {
+		unsigned long flags;
+
+		__set_current_state(TASK_INTERRUPTIBLE);
+
+		spin_lock_irqsave(&event_lock, flags);
+		if (!list_empty(&gpio_events))
+			list_for_each_entry(g, &gpio_events, l) {
+			list_del(&g->l);
+			break;
+			}
+
+		spin_unlock_irqrestore(&event_lock, flags);
+
+		if (g != NULL)
+			break;
+
+		if (filp->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto out;
+		}
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+
+		schedule();
+
+	};
+
+	if (copy_to_user(buf, &g->t, sizeof(struct timeval)))
+		retval = -EFAULT;
+	else
+		retval = sizeof(struct timeval);
+
+	kmem_cache_free(event_cachep, g);
+
+      out:
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&gpio_wait, &wait);
+
+	return retval;
+}
+
+static unsigned int ttml_poll_gpio(struct file *filp,
+				   struct poll_table_struct *poll)
+{
+	unsigned long flags;
+	int retval = 0;
+
+	poll_wait(filp, &gpio_wait, poll);
+
+	spin_lock_irqsave(&event_lock, flags);
+	if (!list_empty(&gpio_events))
+		retval = (POLLIN | POLLRDNORM);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return retval;
+}
+
+static int ttml_read_button(struct file *filp, char __user * buf, size_t size,
+			    loff_t * off)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct ttml_event *b = NULL;
+	int retval = -EINVAL;
+
+	if (size != sizeof(struct timeval))
+		return -EINVAL;
+
+	add_wait_queue(&button_wait, &wait);
+
+	while (1) {
+		unsigned long flags;
+
+		__set_current_state(TASK_INTERRUPTIBLE);
+
+		spin_lock_irqsave(&event_lock, flags);
+		if (!list_empty(&button_events)) {
+			list_for_each_entry(b, &button_events, l) {
+				list_del(&b->l);
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&event_lock, flags);
+
+		if (b != NULL)
+			break;
+
+		if (filp->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto out;
+		}
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+
+		schedule();
+
+	};
+
+	if (copy_to_user(buf, &b->t, sizeof(struct timeval)))
+		retval = -EFAULT;
+	else
+		retval = sizeof(struct timeval);
+
+	kmem_cache_free(event_cachep, b);
+
+      out:
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&button_wait, &wait);
+
+	return retval;
+}
+
+static unsigned int ttml_poll_button(struct file *filp,
+				     struct poll_table_struct *poll)
+{
+	unsigned long flags;
+	int retval = 0;
+
+	poll_wait(filp, &button_wait, poll);
+
+	spin_lock_irqsave(&event_lock, flags);
+	if (!list_empty(&button_events))
+		retval = (POLLIN | POLLRDNORM);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return retval;
+}
+
+static int ttml_ioctl(struct inode *inode, struct file *filp,
+		      unsigned int command, unsigned long arg)
+{
+	void __user *p = (void __user *)arg;
+	const int minor = iminor(inode);
+	int err = -ENOSYS;
+
+	switch (command) {
+	case TTML_GET_LED:
+		if (minor == TTML_MINOR_LED)
+			err = do_get_led(p);
+		break;
+	case TTML_GET_BUZZER:
+		if (minor == TTML_MINOR_BUZZER)
+			err = do_get_buzzer(p);
+		break;
+	case TTML_GET_SPEEDO:
+		if (minor == TTML_MINOR_SPEEDO)
+			err = do_get_speedo(p);
+		break;
+	case TTML_GET_GPIO:
+		if (minor == TTML_MINOR_GPIO)
+			err = do_get_gpio(p);
+		break;
+	case TTML_GET_BUTTON:
+		if (minor == TTML_MINOR_BUTTON)
+			err = do_get_button(p);
+		break;
+	case TTML_SET_LED:
+		if (minor == TTML_MINOR_LED)
+			err = do_set_led(p);
+		break;
+	case TTML_SET_BUZZER:
+		if (minor == TTML_MINOR_BUZZER)
+			err = do_set_buzzer(p);
+		break;
+	}
+
+	return err;
+}
+
+static int ttml_open(struct inode *inode, struct file *filp)
+{
+	const int minor = iminor(inode);
+	int err = -EBUSY;
+
+	if (minor == TTML_MINOR_WD) {
+		unsigned char msg[3] = { 0xaa, 0x82, 0xd7 };
+		unsigned char reply[10];
+		ssp_do_ttml(&ep93xx_ssp_micro, msg, 3, reply, 10);
+	}
+
+	down(&mutex);
+	if (minor_busy(minor))
+		goto err;
+	minor_get(minor);
+	if (minor == TTML_MINOR_GPIO)
+		filp->f_op = &ttml_fops_gpio;
+	if (minor == TTML_MINOR_BUTTON)
+		filp->f_op = &ttml_fops_button;
+	err = 0;
+
+      err:
+	up(&mutex);
+	return err;
+}
+
+static int ttml_release(struct inode *inode, struct file *filp)
+{
+	down(&mutex);
+	minor_put(iminor(inode));
+	up(&mutex);
+	return 0;
+}
+
+static int __init ttml_init(void)
+{
+	dev_t dev = MKDEV(TTML_MAJOR, 240);
+	int err = -EIO;
+	int i;
+
+	err = -ENOMEM;
+	event_cachep = kmem_cache_create("ttml_event",
+					 sizeof(struct ttml_event),
+					 0, 0, NULL, NULL);
+	if (event_cachep == NULL)
+		goto err;
+
+	err = -EIO;
+	if (register_chrdev_region(dev, MAX_TTML_MINORS, "ttml"))
+		goto err_uncache;
+
+	cdev_init(&ttml_cdev, &ttml_fops);
+
+	if (cdev_add(&ttml_cdev, dev, MAX_TTML_MINORS)) {
+		kobject_put(&ttml_cdev.kobj);
+		goto err_unreg;
+	}
+
+	ttml_class = class_create(THIS_MODULE, "ttml");
+
+	if (IS_ERR(ttml_class)) {
+		err = PTR_ERR(ttml_class);
+		cdev_del(&ttml_cdev);
+		goto err_unreg;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(devlist); i++)
+		class_device_create(ttml_class,
+					MKDEV(TTML_MAJOR, devlist[i].minor),
+					NULL, "%s", devlist[i].name);
+
+	init_timer(&monitor_timer);
+	setup_timer();
+
+	printk(KERN_INFO "TTML system devices version 0.1\n");
+	return 0;
+
+      err_unreg:
+	unregister_chrdev_region(dev, MAX_TTML_MINORS);
+      err_uncache:
+	kmem_cache_destroy(event_cachep);
+      err:
+	printk(KERN_WARNING "unable to register ttml devices\n");
+	return err;
+}
+
+static void __exit ttml_exit(void)
+{
+	struct ttml_event *b;
+	int i;
+
+	/* stop our button polling timer */
+	del_timer_sync(&monitor_timer);
+
+	/* delete any events captured but not yet read */
+	list_for_each_entry(b, &button_events, l) {
+		list_del(&b->l);
+		kmem_cache_free(event_cachep, b);
+	}
+
+	list_for_each_entry(b, &gpio_events, l) {
+		list_del(&b->l);
+		kmem_cache_free(event_cachep, b);
+	}
+
+	/* free up the event cache */
+	kmem_cache_destroy(event_cachep);
+
+	/* clean up the device */
+	for (i = 0; i < ARRAY_SIZE(devlist); i++)
+		class_device_destroy(ttml_class,
+				MKDEV(TTML_MAJOR, devlist[i].minor));
+	class_destroy(ttml_class);
+	cdev_del(&ttml_cdev);
+	unregister_chrdev_region(MKDEV(TTML_MAJOR, 240), MAX_TTML_MINORS);
+}
+
+module_init(ttml_init);
+module_exit(ttml_exit);
+
+MODULE_AUTHOR("Ray Lehtiniemi");
+MODULE_DESCRIPTION("TTML system devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 344001b..b5a7a90 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -148,6 +148,17 @@ config MPCORE_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called mpcore_wdt.
 
+config EP93XX_WATCHDOG
+	tristate "EP93xx Watchdog"
+	depends on WATCHDOG && ARCH_EP93XX
+	help
+	  Say Y here if to include support for the watchdog timer
+	  in the Cirrus EP93xx family of devices. This driver can
+	  be built as a module by choosing M. The module will
+	  be called ep93xx_wdt.
+
+	  Say N if you are unsure.
+
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index cfd0a39..061671b 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.
 # ARM Architecture
 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
+obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c
new file mode 100644
index 0000000..a2a7a49
--- /dev/null
+++ b/drivers/char/watchdog/ep93xx_wdt.c
@@ -0,0 +1,210 @@
+/*
+ * drivers/watchdog/ep93xx_wdt.c
+ *
+ * Watchdog driver for Cirrus EP93xx family of devices.
+ *
+ * Author: Ray Lehtiniemi <rayl@mail.com>
+ *
+ * Copyright 2004 (c) Ray Lehtiniemi
+ * Based on ep93xx driver.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/*
+    Todo:
+
+    - test last rst from watchdog status
+    - test module loading
+    - test nowayout
+    - test all ioctl, add missing ones
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/arch/regmap.h>
+
+#define WD_VERSION "0.01"
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+static unsigned long wdt_status;
+static unsigned long boot_status;
+
+#define	WDT_IN_USE		0
+#define	WDT_OK_TO_CLOSE		1
+
+static void wdt_enable(void)
+{
+	writel(0xaaaa, WATCHDOG);
+}
+
+static void wdt_disable(void)
+{
+	writel(0xaa55, WATCHDOG);
+}
+
+static void wdt_ping(void)
+{
+	writel(0x5555, WATCHDOG);
+}
+
+static int ep93xx_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+		return -EBUSY;
+
+	clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+	wdt_enable();
+
+	return 0;
+}
+
+static ssize_t
+ep93xx_wdt_write(struct file *file, const char __user * data, size_t len,
+		 loff_t * ppos)
+{
+	/* Can't seek (pwrite) on this device  */
+	if (*ppos != file->f_pos)
+		return -ESPIPE;
+
+	if (len) {
+		if (!nowayout) {
+			size_t i;
+
+			clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+			for (i = 0; i != len; i++) {
+				char c;
+
+				if (get_user(c, data + i))
+					return -EFAULT;
+
+				if (c == 'V')
+					set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+				else
+					clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+			}
+		}
+		wdt_ping();
+	}
+
+	return len;
+}
+
+static struct watchdog_info ident = {
+	.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
+	.identity = "EP93xx Watchdog",
+};
+
+static int
+ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		 unsigned long arg)
+{
+	int ret = -ENOIOCTLCMD;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
+				   sizeof(ident)) ? -EFAULT : 0;
+		break;
+
+	case WDIOC_GETSTATUS:
+		ret = put_user(0, (int __user *)arg);
+		break;
+
+	case WDIOC_GETBOOTSTATUS:
+		ret = put_user(boot_status, (int __user *)arg);
+		break;
+
+	case WDIOC_GETTIMEOUT:
+		/* actually, it is 0.250 seconds.... */
+		ret = put_user(1, (int __user *)arg);
+		break;
+
+	case WDIOC_KEEPALIVE:
+		wdt_ping();
+		ret = 0;
+		break;
+	}
+	return ret;
+}
+
+static int ep93xx_wdt_release(struct inode *inode, struct file *file)
+{
+	if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+		wdt_disable();
+	else
+		printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
+		       "timer will not stop\n");
+
+	clear_bit(WDT_IN_USE, &wdt_status);
+	clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+	return 0;
+}
+
+static struct file_operations ep93xx_wdt_fops = {
+	.owner = THIS_MODULE,
+	.write = ep93xx_wdt_write,
+	.ioctl = ep93xx_wdt_ioctl,
+	.open = ep93xx_wdt_open,
+	.release = ep93xx_wdt_release,
+};
+
+static struct miscdevice ep93xx_wdt_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "EP93xx Watchdog",
+	.fops = &ep93xx_wdt_fops,
+};
+
+static int __init ep93xx_wdt_init(void)
+{
+	int ret;
+
+	ret = misc_register(&ep93xx_wdt_miscdev);
+
+	boot_status = readl(WATCHDOG) & 0x01 ? 1 : 0;
+
+	printk("EP93xx Watchdog: Version " WD_VERSION "%s\n",
+	       (readl(WATCHDOG) & 0x08) ? " (nCS1 disable detected)"
+	       : "");
+
+	return ret;
+}
+
+static void __exit ep93xx_wdt_exit(void)
+{
+	misc_deregister(&ep93xx_wdt_miscdev);
+}
+
+module_init(ep93xx_wdt_init);
+module_exit(ep93xx_wdt_exit);
+
+MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>");
+MODULE_DESCRIPTION("EP93xx Watchdog");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4010fe9..895dfa8 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -95,6 +95,19 @@ config I2C_ELEKTOR
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-elektor.
 
+config I2C_EP93XX
+	tristate "Cirrus EP93XX interface"
+	depends on I2C && ARCH_EP93XX
+	select I2C_ALGOBIT
+	help
+	  This supports the Cirrus EP93xx CPU family I2C bus. Choose this
+	  if you want to access I2C devices connected to EECLK and EEDAT pins
+	  of your EP93XX.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-ep93xx.
+
+
 config I2C_HYDRA
 	tristate "CHRP Apple Hydra Mac I/O I2C interface"
 	depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index f1df00f..fbb35f7 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_I2C_AMD756_S4882)	+= i2c-am
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
+obj-$(CONFIG_I2C_EP93XX)	+= i2c-ep93xx.o
 obj-$(CONFIG_I2C_HYDRA)		+= i2c-hydra.o
 obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
 obj-$(CONFIG_I2C_I810)		+= i2c-i810.o
diff --git a/drivers/i2c/busses/i2c-ep93xx.c b/drivers/i2c/busses/i2c-ep93xx.c
new file mode 100644
index 0000000..1477bf3
--- /dev/null
+++ b/drivers/i2c/busses/i2c-ep93xx.c
@@ -0,0 +1,180 @@
+/* ------------------------------------------------------------------------ *
+ * i2c-ep933xx.c I2C bus glue for Cirrus EP93xx                             *
+ * ------------------------------------------------------------------------ *
+
+   Copyright (C) 2004 Michael Burian
+
+   Based on i2c-parport-light.c
+   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+
+   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.
+ * ------------------------------------------------------------------------ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <asm/io.h>
+#include <asm/arch/regmap.h>
+
+/* 1/(2*clockfrequency) */
+#define EE_DELAY_USEC       50
+#define GPIOG_EECLK 1
+#define GPIOG_EEDAT 2
+
+/* ----- I2C algorithm call-back functions and structures ----------------- */
+
+static void ep93xx_setscl(void *data, int state)
+{
+	unsigned int val, dir;
+
+	val = readl(GPIO_PGDR);
+	dir = readl(GPIO_PGDDR);
+
+	/* Configure the clock line as output. */
+	dir |= GPIOG_EECLK;
+	writel(dir, GPIO_PGDDR);
+
+	/* Set clock line to state */
+	if (state)
+		val |= GPIOG_EECLK;
+	else
+		val &= ~GPIOG_EECLK;
+
+	writel(val, GPIO_PGDR);
+}
+
+static void ep93xx_setsda(void *data, int state)
+{
+	unsigned int val, dir;
+	val = readl(GPIO_PGDR);
+	dir = readl(GPIO_PGDDR);
+
+	/* Configure the data line as output. */
+	dir |= GPIOG_EEDAT;
+	writel(dir, GPIO_PGDDR);
+
+	/* Set data line to state */
+	if (state)
+		val |= GPIOG_EEDAT;
+	else
+		val &= ~GPIOG_EEDAT;
+
+	writel(val, GPIO_PGDR);
+}
+
+static int ep93xx_getscl(void *data)
+{
+	unsigned int val, dir;
+	val = readl(GPIO_PGDR);
+	dir = readl(GPIO_PGDDR);
+
+	/* Configure the clock line as input */
+	dir &= ~GPIOG_EECLK;
+	writel(dir, GPIO_PGDDR);
+
+	/* Return state of the clock line */
+	return (readl(GPIO_PGDR) & GPIOG_EECLK) ? 1 : 0;
+}
+
+static int ep93xx_getsda(void *data)
+{
+	unsigned int val, dir;
+	val = readl(GPIO_PGDR);
+	dir = readl(GPIO_PGDDR);
+
+	/* Configure the data line as input */
+	dir &= ~GPIOG_EEDAT;
+	writel(dir, GPIO_PGDDR);
+
+	/* Return state of the data line */
+	return (readl(GPIO_PGDR) & GPIOG_EEDAT) ? 1 : 0;
+}
+
+static struct i2c_algo_bit_data ep93xx_algo_data = {
+	.setsda = ep93xx_setsda,
+	.setscl = ep93xx_setscl,
+	.getsda = ep93xx_getsda,
+	.getscl = ep93xx_getscl,
+	.udelay = EE_DELAY_USEC,
+	.mdelay = EE_DELAY_USEC * 1000,
+	.timeout = HZ,
+};
+
+/* ----- I2c structure ---------------------------------------------------- */
+
+static struct i2c_adapter ep93xx_adapter = {
+	.owner = THIS_MODULE,
+	.class = I2C_CLASS_HWMON,
+	.id = I2C_HW_B_LP,
+	.algo_data = &ep93xx_algo_data,
+	.name = "EP93XX I2C interface",
+};
+
+/* ----- Module loading, unloading and information ------------------------ */
+
+static int __init i2c_ep93xx_init(void)
+{
+	unsigned long uiVal, uiDDR;
+
+	/* Read the current value of the GPIO data and data direction registers. */
+	uiVal = readl(GPIO_PGDR);
+	uiDDR = readl(GPIO_PGDDR);
+
+	/* If the GPIO pins have not been configured since reset, the data
+	 * and clock lines will be set as inputs and with data value of 0.
+	 * External pullup resisters are pulling them high.
+	 * Set them both high before configuring them as outputs. */
+	uiVal |= (GPIOG_EEDAT | GPIOG_EECLK);
+	writel(uiVal, GPIO_PGDR);
+
+	/* Delay to meet the EE Interface timing specification. */
+	udelay(EE_DELAY_USEC);
+
+	/* Configure the EE data and clock lines as outputs. */
+	writel(0x3, GPIO_EEDRIVE); /* use open drain outputs! */
+	uiDDR |= (GPIOG_EEDAT | GPIOG_EECLK);
+	writel(uiDDR, GPIO_PGDDR);
+
+	/* Delay to meet the EE Interface timing specification. */
+	udelay(EE_DELAY_USEC);
+
+	/* Reset hardware to a sane state (SCL and SDA high) */
+	ep93xx_setsda(NULL, 1);
+	ep93xx_setscl(NULL, 1);
+
+	if (i2c_bit_add_bus(&ep93xx_adapter) < 0) {
+		printk(KERN_ERR "i2c-ep93xx: Unable to register with I2C\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit i2c_ep93xx_exit(void)
+{
+	i2c_bit_del_bus(&ep93xx_adapter);
+}
+
+MODULE_AUTHOR("Michael Burian");
+MODULE_DESCRIPTION("I2C bus glue for Cirrus EP93xx processors");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_ep93xx_init);
+module_exit(i2c_ep93xx_exit);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index f9fae28..45f9286 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -25,6 +25,18 @@ config SENSORS_DS1374
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1374.
 
+config SENSORS_DS1307
+	tristate "Dallas Semiconductor DS1307 RTC"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Dallas Semiconductor
+	  DS1307 RTC. Usually only embedded devices will need this.
+
+	  Only say yes here if your sure you have such a chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ds1307.
+
 config SENSORS_EEPROM
 	tristate "EEPROM reader"
 	depends on I2C && EXPERIMENTAL
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 46178b5..90be351 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_SENSORS_DS1337)	+= ds1337.o
+obj-$(CONFIG_SENSORS_DS1307)	+= ds1307.o
 obj-$(CONFIG_SENSORS_DS1374)	+= ds1374.o
 obj-$(CONFIG_SENSORS_EEPROM)	+= eeprom.o
 obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
diff --git a/drivers/i2c/chips/ds1307.c b/drivers/i2c/chips/ds1307.c
new file mode 100644
index 0000000..76ea8b8
--- /dev/null
+++ b/drivers/i2c/chips/ds1307.c
@@ -0,0 +1,651 @@
+/*
+ * ds1307.c
+ *
+ * Device driver for Dallas Semiconductor's Real Time Controller DS1307.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/string.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+
+#include "ds1307.h"
+
+#undef DEBUG
+#ifdef DEBUG
+static unsigned int rtc_debug = DEBUG;
+#define DPRINTK(i,x...)	do { if (rtc_debug > (i)) printk(x); } while (0)
+#else
+#define rtc_debug 0	/* gcc will remove all the debug code for us */
+#define DPRINTK(i,x...)	do { } while (0)
+#endif
+
+static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR;
+
+struct i2c_driver ds1307_driver;
+struct i2c_client *ds1307_i2c_client = 0;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+	normal_i2c:		normal_addr,
+	probe:			ignore,
+	ignore: 		ignore,
+	force:			ignore,
+};
+
+static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long);
+static int ds1307_rtc_open(struct inode *inode, struct file *file);
+static int ds1307_rtc_release(struct inode *inode, struct file *file);
+
+static struct file_operations rtc_fops = {
+	owner:		THIS_MODULE,
+	ioctl:		ds1307_rtc_ioctl,
+	open:		ds1307_rtc_open,
+	release:	ds1307_rtc_release,
+};
+
+static struct miscdevice ds1307_rtc_miscdev = {
+	RTC_MINOR,
+	"rtc",
+	&rtc_fops
+};
+
+static int ds1307_probe(struct i2c_adapter *adap);
+static int ds1307_detach(struct i2c_client *client);
+static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg);
+
+struct i2c_driver ds1307_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "DS1307",
+	.id		= I2C_DRIVERID_DS1307,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= ds1307_probe,
+	.detach_client	= ds1307_detach,
+	.command	= ds1307_command,
+};
+
+static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED;
+
+static int
+ds1307_readram( char *buf, int len)
+{
+	unsigned long	flags;
+	unsigned char ad[1] = { 0 };
+	int ret;
+	struct i2c_msg msgs[2] = {
+		{ ds1307_i2c_client->addr  , 0,        1, ad  },
+		{ ds1307_i2c_client->addr  , I2C_M_RD, len, buf } };
+
+	spin_lock_irqsave(&ds1307_rtc_lock, flags);
+	ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
+	spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
+
+	return ret;
+}
+
+static void
+ds1307_dumpram( void)
+{
+	unsigned char buf[DS1307_RAM_SIZE];
+	int ret;
+
+	ret = ds1307_readram( buf, DS1307_RAM_SIZE);
+
+	if( ret > 0)
+	{
+		int i;
+		for( i=0; i<DS1307_RAM_SIZE; i++)
+		{
+			printk ("%02X ", buf[i]);
+			if( (i%8) == 7) printk ("\n");
+		}
+		printk ("\n");
+	}
+}
+
+static void
+ds1307_enable_clock( int enable)
+{
+	unsigned char buf[2], ad[1] = { 0 };
+	struct i2c_msg msgs[2] = {
+		{ ds1307_i2c_client->addr	, 0,	    1, ad  },
+		{ ds1307_i2c_client->addr	, I2C_M_RD, 1, buf }
+	};
+	unsigned char ctrl_info;
+	int ret;
+
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+
+	if (enable)
+		ctrl_info = SQW_ENABLE | RATE_32768HZ;
+	else
+		ctrl_info = SQW_DISABLE;
+	ret = ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info);
+	DPRINTK(2, "%s: set ctrl rtn'd %d\n", __FUNCTION__, ret);
+
+	/* read addr 0 (Clock-Halt bit and second counter */
+	ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
+	DPRINTK(2, "%s: %s msg xfer rtn'd %d\n", __FUNCTION__, enable ? "enable" : "disable", ret);
+
+	if (enable)
+		buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */
+	else
+		buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */
+	buf[0] = 0;	/* control register address on DS1307 */
+
+	ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2);
+	DPRINTK(2, "%s: master send rtn'd %d\n", __FUNCTION__, ret);
+}
+
+static int
+ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt);
+
+static int
+ds1307_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct i2c_client *c;
+
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+
+	c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return -ENOMEM;
+	memset(c, 0, sizeof(*c));
+
+	strcpy(c->name, "DS1307");
+	c->flags	= 0;
+	c->addr 	= addr;
+	c->adapter	= adap;
+	c->driver	= &ds1307_driver;
+
+	ds1307_i2c_client = c;
+	ds1307_enable_clock(1);
+
+#define DS1307_SET_TIME_ON_BOOT
+#ifdef DS1307_SET_TIME_ON_BOOT
+	{
+		struct rtc_time dt;
+		ds1307_get_datetime(c, &dt);
+		xtime.tv_sec = mktime(dt.tm_year + 1900,
+				      dt.tm_mon + 1, /* tm_mon starts from 0 */
+				      dt.tm_mday,
+				      dt.tm_hour,
+				      dt.tm_min,
+				      dt.tm_sec);
+	}
+#endif
+
+	return i2c_attach_client(c);
+}
+
+static int
+ds1307_probe(struct i2c_adapter *adap)
+{
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+
+	return i2c_probe(adap, &addr_data, ds1307_attach);
+}
+
+static int
+ds1307_detach(struct i2c_client *client)
+{
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+
+	i2c_detach_client(client);
+	ds1307_enable_clock(0);
+
+	return 0;
+}
+
+static void
+ds1307_convert_to_time( struct rtc_time *dt, char *buf)
+{
+	dt->tm_sec = BCD_TO_BIN(buf[0]);
+	dt->tm_min = BCD_TO_BIN(buf[1]);
+
+	if ( TWELVE_HOUR_MODE(buf[2]) )
+	{
+		dt->tm_hour = HOURS_12(buf[2]);
+		if (HOURS_AP(buf[2])) /* PM */
+		{
+			dt->tm_hour += 12;
+		}
+	}
+	else /* 24-hour-mode */
+	{
+		dt->tm_hour = HOURS_24(buf[2]);
+	}
+
+	dt->tm_mday = BCD_TO_BIN(buf[4]);
+	/* dt->tm_mon is zero-based */
+	dt->tm_mon = BCD_TO_BIN(buf[5]) - 1;
+	/* year is 1900 + dt->tm_year */
+	dt->tm_year = BCD_TO_BIN(buf[6]) + 100;
+
+	if (rtc_debug > 1)
+	{
+		printk("ds1307_get_datetime: year = %d\n", dt->tm_year);
+		printk("ds1307_get_datetime: mon  = %d\n", dt->tm_mon);
+		printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday);
+		printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour);
+		printk("ds1307_get_datetime: min  = %d\n", dt->tm_min);
+		printk("ds1307_get_datetime: sec  = %d\n", dt->tm_sec);
+	}
+}
+
+static int
+ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+	unsigned char buf[7], addr[1] = { 0 };
+	struct i2c_msg msgs[2] = {
+		{ 0, 0,	  1, addr },
+		{ 0, I2C_M_RD, 7, buf  }
+	};
+	int ret = -EIO;
+
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+
+	if (client) {
+
+		msgs[0].addr = client->addr;
+		msgs[1].addr = client->addr;
+
+		memset(buf, 0, sizeof(buf));
+
+		ret = i2c_transfer(client->adapter, msgs, 2);
+
+		if (ret == 2) {
+			ds1307_convert_to_time( dt, buf);
+			ret = 0;
+		} else {
+			DPRINTK(0, "%s: i2c_transfer() returned %d\n", __FUNCTION__, ret);
+		}
+	}
+	return ret;
+}
+
+static int
+ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
+{
+	unsigned char buf[8];
+	int ret, len = 4;
+
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+
+	if (!client) return -EIO;
+
+	if (rtc_debug > 1)
+	{
+		printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year);
+		printk("ds1307_set_datetime: tm_mon  = %d\n", dt->tm_mon);
+		printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday);
+		printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour);
+		printk("ds1307_set_datetime: tm_min  = %d\n", dt->tm_min);
+		printk("ds1307_set_datetime: tm_sec  = %d\n", dt->tm_sec);
+	}
+
+	buf[0] = 0;	/* register address on DS1307 */
+	buf[1] = (BIN_TO_BCD(dt->tm_sec));
+	buf[2] = (BIN_TO_BCD(dt->tm_min));
+	buf[3] = (BIN_TO_BCD(dt->tm_hour));
+
+	if (datetoo) {
+		len = 8;
+		/* we skip buf[4] as we don't use day-of-week. */
+		buf[5] = (BIN_TO_BCD(dt->tm_mday));
+		buf[6] = (BIN_TO_BCD(dt->tm_mon + 1));
+		/* The year only ranges from 0-99, we are being passed an offset from 1900,
+		 * and the chip calulates leap years based on 2000, thus we adjust by 100.
+		 */
+		buf[7] = (BIN_TO_BCD(dt->tm_year - 100));
+	}
+	ret = i2c_master_send(client, (char *)buf, len);
+	if (ret == len)
+		ret = 0;
+	else
+		DPRINTK(0, "%s: i2c_master_send() returned %d\n", __FUNCTION__, ret);
+
+	return ret;
+}
+
+static int
+ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+	unsigned char addr[1] = { 7 };	/* control register address on DS1307 */
+	struct i2c_msg msgs[2] = {
+		{ 0, 0,        1, addr },
+		{ 0, I2C_M_RD, 1, ctrl }
+	};
+	int ret = -EIO;
+
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+
+	if (client) {
+
+		msgs[0].addr = client->addr;
+		msgs[1].addr = client->addr;
+
+		*ctrl = 0;
+
+		ret = i2c_transfer(client->adapter, msgs, 2);
+
+		if (ret == 2) {
+			DPRINTK(2, "%s: info %d\n", __FUNCTION__, *ctrl);
+			ret = 0;
+		} else {
+			DPRINTK(0, "%s: i2c_transfer() returned %d\n", __FUNCTION__, ret);
+		}
+	}
+
+	return ret;
+}
+
+static int
+ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo)
+{
+	unsigned char buf[2];
+	int ret;
+
+	buf[0] = 7;	/* control register address on DS1307 */
+	buf[1] = *cinfo;
+
+	DPRINTK(2, "%s: info %d\n", __FUNCTION__, buf[1]);
+
+	ret = i2c_master_send(client, (char *)buf, 2);
+
+	return ret;
+}
+
+static int
+ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+	unsigned char addr[1];
+	struct i2c_msg msgs[2] = {
+		{ client->addr, 0,	  1, addr },
+		{ client->addr, I2C_M_RD, mem->nr, mem->data }
+	};
+
+	if ( (mem->loc < DS1307_RAM_ADDR_START) ||
+	     ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
+		return -EINVAL;
+
+	addr[0] = mem->loc;
+
+	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int
+ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+	unsigned char addr[1];
+	struct i2c_msg msgs[2] = {
+		{ client->addr, 0, 1, addr },
+		{ client->addr, 0, mem->nr, mem->data }
+	};
+
+	if ( (mem->loc < DS1307_RAM_ADDR_START) ||
+	     ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
+		return -EINVAL;
+
+	addr[0] = mem->loc;
+
+	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int
+ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	DPRINTK(1, "%s: cmd %d\n", __FUNCTION__, cmd);
+
+	switch (cmd) {
+	case DS1307_GETDATETIME:
+		return ds1307_get_datetime(client, arg);
+
+	case DS1307_SETTIME:
+		return ds1307_set_datetime(client, arg, 0);
+
+	case DS1307_SETDATETIME:
+		return ds1307_set_datetime(client, arg, 1);
+
+	case DS1307_GETCTRL:
+		return ds1307_get_ctrl(client, arg);
+
+	case DS1307_SETCTRL:
+		return ds1307_set_ctrl(client, arg);
+
+	case DS1307_MEM_READ:
+		return ds1307_read_mem(client, arg);
+
+	case DS1307_MEM_WRITE:
+		return ds1307_write_mem(client, arg);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int
+ds1307_rtc_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int
+ds1307_rtc_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int
+ds1307_rtc_ioctl( struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	unsigned long	flags;
+	struct rtc_time wtime;
+	int status = 0;
+
+	DPRINTK(2, "%s: cmd %c %x\n", __FUNCTION__, (char)(cmd>>8)&0xff, cmd&0xff);
+
+	switch (cmd) {
+		default:
+		case RTC_UIE_ON:
+		case RTC_UIE_OFF:
+		case RTC_PIE_ON:
+		case RTC_PIE_OFF:
+		case RTC_AIE_ON:
+		case RTC_AIE_OFF:
+		case RTC_ALM_SET:
+		case RTC_ALM_READ:
+		case RTC_IRQP_READ:
+		case RTC_IRQP_SET:
+		case RTC_EPOCH_READ:
+		case RTC_EPOCH_SET:
+		case RTC_WKALM_SET:
+		case RTC_WKALM_RD:
+			status = -EINVAL;
+			break;
+
+		case RTC_RD_TIME:
+			spin_lock_irqsave(&ds1307_rtc_lock, flags);
+			ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime);
+			spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
+
+			if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)))
+				status = -EFAULT;
+			break;
+
+		case RTC_SET_TIME:
+			if (!capable(CAP_SYS_TIME))
+			{
+				status = -EACCES;
+				break;
+			}
+
+			if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
+			{
+				status = -EFAULT;
+				break;
+			}
+
+			spin_lock_irqsave(&ds1307_rtc_lock, flags);
+			ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime);
+			spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
+			break;
+	}
+
+	return status;
+}
+
+static char *
+ds1307_mon2str( unsigned int mon)
+{
+	char *mon2str[12] = {
+	  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+	};
+	if( mon > 11) return "error";
+	else return mon2str[ mon];
+}
+
+static int ds1307_rtc_proc_output( char *buf)
+{
+#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no")
+	unsigned char ram[DS1307_RAM_SIZE];
+	int ret;
+
+	char *p = buf;
+
+	ret = ds1307_readram( ram, DS1307_RAM_SIZE);
+	if( ret > 0)
+	{
+		int i;
+		struct rtc_time dt;
+		char text[9];
+
+		p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n");
+
+		ds1307_convert_to_time( &dt, ram);
+		p += sprintf(p, "Date/Time	     : %02d-%s-%04d %02d:%02d:%02d\n",
+			dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900,
+			dt.tm_hour, dt.tm_min, dt.tm_sec);
+
+		p += sprintf(p, "Clock halted	     : %s\n", CHECK(ram[0],0x80));
+		p += sprintf(p, "24h mode	     : %s\n", CHECK(ram[2],0x40));
+		p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10));
+		p += sprintf(p, "Freq		     : ");
+
+		switch( ram[7] & 0x03)
+		{
+			case RATE_1HZ:
+				p += sprintf(p, "1Hz\n");
+				break;
+			case RATE_4096HZ:
+				p += sprintf(p, "4.096kHz\n");
+				break;
+			case RATE_8192HZ:
+				p += sprintf(p, "8.192kHz\n");
+				break;
+			case RATE_32768HZ:
+			default:
+				p += sprintf(p, "32.768kHz\n");
+				break;
+
+		}
+
+		p += sprintf(p, "RAM dump:\n");
+		text[8]='\0';
+		for( i=0; i<DS1307_RAM_SIZE; i++)
+		{
+			p += sprintf(p, "%02X ", ram[i]);
+
+			if( (ram[i] < 32) || (ram[i]>126)) ram[i]='.';
+			text[i%8] = ram[i];
+			if( (i%8) == 7) p += sprintf(p, "%s\n",text);
+		}
+		p += sprintf(p, "\n");
+	}
+	else
+	{
+		p += sprintf(p, "Failed to read RTC memory!\n");
+	}
+
+	return	p - buf;
+}
+
+static int ds1307_rtc_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data)
+{
+	int len = ds1307_rtc_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;
+}
+
+static __init int ds1307_init(void)
+{
+	int retval=0;
+
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+
+	if (slave_address != 0xffff)
+	{
+		DPRINTK(2, "%s: slave address is %#x\n", __FUNCTION__, slave_address);
+		normal_addr[0] = slave_address;
+	}
+
+	if (normal_addr[0] == 0xffff)
+	{
+		printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n",
+			normal_addr[0]);
+		return -EINVAL;
+	}
+
+	retval = i2c_add_driver(&ds1307_driver);
+
+	if (retval==0)
+	{
+		misc_register (&ds1307_rtc_miscdev);
+		create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL);
+		printk("I2C: DS1307 RTC driver successfully loaded\n");
+		if (rtc_debug > 2) ds1307_dumpram();
+	}
+	return retval;
+}
+
+static __exit void ds1307_exit(void)
+{
+	DPRINTK(1, "%s()\n", __FUNCTION__);
+	remove_proc_entry (PROC_DS1307_NAME, NULL);
+	misc_deregister(&ds1307_rtc_miscdev);
+	i2c_del_driver(&ds1307_driver);
+}
+
+module_init(ds1307_init);
+module_exit(ds1307_exit);
+
+MODULE_PARM (slave_address, "i");
+MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC.");
+
+MODULE_AUTHOR ("Intrinsyc Software Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/ds1307.h b/drivers/i2c/chips/ds1307.h
new file mode 100644
index 0000000..bf8cc20
--- /dev/null
+++ b/drivers/i2c/chips/ds1307.h
@@ -0,0 +1,54 @@
+/*
+ * ds1307.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 DS1307_H
+#define DS1307_H
+
+#define DS1307_I2C_SLAVE_ADDR	0x68
+
+#define DS1307_RAM_ADDR_START	0x08
+#define DS1307_RAM_ADDR_END	0x3F
+#define DS1307_RAM_SIZE 0x40
+
+#define PROC_DS1307_NAME	"driver/ds1307"
+
+struct rtc_mem {
+	unsigned int	loc;
+	unsigned int	nr;
+	unsigned char	*data;
+};
+
+#define DS1307_GETDATETIME	0
+#define DS1307_SETTIME		1
+#define DS1307_SETDATETIME	2
+#define DS1307_GETCTRL		3
+#define DS1307_SETCTRL		4
+#define DS1307_MEM_READ		5
+#define DS1307_MEM_WRITE	6
+
+#define SQW_ENABLE	0x10	/* Square Wave Enable */
+#define SQW_DISABLE	0x00	/* Square Wave disable */
+
+#define RATE_32768HZ	0x03	/* Rate Select 32.768KHz */
+#define RATE_8192HZ	0x02	/* Rate Select 8.192KHz */
+#define RATE_4096HZ	0x01	/* Rate Select 4.096KHz */
+#define RATE_1HZ	0x00	/* Rate Select 1Hz */
+
+#define CLOCK_HALT	0x80	/* Clock Halt */
+
+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
+#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
+
+#define TWELVE_HOUR_MODE(n)	(((n)>>6)&1)
+#define HOURS_AP(n)		(((n)>>5)&1)
+#define HOURS_12(n)		BCD_TO_BIN((n)&0x1F)
+#define HOURS_24(n)		BCD_TO_BIN((n)&0x3F)
+
+#endif
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 02682fb..6a28f08 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -338,12 +338,37 @@ exit:
 static void ds1337_init_client(struct i2c_client *client)
 {
 	s32 val;
+	u8 status, control;
+
+	/* On some boards, the RTC isn't configured by boot firmware.
+	 * Handle that case by starting/configuring the RTC now.
+	 */
+	status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+	control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+
+	if ((status & 0x80) || (control & 0x80)) {
+		/* RTC not running */
+		u8 buf[16];
+		struct i2c_msg msg[1];
+		
+		dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
+
+		/* Initialize all, including STATUS and CONTROL to zero */
+		memset(buf, 0, sizeof(buf));
+		msg[0].addr = client->addr;
+		msg[0].flags = 0;
+		msg[0].len = sizeof(buf);
+		msg[0].buf = &buf[0];
+		
+		i2c_transfer(client->adapter, msg, 1);
+	} else {
+		/* Running: ensure that device is set in 24-hour mode */
+		val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+		if ((val >= 0) && (val & (1 << 6)))
+			i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+						  val & 0x3f);
+	}
 
-	/* Ensure that device is set in 24-hour mode */
-	val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
-	if ((val >= 0) && (val & (1 << 6)))
-		i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
-					  val & 0x3f);
 }
 
 static int ds1337_detach_client(struct i2c_client *client)
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 1c81174..e0fcc08 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -314,6 +314,18 @@ config BLK_DEV_CMD640_ENHANCED
 	  and your BIOS does not already do this for you, then say Y here.
 	  Otherwise say N.
 
+config BLK_DEV_EP93XX
+	bool "EP93xx support"
+	depends on (ARCH_EP9312 || ARCH_EP9315)
+	help
+	  If you want IDE support for your EP93xx based board say Y here.
+
+config BLK_DEV_IDEDMA_EP93XX
+	bool "EP93xx DMA support"
+	depends on BLK_DEV_EP93XX && EP93XX_DMA
+	help
+	  If you want DMA support for your EP93xx based board say Y here.
+
 config BLK_DEV_IDEPNP
 	bool "PNP EIDE support"
 	depends on PNP
@@ -813,7 +825,7 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
        depends BLK_DEV_IDE_AU1XXX
 
 config IDE_ARM
-	def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
+	def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK || BLK_DEV_EP93XX)
 
 config BLK_DEV_IDE_ICSIDE
 	tristate "ICS IDE interface support"
@@ -1047,7 +1059,7 @@ config BLK_DEV_UMC8672
 endif
 
 config BLK_DEV_IDEDMA
-	def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+	def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA || BLK_DEV_IDEDMA_EP93XX
 
 config IDEDMA_IVB
 	bool "IGNORE word93 Validation BITS"
diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
index 6a78f07..cf0f91a 100644
--- a/drivers/ide/arm/Makefile
+++ b/drivers/ide/arm/Makefile
@@ -2,5 +2,6 @@
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
 obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
+obj-$(CONFIG_BLK_DEV_EP93XX)		+= ide-ep93xx.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
diff --git a/drivers/ide/arm/ide-ep93xx.c b/drivers/ide/arm/ide-ep93xx.c
new file mode 100644
index 0000000..75fbbf5
--- /dev/null
+++ b/drivers/ide/arm/ide-ep93xx.c
@@ -0,0 +1,1957 @@
+/*****************************************************************************
+ *
+ * drivers/ide/ide-ep93xx.c
+ *
+ *  Copyright (c) 2003 Cirrus Logic, Inc.
+ *
+ * Some code based in whole or in part on:
+ *
+ *      linux/drivers/ide/ide-dma.c		Version 4.13	May 21, 2003
+ *
+ *      Copyright (c) 1999-2000	Andre Hedrick <andre@linux-ide.org>
+ *      May be copied or modified under the terms of the GNU General Public License
+ *
+ *      Portions Copyright Red Hat 2003
+ *
+ *      Special Thanks to Mark for his Six years of work.
+ *
+ *      Copyright (c) 1995-1998  Mark Lord
+ *      May be copied or modified under the terms of the GNU General Public License
+ *
+ *
+ * Some code taken from the PowerMac implentation
+ *
+ *      Copyright (C) 1998-2001 Paul Mackerras & Ben. Herrenschmidt
+ *
+ * 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
+ *
+ * ***************************************************************************
+ *
+ * Cirrus Logic's EP93XX architecture specific ide driver. This driver
+ * supports the following ide transfer modes:
+ *  PIO modes 0 - 4
+ *  MDMA modes 0 - 2
+ *  UDMA modes 0 - 4
+ *
+ * 2/17/04 - TO - Initial DMA support.  Only UDMA on ATA hard drives for now.
+ *
+ ****************************************************************************/
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/ide.h>
+#include <asm/io.h>
+
+#include <asm/arch/ide.h>
+
+#include <asm/arch/dma.h>
+#include <asm/hardware.h>
+
+/*****************************************************************************
+ *
+ * Debugging macros
+ *
+ ****************************************************************************/
+#undef DEBUG
+ /* #define DEBUG 1 */
+#ifdef DEBUG
+#define DPRINTK( x... )  printk( ##x )
+#else
+#define DPRINTK( x... )
+#endif
+
+/*
+ *  IDE control register mask used when setting the CS0n, CS1n and DA bits
+ *  in this register.
+ */
+#define IDECR_REG_MASK          (IDECtrl_CS0n | IDECtrl_CS1n | IDECtrl_DA_MASK)
+
+/*****************************************************************************
+ *
+ * Functions and macros for handling dma transfers.
+ *
+ ****************************************************************************/
+#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
+
+/*****************************************************************************
+ *
+ * Our Physical Region Descriptor (PRD) table should be large enough
+ * to handle the biggest I/O request we are likely to see.  Since requests
+ * can have no more than 256 sectors, and since the typical blocksize is
+ * two or more sectors, we could get by with a limit of 128 entries here for
+ * the usual worst case.  Most requests seem to include some contiguous blocks,
+ * further reducing the number of table entries required.
+ *
+ * The driver reverts to PIO mode for individual requests that exceed
+ * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
+ * 100% of all crazy scenarios here is not necessary.
+ *
+ * As it turns out though, we must allocate a full 4KB page for this,
+ * so the two PRD tables (ide0 & ide1) will each get half of that,
+ * allowing each to have about 256 entries (8 bytes each) from this.
+ *
+ ****************************************************************************/
+#define PRD_BYTES	8
+#define PRD_ENTRIES	(PAGE_SIZE / (2 * PRD_BYTES))
+
+/*****************************************************************************
+ *
+ * Global to keep track of the number of entries in the dma buffer
+ * table for each transfer.
+ *
+ ****************************************************************************/
+static int g_prd_count;
+static unsigned int g_prd_total;
+static unsigned int g_prd_returned;
+static unsigned int g_dma_table_base;
+
+/*****************************************************************************
+ *
+ * Global to set during the dma callback function to indicate that from
+ * the dma perspective, the transfer is complete.
+ *
+ ****************************************************************************/
+static unsigned int g_done;
+
+/*****************************************************************************
+ *
+ * The following is directly from ide-dma.c.
+ *
+ ****************************************************************************/
+struct drive_list_entry {
+	const char *id_model;
+	const char *id_firmware;
+};
+
+static const struct
+drive_list_entry drive_whitelist[] = {
+	{"Micropolis 2112A", "ALL"},
+	{"CONNER CTMA 4000", "ALL"},
+	{"CONNER CTT8000-A", "ALL"},
+	{"ST34342A", "ALL"},
+	{NULL, NULL}
+};
+
+static const struct
+drive_list_entry drive_blacklist[] = {
+	{"WDC AC11000H", "ALL"},
+	{"WDC AC22100H", "ALL"},
+	{"WDC AC32500H", "ALL"},
+	{"WDC AC33100H", "ALL"},
+	{"WDC AC31600H", "ALL"},
+	{"WDC AC32100H", "24.09P07"},
+	{"WDC AC23200L", "21.10N21"},
+	{"Compaq CRD-8241B", "ALL"},
+	{"CRD-8400B", "ALL"},
+	{"CRD-8480B", "ALL"},
+	{"CRD-8480C", "ALL"},
+	{"CRD-8482B", "ALL"},
+	{"CRD-84", "ALL"},
+	{"SanDisk SDP3B", "ALL"},
+	{"SanDisk SDP3B-64", "ALL"},
+	{"SANYO CD-ROM CRD", "ALL"},
+	{"HITACHI CDR-8", "ALL"},
+	{"HITACHI CDR-8335", "ALL"},
+	{"HITACHI CDR-8435", "ALL"},
+	{"Toshiba CD-ROM XM-6202B", "ALL"},
+	{"CD-532E-A", "ALL"},
+	{"E-IDE CD-ROM CR-840", "ALL"},
+	{"CD-ROM Drive/F5A", "ALL"},
+	{"RICOH CD-R/RW MP7083A", "ALL"},
+	{"WPI CDD-820", "ALL"},
+	{"SAMSUNG CD-ROM SC-148C", "ALL"},
+	{"SAMSUNG CD-ROM SC-148F", "ALL"},
+	{"SAMSUNG CD-ROM SC", "ALL"},
+	{"SanDisk SDP3B-64", "ALL"},
+	{"SAMSUNG CD-ROM SN-124", "ALL"},
+	{"PLEXTOR CD-R PX-W8432T", "ALL"},
+	{"ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL"},
+	{"_NEC DV5800A", "ALL"},
+	{NULL, NULL}
+};
+
+/*****************************************************************************
+ *
+ *	This is directly from ide-dma.c
+ *
+ *  in_drive_list	-	look for drive in black/white list
+ *	@id: drive identifier
+ *	@drive_table: list to inspect
+ *
+ *	Look for a drive in the blacklist and the whitelist tables
+ *	Returns 1 if the drive is found in the table.
+ *
+ ****************************************************************************/
+static int
+in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
+{
+	for (; drive_table->id_model; drive_table++)
+		if ((!strcmp(drive_table->id_model, id->model)) &&
+		    ((!strstr(drive_table->id_firmware, id->fw_rev)) ||
+		     (!strcmp(drive_table->id_firmware, "ALL"))))
+			return 1;
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_intr() is the handler for disk read/write DMA interrupts
+ *
+ ****************************************************************************/
+ide_startstop_t ep93xx_ide_dma_intr(ide_drive_t * drive)
+{
+	int i;
+	byte stat, dma_stat;
+
+	DPRINTK("\n dma_intr \n");
+
+	/*
+	 *  Disable the dma for this transfer and cleanup.
+	 */
+	dma_stat = ep93xx_ide_dma_end(drive);
+
+	/*
+	 *  Get status from the ide device.
+	 */
+	stat = HWIF(drive)->INB(IDE_STATUS_REG);
+
+	if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
+		if (!dma_stat) {
+			struct request *rq = HWGROUP(drive)->rq;
+
+			for (i = rq->nr_sectors; i > 0;) {
+				i -= rq->current_nr_sectors;
+				DRIVER(drive)->end_request(drive, 1);
+			}
+
+			return ide_stopped;
+		}
+
+		printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
+		       drive->name, dma_stat);
+	}
+
+	return DRIVER(drive)->error(drive, __FUNCTION__, stat);
+}
+
+/*****************************************************************************
+ *
+ * ide_build_sglist()
+ *
+ * Builds a table of buffers to be used by the dma.  Each buffer consists
+ * of a region of memory which is contiguous in virtual memory.
+ *
+ ****************************************************************************/
+static int ide_build_sglist(ide_hwif_t * hwif, struct request *rq)
+{
+	struct buffer_head *buf_head;
+	struct scatterlist *sg = hwif->sg_table;
+	int nents = 0;
+
+	if (hwif->sg_dma_active)
+		BUG();
+
+	DPRINTK("\nbuild_sglist: sg_table 0x%x, ", hwif->sg_table);
+
+	/*
+	 *  Set up the direction of the command
+	 */
+	if (rq->cmd == READ) {
+		hwif->sg_dma_direction = EP93XX_DMA_FROMDEVICE;
+	} else {
+		hwif->sg_dma_direction = EP93XX_DMA_TODEVICE;
+	}
+
+	/*
+	 *  Get a pointer to the buffer head.
+	 */
+	buf_head = rq->bh;
+
+	do {
+		unsigned char *virt_addr = buf_head->b_data;
+		unsigned int size = buf_head->b_size;
+
+		if (nents >= PRD_ENTRIES) {
+			return 0;
+		}
+
+		while ((buf_head = buf_head->b_reqnext) != NULL) {
+			if ((virt_addr + size) !=
+			    (unsigned char *)buf_head->b_data) {
+				break;
+			}
+
+			size += buf_head->b_size;
+		}
+		memset(&sg[nents], 0, sizeof(*sg));
+		sg[nents].address = virt_addr;
+		sg[nents].length = size;
+		nents++;
+	} while (buf_head != NULL);
+
+	/*
+	 *  This call to map_sg will return the number of entries
+	 *  for which DMAable memory could be mapped.
+	 */
+	return ep93xx_map_sg(sg, nents, hwif->sg_dma_direction);
+}
+
+/****************************************************************************
+ *
+ * report_drive_dmaing()
+ *
+ ****************************************************************************/
+int report_drive_dmaing(ide_drive_t * drive)
+{
+	struct hd_driveid *id = drive->id;
+
+	if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
+	    (id->dma_ultra & (id->dma_ultra >> 14) & 3)) {
+		if ((id->dma_ultra >> 15) & 1) {
+			/*
+			 *  UDMA enabled
+			 */
+			printk(", UDMA(mode 7)");
+		} else {
+			/*
+			 *  UDMA enabled.
+			 */
+			printk(", UDMA(133)");
+		}
+	} else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
+		   (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
+		DPRINTK("\n report_drive_dmaing: %d \n", id->dma_ultra);
+		if ((id->dma_ultra >> 13) & 1) {
+			/*
+			 *  UDMA enabled!
+			 */
+			printk(", UDMA(100)");
+		} else if ((id->dma_ultra >> 12) & 1) {
+			/*
+			 *  UDMA enabled.
+			 */
+			printk(", UDMA(66)");
+		} else {
+			/*
+			 *  UDMA enabled.
+			 */
+			printk(", UDMA(44)");
+		}
+	} else if ((id->field_valid & 4) &&
+		   (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
+		if ((id->dma_ultra >> 10) & 1) {
+			/*
+			 * UDMA enabled.
+			 */
+			printk(", UDMA(33)");
+		} else if ((id->dma_ultra >> 9) & 1) {
+			/*
+			 *  UDMA enabled.
+			 */
+			printk(", UDMA(25)");
+		} else {
+			/*
+			 *  UDMA enabled.
+			 */
+			printk(", UDMA(16)");
+		}
+	} else if (id->field_valid & 4) {
+		/*
+		 *  Can be enabled.
+		 */
+		printk(", (U)DMA capable, but not enabled");
+	} else {
+		/*
+		 *  maybe MDMA?
+		 */
+		printk(", DMA");
+	}
+
+	return 1;
+}
+
+/*****************************************************************************
+ *
+ * ide_build_dmatable() prepares a dma request.
+ * Returns 0 if all went okay, returns 1 otherwise.
+ *
+ ****************************************************************************/
+int ide_build_dmatable(ide_drive_t * drive)
+{
+	unsigned int *table = HWIF(drive)->dmatable_cpu;
+	unsigned int count = 0;
+	int i;
+	struct scatterlist *sg;
+	unsigned int is_trm290_chipset = 0;
+
+	HWIF(drive)->sg_nents = i =
+	    ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+
+	if (!i)
+		return 0;
+
+	sg = HWIF(drive)->sg_table;
+
+	while (i && sg_dma_len(sg)) {
+		u32 cur_addr;
+		u32 cur_len;
+
+		cur_addr = sg_dma_address(sg);
+		cur_len = sg_dma_len(sg);
+
+		/*                                                                                      1
+		 * Fill in the dma table, without crossing any 64kB boundaries.
+		 * Most hardware requires 16-bit alignment of all blocks,
+		 * but the trm290 requires 32-bit alignment.
+		 */
+		while (cur_len) {
+
+			if (count++ >= PRD_ENTRIES) {
+				printk("%s: DMA table too small\n",
+				       drive->name);
+				goto use_pio_instead;
+			} else {
+				u32 xcount, bcount =
+				    0x10000 - (cur_addr & 0xffff);
+
+				if (bcount > cur_len)
+					bcount = cur_len;
+				*table++ = cpu_to_le32(cur_addr);
+				xcount = bcount & 0xffff;
+				if (is_trm290_chipset)
+					xcount = ((xcount >> 2) - 1) << 16;
+				if (xcount == 0x0000) {
+					/*
+					 * Most chipsets correctly interpret a length of 0x0000 as 64KB,
+					 * but at least one (e.g. CS5530) misinterprets it as zero (!).
+					 * So here we break the 64KB entry into two 32KB entries instead.
+					 */
+					if (count++ >= PRD_ENTRIES) {
+						printk
+						    ("%s: DMA table too small\n",
+						     drive->name);
+						goto use_pio_instead;
+					}
+					*table++ = cpu_to_le32(0x8000);
+					*table++ =
+					    cpu_to_le32(cur_addr + 0x8000);
+					xcount = 0x8000;
+				}
+				*table++ = cpu_to_le32(xcount);
+				cur_addr += bcount;
+				cur_len -= bcount;
+			}
+		}
+		sg++;
+		i--;
+	}
+
+	if (count) {
+		if (!is_trm290_chipset)
+			*--table |= cpu_to_le32(0x80000000);
+		return count;
+	}
+	printk("%s: empty DMA table?\n", drive->name);
+
+      use_pio_instead:
+	/*
+	 *  Revert to PIO for this request.
+	 */
+	HWIF(drive)->sg_dma_active = 0;
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ide_destroy_dmatable()
+ *
+ * Teardown mappings after DMA has completed.
+ *
+ ****************************************************************************/
+void ide_destroy_dmatable(ide_drive_t * drive)
+{
+	/*
+	 *  Restore the original dma table base address.
+	 */
+	HWIF(drive)->dmatable_cpu = g_dma_table_base;
+
+	/*
+	 *  Nothing much to do here.
+	 */
+	HWIF(drive)->sg_dma_active = 0;
+}
+
+/*****************************************************************************
+ *
+ * ide_release_dma()
+ *
+ * This function releases the memory allocated for the scatter gather list
+ *  and for the dma table, and frees the dma channel.
+ *
+ ****************************************************************************/
+void ep93xx_ide_release_dma(ide_hwif_t * hwif)
+{
+	/*
+	 *  Check if we have a valid dma handle.
+	 */
+	if (hwif->hw.dma != NULL) {
+		/*
+		 * Pause the DMA channel.
+		 */
+		ep93xx_dma_pause(hwif->hw.dma, 1, 0);
+
+		/*
+		 *  Flush the DMA channel
+		 */
+		ep93xx_dma_flush(hwif->hw.dma);
+	}
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_callback()
+ *
+ * Registered with the ep93xx dma driver and called at the end of the dma
+ * interrupt handler, this function should process the dma buffers.
+ *
+ ****************************************************************************/
+
+static void
+ep93xx_ide_callback(ep93xx_dma_int_t dma_int, ep93xx_dma_dev_t device,
+		    unsigned int user_data)
+{
+	ide_drive_t *drive = (ide_drive_t *) user_data;
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned int temp;
+
+	/*
+	 *  Retrieve from the dma interface as many used buffers as are
+	 *  available.
+	 */
+	while (ep93xx_dma_remove_buffer(hwif->hw.dma, &temp) == 0) {
+		g_prd_returned++;
+
+	}
+
+	/*
+	 *  Add new buffers if we have any available.
+	 */
+	while (g_prd_count) {
+		/*
+		 *  Check if this is a read or write operation.
+		 */
+		if (hwif->sg_dma_direction == 2) {
+			/*
+			 *  Set up buffers for a read op.
+			 */
+			temp =
+			    ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base,
+						  *hwif->dmatable_cpu++,
+						  *hwif->dmatable_cpu++, 0,
+						  g_prd_count);
+		} else {
+			/*
+			 *  Set up buffers for a write op.
+			 */
+			temp =
+			    ep93xx_dma_add_buffer(hwif->hw.dma,
+						  *hwif->dmatable_cpu++,
+						  hwif->dma_base,
+						  *hwif->dmatable_cpu++, 0,
+						  g_prd_count);
+		}
+
+		/*
+		 *  Add a buffer to the dma interface.
+		 */
+		if (temp != 0) {
+			/*
+			 *  This buffer didn't make it into the dma
+			 *  interface, so move the dma table pointer
+			 *  to the start of the current entry.
+			 */
+			hwif->dmatable_cpu -= 4;
+			break;
+		}
+
+		/*
+		 *  Decrement the count of dmatable entries
+		 */
+		g_prd_count--;
+	}
+
+	/*
+	 *  Check if the transfer is complete.
+	 */
+	if (dma_int == DONE) {
+		g_done = 1;
+	}
+
+	if (g_prd_returned == g_prd_total) {
+		g_done = 1;
+	}
+}
+
+/*****************************************************************************
+ *
+ *  ep93xx_dma_timer_expiry()
+ *
+ *
+ *	dma_timer_expiry	-	handle a DMA timeout
+ *	@drive: Drive that timed out
+ *
+ *	An IDE DMA transfer timed out. In the event of an error we ask
+ *	the driver to resolve the problem, if a DMA transfer is still
+ *	in progress we continue to wait (arguably we need to add a
+ *	secondary 'I dont care what the drive thinks' timeout here)
+ *	Finally if we have an interrupt we let it complete the I/O.
+ *	But only one time - we clear expiry and if it's still not
+ *	completed after WAIT_CMD, we error and retry in PIO.
+ *	This can occur if an interrupt is lost or due to hang or bugs.
+ *
+ *
+ ****************************************************************************/
+static int ep93xx_idedma_timer_expiry(ide_drive_t * drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	u8 dev_stat = hwif->INB(IDE_ALTSTATUS_REG);
+	u8 irq_stat = ep93xx_ide_regs->IDECR.Value & IDECtrl_INTRQ;
+
+	printk(KERN_WARNING
+	       "%s: dma_timer_expiry: dev status == 0x%02x, done= %d, irq= %d\n",
+	       drive->name, dev_stat, g_done, irq_stat);
+
+	/*
+	 *  Check if the device is busy, or the dma engine is still working.
+	 */
+	if ((dev_stat & 0x80) || !g_done)	/* BUSY Stupid Early Timer !! */
+		return (2 * WAIT_CMD);
+
+	/*
+	 * Clear the expiry handler in case we decide to wait more,
+	 * next time timer expires it is an error
+	 */
+	HWGROUP(drive)->expiry = NULL;
+
+	/*
+	 *  the device is not busy, so check if there's an error, or if the
+	 *  interrupt is asserted.
+	 */
+	if (dev_stat & 0x01)	/* ERROR */
+		return -1;
+
+	if (irq_stat || g_done)	/* Got an Interrupt or the dma is done */
+		return WAIT_CMD;
+
+	return 0;		/* Unknown status -- reset the bus */
+}
+
+/*****************************************************************************
+ *
+ *	ep93xx_config_ide_dma()
+ *
+ *  This function allocates dma-able memory and configures the ep93xx dma
+ *  interface for use with the ide interface.  This only need be done
+ *  once for the interface.  So, if this is the second drive, we don't have
+ *  much to do here.
+ *
+ ****************************************************************************/
+static int ep93xx_config_ide_dma(ide_drive_t * drive)
+{
+	DPRINTK("ep93xx_config_ide_dma\n");
+
+	/*
+	 *  Success.
+	 */
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_config_ide_device()
+ *
+ * This function sets up the ep93xx ide device for a dma transfer by first
+ * probing to find the best dma mode supported by the device.
+ *
+ * Returns a 0 for success, and a 1 otherwise.
+ *
+ ****************************************************************************/
+static unsigned int ep93xx_config_ide_device(ide_drive_t * drive)
+{
+	struct hd_driveid *id = drive->id;
+	byte transfer = 0;
+
+	DPRINTK("%s: ep93xx_config_ide_device - dma on\n", HWIF(drive)->name);
+
+	/*
+	 * check if the device supports a udma mode.
+	 */
+	if (transfer = (id->dma_ultra & 0x001F)) {
+		DPRINTK("IDE: udma xfer support, transfer = %d \n", transfer);
+
+		/*
+		 *  UDMA mode 4 support.
+		 */
+		if (transfer & 0x10) {
+			transfer = XFER_UDMA_4;
+		}
+		/*
+		 *  UDMA mode 3 support.
+		 */
+		else if (transfer & 0x08) {
+			transfer = XFER_UDMA_3;
+		}
+		/*
+		 *  UDMA mode 2.
+		 */
+		else if (transfer & 0x04) {
+			transfer = XFER_UDMA_2;
+		}
+		/*
+		 *  UDMA mode 1.
+		 */
+		else if (transfer & 0x02) {
+			transfer = XFER_UDMA_1;
+		}
+		/*
+		 *  UDMA mode 0.
+		 */
+		else if (transfer & 0x01) {
+			transfer = XFER_UDMA_0;
+		}
+	}
+	/*
+	 *  The device doesn't support a udma mode, so check if it
+	 *  supports an mdma mode.
+	 */
+	else if (transfer = (drive->id->dma_mword & 0x0007)) {
+		DPRINTK("IDE: mdma support, transfer = %d \n", transfer);
+
+		/*
+		 *  MDMA mode 2.
+		 */
+		if (transfer & 0x04) {
+			transfer = XFER_MW_DMA_2;
+		}
+		/*
+		 *  MDMA mode 1.
+		 */
+		else if (transfer & 0x02) {
+			transfer = XFER_MW_DMA_1;
+		}
+		/*
+		 *  MDMA mode 0.
+		 */
+		else if (transfer & 0x01) {
+			transfer = XFER_MW_DMA_0;
+		}
+	}
+
+	if (transfer == 0) {
+		DPRINTK("IDE: config device failed \n");
+
+		/*
+		 *  Fail.
+		 */
+		return 1;
+	}
+
+	if (ide_config_drive_speed(drive, transfer) == 0) {
+		printk("%s: %s selected\n", drive->name,
+		       ide_xfer_verbose(transfer));
+
+		/*
+		 *  Hold on to this value for use later.
+		 */
+		drive->current_speed = transfer;
+
+		/*
+		 *  Success, so turn on DMA.
+		 */
+		return ep93xx_ide_dma_on(drive);
+	} else {
+		return ep93xx_ide_dma_off(drive);
+	}
+}
+
+/*****************************************************************************
+ *
+ *  ep93xx_set_pio()
+ *
+ *  Configures the ep93xx controller for a PIO mode transfer.
+ *
+ ****************************************************************************/
+static void ep93xx_set_pio(void)
+{
+	/*
+	 *  Disable the interface.
+	 */
+	ep93xx_ide_regs->IDECFG.Field.IDEEN = 0;
+
+	/*
+	 *  Enable PIO mode of operation.
+	 */
+	ep93xx_ide_regs->IDECFG.Field.PIO = 1;
+	ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
+	ep93xx_ide_regs->IDECFG.Field.MDMA = 0;
+
+	/*
+	 *  Enable the IDE interface.
+	 */
+	ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
+}
+
+/*****************************************************************************
+ *
+ *  ep93xx_rwproc()
+ *
+ *  Initializes the ep93xx IDE controller interface with the transfer type,
+ *  transfer mode, and transfer direction.
+ *
+ ****************************************************************************/
+static void ep93xx_rwproc(ide_drive_t * drive, int action)
+{
+	unsigned int temp;
+
+	DPRINTK("\nep93xx_rwproc \n");
+	/*
+	 *  Configure the IDE controller for the specified transfer mode.
+	 */
+	switch (drive->current_speed) {
+		/*
+		 *  Configure for an MDMA operation.
+		 */
+	case XFER_MW_DMA_0:
+	case XFER_MW_DMA_1:
+	case XFER_MW_DMA_2:
+		{
+			DPRINTK("\n ep93xx set up for MDMA \n");
+			ep93xx_ide_regs->IDECFG.Field.PIO = 0;
+			ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
+			ep93xx_ide_regs->IDECFG.Field.MDMA = 1;
+			ep93xx_ide_regs->IDECFG.Field.MODE =
+			    (0x3 & drive->current_speed);
+			ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
+			ep93xx_ide_regs->IDEMDMAOP.Field.RWOP = action;
+			ep93xx_ide_regs->IDEMDMAOP.Field.MEN = 1;
+			break;
+		}
+
+		/*
+		 *  Configure for a UDMA operation.
+		 */
+	case XFER_UDMA_0:
+	case XFER_UDMA_1:
+	case XFER_UDMA_2:
+	case XFER_UDMA_3:
+	case XFER_UDMA_4:
+		{
+			DPRINTK("\n ep93xx set up for UDMA \n");
+			ep93xx_ide_regs->IDECFG.Field.IDEEN = 0;
+			ep93xx_ide_regs->IDEUDMAOP.Field.UEN = 0;
+			ep93xx_ide_regs->IDECFG.Field.PIO = 0;
+			ep93xx_ide_regs->IDECFG.Field.MDMA = 0;
+			ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
+			ep93xx_ide_regs->IDECFG.Field.WST = 0;
+			ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
+
+			ep93xx_ide_regs->IDECFG.Field.MODE =
+			    (0x7 & drive->current_speed);
+			ep93xx_ide_regs->IDECFG.Field.UDMA = 1;
+			ep93xx_ide_regs->IDEUDMAOP.Field.RWOP = action;
+			temp = ep93xx_ide_regs->IDEUDMAOP.Value;
+			ep93xx_ide_regs->IDEUDMAOP.Field.UEN = 1;
+			temp = ep93xx_ide_regs->IDEUDMAOP.Value;
+
+			DPRINTK("\nIDE Regs: config - 0x%x, udmaop - 0x%x \n",
+				ep93xx_ide_regs->IDECFG.Value,
+				ep93xx_ide_regs->IDEUDMAOP.Value);
+
+			break;;
+		}
+
+	default:
+		{
+			break;
+		}
+	}
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_check()
+ *
+ * This function determines if the device supports dma transfers, and if it
+ * does, then enables dma.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_check(ide_drive_t * drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct hd_driveid *id = drive->id;
+
+	DPRINTK("%s: ep93xx_ide_dma_check \n", drive->name);
+
+	if (!id || !(id->capability & 1) || !hwif->autodma) {
+		/*
+		 *  Disable dma for this drive.
+		 */
+		ep93xx_ide_dma_off(drive);
+	}
+
+	/*
+	 * Consult the list of known "bad" drives
+	 */
+	if (in_drive_list(id, drive_blacklist)) {
+		printk("%s: Disabling DMA for %s (blacklisted)\n",
+		       drive->name, id->model);
+
+		/*
+		 *  Disable dma for this drive.
+		 */
+		ep93xx_ide_dma_off(drive);
+	}
+
+	/*
+	 *  Check if the drive supports multiword dma or udma modes.
+	 *  If it does, then set the device up for that
+	 *  type of dma transfer, and call ep93xx_ide_dma_on.
+	 */
+	return ep93xx_config_ide_device(drive);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_host_off()
+ *
+ * This function disables dma for the host.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_host_off(ide_drive_t * drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+
+	/*
+	 *  TODO: what's to be done here?
+	 */
+	DPRINTK("%s: ep93xx_ide_dma_host_off() \n", drive->name);
+
+	/*
+	 *  Release the dma channel and all memory allocated for dma
+	 *  purposes.
+	 */
+	ep93xx_ide_release_dma(hwif);
+
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_off_quietly()
+ *
+ * This function, without announcing it,  disables dma for the device.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_off_quietly(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_off_quietly: \n", drive->name);
+
+	/*
+	 *  Clear the using_dma field to indicate that dma is disabled
+	 *  for this drive.
+	 */
+	drive->using_dma = 0;
+
+	/*
+	 *  Disable dma on the host side.
+	 */
+	ep93xx_ide_dma_host_off(drive);
+
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_off()
+ *
+ * This function disables dma for the device.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_off(ide_drive_t * drive)
+{
+	printk("%s: DMA disabled\n", drive->name);
+
+	return ep93xx_ide_dma_off_quietly(drive);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_on()
+ *
+ * This function enables dma for the device.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_on(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_on: \n", drive->name);
+
+	if (drive->using_dma) {
+		DPRINTK("%s: ep93xx_ide_dma_on, already on! \n", drive->name);
+		return 0;
+	}
+
+	/*
+	 *  Set the using_dma field to indicate that dma is enabled.
+	 */
+	drive->using_dma = 1;
+
+	/*
+	 *  Enable DMA on the host side.
+	 */
+	return ep93xx_ide_dma_host_on(drive);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_host_on()
+ *
+ * This function enables dma for the device.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_host_on(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_host_on: \n", drive->name);
+
+	/*
+	 *  Enable the ep93xx dma interface for use with IDE.
+	 */
+	return ep93xx_config_ide_dma(drive);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_read()
+ *
+ * This function sets up a dma read operation.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_read(ide_drive_t * drive)
+{
+	unsigned int flags, result;
+	ide_hwif_t *hwif = HWIF(drive);
+
+	DPRINTK("%s: ep93xx_ide_dma_read: \n", drive->name);
+
+	/*
+	 *  Check if we are already transferring on this dma channel.
+	 */
+	BUG_ON(hwif->sg_dma_active);
+
+	/*
+	 *  Configure DMA M2M channel flags for a source address hold, h/w
+	 *  initiated P2M transfer.
+	 */
+	flags = (SOURCE_HOLD | TRANSFER_MODE_HW_P2M);
+
+	if (drive->current_speed & 0x20) {
+		flags |= (WS_IDE_MDMA_READ_WRITE << WAIT_STATES_SHIFT);
+
+		/*
+		 *  MDMA data register address.
+		 */
+		hwif->dma_base = 0x800A001C;
+	} else {
+		flags |= (WS_IDE_UDMA_READ << WAIT_STATES_SHIFT);
+
+		/*
+		 *  UDMA data register address.
+		 */
+		hwif->dma_base = 0x800a0024;
+	}
+
+	/*
+	 *  Configure the dma interface for this IDE operation.
+	 */
+	if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback,
+			      (unsigned int)drive) != 0) {
+		DPRINTK("%s: ep93xx_ide_dma_read: ERROR- dma config failed",
+			drive->name);
+
+		/*
+		 *  Fail.
+		 */
+		return 1;
+	}
+
+	/*
+	 *  Build the table of dma-able buffers.
+	 */
+	if (!(g_prd_count = ide_build_dmatable(drive))) {
+		DPRINTK
+		    ("%s: ep93xx_ide_dma_read: ERROR- failed to build dma table",
+		     drive->name);
+
+		/*
+		 *  Fail, try PIO instead of DMA
+		 */
+		return 1;
+	}
+
+	/*
+	 *  Indicate that we're waiting for dma.
+	 */
+	drive->waiting_for_dma = 1;
+
+	hwif->sg_dma_active = 1;
+
+	/*
+	 * test stuff
+	 */
+	g_prd_total = g_prd_count;
+	g_prd_returned = 0;
+	g_dma_table_base = hwif->dmatable_cpu;
+
+	/*
+	 *  Prepare the dma interface with some buffers from the
+	 *  dma_table.
+	 */
+	do {
+		/*
+		 *  Add a buffer to the dma interface.
+		 */
+		result = ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base,
+					       *hwif->dmatable_cpu++,
+					       *hwif->dmatable_cpu++, 0,
+					       g_prd_count);
+
+		if (result != 0) {
+			/*
+			 *  This buffer didn't make it into the dma
+			 *  interface, so move the dma table pointer
+			 *  to the start of the current entry.
+			 */
+			hwif->dmatable_cpu -= 4;
+			break;
+		}
+
+		/*
+		 *  Decrement the count of dmatable entries
+		 */
+		g_prd_count--;
+
+	} while (g_prd_count);
+
+	/*
+	 *  Check if this is a disk or cd drive.
+	 */
+	if (drive->media == ide_disk) {
+		/*
+		 *  Send the read command to the device.
+		 */
+		ide_execute_command(drive, WIN_READDMA, &ep93xx_ide_dma_intr,
+				    4 * WAIT_CMD, &ep93xx_idedma_timer_expiry);
+
+	}
+
+	/*
+	 *  Configure the ep93xx ide controller for a dma read operation.
+	 */
+	ep93xx_rwproc(drive, 0);
+
+	/*
+	 *  initiate the dma transfer.
+	 */
+	return ep93xx_ide_dma_begin(drive);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_write()
+ *
+ * This function sets up a dma write operation.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_write(ide_drive_t * drive)
+{
+	unsigned int flags, result;
+	ide_hwif_t *hwif = HWIF(drive);
+
+	DPRINTK("%s: ep93xx_ide_dma_write: \n", drive->name);
+
+	/*
+	 *  Check if we are already transferring on this dma channel.
+	 */
+	BUG_ON(hwif->sg_dma_active);
+
+	/*
+	 *  Configure DMA M2M channel flags for a destination address
+	 *  hold, h/w initiated M2P transfer.
+	 */
+	flags = (DESTINATION_HOLD | TRANSFER_MODE_HW_M2P);
+
+	/*
+	 *  Determine if we need the MDMA or UDMA data register.
+	 */
+	if (drive->current_speed & 0x20) {
+		flags |= (WS_IDE_MDMA_READ_WRITE << WAIT_STATES_SHIFT);
+
+		/*
+		 *  MDMA data register address.
+		 */
+		hwif->dma_base = 0x800A0018;
+	} else {
+		flags |= (WS_IDE_UDMA_WRITE << WAIT_STATES_SHIFT);
+
+		/*
+		 *  UDMA data register address.
+		 */
+		hwif->dma_base = 0x800a0020;
+	}
+
+	/*
+	 *  Configure the dma interface for this IDE operation.
+	 */
+	if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback,
+			      (unsigned int)drive) != 0) {
+		return 1;
+	}
+
+	/*
+	 *  Build the table of dma-able buffers.
+	 */
+	if (!(g_prd_count = ide_build_dmatable(drive))) {
+		/*
+		 *  Fail, try PIO instead of DMA
+		 */
+		return 1;
+	}
+
+	/*
+	 *  Indicate that we're waiting for dma.
+	 */
+	drive->waiting_for_dma = 1;
+
+	hwif->sg_dma_active = 1;
+
+	/*
+	 * test stuff
+	 */
+	g_prd_total = g_prd_count;
+	g_prd_returned = 0;
+	g_dma_table_base = hwif->dmatable_cpu;
+
+	/*
+	 *  Prepare the dma interface with some buffers from the
+	 *  dma_table.
+	 */
+	do {
+		/*
+		 *  Add a buffer to the dma interface.
+		 */
+		result =
+		    ep93xx_dma_add_buffer(hwif->hw.dma, *hwif->dmatable_cpu++,
+					  hwif->dma_base, *hwif->dmatable_cpu++,
+					  0, g_prd_count);
+
+		if (result != 0) {
+			/*
+			 *  This buffer didn't make it into the dma
+			 *  interface, so move the dma table pointer
+			 *  to the start of the current entry.
+			 */
+			hwif->dmatable_cpu -= 4;
+			break;
+		}
+
+		/*
+		 *  Decrement the count of dmatable entries
+		 */
+		g_prd_count--;
+
+	} while (g_prd_count);
+
+	/*
+	 * Check if this is a disk or cd drive.
+	 */
+	if (drive->media == ide_disk) {
+		/*
+		 *  Send the write dma command to the device.
+		 */
+		ide_execute_command(drive, WIN_WRITEDMA, &ep93xx_ide_dma_intr,
+				    4 * WAIT_CMD, &ep93xx_idedma_timer_expiry);
+	}
+
+	/*
+	 *  Configure the ep93xx ide controller for a dma read operation.
+	 */
+	ep93xx_rwproc(drive, 1);
+
+	/*
+	 *  initiate the dma transfer.
+	 */
+	return ep93xx_ide_dma_begin(drive);
+
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_begin()
+ *
+ * This function initiates a dma transfer.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_begin(ide_drive_t * drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+
+	DPRINTK("%s: ep93xx_ide_dma_begin: \n", drive->name);
+
+	/* Note that this is done *after* the cmd has
+	 * been issued to the drive, as per the BM-IDE spec.
+	 * The Promise Ultra33 doesn't work correctly when
+	 * we do this part before issuing the drive cmd.
+	 */
+	g_done = 0;
+
+	/*
+	 *  Start the dma transfer.
+	 */
+	ep93xx_dma_start(hwif->hw.dma, 1, NULL);
+
+	/*
+	 * TODO: not sure if we need to keep track of the end
+	 * of the transfer from the dma perspective, but
+	 * for now, let's do it.
+	 */
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_end()
+ *
+ * This function performs any tasks needed to cleanup after a dma transfer.
+ * Returns 1 if an error occured, and 0 otherwise.
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_end(ide_drive_t * drive)
+{
+	unsigned char dev_stat;
+	ide_hwif_t *hwif = HWIF(drive);
+
+	DPRINTK("%s: ep93xx_ide_dma_end: \n", drive->name);
+
+	/*
+	 *  Indicate there's no dma transfer currently in progress.
+	 */
+	drive->waiting_for_dma = 0;
+
+	/*
+	 *  Put the dma interface into pause mode.
+	 */
+	ep93xx_dma_pause(hwif->hw.dma, 1, 0);
+	ep93xx_dma_flush(hwif->hw.dma);
+
+	/*
+	 *  Enable PIO mode on the IDE interface.
+	 */
+	ep93xx_set_pio();
+
+	/*
+	 *  Read the ide device status register.  This clears the interrupt.
+	 *  TODO: should I read the alt status instead to prevent clearing
+	 *  an asserted interrupt??
+	 */
+	dev_stat = hwif->INB(IDE_STATUS_REG);
+
+	/*
+	 *  Purge the contents of the dma table of buffer entries.
+	 */
+	ide_destroy_dmatable(drive);
+
+	hwif->sg_dma_active = 0;
+
+	/*
+	 *  If the error bit is set in the device status register,
+	 *  return a positive value.
+	 */
+	if (dev_stat & ERR_STAT) {
+		printk("ide_dma_end: device error \n");
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_test_irq()
+ *
+ * This function checks if the IDE interrupt is asserted and returns a
+ * 1 if it is, and 0 otherwise..
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_test_irq(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_test_irq: \n", drive->name);
+
+	if (!drive->waiting_for_dma)
+		printk(KERN_WARNING "%s: (%s) called while not waiting\n",
+		       drive->name, __FUNCTION__);
+
+	/*
+	 *  TODO: need to use the io macros to get this value.
+	 *  Return the value of the IDE interrupt bit.
+	 */
+	return (ep93xx_ide_regs->IDECR.Value & IDECtrl_INTRQ);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_bad_drive()
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_bad_drive(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_bad_drive: \n", drive->name);
+
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_good_drive()
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_good_drive(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_good_drive: \n", drive->name);
+
+	/*
+	 *  TODO: need to implement.
+	 */
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_count()
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_count(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_count: \n", drive->name);
+
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_verbose()
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_verbose(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_verbose: \n", drive->name);
+
+	printk(", %s ", ide_xfer_verbose(drive->current_speed));
+
+	return 1;
+
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_bad_timeout()
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_timeout(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_timeout: \n", drive->name);
+
+	printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
+	if (HWIF(drive)->ide_dma_test_irq(drive))
+		return 0;
+	return HWIF(drive)->ide_dma_end(drive);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_retune()
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_retune(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_retune\n", drive->name);
+	return 1;
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_dma_lostirq()
+ *
+ ****************************************************************************/
+int ep93xx_ide_dma_lostirq(ide_drive_t * drive)
+{
+	DPRINTK("%s: ep93xx_ide_dma_lostirq\n", drive->name);
+	printk("%s: DMA interrupt recovery\n", drive->name);
+
+	return 1;
+}
+
+#endif				/* CONFIG_BLK_DEV_IDEDMA_EP93XX */
+
+/*****************************************************************************
+ *
+ *  functions to set up the IDE control register and data register to read
+ *  or write a byte of data to/from the specified IDE device register.
+ *
+ ****************************************************************************/
+static void ep93xx_ide_outb(u8 b, unsigned long addr)
+{
+	unsigned int uiIDECR;
+
+	DPRINTK("ep93xx_ide_outb, addr:%02lx data: %04x\n", addr, b);
+
+	/*
+	 * Write the address out (CS0n, CS1n, DA) fields only.
+	 */
+	uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
+	writel(uiIDECR, IDECtrl);
+
+	writel((unsigned int)b, IDEDataOut);
+
+	/*
+	 * Toggle Write signal.
+	 */
+	uiIDECR &= ~IDECtrl_DIOWn;
+	writel(uiIDECR, IDECtrl);
+	uiIDECR |= IDECtrl_DIOWn;
+	writel(uiIDECR, IDECtrl);
+}
+
+static void ep93xx_ide_outbsync(ide_drive_t * drive, u8 b, unsigned long addr)
+{
+	unsigned int uiIDECR;
+
+	DPRINTK("ep93xx_ide_outbsync, addr:%02lx data: %04x\n", addr, b);
+
+	/*
+	 * Write the address out (CS0n, CS1n, DA) fields only.
+	 */
+	uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
+	writel(uiIDECR, IDECtrl);
+
+	writel((unsigned int)b, IDEDataOut);
+
+	/*
+	 * Toggle Write signal.
+	 */
+	uiIDECR &= ~IDECtrl_DIOWn;
+	writel(uiIDECR, IDECtrl);
+	uiIDECR |= IDECtrl_DIOWn;
+	writel(uiIDECR, IDECtrl);
+}
+
+static unsigned char ep93xx_ide_inb(unsigned long addr)
+{
+	unsigned int uiIDECR;
+
+	DPRINTK("ep93xx_ide_inb addr: %04lx ", addr);
+
+	/*
+	 * Write the address out (CS0n, CS1n, DA) fields only.
+	 */
+	uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
+	writel(uiIDECR, IDECtrl);
+
+	/*
+	 * Toggle Read signal.
+	 */
+	uiIDECR &= ~IDECtrl_DIORn;
+	writel(uiIDECR, IDECtrl);
+	uiIDECR |= IDECtrl_DIORn;
+	writel(uiIDECR, IDECtrl);
+
+	DPRINTK("data: %02x\n", readl(IDEDataIn));
+	return (unsigned char)readl(IDEDataIn);
+}
+
+/*****************************************************************************
+ *
+ *  functions to set up the IDE control register and data restister to read
+ *  or write 16 bits of data to/from the specified IDE device register.
+ *  These functions should only be used when reading/writing data to/from
+ *  the data register.
+ *
+ ****************************************************************************/
+static void ep93xx_ide_outw(u16 w, unsigned long addr)
+{
+	unsigned int uiIDECR;
+
+	DPRINTK("ep93xx_ide_outw addr: %04lx data: %04x\n", addr, w);
+
+	/*
+	 * Write the address out (CS0n, CS1n, DA) fields only.
+	 */
+	uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
+	writel(uiIDECR, IDECtrl);
+
+	writel((unsigned int)w, IDEDataOut);
+
+	/*
+	 * Toggle Write signal.
+	 */
+	uiIDECR &= ~IDECtrl_DIOWn;
+	writel(uiIDECR, IDECtrl);
+	uiIDECR |= IDECtrl_DIOWn;
+	writel(uiIDECR, IDECtrl);
+}
+
+static u16 ep93xx_ide_inw(unsigned long addr)
+{
+	unsigned int uiIDECR;
+
+	DPRINTK("ep93xx_ide_inw addr: %04lx ", addr);
+
+	/*
+	 * Write the address out (CS0n, CS1n, DA) fields only.
+	 */
+	uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
+	writel(uiIDECR, IDECtrl);
+
+	/*
+	 * Toggle Read signal.
+	 */
+	uiIDECR &= ~IDECtrl_DIORn;
+	writel(uiIDECR, IDECtrl);
+	uiIDECR |= IDECtrl_DIORn;
+	writel(uiIDECR, IDECtrl);
+
+	DPRINTK("data: %04x\n", readl(IDEDataIn));
+	return (unsigned short)readl(IDEDataIn);
+}
+
+/*****************************************************************************
+ *
+ *  functions to read/write a block of data to/from the ide device using
+ *  PIO mode.
+ *
+ ****************************************************************************/
+static void ep93xx_ide_insw(unsigned long addr, void *buf, u32 count)
+{
+	unsigned short *data = (unsigned short *)buf;
+	unsigned char status;
+	DPRINTK("ep93xx_ide_insw\n");
+
+	/*
+	 *  Read in data from the data register 16 bits at a time.
+	 */
+	while (count) {
+		/*
+		 *  Read the status register.
+		 */
+		status = ep93xx_ide_inb((STATUSREGISTER << 2) + 2);
+
+		/*
+		 *  Check for the BSY to be clear and DRQ to be set.
+		 */
+		if ((status & ATADRQ) && !(status & ATABSY)) {
+			*data = ep93xx_ide_inw(addr);
+			data++;
+			count--;
+		}
+	}
+}
+
+static void ep93xx_ide_outsw(unsigned long addr, void *buf, u32 count)
+{
+	unsigned short *data = (unsigned short *)buf;
+	unsigned char status;
+
+	DPRINTK("ep93xx_ide_outsw\n");
+
+	/*
+	 *  Write out data to the data register 16 bits at a time.
+	 */
+	while (count) {
+		/*
+		 *  Read the status register.
+		 */
+		status = ep93xx_ide_inb((STATUSREGISTER << 2) + 2);
+
+		/*
+		 *  Check for the BSY to be clear and DRQ to be set.
+		 */
+		if ((status & ATADRQ) && !(status & ATABSY)) {
+			ep93xx_ide_outw(*data, addr);
+			data++;
+			count--;
+		}
+	}
+}
+
+static void ep93xx_ide_outl(u32 l, unsigned long addr)
+{
+	printk("ep93xx_ide_outl\n");
+}
+
+static u32 ep93xx_ide_inl(unsigned long addr)
+{
+	printk("ep93xx_ide_inl\n");
+	return 0;
+}
+
+static void ep93xx_ide_outsl(unsigned long addr, void *buf, u32 count)
+{
+	printk("ep93xx_ide_inl\n");
+}
+
+static void ep93xx_ide_insl(unsigned long addr, void *buf, u32 count)
+{
+	printk("ep93xx_ide_inl\n");
+}
+
+/*****************************************************************************
+ *
+ *  Functions to read/write a block of data to/from the ide device using
+ *  PIO mode, using an ATAPI interface.
+ *
+ ****************************************************************************/
+static void ep93xx_ide_insw_atapi(unsigned int addr, void *buf, int count)
+{
+	DPRINTK("ep93xx_ide_insw_atapi \n");
+
+	/*
+	 * Convert count from bytes to half words.
+	 */
+	if (count % 2) {
+		count = count / 2;
+		count++;
+	} else {
+		count = count / 2;
+	}
+
+	/*
+	 * Call the function which will read in the data.
+	 */
+	ep93xx_ide_insw(addr, buf, count);
+}
+
+static void ep93xx_ide_outsw_atapi(unsigned int addr, void *buf, int count)
+{
+	DPRINTK("ep93xx_ide_outsw_atapi \n");
+
+	/*
+	 * Convert count from bytes to half words.
+	 */
+	if (count % 2) {
+		count = count / 2;
+		count++;
+	} else {
+		count = count / 2;
+	}
+
+	/*
+	 * Call the function which will write out the data.
+	 */
+	ep93xx_ide_outsw(addr, buf, count);
+}
+
+void ep93xx_ata_input_data(ide_drive_t * drive, void *buffer, u32 count)
+{
+	DPRINTK("ep93xx_ata_input_data \n");
+
+	/*
+	 *  Read in the specified number of half words from the ide interface.
+	 */
+	ep93xx_ide_insw(IDE_DATA_REG, buffer, count << 1);
+}
+
+void ep93xx_ata_output_data(ide_drive_t * drive, void *buffer, u32 count)
+{
+	DPRINTK("ep93xx_ata_output_data \n");
+
+	/*
+	 *  write the specified number of half words from the ide interface
+	 *  to the ide device.
+	 */
+	ep93xx_ide_outsw(IDE_DATA_REG, buffer, count << 1);
+}
+
+void ep93xx_atapi_input_bytes(ide_drive_t * drive, void *buffer, u32 count)
+{
+	DPRINTK("ep93xx_atapi_input_bytes \n");
+
+	/*
+	 *  read in the specified number of bytes from the ide interface.
+	 */
+	ep93xx_ide_insw_atapi(IDE_DATA_REG, buffer, count);
+}
+
+void ep93xx_atapi_output_bytes(ide_drive_t * drive, void *buffer, u32 count)
+{
+	DPRINTK("ep93xx_atapi_output_bytes \n");
+
+	/*
+	 *  Write the specified number of bytes from the ide interface
+	 *  to the ide device.
+	 */
+	ep93xx_ide_outsw_atapi(IDE_DATA_REG, buffer, count);
+}
+
+/*****************************************************************************
+ *
+ * ep93xx_ide_init()
+ *
+ * This function sets up a pointer to the ep93xx specific ideproc funciton.
+ *
+ ****************************************************************************/
+void ep93xx_ide_init(struct hwif_s *hwif)
+{
+
+	DPRINTK("ep93xx_ide_init \n");
+
+	/*
+	 *  Set up the HW interface function pointers with the ep93xx specific
+	 *  function.
+	 */
+	hwif->ata_input_data = ep93xx_ata_input_data;
+	hwif->ata_output_data = ep93xx_ata_output_data;
+	hwif->atapi_input_bytes = ep93xx_atapi_input_bytes;
+	hwif->atapi_output_bytes = ep93xx_atapi_output_bytes;
+
+	hwif->OUTB = ep93xx_ide_outb;
+	hwif->OUTBSYNC = ep93xx_ide_outbsync;
+	hwif->OUTW = ep93xx_ide_outw;
+	hwif->OUTL = ep93xx_ide_outl;
+	hwif->OUTSW = ep93xx_ide_outsw;
+	hwif->OUTSL = ep93xx_ide_outsl;
+
+	hwif->INB = ep93xx_ide_inb;
+	hwif->INW = ep93xx_ide_inw;
+	hwif->INL = ep93xx_ide_inl;
+	hwif->INSW = ep93xx_ide_insw;
+	hwif->INSL = ep93xx_ide_insl;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
+
+	DPRINTK("ep93xx_ide_init- dma enabled \n");
+
+	printk("    %s: SG-DMA", hwif->name);
+
+	/*
+	 *  Allocate dma-able memory space, in one consistent chunk.  The call
+	 *  to alloc_consistent will return a virtual address and fill in a dma
+	 *  physical address.  (arch/arm/mm/consistent.c)
+	 *
+	 */
+	hwif->dmatable_cpu = consistent_alloc(GFP_KERNEL | GFP_DMA,
+					      PRD_ENTRIES * PRD_BYTES,
+					      &hwif->dmatable_dma);
+
+	/*
+	 *  Check if we allocated memory for dma
+	 */
+	if (hwif->dmatable_cpu == NULL) {
+		printk(" -- disabled, UNABLE TO ALLOCATE DMA TABLES\n");
+		return;
+	}
+
+	DPRINTK("    %s: EP93XX-DMA at 0x%x - 0x%x \n", hwif->name,
+		hwif->dmatable_dma,
+		(unsigned int)(hwif->dmatable_dma + (PRD_ENTRIES * PRD_BYTES)));
+
+	/*
+	 *  Allocate memory for the scatterlist structures.
+	 */
+	hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
+				 GFP_KERNEL);
+
+	/*
+	 *  Check if we allocated the memory we expected to.
+	 */
+	if (hwif->sg_table == NULL) {
+		/*
+		 *  Fail, so clean up.
+		 */
+		consistent_free(hwif->dmatable_cpu, PRD_ENTRIES * PRD_BYTES,
+				hwif->dmatable_dma);
+		printk(" -- disabled, UNABLE TO ALLOCATE DMA TABLES\n");
+		return;
+	}
+
+	/*
+	 *  Init the dma handle to 0.  This field is used to hold a handle to the
+	 *  dma instance.
+	 */
+	hwif->hw.dma = NULL;
+
+	/*
+	 *  Open an instance of the ep93xx dma interface.
+	 */
+	if (ep93xx_dma_request(&hwif->hw.dma, hwif->name, DMA_IDE) != 0) {
+		/*
+		 *  Fail, so clean up.
+		 */
+		consistent_free(hwif->dmatable_cpu, PRD_ENTRIES * PRD_BYTES,
+				hwif->dmatable_dma);
+		kfree(hwif->sg_table);
+		printk(" -- disabled, unable to allocate DMA channel.\n");
+	}
+
+	/*
+	 *  Now that we've got a dma channel allocated, set up the rest of the
+	 *  dma specific stuff.
+	 */
+	else {
+		DPRINTK("\n ide init- dma channel allocated: %d \n",
+			hwif->hw.dma);
+
+		/*
+		 *  Enable dma support for atapi devices.
+		 */
+		hwif->atapi_dma = 1;
+
+		/*
+		 *  TODO: how are these used?
+		 */
+		hwif->mwdma_mask = 7;	/* MW0..2 */
+		hwif->ultra_mask = 7;	/* SW0..2 */
+
+		hwif->speedproc = NULL;
+		hwif->autodma = 1;
+
+		hwif->ide_dma_check = ep93xx_ide_dma_check;
+		hwif->ide_dma_host_off = ep93xx_ide_dma_host_off;
+		hwif->ide_dma_off_quietly = ep93xx_ide_dma_off_quietly;
+		hwif->ide_dma_off = ep93xx_ide_dma_off;
+		hwif->ide_dma_host_on = ep93xx_ide_dma_host_on;
+		hwif->ide_dma_on = ep93xx_ide_dma_on;
+		hwif->ide_dma_read = ep93xx_ide_dma_read;
+		hwif->ide_dma_write = ep93xx_ide_dma_write;
+		hwif->ide_dma_count = ep93xx_ide_dma_count;
+		hwif->ide_dma_begin = ep93xx_ide_dma_begin;
+		hwif->ide_dma_end = ep93xx_ide_dma_end;
+		hwif->ide_dma_test_irq = ep93xx_ide_dma_test_irq;
+		hwif->ide_dma_verbose = ep93xx_ide_dma_verbose;
+		hwif->ide_dma_timeout = ep93xx_ide_dma_timeout;
+		hwif->ide_dma_lostirq = ep93xx_ide_dma_lostirq;
+
+		printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
+	}
+
+#endif
+}
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
index 23488c4..cc411c2 100644
--- a/drivers/ide/arm/ide_arm.c
+++ b/drivers/ide/arm/ide_arm.c
@@ -20,6 +20,15 @@
 # define IDE_ARM_HOST	(1)
 #endif
 
+/* FIXME: Part 1 of dirty hack to get IDE working for EP93XX Processor */
+#ifdef CONFIG_BLK_DEV_EP93XX
+#include <asm/arch/ide.h>
+#ifndef IRQ_HARDDISK
+# define IRQ_HARDDISK  -1
+#endif
+#endif
+/* END OF HACK */
+
 #ifdef CONFIG_ARCH_CLPS7500
 # include <asm/arch/hardware.h>
 #
@@ -36,8 +45,15 @@ void __init ide_arm_init(void)
 		hw_regs_t hw;
 
 		memset(&hw, 0, sizeof(hw));
+
+/* FIXME: Part 2 of dirty hack to get IDE working for EP93XX Processor */
+#ifdef CONFIG_BLK_DEV_EP93XX
+		old_ide_init_default_hwifs();
+#else
 		ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
 		hw.irq = IDE_ARM_IRQ;
 		ide_register_hw(&hw, NULL);
+#endif
 	}
+
 }
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4a91774..68c06fa 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -193,4 +193,38 @@ config KEYBOARD_HIL
 	  This driver implements support for HIL-keyboards attached
 	  to your machine, so normally you should say Y here.
 
+config KEYBOARD_EP93XX
+	tristate "EP93xx Keyboard support"
+	depends on ARCH_EP93XX && INPUT && INPUT_KEYBOARD
+	default y
+	help
+	  This is support for the Cirrus EP93xx Keyboards. Say yes here if you
+	  have such a CPU, and choose some drivers below.
+
+config KEYBOARD_EP93XX_SPI
+	bool "EP93xx PS2 Keyboard support"
+	depends on KEYBOARD_EP93XX
+	help
+	  Say Y here if you want support for a PS2 keyboard connected via SPI.
+
+config KEYBOARD_EP93XX_8X8
+	bool "EP93xx 8x8 keypad matrix support"
+	depends on KEYBOARD_EP93XX
+	help
+	  Say Y here if you have a 8x8 keypad connected to your EP93xx.
+	  You might want to generate a custom keymap for it.
+	  If you do not have such a keypad, say N.
+
+config KEYBOARD_EP93XX_8X8_CYCLING
+	bool "EP93xx 8x8 keypad matrix keycode cycling support"
+	depends on KEYBOARD_EP93XX_8X8
+	help
+	  Key cycling feature - assign more than one keycode per key.
+	  If you press such a key more than twice per second, alternative
+	  keycodes will be cycled through.
+	  This should result in a behavoir similar to some mobile phones.
+	  You might want to generate a custom keymap for this feature, too.
+	  See the sourcecode for known limitations.
+	  Say N unless you really need it.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 9ce0b87..7ac6fca 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -17,4 +17,6 @@ obj-$(CONFIG_KEYBOARD_CORGI)		+= corgikb
 obj-$(CONFIG_KEYBOARD_SPITZ)		+= spitzkbd.o
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
+obj-$(CONFIG_KEYBOARD_EP93XX_8X8)		+= ep93xx_kbd_8x8.o
+obj-$(CONFIG_KEYBOARD_EP93XX_SPI) 		+= ep93xx_spi_kbd.o
 
diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8.c b/drivers/input/keyboard/ep93xx_kbd_8x8.c
new file mode 100644
index 0000000..d772381
--- /dev/null
+++ b/drivers/input/keyboard/ep93xx_kbd_8x8.c
@@ -0,0 +1,482 @@
+/******************************************************************************
+ *
+ *  File:	linux/drivers/input/keyboard/ep93xx_kbd_8x8.c
+ *
+ *  Purpose:	Support for Cirrus EP93xx architecture core keyboard scanner.
+ *
+ *
+ *  History:	2005-08-10 Michael Burian added "cycling keys" support
+ *  		2004-05-28 Michael Burian ported to 2.6.6
+ *
+ *  		010406	Norman Farquhar at LynuxWorks
+ *
+ *		Initial version
+ *		- Will scan keyboard and feed keyboard.c, which translates
+ *		to input codes and puts them into tty console queue.
+ *		- Raw mode tbd
+ *		- keymaps other than default not supported
+ *		- does not support standby mode yet
+ *
+ *  Limitations:
+ *		1.  The EP93xx is limited to supporting small keyboards
+ *		and cannot handle full PC style keyboards and key usage:
+ *		a)  64 key limit: 8x8 key matrix
+ *		b)  limited to 2 keys down MAXIMUM,
+ *		which makes it impossible to support SHIFT+SHIFT+KEY
+ *		states like shift-control or control-alt keys.
+ *		2.  This means the default keyboard, 83key CherryG84-4001QAU/02,
+ *		will have some dead keys.
+ *
+ *
+ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA.  All rights reserved.
+ *
+ *=============================================================================
+ *	Overview of EP93xx Scan Keyboard driver
+ *=============================================================================
+ *
+ *	The EP93xx scanned keyboard driver is a low-level hardware driver which
+ *	supports the core logic scanned keyboard controller block of the
+ *	EP93xx.  These machines are embedded systems and this keyboard driver
+ *	can support small keyboards.
+ *
+ *	The keyboard driver does not have a normal device driver interface
+ *	and instead interfaces to the keyboard.c driver through function calls.
+ *	Note that not all interface function calls are implemented at this time.
+ *	(see /asm/arch/keyboard.h for function definitions):
+ *
+ *	ep93xxkbd_init
+ *		initializes the scan keyboard hw.
+ *
+ *	handle_scancode
+ *		when scan controller generates interrupt, handler
+ *		used to pass scan codes to queue in keyboard.c with this function call.
+ *
+ *		UPDATE: Now this is inplemented right here and just used as a
+ *		        wrapper for the input layer
+ *
+ *	Note that key scan codes will be delivered by this driver on both
+ *	key down and key up events, using a coding similar to PC XT keyboard.
+ *
+ *	Note however that scan compatibility and key code compatibility
+ *	to PC standard are not required by Linux, and are not guaranteed.
+ *
+ ******************************************************************************/
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/arch/keyboard.h>
+#include <asm/hardware.h>
+
+#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
+#include "ep93xx_kbd_8x8_keymap-cycling.h"
+#else
+#include "ep93xx_kbd_8x8_keymap.h"
+#endif
+
+#define EP93XX_KEYMAP_SIZE (8*8)
+
+/* #define DEBUG */
+
+#define KEYREG_KEY1_MASK                        0x0000003F
+#define KEYREG_KEY1_SHIFT                       0
+#define KEYREG_KEY2_MASK                        0x00000Fc0
+#define KEYREG_KEY2_SHIFT                       6
+
+#define KEYREG_KEY1ROW_MASK                     0x00000007
+#define KEYREG_KEY1ROW_SHIFT                    0
+#define KEYREG_KEY1COL_MASK                     0x00000038
+#define KEYREG_KEY1COL_SHIFT                    3
+
+#define KEYREG_KEY2ROW_MASK                     0x000001c0
+#define KEYREG_KEY2ROW_SHIFT                    6
+#define KEYREG_KEY2COL_MASK                     0x00000E00
+#define KEYREG_KEY2COL_SHIFT                    9
+
+#define KEYREG_1KEY                             0x00001000
+#define KEYREG_2KEYS                            0x00002000
+#define KEYREG_INT                              0x00004000
+#define KEYREG_K                                0x00008000
+
+#define SCANINIT_DIS3KY                         0x00008000
+
+static struct input_dev *dev;
+
+#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
+struct last_key_event {
+	unsigned long jiffies;
+	unsigned char scancode;
+};
+
+static struct last_key_event lke;
+
+/**
+ * handle_scancode - wrapper
+ *
+ * We need to do two things here:
+ * 1. wrap old style (2.4.x) to 2.6.x input subsystem
+ * 2. also implement the key cycling feature here.
+ * CYCLING FEATURE:
+ * If the same key is pressed withing 500ms, we send a delete
+ * character to delete the former key, and use the keycode from the next layer
+ * instead. This should result "mobile phone" like behavior.
+ * KNOWN BUG:
+ * This will mess up anything that depends on single keystrokes
+ * (raw mode, non canonical mode, hotkeys, ...)
+ * TODO 1:
+ * A possible fix would be to delay till we know for sure what key it is
+ * and send just that key, but in that case the user would have to type
+ * blindly. :(
+ * TODO 2:
+ * A possible enhancement to the fix would be to provide some kind of preview
+ * with an additional character device and write some userspace app to display
+ * it in a seperate dialog.
+ *
+ */
+static void handle_scancode(unsigned char scancode, int down)
+{
+	unsigned char row = (scancode & 0xF) - 1;
+	unsigned char col = ((scancode & 0x70) >> 4);
+	unsigned char index = row * 8 + col;
+	static int layer = 0;
+
+	/*
+	 * straight forward processing in case of:
+	 * 	"up" events
+	 * 	repeated keypress events that happen after more than 500ms
+	 * 	after different key has been pressed ( ignore up/down! )
+	 * 	there are no alternative keycodes available
+	 */
+	if (!down || time_before(lke.jiffies + msecs_to_jiffies(500), jiffies)
+			|| (lke.scancode & 0x7f) != (scancode &0x7F) ||
+			(keycode[1][index] == KEY_RESERVED) ) {
+		/* no cycling: process straightforward */
+		input_report_key(dev, keycode[0][index], down);
+		input_sync(dev);
+
+		/* end cycling on all but up events */
+		if(down)
+			layer=0;
+	} else {
+		/*
+		 * cycling mode:
+		 *
+		 * if we have an alternative keycode available:
+		 * 1. pretend the former key was wrong (and delete it)
+		 * 2. replace with the keycode from the next layer
+		 */
+
+		/* suppress real "up" events, as we fake immediate "up" here */
+		if (!down)
+			return;
+
+		/* switch to next layer, with wraparound */
+		if(++layer >= 16)
+			layer = 0;
+
+		/* if alternative keycodes are available */
+		if (keycode[layer][index] != KEY_RESERVED) {
+			/* pretend former key was wrong and delete it */
+			input_report_key(dev, KEY_BACKSPACE, 1);
+			input_report_key(dev, KEY_BACKSPACE, 0);
+		} else {
+			/* no more valid keycodes? => switch to layer 0 */
+			layer=0;
+			return;
+		}
+
+		/* send alternative keycode */
+		input_report_key(dev, keycode[layer][index], 1);
+		input_report_key(dev, keycode[layer][index], 0);
+		input_sync(dev);
+
+
+	}
+	lke.scancode = scancode;
+	lke.jiffies = jiffies;
+}
+#else
+/**
+ * handle_scancode - wrapper
+ *
+ * wrap old style (2.4.x) to 2.6.x input subsystem
+ */
+static void handle_scancode(unsigned char scancode, int down)
+{
+	/* printk("handle_scancode(scancode=%04X, down=%d); %02X ", scancode, down, scancode &0x7f); */
+
+	unsigned char row = (scancode & 0xF) - 1;
+	unsigned char col = ((scancode & 0x70) >> 4);
+	unsigned char index = row * 8 + col;
+
+	input_report_key(dev, keycode[index], down);
+	input_sync(dev);
+
+	/* printk("index=%02X\n", index); */
+}
+#endif
+
+static irqreturn_t ep93xxkbd_irq_handler(int irq, void *dev_id,
+					 struct pt_regs *regs)
+{
+	unsigned int keystat, key1, key2;
+	static unsigned int lastkeystat = 0, lastkey1 = 0, lastkey2 = 0;
+
+	/* Note: IRQ_KEY automatically disabled before entry, */
+	/* and reenabled after exit by Linux interrupt code. */
+
+	/* Reading status clears keyboard interrupt */
+
+	keystat = readl(KEY_REG) &
+	    (KEYREG_KEY1COL_MASK | KEYREG_KEY1ROW_MASK |
+	     KEYREG_KEY2COL_MASK | KEYREG_KEY2ROW_MASK |
+	     KEYREG_1KEY | KEYREG_2KEYS);
+
+#ifdef DEBUG			/* DEBUGGING */
+	if (keystat == lastkeystat)
+		printk("ep93xx_scan_keyb:  spurious interrupt, stat %x\n",
+		       keystat);
+	else
+		printk("ep93xx_scan_keyb:  interrupt, stat %x\n", keystat);
+#endif
+	if (keystat & KEYREG_1KEY)
+		key1 =
+		    KEYCODE((keystat & KEYREG_KEY1ROW_MASK) >>
+			    KEYREG_KEY1ROW_SHIFT,
+			    (keystat & KEYREG_KEY1COL_MASK) >>
+			    KEYREG_KEY1COL_SHIFT);
+	else
+		key1 = 0;	/* invalid */
+
+	if (keystat & KEYREG_2KEYS)
+		key2 =
+		    KEYCODE((keystat & KEYREG_KEY2ROW_MASK) >>
+			    KEYREG_KEY2ROW_SHIFT,
+			    (keystat & KEYREG_KEY2COL_MASK) >>
+			    KEYREG_KEY2COL_SHIFT);
+	else
+		key2 = 0;	/* invalid */
+
+	/*
+	 * This 'monster' decision tree is used to decide what to report
+	 * when last key state has changed to current key state.
+	 * This may involve up to 4 keys changing state simultaneously:
+	 * lastkey1, lastkey2 going up and key1, key2 going down.
+	 *
+	 * We use keyboard scanner hardware guarantees to simplify the logic:
+	 *      key1 < key2     if both are valid
+	 *      key1 is valid   if key2 is valid
+	 *
+	 *      handle_scancode called with down and up scancodes
+	 *              scancode = keycode when down
+	 *              scancode = keycode|KBUP when up
+	 *
+	 * Note that if more than one keys change state in the same scan period,
+	 * then we really do NOT know the order in which the key events occurred.
+	 * Our default behavior is to always report key up events before key down
+	 * events.  However, multiple key up events or multiple key down events
+	 * will be reported in no special order.
+	 */
+	if (!(lastkeystat & (KEYREG_1KEY | KEYREG_2KEYS))) {	/* No keys down lasttime */
+		if (key1)
+			handle_scancode(key1, 1);
+		if (key2)
+			handle_scancode(key2, 1);
+	} else if (lastkey1 == key1) {	/* means key still down */
+		/* no change for key1 or lastkey1, both valid */
+		if (lastkey2 != key2) {
+			/* lastkey2 went up if valid, key2 went down if valid */
+			if (lastkey2)
+				handle_scancode(lastkey2 | KBUP, 0);
+			if (key2)
+				handle_scancode(key2, 1);
+		}
+		/* else no change for all keys */
+	} else if (key1)
+	{			/* key1 valid and */
+		/* lastkey1 valid (because NOT no keys lasttime) */
+		if (lastkey1 == key2) {
+			/* no change for lastkey1 or key2 */
+			/* lastkey2 went up if valid, key1 went down */
+			if (lastkey2)
+				handle_scancode(lastkey2 | KBUP, 0);
+			handle_scancode(key1, 1);
+
+		} else {
+			/* we know: lastkey1 valid and went up, key1 valid */
+			handle_scancode(lastkey1 | KBUP, 0);
+
+			if (lastkey2 == key1) {
+				/* no change for lastkey2 or key1 */
+				/* key2 went down if valid */
+				if (key2)
+					handle_scancode(key2, 1);
+
+			} else {
+				if (lastkey2 != key2) {
+					/* lastkey2 went up if valid */
+					/* key2 went down if valid */
+					if (lastkey2)
+						handle_scancode(lastkey2 | KBUP,
+								0);
+					if (key2)
+						handle_scancode(key2, 1);
+				}
+				/* else no change for lastkey2 or key2 */
+
+				/* key1 valid and went down */
+				handle_scancode(key1, 1);
+			}
+		}
+	} else {
+		/* key1 not valid and */
+		/* lastkey1 valid (because NOT no keys lasttime) */
+
+		/* key1 not valid means both key1, key2 not valid */
+		/* so lastkey1 went up and lastkey2 went up if valid */
+		handle_scancode(lastkey1 | KBUP, 0);
+		if (lastkey2)
+			handle_scancode(lastkey2 | KBUP, 0);
+	}
+
+	lastkeystat = keystat;
+	lastkey1 = key1;
+	lastkey2 = key2;
+	return IRQ_HANDLED;
+}
+
+int __init ep93xxkbd_init(void)
+{
+	int i = 3;
+	unsigned int uiTemp;
+	int error = 0;
+	
+	dev = input_allocate_device();
+	if (!dev) {
+		printk(KERN_ERR "ep93xx_kbd_8x8: not enough memory for input device\n");
+		return -ENOMEM;
+	}
+
+	dev->name = "Cirrus EP93xx 8x8 keypad matrix driver";
+	dev->phys = "input0";
+	dev->id.bustype = BUS_HOST;
+	dev->evbit[0] = BIT(EV_KEY);
+
+	printk("%s\n", dev->name);
+
+	/* Make sure scanner enabled, active and that */
+	/* Keyboard ROW/COL interface enabled. */
+
+	uiTemp = readl(SYSCON_DEVCFG);
+
+	uiTemp &= ~(SYSCON_DEVCFG_KEYS | SYSCON_DEVCFG_GONK);
+
+	SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(uiTemp));
+
+	/* SYSCON locked automatically now after RSTCR written */
+
+	/* Enable Keyboard Clock and select clock rate
+	 *
+	 *      TBD Boot ROM has already inited KTDIV = 0x20018004
+	 *      TBD Measured default 64usec scan period with scope.
+
+	 * Assume that GPIO registers do not impact row,col pins since
+	 * they are assigned to keyboard scanner.
+
+	 * Setup Keyboard Scanner
+	 *
+	 * Note that we change the scanner parameters on the fly
+	 * while it is running, which is okay.  No need to disable
+	 * scanner while tweaking these.
+	 *
+	 * TBD Keyboard scan rate will change as master clocks/dividers change
+	 *
+	 * For now, this gives us measured rate of about 480Hz row scan rate,
+	 * which implies 60Hz full kbd scan rate.  Together with debounce
+	 * count of 3, means debounce period = 3/60Hz = 50ms>30ms recommended,
+	 * so okay.
+	 */
+	writel((0x00FC00FA | SCANINIT_DIS3KY), SCANINIT);
+
+	/*TBD If too much capacitance on keyboard */
+	/* writel( (0x00FC0020 | SCBACK | SCDIS3KEY), SCANINIT ); */
+
+	uiTemp = readl(SYSCON_KTDIV) | SYSCON_KTDIV_KEN;
+
+	SysconSetLocked(SYSCON_KTDIV, uiTemp);
+
+	error =
+	    request_irq(IRQ_KEY, ep93xxkbd_irq_handler, 0,
+			"ep93xx_keypad_handler",
+			(void *)(ep93xxkbd_irq_handler));
+	if (error) {
+		printk("Error: %s could not allocate IRQ%d\n", dev->name, IRQ_KEY);
+		return error;
+	}
+	/* Note: request_irq has just enabled IRQ_KEY for us. */
+
+	/* Warning: We have initialized last key status to indicate
+	 * all keys up which may not be the current hardware state.
+	 *
+	 *      TBD If this is important to detect, to alert user
+	 *      TBD to a possibly faulty keyboard, then we could
+	 *      TBD manually scan the keyboard to verify all keys up.
+	 *
+
+	 * Three common cases here:
+	 *      1.  All keys up.  This is normal, expected status of keyboard.
+	 *      2.  All keys up, although at some time ago during initialization
+	 *      a key was momentarily pressed, causing the hardware to latch it.
+	 *      3.  Some key is being held down now.
+	 *
+	 * Reading status clears any pending keyboard interrupt.
+	 */
+
+	i = readl(KEY_REG);
+
+	/*
+	 * We believe this will have the following impact on common cases:
+	 *
+	 *      1.  No impact.
+	 *      2.  Momentary presses will be cleared out so they do not
+	 *      bother us.  Although we get a spurious key up immediately because
+	 *      the keyboard hardware will see change from last
+	 *      latched status and current status, higher level keyboard driver
+	 *      should ignore.
+	 *      3.  Key being held will generate a new pending key down
+	 *      event which is acceptable.
+	 *
+	 * Now keyboard is active and will generate interrupts
+	 * on key presses.  Driver only needs to handle interrupts.
+	 * There are NO driver ioctl or deinit functions in lowlevel.
+	 */
+
+#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
+	for (i = 0; i < EP93XX_KEYMAP_SIZE * 16; i++)
+		set_bit(keycode[i/EP93XX_KEYMAP_SIZE][i%EP93XX_KEYMAP_SIZE], dev->keybit);
+#else
+	for (i = 0; i < EP93XX_KEYMAP_SIZE; i++)
+		set_bit(keycode[i], dev->keybit);
+#endif
+
+	input_register_device(dev);
+
+	return 0;
+}
+
+static void __exit ep93xxkbd_cleanup(void)
+{
+	writel(0x000000AA, SYSCON_SWLOCK);	/* unlock SYSCON Software Lock */
+	writel(readl(SYSCON_KTDIV) & 0xFFFF7FFF, SYSCON_KTDIV);	/* disable Key Matrix Clock KEN */
+	free_irq(IRQ_KEY, NULL);
+	input_unregister_device(dev);
+}
+
+module_init(ep93xxkbd_init);
+module_exit(ep93xxkbd_cleanup);
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h
new file mode 100644
index 0000000..31fd4db
--- /dev/null
+++ b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h
@@ -0,0 +1,146 @@
+static unsigned char keycode[16][0x40] = 
+{{
+	KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, 0, 0,
+	KEY_ESC, KEY_BACKSPACE, KEY_7, KEY_8, KEY_9, 0, 0, 0,
+	KEY_PROG1, KEY_PROG2, KEY_4, KEY_5, KEY_6, 0, 0, 0,
+	KEY_MENU, KEY_0, KEY_1, KEY_2, KEY_3, 0, 0, 0,
+	KEY_LEFTSHIFT, KEY_UP, KEY_TAB, 0, 0, 0, 0, 0,
+	KEY_LEFT, KEY_LEFTALT, KEY_RIGHT, 0, 0, 0, 0, 0,
+	KEY_LEFTCTRL, KEY_DOWN, KEY_ENTER, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, KEY_A, KEY_D, KEY_G, 0, 0, 0,
+	0, 0, KEY_J, KEY_M, KEY_P, 0, 0, 0,
+	0, KEY_DOT, KEY_S, KEY_V, KEY_Y, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, KEY_B, KEY_E, KEY_H, 0, 0, 0,
+	0, 0, KEY_K, KEY_N, KEY_Q, 0, 0, 0,
+	0, KEY_COMMA, KEY_T, KEY_W, KEY_Z, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, KEY_C, KEY_F, KEY_I, 0, 0, 0,
+	0, 0, KEY_L, KEY_O, KEY_R, 0, 0, 0,
+	0, KEY_SLASH, KEY_U, KEY_X, KEY_SPACE, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_KPASTERISK, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_KPPLUS, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_KPMINUS, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_EQUAL, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_SEMICOLON, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_APOSTROPHE, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_KPLEFTPAREN, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_KPRIGHTPAREN, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_LEFTBRACE, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, KEY_RIGHTBRACE, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	}, {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+}};
diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h
new file mode 100644
index 0000000..65dca77
--- /dev/null
+++ b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h
@@ -0,0 +1,11 @@
+static unsigned char keycode[0x40] =
+{
+	KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, 0, 0,
+	KEY_ESC, KEY_BACKSPACE, KEY_7, KEY_8, KEY_9, 0, 0, 0,
+	KEY_PROG1, KEY_PROG2, KEY_4, KEY_5, KEY_6, 0, 0, 0,
+	KEY_MENU, KEY_0, KEY_1, KEY_2, KEY_3, 0, 0, 0,
+	KEY_LEFTSHIFT, KEY_UP, KEY_TAB, 0, 0, 0, 0, 0,
+	KEY_LEFT, KEY_LEFTALT, KEY_RIGHT, 0, 0, 0, 0, 0,
+	KEY_LEFTCTRL, KEY_DOWN, KEY_ENTER, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+};
diff --git a/drivers/input/keyboard/ep93xx_spi_kbd.c b/drivers/input/keyboard/ep93xx_spi_kbd.c
new file mode 100644
index 0000000..b6ad607
--- /dev/null
+++ b/drivers/input/keyboard/ep93xx_spi_kbd.c
@@ -0,0 +1,407 @@
+/******************************************************************************
+ *
+ *  File:	linux/drivers/char/ep93xx_spi_kbd.c
+ *
+ *  Purpose:	Support for SPI Keyboard for a Cirrus Logic EP93xx
+ *
+ *  History:
+ *
+ *  Limitations:
+ *  Break and Print Screen keys not handled yet!
+ *
+ *
+ *  Copyright 2003 Cirrus Logic Inc.
+ * 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
+ *
+ ******************************************************************************/
+
+/*
+ * FIXME: There are more parity problems than there ought to be.
+ * TODO: Track down
+ * WHERE: grep for "BAD_PARITY"
+ * 
+ * WORKAROUND: Do not press too many keys and do not type too fast
+ *             type key another time if it got lost
+ *
+ * WORKAROUND2: Use USB Keyboards or 8x8 matrix keypad instead
+ * 
+ * FIXME2: Keymap should be done properly
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/arch/ssp-cirrus.h>
+
+#include "ep93xx_spi_kbd.h"
+
+#define EP93XX_MAX_KEY_DOWN_COUNT 6
+
+void DataCallback(unsigned int Data);
+static int g_SSP_Handle;
+static struct input_dev *ep93xxkbd_dev;
+
+#undef UART_HACK_DEBUG
+/* #define UART_HACK_DEBUG 1 */
+
+#if defined(UART_HACK_DEBUG) && defined(CONFIG_DEBUG_LL)
+char szBuf[256];
+#define DPRINTK( x... )   \
+	sprintf( szBuf, ##x ); \
+	printascii( szBuf );
+#else
+#define DPRINTK( x... )
+#endif
+
+struct key_down_tracker_t {
+	unsigned char scancode;
+	unsigned char count;
+};
+
+/*
+ * In the interest of efficiency, let's only allow 5 keys to be down
+ * at a time, maximum.  So if anybody is having a temper tantrum on
+ * their keyboard, they may get stuck keys, but that's to be expected.
+ */
+
+#define MAX_KEYS_DOWN 8
+static struct key_down_tracker_t KeyTracker[MAX_KEYS_DOWN];
+
+static unsigned char SPI2KScan(unsigned int uiSPIValue, int *pValid);
+static void InitSniffer(void);
+static void KeySniffer(unsigned char scancode, int down);
+static void Check4StuckKeys(void);
+
+/**
+ * handle_scancode - wrapper
+ *
+ * wrap old style (2.4.x) to 2.6.x input subsystem
+ */
+static void handle_scancode(unsigned char scancode, int down)
+{
+	DPRINTK("handle_scancode(scancode=%04X, down=%d); %02X ", scancode,
+		down, scancode & 0x7f);
+
+	if (scancode > KSCAN_TABLE_SIZE)
+		scancode &= ~EXTENDED_KEY;
+
+	input_report_key(ep93xxkbd_dev, KScanCodeToVKeyTable[scancode], down);
+	input_sync(ep93xxkbd_dev);
+
+	DPRINTK("(virtual) scancode=%02X\n", scancode);
+}
+
+/**
+ * InitSniffer
+ *
+ * Clear our struct to indicate that no keys are down now.
+ * If somebody boots this thing while holding down keys, then they'll
+ * get what they deserve.
+ *
+ */
+static void InitSniffer(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_KEYS_DOWN; i++) {
+		KeyTracker[i].count = 0;
+		KeyTracker[i].scancode = 0;
+	}
+}
+
+/**
+ * KeySniffer
+ *
+ * To prevent stuck keys, keep track of what keys are down.  This information
+ * is used by Check4StuckKeys().
+ */
+static void KeySniffer(unsigned char scancode, int down)
+{
+	int i;
+
+	/*
+	 * There are certain keys that will definately get held down
+	 * and we can't interfere with that.
+	 */
+	switch (scancode) {
+	case 0x12:		/* left  shift */
+	case 0x59:		/* right shift */
+	case 0x14:		/* left  ctrl  */
+	case 0x94:		/* right ctrl  */
+	case 0x11:		/* left  alt   */
+	case 0x91:		/* right alt   */
+	case 0x58:		/* caps lock   */
+	case 0x77:		/* Num lock    */
+		/* printk("Snuff - %02x, %d\n", scancode, down); */
+		handle_scancode(scancode, down);
+		return;
+
+	default:
+		break;
+	}
+
+	/* printk("Sniff - %02x, %d\n", scancode, down ); */
+
+	/*
+	 * Go thru our array, looking for the key.  If it already
+	 * is recorded, update its count.
+	 * Also look for empty cells in the array in case we
+	 * need one.
+	 */
+	for (i = 0; i < MAX_KEYS_DOWN; i++) {
+		/* If this is a key up in our list then we are done. */
+		if (down == 0) {
+			if (KeyTracker[i].scancode == scancode) {
+				KeyTracker[i].count = 0;
+				KeyTracker[i].scancode = 0;
+				handle_scancode(scancode, down);
+				break;
+			}
+		}
+		/* Hey here's an unused cell.  Save its index. */
+		else if (KeyTracker[i].count == 0) {
+			KeyTracker[i].scancode = scancode;
+			KeyTracker[i].count = 1;
+			handle_scancode(scancode, down);
+			break;
+		}
+	}
+}
+
+/**
+ * Check4StuckKeys
+ *
+ * When a key is held down longer than 1/2 sec, it start repeating
+ * 10 times a second.  What we do is watch how long each key is
+ * held down.  If longer than X where X is less than 1/2 second
+ * then we assume it is stuck and issue the key up.  If we were
+ * wrong and the key really is being held down, no problem because
+ * the keyboard is about to start sending it to us repeatedly
+ * anyway.
+ */
+static void Check4StuckKeys(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_KEYS_DOWN; i++) {
+		if (KeyTracker[i].count) {
+			KeyTracker[i].count++;
+			if (KeyTracker[i].count >= EP93XX_MAX_KEY_DOWN_COUNT) {
+				handle_scancode(KeyTracker[i].scancode, 0);
+				KeyTracker[i].count = 0;
+				KeyTracker[i].scancode = 0;
+			}
+		}
+	}
+}
+
+/**
+ * HandleKeyPress
+ *
+ * Checks if there are any keys in the FIFO and processes them if there are.
+ */
+void HandleKeyPress(unsigned int Data)
+{
+	static unsigned char ucKScan[4] = { 0, 0, 0, 0 };
+	static unsigned int ulNum = 0;
+	int bParityValid;
+
+	/*
+	 * No keys to decode, but the timer went off and is calling us
+	 * to check for stuck keys.
+	 */
+	if (Data == -1) {
+		Check4StuckKeys();
+		return;
+	}
+	/*
+	 * Read in the value from the SPI controller.
+	 */
+	ucKScan[ulNum++] = SPI2KScan(Data, &bParityValid);
+
+	/*
+	 * Bad parity?  We should read the rest of the fifo and
+	 * throw it away, because it will all be bad.  Then the
+	 * SSP will be reset when we close the SSP driver and
+	 * all will be good again.
+	 */
+	if (!bParityValid) {
+		/*      printk("_BAD_PARITY_");   */
+		ulNum = 0;
+	}
+	/* If we have one character in the array, do the following. */
+	if (ulNum == 1) {
+		/*
+		 * If it is a simple key without the extended scan code perform
+		 * following.
+		 */
+		if (ucKScan[0] < KSCAN_TABLE_SIZE) {
+			DPRINTK("1:Dn %02x\n", ucKScan[0]);
+			KeySniffer(ucKScan[0], 1);
+			ulNum = 0;
+		}
+		/*
+		 * I don't know what type of character this is so erase the
+		 * keys stored in the buffer and continue.
+		 */
+		else if ((ucKScan[0] != 0xF0) && (ucKScan[0] != 0xE0)) {
+			DPRINTK("1:oops - %02x\n", ucKScan[0]);
+			ulNum = 0;
+		}
+	} else if (ulNum == 2) {
+		/*
+		 * 0xF0 means that a key has been released.
+		 */
+		if (ucKScan[0] == 0xF0) {
+			/*
+			 * If it is a simple key without the extended scan code
+			 * perform the following.
+			 */
+			if (ucKScan[1] < KSCAN_TABLE_SIZE) {
+				DPRINTK("2:Up %02x %02x\n", ucKScan[0],
+					ucKScan[1]);
+				KeySniffer(ucKScan[1], 0);
+				ulNum = 0;
+			}
+			/*
+			 * If it a extended kscan continue to get the next byte.
+			 */
+			else if (ucKScan[1] != 0xE0) {
+				DPRINTK("2:oops - %02x %02x\n", ucKScan[0],
+					ucKScan[1]);
+				ulNum = 0;
+			}
+		}
+		/*
+		 * Find out what extended code it is.
+		 */
+		else if (ucKScan[0] == 0xE0 && ucKScan[1] != 0xF0) {
+			DPRINTK("2:Dn %02x %02x\n", ucKScan[0], ucKScan[1]);
+			KeySniffer(EXTENDED_KEY | ucKScan[1], 1);
+			ulNum = 0;
+		}
+	}
+	/* This means that an extended code key has been released. */
+	else if (ulNum == 3) {
+		/* 0xF0 means that a key has been released. */
+		if (ucKScan[0] == 0xE0 && ucKScan[1] == 0xF0) {
+			DPRINTK("3:Up %02x %02x %02x",
+				ucKScan[0], ucKScan[1], ucKScan[2]);
+			KeySniffer(EXTENDED_KEY | ucKScan[2], 0);
+		} else {
+			DPRINTK("3:oops - %02x %02x %02x\n",
+				ucKScan[0], ucKScan[1], ucKScan[2]);
+		}
+		ulNum = 0;
+	}
+}
+
+/**
+ * SPI2KScan - Get a character from the spi port if it is available.
+ *
+ * Below is a picture of the spi signal from the PS2.
+ *
+ * CK HHllllHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHllll
+ * DA HHHllllll000000111111222222333333444444555555666666777777ppppppssssssLLLLHHH
+ *        ^                                                                ^
+ *    start bit                                                   important bit
+ *
+ * where:  l = 8042 driving the line
+ *        L = KEYBOARD driving the line
+ *        1..7 data
+ *         = Parity 8042 driving
+ *        s = stop   8042 driving
+ *         = PARITY KEYBOARD driving the line
+ *        S = STOP   KEYBOARD driving the line
+ *
+ *  In our design the value comes high bit first and is inverted.  So we must
+ *  convert it to low byte first and then inverted it back.
+ *
+ */
+static unsigned char SPI2KScan(unsigned int uiSPIValue, int *pValid)
+{
+	unsigned char ucKScan = 0;
+	unsigned int uiParity = 0;
+	unsigned int uiCount = 0;
+
+	for (uiCount = 1; uiCount < 10; uiCount++) {
+		uiParity += (uiSPIValue >> uiCount) & 0x1;
+	}
+
+	if (!(uiParity & 0x1) && (uiSPIValue & 0x401) == 0x400) {
+		*pValid = 1;
+
+		/* Invert the pattern. */
+		uiSPIValue = ~uiSPIValue;
+
+		/* Read in the value from the motorola spi file */
+		ucKScan = (unsigned char)((uiSPIValue & 0x004) << 5);
+		ucKScan |= (unsigned char)((uiSPIValue & 0x008) << 3);
+		ucKScan |= (unsigned char)((uiSPIValue & 0x010) << 1);
+		ucKScan |= (unsigned char)((uiSPIValue & 0x020) >> 1);
+		ucKScan |= (unsigned char)((uiSPIValue & 0x040) >> 3);
+		ucKScan |= (unsigned char)((uiSPIValue & 0x080) >> 5);
+		ucKScan |= (unsigned char)((uiSPIValue & 0x100) >> 7);
+		ucKScan |= (unsigned char)((uiSPIValue & 0x200) >> 9);
+	} else {
+		*pValid = 0;
+	}
+
+	return ucKScan;
+}
+
+int __init EP93XXSpiKbdInit(void)
+{
+	int i;
+	
+	ep93xxkbd_dev = input_allocate_device();
+	if (!ep93xxkbd_dev) {
+		printk(KERN_ERR "ep93xxkbd: not enough memory for input device\n");
+		return -ENOMEM;
+	}
+	
+	ep93xxkbd_dev->name = "Cirrus EP93xx PS/2 keyboard driver";
+	printk("%s\n", ep93xxkbd_dev->name);
+	
+	ep93xxkbd_dev->evbit[0] = BIT(EV_KEY);
+
+	for (i = 0; i < KSCAN_TABLE_SIZE; i++)
+		set_bit(KScanCodeToVKeyTable[i], ep93xxkbd_dev->keybit);
+
+	input_register_device(ep93xxkbd_dev);
+
+	/* Open SSP driver for Keyboard input. */
+	g_SSP_Handle = SSPDriver->Open(PS2_KEYBOARD, HandleKeyPress);
+
+	InitSniffer();
+
+	DPRINTK("Leaving EP93XXSpiKbdInit()\n");
+
+	return 0;
+}
+
+void __exit EP93XXSpiKbdCleanup(void)
+{
+	SSPDriver->Close(g_SSP_Handle);
+	input_unregister_device(ep93xxkbd_dev);
+}
+
+module_init(EP93XXSpiKbdInit);
+module_exit(EP93XXSpiKbdCleanup);
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/ep93xx_spi_kbd.h b/drivers/input/keyboard/ep93xx_spi_kbd.h
new file mode 100644
index 0000000..7f4bd90
--- /dev/null
+++ b/drivers/input/keyboard/ep93xx_spi_kbd.h
@@ -0,0 +1,147 @@
+/*
+ * ep93xx_spi_kbd.h Keymap definitions (to be cleaned up)
+ */
+
+#define KSCAN_TABLE_SIZE    0x88
+
+#define EXTENDED_KEY     0x80
+
+/* This table is used to map the scan code to the Linux default keymap. */
+static unsigned int const KScanCodeToVKeyTable[KSCAN_TABLE_SIZE] = {
+	KEY_RESERVED,		/* Scan Code 0x0 */
+	KEY_F9,			/* Scan Code 0x1 */
+	KEY_RESERVED,		/* Scan Code 0x2 */
+	KEY_F5,			/* Scan Code 0x3 */
+	KEY_F3,			/* Scan Code 0x4 */
+	KEY_F1,			/* Scan Code 0x5 */
+	KEY_F2,			/* Scan Code 0x6 */
+	KEY_F12,		/* Scan Code 0x7 */
+	KEY_RESERVED,		/* Scan Code 0x8 */
+	KEY_F10,		/* Scan Code 0x9 */
+	KEY_F8,			/* Scan Code 0xA */
+	KEY_F6,			/* Scan Code 0xB */
+	KEY_F4,			/* Scan Code 0xC */
+	KEY_TAB,		/* Scan Code 0xD Tab */
+	KEY_GRAVE,		/* Scan Code 0xE ' */
+	KEY_RESERVED,		/* Scan Code 0xF */
+	KEY_RESERVED,		/* Scan Code 0x10 */
+	KEY_LEFTALT,		/* Scan Code 0x11 Left Menu */
+	KEY_LEFTSHIFT,		/* Scan Code 0x12 Left Shift */
+	KEY_RESERVED,		/* Scan Code 0x13 */
+	KEY_LEFTCTRL,		/* Scan Code 0x14 */
+	KEY_Q,			/* Scan Code 0x15 */
+	KEY_1,			/* Scan Code 0x16 */
+	KEY_RESERVED,		/* Scan Code 0x17 */
+	KEY_RESERVED,		/* Scan Code 0x18 */
+	KEY_RESERVED,		/* Scan Code 0x19 */
+	KEY_Z,			/* Scan Code 0x1A */
+	KEY_S,			/* Scan Code 0x1B */
+	KEY_A,			/* Scan Code 0x1C */
+	KEY_W,			/* Scan Code 0x1D */
+	KEY_2,			/* Scan Code 0x1E */
+	KEY_RESERVED,		/* Scan Code 0x1F */
+	KEY_RESERVED,		/* Scan Code 0x20 */
+	KEY_C,			/* Scan Code 0x21 */
+	KEY_X,			/* Scan Code 0x22 */
+	KEY_D,			/* Scan Code 0x23 */
+	KEY_E,			/* Scan Code 0x24 */
+	KEY_4,			/* Scan Code 0x25 */
+	KEY_3,			/* Scan Code 0x26 */
+	KEY_RESERVED,		/* Scan Code 0x27 */
+	KEY_RESERVED,		/* Scan Code 0x28 */
+	KEY_SPACE,		/* Scan Code 0x29  Space */
+	KEY_V,			/* Scan Code 0x2A */
+	KEY_F,			/* Scan Code 0x2B */
+	KEY_T,			/* Scan Code 0x2C */
+	KEY_R,			/* Scan Code 0x2D */
+	KEY_5,			/* Scan Code 0x2E */
+	KEY_RESERVED,		/* Scan Code 0x2F */
+	KEY_RESERVED,		/* Scan Code 0x30 */
+	KEY_N,			/* Scan Code 0x31 */
+	KEY_B,			/* Scan Code 0x32 B */
+	KEY_H,			/* Scan Code 0x33 */
+	KEY_G,			/* Scan Code 0x34 */
+	KEY_Y,			/* Scan Code 0x35 */
+	KEY_6,			/* Scan Code 0x36 */
+	KEY_RESERVED,		/* Scan Code 0x37 */
+	KEY_RESERVED,		/* Scan Code 0x38 */
+	KEY_RESERVED,		/* Scan Code 0x39 */
+	KEY_M,			/* Scan Code 0x3A */
+	KEY_J,			/* Scan Code 0x3B */
+	KEY_U,			/* Scan Code 0x3C */
+	KEY_7,			/* Scan Code 0x3D */
+	KEY_8,			/* Scan Code 0x3E */
+	KEY_RESERVED,		/* Scan Code 0x3F */
+	KEY_RESERVED,		/* Scan Code 0x40 */
+	KEY_COMMA,		/* Scan Code 0x41 */
+	KEY_K,			/* Scan Code 0x42 */
+	KEY_I,			/* Scan Code 0x43 */
+	KEY_O,			/* Scan Code 0x44 */
+	KEY_0,			/* Scan Code 0x45 */
+	KEY_9,			/* Scan Code 0x46 */
+	KEY_RESERVED,		/* Scan Code 0x47 */
+	KEY_RESERVED,		/* Scan Code 0x48 */
+	KEY_DOT,		/* Scan Code 0x49 */
+	KEY_SLASH,		/* Scan Code 0x4A */
+	KEY_L,			/* Scan Code 0x4B */
+	KEY_SEMICOLON,		/* Scan Code 0x4C */
+	KEY_P,			/* Scan Code 0x4D */
+	KEY_MINUS,		/* Scan Code 0x4E */
+	KEY_RESERVED,		/* Scan Code 0x4F */
+	KEY_RESERVED,		/* Scan Code 0x50 */
+	KEY_RESERVED,		/* Scan Code 0x51 */
+	KEY_APOSTROPHE,		/* Scan Code 0x52 */
+	KEY_RESERVED,		/* Scan Code 0x53 */
+	KEY_LEFTBRACE,		/* Scan Code 0x54 */
+	KEY_EQUAL,		/* Scan Code 0x55 */
+	KEY_BACKSPACE,		/* Scan Code 0x56 */
+	KEY_RESERVED,		/* Scan Code 0x57 */
+	KEY_CAPSLOCK,		/* Scan Code 0x58 Caps Lock */
+	KEY_RIGHTSHIFT,		/* Scan Code 0x59 Right Shift */
+	KEY_ENTER,		/* Scan Code 0x5A */
+	KEY_RIGHTBRACE,		/* Scan Code 0x5B */
+	KEY_RESERVED,		/* Scan Code 0x5C */
+	KEY_BACKSLASH,		/* Scan Code 0x5D */
+	KEY_RESERVED,		/* Scan Code 0x5E */
+	KEY_RESERVED,		/* Scan Code 0x5F */
+	KEY_RESERVED,		/* Scan Code 0x60 */
+	KEY_BACKSLASH,		/* Scan Code 0x61 ?? VK_BSLH,             */
+	KEY_RESERVED,		/* Scan Code 0x62 */
+	KEY_RESERVED,		/* Scan Code 0x63 */
+	KEY_RESERVED,		/* Scan Code 0x64 */
+	KEY_RESERVED,		/* Scan Code 0x65 */
+	KEY_BACKSPACE,		/* Scan Code 0x66 ?? VK_BKSP,             */
+	KEY_RESERVED,		/* Scan Code 0x67 */
+	KEY_RESERVED,		/* Scan Code 0x68 */
+	KEY_KP1,		/* Scan Code 0x69 */
+	KEY_RESERVED,		/* Scan Code 0x6A */
+	KEY_KP4,		/* Scan Code 0x6B */
+	KEY_KP7,		/* Scan Code 0x6C */
+	KEY_RESERVED,		/* Scan Code 0x6D */
+	KEY_RESERVED,		/* Scan Code 0x6E */
+	KEY_RESERVED,		/* Scan Code 0x6F */
+	KEY_KP0,		/* Scan Code 0x70 */
+	KEY_KPDOT,		/* Scan Code 0x71 DECIMAL?? */
+	KEY_KP2,		/* Scan Code 0x72 */
+	KEY_KP5,		/* Scan Code 0x73 */
+	KEY_KP6,		/* Scan Code 0x74 */
+	KEY_KP8,		/* Scan Code 0x75 */
+	KEY_ESC,		/* Scan Code 0x76 */
+	KEY_NUMLOCK,		/* Scan Code 0x77 */
+	KEY_F11,		/* Scan Code 0x78 */
+	KEY_KPPLUS,		/* Scan Code 0x79 */
+	KEY_KP3,		/* Scan Code 0x7A */
+	KEY_KPMINUS,		/* Scan Code 0x7B */
+	KEY_KPASTERISK,		/* Scan Code 0x7C */
+	KEY_KP9,		/* Scan Code 0x7D */
+	KEY_SCROLLLOCK,		/* Scan Code 0x7E */
+	KEY_RESERVED,		/* Scan Code 0x7F */
+	KEY_RESERVED,		/* Scan Code 0x80 */
+	KEY_RESERVED,		/* Scan Code 0x81 */
+	KEY_RESERVED,		/* Scan Code 0x82 */
+	KEY_F7,			/* Scan Code 0x83 */
+	KEY_RESERVED,		/* Scan Code 0x84 */
+	KEY_RESERVED,		/* Scan Code 0x85 */
+	KEY_RESERVED,		/* Scan Code 0x86 */
+	KEY_RESERVED		/* Scan Code 0x87 */
+};
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 21d55ed..5453395 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -95,4 +95,15 @@ config TOUCHSCREEN_HP600
 	  To compile this driver as a module, choose M here: the
 	  module will be called hp680_ts_input.
 
+config TOUCHSCREEN_EP93XX
+	tristate "EP93xx touchscreen"
+        depends on ARCH_EP93XX
+	help
+	  Say Y here if you have a touchscreen connected to your EP93xx CPU.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ep93xx_ts.
+
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 6842869..f8e6eb4 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_TOUCHSCREEN_ELO)	+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
 obj-$(CONFIG_TOUCHSCREEN_MK712)	+= mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)	+= hp680_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_EP93XX) += ep93xx_ts.o
diff --git a/drivers/input/touchscreen/ep93xx_ts.c b/drivers/input/touchscreen/ep93xx_ts.c
new file mode 100644
index 0000000..fc4622e
--- /dev/null
+++ b/drivers/input/touchscreen/ep93xx_ts.c
@@ -0,0 +1,748 @@
+/*
+ *  linux/drivers/char/ep93xx_ts.c
+ *
+ *  Copyright (C) 2003-2004 Cirrus Corp.
+ *
+ * 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/types.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/input.h>
+#include <linux/pci.h>
+
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+/*
+ * To customize for a new touchscreen, there are various macros that
+ * have to be set.  If you allow UART_HACK_DEBUG to be defined, you
+ * will get real time ts data scrolling up your serial terminal
+ * screen that will help you empirically determine good values for these.
+ *
+ *
+ * These are used as trigger levels to know when we have pen up/down
+ *
+ * The rules:
+ * 1.  TS_HEAVY_INV_PRESSURE < TS_LIGHT_INV_PRESSURE because these
+ *    are Inverse pressure.
+ * 2.  Any touch lighter than TS_LIGHT_INV_PRESSURE is a pen up.
+ * 3.  Any touch heavier than TS_HEAVY_INV_PRESSURE is a pen down.
+ */
+#define TS_HEAVY_INV_PRESSURE	(0x1000 - pressure_max)
+#define TS_LIGHT_INV_PRESSURE	(0x1000 - pressure_min)
+
+/*
+ * If the x, y, or inverse pressure changes more than these values
+ * between two succeeding points, the point is not reported.
+ */
+#define TS_MAX_VALID_PRESSURE_CHANGE	(pressure_jitter)
+#define TS_MAX_VALID_XY_CHANGE  (xy_jitter)
+
+/* old defaults */
+#if 0
+#define TS_X_MIN	0
+#define TS_Y_MIN	0
+#define TS_X_MAX	0xfff
+#define TS_Y_MAX	0xfff
+#endif
+
+/* "improved" defaults */
+#define TS_X_MIN	0x2d9
+#define TS_Y_MIN	0xd0a
+#define TS_X_MAX	0xd42
+#define TS_Y_MAX	0x2e0
+
+static uint16_t pressure_min = 0x001;
+static uint16_t pressure_max = 0x010;
+static uint16_t pressure_jitter = 0x300;
+static uint16_t xy_jitter = 0x100;
+module_param(pressure_min, ushort, 0);
+module_param(pressure_max, ushort, 0);
+module_param(pressure_jitter, ushort, 0);
+module_param(xy_jitter, ushort, 0);
+MODULE_PARM_DESC(pressure_min, "Minimum pressure (0 - 4095)");
+MODULE_PARM_DESC(pressure_max, "Maximum pressure (0 - 4095)");
+MODULE_PARM_DESC(pressure_jitter, "Minimum pressure jitter (0 - 4095)");
+MODULE_PARM_DESC(xy_jitter, "Minimum X-Y jitter (0 - 4095)");
+
+/* This is the minimum Z1 Value that is valid. */
+#define     MIN_Z1_VALUE                    0x50
+
+/*
+ * Settling delay for taking each ADC measurement.  Increase this
+ * if ts is jittery.
+ */
+#define EP93XX_TS_ADC_DELAY_USEC 2000
+
+/* Delay between TS points. */
+
+#define EP93XX_TS_PER_POINT_DELAY_USEC 10000
+
+/*-----------------------------------------------------------------------------
+ * Debug messaging thru the UARTs
+ *-----------------------------------------------------------------------------
+ *
+ *  Hello there!  Are you trying to get this driver to work with a new
+ *  touschscreen?  Turn this on and you will get useful info coming
+ *  out of your serial port.
+ */
+
+/* #define PRINT_CALIBRATION_FACTORS */
+#ifdef PRINT_CALIBRATION_FACTORS
+#define UART_HACK_DEBUG 1
+int iMaxX = 0, iMaxY = 0, iMinX = 0xfff, iMinY = 0xfff;
+#endif
+
+/*
+ * For debugging, let's spew messages out serial port 1 or 3 at 57,600 baud.
+ */
+#undef UART_HACK_DEBUG
+#if defined(UART_HACK_DEBUG) && defined (CONFIG_DEBUG_LL)
+static char szBuf[256];
+void UARTWriteString(char *msg);
+extern void printascii(const char *msg);
+#define DPRINTK( x... )   \
+    sprintf( szBuf, ##x ); \
+    printascii( szBuf );
+#else
+#define DPRINTK( x... )
+#endif
+
+#define TSSETUP_DEFAULT  ( TSSETUP_NSMP_32 | TSSETUP_DEV_64 |  \
+                           ((128<<TSSETUP_SDLY_SHIFT) & TSSETUP_SDLY_MASK) | \
+                           ((128<<TSSETUP_DLY_SHIFT)  & TSSETUP_DLY_MASK) )
+
+#define TSSETUP2_DEFAULT (TSSETUP2_NSIGND)
+
+static unsigned int guiLastX, guiLastY;
+static unsigned int guiLastInvPressure;
+static int bCurrentPenDown;
+static DECLARE_MUTEX(open_sem);
+
+enum ts_mode_t {
+	TS_MODE_UN_INITIALIZED,
+	TS_MODE_HARDWARE_SCAN,
+	TS_MODE_SOFT_SCAN
+};
+
+static enum ts_mode_t gScanningMode;
+
+enum ts_states_t {
+	TS_STATE_STOPPED = 0,
+	TS_STATE_Z1,
+	TS_STATE_Z2,
+	TS_STATE_Y,
+	TS_STATE_X,
+	TS_STATE_DONE
+};
+
+struct ts_struct_t {
+	unsigned int uiX;
+	unsigned int uiY;
+	unsigned int uiZ1;
+	unsigned int uiZ2;
+	enum ts_states_t state;
+};
+
+static struct ts_struct_t sTouch;
+
+/*
+ * From the spec, here's how to set up the touch screen's switch registers.
+ */
+struct SwitchStructType {
+	unsigned int uiDetect;
+	unsigned int uiDischarge;
+	unsigned int uiXSample;
+	unsigned int uiYSample;
+	unsigned int uiSwitchZ1;
+	unsigned int uiSwitchZ2;
+};
+
+/*
+ * Here's the switch settings for a 4-wire touchscreen.  See the spec
+ * for how to handle a 4, 7, or 8-wire.
+ */
+const static struct SwitchStructType sSwitchSettings =
+/*     s28en=0
+ *   TSDetect    TSDischarge  TSXSample  TSYSample    SwitchZ1   SwitchZ2
+ */
+{ 0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608 };
+
+static void ep93xx_ts_set_direct(unsigned int uiADCSwitch);
+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id,
+				     struct pt_regs *regs);
+static void ep93xx_hw_setup(void);
+static void ep93xx_hw_shutdown(void);
+static unsigned int CalculateInvPressure(void);
+static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff);
+static void TS_Soft_Scan_Mode(void);
+static void TS_Hardware_Scan_Mode(void);
+static void ProcessPointData(struct input_dev *dev);
+static void Set_Timer2_uSec(unsigned int Delay_mSec);
+static void Stop_Timer2(void);
+
+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	DPRINTK("isr\n");
+
+	/*
+	 * Note that we don't clear the interrupt here.  The interrupt
+	 * gets cleared in TS_Soft_Scan_Mode when the TS ENABLE
+	 * bit is cleared.
+	 *
+
+	 *
+	 * Set the ts to manual polling mode and schedule a callback.
+	 * That way we can return from the isr in a reasonable amount of
+	 * time and process the touch in the callback after a brief delay.
+	 */
+	TS_Soft_Scan_Mode();
+	return IRQ_HANDLED;
+}
+
+static int ep93xx_ts_open(struct input_dev *dev)
+{
+	int err;
+
+	if (down_trylock(&open_sem))
+		return -EBUSY;
+
+	err =
+	    request_irq(IRQ_TOUCH, ep93xx_ts_isr, SA_INTERRUPT, "ep93xx_ts",
+			dev);
+	if (err) {
+		printk(KERN_WARNING
+		       "ep93xx_ts: failed to get touchscreen IRQ\n");
+		return err;
+	}
+
+	err = request_irq(IRQ_TIMER2, ep93xx_timer2_isr,
+			  SA_INTERRUPT, "ep93xx_timer2", dev);
+	if (err) {
+		printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n");
+		free_irq(IRQ_TOUCH, dev);
+		return err;
+	}
+
+	ep93xx_hw_setup();
+
+	return 0;
+}
+
+static void ep93xx_ts_close(struct input_dev *dev)
+{
+	Stop_Timer2();
+
+	ep93xx_hw_shutdown();
+
+	free_irq(IRQ_TIMER2, dev);
+	free_irq(IRQ_TOUCH, dev);
+
+	up(&open_sem);
+}
+
+static void ep93xx_hw_setup(void)
+{
+	unsigned int uiKTDIV, uiTSXYMaxMin;
+
+	/*
+	 * Set the TSEN bit in KTDIV so that we are enabling the clock
+	 * for the touchscreen.
+	 */
+	uiKTDIV = readl(SYSCON_KTDIV);
+	uiKTDIV |= SYSCON_KTDIV_TSEN;
+	SysconSetLocked(SYSCON_KTDIV, uiKTDIV);
+
+	writel(TSSETUP_DEFAULT, TSSetup);
+	writel(TSSETUP2_DEFAULT, TSSetup2);
+
+	/* Set the the touch settings.  */
+	writel(0xaa, TSSWLock);
+	writel(sSwitchSettings.uiDischarge, TSDirect);
+
+	writel(0xaa, TSSWLock);
+	writel(sSwitchSettings.uiDischarge, TSDischarge);
+
+	writel(0xaa, TSSWLock);
+	writel(sSwitchSettings.uiSwitchZ1, TSXSample);
+
+	writel(0xaa, TSSWLock);
+	writel(sSwitchSettings.uiSwitchZ2, TSYSample);
+
+	writel(0xaa, TSSWLock);
+	writel(sSwitchSettings.uiDetect, TSDetect);
+
+	/*
+	 * X,YMin set to 0x40 = have to drag that many pixels for a new irq.
+	 * X,YMax set to 0x40 = 1024 pixels is the maximum movement within the
+	 * time scan limit.
+	 */
+	uiTSXYMaxMin = (50 << TSMAXMIN_XMIN_SHIFT) & TSMAXMIN_XMIN_MASK;
+	uiTSXYMaxMin |= (50 << TSMAXMIN_YMIN_SHIFT) & TSMAXMIN_YMIN_MASK;
+	uiTSXYMaxMin |= (0xff << TSMAXMIN_XMAX_SHIFT) & TSMAXMIN_XMAX_MASK;
+	uiTSXYMaxMin |= (0xff << TSMAXMIN_YMAX_SHIFT) & TSMAXMIN_YMAX_MASK;
+	writel(uiTSXYMaxMin, TSXYMaxMin);
+
+	bCurrentPenDown = 0;
+	guiLastX = 0;
+	guiLastY = 0;
+	guiLastInvPressure = 0xffffff;
+
+	/* Enable the touch screen scanning engine. */
+
+	TS_Hardware_Scan_Mode();
+
+}
+
+static void ep93xx_hw_shutdown(void)
+{
+	unsigned int uiKTDIV;
+
+	DPRINTK("ep93xx_hw_shutdown\n");
+
+	sTouch.state = TS_STATE_STOPPED;
+	Stop_Timer2();
+
+	/*
+	 * Disable the scanning engine.
+	 */
+	writel(0, TSSetup);
+	writel(0, TSSetup2);
+
+	/*
+	 * Clear the TSEN bit in KTDIV so that we are disabling the clock
+	 * for the touchscreen.
+	 */
+	uiKTDIV = readl(SYSCON_KTDIV);
+	uiKTDIV &= ~SYSCON_KTDIV_TSEN;
+	SysconSetLocked(SYSCON_KTDIV, uiKTDIV);
+
+}
+
+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id,
+				     struct pt_regs *regs)
+{
+	DPRINTK("%d", (int)sTouch.state);
+
+	switch (sTouch.state) {
+	case TS_STATE_STOPPED:
+		TS_Hardware_Scan_Mode();
+		break;
+
+		/*
+		 * Get the Z1 value for pressure measurement and set up
+		 * the switch register for getting the Z2 measurement.
+		 */
+	case TS_STATE_Z1:
+		Set_Timer2_uSec(EP93XX_TS_ADC_DELAY_USEC);
+		sTouch.uiZ1 = ADCGetData(2, 200);
+		ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ2);
+		sTouch.state = TS_STATE_Z2;
+		break;
+
+		/*
+		 * Get the Z2 value for pressure measurement and set up
+		 * the switch register for getting the Y measurement.
+		 */
+	case TS_STATE_Z2:
+		sTouch.uiZ2 = ADCGetData(2, 200);
+		ep93xx_ts_set_direct(sSwitchSettings.uiYSample);
+		sTouch.state = TS_STATE_Y;
+		break;
+
+		/*
+		 * Get the Y value and set up the switch register for
+		 * getting the X measurement.
+		 */
+	case TS_STATE_Y:
+		sTouch.uiY = ADCGetData(4, 20);
+		ep93xx_ts_set_direct(sSwitchSettings.uiXSample);
+		sTouch.state = TS_STATE_X;
+		break;
+
+		/*
+		 * Read the X value.  This is the last of the 4 adc values
+		 * we need so we continue on to process the data.
+		 */
+	case TS_STATE_X:
+		Stop_Timer2();
+
+		sTouch.uiX = ADCGetData(4, 20);
+
+		writel(0xaa, TSSWLock);
+		writel(sSwitchSettings.uiDischarge, TSDirect);
+
+		sTouch.state = TS_STATE_DONE;
+
+		/* Process this set of ADC readings. */
+		ProcessPointData(dev_id);
+
+		break;
+
+		/* Shouldn't get here.  But if we do, we can recover... */
+	case TS_STATE_DONE:
+		TS_Hardware_Scan_Mode();
+		break;
+	}
+
+	/* Clear the timer2 interrupt. */
+	writel(1, TIMER2CLEAR);
+	return IRQ_HANDLED;
+
+}
+
+/*---------------------------------------------------------------------
+ * ProcessPointData
+ *
+ * This routine processes the ADC data into usable point data and then
+ * puts the driver into hw or sw scanning mode before returning.
+ *
+ * We calculate inverse pressure (lower number = more pressure) then
+ * do a hystheresis with the two pressure values 'light' and 'heavy'.
+ *
+ * If we are above the light, we have pen up.
+ * If we are below the heavy we have pen down.
+ * As long as the pressure stays below the light, pen stays down.
+ * When we get above the light again, pen goes back up.
+ *
+ */
+static void ProcessPointData(struct input_dev *dev)
+{
+	int bValidPoint = 0;
+	unsigned int uiXDiff, uiYDiff, uiInvPressureDiff;
+	unsigned int uiInvPressure;
+
+	/* Calculate the current pressure. */
+	uiInvPressure = CalculateInvPressure();
+
+	DPRINTK(" X=0x%x, Y=0x%x, Z1=0x%x, Z2=0x%x, InvPressure=0x%x",
+		sTouch.uiX, sTouch.uiY, sTouch.uiZ1, sTouch.uiZ2,
+		uiInvPressure);
+
+	/*
+	 * If pen pressure is so light that it is greater than the 'max' setting
+	 * then we consider this to be a pen up.
+	 */
+	if (uiInvPressure >= TS_LIGHT_INV_PRESSURE) {
+		DPRINTK(" -- up \n");
+		bCurrentPenDown = 0;
+/*		input_report_key(dev, BTN_TOUCH, 0); */
+		input_report_abs(dev, ABS_PRESSURE, 0);
+		input_sync(dev);
+		TS_Hardware_Scan_Mode();
+		return;
+	}
+	/*
+	 * Hystheresis:
+	 * If the pen pressure is hard enough to be less than the 'min' OR
+	 * the pen is already down and is still less than the 'max'...
+	 */
+	if ((uiInvPressure < TS_HEAVY_INV_PRESSURE) ||
+	    (bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE))) {
+		if (bCurrentPenDown) {
+			/*
+			 * If pen was previously down, check the difference between
+			 * the last sample and this one... if the difference between
+			 * samples is too great, ignore the sample.
+			 */
+			uiXDiff = abs(guiLastX - sTouch.uiX);
+			uiYDiff = abs(guiLastY - sTouch.uiY);
+			uiInvPressureDiff =
+			    abs(guiLastInvPressure - uiInvPressure);
+
+			if ((uiXDiff < TS_MAX_VALID_XY_CHANGE) &&
+			    (uiYDiff < TS_MAX_VALID_XY_CHANGE) &&
+			    (uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE))
+			{
+				DPRINTK(" -- valid(two) \n");
+				bValidPoint = 1;
+			} else {
+				DPRINTK(" -- INvalid(two) \n");
+			}
+		} else {
+			DPRINTK(" -- valid \n");
+			bValidPoint = 1;
+		}
+
+		/*
+		 * If either the pen was put down or dragged make a note of it.
+		 */
+		if (bValidPoint) {
+			guiLastX = sTouch.uiX;
+			guiLastY = sTouch.uiY;
+			guiLastInvPressure = uiInvPressure;
+			bCurrentPenDown = 1;
+			input_report_abs(dev, ABS_X, sTouch.uiX);
+			input_report_abs(dev, ABS_Y, sTouch.uiY);
+/* 			input_report_key(dev, BTN_TOUCH, 1); */
+			input_report_abs(dev, ABS_PRESSURE, 1);
+			input_sync(dev);
+		}
+
+		TS_Soft_Scan_Mode();
+		return;
+	}
+
+	DPRINTK(" -- fallout \n");
+	TS_Hardware_Scan_Mode();
+}
+
+static void ep93xx_ts_set_direct(unsigned int uiADCSwitch)
+{
+	unsigned int uiResult;
+
+	/* Set the switch settings in the direct register. */
+	writel(0xaa, TSSWLock);
+	writel(uiADCSwitch, TSDirect);
+
+	/* Read and throw away the first sample. */
+	do {
+		uiResult = readl(TSXYResult);
+	} while (!(uiResult & TSXYRESULT_SDR));
+
+}
+
+static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff)
+{
+	unsigned int uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum,
+	    uiAve;
+
+	do {
+		/* Initialize our values. */
+		uiLowest = 0xfffffff;
+		uiHighest = 0;
+		uiSum = 0;
+
+		for (uiCount = 0; uiCount < uiSamples; uiCount++) {
+			/* Read the touch screen four more times and average. */
+			do {
+				uiResult = readl(TSXYResult);
+			} while (!(uiResult & TSXYRESULT_SDR));
+
+			uiValue =
+			    (uiResult & TSXYRESULT_AD_MASK) >>
+			    TSXYRESULT_AD_SHIFT;
+			uiValue =
+			    ((uiValue >> 4) +
+			     ((1 +
+			       TSXYRESULT_X_MASK) >> 1)) & TSXYRESULT_X_MASK;
+
+			/* Add up the values. */
+			uiSum += uiValue;
+
+			/* Get the lowest and highest values. */
+			if (uiValue < uiLowest)
+				uiLowest = uiValue;
+
+			if (uiValue > uiHighest)
+				uiHighest = uiValue;
+
+		}
+
+	} while ((uiHighest - uiLowest) > uiMaxDiff);
+
+	/* Calculate the Average value. */
+	uiAve = uiSum / uiSamples;
+
+	return uiAve;
+}
+
+/**
+ * CalculateInvPressure
+ *
+ * Is the Touch Valid.  Touch is not valid if the X or Y value is not
+ * in range and the pressure is not  enough.
+ *
+ * Touch resistance can be measured by the following formula:
+ *
+ *          Rx * X *     Z2
+ * Rtouch = --------- * (-- - 1)
+ *           4096        Z1
+ *
+ * This is simplified in the ration of Rtouch to Rx.  The lower the value, the
+ * higher the pressure.
+ *
+ *                     Z2
+ * InvPressure =  X * (-- - 1)
+ *                     Z1
+ */
+static unsigned int CalculateInvPressure(void)
+{
+	unsigned int uiInvPressure;
+
+	/* Check to see if the point is valid. */
+	if (sTouch.uiZ1 < MIN_Z1_VALUE)
+		uiInvPressure = 0x10000;
+
+	/* Can omit the pressure calculation if you need to get rid of the division. */
+	else {
+		uiInvPressure =
+		    ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX;
+	}
+
+	return uiInvPressure;
+}
+
+/**
+ * TS_Hardware_Scan_Mode
+ * Enables the ep93xx ts scanning engine so that when the pen goes down
+ * we will get an interrupt.
+ */
+static void TS_Hardware_Scan_Mode(void)
+{
+	unsigned int uiDevCfg;
+
+	DPRINTK("S\n");
+
+	/* Disable the soft scanning engine. */
+	sTouch.state = TS_STATE_STOPPED;
+	Stop_Timer2();
+
+	/*
+	 * Clear the TIN (Touchscreen INactive) bit so we can go to
+	 * automatic scanning mode.
+	 */
+	uiDevCfg = readl(SYSCON_DEVCFG);
+	SysconSetLocked(SYSCON_DEVCFG,
+			ep93xx_SYSCON_DEVCFG(uiDevCfg & ~SYSCON_DEVCFG_TIN));
+
+	/*
+	 * Enable the touch screen scanning state machine by setting
+	 * the ENABLE bit.
+	 */
+	writel((TSSETUP_DEFAULT | TSSETUP_ENABLE), TSSetup);
+
+	/* Set the flag to show that we are in interrupt mode. */
+	gScanningMode = TS_MODE_HARDWARE_SCAN;
+
+	/* Initialize TSSetup2 register. */
+	writel(TSSETUP2_DEFAULT, TSSetup2);
+
+}
+
+/**
+ * TS_Soft_Scan_Mode - Set the touch screen to manual polling mode.
+ */
+static void TS_Soft_Scan_Mode(void)
+{
+	unsigned int uiDevCfg;
+
+	DPRINTK("M\n");
+
+	if (gScanningMode != TS_MODE_SOFT_SCAN) {
+		/*
+		 * Disable the touch screen scanning state machine by clearing
+		 * the ENABLE bit.
+		 */
+		writel(TSSETUP_DEFAULT, TSSetup);
+
+		/* Set the TIN bit so we can do manual touchscreen polling. */
+		uiDevCfg = readl(SYSCON_DEVCFG);
+		SysconSetLocked(SYSCON_DEVCFG,
+				ep93xx_SYSCON_DEVCFG(uiDevCfg |
+						     SYSCON_DEVCFG_TIN));
+	}
+	/* Set the switch register up for the first ADC reading */
+	ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ1);
+
+	/*
+	 * Initialize our software state machine to know which ADC
+	 * reading to take
+	 */
+	sTouch.state = TS_STATE_Z1;
+
+	/*
+	 * Set the timer so after a mSec or two settling delay it will
+	 * take the first ADC reading.
+	 */
+	Set_Timer2_uSec(EP93XX_TS_PER_POINT_DELAY_USEC);
+
+	/* Note that we are in sw scanning mode not hw scanning mode. */
+	gScanningMode = TS_MODE_SOFT_SCAN;
+
+}
+
+static void Set_Timer2_uSec(unsigned int uiDelay_uSec)
+{
+	unsigned int uiClockTicks;
+
+	/*
+	 * Stop timer 2
+	 */
+	writel(0, TIMER2CONTROL);
+
+	uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000;
+	writel(uiClockTicks, TIMER2LOAD);
+	writel(uiClockTicks, TIMER2VALUE);
+
+	/*
+	 * Set up Timer 2 for 508 kHz clock and periodic mode.
+	 */
+	writel(0xC8, TIMER2CONTROL);
+
+}
+
+static void Stop_Timer2(void)
+{
+	writel(0, TIMER2CONTROL);
+}
+
+static struct input_dev *ep93xx_ts_dev;
+
+static int __init ep93xx_ts_init(void)
+{
+	ep93xx_ts_dev = input_allocate_device();
+	if (!ep93xx_ts_dev) {
+		printk(KERN_ERR "ep93xx_ts_dev: not enough memory for input device\n");
+		return -ENOMEM;
+	}
+			
+	ep93xx_ts_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	ep93xx_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	ep93xx_ts_dev->keybit[LONG(BTN_RAW)] = BIT(BTN_RAW);
+
+	/* untested, I haven't got a touchscreen (yet) :( */
+        input_set_abs_params(ep93xx_ts_dev, ABS_X, 0, 4095, 0, 0);
+        input_set_abs_params(ep93xx_ts_dev, ABS_Y, 0, 4095, 0, 0);
+        input_set_abs_params(ep93xx_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
+	
+	ep93xx_ts_dev->open = ep93xx_ts_open;
+	ep93xx_ts_dev->close = ep93xx_ts_close;
+	ep93xx_ts_dev->name = "Cirrus Logic EP93xx Touchscreen";
+	ep93xx_ts_dev->phys = "ep93xx_ts/input0";
+	ep93xx_ts_dev->id.bustype = BUS_HOST;
+	ep93xx_ts_dev->id.vendor = PCI_VENDOR_ID_CIRRUS;
+	ep93xx_ts_dev->id.product = 0x9300;
+
+	input_set_abs_params(ep93xx_ts_dev, ABS_X, TS_X_MIN, TS_X_MAX, 0, 0);
+	input_set_abs_params(ep93xx_ts_dev, ABS_Y, TS_Y_MIN, TS_Y_MAX, 0, 0);
+	input_register_device(ep93xx_ts_dev);
+
+	sTouch.state = TS_STATE_STOPPED;
+	gScanningMode = TS_MODE_UN_INITIALIZED;
+
+	printk(KERN_NOTICE
+	       "EP93xx touchscreen driver configured for 4-wire operation\n");
+	return 0;
+}
+
+static void __exit ep93xx_ts_exit(void)
+{
+	input_unregister_device(ep93xx_ts_dev);
+}
+
+module_init(ep93xx_ts_init);
+module_exit(ep93xx_ts_exit);
+
+MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver");
+MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx");
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b9b77cf..4e0e427 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -137,6 +137,13 @@ config MTD_MAINSTONE
 	  This provides a driver for the on-board flash of the Intel
 	  'Mainstone PXA27x evaluation board.
 
+config MTD_ADSFLASH
+	tristate "CFI Flash device mapped on ADS"
+	depends on ARM && MTD_CFI && MACH_ADSSPHERE && MTD_PARTITIONS
+	help
+	  This enables access to on-board flash memory on ADS platforms that
+	  have an Intel XScale PXA2xx CPU.
+
 config MTD_OCTAGON
 	tristate "JEDEC Flash device mapped on Octagon 5066 SBC"
 	depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
@@ -639,5 +646,19 @@ config MTD_PLATRAM
 
 	  This selection automatically selects the map_ram driver.
 
+config MTD_ZEFEERDZB
+	tristate "Map driver for DAVE Srl ZefeerDZB processor module"
+	depends on (MTD_CFI && MACH_ZEFEERDZB)
+	select MTD_PARTITIONS
+	help
+	  Map driver for DAVE Srl ZefeerDZB processor module.
+
+config MTD_ZEFEERDZQ
+	tristate "Map driver for DAVE Srl ZefeerDZQ processor module"
+	depends on (MTD_CFI && MACH_ZEFEERDZQ)
+	select MTD_PARTITIONS
+	help
+	  Map driver for DAVE Srl ZefeerDZQ processor module.
+
 endmenu
 
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 2f7e254..a821568 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_MTD_AMD76XROM)	+= amd76xrom
 obj-$(CONFIG_MTD_ICHXROM)	+= ichxrom.o
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_LUBBOCK)	+= lubbock-flash.o
+obj-$(CONFIG_MTD_ADSFLASH)	+= ads-flash.o
 obj-$(CONFIG_MTD_MAINSTONE)	+= mainstone-flash.o
 obj-$(CONFIG_MTD_MBX860)	+= mbx860.o
 obj-$(CONFIG_MTD_CEIVA)		+= ceiva.o
@@ -72,3 +73,5 @@ obj-$(CONFIG_MTD_PLATRAM)	+= plat-ram.o
 obj-$(CONFIG_MTD_OMAP_NOR)	+= omap_nor.o
 obj-$(CONFIG_MTD_MTX1)		+= mtx-1_flash.o
 obj-$(CONFIG_MTD_TQM834x)	+= tqm834x.o
+obj-$(CONFIG_MTD_ZEFEERDZB)	+= zefeerdzb.o
+obj-$(CONFIG_MTD_ZEFEERDZQ)	+= zefeerdzq.o
diff --git a/drivers/mtd/maps/ads-flash.c b/drivers/mtd/maps/ads-flash.c
new file mode 100644
index 0000000..2428e9c
--- /dev/null
+++ b/drivers/mtd/maps/ads-flash.c
@@ -0,0 +1,221 @@
+/*
+ * Map driver for the ADS PXA Boards.
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#ifdef CONFIG_MACH_ADSVIX
+#define NUM_CHIPS 	1
+#else
+#define NUM_CHIPS 	2
+#endif
+
+#ifdef CONFIG_PXA27x
+#define WINDOW_ADDR 	0
+#elif defined(CONFIG_ARCH_EP93XX)
+#define WINDOW_ADDR     0x60000000
+#else
+#define WINDOW_ADDR 	0x04000000
+#endif
+
+#define WINDOW_SIZE 	(NUM_CHIPS * 32*1024*1024)
+#define BLOCKSIZE 	(NUM_CHIPS * 0x20000)
+#define BANKWIDTH 	(NUM_CHIPS * 2)
+
+static void pxa_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
+{
+	consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
+}
+
+static struct map_info pxa_map = {
+	.name		= "pxa",
+	.size		= WINDOW_SIZE,
+	.phys		= WINDOW_ADDR,
+	.virt		= 0,
+	.cached		= (void *)NULL,
+	.bankwidth	= BANKWIDTH,
+	.inval_cache	= pxa_map_inval_cache,
+};
+
+static struct mtd_partition ads_partitions[] = {
+	{
+		name:		"boot",
+		size:		BLOCKSIZE,
+		offset:		0,
+	}, {
+		name:		"bootvars",
+		size:		BLOCKSIZE,
+		offset:		MTDPART_OFS_APPEND,
+	}, {
+		name:		"zImage",
+		size:		0x00180000,
+		offset:		MTDPART_OFS_APPEND,
+	}, {
+		name:		"ramdisk.gz",
+		size:		0x00500000,
+		offset:		MTDPART_OFS_APPEND,
+	}, {
+		name:		"flashfs1",
+		size:		MTDPART_SIZ_FULL,
+		offset:		MTDPART_OFS_APPEND
+	}
+};
+
+unsigned char ads_flash_serial_id[32+2] = {0};
+
+static struct mtd_info *mymtd = NULL;
+static struct mtd_partition *parsed_parts = NULL;
+static int num_parts = 0;
+static const char *probes[] = {
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+  "cmdlinepart",
+#endif
+#ifdef CONFIG_MTD_REDBOOT_PARTS
+  "RedBoot",
+#endif
+  NULL };
+
+// This implementation supports 1 or 2 chips.
+static void ads_get_flash_serial_id(int chips)
+{
+	map_word val;
+	unsigned int addr = 0x81 << chips;
+	unsigned int mask = chips == 1 ? 0xffff : 0xffffffff;
+	unsigned int tmp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+	int i;
+
+	/* read array mode */
+	// *(__u32 *)pxa_map.virt = 0x00FF00FF;
+	// *(__u16 *)pxa_map.virt = 0x00ff;
+	val.x[0] = 0x00ff00ff & mask;
+	map_write(&pxa_map, val, 0);
+
+	/* read id mode */
+	// *(__u32 *)pxa_map.virt = 0x00900090;
+	// *(__u16 *)pxa_map.virt = 0x0090;
+	val.x[0] = 0x00900090 & mask;
+	map_write(&pxa_map, val, 0);
+
+	for (i=0; i<8; i++) {
+		// tmp[i] = 0x0000ffff & *(__u32 *)(pxa_map.virt + addr);
+		// tmp[i] = *(__u16 *)(pxa_map.virt + addr);
+		val = map_read(&pxa_map, addr);
+		tmp[i] = val.x[0] & 0xffff;
+		addr += BANKWIDTH;
+	}
+
+	/* back to read array mode */
+	// *(__u32 *)pxa_map.virt = 0x00FF00FF;
+	// *(__u16 *)pxa_map.virt = 0x00ff;
+	val.x[0] = 0x00ff00ff & mask;
+	map_write(&pxa_map, val, 0);
+
+	sprintf(ads_flash_serial_id, "%04x%04x%04x%04x.%04x%04x%04x%04x",
+		tmp[7], tmp[6], tmp[5], tmp[4], tmp[3], tmp[2], tmp[1], tmp[0]);
+
+}
+
+static int __init init_pxa_flash(void)
+{
+	struct mtd_partition *parts;
+	char *part_type;
+	int rtn;
+
+	printk(KERN_NOTICE "Probing PXA flash at physical address 0x%08x\n", WINDOW_ADDR);
+	pxa_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
+	if (!pxa_map.virt) {
+		printk(KERN_ERR "Failed to ioremap flash\n");
+		return -EIO;
+	}
+
+	pxa_map.cached = __ioremap(WINDOW_ADDR, WINDOW_SIZE, L_PTE_CACHEABLE, 1);
+	if (!pxa_map.cached)
+		printk(KERN_WARNING "Failed to ioremap cached flash\n");
+
+	simple_map_init(&pxa_map);
+
+	mymtd = do_map_probe("cfi_probe", &pxa_map);
+	if (!mymtd) {
+		if (pxa_map.cached)
+			iounmap((void *)pxa_map.cached);
+		if (pxa_map.virt)
+			iounmap((void *)pxa_map.virt);
+		return -ENXIO;
+	}
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+	pxa_map.name = "pxa";
+	rtn = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
+	if (rtn <= 0) {
+		pxa_map.name = "sa1100";
+		rtn = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
+	}
+	if (rtn > 0) {
+		num_parts = rtn;
+		parts     = parsed_parts;
+		part_type = "command line";
+		goto add_parts;
+	}
+#endif
+	num_parts = ARRAY_SIZE(ads_partitions);
+	parts     = ads_partitions;
+	part_type = "static";
+add_parts:
+	if (num_parts) {
+		printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+		add_mtd_partitions(mymtd, parts, num_parts);
+#if 0
+		if (mymtd->unlock) {
+			int i;
+			for (i = 0; i < num_parts; i++) {
+				// unlock partition
+				mymtd->unlock(mymtd, parts[num_parts - 1].offset,
+						     parts[num_parts - 1].size);
+			}
+		}
+#endif
+	}
+	else {
+		add_mtd_device(mymtd);
+	}
+
+	ads_get_flash_serial_id(NUM_CHIPS);
+
+	return 0;
+}
+
+static void __exit cleanup_pxa_flash(void)
+{
+	if (mymtd) {
+		if (num_parts)
+			del_mtd_partitions(mymtd);
+		else
+			del_mtd_device(mymtd);
+		map_destroy(mymtd);
+		if (parsed_parts)
+			kfree(parsed_parts);
+	}
+	if (pxa_map.cached)
+		iounmap((void *)pxa_map.cached);
+	if (pxa_map.virt)
+		iounmap((void *)pxa_map.virt);
+}
+
+module_init(init_pxa_flash);
+module_exit(cleanup_pxa_flash);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/zefeerdzb.c b/drivers/mtd/maps/zefeerdzb.c
new file mode 100644
index 0000000..bb47bc6
--- /dev/null
+++ b/drivers/mtd/maps/zefeerdzb.c
@@ -0,0 +1,134 @@
+/*
+ * $Id: zefeerdzb.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $
+ *
+ * drivers/mtd/maps/zefeerdzb.c
+ *
+ * FLASH map for the DAVE Srl ZefeerDZB processor module.
+ *
+ *
+ * 2004 (c) DAVE Srl. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/io.h>
+
+#if 0
+/* Support for ZELK <= 0.9.5 */
+#define WINDOW_ADDR 0x60000000
+#else
+#define WINDOW_ADDR 0x00000000
+#endif
+#define WINDOW_SIZE 0x00400000
+
+/* 128 kB U-Boot */
+#define ZEFEERDZB_PART0_OF	0
+#define ZEFEERDZB_PART0_SZ	0x20000
+/* 128  kB U-Boot env #1 */
+#define ZEFEERDZB_PART1_OF	ZEFEERDZB_PART0_OF + ZEFEERDZB_PART0_SZ
+#define ZEFEERDZB_PART1_SZ	0x20000
+/* 128  kB U-Boot env #2 */
+#define ZEFEERDZB_PART2_OF	ZEFEERDZB_PART1_OF + ZEFEERDZB_PART1_SZ
+#define ZEFEERDZB_PART2_SZ	0x20000
+/* Linux kernel */
+#define ZEFEERDZB_PART3_OF	ZEFEERDZB_PART2_OF + ZEFEERDZB_PART2_SZ
+#define ZEFEERDZB_PART3_SZ	(0x200000 - ZEFEERDZB_PART2_SZ - ZEFEERDZB_PART1_SZ - ZEFEERDZB_PART0_SZ)
+/* spare */
+#define ZEFEERDZB_PART4_OF	ZEFEERDZB_PART3_OF + ZEFEERDZB_PART3_SZ
+#define ZEFEERDZB_PART4_SZ	(0x400000 - ZEFEERDZB_PART3_SZ - ZEFEERDZB_PART2_SZ - ZEFEERDZB_PART1_SZ - ZEFEERDZB_PART0_SZ)
+
+static struct mtd_partition zefeerdzb_flash_partitions[] = {
+	{
+	 .name = "U-Boot",
+	 .offset = ZEFEERDZB_PART0_OF,
+	 .size = ZEFEERDZB_PART0_SZ,
+	 .mask_flags = MTD_WRITEABLE	/* force read-only */
+	 },
+	{
+	 .name = "U-Boot environment #1",
+	 .offset = ZEFEERDZB_PART1_OF,
+	 .size = ZEFEERDZB_PART1_SZ,
+	 },
+	{
+	 .name = "U-Boot environment #2",
+	 .offset = ZEFEERDZB_PART2_OF,
+	 .size = ZEFEERDZB_PART2_SZ,
+	 },
+	{
+	 .name = "Linux kernel",
+	 .offset = ZEFEERDZB_PART3_OF,
+	 .size = ZEFEERDZB_PART3_SZ,
+	 },
+	{
+	 .name = "spare 1",
+	 .offset = ZEFEERDZB_PART4_OF,
+	 .size = ZEFEERDZB_PART4_SZ,
+	 }
+};
+
+struct map_info zefeerdzb_flash_map = {
+	.name = "DAVE Srl ZefeerDZB",
+	.size = WINDOW_SIZE,
+	.bankwidth = 2,
+	.phys = WINDOW_ADDR,
+};
+
+#define NUM_ZEFEERDZB_FLASH_PARTITIONS \
+	(sizeof(zefeerdzb_flash_partitions)/sizeof(zefeerdzb_flash_partitions[0]))
+
+static struct mtd_info *zefeerdzb_mtd;
+
+int __init init_zefeerdzb_flash(void)
+{
+	printk(KERN_NOTICE "zefeerdzb: flash mapping: %x at %x\n",
+	       WINDOW_SIZE, WINDOW_ADDR);
+
+	zefeerdzb_flash_map.virt =
+	    (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
+
+	if (!zefeerdzb_flash_map.virt) {
+		printk("init_zefeerdzb_flash: failed to ioremap\n");
+		return -EIO;
+	}
+	simple_map_init(&zefeerdzb_flash_map);
+
+	zefeerdzb_mtd = do_map_probe("cfi_probe", &zefeerdzb_flash_map);
+
+	if (zefeerdzb_mtd) {
+		zefeerdzb_mtd->owner = THIS_MODULE;
+		return add_mtd_partitions(zefeerdzb_mtd,
+					  zefeerdzb_flash_partitions,
+					  NUM_ZEFEERDZB_FLASH_PARTITIONS);
+	}
+
+	return -ENXIO;
+}
+
+static void __exit cleanup_zefeerdzb_flash(void)
+{
+	if (zefeerdzb_mtd) {
+		del_mtd_partitions(zefeerdzb_mtd);
+		/* moved iounmap after map_destroy - armin */
+		map_destroy(zefeerdzb_mtd);
+		iounmap((void *)zefeerdzb_flash_map.virt);
+	}
+}
+
+module_init(init_zefeerdzb_flash);
+module_exit(cleanup_zefeerdzb_flash);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("DAVE Srl <info@dave-tech.it>");
+MODULE_DESCRIPTION
+    ("MTD map driver for the DAVE Srl ZefeerDZB processor module");
diff --git a/drivers/mtd/maps/zefeerdzq.c b/drivers/mtd/maps/zefeerdzq.c
new file mode 100644
index 0000000..dc0e402
--- /dev/null
+++ b/drivers/mtd/maps/zefeerdzq.c
@@ -0,0 +1,142 @@
+/*
+ * $Id: zefeerdzq.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $
+ *
+ * drivers/mtd/maps/zefeerdzq.c
+ *
+ * FLASH map for the DAVE Srl ZefeerDZQ processor module.
+ *
+ *
+ * 2004 (c) DAVE Srl. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/io.h>
+
+#if 0
+/* Support for ZELK <= 0.9.5 */
+#define WINDOW_ADDR 0x60000000
+#else
+#define WINDOW_ADDR 0x00000000
+#endif
+#define WINDOW_SIZE 0x01000000
+
+/* 128 kB U-Boot */
+#define ZEFEERDZQ_PART0_OF	0
+#define ZEFEERDZQ_PART0_SZ	0x20000
+/* 128  kB U-Boot env #1 */
+#define ZEFEERDZQ_PART1_OF	ZEFEERDZQ_PART0_OF + ZEFEERDZQ_PART0_SZ
+#define ZEFEERDZQ_PART1_SZ	0x20000
+/* 128  kB U-Boot env #2 */
+#define ZEFEERDZQ_PART2_OF	ZEFEERDZQ_PART1_OF + ZEFEERDZQ_PART1_SZ
+#define ZEFEERDZQ_PART2_SZ	0x20000
+/* Linux kernel */
+#define ZEFEERDZQ_PART3_OF	ZEFEERDZQ_PART2_OF + ZEFEERDZQ_PART2_SZ
+#define ZEFEERDZQ_PART3_SZ	(0x200000 - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
+/* ramdisk */
+#define ZEFEERDZQ_PART4_OF	ZEFEERDZQ_PART3_OF + ZEFEERDZQ_PART3_SZ
+#define ZEFEERDZQ_PART4_SZ	(0x400000 - ZEFEERDZQ_PART3_SZ - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
+/* spare */
+#define ZEFEERDZQ_PART5_OF	ZEFEERDZQ_PART4_OF + ZEFEERDZQ_PART4_SZ
+#define ZEFEERDZQ_PART5_SZ	(WINDOW_SIZE - ZEFEERDZQ_PART4_SZ - ZEFEERDZQ_PART3_SZ - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
+
+static struct mtd_partition zefeerdzq_flash_partitions[] = {
+	{
+	 .name = "U-Boot",
+	 .offset = ZEFEERDZQ_PART0_OF,
+	 .size = ZEFEERDZQ_PART0_SZ,
+	 .mask_flags = MTD_WRITEABLE	/* force read-only */
+	 },
+	{
+	 .name = "U-Boot environment #1",
+	 .offset = ZEFEERDZQ_PART1_OF,
+	 .size = ZEFEERDZQ_PART1_SZ,
+	 },
+	{
+	 .name = "U-Boot environment #2",
+	 .offset = ZEFEERDZQ_PART2_OF,
+	 .size = ZEFEERDZQ_PART2_SZ,
+	 },
+	{
+	 .name = "Linux kernel",
+	 .offset = ZEFEERDZQ_PART3_OF,
+	 .size = ZEFEERDZQ_PART3_SZ,
+	 },
+	{
+	 .name = "spare 1",
+	 .offset = ZEFEERDZQ_PART4_OF,
+	 .size = ZEFEERDZQ_PART4_SZ,
+	 },
+	{
+	 .name = "spare 2",
+	 .offset = ZEFEERDZQ_PART5_OF,
+	 .size = ZEFEERDZQ_PART5_SZ,
+	 }
+};
+
+struct map_info zefeerdzq_flash_map = {
+	.name = "DAVE Srl ZefeerDZQ",
+	.size = WINDOW_SIZE,
+	.bankwidth = 2,
+	.phys = WINDOW_ADDR,
+};
+
+#define NUM_ZEFEERDZQ_FLASH_PARTITIONS \
+	(sizeof(zefeerdzq_flash_partitions)/sizeof(zefeerdzq_flash_partitions[0]))
+
+static struct mtd_info *zefeerdzq_mtd;
+
+int __init init_zefeerdzq_flash(void)
+{
+	printk(KERN_NOTICE "zefeerdzq: flash mapping: %x at %x\n",
+	       WINDOW_SIZE, WINDOW_ADDR);
+
+	zefeerdzq_flash_map.virt =
+	    (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
+
+	if (!zefeerdzq_flash_map.virt) {
+		printk("init_zefeerdzq_flash: failed to ioremap\n");
+		return -EIO;
+	}
+	simple_map_init(&zefeerdzq_flash_map);
+
+	zefeerdzq_mtd = do_map_probe("cfi_probe", &zefeerdzq_flash_map);
+
+	if (zefeerdzq_mtd) {
+		zefeerdzq_mtd->owner = THIS_MODULE;
+		return add_mtd_partitions(zefeerdzq_mtd,
+					  zefeerdzq_flash_partitions,
+					  NUM_ZEFEERDZQ_FLASH_PARTITIONS);
+	}
+
+	return -ENXIO;
+}
+
+static void __exit cleanup_zefeerdzq_flash(void)
+{
+	if (zefeerdzq_mtd) {
+		del_mtd_partitions(zefeerdzq_mtd);
+		/* moved iounmap after map_destroy - armin */
+		map_destroy(zefeerdzq_mtd);
+		iounmap((void *)zefeerdzq_flash_map.virt);
+	}
+}
+
+module_init(init_zefeerdzq_flash);
+module_exit(cleanup_zefeerdzq_flash);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("DAVE Srl <info@dave-tech.it>");
+MODULE_DESCRIPTION
+    ("MTD map driver for the DAVE Srl ZefeerDZQ processor module");
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1fc4c13..8e79d32 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -109,6 +109,12 @@ config MTD_NAND_S3C2410_HWECC
 	  currently not be able to switch to software, as there is no
 	  implementation for ECC method used by the S3C2410
 
+config MTD_NAND_ZEFEEREVB
+	tristate "NAND Flash device on ZefeerEVB (L/H) board"
+	depends on (MACH_ZEFEERDZA || MACH_ZEFEERDZB || MACH_ZEFEERDZG || MACH_ZEFEERDZN ||  MACH_ZEFEERDZQ) && MTD_NAND
+	help
+	  This enables the NAND flash driver on the ZefeerEVB Board (L or H version).
+
 config MTD_NAND_DISKONCHIP
 	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
 	depends on MTD_NAND && EXPERIMENTAL
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 4174202..bee7760 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -18,5 +18,6 @@ obj-$(CONFIG_MTD_NAND_H1900)		+= h1910.o
 obj-$(CONFIG_MTD_NAND_RTC_FROM4)	+= rtc_from4.o
 obj-$(CONFIG_MTD_NAND_SHARPSL)		+= sharpsl.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)		+= nandsim.o
+obj-$(CONFIG_MTD_NAND_ZEFEEREVB)	+= zefeerevb.o
 
 nand-objs = nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/zefeerevb.c b/drivers/mtd/nand/zefeerevb.c
new file mode 100644
index 0000000..b67e958
--- /dev/null
+++ b/drivers/mtd/nand/zefeerevb.c
@@ -0,0 +1,280 @@
+/*
+ *  drivers/mtd/nand/zefeerevb.c
+ *
+ *  Copyright (C) 2004 DAVE Srl (info@dave-tech.it)
+ *
+ *
+ *
+ * $Id: zefeerevb.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $
+ *
+ * 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.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash devices found on the
+ *   ZefeerEVB board (Samsung K9F5608U0B 32MB).
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/arch/regmap.h>
+#include <asm/arch/zefeerevb.h>
+#include <asm/io.h>
+
+#define USE_READY_BUSY_PIN
+/* see datasheets (tR) */
+#define NAND_BIG_DELAY_US		25
+#define NAND_SMALL_DELAY_US		10
+
+/* handy sizes */
+#define SZ_4M                           0x00400000
+#define NAND_SMALL_SIZE                 0x02000000
+#define NAND_EVB_MTD_NAME	"zefeerevb-nand"
+
+/* Macros to perform I/O operations */
+#define MACRO_NAND_DISABLE_CE(nandptr) do \
+{ \
+	writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_nCE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
+} while(0)
+
+#define MACRO_NAND_ENABLE_CE(nandptr) do \
+{ \
+	writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_nCE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
+} while(0)
+
+#define MACRO_NAND_CTL_CLRALE(nandptr) do \
+{ \
+	writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_ALE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
+} while(0)
+
+#define MACRO_NAND_CTL_SETALE(nandptr) do \
+{ \
+	writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_ALE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
+} while(0)
+
+#define MACRO_NAND_CTL_CLRCLE(nandptr) do \
+{ \
+	writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_CLE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
+} while(0)
+
+#define MACRO_NAND_CTL_SETCLE(nandptr) do \
+{ \
+	writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_CLE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
+} while(0)
+
+#define MACRO_NAND_WAIT_READY(nand) \
+while ( !(readl((volatile unsigned*)GPIO_PADR) & NAND_EVB_RB_GPIO_PIN); )
+
+/*
+ * MTD structure for ZefeerEVB board
+ */
+static struct mtd_info *zefeerevb_mtd = NULL;
+
+/*
+ * Module stuff
+ */
+static int zefeerevb_fio_pbase = ZEFEEREVB_NAND_PADDR;
+
+#ifdef MODULE
+MODULE_PARM(zefeerevb_fio_pbase, "i");
+__setup("zefeerevb_fio_pbase=", zefeerevb_fio_pbase);
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
+/*
+ * Define static partitions for flash devices
+ */
+static struct mtd_partition partition_info_evb[] = {
+      {name:"ZefeerEVB Nand Flash",
+	      offset:0,
+      size:32 * 1024 * 1024}
+};
+
+#define NUM_PARTITIONS 1
+
+extern int parse_cmdline_partitions(struct mtd_info *master,
+				    struct mtd_partition **pparts,
+				    const char *mtd_id);
+#endif
+
+static void zefeerevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+{
+	switch (cmd) {
+
+	case NAND_CTL_SETCLE:
+		MACRO_NAND_CTL_SETCLE((unsigned long)0);
+		break;
+	case NAND_CTL_CLRCLE:
+		MACRO_NAND_CTL_CLRCLE((unsigned long)0);
+		break;
+	case NAND_CTL_SETALE:
+		MACRO_NAND_CTL_SETALE((unsigned long)0);
+		break;
+	case NAND_CTL_CLRALE:
+		MACRO_NAND_CTL_CLRALE((unsigned long)0);
+		break;
+	case NAND_CTL_SETNCE:
+		MACRO_NAND_ENABLE_CE((unsigned long)0);
+		break;
+	case NAND_CTL_CLRNCE:
+		MACRO_NAND_DISABLE_CE((unsigned long)0);
+		break;
+	}
+}
+
+#ifdef USE_READY_BUSY_PIN
+/*
+ *	read device ready pin
+ */
+static int zefeerevb_device_ready(struct mtd_info *minfo)
+{
+	return (readl((volatile unsigned *)GPIO_PADR) &
+		NAND_EVB_RB_GPIO_PIN);
+}
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes_evb[] = { "cmdlinepart", NULL };
+#endif
+
+/*
+ * Main initialization routine
+ */
+static int __init zefeerevb_init(void)
+{
+	struct nand_chip *this;
+	const char *part_type = 0;
+	int mtd_parts_nb = 0;
+	struct mtd_partition *mtd_parts = 0;
+	void __iomem *zefeerevb_fio_base;
+	u32 tmp;
+
+	/* Init I/O pins */
+	MACRO_NAND_DISABLE_CE(0);
+	MACRO_NAND_CTL_CLRALE(0);
+	MACRO_NAND_CTL_CLRCLE(0);
+
+	tmp = (u32) readl(GPIO_PADDR);
+	tmp |=
+	    (NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN |
+	     NAND_EVB_ALE_GPIO_PIN);
+#ifdef USE_READY_BUSY_PIN
+	tmp &= ~NAND_EVB_RB_GPIO_PIN;
+#endif
+	writel(tmp, GPIO_PADDR);
+
+	/* Init I/O pins */
+	MACRO_NAND_DISABLE_CE(0);
+	MACRO_NAND_CTL_CLRALE(0);
+	MACRO_NAND_CTL_CLRCLE(0);
+
+	/* Set up chip select */
+	writel((0 << 30) | (0 << 28) | (0 << 27) | (0 << 26) | (0 << 11) |
+	       (1 << 10) | (4 << 5) | (6 << 0), SMCBCR2);
+
+	/* Allocate memory for MTD device structure and private data */
+	zefeerevb_mtd = kmalloc(sizeof(struct mtd_info) +
+				sizeof(struct nand_chip), GFP_KERNEL);
+	if (!zefeerevb_mtd) {
+		printk
+		    ("Unable to allocate ZefeerEVB NAND MTD device structure.\n");
+		return -ENOMEM;
+	}
+
+	/* map physical address */
+	zefeerevb_fio_base =
+	    (void __iomem *)ioremap(zefeerevb_fio_pbase, SZ_4M);
+	if (!zefeerevb_fio_base) {
+		printk("ioremap ZefeerEVB NAND flash failed\n");
+		kfree(zefeerevb_mtd);
+		return -EIO;
+	}
+
+	/* Get pointer to private data */
+	this = (struct nand_chip *)(&zefeerevb_mtd[1]);
+
+	/* Initialize structures */
+	memset((char *)zefeerevb_mtd, 0, sizeof(struct mtd_info));
+	memset((char *)this, 0, sizeof(struct nand_chip));
+
+	/* Link the private data with the MTD structure */
+	zefeerevb_mtd->priv = this;
+
+	/* insert callbacks */
+	this->IO_ADDR_R = (void __iomem *)zefeerevb_fio_base;
+	this->IO_ADDR_W = (void __iomem *)zefeerevb_fio_base;
+	this->hwcontrol = zefeerevb_hwcontrol;
+#ifdef USE_READY_BUSY_PIN
+	this->dev_ready = zefeerevb_device_ready;
+#endif
+	this->chip_delay = NAND_SMALL_DELAY_US;
+
+	/* ECC mode */
+	this->eccmode = NAND_ECC_SOFT;
+
+	/* Scan to find existence of the device */
+	if (nand_scan(zefeerevb_mtd, 1)) {
+		iounmap((void *)zefeerevb_fio_base);
+		kfree(zefeerevb_mtd);
+		return -ENXIO;
+	}
+#ifdef CONFIG_MTD_PARTITIONS
+	zefeerevb_mtd->name = NAND_EVB_MTD_NAME;
+	mtd_parts_nb =
+	    parse_mtd_partitions(zefeerevb_mtd, part_probes_evb, &mtd_parts, 0);
+	if (mtd_parts_nb > 0)
+		part_type = "command line";
+	else
+		mtd_parts_nb = 0;
+#endif
+	if (mtd_parts_nb == 0) {
+#ifdef CONFIG_MTD_PARTITIONS
+		mtd_parts = partition_info_evb;
+		mtd_parts_nb = NUM_PARTITIONS;
+#endif
+		part_type = "static";
+	}
+
+	/* Register the partitions */
+	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+	add_mtd_partitions(zefeerevb_mtd, mtd_parts, mtd_parts_nb);
+
+	/* Return happy */
+	return 0;
+}
+
+module_init(zefeerevb_init);
+
+#ifdef MODULE
+/*
+ * Clean up routine
+ */
+static void __exit zefeerevb_cleanup(void)
+{
+	struct nand_chip *this;
+
+	/* Release resources, unregister device(s) */
+	nand_release(zefeer_mtd);
+	nand_release(zefeerevb_mtd);
+
+	/* Release iomaps */
+	this = (struct nand_chip *)&zefeer_mtd[1];
+	iounmap((void *)this->zefeer_fio_base;
+		this = (struct nand_chip *)&zefeerevb_mtd[1];
+		iounmap((void *)this->zefeerevb_fio_base;
+			/* Free the MTD device structure */
+			kfree(zefeer_mtd);
+			kfree(zefeerevb_mtd);
+			}
+
+			module_exit(zefeerevb_cleanup);
+#endif
+			MODULE_LICENSE("GPL");
+			MODULE_AUTHOR("DAVE Srl <support-zefeer@dave-tech.it>");
+			MODULE_DESCRIPTION
+			("MTD map driver for DAVE Srl ZefeerEVB (L/H) board");
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 470364d..12afe1d 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -44,3 +44,13 @@ config ARM_ETHER00
 	  will generate a suitable hw address based on the board serial
 	  number (MTD support is required for this). Otherwise you will
 	  need to set a suitable hw address using ifconfig.
+
+config EP93XX_ETHERNET
+	tristate "EP93xx Ethernet support"
+	depends on NET_ETHERNET && ARM && ARCH_EP93XX
+	select CRC32
+	select MII
+	help
+	  This is a driver for the ethernet hardware included in EP93xx CPUs.
+	  Say Y if you are building a kernel for EP93xx based devices.
+
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
index b0d7068..c1539da 100644
--- a/drivers/net/arm/Makefile
+++ b/drivers/net/arm/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_ETHER00)	+= ether00.o
 obj-$(CONFIG_ARM_ETHERH)	+= etherh.o
 obj-$(CONFIG_ARM_ETHER3)	+= ether3.o
 obj-$(CONFIG_ARM_ETHER1)	+= ether1.o
+obj-$(CONFIG_EP93XX_ETHERNET)	+= ep93xx_eth.o
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
new file mode 100644
index 0000000..e314549
--- /dev/null
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -0,0 +1,1412 @@
+/*
+ * ep93xx_eth.c
+ *  Ethernet Device Driver for Cirrus Logic EP93xx.
+ *
+ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License.
+ *
+ *   This driver was written based on skeleton.c by Donald Becker and
+ * smc9194.c by Erik Stahlman.
+ *
+ * Getting a MAC address:
+ *
+ * Former versions of this driver got their MAC from I2C EEPROM or even used
+ * hardcoded ones. Unfortunately I had to remove the board dependant I2C stuff,
+ * and use a random generated MAC instead of the hardcoded one. Good news is
+ * the there is support for setting the MAC from userspace now. (see below)
+ *
+ * first consider some potential problems if you use this random generated MAC:
+ *
+ *    you can no longer count on it to be really unique
+ *    identifying a particular board over network will be difficult
+ *    DHCP servers can no longer use the MAC for assigning static IPs
+ *    DHCP servers with long leasetimes quickly run out of leases
+ *    ...
+ *
+ * So how can you set a valid MAC from userspace then?
+ *
+ * Let's say you've just bought your OUI from IEEE and it's "aa:bb:cc"
+ * Now you'd like to assign the MAC for your EP93xx board with serial #5
+ * MAC = OUI<<24 + serial number = aa:bb:cc:00:00:05
+ *
+ *   ifconfig eth0 hw ether aa:bb:cc:00:00:05            # first set the MAC
+ *   ifconfig eth0 192.168.1.1 netmask 255.255.255.0 up  # then set the IP
+ *
+ * Apart from hardcoding this lines in your startup scripts you could also use
+ * some userspace utility to read (and set) the MAC from eeprom, flash, ...
+ *
+ * History:
+ * 07/19/01 0.1  Sungwook Kim  initial release
+ * 10/16/01 0.2  Sungwook Kim  add workaround for ignorance of Tx request
+ *                              while sending frame
+ *                             add some error stuations handling
+ *
+ * 03/25/03 Melody Lee Modified for EP93xx
+ *
+ * 2004/2005  Michael Burian	porting to linux-2.6
+ * 2005-10-12 Michael Burian	fix problems when setting MAC with ifconfig
+ * 2005-10-30 Michael Burian	cleanups, ethtool support
+ */
+
+/* TODO: 
+ * 1. try if it's possible to use skbuff directly for RX/TX (avoid memcpy)
+ * 2. use kzalloc instead of kmalloc+memset
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/random.h>
+#include <linux/ethtool.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/arch/hardware.h>
+
+#include "ep93xx_eth.h"
+
+#define DRV_NAME	"ep93xx_eth"
+#define DRV_VERSION	"2.8"
+#define DRV_DATE	"2005-11-08"
+
+static const char *version = DRV_NAME ": version " DRV_VERSION " " DRV_DATE \
+							" Cirrus Logic\n";
+
+/* total number of device instance, 0 means the 1st instance. */
+static int num_of_instance;
+static struct net_device * ep93xx_etherdev;
+
+/*
+ * A List of default device port configuration for auto probing.
+ * At this time, the CPU has only one Ethernet device,
+ * but better to support multiple device configuration.
+ * Keep in mind that the array must end in zero.
+ */
+
+/* We get the MAC_BASE from include/asm-arm/arch-ep93xx/regmap.h */
+static struct {
+	unsigned int base_addr;	/* base address, (0:end mark) */
+	int irq;		/* IRQ number, (0:auto detect) */
+} port_list[] __initdata = {
+	{
+	MAC_BASE, 39}, {
+	0 /* end mark */ , 0}
+};
+
+/*
+ * Some definitions belong to the operation of this driver.
+ * You should understand how it affect to driver before any modification.
+ */
+
+/* Interrupt Sources in Use */
+#define  DEF_INT_SRC  (IntEn_TxSQIE|IntEn_RxEOFIE|IntEn_RxEOBIE|IntEn_RxHDRIE)
+
+/*
+ * Length of Device Queue in number of entries
+ * (must be less than or equal to 255)
+ */
+
+/* length of Rx Descriptor Queue (4 or bigger) Must be power of 2. */
+#define  LQRXD  64
+#define  LQRXS   LQRXD		/* length of Rx Status Queue */
+
+/* length of Tx Descriptor Queue (4 or bigger) Must be power of 2. */
+#define  LQTXD  8
+#define  LQTXS   LQTXD		/* length of Tx Status Queue */
+
+/* Tx Queue fill-up level control */
+#define  LVL_TXSTOP    LQTXD - 2	/* level to ask the stack to stop Tx */
+#define  LVL_TXRESUME  2	/* level to ask the stack to resume Tx */
+
+/* Rx Buffer length in byte */
+#define  LRXB  (1518+2+16)	/* length of Rx buf, must be 4-byte aligned */
+#define  LTXB   LRXB
+
+#define EP93XX_DEF_MSG (NETIF_MSG_DRV		| \
+			NETIF_MSG_PROBE		| \
+			NETIF_MSG_LINK		| \
+			NETIF_MSG_RX_ERR	| \
+			NETIF_MSG_TX_ERR	| \
+			NETIF_MSG_HW)
+
+#define DBG(lvl,msg,args...) do { printk(lvl"%s:%d: %s(): " msg, __FILE__, \
+		__LINE__,  __FUNCTION__, ## args); } while (0)
+
+/*
+ * Custom Data Structures
+ */
+
+/*
+ * the information about the buffer passed to device.
+ * there are matching bufdsc informations
+ * for each Tx/Rx Descriptor Queue entry to trace
+ * the buffer within those queues.
+ */
+struct bufdsc {
+	/* virtual address representing the buffer passed to device */
+	void *vaddr;
+	/* free routine */
+	int (*free_rout) (void *buf);
+};
+
+/* device private information */
+struct ep93xx_priv {
+	/*  static device information */
+	int id;			/* device instance ID */
+	/* pointers to various queues (virtual address) */
+	struct rx_dsc *rdq;	/* Rx Descriptor Queue */
+	struct rx_sts *rsq;	/* Rx Status Queue */
+	struct tx_dsc *tdq;	/* Tx Descriptor Queue */
+	struct tx_sts *tsq;	/* Tx Status Queue */
+	unsigned char *rxbuf;	/* base of Rx Buffer pool */
+	unsigned char *txbuf;	/* base of Tx Buffer pool */
+	struct bufdsc *rxbd;	/* Rx Buffers info */
+	struct bufdsc *txbd;	/* Tx Buffers info */
+	/* physical addresses of the same queues */
+	dma_addr_t p_qbase;	/* base */
+	dma_addr_t p_rdq;	/* Rx Descriptor Queue */
+	dma_addr_t p_rsq;	/* Rx Status Queue */
+	dma_addr_t p_tdq;	/* Tx Descriptor Queue */
+	dma_addr_t p_tsq;	/* Tx Status Queue */
+	dma_addr_t p_rxbuf;	/* Rx Buffer pool */
+	dma_addr_t p_txbuf;	/* Tx Buffer pool */
+	/* MII Bus ID of Ethernet PHY */
+	struct mii_if_info mii;
+	/* lock for mii when using ioctls */
+	spinlock_t mii_lock;
+	/*  dynamic information, subject to clear when device open */
+	struct net_device_stats stats;	/* statistic data */
+	/* next processing index of device queues */
+	int idx_rdq;
+	int idx_rsq;
+	int idx_tdqhead;
+	int idx_tdqtail;
+	int idx_tsq;
+	void __iomem *base_addr;	/* base address */
+	u32 msg_enable;
+	int regs_len;
+};
+
+/*
+ * Internal Routines
+ */
+
+static inline unsigned int next_index(unsigned int idx_cur, unsigned int len)
+{
+	return (idx_cur + 1) % len;	/* next array index */
+}
+
+static inline u32 _rdl(struct net_device *dev, u32 reg)
+{
+	return readl(((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
+}
+
+static inline void _wrl(struct net_device *dev, u32 val, u32 reg)
+{
+	writel(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
+}
+
+static inline void _wrw(struct net_device *dev, u16 val, u32 reg)
+{
+	writew(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
+}
+
+static inline void _wrb(struct net_device *dev, u8 val, u32 reg)
+{
+	writeb(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
+}
+
+/**
+ * wait_on_reg()
+ */
+static int wait_on_reg(struct net_device *dev, int reg, unsigned long mask, unsigned long expect)
+{
+	int i, dt;
+
+	for (i = 0; i < 10000; i++) {
+		dt = _rdl(dev, reg);
+		dt = (dt ^ expect) & mask;
+		if (0 == dt)
+			break;
+	}
+	return dt;
+}
+
+/**
+ * mdio_write()
+ */
+static void mdio_write(struct net_device *dev, int idPhy, int reg, int dt)
+{
+	wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
+	_wrl(dev, dt, REG_MIIData);
+	_wrl(dev, MIICmd_OP_WR | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0), REG_MIICmd);
+}
+
+/**
+ * mdio_read()
+ */
+static int mdio_read(struct net_device *dev, int idPhy, int reg)
+{
+	int dt;
+
+	wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
+	_wrl(dev, MIICmd_OP_RD | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0), REG_MIICmd);
+
+	wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
+	dt = _rdl(dev, REG_MIIData);
+
+	return dt & 0xffff;
+}
+
+/**
+ * phy_init()
+ */
+static void phy_init(struct net_device *dev)
+{
+
+	u32 oldval;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	oldval = _rdl(dev, REG_SelfCTL);
+
+	/* Set MDC clock to be divided by 8 and disable PreambleSuppress bit */
+	_wrl(dev, 0x0e00, REG_SelfCTL);
+
+	if (mii_link_ok(&(priv->mii)))
+		mii_check_media(&(priv->mii), netif_msg_link(priv), 1);
+
+	/* restore the old value */
+	_wrl(dev, oldval, REG_SelfCTL);
+}
+
+/**
+ * devQue_start()
+ *
+ * make descriptor queues active
+ * allocate queue entries if needed
+ * and set device registers up to make it operational
+ * assume device has been initialized
+ */
+static int devQue_start(struct net_device *dev)
+{
+	int err;
+	int i;
+	void *buf;
+	u32 phy_addr;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	/* turn off device bus mastering */
+	_wrl(dev, BMCtl_RxDis | BMCtl_TxDis | _rdl(dev, REG_BMCtl), REG_BMCtl);
+	err = wait_on_reg(dev, REG_BMSts, BMSts_TxAct, ~BMSts_TxAct);
+	err |= wait_on_reg(dev, REG_BMSts, BMSts_RxAct, ~BMSts_RxAct);
+	if (err && netif_msg_hw(priv))
+		DBG(KERN_ERR, "%s: BM does not stop\n", dev->name);
+
+	/* Tx Status Queue */
+	memset(priv->tsq, 0, sizeof(priv->tsq[0]) * LQTXS);
+	priv->idx_tsq = 0;
+	_wrl(dev, priv->p_tsq, REG_TxSBA);
+	_wrl(dev, priv->p_tsq, REG_TxSCA);
+	_wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSBL);
+	_wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSCL);
+
+	/* Tx Descriptor Queue */
+	memset(priv->tdq, 0, sizeof(priv->tdq[0]) * LQTXD);
+	priv->idx_tdqhead = priv->idx_tdqtail = 0;
+	_wrl(dev, priv->p_tdq, REG_TxDBA);
+	_wrl(dev, priv->p_tdq, REG_TxDCA);
+	_wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDBL);
+	_wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDCL);
+
+	/* Rx Status Queue */
+	memset(priv->rsq, 0, sizeof(priv->rsq[0]) * LQRXS);
+	priv->idx_rsq = 0;
+	_wrl(dev, priv->p_rsq, REG_RxSBA);
+	_wrl(dev, priv->p_rsq, REG_RxSCA);
+	_wrw(dev, sizeof(priv->rsq[0]) * LQRXS, REG_RxSBL);
+	_wrw(dev, sizeof(priv->rsq[0]) * LQRXS, REG_RxSCL);
+
+	/* Rx Descriptor Queue */
+	memset(priv->rdq, 0, sizeof(priv->rdq[0]) * LQRXD);
+	phy_addr = priv->p_rxbuf;
+	for (i = 0; i < LQRXD; i++) {
+		priv->rdq[i].bi = i;	/* index */
+		priv->rdq[i].ba = phy_addr;	/* physical address */
+		priv->rdq[i].bl = LRXB;	/* length */
+		phy_addr += LRXB;
+	}
+	priv->idx_rdq = 0;
+	_wrl(dev, priv->p_rdq, REG_RxDBA);
+	_wrl(dev, priv->p_rdq, REG_RxDCA);
+	_wrw(dev, sizeof(priv->rdq[0]) * LQRXD, REG_RxDBL);
+	_wrw(dev, sizeof(priv->rdq[0]) * LQRXD, REG_RxDCL);
+
+	/* init Rx Buffer Descriptors */
+	buf = priv->rxbuf;
+	for (i = 0; i < LQRXD; i++) {
+		priv->rxbd[i].vaddr = buf;
+		priv->rxbd[i].free_rout = NULL;
+		buf += LRXB;
+	}
+
+	/* init Tx Buffer Descriptors */
+	memset(priv->txbd, 0x0, sizeof(*priv->txbd) * LQTXD);
+
+	buf = priv->txbuf;
+	for (i = 0; i < LQTXD; i++) {
+		priv->txbd[i].vaddr = buf;
+		priv->txbd[i].free_rout = NULL;
+		buf += LTXB;
+	}
+
+	/* turn on device bus mastering */
+	_wrl(dev, BMCtl_TxEn | BMCtl_RxEn | _rdl(dev, REG_BMCtl), REG_BMCtl);
+	err = wait_on_reg(dev, REG_BMSts, BMSts_TxAct | BMSts_TxAct, BMSts_TxAct | BMSts_TxAct);
+	if (err && netif_msg_hw(priv))
+		DBG(KERN_ERR, "%s: BM does not start\n", dev->name);
+
+	/* Enqueue whole entries; this must be done after BM activation */
+	_wrl(dev, LQRXS, REG_RxSEQ);	/* Rx Status Queue */
+	_wrl(dev, LQRXD, REG_RxDEQ);	/* Rx Desc. queue */
+
+	return 0;
+}
+
+/**
+ * devQue_init()
+ * init device descriptor queues at system level
+ *  device access is not recommended at this point
+ *
+ */
+static int devQue_init(struct net_device *dev)
+{
+	void *buf;
+	void *tmp;
+	int size, size2;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	/* verify device Tx/Rx Descriptor/Status Queue data size */
+	if (8 != sizeof(struct rx_dsc)) {
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "sizeof rx_dsc != 8 bytes!\n");
+		return -ENOMEM;
+	} else if (8 != sizeof(struct rx_sts)) {
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "sizeof rx_sts != 8 bytes!\n");
+		return -ENOMEM;
+	} else if (8 != sizeof(struct tx_dsc)) {
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "sizeof tx_dsc != 8 bytes!\n");
+		return -ENOMEM;
+	} else if (4 != sizeof(struct tx_sts)) {
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "sizeof tx_sts != 4 bytes!\n");
+		return -ENOMEM;
+	}
+
+	/*
+	   allocate kernel memory for whole queues
+	   best if non-cached memory block due to DMA access by the device
+	   if CPU doesn't have bus snooping
+	 */
+	size = sizeof(struct rx_dsc) * (LQRXD + 1) +
+	    sizeof(struct rx_sts) * (LQRXS + 1) +
+	    sizeof(struct tx_dsc) * (LQTXD + 1) +
+	    sizeof(struct tx_sts) * (LQTXS + 1) + sizeof(unsigned long) * 4;
+
+	buf = tmp = dma_alloc_coherent(NULL, size, &priv->p_qbase, GFP_KERNEL | GFP_DMA);
+	if (!buf) {
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "no memory for queue\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * assign memory to each queue
+	 */
+	priv->rdq = buf;
+	buf = buf + sizeof(struct rx_dsc) * (LQRXD + 1);
+	priv->rsq = buf;
+	buf = buf + sizeof(struct rx_sts) * (LQRXS + 1);
+	priv->tdq = buf;
+	buf = buf + sizeof(struct tx_dsc) * (LQTXD + 1);
+	priv->tsq = buf;
+	buf = buf + sizeof(struct tx_sts) * (LQTXS + 1);
+
+	/*
+	 * store physical address of each queue
+	 */
+	priv->p_rdq = priv->p_qbase;
+	priv->p_rsq = priv->p_rdq + ((u32) priv->rsq - (u32) priv->rdq);
+	priv->p_tdq = priv->p_rdq + ((u32) priv->tdq - (u32) priv->rdq);
+	priv->p_tsq = priv->p_rdq + ((u32) priv->tsq - (u32) priv->rdq);
+
+	/*
+	 *  init queue entries
+	 */
+	memset(priv->rdq, 0, sizeof(struct rx_dsc) * LQRXD);
+	memset(priv->rsq, 0, sizeof(struct rx_sts) * LQRXS);
+	memset(priv->tdq, 0, sizeof(struct tx_dsc) * LQTXD);
+	memset(priv->tsq, 0, sizeof(struct tx_sts) * LQTXS);
+
+	/* Allocate Rx Buffer
+	   (We might need to copy from Rx buf to skbuff in whatever case,
+	   because device bus master requires 32bit aligned Rx buffer address
+	   but Linux network stack requires odd 16bit aligned Rx buf address) */
+	priv->rxbuf = dma_alloc_coherent(NULL, LRXB * LQRXD, &priv->p_rxbuf, GFP_KERNEL | GFP_DMA);
+
+	if (!priv->rxbuf) {
+		priv->rxbuf = NULL;
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "no memory for RxBuf\n");
+		goto err_free_qbase_1;
+	}
+
+	/* Allocate Tx Buffer */
+	priv->txbuf = dma_alloc_coherent(NULL, LTXB * LQTXD, &priv->p_txbuf, GFP_KERNEL | GFP_DMA);
+
+	if (!priv->txbuf) {
+		priv->txbuf = NULL;
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "no memory for TxBuf\n");
+		goto err_free_rxbuf_2;
+	}
+
+	/*
+	 * allocate kernel memory for buffer descriptors
+	 */
+	size2 = sizeof(struct bufdsc) * (LQRXD + LQTXD);
+	buf = kmalloc(size2, GFP_KERNEL);
+	if (!buf) {
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "no memory for buf desc\n");
+		goto err_free_txbuf_3;
+	}
+	memset(buf, 0x0, size2);	/* clear with 0 */
+	priv->rxbd = buf;
+	priv->txbd = buf + sizeof(struct bufdsc) * LQRXD;
+
+	return 0;
+
+err_free_txbuf_3:
+	dma_free_coherent(NULL, LTXB * LQTXD, priv->txbuf, priv->p_txbuf);
+err_free_rxbuf_2:
+	dma_free_coherent(NULL, LRXB * LQRXD, priv->rxbuf, priv->p_rxbuf);
+err_free_qbase_1:
+	dma_free_coherent(NULL, size, tmp, priv->p_qbase);
+	return -ENOMEM;
+}
+
+/**
+ * devQue_cleanup()
+ * Release queue, Tx buffers and Rx buffers memory
+ * Only call after unregister_netdev
+ */
+static void devQue_cleanup(struct net_device *dev)
+{
+	int size;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	/* descriptor queues size */
+	size = sizeof(struct rx_dsc) * (LQRXD + 1) +
+	    sizeof(struct rx_sts) * (LQRXS + 1) +
+	    sizeof(struct tx_dsc) * (LQTXD + 1) +
+	    sizeof(struct tx_sts) * (LQTXS + 1) + sizeof(unsigned long) * 4;
+
+	dma_free_coherent(NULL, size, priv->rdq, priv->p_qbase);
+	dma_free_coherent(NULL, LTXB * LQTXD, priv->txbuf, priv->p_txbuf);
+	dma_free_coherent(NULL, LRXB * LQRXD, priv->rxbuf, priv->p_rxbuf);
+	kfree(priv->rxbd);
+
+}
+
+/**
+ * set_multicast_tbl()
+ */
+static void set_multicast_tbl(struct net_device *dev, u8 *buf)
+{
+	int i;
+	unsigned char position;
+	struct dev_mc_list *cur_addr;
+
+	memset(buf, 0x00, 8);
+
+	cur_addr = dev->mc_list;
+	for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
+
+		if (!cur_addr)
+			break;
+		if (!(*cur_addr->dmi_addr & 1))
+			continue;	/* make sure multicast addr */
+		position = ether_crc_le(6, cur_addr->dmi_addr) >> 26;
+		buf[position >> 3] |= 1 << (position & 0x07);
+	}
+}
+
+/**
+ * ind_addr_wr()
+ */
+static int ind_addr_wr(struct net_device *dev, int afp, char *buf)
+{
+	u32 rxctl;
+	int i, len;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	afp &= 0x07;
+	if (4 == afp || 5 == afp) {
+		if (netif_msg_hw(priv))
+			DBG(KERN_ERR, "invalid afp value\n");
+		return -1;
+	}
+	len = (AFP_AFP_HASH == afp) ? 8 : 6;
+
+	rxctl = _rdl(dev, REG_RxCTL);	/* turn Rx off */
+	_wrl(dev, ~RxCTL_SRxON & rxctl, REG_RxCTL);
+	_wrl(dev, afp, REG_AFP);	/* load new address pattern */
+	for (i = 0; i < len; i++)
+		_wrb(dev, buf[i], REG_IndAD + i);
+	_wrl(dev, rxctl, REG_RxCTL);	/* turn Rx back */
+
+	return 0;
+}
+
+/**
+ * rx_ctl()
+ */
+static int rx_ctl(struct net_device *dev, int sw)
+{
+	unsigned long tmp = _rdl(dev, REG_RxCTL);
+
+	/*
+	 * Workaround for MAC lost 60-byte-long frames:
+	 * must enable Runt_CRC_Accept bit
+	 */
+	if (sw)
+		_wrl(dev, tmp | RxCTL_SRxON | RxCTL_RCRCA, REG_RxCTL);
+	else
+		_wrl(dev, tmp & ~RxCTL_SRxON, REG_RxCTL);
+
+	return 0;
+}
+
+/**
+ * chk_tx_lvl()
+ */
+static void chk_tx_lvl(struct net_device *dev)
+{
+	int filled;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	/* check Tx Descriptor Queue fill-up level */
+	filled = priv->idx_tdqhead - priv->idx_tdqtail;
+	if (filled < 0)
+		filled += LQTXD;
+
+	if (filled <= (LVL_TXRESUME + 1))
+		netif_wake_queue(dev);
+}
+
+/**
+ * cleanup_tx()
+ */
+static void cleanup_tx(struct net_device *dev)
+{
+	struct tx_sts *txsts;
+	int idxsts, bi;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	/*
+	 * process Tx Status Queue (no need to limit processing of TxStatus
+	 * Queue because each queue entry consist of 1 dword)
+	 */
+	while (priv->tsq[priv->idx_tsq].flags & TXSTS_TXFP) {
+		idxsts = priv->idx_tsq;
+		priv->idx_tsq = next_index(priv->idx_tsq, LQTXS);
+		txsts = &priv->tsq[idxsts];
+		if (!(txsts->flags & TXSTS_TXFP)) {	/* empty? */
+			if (netif_msg_tx_err(priv))
+				DBG(KERN_ERR, "QueTxSts is empty\n");
+			return;
+		}
+		txsts->flags &= ~TXSTS_TXFP;	/* mark processed */
+
+		bi = txsts->bi & TXSTS_BI;	/* buffer index */
+
+		/* statistics collection */
+		if (txsts->flags & TXSTS_TXWE) {	/* Sent without error */
+			priv->stats.tx_packets++;
+			priv->stats.tx_bytes += ((struct tx_dsc *)(priv->txbd[bi].vaddr))->bl_af & TXDSC_BL;
+		} else {	/* Tx failed due to error */
+			if (netif_msg_tx_err(priv))
+				DBG(KERN_ERR, "Tx failed QueTxSts");
+			priv->stats.tx_errors++;
+			if (txsts->flags & TXSTS_LCRS)
+				priv->stats.tx_carrier_errors++;
+			if (txsts->flags & TXSTS_TXU)
+				priv->stats.tx_fifo_errors++;
+			if (txsts->flags & TXSTS_ECOLL)
+				priv->stats.collisions++;
+		}
+
+		/* free Tx buffer */
+		if (priv->txbd[bi].free_rout) {
+			(*priv->txbd[bi].free_rout)(priv->txbd[bi].vaddr);
+			priv->txbd[bi].free_rout = NULL;
+		}
+
+		/* ahead Tx Descriptor Queue tail index */
+		priv->idx_tdqtail = next_index(priv->idx_tdqtail, LQTXD);
+	}
+}
+
+/**
+ * restart_tx()
+ */
+static int restart_tx(struct net_device *dev)
+{
+	int i;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	/* disable int */
+
+	/* turn off master INT control */
+	_wrl(dev, _rdl(dev, REG_GIntMsk) & ~GIntMsk_IntEn, REG_GIntMsk);
+
+	/* stop Tx and disable Tx DMA */
+	_wrl(dev, _rdl(dev, REG_TxCTL) & ~TxCTL_STxON, REG_TxCTL);
+	_wrl(dev, _rdl(dev, REG_BMCtl) | BMCtl_TxDis, REG_BMCtl);
+
+	/* reset Tx DMA */
+	_wrl(dev, BMCtl_TxChR | _rdl(dev, REG_BMCtl), REG_BMCtl);
+
+	/* release Tx buffers */
+	for (i = 0; i < LQTXD; i++) {
+		if (priv->txbd[i].free_rout) {
+			priv->txbd[i].free_rout(priv->txbd[i].vaddr);
+			priv->txbd[i].free_rout = NULL;
+		}
+		priv->stats.tx_dropped++;
+	}
+
+	/* init Tx Queues and flush cache */
+	memset(priv->tsq, 0, sizeof(priv->tsq[0]) * LQTXS);
+
+	/* init variables */
+	priv->idx_tsq = priv->idx_tdqhead = priv->idx_tdqtail = 0;
+
+	/* init registers */
+	wait_on_reg(dev, REG_BMSts, BMCtl_TxChR, ~BMCtl_TxChR);
+	_wrl(dev, priv->p_tsq, REG_TxSBA);
+	_wrl(dev, priv->p_tsq, REG_TxSCA);
+	_wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSBL);
+	_wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSCL);
+	_wrl(dev, priv->p_tdq, REG_TxDBA);
+	_wrl(dev, priv->p_tdq, REG_TxDCA);
+	_wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDBL);
+	_wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDCL);
+
+	/* start Tx and enable Tx DMA */
+	_wrl(dev, _rdl(dev, REG_TxCTL) | TxCTL_STxON, REG_TxCTL);
+	_wrl(dev, _rdl(dev, REG_BMCtl) | BMCtl_TxEn, REG_BMCtl);
+
+	/* enable int again */
+	_wrl(dev, _rdl(dev, REG_GIntMsk) | GIntMsk_IntEn, REG_GIntMsk);
+
+	return 0;
+}
+
+/**
+ * reset()
+ */
+static void reset(struct net_device *dev)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	/* soft reset command */
+	_wrb(dev, SelfCTL_RESET, REG_SelfCTL);
+	if (wait_on_reg(dev, REG_SelfCTL, SelfCTL_RESET, ~SelfCTL_RESET))
+		if (netif_msg_drv(priv))
+			DBG(KERN_WARNING, "Soft Reset does not self-clear\n");
+}
+
+/**
+ * eth_shutdown()- closes down the Ethernet module
+ *
+ * Make sure to:
+ *	1. disable all interrupt mask
+ *	2. disable Rx
+ *	3. disable Tx
+ *
+ *	TODO:
+ *   (1) maybe utilize power down mode.
+ *	Why not yet?  Because while the chip will go into power down mode,
+ *	the manual says that it will wake up in response to any I/O requests
+ *	in the register space.   Empirical results do not show this working.
+ */
+static int eth_shutdown(struct net_device *dev)
+{
+	reset(dev);
+	return 0;
+}
+
+/**
+ * eth_init() - Reset and initialize the device.
+ *
+ * Device should be initialized enough to function in polling mode.
+ * Tx and Rx must be disabled and no INT generation.
+ */
+static int eth_init(struct net_device *dev)
+{
+	/* reset device */
+	reset(dev);
+
+	/* init PHY */
+	phy_init(dev);
+
+	/* init MAC */
+
+	/*i Set MDC clock to be divided by 8 and enable PreambleSuppress bit */
+	_wrl(dev, 0x0f00, REG_SelfCTL);
+	/* mask Interrupt */
+	_wrl(dev, 0x00, REG_GIntMsk);
+	/* no Rx on at this point */
+	_wrl(dev, RxCTL_BA | RxCTL_IA0, REG_RxCTL);
+	_wrl(dev, 0x00, REG_TxCTL);
+	_wrl(dev, 0x00, REG_GT);
+	_wrl(dev, 0x00, REG_BMCtl);
+	/* Buffer Threshold */
+	_wrl(dev, (0x80 << 16) | (0x40 << 0), REG_RxBTH);
+	_wrl(dev, (0x80 << 16) | (0x40 << 0), REG_TxBTH);
+	/* Status Threshold */
+	_wrl(dev, (4 << 16) | (2 << 0), REG_RxSTH);
+	_wrl(dev, (4 << 16) | (2 << 0), REG_TxSTH);
+	/* Descriptor Threshold */
+	_wrl(dev, (4 << 16) | (2 << 0), REG_RxDTH);
+	_wrl(dev, (4 << 16) | (2 << 0), REG_TxDTH);
+	/* Max Frame Length & Tx Start Threshold */
+	_wrl(dev, ((1518 + 1) << 16) | (944 << 0), REG_MaxFL);
+
+	_rdl(dev, REG_TxCollCnt);	/* clear Tx Collision Count */
+	_rdl(dev, REG_RxMissCnt);	/* clear Rx Miss Counter */
+	_rdl(dev, REG_RxRntCnt);	/* clear Rx Runt Counter */
+
+	/* clear Pending INT */
+	_rdl(dev, REG_IntStsC);
+	/* Tx on */
+	_wrl(dev, TxCTL_STxON | _rdl(dev, REG_TxCTL), REG_TxCTL);
+
+	/* Set MAC address */
+	ind_addr_wr(dev, AFP_AFP_IA0, &dev->dev_addr[0]);
+
+	/* init queue */
+	devQue_start(dev);
+
+	return 0;
+}
+
+/**
+ * rx_isr() - Receive Interrupt Service Routine
+ */
+static void rx_isr(struct net_device *dev)
+{
+	struct rx_sts *rxsts;
+	/* index of Rx Status Queue Head from device (next put point) */
+	int idx_rsqhead;
+	int idxsts;
+	int cnt_sts_processed, cnt_desc_processed;
+	char *dest;
+	struct sk_buff *skb;
+	int len;
+	unsigned int dt;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	/* get Current Rx Status Queue pointer */
+	dt = _rdl(dev, REG_RxSCA);
+
+	/* convert to array index */
+	idx_rsqhead = (dt - priv->p_rsq) / sizeof(priv->rsq[0]);
+	if (!(0 <= idx_rsqhead && idx_rsqhead < LQRXS)) {
+		if (netif_msg_rx_err(priv))
+			DBG(KERN_ERR, " invalid REG_RxSCA\n");
+		return;
+	}
+
+	/* process Rx (limit to idx_rsqhead due to cache) */
+	cnt_sts_processed = cnt_desc_processed = 0;
+	while (idx_rsqhead != priv->idx_rsq) {
+		idxsts = priv->idx_rsq;
+		priv->idx_rsq = next_index(priv->idx_rsq, LQRXS);
+		rxsts = &priv->rsq[idxsts];
+		if (!(rxsts->w1 & RXSTS_RFP)) {	/* empty? */
+			if (netif_msg_rx_err(priv))
+				DBG(KERN_ERR, "QueRxSts empty\n");
+			return;
+		}
+		rxsts->w1 &= ~RXSTS_RFP;	/* mark processed */
+
+		cnt_sts_processed++;
+
+		if (!(rxsts->w1 & RXSTS_EOB))	/* buffer has no data */
+			continue;
+
+		if ((rxsts->bi & RXSTS_BI) != priv->idx_rdq) {
+			if (netif_msg_rx_err(priv))
+				DBG(KERN_ERR, "unmatching idx_rdq\n");
+			continue;
+		}
+		priv->idx_rdq = next_index(priv->idx_rdq, LQRXD);
+		cnt_desc_processed++;
+
+		/* received a frame with error */
+		if (!((rxsts->w1 & RXSTS_EOF) && (rxsts->w1 & RXSTS_RWE))) {
+			if (netif_msg_rx_err(priv))
+				DBG(KERN_WARNING, "Rx error RxSts\n");
+			priv->stats.rx_errors++;
+			if (rxsts->w1 & RXSTS_OE)
+				priv->stats.rx_fifo_errors++;
+			if (rxsts->w1 & RXSTS_FE)
+				priv->stats.rx_frame_errors++;
+			if ((rxsts->w1 & RXSTS_RUNT) || (rxsts->w1 & RXSTS_EDATA))
+				priv->stats.rx_length_errors++;
+			if (rxsts->w1 & RXSTS_CRCE)
+				priv->stats.rx_crc_errors++;
+			continue;
+		}
+
+		len = rxsts->fl;
+
+		/* alloc buffer for protocal stack */
+		skb = dev_alloc_skb(len + 5);
+		if (NULL == skb) {
+			if (netif_msg_rx_err(priv))
+				DBG(KERN_ERR, "Low Memory, Rx dropped\n");
+			priv->stats.rx_dropped++;
+			continue;
+		}
+
+		/* odd 16 bit alignment to make protocal stack happy */
+		skb_reserve(skb, 2);
+		skb->dev = dev;
+		dest = skb_put(skb, len);
+		memcpy(dest, priv->rxbd[(rxsts->bi & RXSTS_BI)].vaddr, len);
+		skb->protocol = eth_type_trans(skb, dev);
+		/* pass Rx packet to system */
+		netif_rx(skb);
+		dev->last_rx = jiffies;
+		priv->stats.rx_packets++;
+		priv->stats.rx_bytes += len;
+		if (RXSTS_AM == (rxsts->w1 & RXSTS_AM))
+			priv->stats.multicast++;
+	}
+
+	/* enqueue */
+	_wrl(dev, cnt_sts_processed, REG_RxSEQ);
+	_wrl(dev, cnt_desc_processed, REG_RxDEQ);
+}
+
+/**
+ * tx_isr() - Transmit Interrupt Service Routine
+ */
+static int tx_isr(struct net_device *dev)
+{
+	cleanup_tx(dev);
+	chk_tx_lvl(dev);	/* resume Tx if it was stopped */
+	return 0;
+}
+
+/**
+ * ep93xx_isr()
+ */
+static irqreturn_t ep93xx_isr(int irq, void *dev_id, struct pt_regs *pRegs)
+{
+	struct net_device *dev = dev_id;
+	int lpCnt;
+	u32 intS;
+
+	lpCnt = 0;
+	do {
+		/* get INT status and then clear */
+		intS = _rdl(dev, REG_IntStsC);
+
+		if (!intS)
+			break;	/* no INT */
+		if (IntSts_RxSQ & intS)
+			rx_isr(dev);	/* Rx INT */
+		if (IntSts_TxSQ & intS)
+			tx_isr(dev);	/* Tx INT */
+	} while (lpCnt++ < 64);	/* limit loop to serve other interrupts too */
+	return IRQ_HANDLED;
+}
+
+/* Exposed Driver Routines to the Outside World */
+
+/**
+ * ep93xx_get_stats()
+ */
+static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	return &priv->stats;
+}
+
+/**
+ * ep93xx_set_multicast_list()
+ */
+static void ep93xx_set_multicast_list(struct net_device *dev)
+{
+	u8 tbl[8 + 1];
+
+	if (IFF_PROMISC & dev->flags) {
+		_wrl(dev, RxCTL_PA | _rdl(dev, REG_RxCTL), REG_RxCTL);
+
+	} else if (IFF_ALLMULTI & dev->flags) {	/* receive all multicast addr */
+		_wrl(dev, RxCTL_MA | (~RxCTL_PA & _rdl(dev, REG_RxCTL)), REG_RxCTL);
+		memset(tbl, 0xff, 8);
+		ind_addr_wr(dev, AFP_AFP_HASH, &tbl[0]);
+
+	} else if (dev->mc_count) {	/* set H/W multicasting filter */
+		_wrl(dev, RxCTL_MA | (~RxCTL_PA & _rdl(dev, REG_RxCTL)), REG_RxCTL);
+		set_multicast_tbl(dev, &tbl[0]);
+		ind_addr_wr(dev, AFP_AFP_HASH, &tbl[0]);
+
+	} else {		/* no multicasting */
+		_wrl(dev, ~(RxCTL_PA | RxCTL_MA) & _rdl(dev, REG_RxCTL), REG_RxCTL);
+	}
+}
+
+/**
+ * ep93xx_tx_timeout()
+ */
+static void ep93xx_tx_timeout(struct net_device *dev)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	/* If we get here, some higher level has decided we are broken.
+	   There should really be a "kick me" function call instead. */
+	if (netif_msg_tx_err(priv))
+		DBG(KERN_WARNING, "transmit timed out\n");
+
+	phy_init(dev);
+
+	/* kick Tx engine */
+	restart_tx(dev);
+
+	/* ask the Network Stack to resume Tx if there is room available */
+	chk_tx_lvl(dev);
+}
+
+/**
+ * ep93xx_start_xmit()
+ */
+static int ep93xx_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+/* @swk check H/W defect of Tx Underrun Error caused by certain frame length */
+	struct tx_dsc *txdsc;
+	int idx_tdqhd;
+	int filled;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	idx_tdqhd = priv->idx_tdqhead;
+	txdsc = &priv->tdq[idx_tdqhd];
+
+	/* check Tx Descriptor Queue fill-up level */
+	filled = idx_tdqhd - priv->idx_tdqtail;
+	if (filled < 0)
+		filled += LQTXD;
+	filled += 1;
+
+	/* check Queue level */
+	if (LVL_TXSTOP <= filled) {
+		netif_stop_queue(dev);	/* no more Tx allowed */
+		if (netif_msg_tx_err(priv))
+			DBG(KERN_INFO, "%s: Tx STOP requested\n", dev->name);
+		if (LVL_TXSTOP < filled) {
+			/* this situation can not be happen */
+			if (netif_msg_tx_err(priv))
+				DBG(KERN_ERR, "%s: Tx Request while stopped\n", dev->name);
+			return NETDEV_TX_BUSY;
+		}
+	}
+
+	/* fill up Tx Descriptor Queue entry */
+	if (skb->len < ETH_ZLEN) {
+		txdsc->bl_af = ETH_ZLEN & TXDSC_BL;	/* also clears AF! */
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return NETDEV_TX_OK;
+	} else {
+		txdsc->bl_af = skb->len & TXDSC_BL;	/* also clears AF! */
+	}
+	txdsc->ba = priv->p_txbuf + (idx_tdqhd * LTXB);
+	txdsc->bi_eof = (idx_tdqhd & TXDSC_BI) | TXDSC_EOF;
+
+	dev->trans_start = jiffies;
+
+	/* copy data to Tx buffer */
+	memcpy(priv->txbd[idx_tdqhd].vaddr, skb->data, skb->len);
+	priv->txbd[idx_tdqhd].free_rout = NULL;
+
+	/* Free the data buffer passed by upper layer */
+	dev_kfree_skb_any(skb);
+
+	/* ahead Tx Desc Queue */
+	priv->idx_tdqhead = next_index(priv->idx_tdqhead, LQTXD);
+	wmb();
+
+	/* Enqueue a Tx Descriptor to the device */
+	_wrl(dev, 1, REG_TxDEQ);
+
+	if (netif_msg_tx_queued(priv))
+		DBG(KERN_DEBUG, "%s: Tx packet queued\n", dev->name);
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * ep93xx_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 ep93xx_close(struct net_device *dev)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	free_irq(dev->irq, dev);
+
+	netif_stop_queue(dev);
+	eth_shutdown(dev);
+
+	if (netif_msg_ifdown(priv))
+		DBG(KERN_INFO, "%s: ep93xx_close()\n", dev->name);
+
+	return 0;
+}
+
+/**
+ * ep93xx_open() - Open and Initialize the board
+ *
+ * Set up everything, reset the card, etc ..
+ */
+static int ep93xx_open(struct net_device *dev)
+{
+	int status;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	/* clear dynamic device info */
+	memset(&priv->stats, 0, sizeof(priv->stats));
+	priv->idx_rdq = 0;
+	priv->idx_rsq = 0;
+	priv->idx_tdqhead = 0;
+	priv->idx_tdqtail = 0;
+	priv->idx_tsq = 0;
+
+	/* reset/init device */
+	status = eth_init(dev);
+	if (status != 0) {
+		return -EAGAIN;
+	}
+
+	/* turn on INT, turn on Rx */
+	status = request_irq(dev->irq, &ep93xx_isr, 0, DRV_NAME, dev);
+	if (status) {
+		if (netif_msg_ifup(priv))
+			DBG(KERN_ERR, "%s: unable to get IRQ\n", dev->name);
+		return status;
+	}
+
+	/* Enable interrupt driven operation. Also turn on Rx but no Tx. */
+	/* setup Interrupt sources */
+	_wrl(dev, DEF_INT_SRC, REG_IntEn);
+	/* turn on INT */
+	_wrl(dev, GIntMsk_IntEn, REG_GIntMsk);
+	/* turn on Rx */
+	rx_ctl(dev, 1);
+
+	/* link to upper layer */
+	netif_start_queue(dev);
+
+	if (netif_msg_ifup(priv))
+		DBG(KERN_INFO, "%s: irq=%d\n", dev->name, dev->irq);
+
+	return 0;
+}
+
+static int ep93xx_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	int rc;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	spin_lock_irq(&priv->mii_lock);
+	rc = generic_mii_ioctl(&priv->mii, if_mii(rq), cmd, NULL);
+	spin_unlock_irq(&priv->mii_lock);
+
+	return rc;
+}
+
+/*
+ * Ethtool support
+ */
+
+static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+}
+
+static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	spin_lock_irq(&priv->mii_lock);
+	mii_ethtool_gset(&priv->mii, cmd);
+	spin_unlock_irq(&priv->mii_lock);
+	return 0;
+}
+
+static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	int rc;
+	spin_lock_irq(&priv->mii_lock);
+	rc = mii_ethtool_sset(&priv->mii, cmd);
+	spin_unlock_irq(&priv->mii_lock);
+	return rc;
+}
+
+static int ep93xx_nway_reset(struct net_device *dev)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	return mii_nway_restart(&priv->mii);
+}
+
+static u32 ep93xx_get_link(struct net_device *dev)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	return mii_link_ok(&priv->mii);
+}
+
+static u32 ep93xx_get_msglevel(struct net_device *dev)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	return priv->msg_enable;
+}
+
+static void ep93xx_set_msglevel(struct net_device *dev, u32 datum)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	priv->msg_enable = datum;
+}
+
+static void ep93xx_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	spin_lock_irq(&priv->mii_lock);
+	memcpy_fromio(regbuf, priv->base_addr, regs->len);
+	spin_unlock_irq(&priv->mii_lock);
+}
+
+static int ep93xx_get_regs_len(struct net_device *dev)
+{
+	struct ep93xx_priv *priv = netdev_priv(dev);
+	return priv->regs_len;
+}
+
+static struct ethtool_ops ep93xx_ethtool_ops = {
+	.get_drvinfo		= ep93xx_get_drvinfo,
+	.get_settings		= ep93xx_get_settings,
+	.set_settings		= ep93xx_set_settings,
+	.get_regs		= ep93xx_get_regs,
+	.get_regs_len		= ep93xx_get_regs_len,
+	.nway_reset		= ep93xx_nway_reset,
+	.get_link		= ep93xx_get_link,
+	.get_msglevel		= ep93xx_get_msglevel,
+	.set_msglevel		= ep93xx_set_msglevel,
+};
+
+/**
+ *  driver_init() - Logical driver initialization for an individual device
+ *
+ *      Minimum device H/W access at this point
+ *
+ *  Task:
+ *        Initialize the structure if needed
+ *        print out my vanity message if not done so already
+ *        print out what type of hardware is detected
+ *        print out the ethernet address
+ *        find the IRQ
+ *        set up my private data
+ *        configure the dev structure with my subroutines
+ *        actually GRAB the irq.
+ *        GRAB the region
+ *
+ */
+static int __init driver_init(struct net_device *dev, u32 baseA, int irq)
+{
+	int i;
+	struct resource *res;
+	struct sockaddr sa;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	if (0 == num_of_instance)
+		printk("%s", version);
+
+	/* skip probing for a second one, we _know_ that it does not exist */
+	if (1 == num_of_instance)
+		return -ENODEV;
+
+	memset(dev->priv, 0x00, sizeof(struct ep93xx_priv));
+
+	/* device instance ID */
+	priv->id = num_of_instance;
+
+	/* mii stuff */
+	spin_lock_init(&priv->mii_lock);
+	priv->mii.dev = dev;
+	priv->mii.mdio_read = mdio_read;
+	priv->mii.mdio_write = mdio_write;
+	priv->mii.phy_id_mask = 0x1f;
+	priv->mii.reg_num_mask = 0x1f;
+	priv->msg_enable = EP93XX_DEF_MSG;
+	priv->regs_len = DEV_REG_SPACE;
+
+	priv->base_addr = (void *)(baseA);
+
+	dev->irq = irq;
+
+	res = request_mem_region(baseA, DEV_REG_SPACE, DRV_NAME);
+	if (res == NULL) {
+		if (netif_msg_probe(priv))
+			DBG(KERN_ERR, "request_mem_region failed!\n");
+		goto err_free_priv_1;
+	}
+
+	dev->open = &ep93xx_open;
+	dev->stop = &ep93xx_close;
+	dev->do_ioctl = &ep93xx_ioctl;
+	dev->hard_start_xmit = &ep93xx_start_xmit;
+	dev->tx_timeout = &ep93xx_tx_timeout;
+	dev->watchdog_timeo = HZ * 5;
+	dev->get_stats = &ep93xx_get_stats;
+	dev->set_multicast_list = &ep93xx_set_multicast_list;
+	dev->ethtool_ops = &ep93xx_ethtool_ops;
+
+	ether_setup(dev);
+
+	if (devQue_init(dev))
+		goto err_free_bd_memregion_irq_2;
+
+	reset(dev);
+
+	/*
+	 * use a random MAC for now -
+	 * don't forget to set a valid MAC later on with ifconfig
+	 */
+	sa.sa_family = AF_INET;
+	random_ether_addr(sa.sa_data);
+	dev->set_mac_address(dev, &sa);
+
+	if (netif_msg_probe(priv)) {
+		printk(KERN_INFO DRV_NAME ": #%d at 0x%p IRQ:%d\n", priv->id, priv->base_addr, dev->irq);
+		printk(KERN_INFO DRV_NAME ": using random number");
+		for (i = 0; i < 6; i++)
+			printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
+
+		printk(" as MAC, don't forget to assign a valid MAC later!\n");
+	}
+	num_of_instance++;
+	return 0;
+
+err_free_bd_memregion_irq_2:
+	kfree(priv->rxbd);
+	disable_irq(dev->irq);
+	free_irq(dev->irq, dev);
+	release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
+err_free_priv_1:
+	kfree(dev->priv);
+	return -EAGAIN;
+}
+
+/**
+ * ep93xx_probe - probe for ep93xx device
+ *
+ * Probe for the one (and only) ethernet device found on
+ * EP93xx SOC CPU.
+ */
+static int __init ep93xx_probe(void)
+{
+	int err;
+	struct ep93xx_priv *priv;
+	struct net_device *dev = alloc_etherdev(sizeof(struct ep93xx_priv));
+
+	if (!dev)
+		return -ENODEV;
+
+	priv = netdev_priv(dev);
+
+	SET_MODULE_OWNER(dev);
+
+	sprintf(dev->name, "eth0");
+
+	priv->base_addr = (void *)(port_list[0].base_addr);
+
+	dev->irq = port_list[0].irq;
+
+	err = driver_init(dev, (u32)priv->base_addr, dev->irq);
+	if (err)
+		goto err_free_netdev;
+
+	err = register_netdev(dev);
+	if (err)
+		goto err_free_memregion_irq_1;
+
+	ep93xx_etherdev = dev;
+	disable_irq(dev->irq);
+	return 0;
+
+err_free_memregion_irq_1:
+	kfree(priv->rxbd);
+	disable_irq(dev->irq);
+	free_irq(dev->irq, dev);
+	release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
+err_free_netdev:
+	free_netdev(dev);
+	return err;
+}
+
+static void __exit ep93xx_exit(void)
+{
+	struct net_device *dev = ep93xx_etherdev;
+	struct ep93xx_priv *priv = netdev_priv(dev);
+
+	if (dev) {
+		unregister_netdev(dev);
+		devQue_cleanup(dev);
+		free_irq(dev->irq, dev);
+		release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
+		free_netdev(dev);
+	}
+}
+
+module_init(ep93xx_probe);
+module_exit(ep93xx_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/arm/ep93xx_eth.h b/drivers/net/arm/ep93xx_eth.h
new file mode 100644
index 0000000..1752eaf
--- /dev/null
+++ b/drivers/net/arm/ep93xx_eth.h
@@ -0,0 +1,355 @@
+/*
+ * ep93xx_eth.h
+ * : header file of Ethernet Device Driver for Cirrus Logic EP93xx.
+ *
+ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License.
+ *
+ * This file contains device related information like register info
+ * and register access method macros for the Ethernet device
+ * embedded within Cirrus Logic's EP93xx SOC chip.
+ *
+ * Information contained in this file was obtained from
+ * the EP9312 Manual Revision 0.12 and 0.14 from Cirrus Logic.
+ *
+ * History
+ * 05/18/01  Sungwook Kim  Initial release
+ * 03/25/2003  Melody Modified for EP92xx
+ */
+
+#ifndef _EP93xx_ETH_H_
+#define _EP93xx_ETH_H_
+
+/*
+ * Definition of the registers.
+ * For details, refer to the datasheet  .
+ *
+ * Basically, most registers are 32 bits width register.
+ * But some are 16 bits and some are 6 or 8 bytes long.
+ */
+
+#define  REG_RxCTL  0x0000	/*offset to Receiver Control Reg */
+#define  RxCTL_PauseA  (1<<20)
+#define  RxCTL_RxFCE1  (1<<19)
+#define  RxCTL_RxFCE0  (1<<18)
+#define  RxCTL_BCRC    (1<<17)
+#define  RxCTL_SRxON   (1<<16)
+#define  RxCTL_RCRCA   (1<<13)
+#define  RxCTL_RA      (1<<12)
+#define  RxCTL_PA      (1<<11)
+#define  RxCTL_BA      (1<<10)
+#define  RxCTL_MA      (1<<9)
+#define  RxCTL_IAHA    (1<<8)
+#define  RxCTL_IA3     (1<<3)
+#define  RxCTL_IA2     (1<<2)
+#define  RxCTL_IA1     (1<<1)
+#define  RxCTL_IA0     (1<<0)
+
+#define  REG_TxCTL  0x0004	/*offset to Transmit Control Reg */
+#define  TxCTL_DefDis  (1<<7)
+#define  TxCTL_MBE     (1<<6)
+#define  TxCTL_ICRC    (1<<5)
+#define  TxCTL_TxPD    (1<<5)
+#define  TxCTL_OColl   (1<<3)
+#define  TxCTL_SP      (1<<2)
+#define  TxCTL_PB      (1<<1)
+#define  TxCTL_STxON   (1<<0)
+
+#define  REG_TestCTL   0x0008	/*Test Control Reg, R/W */
+#define  TestCTL_MACF  (1<<7)
+#define  TestCTL_MFDX  (1<<6)
+#define  TestCTL_DB    (1<<5)
+#define  TestCTL_MIIF  (1<<4)
+
+#define  REG_MIICmd  0x0010	/*offset to MII Command Reg, R/W */
+#define  MIICmd_OP     (0x03<<14)
+#define  MIICmd_OP_RD  (2<<14)
+#define  MIICmd_OP_WR  (1<<14)
+#define  MIICmd_PHYAD  (0x1f<<5)
+#define  MIICmd_REGAD  (0x1f<<0)
+
+#define  REG_MIIData  0x0014	/*offset to MII Data Reg, R/W */
+#define  MIIData_MIIData  (0xffff<<0)
+
+#define  REG_MIISts  0x0018	/*offset to MII Status Reg, R */
+#define  MIISts_Busy  (1<<0)
+
+#define  REG_SelfCTL  0x0020	/*offset to Self Control Reg */
+#define  SelfCTL_RWP    (1<<7)	/*Remote Wake Pin */
+#define  SelfCTL_GPO0   (1<<5)
+#define  SelfCTL_PUWE   (1<<4)
+#define  SelfCTL_PDWE   (1<<3)
+#define  SelfCTL_MIIL   (1<<2)
+#define  SelfCTL_RESET  (1<<0)
+
+#define  REG_IntEn   0x0024	/*Interrupt Enable Reg, R/W */
+#define  IntEn_RWIE    (1<<30)
+#define  IntEn_RxMIE   (1<<29)
+#define  IntEn_RxBIE   (1<<28)
+#define  IntEn_RxSQIE  (1<<27)
+#define  IntEn_TxLEIE  (1<<26)
+#define  IntEn_ECIE    (1<<25)
+#define  IntEn_TxUHIE  (1<<24)
+#define  IntEn_MOIE    (1<<18)
+#define  IntEn_TxCOIE  (1<<17)
+#define  IntEn_RxROIE  (1<<16)
+#define  IntEn_MIIIE   (1<<12)
+#define  IntEn_PHYSIE  (1<<11)
+#define  IntEn_TIE     (1<<10)
+#define  IntEn_SWIE    (1<<8)
+#define  IntEn_TxSQIE   (1<<3)
+#define  IntEn_RxEOFIE  (1<<2)
+#define  IntEn_RxEOBIE  (1<<1)
+#define  IntEn_RxHDRIE  (1<<0)
+
+#define  REG_IntStsP  0x0028	/*offset to Interrupt Status Preserve Reg, R/W */
+#define  REG_IntStsC  0x002c	/*offset to Interrupt Status Clear Reg, R */
+#define  IntSts_RWI    (1<<30)
+#define  IntSts_RxMI   (1<<29)
+#define  IntSts_RxBI   (1<<28)
+#define  IntSts_RxSQI  (1<<27)
+#define  IntSts_TxLEI  (1<<26)
+#define  IntSts_ECI    (1<<25)
+#define  IntSts_TxUHI  (1<<24)
+#define  IntSts_MOI    (1<<18)
+#define  IntSts_TxCOI  (1<<17)
+#define  IntSts_RxROI  (1<<16)
+#define  IntSts_MIII   (1<<12)
+#define  IntSts_PHYSI  (1<<11)
+#define  IntSts_TI     (1<<10)
+#define  IntSts_AHBE   (1<<9)
+#define  IntSts_SWI    (1<<8)
+#define  IntSts_OTHER  (1<<4)
+#define  IntSts_TxSQ   (1<<3)
+#define  IntSts_RxSQ   (1<<2)
+
+#define  REG_GT  0x0040		/*offset to General Timer Reg */
+#define  GT_GTC  (0xffff<<16)
+#define  GT_GTP  (0xffff<<0)
+
+#define  REG_FCT  0x0044	/*offset to Flow Control Timer Reg */
+#define  FCT_FCT  (0x00ffffff<<0)
+
+#define  REG_FCF  0x0048	/*offset to Flow Control Format Reg */
+#define  FCF_MACCT  (0xffff<<16)
+#define  FCF_TPT    (0xffff<<0)
+
+#define  REG_AFP  0x004c	/*offset to Address Filter Pointer Reg */
+#define  AFP_AFP  (0x07<<0)	/*Address Filter Pointer
+				   (bank control for REG_IndAD) */
+#define  AFP_AFP_IA0   0	/*Primary Individual Address (MAC Addr) */
+#define  AFP_AFP_IA1   1	/*Individual Address 1 */
+#define  AFP_AFP_IA2   2	/*Individual Address 2 */
+#define  AFP_AFP_IA3   3	/*Individual Address 3 */
+#define  AFP_AFP_DTxP  6	/*Destination Address of Tx Pause Frame */
+#define  AFP_AFP_HASH  7	/*Hash Table */
+
+#define  REG_IndAD      0x0050	/*offset to Individual Address Reg,
+				   n bytes, R/W */
+
+#define  REG_GIntSts    0x0060	/*offset to Global Interrupt
+				   Status Reg (writing 1 will clear) */
+#define  REG_GIntROS    0x0068	/*offset to Global Interrupt
+				   Status Read Only Reg */
+#define  GIntSts_INT  (1<<15)	/*Global Interrupt Request Status */
+
+#define  REG_GIntMsk    0x0064	/*offset to Global Interrupt Mask Reg */
+#define  GIntMsk_IntEn  (1<<15)	/*Global Interrupt Enable */
+
+#define  REG_GIntFrc    0x006c	/*offset to Global Interrupt Force Reg */
+#define  GIntFrc_INT  (1<<15)	/*Force to set GIntSts */
+
+#define  REG_TxCollCnt  0x0070	/*Transmit Collision Count Reg, R */
+#define  REG_RxMissCnt  0x0074	/*Receive Miss Count Reg, R */
+#define  REG_RxRntCnt   0x0078	/*Receive Runt Count Reg, R */
+
+#define  REG_BMCtl  0x0080	/*offset to Bus Master Control Reg, R/W */
+#define  BMCtl_MT     (1<<13)
+#define  BMCtl_TT     (1<<12)
+#define  BMCtl_UnH    (1<<11)
+#define  BMCtl_TxChR  (1<<10)
+#define  BMCtl_TxDis  (1<<9)
+#define  BMCtl_TxEn   (1<<8)
+#define  BMCtl_EH2    (1<<6)
+#define  BMCtl_EH1    (1<<5)
+#define  BMCtl_EEOB   (1<<4)
+#define  BMCtl_RxChR  (1<<2)
+#define  BMCtl_RxDis  (1<<1)
+#define  BMCtl_RxEn   (1<<0)
+
+#define  REG_BMSts  0x0084	/*offset to Bus Master Status Reg, R */
+#define  BMSts_TxAct  (1<<7)
+#define  BMSts_TP     (1<<4)
+#define  BMSts_RxAct  (1<<3)
+#define  BMSts_QID    (0x07<<0)
+#define  BMSts_QID_RxDt   (0<<0)
+#define  BMSts_QID_TxDt   (1<<0)
+#define  BMSts_QID_RxSts  (2<<0)
+#define  BMSts_QID_TxSts  (3<<0)
+#define  BMSts_QID_RxDesc (4<<0)
+#define  BMSts_QID_TxDesc (5<<0)
+
+#define  REG_RBCA   0x0088	/*offset to Receive Buffer
+				   Current Address Reg, R */
+#define  REG_TBCA   0x008c	/*offset to Transmit Buffer
+				   Current Address Reg, R */
+
+#define  REG_RxDBA  0x0090	/*offset to Receive Descriptor Queue
+				   Base Address Reg, R/W */
+#define  REG_RxDBL  0x0094	/*offset to Receive Descriptor Queue
+				   Base Length Reg, R/W, 16bits */
+#define  REG_RxDCL  0x0096	/*offset to Receive Descriptor Queue
+				   Current Length Reg, R/W, 16bits */
+#define  REG_RxDCA  0x0098	/*offset to Receive Descriptor Queue
+				   Current Address Reg, R/W */
+
+#define  REG_RxDEQ  0x009c	/*offset to Receive Descriptor
+				   Enqueue Reg, R/W */
+#define  RxDEQ_RDV  (0xffff<<16)	/*R 16bit; Receive Descriptor Value */
+#define  RxDEQ_RDI  (0xff<<0)	/*W 8bit; Receive Descriptor Increment */
+
+#define  REG_RxSBA  0x00a0	/*offset to Receive Status Queue
+				   Base Address Reg, R/W */
+#define  REG_RxSBL  0x00a4	/*offset to Receive Status Queue
+				   Base Length Reg, R/W, 16bits */
+#define  REG_RxSCL  0x00a6	/*offset to Receive Status Queue
+				   Current Length Reg, R/W, 16bits */
+#define  REG_RxSCA  0x00a8	/*offset to Receive Status Queue
+				   Current Address Reg, R/W */
+
+#define  REG_RxSEQ  0x00ac	/*offset to Receive Status Queue
+				   Current Address Reg, R/W */
+#define  RxSEQ_RSV  (0xffff<<16)
+#define  RxSEQ_RSI  (0xff<<0)
+
+#define  REG_TxDBA  0x00b0	/*offset to Transmit Descriptor Queue
+				   Base Address Reg, R/W */
+#define  REG_TxDBL  0x00b4	/*offset to Transmit Descriptor Queue
+				   Base Length Reg, R/W, 16bits */
+#define  REG_TxDCL  0x00b6	/*offset to Transmit Descriptor Queue
+				   Current Length Reg, R/W, 16bits */
+#define  REG_TxDCA  0x00b8	/*offset to Transmit Descriptor Queue
+				   Current Address Reg, R/W */
+
+#define  REG_TxDEQ  0x00bc	/*offset to Transmit Descriptor Queue
+				   Current Address Reg, R/W */
+#define  TxDEQ_TDV  (0xffff<<16)
+#define  TxDEQ_TDI  (0xff<<0)
+
+#define  REG_TxSBA  0x00c0	/*offset to Transmit Status Queue
+				   Base Address Reg, R/W */
+#define  REG_TxSBL  0x00c4	/*offset to Transmit Status Queue
+				   Base Length Reg, R/W, 16bits */
+#define  REG_TxSCL  0x00c6	/*offset to Transmit Status Queue
+				   Current Length Reg, R/W, 16bits */
+#define  REG_TxSCA  0x00c8	/*offset to Transmit Status Queue
+				   Current Address Reg, R/W */
+
+#define  REG_RxBTH  0x00d0	/*offset to Receive Buffer
+				   Threshold Reg, R/W */
+#define  RxBTH_RDHT  (0x03ff<<16)
+#define  RxBTH_RDST  (0x03ff<<0)
+
+#define  REG_TxBTH  0x00d4	/*offset to Transmit Buffer
+				   Threshold Reg, R/W */
+#define  TxBTH_TDHT  (0x03ff<<16)
+#define  TxBTH_TDST  (0x03ff<<0)
+
+#define  REG_RxSTH  0x00d8	/*offset to Receive Status
+				   Threshold Reg, R/W */
+#define  RxSTH_RSHT  (0x003f<<16)
+#define  RxSTH_RSST  (0x003f<<0)
+
+#define  REG_TxSTH  0x00dc	/*offset to Transmit Status
+				   Threshold Reg, R/W */
+#define  TxSTH_TSHT  (0x003f<<16)
+#define  TxSTH_TSST  (0x003f<<0)
+
+#define  REG_RxDTH  0x00e0	/*offset to Receive Descriptor
+				   Threshold Reg, R/W */
+#define  RxDTH_RDHT  (0x003f<<16)
+#define  RxDTH_RDST  (0x003f<<0)
+
+#define  REG_TxDTH  0x00e4	/*offset to Transmit Descriptor
+				   Threshold Reg, R/W */
+#define  TxDTH_TDHT  (0x003f<<16)
+#define  TxDTH_TDST  (0x003f<<0)
+
+#define  REG_MaxFL  0x00e8	/*offset to Max Frame Length Reg, R/W */
+#define  MaxFL_MFL  (0x07ff<<16)
+#define  MaxFL_TST  (0x07ff<<0)
+
+#define  REG_RxHL  0x00ec	/*offset to Receive Header Length Reg, R/W */
+#define  RxHL_RHL2  (0x07ff<<16)
+#define  RxHL_RHL1  (0x03ff<<0)
+
+#define  REG_MACCFG0  0x0100	/*offset to Test Reg #0, R/W */
+#define  MACCFG0_DbgSel  (1<<7)
+#define  MACCFG0_LCKEN   (1<<6)
+#define  MACCFG0_LRATE   (1<<5)
+#define  MACCFG0_RXERR   (1<<4)
+#define  MACCFG0_BIT33   (1<<2)
+#define  MACCFG0_PMEEN   (1<<1)
+#define  MACCFG0_PMEST   (1<<0)
+
+#define  REG_MACCFG1  0x0104	/*offset to Test Reg #1, R/W */
+#define  REG_MACCFG2  0x0108	/*offset to Test Reg #2, R */
+#define  REG_MACCFG3  0x010c	/*offset to Test Reg #3, R */
+
+/*---------------------------------------------------------------
+ * Definition of Descriptor/Status Queue Entry
+ *-------------------------------------------------------------*/
+struct rx_dsc {
+	__be32 ba;
+	__be16 bl;
+	__be16 bi;		/* let nsof flag be part of bi */
+};
+
+#define RXSTS_RFP 	0x80000000
+#define RXSTS_RWE	0x40000000
+#define RXSTS_EOF	0x20000000
+#define RXSTS_EOB	0x10000000
+#define RXSTS_AM	0x00C00000
+#define RXSTS_OE	0x00100000
+#define RXSTS_FE	0x00080000
+#define RXSTS_RUNT	0x00040000
+#define RXSTS_EDATA	0x00020000
+#define RXSTS_CRCE	0x00010000
+
+#define RXSTS_BI	0x7FFF
+struct rx_sts {			/* Receive Status Queue Entry */
+	__be32	w1;		
+	__be16	fl;		
+	__be16	bi;		/* bi and rfp2 */
+};
+
+#define TXDSC_BL	0x0FFF
+#define TXDSC_AF	0x8000
+#define TXDSC_BI	0x7FFF
+#define TXDSC_EOF	0x8000
+struct tx_dsc {                 /* Transmit Descriptor Queue Entry */
+	__be32	ba;	/*b31-0: physical Buffer Address */
+	__be16	bl_af;	/* Buffer Length, Abort Frame */
+	__be16	bi_eof;	/* Buffer Index, End Of Frame */
+};
+
+#define TXSTS_BI	0x7fff
+#define TXSTS_TXFP	0x80
+#define TXSTS_TXWE	0x40
+#define TXSTS_LCRS	0x10
+#define TXSTS_TXU	0x02
+#define TXSTS_ECOLL	0x01
+
+struct tx_sts {
+	__be16	bi;
+	u8	ncoll;
+	u8	flags;
+};
+
+/*
+ *  Size of device registers occupied in memory/IO address map
+ */
+#define  DEV_REG_SPACE  0x00010000
+
+#endif				/* _EP93xx_ETH_H_ */
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 309eb55..b7e03e3 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -198,6 +198,19 @@ config PCMCIA_PXA2XX
 	help
 	  Say Y here to include support for the PXA2xx PCMCIA controller
 
+config PCMCIA_EP93XX
+	tristate "EP93xx support"
+	depends on ARM && ARCH_EP93XX && PCMCIA
+	help
+	  Say Y here to include support for the EP93xx PCMCIA controller
+
+config PCMCIA_ZEFEEREVBH
+	bool "ZefeerEVB-H support"
+	depends on ARM && ARCH_EP93XX && PCMCIA && PCMCIA_EP93XX && MACH_ZEFEERDZQ
+	help
+	  Say Y here to include support for the PCMCIA interface on 
+	  ZefeerEVB-H board
+
 config PCMCIA_PROBE
 	bool
 	default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index bcecf51..5878b5a 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_HD64465_PCMCIA)			+= hd6446
 obj-$(CONFIG_PCMCIA_SA1100)			+= sa11xx_core.o sa1100_cs.o
 obj-$(CONFIG_PCMCIA_SA1111)			+= sa11xx_core.o sa1111_cs.o
 obj-$(CONFIG_PCMCIA_PXA2XX)                     += pxa2xx_core.o pxa2xx_cs.o
+obj-$(CONFIG_PCMCIA_EP93XX)                     += ep93xx_core.o ep93xx_cs.o
 obj-$(CONFIG_M32R_PCC)				+= m32r_pcc.o
 obj-$(CONFIG_M32R_CFC)				+= m32r_cfc.o
 obj-$(CONFIG_PCMCIA_AU1X00)			+= au1x00_ss.o
@@ -39,6 +40,7 @@ obj-$(CONFIG_OMAP_CF)				+= omap_cf.o
 
 sa11xx_core-y					+= soc_common.o sa11xx_base.o
 pxa2xx_core-y					+= soc_common.o pxa2xx_base.o
+ep93xx_core-y					+= soc_common.o ep93xx_base.o
 
 au1x00_ss-y					+= au1000_generic.o
 au1x00_ss-$(CONFIG_MIPS_PB1000)			+= au1000_pb1x00.o
@@ -69,3 +71,7 @@ pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK)		+= pxa
 pxa2xx_cs-$(CONFIG_MACH_MAINSTONE)		+= pxa2xx_mainstone.o
 pxa2xx_cs-$(CONFIG_PXA_SHARPSL)			+= pxa2xx_sharpsl.o
 
+ep93xx_cs-$(CONFIG_MACH_ADSSPHERE)		+= ep93xx_adssphere.o
+ep93xx_cs-$(CONFIG_MACH_EDB9315)		+= ep93xx_edb9315.o
+ep93xx_cs-$(CONFIG_MACH_DMA03)			+= ep93xx_edb9315.o
+ep93xx_cs-$(CONFIG_PCMCIA_ZEFEEREVBH)			+= ep93xx_zefeerevbh.o
diff --git a/drivers/pcmcia/ep93xx_adssphere.c b/drivers/pcmcia/ep93xx_adssphere.c
new file mode 100644
index 0000000..8e1a181
--- /dev/null
+++ b/drivers/pcmcia/ep93xx_adssphere.c
@@ -0,0 +1,190 @@
+/*
+ * linux/drivers/pcmcia/ep93xx_adssphere.c
+ *
+ * Adapted from pxa27x_mainstone.c
+ *
+ * Robert Whaley 2005 rwhaley@applieddata.net
+ *
+ * Adssphere PCMCIA specific routines.
+ *
+ * Created:	May 12, 2004
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/arch/adssphere.h>
+
+#include "soc_common.h"
+
+static struct pcmcia_irqs irqs[] = {
+	{ 0, IRQ_GPIO1, "CF CD1" },
+	{ 0, IRQ_GPIO2, "CF CD2" },
+	{ 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
+	{ 0, IRQ_GPIO4, "CF SPKR/BVD2" },
+};
+
+
+static int adssphere_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	int rtn;
+
+	if (skt->nr != 0)
+		return -ENXIO;
+
+	skt->irq = IRQ_GPIO6;
+
+	rtn =  soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+	/* enable GPIO6 as interrupt */
+	writel(0x40, GPIO_INTEN);
+
+	/* enable GPIO1-4 and 6 as interrupt */
+	/* Note: 1-4 need to be edge triggered, but
+	   then the irq vectors need to hit GPIOxEIO
+	   which they don't currently do - no big deal
+	   since CD and BVD are polled anyway */
+	/* writel(0x5e, GPIO_INTEN); */
+
+	return rtn;
+}
+
+static void adssphere_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void adssphere_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+				    struct pcmcia_state *state)
+{
+	unsigned long status;
+
+	status = inl(GPIO_PFDR);
+
+	state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
+	state->ready  = (status & PCMCIA_READY)  ? 1 : 0;
+	state->bvd1   = (status & PCMCIA_BVD1)   ? 1 : 0;
+	state->bvd2   = (status & PCMCIA_BVD2)   ? 1 : 0;
+	state->vs_3v  = (status & PCMCIA_VS_3V)  ? 0 : 1;
+	state->vs_Xv  = (status & PCMCIA_VS_XV)  ? 0 : 1;
+	state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
+
+//	printk("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
+}
+
+static int adssphere_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+				       const socket_state_t *state)
+{
+	unsigned long clrbits = 0, setbits = 0, cr0;
+	int ret = 0;
+
+	switch (state->Vcc) {
+	case 0:  {
+		clrbits = ADSSPHERE_CR0_CF_33 | ADSSPHERE_CR0_CF_50;
+		setbits = 0;
+		break;
+	}
+	case 33: {
+		clrbits = ADSSPHERE_CR0_CF_50;
+		setbits = ADSSPHERE_CR0_CF_33;
+		break;
+	}
+	case 50: {
+		clrbits = ADSSPHERE_CR0_CF_33;
+		setbits = ADSSPHERE_CR0_CF_50;
+		break;
+	}
+	default:
+		 printk(KERN_ERR "%s(): bad Vcc %u\n",
+				 __FUNCTION__, state->Vcc);
+		 ret = -1;
+	}
+
+	if (!ret && skt->nr == 0) {
+		cr0 = inl(ADSSPHERE_CR0);
+		cr0 &= ~clrbits;
+		cr0 |=  setbits;
+		writel(cr0, ADSSPHERE_CR0);
+
+		if (state->flags & SS_RESET) {
+			/* see EP93xx User's Guide */
+			writel(0x15, PCMCIACNT);
+		} else {
+			/* CF mode -  BIT1 for PCMCIA mode */
+			writel(0x11, PCMCIACNT);
+		}
+	}
+
+	return ret;
+}
+
+static void adssphere_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void adssphere_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level adssphere_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+	.hw_init		= adssphere_pcmcia_hw_init,
+	.hw_shutdown		= adssphere_pcmcia_hw_shutdown,
+	.socket_state		= adssphere_pcmcia_socket_state,
+	.configure_socket	= adssphere_pcmcia_configure_socket,
+	.socket_init		= adssphere_pcmcia_socket_init,
+	.socket_suspend		= adssphere_pcmcia_socket_suspend,
+	.nr			= 1,
+};
+
+static struct platform_device *adssphere_pcmcia_device;
+
+static int __init adssphere_pcmcia_init(void)
+{
+	int ret;
+
+	adssphere_pcmcia_device = kmalloc(sizeof(*adssphere_pcmcia_device), GFP_KERNEL);
+	if (!adssphere_pcmcia_device)
+		return -ENOMEM;
+	memset(adssphere_pcmcia_device, 0, sizeof(*adssphere_pcmcia_device));
+	adssphere_pcmcia_device->name = "ep93xx-pcmcia";
+	adssphere_pcmcia_device->dev.platform_data = &adssphere_pcmcia_ops;
+
+	ret = platform_device_register(adssphere_pcmcia_device);
+	if (ret)
+		kfree(adssphere_pcmcia_device);
+
+	return ret;
+}
+
+static void __exit adssphere_pcmcia_exit(void)
+{
+	/*
+	 * This call is supposed to free our adssphere_pcmcia_device.
+	 * Unfortunately platform_device don't have a free method, and
+	 * we can't assume it's free of any reference at this point so we
+	 * can't free it either.
+	 */
+	platform_device_unregister(adssphere_pcmcia_device);
+}
+
+module_init(adssphere_pcmcia_init);
+module_exit(adssphere_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/ep93xx_base.c b/drivers/pcmcia/ep93xx_base.c
new file mode 100644
index 0000000..2377989
--- /dev/null
+++ b/drivers/pcmcia/ep93xx_base.c
@@ -0,0 +1,190 @@
+/*======================================================================
+
+  Device driver for the PCMCIA control functionality of EP93xx
+  microprocessors.  Derived from pxa2xx_base.c
+
+    The contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL")
+
+    (c) Ian Molton (spyro@f2s.com) 2003
+    (c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4
+    (c) Robert Whaley (rwhaley@applieddata.net) 2005
+
+    derived from sa11xx_base.c
+
+     Portions created by John G. Dorsey are
+     Copyright (C) 1999 John G. Dorsey.
+
+  ======================================================================*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+
+#include "cs_internal.h"
+#include "soc_common.h"
+
+#define MIN(a,b)	((a)>(b) ? (b) : (a))
+
+#define MCXX_SETUP_MAX     0xff
+#define MCXX_ASST_MAX      0xff
+#define MCXX_HOLD_MAX      0x0f
+
+#define MCXX_SETUP_SHIFT   0
+#define MCXX_ASST_SHIFT    16
+#define MCXX_HOLD_SHIFT    8
+
+
+
+static inline u_int ep93xx_mcxx_hold(u_int pcmcia_cycle_ns,
+				     u_int hclk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * hclk_10khz;
+	return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
+}
+
+static inline u_int ep93xx_mcxx_asst(u_int pcmcia_cycle_ns,
+				     u_int hclk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * hclk_10khz;
+	return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
+}
+
+static inline u_int ep93xx_mcxx_setup(u_int pcmcia_cycle_ns,
+				      u_int hclk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * hclk_10khz;
+	return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
+}
+
+static int ep93xx_pcmcia_set_mcmem( int sock, int speed, int clock )
+{
+        writel(PC16BITSWIDE
+	     | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
+	     | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
+	     | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
+	     PC1COMMON);
+
+	return 0;
+}
+
+static int ep93xx_pcmcia_set_mcio( int sock, int speed, int clock )
+{
+        writel(PC16BITSWIDE
+	     | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
+	     | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
+	     | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
+	     PC1IO);
+
+	return 0;
+}
+
+static int ep93xx_pcmcia_set_mcatt( int sock, int speed, int clock )
+{
+        writel(PC16BITSWIDE
+	     | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
+	     | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
+	     | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
+	     PC1ATTRIB);
+
+	return 0;
+}
+
+static int ep93xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int clk)
+{
+	struct soc_pcmcia_timing timing;
+	int sock = skt->nr;
+
+	soc_common_pcmcia_get_timing(skt, &timing);
+
+	ep93xx_pcmcia_set_mcmem(sock, timing.mem, clk);
+	ep93xx_pcmcia_set_mcatt(sock, timing.attr, clk);
+	ep93xx_pcmcia_set_mcio(sock, timing.io, clk);
+
+	return 0;
+}
+
+static int ep93xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
+{
+	unsigned int hclk = 10000; /* for now just hard code hclk to 100Mhz (in 10khz units)*/
+	return ep93xx_pcmcia_set_mcxx(skt, hclk);
+}
+
+int ep93xx_drv_pcmcia_probe(struct device *dev)
+{
+	int ret;
+	struct pcmcia_low_level *ops;
+	int first, nr;
+
+	if (!dev || !dev->platform_data)
+		return -ENODEV;
+
+	ops = (struct pcmcia_low_level *)dev->platform_data;
+	first = ops->first;
+	nr = ops->nr;
+
+	/* Provide our EP93xx specific timing routines. */
+	ops->set_timing  = ep93xx_pcmcia_set_timing;
+
+	ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr);
+
+	return ret;
+}
+EXPORT_SYMBOL(ep93xx_drv_pcmcia_probe);
+
+static int ep93xx_drv_pcmcia_suspend(struct device *dev, u32 state, u32 level)
+{
+	int ret = 0;
+	if (level == SUSPEND_SAVE_STATE)
+		ret = pcmcia_socket_dev_suspend(dev, state);
+	return ret;
+}
+
+static int ep93xx_drv_pcmcia_resume(struct device *dev, u32 level)
+{
+	int ret = 0;
+	if (level == RESUME_RESTORE_STATE)
+	{
+		ret = pcmcia_socket_dev_resume(dev);
+	}
+	return ret;
+}
+
+static struct device_driver ep93xx_pcmcia_driver = {
+	.probe		= ep93xx_drv_pcmcia_probe,
+	.remove		= soc_common_drv_pcmcia_remove,
+	.suspend 	= ep93xx_drv_pcmcia_suspend,
+	.resume 	= ep93xx_drv_pcmcia_resume,
+	.name		= "ep93xx-pcmcia",
+	.bus		= &platform_bus_type,
+};
+
+static int __init ep93xx_pcmcia_init(void)
+{
+	return driver_register(&ep93xx_pcmcia_driver);
+}
+
+static void __exit ep93xx_pcmcia_exit(void)
+{
+	driver_unregister(&ep93xx_pcmcia_driver);
+}
+
+module_init(ep93xx_pcmcia_init);
+module_exit(ep93xx_pcmcia_exit);
+
+MODULE_AUTHOR("Robert Whaley (whaley@applieddata.net)");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services: EP93xx core socket driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/ep93xx_edb9315.c b/drivers/pcmcia/ep93xx_edb9315.c
new file mode 100644
index 0000000..519fc8d
--- /dev/null
+++ b/drivers/pcmcia/ep93xx_edb9315.c
@@ -0,0 +1,283 @@
+/*
+ * linux/drivers/pcmcia/ep93xx_edb9315.c
+ *
+ * Adapted from pxa27x_mainstone.c
+ *
+ * Edb9315 PCMCIA specific routines.
+ *
+ * Created:	May 12, 2004
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/arch/edb9315.h>
+
+#include "soc_common.h"
+
+static struct pcmcia_irqs irqs[] = {
+	{ 0, IRQ_GPIO1, "CF CD1" },
+	{ 0, IRQ_GPIO2, "CF CD2" },
+	{ 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
+	{ 0, IRQ_GPIO4, "CF SPKR/BVD2" },
+};
+
+
+static int edb9315_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	int rtn;
+
+	if (skt->nr == 0)
+		return -ENXIO;
+
+	skt->irq = IRQ_GPIO6;
+
+	rtn =  soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+	/* enable GPIO6 as interrupt */
+	writel(0x40, GPIO_INTEN);
+
+	/* enable GPIO1-4 and 6 as interrupt */
+	/* Note: 1-4 need to be edge triggered, but
+	   then the irq vectors need to hit GPIOxEIO
+	   which they don't currently do - no big deal
+	   since CD and BVD are polled anyway */
+	/* writel(0x5e, GPIO_INTEN); */
+
+	return rtn;
+}
+
+static void edb9315_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void edb9315_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+				    struct pcmcia_state *state)
+{
+	unsigned long status;
+
+	status = inl(GPIO_PFDR);
+
+	state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
+	state->ready  = (status & PCMCIA_READY)  ? 1 : 0;
+	state->bvd1   = (status & PCMCIA_BVD1)   ? 1 : 0;
+	state->bvd2   = (status & PCMCIA_BVD2)   ? 1 : 0;
+	state->vs_3v  = (status & PCMCIA_VS_3V)  ? 0 : 1;
+	state->vs_Xv  = (status & PCMCIA_VS_XV)  ? 0 : 1;
+	state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
+
+//	printk("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
+}
+
+/*
+ * We bit-bang the pcmcia power controller using this function.
+ */
+static void ep93xx_bitbang( unsigned long ulNewEEValue )
+{
+	unsigned long ulGdata;
+
+	ulGdata = inl( GPIO_PGDR );
+
+	ulGdata &= ~(GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0);
+
+	ulNewEEValue &= (GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0);
+
+	ulGdata |= ulNewEEValue;
+
+	outl( ulGdata, GPIO_PGDR );
+	ulGdata = inl( GPIO_PGDR ); // read to push write out wrapper
+
+	// Voltage controller's data sheet says minimum pulse width is
+	// one microsecond.
+	udelay(5);
+}
+
+static int
+ep93xx_set_voltage( u_short sock, u_char NewVcc )
+{
+	struct socket_info_t * skt = &socket_info[sock];
+	unsigned long ulSwitchSettings, ulDataBit, ulGdirection;
+	int       i;
+
+	if (sock >= EP93XX_MAX_SOCK)
+		return -EINVAL;
+
+	if( skt->Vcc == NewVcc ){
+		DEBUG(3, "Power already set to %d\n", NewVcc );
+		return 0;
+	}
+
+	ulSwitchSettings = EE_ADDRESS | ENABLE;
+	switch( NewVcc )
+	{
+		case 0:
+			DEBUG(3, "Configure the socket for 0 Volts\n");
+			ulSwitchSettings |= AVCC_0V;
+			break;
+
+		case 50:
+			ulSwitchSettings |= AVCC_5V;
+			DEBUG(3, "Configure the socket for 5 Volts\n");
+			break;
+
+		case 33:
+			DEBUG(3, "Configure the socket for 3.3 Volts\n");
+			ulSwitchSettings |= AVCC_33V;
+			break;
+
+		default:
+			printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+				NewVcc);
+			return -1;
+	}
+
+	//
+	// Configure the proper GPIO pins as outputs.
+	//
+	ep93xx_bitbang( GPIOA_EECLK | GPIOA_EEDAT );
+
+	//
+	// Read modify write the data direction register, set the
+	// proper lines to be outputs.
+	//
+	ulGdirection = inl( GPIO_PGDDR );
+	ulGdirection |= GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0;
+	outl( ulGdirection, GPIO_PGDDR );
+	ulGdirection = inl( GPIO_PGDDR ); // read to push write out wrapper
+
+	//
+	// Clear all except EECLK
+	// Lower the clock.
+	//
+	ep93xx_bitbang( GPIOA_EECLK );
+	ep93xx_bitbang( 0 );
+
+	//
+	// Serial shift the command word out to the voltage controller.
+	//
+	for( i=18 ; i>=0 ; --i )
+	{
+		if( (ulSwitchSettings >> i) & 0x1 )
+			ulDataBit = GPIOA_EEDAT;
+		else
+			ulDataBit = 0;
+
+		//
+		// Put the data on the bus and lower the clock.
+		// Raise the clock to latch the data in.
+		// Lower the clock again.
+		//
+		ep93xx_bitbang( ulDataBit );
+		ep93xx_bitbang( ulDataBit | GPIOA_EECLK );
+		ep93xx_bitbang( ulDataBit );
+	}
+
+	//
+	// Raise and lower the Latch.
+	// Raise EECLK, delay, raise EEDAT, leave them that way.
+	//
+	ep93xx_bitbang( GPIOA_SLA0 );
+	ep93xx_bitbang( 0 );
+	ep93xx_bitbang( GPIOA_EECLK );
+	ep93xx_bitbang( GPIOA_EECLK | GPIOA_EEDAT );
+
+	skt->Vcc = NewVcc;
+
+	DEBUG(3, "ep93xx_set_voltage - exit\n");
+
+	return 0;
+}
+
+static int edb9315_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+				       const socket_state_t *state)
+{
+	unsigned long clrbits = 0, setbits = 0, cr0;
+	int ret = 0;
+
+	ep93xx_set_voltage(skt->nr, state->Vxx);
+
+	if (!ret && skt->nr == 0) {
+
+		if (state->flags & SS_RESET) {
+			/* see EP93xx User's Guide */
+			writel(0x15, PCMCIACNT);
+		} else {
+			/* CF mode -  BIT1 for PCMCIA mode */
+			writel(0x11, PCMCIACNT);
+		}
+	}
+
+	return ret;
+}
+
+static void edb9315_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void edb9315_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level edb9315_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+	.hw_init		= edb9315_pcmcia_hw_init,
+	.hw_shutdown		= edb9315_pcmcia_hw_shutdown,
+	.socket_state		= edb9315_pcmcia_socket_state,
+	.configure_socket	= edb9315_pcmcia_configure_socket,
+	.socket_init		= edb9315_pcmcia_socket_init,
+	.socket_suspend		= edb9315_pcmcia_socket_suspend,
+	.nr			= 1,
+};
+
+static struct platform_device *edb9315_pcmcia_device;
+
+static int __init edb9315_pcmcia_init(void)
+{
+	int ret;
+
+	edb9315_pcmcia_device = kmalloc(sizeof(*edb9315_pcmcia_device), GFP_KERNEL);
+	if (!edb9315_pcmcia_device)
+		return -ENOMEM;
+	memset(edb9315_pcmcia_device, 0, sizeof(*edb9315_pcmcia_device));
+	edb9315_pcmcia_device->name = "ep93xx-pcmcia";
+	edb9315_pcmcia_device->dev.platform_data = &edb9315_pcmcia_ops;
+
+	ret = platform_device_register(edb9315_pcmcia_device);
+	if (ret)
+		kfree(edb9315_pcmcia_device);
+
+	return ret;
+}
+
+static void __exit edb9315_pcmcia_exit(void)
+{
+	/*
+	 * This call is supposed to free our edb9315_pcmcia_device.
+	 * Unfortunately platform_device don't have a free method, and
+	 * we can't assume it's free of any reference at this point so we
+	 * can't free it either.
+	 */
+	platform_device_unregister(edb9315_pcmcia_device);
+}
+
+module_init(edb9315_pcmcia_init);
+module_exit(edb9315_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/ep93xx_zefeerevbh.c b/drivers/pcmcia/ep93xx_zefeerevbh.c
new file mode 100644
index 0000000..44d44ed
--- /dev/null
+++ b/drivers/pcmcia/ep93xx_zefeerevbh.c
@@ -0,0 +1,175 @@
+/*
+ * linux/drivers/pcmcia/ep93xx_zefeerevbh.c
+ *
+ * Adapted from ep93xx_zefeerevbh.c
+ *
+ *
+ * ZefeerEVB-H PCMCIA specific routines.
+ *
+ * Copyright:	DAVE Srl <www.dave-tech.it>
+ *
+ * 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/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/arch/zefeerevb.h>
+
+#include "soc_common.h"
+
+#if 0
+#define DPRINTK(fmt, args...) printk( "[%s:] \n" fmt, __FUNCTION__, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static struct pcmcia_irqs irqs[] = {
+	{ 0, IRQ_GPIO1, "CF CD1" },
+	{ 0, IRQ_GPIO2, "CF CD2" },
+	{ 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
+	{ 0, IRQ_GPIO4, "CF SPKR/BVD2" },
+};
+
+
+static int zefeerevbh_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	int rtn;
+	unsigned long tmp;
+
+	if (skt->nr != 0)
+		return -ENXIO;
+
+	/* Set interrupt lines as input */
+	tmp = readl(GPIO_PFDDR);
+	tmp = (tmp & (~((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 6))));
+	writel(tmp, GPIO_PFDDR);
+		
+	skt->irq = IRQ_GPIO6;
+
+	rtn =  soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+	/* enable GPIO6 as interrupt */
+	writel(0x40, GPIO_INTEN);
+
+	/* enable GPIO1-4 and 6 as interrupt */
+	/* Note: 1-4 need to be edge triggered, but
+	   then the irq vectors need to hit GPIOxEIO
+	   which they don't currently do - no big deal
+	   since CD and BVD are polled anyway */
+	/* writel(0x5e, GPIO_INTEN); */
+
+	return rtn;
+}
+
+static void zefeerevbh_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void zefeerevbh_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+				    struct pcmcia_state *state)
+{
+	unsigned long status;
+
+	status = inl(GPIO_PFDR);
+
+	state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
+	state->ready  = (status & PCMCIA_READY)  ? 1 : 0;
+	state->bvd1   = (status & PCMCIA_BVD1)   ? 1 : 0;
+	state->bvd2   = (status & PCMCIA_BVD2)   ? 1 : 0;
+	state->vs_3v  = (status & PCMCIA_VS_3V)  ? 0 : 1;
+	state->vs_Xv  = (status & PCMCIA_VS_XV)  ? 0 : 1;
+	state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
+
+	DPRINTK("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
+}
+
+static int zefeerevbh_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+				       const socket_state_t *state)
+{
+
+	printk(KERN_INFO "[%s]: Vcc = %u, Vpp = %u\n", __FUNCTION__, state->Vcc, state->Vpp);
+	
+	/* By default power handling is managed by external controller automatically */
+
+	if (skt->nr == 0) {
+		if (state->flags & SS_RESET) {
+			/* see EP93xx User's Guide */
+			writel(0x15, PCMCIACNT);
+		} else {
+			/* CF mode -  BIT1 for PCMCIA mode */
+			writel(0x11, PCMCIACNT);
+		}
+	}
+
+
+	return 0;
+}
+
+static void zefeerevbh_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void zefeerevbh_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level zefeerevbh_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+	.hw_init		= zefeerevbh_pcmcia_hw_init,
+	.hw_shutdown		= zefeerevbh_pcmcia_hw_shutdown,
+	.socket_state		= zefeerevbh_pcmcia_socket_state,
+	.configure_socket	= zefeerevbh_pcmcia_configure_socket,
+	.socket_init		= zefeerevbh_pcmcia_socket_init,
+	.socket_suspend		= zefeerevbh_pcmcia_socket_suspend,
+	.nr			= 1,
+};
+
+static struct platform_device *zefeerevbh_pcmcia_device;
+
+static int __init zefeerevbh_pcmcia_init(void)
+{
+	int ret;
+
+	zefeerevbh_pcmcia_device = kmalloc(sizeof(*zefeerevbh_pcmcia_device), GFP_KERNEL);
+	if (!zefeerevbh_pcmcia_device)
+		return -ENOMEM;
+	memset(zefeerevbh_pcmcia_device, 0, sizeof(*zefeerevbh_pcmcia_device));
+	zefeerevbh_pcmcia_device->name = "ep93xx-pcmcia";
+	zefeerevbh_pcmcia_device->dev.platform_data = &zefeerevbh_pcmcia_ops;
+
+	ret = platform_device_register(zefeerevbh_pcmcia_device);
+	if (ret)
+		kfree(zefeerevbh_pcmcia_device);
+
+	return ret;
+}
+
+static void __exit zefeerevbh_pcmcia_exit(void)
+{
+	/*
+	 * This call is supposed to free our zefeerevbh_pcmcia_device.
+	 * Unfortunately platform_device don't have a free method, and
+	 * we can't assume it's free of any reference at this point so we
+	 * can't free it either.
+	 */
+	platform_device_unregister(zefeerevbh_pcmcia_device);
+}
+
+module_init(zefeerevbh_pcmcia_init);
+module_exit(zefeerevbh_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 812bae6..15bfa5d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -289,6 +289,25 @@ config SERIAL_CLPS711X_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+config SERIAL_EP93XX
+	tristate "EP93XX serial port support"
+	depends on ARM && ARCH_EP93XX
+	select SERIAL_CORE
+	help
+	  Support for the serial ports included in the EP93xx CPU SOC.
+
+config SERIAL_EP93XX_CONSOLE
+	bool "Support for console on EP93XX serial port"
+	depends on SERIAL_EP93XX=y
+	select SERIAL_CORE_CONSOLE
+	help
+	  Even if you say Y here, the currently visible virtual console
+	  (/dev/tty0) will still be used as the system console by default, but
+	  you can alter that using a kernel command line option such as
+	  "console=ttyCL1". (Try "man bootparam" or see the documentation of
+	  your boot loader (lilo or loadlin) about how to pass options to the
+	  kernel at boot time.)
+
 config SERIAL_S3C2410
 	tristate "Samsung S3C2410 Serial port support"
 	depends on ARM && ARCH_S3C2410
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index d7c7c71..ef074dc 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250
 obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
+obj-$(CONFIG_SERIAL_EP93XX) += ep93xx.o
 obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
diff --git a/drivers/serial/ep93xx.c b/drivers/serial/ep93xx.c
new file mode 100644
index 0000000..60f91a6
--- /dev/null
+++ b/drivers/serial/ep93xx.c
@@ -0,0 +1,863 @@
+/*
+ *  drivers/serial/ep93xx.c
+ *
+ *  Driver for EP93xx serial ports
+ *
+ *  Based on drivers/serial/amba-pl011.c
+ *
+ *  Copyright 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *
+ * 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
+ *
+ *  $Id: ep93xx.c,v 1.42 2002/07/28 10:03:28 rmk Exp $
+ *
+ */
+
+/* todo:
+ *  - correct major/minor numbers
+ *  - implement request/release/verify port
+ *  - from /dev/ttyAM0, 'stty -F /dev/ttyAM1 57600' not working right.
+ *    looks like it changes the divisor, but it gets changed back as
+ *    soon as you enter a char on /dev/ttyAM1.
+ *  - do not enable modem status ints unless HW is setup
+ *  - do not return modem status unless HW is setup
+ *  - figure out a nice way to handle CL0 HDLC/modem, CL1 SIR IrDA,
+ *    and CL2 HDLC/RS485
+ *  - UART DMA operation?
+ *  - handle icount fields rng and buf_overrun?
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/device.h>
+#include <linux/sysrq.h>
+#include <linux/console.h>
+#include <linux/serial.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware/amba.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/clocks.h>
+
+#if defined(CONFIG_SERIAL_EP93XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#if defined(CONFIG_ARCH_EP9312) || defined(CONFIG_ARCH_EP9315)
+#define UART_NR		3
+#else
+#define UART_NR		2
+#endif
+
+#define SERIAL_EP93XX_MAJOR	204
+#define SERIAL_EP93XX_MINOR	16
+
+#define ISR_PASS_LIMIT 256
+
+#define REG(port,name)	((port)->membase + (name) - EP93XX_APB_BASE - UART1_OFFSET)
+
+#define UARTDR(port)	REG(port,UART1DR)
+#define UARTCR(port)	REG(port,UART1CR)
+#define UARTFR(port)	REG(port,UART1FR)
+#define UARTRSR(port)	REG(port,UART1RSR)
+#define UARTECR(port)	REG(port,UART1ECR)
+#define UARTMCR(port)	REG(port,UART1MCR)
+#define UARTMSR(port)	REG(port,UART1MSR)
+#define UARTIIR(port)	REG(port,UART1IIR)
+#define UARTICR(port)	REG(port,UART1ICR)
+#define UARTLCH(port)	REG(port,UART1CR_H)
+#define UARTLCM(port)	REG(port,UART1CR_M)
+#define UARTLCL(port)	REG(port,UART1CR_L)
+
+#define UARTRSR_CREAD 0x100
+
+static void enable_clocks(struct uart_port *port)
+{
+	unsigned int devcfg = readl(SYSCON_DEVCFG);
+
+	switch (port->line) {
+	case 0:
+		devcfg |= SYSCON_DEVCFG_U1EN;
+		devcfg &= ~SYSCON_DEVCFG_MonG;	/* handle this better... */
+		break;
+	case 1:
+		devcfg |= SYSCON_DEVCFG_U2EN;
+		break;
+	case 2:
+		devcfg |= SYSCON_DEVCFG_U3EN;
+		break;
+	}
+
+	SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(devcfg));
+}
+
+static void disable_clocks(struct uart_port *port)
+{
+	unsigned int devcfg = readl(SYSCON_DEVCFG);
+
+	switch (port->line) {
+	case 0:
+		devcfg &= ~SYSCON_DEVCFG_U1EN;
+		break;
+	case 1:
+		devcfg &= ~SYSCON_DEVCFG_U2EN;
+		break;
+	case 2:
+		devcfg &= ~SYSCON_DEVCFG_U3EN;
+		break;
+	}
+
+	SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(devcfg));
+}
+
+static int is_port_enabled(struct uart_port *port)
+{
+	unsigned int devcfg = readl(SYSCON_DEVCFG);
+
+	switch (port->line) {
+	case 0:
+		devcfg &= SYSCON_DEVCFG_U1EN;
+		break;
+	case 1:
+		devcfg &= SYSCON_DEVCFG_U2EN;
+		break;
+	case 2:
+		devcfg &= SYSCON_DEVCFG_U3EN;
+		break;
+	}
+
+	return devcfg ? 1 : 0;
+}
+
+static void ep93xxuart_stop_tx(struct uart_port *port)
+{
+	unsigned long cr = readl(UARTCR(port));
+	cr &= ~UARTCR_TIE;
+	writel(cr, UARTCR(port));
+}
+
+static void ep93xxuart_start_tx(struct uart_port *port)
+{
+	unsigned long cr = readl(UARTCR(port));
+	cr |= UARTCR_TIE;
+	writel(cr, UARTCR(port));
+}
+
+static void ep93xxuart_stop_rx(struct uart_port *port)
+{
+	unsigned long cr = readl(UARTCR(port));
+	cr &= ~(UARTCR_RIE | UARTCR_RTIE);
+	writel(cr, UARTCR(port));
+}
+
+static void ep93xxuart_enable_ms(struct uart_port *port)
+{
+	/* fixme: add an ms mask to a wrapper port struct */
+	if (port->line == 0) {
+		unsigned long cr = readl(UARTCR(port));
+		cr |= UARTCR_MSIE;
+		writel(cr, UARTCR(port));
+	}
+}
+
+#ifdef SUPPORT_SYSRQ
+static void ep93xxuart_rx_chars(struct uart_port *port, struct pt_regs *regs)
+#else
+static void ep93xxuart_rx_chars(struct uart_port *port)
+#endif
+{
+	struct tty_struct *tty = port->info->tty;
+	unsigned long fifo, chr, stat, flg;
+	unsigned int count = 256;
+
+	fifo = readl(UARTFR(port));
+	while (((fifo & UARTFR_RXFE) == 0) && count--) {
+
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+			tty->flip.work.func((void *)tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
+				return;
+			}
+		}
+
+		chr = readl(UARTDR(port));
+		flg = TTY_NORMAL;
+
+		port->icount.rx++;
+
+		stat = readl(UARTRSR(port)) | UARTRSR_CREAD;
+
+		if (stat & (UARTRSR_FE | UARTRSR_PE | UARTRSR_OE | UARTRSR_BE)) {
+
+			writel(0, UARTECR(port));
+
+			if (stat & UARTRSR_BE) {
+				stat &= ~(UARTRSR_PE | UARTRSR_FE);
+				port->icount.brk++;
+				if (uart_handle_break(port))
+					goto ignore_char;
+			} else if (stat & UARTRSR_PE) {
+				port->icount.parity++;
+			} else if (stat & UARTRSR_FE) {
+				port->icount.frame++;
+			}
+
+			if (stat & UARTRSR_OE)
+				port->icount.overrun++;
+
+			stat &= port->read_status_mask;
+
+			if (stat & UARTRSR_BE)
+				flg = TTY_BREAK;
+			else if (stat & UARTRSR_PE)
+				flg = TTY_PARITY;
+			else if (stat & UARTRSR_FE)
+				flg = TTY_FRAME;
+		}
+
+		if (uart_handle_sysrq_char(port, chr, regs))
+			goto ignore_char;
+
+		if ((stat & port->ignore_status_mask) == 0) {
+			*tty->flip.flag_buf_ptr++ = flg;
+			*tty->flip.char_buf_ptr++ = chr;
+			tty->flip.count++;
+		}
+
+		if ((stat & UARTRSR_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) {
+			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+			*tty->flip.char_buf_ptr++ = 0;
+			tty->flip.count++;
+		}
+
+	      ignore_char:
+		fifo = readl(UARTFR(port));
+	}
+	tty_flip_buffer_push(tty);
+}
+
+static void ep93xxuart_tx_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->info->xmit;
+	int count;
+
+	if (port->x_char) {
+		writel(port->x_char, UARTDR(port));
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		ep93xxuart_stop_tx(port);
+		return;
+	}
+
+	count = port->fifosize >> 1;
+	do {
+		writel(xmit->buf[xmit->tail], UARTDR(port));
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (--count > 0);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		ep93xxuart_stop_tx(port);
+}
+
+static void ep93xxuart_modem_status(struct uart_port *port)
+{
+	unsigned int status = readl(UARTFR(port));
+
+	writel(0, UARTICR(port));
+
+	if (status & UARTMSR_DDCD)
+		uart_handle_dcd_change(port, status & UARTMSR_DCD);
+
+	if (status & UARTMSR_DDSR)
+		port->icount.dsr++;
+
+	if (status & UARTMSR_DCTS)
+		uart_handle_cts_change(port, status & UARTMSR_CTS);
+
+	if (status & (UARTMSR_DDCD | UARTMSR_DDSR | UARTMSR_DCTS))
+		wake_up_interruptible(&port->info->delta_msr_wait);
+}
+
+static irqreturn_t ep93xxuart_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = dev_id;
+	unsigned int pass_counter = ISR_PASS_LIMIT;
+	int handled = 0;
+	unsigned long iir;
+
+	spin_lock(&port->lock);
+
+	iir = readl(UARTIIR(port));
+
+	if (iir) {
+		do {
+			if (iir & (UARTIIR_RIS | UARTIIR_RTIS))
+#ifdef SUPPORT_SYSRQ
+				ep93xxuart_rx_chars(port, regs);
+#else
+				ep93xxuart_rx_chars(port);
+#endif
+			if (iir & UARTIIR_TIS)
+				ep93xxuart_tx_chars(port);
+			if (iir & UARTIIR_MIS)
+				ep93xxuart_modem_status(port);
+
+			if (pass_counter-- == 0)
+				break;
+
+			iir = readl(UARTIIR(port));
+
+		} while (iir &
+			 (UARTIIR_RIS | UARTIIR_RTIS | UARTIIR_TIS |
+			  UARTIIR_MIS));
+		handled = 1;
+	}
+
+	spin_unlock(&port->lock);
+
+	return IRQ_RETVAL(handled);
+}
+
+static unsigned int ep93xxuart_tx_empty(struct uart_port *port)
+{
+	unsigned long status = readl(UARTFR(port));
+	return status & UARTFR_TXFE ? 0 : TIOCSER_TEMT;	/* FIXME: klaus used UARTFR_BUSY? */
+}
+
+static unsigned int ep93xxuart_get_mctrl(struct uart_port *port)
+{
+	unsigned int result = 0;
+
+	/* fixme: use a wrapper struct w/ ms flags */
+	if (port->line == 0) {
+		unsigned int msr = readl(UARTMSR(port));
+		if (msr & UARTMSR_CTS)
+			result |= TIOCM_CTS;
+		if (msr & UARTMSR_DSR)
+			result |= TIOCM_DSR;
+		if (msr & UARTMSR_RI)
+			result |= TIOCM_RI;
+		if (msr & UARTMSR_DCD)
+			result |= TIOCM_CAR;
+	}
+	return result;
+}
+
+static void ep93xxuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	unsigned long mcr;
+
+	if (port->line == 0) {
+		mcr = readl(UARTMCR(port));
+		if (mctrl & TIOCM_RTS)
+			mcr |= UARTMCR_RTS;
+		else
+			mcr &= ~UARTMCR_RTS;
+		if (mctrl & TIOCM_DTR)
+			mcr |= UARTMCR_DTR;
+		else
+			mcr &= ~UARTMCR_DTR;
+		if (mctrl & TIOCM_OUT1)
+			mcr |= UARTMCR_OUT1;
+		else
+			mcr &= ~UARTMCR_OUT1;
+		if (mctrl & TIOCM_OUT2)
+			mcr |= UARTMCR_OUT2;
+		else
+			mcr &= ~UARTMCR_OUT2;
+		writel(mcr, UARTMCR(port));
+	}
+}
+
+/* FIXME: klaus grabbed the &port->lock spinlock here.. */
+static void ep93xxuart_break_ctl(struct uart_port *port, int break_state)
+{
+	unsigned long lch;
+
+	lch = readl(UARTLCH(port));
+	if (break_state)
+		lch |= UARTLCR_H_BRK;
+	else
+		lch &= ~UARTLCR_H_BRK;
+	writel(lch, UARTLCH(port));
+}
+
+static int ep93xxuart_startup(struct uart_port *port)
+{
+	unsigned int uartcr;
+	int retval;
+
+	retval = request_irq(port->irq, ep93xxuart_int, 0, "ep93xxuart", port);
+	if (retval)
+		return retval;
+
+	enable_clocks(port);
+
+	uartcr = readl(UARTCR(port));
+	uartcr |= UARTCR_UARTE | UARTCR_RIE | UARTCR_RTIE;
+	uartcr &= ~0x6;
+	writel(uartcr, UARTCR(port));
+
+	return 0;
+}
+
+static void ep93xxuart_shutdown(struct uart_port *port)
+{
+	unsigned int uartcr;
+	unsigned int linectl;
+
+	linectl = readl(UARTLCH(port));
+	linectl &= ~(UARTLCR_H_FEN | UARTLCR_H_BRK);
+	writel(linectl, UARTLCH(port));
+
+	uartcr = readl(UARTCR(port));
+	uartcr &= ~(UARTCR_UARTE | UARTCR_RIE | UARTCR_RTIE | UARTCR_TIE);
+	writel(uartcr, UARTCR(port));
+
+	disable_clocks(port);
+
+	free_irq(port->irq, port);
+}
+
+static void
+ep93xxuart_set_termios(struct uart_port *port, struct termios *termios,
+		       struct termios *old)
+{
+	unsigned int baud, quot;
+	unsigned long flags;
+	unsigned long lch;
+
+	/* wait for fifo to drain.. is this needed? upper level should handle it.. */
+	if (is_port_enabled(port))
+		do {
+			flags = readl(UARTFR(port));
+		} while (flags & UARTFR_BUSY);
+
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+	quot = uart_get_divisor(port, baud);
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		lch = UARTLCR_H_WLEN_5_DATA;
+		break;
+	case CS6:
+		lch = UARTLCR_H_WLEN_6_DATA;
+		break;
+	case CS7:
+		lch = UARTLCR_H_WLEN_7_DATA;
+		break;
+	default:
+		lch = UARTLCR_H_WLEN_8_DATA;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		lch |= UARTLCR_H_STP2;
+
+	if (termios->c_cflag & PARENB) {
+		lch |= UARTLCR_H_PEN;
+		if (!(termios->c_cflag & PARODD))
+			lch |= UARTLCR_H_EPS;
+	}
+
+	if (port->fifosize > 1)
+		lch |= UARTLCR_H_FEN;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	lch |= readl(UARTLCH(port)) & UARTLCR_H_BRK;
+
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	port->read_status_mask = UARTRSR_OE;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= UARTRSR_FE | UARTRSR_PE;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= UARTRSR_BE;
+
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= UARTRSR_FE | UARTRSR_PE;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= UARTRSR_BE;
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= UARTRSR_OE;
+	}
+	if ((termios->c_cflag & CREAD) == 0)
+		port->ignore_status_mask |= UARTRSR_CREAD;
+
+	quot -= 1;
+
+	writel(quot & 0xff, UARTLCL(port));
+	writel((quot >> 8) & 0xff, UARTLCM(port));
+	writel(lch, UARTLCH(port));
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *ep93xxuart_type(struct uart_port *port)
+{
+	return port->type == PORT_EP93XX ? "uart-ep93xx" : NULL;
+}
+
+static void ep93xxuart_release_port(struct uart_port *port)
+{
+	/* update when we break up static io_desc maps */
+}
+
+static int ep93xxuart_request_port(struct uart_port *port)
+{
+	/* update when we break up static io_desc maps */
+	return 0;
+}
+
+static void ep93xxuart_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		if (ep93xxuart_request_port(port) == 0)
+			port->type = PORT_EP93XX;
+
+	/* FIXME: handle UART_CONFIG_IRQ? */
+}
+
+static int ep93xxuart_verify_port(struct uart_port *port,
+				  struct serial_struct *ser)
+{
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_EP93XX)
+		return -EINVAL;
+	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+		return -EINVAL;
+	if (ser->baud_base < 9600)
+		return -EINVAL;
+	return 0;
+}
+
+static struct uart_ops ep93xx_pops = {
+	.tx_empty = ep93xxuart_tx_empty,
+	.set_mctrl = ep93xxuart_set_mctrl,
+	.get_mctrl = ep93xxuart_get_mctrl,
+	.stop_tx = ep93xxuart_stop_tx,
+	.start_tx = ep93xxuart_start_tx,
+	.stop_rx = ep93xxuart_stop_rx,
+	.enable_ms = ep93xxuart_enable_ms,
+	.break_ctl = ep93xxuart_break_ctl,
+	.startup = ep93xxuart_startup,
+	.shutdown = ep93xxuart_shutdown,
+	.set_termios = ep93xxuart_set_termios,
+	.type = ep93xxuart_type,
+	.release_port = ep93xxuart_release_port,
+	.request_port = ep93xxuart_request_port,
+	.config_port = ep93xxuart_config_port,
+	.verify_port = ep93xxuart_verify_port,
+};
+
+static struct uart_port ep93xx_ports[UART_NR] = {
+	{
+	 .membase = (void *)UART1_BASE,
+	 .mapbase = UART1_BASE,
+	 .iotype = UPIO_MEM,
+	 .irq = IRQ_UART1,
+	 .uartclk = EP93XX_UART_CLK,
+	 .fifosize = 16,
+	 .ops = &ep93xx_pops,
+	 .flags = UPF_BOOT_AUTOCONF,
+	 },
+	{
+	 .membase = (void *)UART2_BASE,
+	 .mapbase = UART2_BASE,
+	 .iotype = UPIO_MEM,
+	 .irq = IRQ_UART2,
+	 .uartclk = EP93XX_UART_CLK,
+	 .fifosize = 16,
+	 .ops = &ep93xx_pops,
+	 .line = 1,
+	 .flags = UPF_BOOT_AUTOCONF,
+	 },
+#if UART_NR > 2
+	{
+	 .membase = (void *)UART3_BASE,
+	 .mapbase = UART3_BASE,
+	 .iotype = UPIO_MEM,
+	 .irq = IRQ_UART3,
+	 .uartclk = EP93XX_UART_CLK,
+	 .fifosize = 16,
+	 .ops = &ep93xx_pops,
+	 .line = 2,
+	 .flags = UPF_BOOT_AUTOCONF,
+	 }
+#endif
+};
+
+#ifdef CONFIG_SERIAL_EP93XX_CONSOLE
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ *
+ *	The console_lock must be held when we get here.
+ *
+ *	Note that this is called with interrupts already disabled
+ */
+static void
+ep93xxuart_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct uart_port *port = ep93xx_ports + co->index;
+	unsigned long cr, cr2, fr;
+	int i;
+
+	/*
+	 *  Ensure that the port is enabled.
+	 */
+	cr = readl(UARTCR(port));
+	cr2 = cr & ~(UARTCR_RIE | UARTCR_RTIE | UARTCR_TIE | UARTCR_MSIE);
+	writel((cr2 | UARTCR_UARTE), UARTCR(port));
+
+	/*
+	 *      Now, do each character
+	 */
+	for (i = 0; i < count; i++) {
+		do {
+			fr = readl(UARTFR(port));
+		} while (fr & UARTFR_TXFF);
+		writel(s[i], UARTDR(port));
+		if (s[i] == '\n') {
+			do {
+				fr = readl(UARTFR(port));
+			} while (fr & UARTFR_TXFF);
+			writel('\r', UARTDR(port));
+		}
+	}
+
+	/*
+	 *      Finally, wait for transmitter to become empty
+	 *      and restore the uart state.
+	 */
+	do {
+		fr = readl(UARTFR(port));
+	} while ((fr & UARTFR_TXFE) == 0);
+
+	writel(cr, UARTCR(port));
+}
+
+static void __init
+ep93xxuart_console_get_options(struct uart_port *port, int *baud,
+			       int *parity, int *bits)
+{
+	if (readl(UARTCR(port)) & UARTCR_UARTE) {
+		unsigned long lch, quot;
+
+		lch = readl(UARTLCH(port));
+
+		*parity = 'n';
+		if (lch & UARTLCR_H_PEN) {
+			if (lch & UARTLCR_H_EPS)
+				*parity = 'e';
+			else
+				*parity = 'o';
+		}
+
+		if ((lch & UARTLCR_H_WLEN) == UARTLCR_H_WLEN_7_DATA)
+			*bits = 7;
+		else
+			*bits = 8;
+
+		quot =
+		    ((readl(UARTLCM(port)) & 0xff) << 8) | (readl(UARTLCL(port))
+							    & 0xff);
+
+		*baud = port->uartclk / (16 * (quot + 1));
+	}
+}
+
+static int __init ep93xxuart_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	int baud = 57600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	/*
+	 * Check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	port = uart_get_console(ep93xx_ports, UART_NR, co);
+
+	/*
+	 * Temporary fix.
+	 */
+	spin_lock_init(&port->lock);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	else
+		ep93xxuart_console_get_options(port, &baud, &parity, &bits);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+extern struct uart_driver ep93xx_reg;
+static struct console ep93xx_console = {
+	.name = "ttyAM",
+	.write = ep93xxuart_console_write,
+	.device = uart_console_device,
+	.setup = ep93xxuart_console_setup,
+	.flags = CON_PRINTBUFFER,
+	.index = -1,
+	.data = &ep93xx_reg,
+};
+
+static int __init ep93xxuart_console_init(void)
+{
+	register_console(&ep93xx_console);
+	return 0;
+}
+
+console_initcall(ep93xxuart_console_init);
+
+#define EP93XX_CONSOLE	&ep93xx_console
+#else
+#define EP93XX_CONSOLE	NULL
+#endif
+
+static struct uart_driver ep93xx_reg = {
+	.driver_name = "ttyAM",
+	.dev_name = "ttyAM",
+	.major = SERIAL_EP93XX_MAJOR,
+	.minor = SERIAL_EP93XX_MINOR,
+	.nr = UART_NR,
+	.cons = EP93XX_CONSOLE,
+};
+
+static int ep93xxuart_probe(struct amba_device *dev, void *id)
+{
+	int i;
+
+	for (i = 0; i < UART_NR; i++) {
+		if (ep93xx_ports[i].membase != (void *)dev->res.start)
+			continue;
+
+		ep93xx_ports[i].dev = &dev->dev;
+		uart_add_one_port(&ep93xx_reg, &ep93xx_ports[i]);
+		amba_set_drvdata(dev, &ep93xx_ports[i]);
+		break;
+	}
+
+	return 0;
+}
+
+static int ep93xxuart_remove(struct amba_device *dev)
+{
+	struct uart_port *p = amba_get_drvdata(dev);
+
+	if (p)
+		uart_remove_one_port(&ep93xx_reg, p);
+
+	amba_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static int ep93xxuart_suspend(struct amba_device *dev, pm_message_t msg)
+{
+	struct uart_port *p = amba_get_drvdata(dev);
+
+	if (p)
+		uart_suspend_port(&ep93xx_reg, p);
+
+	return 0;
+}
+
+static int ep93xxuart_resume(struct amba_device *dev)
+{
+	struct uart_port *p = amba_get_drvdata(dev);
+
+	if (p)
+		uart_resume_port(&ep93xx_reg, p);
+
+	return 0;
+}
+
+static struct amba_id ep93xxuart_ids[] __initdata = {
+	{			/* UART1 */
+	 .id = 0x808c0000,
+	 .mask = 0xffff0000,
+	 },
+	{			/* UART2 */
+	 .id = 0x808d0000,
+	 .mask = 0xffff0000,
+	 },
+	{			/* UART3 */
+	 .id = 0x808e0000,
+	 .mask = 0xffff0000,
+	 },
+	{0, 0},
+};
+
+static struct amba_driver ep93xxuart_driver = {
+	.drv = {
+		.name = "uart-ep93xx",
+		},
+	.id_table = ep93xxuart_ids,
+	.probe = ep93xxuart_probe,
+	.remove = ep93xxuart_remove,
+	.suspend = ep93xxuart_suspend,
+	.resume = ep93xxuart_resume,
+};
+
+static int __init ep93xxuart_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "Serial: EP93xx driver $Revision: 1.42 $\n");
+
+	ret = uart_register_driver(&ep93xx_reg);
+	if (ret == 0) {
+		ret = amba_driver_register(&ep93xxuart_driver);
+		if (ret)
+			uart_unregister_driver(&ep93xx_reg);
+	}
+
+	return ret;
+}
+
+static void __exit ep93xxuart_exit(void)
+{
+	amba_driver_unregister(&ep93xxuart_driver);
+	uart_unregister_driver(&ep93xx_reg);
+}
+
+module_init(ep93xxuart_init);
+module_exit(ep93xxuart_exit);
+
+MODULE_AUTHOR("Ray Lehtiniemi");
+MODULE_DESCRIPTION("EP93XX generic serial driver $Revision: 1.42 $");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 85dacc9..e57292f 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -22,6 +22,7 @@ config USB_ARCH_HAS_OHCI
 	default y if ARCH_LH7A404
 	default y if ARCH_S3C2410
 	default y if PXA27x
+	default y if ARCH_EP93XX
 	# PPC:
 	default y if STB03xxx
 	default y if PPC_MPC52xx
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
new file mode 100644
index 0000000..8aec2fb
--- /dev/null
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -0,0 +1,248 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ * (C) Copyright 2004 Ray Lehtiniemi
+ *
+ * EP93XX Bus Glue
+ *
+ * Written by Ray Lehtiniemi <rayl@mail.com>
+ * Based on SA-1111 glue.
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <asm/hardware.h>
+#include <asm/hardware/amba.h>
+
+#ifndef CONFIG_ARCH_EP93XX
+#error "This file is EP93xx bus glue.  CONFIG_ARCH_EP93XX must be defined."
+#endif
+
+extern int usb_disabled(void);
+
+
+/*-------------------------------------------------------------------------*/
+
+static void ep93xx_start_hc(struct amba_device *dev)
+{
+	unsigned int pwrcnt;
+
+	printk(KERN_DEBUG __FILE__ ": starting EP93xx OHCI USB Controller\n");
+
+	pwrcnt = readl(SYSCON_PWRCNT);
+	pwrcnt |= SYSCON_PWRCNT_USHEN;
+	writel(pwrcnt, SYSCON_PWRCNT);
+}
+
+static void ep93xx_stop_hc(struct amba_device *dev)
+{
+	unsigned int pwrcnt;
+
+	printk(KERN_DEBUG __FILE__ ": stopping EP93xx OHCI USB Controller\n");
+
+	pwrcnt = readl(SYSCON_PWRCNT);
+	pwrcnt &= ~SYSCON_PWRCNT_USHEN;
+	writel(pwrcnt, SYSCON_PWRCNT);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if 0
+static void dump_hci_status(struct usb_hcd *hcd, const char *label)
+{
+	unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
+
+	dbg("%s USB_STATUS = { %s%s%s%s%s}", label,
+	    ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""),
+	    ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
+	    ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
+	    ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "),
+	    ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : ""));
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+void usb_hcd_ep93xx_remove(struct usb_hcd *, struct amba_device *);
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+/**
+ * usb_hcd_ep93xx_probe - initialize ep93xx HCD
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ * Store this function in the HCD's struct pci_driver as probe().
+ */
+int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
+			 struct amba_device *dev)
+{
+	int retval;
+	struct usb_hcd *hcd;
+
+	hcd = usb_create_hcd(driver, &dev->dev, "ep93xx");
+
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = dev->res.start;
+	hcd->rsrc_len = dev->res.end - dev->res.start + 1;
+
+	hcd->regs = (void __iomem *)dev->res.start;
+
+	ep93xx_start_hc(dev);
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	retval = usb_add_hcd(hcd, dev->irq[0], SA_INTERRUPT);
+	if (retval == 0)
+		return retval;
+
+	ep93xx_stop_hc(dev);
+
+	usb_put_hcd(hcd);
+	return retval;
+}
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_ep93xx_remove - shutdown processing for SA-1111-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_ep93xx_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, struct amba_device *dev)
+{
+	usb_remove_hcd(hcd);
+	ep93xx_stop_hc(dev);
+	usb_put_hcd(hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int ret;
+
+	ohci_dbg(ohci, "ohci_ep93xx_start, ohci:%p", ohci);
+
+	if ((ret = ohci_init(ohci)) < 0)
+		return ret;
+
+	if ((ret = ohci_run(ohci)) < 0) {
+		err("can't start %s", hcd->self.bus_name);
+		ohci_stop(hcd);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct hc_driver ohci_ep93xx_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "EP93xx OHCI",
+	.hcd_priv_size = sizeof(struct ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ohci_irq,
+	.flags = HCD_USB11,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.start = ohci_ep93xx_start,
+#ifdef	CONFIG_PM
+	/* suspend:             ohci_ep93xx_suspend,  -- tbd */
+	/* resume:              ohci_ep93xx_resume,   -- tbd */
+#endif
+	.stop = ohci_stop,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ohci_urb_enqueue,
+	.urb_dequeue = ohci_urb_dequeue,
+	.endpoint_disable = ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ohci_hub_status_data,
+	.hub_control = ohci_hub_control,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int ep93xxohci_probe(struct amba_device *dev, void *id)
+{
+	int ret = -ENODEV;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, dev);
+
+	return ret;
+}
+
+static int ep93xxohci_remove(struct amba_device *dev)
+{
+	struct usb_hcd *hcd = amba_get_drvdata(dev);
+
+	usb_hcd_ep93xx_remove(hcd, dev);
+
+	return 0;
+}
+
+static struct amba_id ep93xxohci_ids[] __initdata = {
+	{
+	 .id = 0x80020000,
+	 .mask = 0xffff0000,
+	 },
+	{0, 0},
+};
+
+static struct amba_driver ep93xxohci_driver = {
+	.drv = {
+		.name = "ohci-ep93xx",
+		},
+	.id_table = ep93xxohci_ids,
+	.probe = ep93xxohci_probe,
+	.remove = ep93xxohci_remove,
+};
+
+static int __init ep93xxohci_init(void)
+{
+	printk(KERN_INFO "USB: EP93xx driver $Revision: 1.42 $\n");
+	return amba_driver_register(&ep93xxohci_driver);
+}
+
+static void __exit ep93xxohci_cleanup(void)
+{
+	amba_driver_unregister(&ep93xxohci_driver);
+}
+
+module_init(ep93xxohci_init);
+module_exit(ep93xxohci_cleanup);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index bf1d9ab..bb525a2 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -909,6 +909,10 @@ MODULE_LICENSE ("GPL");
 #include "ohci-pxa27x.c"
 #endif
 
+#ifdef CONFIG_ARCH_EP93XX
+#include "ohci-ep93xx.c"
+#endif
+
 #ifdef CONFIG_SOC_AU1X00
 #include "ohci-au1xxx.c"
 #endif
@@ -923,6 +927,7 @@ MODULE_LICENSE ("GPL");
       || defined(CONFIG_ARCH_OMAP) \
       || defined (CONFIG_ARCH_LH7A404) \
       || defined (CONFIG_PXA27x) \
+      || defined (CONFIG_ARCH_EP93XX) \
       || defined (CONFIG_SOC_AU1X00) \
       || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
 	)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cc8e3bf..1d46ab0 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -172,6 +172,122 @@ config FB_CLPS711X
 	  Say Y to enable the Framebuffer driver for the CLPS7111 and
 	  EP7212 processors.
 
+config FB_CX25871_I2C
+	tristate "Conexant CX25871 video encoder"
+	depends on I2C && EXPERIMENTAL
+	help
+
+	  ! ! !   B R O K E N   B R O K E N   B R O K E N   ! ! !
+
+	  If you say yes here you get support for the Conexant CX25871
+	  video encoder. Currently only EP93xx CPUs use this for some
+	  NTSC setup. This setup should be done in ep93xxfb.c instead.
+	  It is currently hardcoded here in cx25871, which is wrong, as
+	  it will happen anytime instead of exactly when it is needed.
+	  I've got no NTSC hardware, and no time to test this either.
+
+	  Why I've written it then? Well I had to get I2C working and it
+	  helped me on my way there.
+
+	  If nobody cares about NTSC support for EP93xx it will go away soon!
+
+	  Only say Y if you have such a chip and are prepared to fix the remaining
+	  stuff yourself.
+
+	  See ep93xxfb.[ch] and cx25871.c for details.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called cx25871.
+
+config FB_EP93XX
+	bool "EP93XX Framebuffer support"
+	depends on FB && ARM && (ARCH_EP9312 || ARCH_EP9315)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  Say Y here if you want support for the on EP93XX framebuffer.
+
+	  You can also say M here to compile this as a module. However this
+	  is not recommended as loading the module without a display can
+	  be a problem. (Make sure you can login without display before you
+	  say M or N here).
+
+	  The module will be called ep93xxfb.
+choice
+	prompt "Display Type"
+	depends on FB_EP93XX
+	help
+	  Choose the kind of display you want to attach to the EP93XX framebuffer.
+
+config FB_CRT_EP93XX
+	bool "CRT Display"
+
+config FB_LCD_EP93XX
+	bool "LCD Display"
+	help
+	  Support for the Philips 640x480 Display on the EDB93XX evaluation board.
+
+config FB_LCD_EP93XX_SHARP
+	bool "LCD Display 320x200 SHARP"
+	help
+	  Support for the Sharp LQ057Q3DC02 320x200 Color TFT LCD.
+
+config FB_LCD_EP93XX_SHARP_LQ64D343
+	bool "LCD Display 640x480 SHARP"
+	help
+	  Support for the Sharp LQ64D343 640x480 Color TFT LCD.
+
+config FB_CX25871
+	bool "NTSC Display"
+	select FB_CX25871_I2C
+
+config FB_LCD_TX09D50VM1CCA
+	bool "LCD Display 240x320 Hitachi TX09D50VM1CCA"
+	help
+	  Support for the Hitachi TX09D50VM1CCA 240x320 Color TFT LCD.
+
+endchoice
+
+choice
+	prompt "Display Color Depth"
+	depends on FB_EP93XX
+	default FB_EP93XX_8BPP
+	help
+	  Choose the default color depth for you EP93xx display. Note that using
+	  other than 8BPP depths tends to be slow.
+
+config FB_EP93XX_8BPP
+	bool "8bpp"
+	help
+	  Use 8 bits per pixel (256 color).
+	  Benefits: fastest available mode
+	  Drawback: few colors available (might do for console work, though)
+
+config FB_EP93XX_16BPP_565
+	bool "16bpp_565"
+	help
+	  Use 16 bits per pixel. Weighting red:green:blue is 5:6:5 bits.
+	  Make sure your Xserver / Framebuffer based applications use exactly this
+	  weighting.
+
+config FB_EP93XX_24BPP
+	bool "24bpp"
+	help
+	  Use 24 bits per pixel. Weighting red:green:blue is 8:8:8 bits. Say Y here
+	  if you want lots of colors and do not care that much about performance.
+
+
+
+config FB_EP93XX_32BPP
+	bool "32bpp"
+	help
+	  Use 32 bits per pixel. Weighting transparent:red:green:blue is 8:8:8:8 bits.
+	  Note that transparency is seldom implemented so this one is just slower and
+	  consumes more memory than 24BPP.
+endchoice
+
+
 config FB_SA1100
 	bool "SA-1100 LCD support"
 	depends on (FB = y) && ARM && ARCH_SA1100
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index aa434e7..82f680b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -99,6 +99,8 @@ obj-$(CONFIG_FB_S3C2410)	  += s3c2410fb.
 obj-$(CONFIG_FB_VESA)             += vesafb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
 obj-$(CONFIG_FB_OF)               += offb.o
+obj-$(CONFIG_FB_EP93XX)            += ep93xxfb.o
+obj-$(CONFIG_FB_CX25871_I2C)       += cx25871.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff --git a/drivers/video/cx25871.c b/drivers/video/cx25871.c
new file mode 100644
index 0000000..816cbef
--- /dev/null
+++ b/drivers/video/cx25871.c
@@ -0,0 +1,200 @@
+/*
+    cx25871.c
+
+    Driver for the Conexant CX25871 VIDEO ENCODER
+
+    based on: ds1621.c
+
+
+
+
+    BIG FAT WARNING: THIS IS EXPERIMENTAL AND UNTESTED CODE
+
+
+
+
+
+
+    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.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <asm/io.h>
+
+/*
+ * assign an invalid (local use) id for now
+ * TODO: get an official one!
+ */
+#define I2C_DRIVERID_EP93XX 0xffff
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x44, I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static int cx25871_attach_adapter(struct i2c_adapter *adapter);
+static int cx25871_detect(struct i2c_adapter *adapter, int address, int kind);
+static void cx25871_init_client(struct i2c_client *client);
+static int cx25871_detach_client(struct i2c_client *client);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver cx25871_driver = {
+	.owner = THIS_MODULE,
+	.name = "cx25871",
+	.id = I2C_DRIVERID_EP93XX,
+	.flags = I2C_DF_NOTIFY,
+	.attach_adapter = cx25871_attach_adapter,
+	.detach_client = cx25871_detach_client,
+};
+
+static int cx25871_id = 0;
+
+/* Cleanup and introduce cx25871 specific data, if necessary */
+struct cx25871_data {
+	struct i2c_client client;
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+};
+
+static int cx25871_read_value(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int cx25871_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static void cx25871_init_client(struct i2c_client *client)
+{
+	/*FIXME: This should be done in ep93xxfb.c, shouldn't it? */
+
+	int _todo__fix_this_ugly_hack_;
+
+	cx25871_write_value(client, 0xB8, 0);
+	mdelay(1000);
+	/* After auto-configuration, setup pseudo-master mode BUT with EN_BLANKO bit cleared */
+	cx25871_write_value(client, 0xBA,
+			    CX25871_REGxBA_SLAVER | CX25871_REGxBA_DACOFF);
+	cx25871_write_value(client, 0xC6, (CX25871_REGxC6_INMODE_MASK & 0x3));
+	cx25871_write_value(client, 0xC4, CX25871_REGxC4_EN_OUT);
+	cx25871_write_value(client, 0x32, 0);
+	cx25871_write_value(client, 0xBA, CX25871_REGxBA_SLAVER);
+}
+
+static int cx25871_attach_adapter(struct i2c_adapter *adapter)
+{
+	printk("cx25871_attach_adapter\n");
+	return i2c_probe(adapter, &addr_data, cx25871_detect);
+}
+
+/* This function is called by i2c_detect */
+int cx25871_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct cx25871_data *data;
+	int err = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
+				     | I2C_FUNC_SMBUS_WRITE_BYTE))
+		goto exit;
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access cx25871_{read,write}_value. */
+	if (!(data = kmalloc(sizeof(struct cx25871_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(data, 0, sizeof(struct cx25871_data));
+
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &cx25871_driver;
+	new_client->flags = 0;
+
+	/* Fill in remaining client fields and put it into the global list */
+	strlcpy(new_client->name, "cx25871", I2C_NAME_SIZE);
+
+	new_client->id = cx25871_id++;
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_free;
+	/* Initialize the EP93XX chip */
+	cx25871_init_client(new_client);
+
+/* Register sysfs hooks */
+#if 0
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+	device_create_file(&new_client->dev, &dev_attr_temp1_input);
+	device_create_file(&new_client->dev, &dev_attr_temp1_min);
+	device_create_file(&new_client->dev, &dev_attr_temp1_max);
+#endif
+	return 0;
+
+/* OK, this is not exactly good programming practice, usually. But it is
+   very code-efficient in this case. */
+      exit_free:
+	kfree(data);
+      exit:
+	return err;
+}
+
+static int cx25871_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, "
+			"client not detached.\n");
+		return err;
+	}
+
+	kfree(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+static int __init cx25871_init(void)
+{
+	printk("cx25871_init\n");
+	return i2c_add_driver(&cx25871_driver);
+}
+
+static void __exit cx25871_exit(void)
+{
+	i2c_del_driver(&cx25871_driver);
+}
+
+MODULE_DESCRIPTION("Conexant CX25871 video encoder");
+MODULE_LICENSE("GPL");
+
+module_init(cx25871_init);
+module_exit(cx25871_exit);
diff --git a/drivers/video/ep93xxfb.c b/drivers/video/ep93xxfb.c
new file mode 100644
index 0000000..475943a
--- /dev/null
+++ b/drivers/video/ep93xxfb.c
@@ -0,0 +1,787 @@
+/******************************************************************************
+ *
+ *  File:	linux/drivers/video/ep93xxfb.c
+ *
+ *  Purpose: Framebuffer driver for EP9312/EP9315 evaluation board.
+ *
+ *  based on:
+ *           skeletonfb.c
+ *           ep93xxfb.c from Linux 2.4.21-rmk1-cirrus-1-3-0
+ *
+ *******************************************************************************/
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+#include "ep93xxfb.h"
+
+/*
+#define DEBUG
+#define USE_PRINTASCII
+*/
+
+#ifdef DEBUG
+#  if defined(CONFIG_DEBUG_LL) && defined(USE_PRINTASCII)
+extern void printascii(const char *);
+#    define DPRINTK(fmt, args...) {char str[256];sprintf(str, "%s: " fmt, __FUNCTION__ , ## args);printascii(str);}
+#  else
+#    define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
+#  endif
+#else
+#  define DPRINTK(fmt, args...)
+#endif
+
+static struct fb_info info;
+static struct fb_fix_screeninfo ep93xxfb_fix;
+static struct fb_var_screeninfo ep93xxfb_var;
+static struct ep93xxfb_par ep93xxfb_par;
+static unsigned int pseudo_palette[MAX_PALETTE_NUM_ENTRIES];
+
+int __init ep93xxfb_init(void);
+static int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *info);
+static int ep93xxfb_blank(int blank_mode, struct fb_info *info);
+int __init ep93xxfb_init(void);
+static void __exit ep93xxfb_cleanup(void);
+int __init ep93xxfb_setup(char *options);
+
+static struct fb_ops ep93xxfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_setcolreg = ep93xxfb_setcolreg,
+	.fb_blank = ep93xxfb_blank,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+};
+
+/*
+ * ep93xxfb_palette_write:
+ *	Encode palette data to 24bit palette format.
+ *      Write palette data to the master palette and inactive hw palette
+ *	switch palettes.  And handle asynchronous palette switches.
+ */
+static inline void
+ep93xxfb_palette_write(u_int regno, u_int red, u_int green,
+		       u_int blue, u_int trans)
+{
+	unsigned int cont, i, pal;
+
+	/* Only supports color LUT, not gray LUT
+	 *
+	 *  TBD if not in 4 or 8bpp, then does LUT logic operate?
+	 *  TBD or do we need to do nothing here?
+	 *
+	 * LCD:     TBD RGB mapping may match spec p193.
+	 *
+	 * CRT: LUT RGB mapping is really R/G/B from high to low bits
+	 *  because really determined by wiring to video DAC.
+	 *  (disregard spec p 193 showing color LUT B/G/R order)
+	 *  Here are the details:
+	 *
+	 *  Shift mode 1 directs LUT bits 7-2 onto P5-P0,
+	 *  LUT bits 15-10 onto P11-P6, and LUT bits 23-16
+	 *  onto P17-P12.
+	 *
+	 *  Board wired P17-12 to video DAC Red inputs,
+	 *  P11-P6 wired to video DAC Green inputs, and
+	 *  P5-P0 wired to video DAC Blue inputs.
+	 */
+	pal = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+
+	pseudo_palette[regno] = pal;
+
+	/* Two cases here:
+	 * 1.       If LUT switch is pending, then write inactive LUT and when
+	 *  switch happens, this new palette entry will be active.
+	 *  Race condition here between LUT switch and this write is okay
+	 *  since we fix it below.
+	 *
+	 * 2.       If LUT switch is not pending, then write here is incomplete
+	 *  and whole palette will be written below.
+	 */
+
+	writel(pal, COLOR_LUT + (regno << 2));
+
+	cont = readl(LUTCONT);
+
+	if ((cont & LUTCONT_STAT && cont & LUTCONT_RAM1) ||
+	    (!(cont & LUTCONT_STAT) && !(cont & LUTCONT_RAM1))) {
+		/* LUT switch is no longer pending
+		 *
+		 * We do not know if write to LUT above really went
+		 * to currently active LUT.  So need to make sure that
+		 * data gets into inactive LUT and switch LUTs.
+		 *
+		 * But currently inactive LUT may be out of date
+		 * in more entries than just last write.
+		 * Need to update currently inactive LUT for all writes
+		 * which went to currently active LUT.
+		 * Fully update the LUT now, which is a simpler policy
+		 * than trying to track writes and do partial update of LUT.
+		 * (Worstcase impact: we update palette every frame)
+		 */
+
+		for (i = 0; i < 256; i++)	// Update inactive LUT
+		{
+			writel(pseudo_palette[i],
+			       (COLOR_LUT + (i << 2)));
+		}
+		/* Switch active LUTs next frame */
+		writel(cont ^ LUTCONT_RAM1, LUTCONT);
+	}
+}
+
+/**
+ *  	xxxfb_setcolreg - Optional function. Sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *  	Set a single color register. The values supplied have a 16 bit
+ *  	magnitude which needs to be scaled in this function for the hardware.
+ *	Things to take into consideration are how many color registers, if
+ *	any, are supported with the current color visual. With truecolor mode
+ *	no color palettes are supported. Here a psuedo palette is created
+ *	which we store the value in pseudo_palette in struct fb_info. For
+ *	pseudocolor mode we have a limited color palette. To deal with this
+ *	we can program what color is displayed for a particular pixel value.
+ *	DirectColor is similar in that we can program each color field. If
+ *	we have a static colormap we don't need to implement this function.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int
+ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+		   unsigned transp, struct fb_info *info)
+{
+	if (regno >= MAX_PALETTE_NUM_ENTRIES)	/* no. of hw registers */
+		return 1;
+	/*
+	 * Program hardware... do anything you want with transp
+	 */
+
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Directcolor:
+	 *   var->{color}.offset contains start of bitfield
+	 *   var->{color}.length contains length of bitfield
+	 *   {hardwarespecific} contains width of DAC
+	 *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+	 *   RAMDAC[X] is programmed to (red, green, blue)
+	 *
+	 * Pseudocolor:
+	 *    uses offset = 0 && length = DAC register width.
+	 *    var->{color}.offset is 0
+	 *    var->{color}.length contains widht of DAC
+	 *    cmap is not used
+	 *    DAC[X] is programmed to (red, green, blue)
+	 * Truecolor:
+	 *    does not use RAMDAC (usually has 3 of them).
+	 *    var->{color}.offset contains start of bitfield
+	 *    var->{color}.length contains length of bitfield
+	 *    cmap is programmed to (red << red.offset) | (green << green.offset) |
+	 *                      (blue << blue.offset) | (transp << transp.offset)
+	 *    RAMDAC does not exist
+	 */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_PSEUDOCOLOR:
+		/* Feed the dual 256x24 hardware LUT */
+		ep93xxfb_palette_write(regno, red, green, blue, transp);
+		break;
+	case FB_VISUAL_TRUECOLOR:
+		/* Truecolor has hardware independent palette */
+		if (regno >= 16)
+			return 1;
+
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		transp = CNVT_TOHW(transp, info->var.transp.length);
+		((u32 *) (info->pseudo_palette))[regno] =
+		    (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		/* example here assumes 8 bit DAC. Might be different
+		 * for your hardware */
+		red = CNVT_TOHW(red, 8);
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+
+	return 0;
+}
+
+/**
+ *      xxxfb_blank - NOT a required function. Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *      video mode which doesn't support it. Implements VESA suspend
+ *      and powerdown modes on hardware that supports disabling hsync/vsync:
+ *      blank_mode == 2: suspend vsync
+ *      blank_mode == 3: suspend hsync
+ *      blank_mode == 4: powerdown
+ *
+ *      Returns negative errno on error, or zero on success.
+ *
+ */
+static int ep93xxfb_blank(int blank_mode, struct fb_info *info)
+{
+#ifdef CONFIG_MACH_ADSSPHERE
+	void adssphere_blank(int blank_mode);
+
+	adssphere_blank(blank_mode);
+#endif
+
+	return 1;
+}
+
+static struct device ep93xxfb_device = {
+	.bus_id = "ep93xxfb",
+	.coherent_dma_mask = 0xffffffff,
+};
+
+/*
+ * ep9312fb_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 ep9312fb_map_video_memory(void)
+{
+	dma_addr_t handle;
+
+	ep93xxfb_par.dev = &ep93xxfb_device;
+
+	ep93xxfb_par.v_screen_base = dma_alloc_writecombine(ep93xxfb_par.dev,
+							    FB_MAPPED_MEM_SIZE,
+							    &handle,
+							    GFP_KERNEL);
+
+	if (ep93xxfb_par.v_screen_base == NULL) {
+		printk(KERN_ERR "ep93xxfb: unable to allocate screen memory\n");
+		return -ENOMEM;
+	}
+
+	info.screen_base = ep93xxfb_par.v_screen_base;
+	info.fix.smem_start = (unsigned int)ep93xxfb_par.p_screen_base = handle;
+	info.fix.smem_len = FB_MAPPED_MEM_SIZE;
+
+	return 0;
+}
+
+static int ep93xxfb_probe_configuration(void)
+{
+	int xres, yres, bpp, pixelmode, total;
+	unsigned char lookup_bpp[] = {-1, -1, 8, -1, 16, -1, 24, 32};
+
+	pixelmode = readl(PIXELMODE);
+
+	bpp = lookup_bpp[PIXELMODE_P_MASK & pixelmode];
+
+	if (bpp < 0) return 0;
+
+	yres = readl(SCRNLINES);
+
+	if (yres == 0) return 0;
+
+	xres = (32 * readl(VLINESTEP)) / bpp;
+
+	if (xres == 0) return 0;
+
+	info.node = -1;
+	info.flags = FBINFO_FLAG_DEFAULT;
+
+	info.fix = ep93xxfb_fix;
+	info.var = ep93xxfb_var;
+	info.fbops = &ep93xxfb_ops;
+	info.pseudo_palette = pseudo_palette;
+
+	info.monspecs = monspecs;
+
+	strcpy(info.fix.id, "Cirrus EP93xx");
+	info.fix.type = FB_TYPE_PACKED_PIXELS;
+	info.fix.xpanstep = 0;
+	info.fix.ypanstep = 0;
+	info.fix.ywrapstep = 0;
+	info.fix.accel = FB_ACCEL_NONE;
+
+	info.var.xres = xres;
+	info.var.yres = yres;
+	info.var.xres_virtual = xres;
+	info.var.yres_virtual = yres;
+	info.var.bits_per_pixel = bpp;
+	info.var.activate = FB_ACTIVATE_NOW;
+	info.var.height = -1;
+	info.var.width = -1;
+
+	switch (bpp) {
+	case 8:
+		info.var.red.length = 8;
+		info.var.green.length = 8;
+		info.var.blue.length = 8;
+
+		info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		ep93xxfb_par.bits_per_pixel = 8;
+		break;
+	case 16:
+		info.var.red.length = 5;
+		info.var.green.length = 6;
+		info.var.blue.length = 5;
+		info.var.transp.length = 0;
+		info.var.red.offset = 11;
+		info.var.green.offset = 5;
+		info.var.blue.offset = 0;
+		info.var.transp.offset = 0;
+
+		info.fix.visual = FB_VISUAL_TRUECOLOR;
+		info.pseudo_palette = ep93xxfb_par.palette;
+
+		ep93xxfb_par.bits_per_pixel = 16;
+		break;
+	case 24:
+		info.var.red.length = 8;
+		info.var.blue.length = 8;
+		info.var.green.length = 8;
+		info.var.transp.length = 0;
+		info.var.red.offset = 16;
+		info.var.green.offset = 8;
+		info.var.blue.offset = 0;
+		info.var.transp.offset = 0;
+
+		info.fix.visual = FB_VISUAL_TRUECOLOR;
+
+		ep93xxfb_par.bits_per_pixel = 24;
+		break;
+	case 32:
+		info.var.red.length = 8;
+		info.var.blue.length = 8;
+		info.var.green.length = 8;
+		info.var.transp.length = 0;
+		info.var.red.offset = 16;
+		info.var.green.offset = 8;
+		info.var.blue.offset = 0;
+		info.var.transp.offset = 0;
+
+		info.fix.visual = FB_VISUAL_TRUECOLOR;
+
+		ep93xxfb_par.bits_per_pixel = 32;
+		break;
+	}
+
+	total = readl(HCLKSTOTAL);
+	info.var.hsync_len = (0x7ff & readl(HSYNCSTRTSTOP)) - ((0x07ff0000 & readl(HSYNCSTRTSTOP)) >> 16);
+	info.var.right_margin = ((0x07ff0000 & readl(HSYNCSTRTSTOP)) >> 16) - (0x7ff & readl(HACTIVESTRTSTOP));
+	info.var.left_margin = total - info.var.hsync_len - info.var.right_margin - xres + 1;
+
+	total = readl(VLINESTOTAL);
+	info.var.vsync_len = (0x7ff & readl(VSYNCSTRTSTOP)) - ((0x07ff0000 & readl(VSYNCSTRTSTOP)) >> 16);
+	info.var.upper_margin = total - (0x7ff & readl(VSYNCSTRTSTOP));
+	info.var.lower_margin = ((0x07ff0000 & readl(VSYNCSTRTSTOP)) >> 16) - yres + 1;
+
+	info.var.sync = 0;
+
+	info.var.vmode = FB_VMODE_NONINTERLACED;
+
+	info.fix.line_length = info.var.xres_virtual * info.var.bits_per_pixel / 8;	// stride in bytes
+
+	info.par = &TimingValues[NULL_MODE];
+
+	ep93xxfb_par.screen_size = FB_MAX_MEM_SIZE;
+	ep93xxfb_par.palette_size = MAX_PALETTE_NUM_ENTRIES;
+	ep93xxfb_par.montype = 1;	//TBD why not 0 since single entry?
+	ep93xxfb_par.currcon = 0;	//TBD is this right?
+
+	return 1;
+}
+
+static void
+__init ep93xxfb_init_fbinfo(void)
+{
+	info.node = -1;
+	info.flags = FBINFO_FLAG_DEFAULT;
+
+	info.fix = ep93xxfb_fix;
+	info.var = ep93xxfb_var;
+	info.fbops = &ep93xxfb_ops;
+	info.pseudo_palette = pseudo_palette;
+	info.par = &ep93xxfb_par;
+
+	info.monspecs = monspecs;
+
+	strcpy(info.fix.id, "Cirrus EP93xx");
+	info.fix.type = FB_TYPE_PACKED_PIXELS;
+	info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	info.fix.xpanstep = 0;
+	info.fix.ypanstep = 0;
+	info.fix.ywrapstep = 0;
+	info.fix.accel = FB_ACCEL_NONE;
+
+	info.var.xres = TimingValues[DEFAULT_MODE].HRes;
+	info.var.yres = TimingValues[DEFAULT_MODE].VRes;
+	info.var.xres_virtual = TimingValues[DEFAULT_MODE].HRes;
+	info.var.yres_virtual = TimingValues[DEFAULT_MODE].VRes;
+	info.var.bits_per_pixel = 32;
+	info.var.red.length = 8;
+	info.var.green.length = 8;
+	info.var.blue.length = 8;
+	info.var.activate = FB_ACTIVATE_NOW;
+	info.var.height = -1;
+	info.var.width = -1;
+	info.var.vmode = FB_VMODE_NONINTERLACED;
+
+	/*
+	 * setup initial parameters
+	 */
+	info.var.xres = TimingValues[DEFAULT_MODE].HRes;
+	info.var.yres = TimingValues[DEFAULT_MODE].VRes;
+
+#ifdef CONFIG_FB_EP93XX_8BPP
+	DPRINTK("Default framebuffer is 8bpp.");
+	info.var.bits_per_pixel = 8;
+
+	info.var.red.length = 8;
+	info.var.green.length = 8;
+	info.var.blue.length = 8;
+
+	info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	ep93xxfb_par.bits_per_pixel = 8;
+#endif				/* CONFIG_FB_EP93XX_8BPP */
+#ifdef CONFIG_FB_EP93XX_16BPP_565
+	DPRINTK("Default framebuffer is 16bpp 565.");
+	info.var.bits_per_pixel = 16;
+
+	info.var.red.length = 5;
+	info.var.green.length = 6;
+	info.var.blue.length = 5;
+	info.var.transp.length = 0;
+	info.var.red.offset = 11;
+	info.var.green.offset = 5;
+	info.var.blue.offset = 0;
+	info.var.transp.offset = 0;
+	info.fix.visual = FB_VISUAL_TRUECOLOR;
+	info.pseudo_palette = ep93xxfb_par.palette;
+
+	ep93xxfb_par.bits_per_pixel = 16;
+#endif				/* CONFIG_FB_EP93XX_16BPP */
+#ifdef CONFIG_FB_EP93XX_24BPP
+	DPRINTK("Default framebuffer is 24bpp.");
+	info.var.bits_per_pixel = 24;
+
+	info.var.red.length = 8;
+	info.var.blue.length = 8;
+	info.var.green.length = 8;
+	info.var.transp.length = 0;
+	info.var.red.offset = 16;
+	info.var.green.offset = 8;
+	info.var.blue.offset = 0;
+	info.var.transp.offset = 0;
+	info.fix.visual = FB_VISUAL_TRUECOLOR;
+
+	ep93xxfb_par.bits_per_pixel = 24;
+#endif				/* CONFIG_FB_EP93XX_24BPP */
+#ifdef CONFIG_FB_EP93XX_32BPP
+	DPRINTK("Default framebuffer is 32bpp.");
+	info.var.bits_per_pixel = 32;
+
+	info.var.red.length = 8;
+	info.var.blue.length = 8;
+	info.var.green.length = 8;
+	info.var.transp.length = 0;
+	info.var.red.offset = 16;
+	info.var.green.offset = 8;
+	info.var.blue.offset = 0;
+	info.var.transp.offset = 0;
+	info.fix.visual = FB_VISUAL_TRUECOLOR;
+
+	ep93xxfb_par.bits_per_pixel = 32;
+#endif				/* CONFIG_FB_EP93XX_32BPP */
+
+	info.var.activate = FB_ACTIVATE_NOW;
+	info.var.height = -1;	/*TBD unknown */
+	info.var.width = -1;	/*TBD unknown */
+
+	info.var.left_margin = TimingValues[DEFAULT_MODE].HFrontPorch;
+	info.var.right_margin = TimingValues[DEFAULT_MODE].HBackPorch;
+	info.var.upper_margin = TimingValues[DEFAULT_MODE].VFrontPorch;
+	info.var.lower_margin = TimingValues[DEFAULT_MODE].VBackPorch;
+	info.var.hsync_len = TimingValues[DEFAULT_MODE].HSyncWidth;
+	info.var.vsync_len = TimingValues[DEFAULT_MODE].VSyncWidth;
+	info.var.sync = 0;
+	info.var.vmode = FB_VMODE_NONINTERLACED;
+
+	info.fix.line_length = info.var.xres_virtual * info.var.bits_per_pixel / 8;	/* stride in bytes */
+
+	info.par = &TimingValues[DEFAULT_MODE];
+
+	ep93xxfb_par.screen_size = FB_MAX_MEM_SIZE;
+	ep93xxfb_par.palette_size = MAX_PALETTE_NUM_ENTRIES;
+	ep93xxfb_par.montype = 1;	/*TBD why not 0 since single entry? */
+	ep93xxfb_par.currcon = 0;	/*TBD is this right? */
+}
+
+static int
+ep93xxfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	u_long flags, ulVIDEOATTRIBS;
+	unsigned int total, uiDevCfg, uiBMAR;
+#ifdef CONFIG_FB_LCD_EP93XX
+	unsigned int uiPADDR, uiPADR;
+#endif
+	struct DisplayTimingValues *pTimingValues;
+
+	switch (var->bits_per_pixel) {
+	case 4:
+		ep93xxfb_par.visual = FB_VISUAL_PSEUDOCOLOR;
+		ep93xxfb_par.palette_size = 16;
+		break;
+	case 8:
+		ep93xxfb_par.visual = FB_VISUAL_PSEUDOCOLOR;
+		ep93xxfb_par.palette_size = 256;
+		break;
+	case 16:
+		ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
+		ep93xxfb_par.palette_size = 16;
+		break;
+	case 24:
+		ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
+		ep93xxfb_par.palette_size = 16;
+		break;
+	case 32:
+		ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
+		ep93xxfb_par.palette_size = 16;
+		break;
+	default:
+		printk("ERROR! Bad bpp %d\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
+		return 0;
+	else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) &&
+		 ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN))
+		return -EINVAL;
+
+	pTimingValues = (struct DisplayTimingValues *)info->par;
+
+	/* Disable interrupts and save status */
+	local_irq_save(flags);
+
+	printk("Configuring %dx%dx%dbpp\n", var->xres, var->yres,
+	       var->bits_per_pixel);
+
+	/* Disable the video and outputs while changing the video mode. */
+	writel(0, VIDEOATTRIBS);
+	if (pTimingValues->RasterConfigure) {
+		pTimingValues->RasterConfigure((struct DisplayTimingValues *)info->par);	/*pTimingValues); */
+	} else {
+		total = var->vsync_len + var->upper_margin + var->yres +
+		    var->lower_margin - 1;
+
+		RasterSetLocked(VLINESTOTAL, total);
+
+		RasterSetLocked(VSYNCSTRTSTOP, total - var->lower_margin +
+				((total -
+				  (var->lower_margin + var->vsync_len)) << 16));
+
+		RasterSetLocked(VACTIVESTRTSTOP, var->yres + (total << 16));
+
+		/* Reverse start/stop since N_VBLANK output
+		 * unblanked same as active
+		 */
+		RasterSetLocked(VBLANKSTRTSTOP, var->yres + (total << 16));
+
+		RasterSetLocked(VCLKSTRTSTOP, total + (total << 16));
+
+		/* Now configure the Horizontal timings. */
+		total = var->hsync_len + var->left_margin + var->xres +
+		    var->right_margin - 1;
+
+		RasterSetLocked(HCLKSTOTAL, total);
+
+		RasterSetLocked(HSYNCSTRTSTOP, total +
+				((total - var->hsync_len) << 16));
+
+		RasterSetLocked(HACTIVESTRTSTOP, total - var->hsync_len -
+				var->left_margin +
+				((var->right_margin - 1) << 16));
+
+		RasterSetLocked(HBLANKSTRTSTOP, total - var->hsync_len -
+				var->left_margin +
+				((var->right_margin - 1) << 16));
+
+		RasterSetLocked(HCLKSTRTSTOP, total + (total << 16));
+
+		RasterSetLocked(LINECARRY, 0);
+
+		RasterSetLocked(VIDEOATTRIBS,
+				VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_SYNCEN |
+				VIDEOATTRIBS_DATAEN);
+	}
+
+	/* Configure the Frame Buffer size. */
+	writel((unsigned int)ep93xxfb_par.p_screen_base, VIDSCRNPAGE);
+	writel(var->yres, SCRNLINES);
+
+	/* Set up the Line size. */
+	total = var->xres * var->bits_per_pixel / 32;
+	writel((total - 1), LINELENGTH);
+	writel(total, VLINESTEP);
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		writel((0x8 | PIXELMODE_P_8BPP | PIXELMODE_C_LUT), PIXELMODE);
+		break;
+	case 16:
+		writel(0x8 | PIXELMODE_P_16BPP |
+		       ((PIXELMODE_C_565) << (PIXELMODE_C_SHIFT)), PIXELMODE);
+		break;
+	case 24:
+		writel(0x8 | PIXELMODE_P_24BPP |
+		       ((PIXELMODE_C_888) << (PIXELMODE_C_SHIFT)), PIXELMODE);
+		break;
+	case 32:
+		writel(0x8 | PIXELMODE_P_32BPP |
+		       ((PIXELMODE_C_888) << (PIXELMODE_C_SHIFT)), PIXELMODE);
+		break;
+	default:
+		printk("ERROR! Bad bpp %d\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	uiDevCfg = readl(SYSCON_DEVCFG);
+	SysconSetLocked(SYSCON_DEVCFG,
+			ep93xx_SYSCON_DEVCFG(uiDevCfg | SYSCON_DEVCFG_RasOnP3));
+
+	if (pTimingValues->VDiv)
+		SysconSetLocked(SYSCON_VIDDIV, pTimingValues->VDiv);
+
+	uiBMAR = readl(SYSCON_BMAR);
+	writel((uiBMAR | 1), SYSCON_BMAR);
+
+	ulVIDEOATTRIBS = readl(VIDEOATTRIBS);
+	RasterSetLocked(VIDEOATTRIBS, ulVIDEOATTRIBS | VIDEOATTRIBS_EN |
+#if (defined(CONFIG_MACH_ZEFEERDZG) || defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ))
+			(1 << VIDEOATTRIBS_SDSEL_SHIFT));
+#else
+			(3 << VIDEOATTRIBS_SDSEL_SHIFT));
+#endif
+			
+
+#ifdef CONFIG_FB_LCD_EP93XX
+	uiPADDR = readl(GPIO_PADDR) | 0x2;
+	writel(uiPADDR, GPIO_PADDR);
+
+	uiPADR = readl(GPIO_PADR) | 0x2;
+	writel(uiPADR, GPIO_PADR);
+#endif
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+int __init ep93xxfb_init(void)
+{
+	char *option = NULL;
+	DPRINTK("ep93xxfb_init(void)\n");
+
+	/*
+	 * For kernel boot options (in 'video=xxxfb:<options>' format)
+	 */
+
+	fb_get_options("ep93xxfb", &option);
+	ep93xxfb_setup(option);
+
+	/* init all the important stuff in info */
+	if (!ep93xxfb_probe_configuration())
+		ep93xxfb_init_fbinfo();
+
+	/* Allocate and map framebuffer memory in system DRAM */
+	if (ep9312fb_map_video_memory() != 0)
+		return -ENOMEM;
+
+	/* This has to been done !!! */
+	fb_alloc_cmap(&info.cmap, MAX_PALETTE_NUM_ENTRIES, 0);
+
+	/* hard code, since we don't support modedb & friends yet */
+	ep93xxfb_set_var(&info.var, -1, &info);
+
+	if (register_framebuffer(&info) < 0)
+		return -EINVAL;
+
+	ep93xxfb_blank(FB_BLANK_UNBLANK, &info);
+
+	printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node,
+	       info.fix.id);
+
+	printk(KERN_INFO
+	       "ep93xxfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
+	       info.fix.smem_start, info.screen_base, info.fix.smem_len / 1024);
+	printk(KERN_INFO
+	       "ep93xxfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+	       ep93xxfb_var.xres, ep93xxfb_var.yres,
+	       ep93xxfb_var.bits_per_pixel, info.fix.line_length,
+	       screen_info.pages);
+
+	return 0;
+}
+
+static void __exit ep93xxfb_cleanup(void)
+{
+	DPRINTK("ep93xxfb_cleanup(void)\n");
+	unregister_framebuffer(&info);
+}
+
+int __init ep93xxfb_setup(char *options)
+{
+	DPRINTK("ep93xxfb_setup(char *options=\"%s\")\n", options);
+	/* TODO: Parse user speficied options (`video=ep93xxfb:') */
+	return 0;
+}
+
+module_init(ep93xxfb_init);
+module_exit(ep93xxfb_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Burian");
diff --git a/drivers/video/ep93xxfb.h b/drivers/video/ep93xxfb.h
new file mode 100644
index 0000000..dec4857
--- /dev/null
+++ b/drivers/video/ep93xxfb.h
@@ -0,0 +1,287 @@
+/*
+ * ep93xxfb.h 	Cirrus Logic EP93xx Framebuffer header
+ */
+
+/*
+ * TODO:
+ * 	Still lot's of messy stuff here that belongs elsewhere.
+ *
+ *	I'd say that each display / display family get an own header file
+ *	maybe even the whole ep93xx stuff should get an own directory, just like ati
+ *	It also could not hurt to test the NTSC stuff, which already was split into cx25871.c
+ *	but not tested to work so far.
+ *
+ *	Display initialisation should become human readable, it should be changed
+ *	to reflect what's going on in hardware.
+ *
+ *	This means we should say which PLL, prescaler, divider, ... is used instead
+ *	of just saying VDIV = 0x0000c207, same goes for all the other hardcoded values.
+ *
+ *	How will we handle higher clocked EP93xx once they are available?
+ *
+ */
+
+#define RasterSetLocked(registername,value) \
+    {                                       \
+        writel( 0xAA, REALITI_SWLOCK );       \
+        writel( value, registername);         \
+    }
+
+static void InitializeCX25871For640x480NTSC(void);
+
+struct ep93xxfb_par {
+	struct device *dev;
+	dma_addr_t p_screen_base;
+	unsigned char *v_screen_base;
+	unsigned long screen_size;
+	unsigned int palette_size;
+	unsigned int xres;
+	unsigned int yres;
+	unsigned int bits_per_pixel;
+	signed int montype;
+	unsigned int currcon;
+	unsigned int visual;
+	u16 palette[16];	/* Funky 16 table lookup used by "optional" Parameter. */
+};
+
+#define MAX_PALETTE_NUM_ENTRIES		256
+#define MAX_CRT_XRES	640
+#define MAX_CRT_YRES	480
+#define MAX_BPP		32
+#define FB_MAX_MEM_SIZE ((MAX_CRT_XRES * MAX_CRT_YRES * MAX_BPP)/8)
+#define FB_MAPPED_MEM_SIZE (PAGE_ALIGN(FB_MAX_MEM_SIZE + PAGE_SIZE))
+
+#define EP93XX_NAME	"EP93XX"
+#define NR_MONTYPES	1
+
+/* Fake monspecs to fill in fbinfo structure */
+static struct fb_monspecs monspecs __initdata = {
+	{30000, 70000, 50, 65, 0}	/* Generic */
+};
+
+#if defined (CONFIG_FB_LCD_EP93XX)
+#define DEFAULT_MODE 1
+#elif defined (CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343)
+#define DEFAULT_MODE 2
+#elif defined (CONFIG_FB_CX25871)
+#define DEFAULT_MODE 3
+#elif defined (CONFIG_FB_CRT_EP93XX)
+#define DEFAULT_MODE 0
+#elif defined (CONFIG_FB_LCD_EP93XX_SHARP)
+#define DEFAULT_MODE 5
+#define CONFIG_FB_LCD_EP93XX 1	/*hack!!! FIXME: put whole display support into different files */
+#elif defined (CONFIG_FB_LCD_TX09D50VM1CCA)
+#define DEFAULT_MODE 6
+#else
+#error What Display Setting was that!!!
+#endif
+
+struct DisplayTimingValues {
+	const char *Name;
+	unsigned long DisplayID;
+	int (*RasterConfigure) (struct DisplayTimingValues * pTimingValues);
+	unsigned short Refresh;
+	unsigned long VDiv;
+
+	unsigned short HRes;
+	unsigned short HFrontPorch;
+	unsigned short HBackPorch;
+	unsigned short HSyncWidth;
+	unsigned short HTotalClocks;
+
+	unsigned short VRes;
+	unsigned short VFrontPorch;
+	unsigned short VBackPorch;
+	unsigned short VSyncWidth;
+	unsigned short VTotalClocks;
+};
+
+typedef int (*fRasterConfigure) (struct DisplayTimingValues *);
+
+enum DisplayType {
+	CRT_GENERIC,
+	Philips_LB064V02A1,
+	CX25871,
+	Sharp
+};
+
+static int Conexant_CX25871(struct DisplayTimingValues *pTimingValues);
+static int NecLCD(struct DisplayTimingValues *pTimingValues);
+
+#define TIMING_VALUES(NAME, DISPID, FUNC, REFRESH, VDIV,                \
+                   HRES, HFP, HBP, HSYNC, VRES, VFP, VBP, VSYNC)        \
+{                                                                       \
+    Name:NAME,                                                          \
+    DISPID, FUNC, REFRESH, VDIV,                                        \
+    HRES, HFP, HBP, HSYNC, (HRES + HFP + HBP + HSYNC),                  \
+    VRES, VFP, VBP, VSYNC, (VRES + VFP + VBP + VSYNC)                   \
+}
+
+/* TODO:
+ *
+ * This is a big, confusing mess right now.
+ * We really should see if we can do it like Documentation/fb/modedb.txt
+ * suggests.
+ *
+ * Fix it, probably by moving this into ep93xx_modes.c or something like that
+ */
+
+static struct DisplayTimingValues TimingValues[] = {
+	/* 640x480 Progressive Scan */
+	TIMING_VALUES("CRT_GENERIC", CRT_GENERIC,
+		      (fRasterConfigure) NULL,
+		      60, 0x0000c108, 640, 16, 48, 96, 480, 11, 31, 2),
+	/* 640x480 Progressive Scan Philips LB064V02A1 on EDB9312 Board. */
+
+	/* Display can handle clocks from 22MHz(VDIV=0xc107)-28Mhz(VDIV=0xc106) */
+	TIMING_VALUES("Philips LB064V02A1", Philips_LB064V02A1,
+		      0,
+		      68, 0x0000c106, 640, 16, 48, 96, 480, 11, 31, 2),
+	/*fast refresh rate (26.7MHz) */
+	/*68, 0x0000c106, 640, 16, 48, 96, 480, 11, 31, 2), */
+	/*original setting (slowest refresh) (22.8MHz) */
+	/*68, 0x0000c107, 640, 16, 48, 96, 480, 11, 31, 2), */
+
+	/* Sharp LQ64D343 LCD Panel */
+	TIMING_VALUES("Sharp LQ64d343", CRT_GENERIC,
+		      (fRasterConfigure) NULL,
+		      60, 0x0000c205, 640, 32, 32, 96, 480, 34, 34, 4),
+	/* NEC LCD Panel */
+	TIMING_VALUES("NEC", CRT_GENERIC,
+		      NecLCD,
+		      60, 0x0000c204, 640, 32, 32, 96, 480, 34, 34, 4),
+	/* 640x480 NTSC Support for Conexant CX25871 */
+	TIMING_VALUES("Conexant CX25871", CX25871,
+		      Conexant_CX25871,
+		      60, 0x0000c317, 640, 0, 0, 0, 480, 0, 0, 0),
+	/* 320x240 Sharp LCD Panel */
+	TIMING_VALUES("Sharp LQ057Q3DC02", CRT_GENERIC,
+		      (fRasterConfigure) NULL,
+		      0, 0x0000c108, 320, 32, 32, 96, 240, 3, 3, 4),
+	/*
+		240x320 Hitachi
+	
+		Max pixel clock freq = 1/83ns ~= 12.048 MHz (VDiv = 0x0000c10a)
+		Typ pixel clock freq = 5.33 MHz (VDiv = 0x0000c125)
+	*/
+	TIMING_VALUES("Hitachi TX09D50VM1CCA", CRT_GENERIC,
+		      (fRasterConfigure)NULL,
+		      0, 0x0000c125, 240, 16/*HFP*/, 12/*HBP*/, 5/*HSYNC*/, 320, 3/*VFP*/, 3/*VBP*/, 1/*VSYNC*/), 
+	/* NULL */
+	TIMING_VALUES("Unknown", CRT_GENERIC,
+		      (fRasterConfigure) NULL,
+		      0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+
+};
+
+#define NUM_TIMING_VALUES (sizeof(TimingValues)/sizeof(struct DisplayTimingValues))
+
+#define NULL_MODE (NUM_TIMING_VALUES-1)
+
+#define EE_DELAY_USEC       100
+#define EE_READ_TIMEOUT     100
+#define CX25871_DEV_ADDRESS                     0x88
+#define CX25871_REGx32_AUTO_CHK                 0x80
+#define CX25871_REGx32_DRVS_MASK                0x60
+#define CX25871_REGx32_DRVS_SHIFT               5
+#define CX25871_REGx32_SETUP_HOLD               0x10
+#define CX25871_REGx32_INMODE_                  0x08
+#define CX25871_REGx32_DATDLY_RE                0x04
+#define CX25871_REGx32_OFFSET_RGB               0x02
+#define CX25871_REGx32_CSC_SEL                  0x01
+
+/* Register 0xBA */
+#define CX25871_REGxBA_SRESET                   0x80
+#define CX25871_REGxBA_CHECK_STAT               0x40
+#define CX25871_REGxBA_SLAVER                   0x20
+#define CX25871_REGxBA_DACOFF                   0x10
+#define CX25871_REGxBA_DACDISD                  0x08
+#define CX25871_REGxBA_DACDISC                  0x04
+#define CX25871_REGxBA_DACDISB                  0x02
+#define CX25871_REGxBA_DACDISA                  0x01
+
+/* Register 0xC4 */
+#define CX25871_REGxC4_ESTATUS_MASK             0xC0
+#define CX25871_REGxC4_ESTATUS_SHIFT            6
+#define CX25871_REGxC4_ECCF2                    0x20
+#define CX25871_REGxC4_ECCF1                    0x10
+#define CX25871_REGxC4_ECCGATE                  0x08
+#define CX25871_REGxC4_ECBAR                    0x04
+#define CX25871_REGxC4_DCHROMA                  0x02
+#define CX25871_REGxC4_EN_OUT                   0x01
+
+/* Register 0xC6 */
+#define CX25871_REGxC6_EN_BLANKO                0x80
+#define CX25871_REGxC6_EN_DOT                   0x40
+#define CX25871_REGxC6_FIELDI                   0x20
+#define CX25871_REGxC6_VSYNCI                   0x10
+#define CX25871_REGxC6_HSYNCI                   0x08
+#define CX25871_REGxC6_INMODE_MASK              0x07
+#define CX25871_REGxC6_INMODE_SHIFT             0
+
+#define GPIOG_EEDAT 2
+#define GPIOG_EECLK 1
+
+static int Conexant_CX25871(struct DisplayTimingValues *pTimingValues)
+{
+	unsigned int uiTemp;
+	InitializeCX25871For640x480NTSC();
+
+	RasterSetLocked(VIDEOATTRIBS, 0);
+	uiTemp = readl(SYSCON_DEVCFG);
+	SysconSetLocked(SYSCON_DEVCFG, (uiTemp | SYSCON_DEVCFG_EXVC));
+
+	RasterSetLocked(VLINESTOTAL, 0x0257);
+	RasterSetLocked(VSYNCSTRTSTOP, 0x01FF022C);	/* was 024c */
+	RasterSetLocked(VBLANKSTRTSTOP, 0x000001E0);
+	RasterSetLocked(VACTIVESTRTSTOP, 0x000001E0);
+	RasterSetLocked(VCLKSTRTSTOP, 0x07FF01E0);
+
+	RasterSetLocked(HCLKSTOTAL, 0x30F);
+	RasterSetLocked(HSYNCSTRTSTOP, 0x02c0030F);
+	RasterSetLocked(HBLANKSTRTSTOP, 0x00000280);
+	RasterSetLocked(HACTIVESTRTSTOP, 0x00000280);
+	RasterSetLocked(HCLKSTRTSTOP, 0x07ff0280);
+
+	RasterSetLocked(LINECARRY, 0);
+
+	RasterSetLocked(VIDEOATTRIBS,
+			VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN);
+
+	return 0;
+}
+
+static int NecLCD(struct DisplayTimingValues *pTimingValues)
+{
+	RasterSetLocked(VIDEOATTRIBS, 0);
+
+	RasterSetLocked(VLINESTOTAL, 0x020c);
+	RasterSetLocked(VSYNCSTRTSTOP, 0x01fe0200);	/* was 024c */
+	RasterSetLocked(VBLANKSTRTSTOP, 0x0000000);
+	RasterSetLocked(VACTIVESTRTSTOP, 0x020c01df);
+	RasterSetLocked(VCLKSTRTSTOP, 0x020c020c);
+
+	RasterSetLocked(HCLKSTOTAL, 0x323);
+	RasterSetLocked(HSYNCSTRTSTOP, 0x02c00321);
+	RasterSetLocked(HBLANKSTRTSTOP, 0x00000);
+	RasterSetLocked(HACTIVESTRTSTOP, 0x00100290);
+	RasterSetLocked(HCLKSTRTSTOP, 0x03230323);
+
+	RasterSetLocked(LINECARRY, 0);
+
+	RasterSetLocked(VIDEOATTRIBS, VIDEOATTRIBS_INVCLK |
+			VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_SYNCEN |
+			VIDEOATTRIBS_DATAEN);
+
+	return 0;
+}
+
+void InitializeCX25871For640x480NTSC(void)
+{
+/*
+ * If you need this see cx25871.[ch] and grep for "should be done".
+ * see if you can find a suitable and less messy way to do i2c stuff
+ * also see our patch against 2.6.11.7-ep93xx
+ */
+	printk("ERROR: InitializeCX25871For640x480NTSC unimplemented!\n");
+}
diff --git a/include/asm-arm/arch-ep93xx/adssphere.h b/include/asm-arm/arch-ep93xx/adssphere.h
new file mode 100644
index 0000000..97874c1
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/adssphere.h
@@ -0,0 +1,55 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/adssphere.h
+ *
+ *  Copyright (C) 2005 Robert Whaley <rwhaley@applieddata.net>
+ *
+ * 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
+ */
+#ifndef ASM_ARCH_ADSSPHERE_H
+#define ASM_ARCH_ADSSPHERE_H
+
+#define ADSSPHERE_BASE_VIRT  0xe2000000
+#define ADSSPHERE_BASE_PHYS  0xf0000000
+
+#define ADSSPHERE_CR0       (ADSSPHERE_BASE_VIRT+0x00)
+#define ADSSPHERE_CR1       (ADSSPHERE_BASE_VIRT+0x04)
+#define ADSSPHERE_SR        (ADSSPHERE_BASE_VIRT+0x08)
+#define ADSSPHERE_CAN_ADDR  (ADSSPHERE_BASE_VIRT+0x0c)
+#define ADSSPHERE_CAN_DATA  (ADSSPHERE_BASE_VIRT+0x10)
+#define ADSSPHERE_FW_FW_NUM (ADSSPHERE_BASE_VIRT+0x14)
+#define ADSSPHERE_FW_FW_REV (ADSSPHERE_BASE_VIRT+0x18)
+#define ADSSPHERE_FW_BD_REV (ADSSPHERE_BASE_VIRT+0x1c)
+
+#define ADSSPHERE_CR0_CF_33 0x01
+#define ADSSPHERE_CR0_CF_50 0x02
+#define ADSSPHERE_CR0_COMEN 0x04
+#define ADSSPHERE_CR0_IRDA  0x08
+#define ADSSPHERE_CR0_USB   0x10
+#define ADSSPHERE_CR0_PWSAV 0x20
+
+#define ADSSPHERE_CR1_PNL_ON 0x01
+#define ADSSPHERE_CR1_PNL_EN 0x04
+#define ADSSPHERE_CR1_BL_ON  0x08
+#define ADSSPHERE_CR1_AMP_ON 0x10
+#define ADSSPHERE_CR1_CDC_ON 0x20
+#define ADSSPHERE_CR1_BTL_ON 0x40
+
+#define ADSSPHERE_SR1_SW0 0x01
+#define ADSSPHERE_SR1_SW1 0x02
+#define ADSSPHERE_SR1_SW2 0x04
+#define ADSSPHERE_SR1_SW3 0x08
+#define ADSSPHERE_SR1_HP  0x10
+
+#endif /* ASM_ARCH_ADSSPHERE_H */
diff --git a/include/asm-arm/arch-ep93xx/clocks.h b/include/asm-arm/arch-ep93xx/clocks.h
new file mode 100644
index 0000000..acc8023
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/clocks.h
@@ -0,0 +1,160 @@
+/*
+ *
+ * Filename: clocks.h
+ *
+ * Description: Header file for the clocks.
+ *
+ * Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#include <asm/hardware.h>
+#ifndef _H_CLOCKS
+#define _H_CLOCKS
+
+/*
+ * How this file works:
+ * Choose your FCLOCK value this causes FDIV, HDIV, PDIV values to be set
+ *
+ * The Real FDIV, HDIV, and PDIV are set according to the following table.
+ * Processor runs at (PLL1 speed/PLL Divide specified by FDIV)
+ * AHB runs at (PLL1 speed/PLL Divide specified by HDIV)
+ * APB runs at AHB/(2^PDIV)
+ * ------------------------------------------------------------------
+ * HDIV   PLL Divide    FDIV    PLL Divide
+ * 0      1             0       1
+ * 1      2             1       2
+ * 2      4             2       4
+ * 3      5             3       8
+ * 4      6             4       16
+ * 5      8
+ * 6      16
+ * 7      32
+ *
+ */
+
+/* there is some confusion here about MACH vs. ARCH. clean it up
+   once we get a nice clock management system going */
+#ifdef CONFIG_ARCH_EP9301
+#define FCLOCK 166
+#define EP93XX_UART_CLK 14745600
+#endif
+
+#ifdef CONFIG_MACH_EDB9302
+#define FCLOCK 200
+#define EP93XX_UART_CLK 14745600
+#endif
+
+#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_ADSSPHERE)
+#define FCLOCK 200
+#define EP93XX_UART_CLK 14745600
+#endif
+
+#if defined(CONFIG_MACH_DMA03)
+#define FCLOCK 200
+#define EP93XX_UART_CLK 14745600
+#endif
+
+#ifdef CONFIG_MACH_ACC
+#define EP93XX_UART_CLK 24576000
+#endif
+
+#if defined(CONFIG_MACH_ZEFEERDZA)
+#define FCLOCK 166
+#define EP93XX_UART_CLK 14745600
+#endif
+
+#if defined(CONFIG_MACH_ZEFEERDZB) || defined(CONFIG_MACH_ZEFEERDZG) || \
+    defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ)
+#define FCLOCK 200
+#define EP93XX_UART_CLK 14745600
+#endif
+
+/*
+ * PLL1 Clock =442  Mhz
+ *
+ * FClock    = 221  Mhz
+ * HCLock    = 73   Mhz
+ * PClock    = 46   Mhz
+ */
+#if (FCLOCK == 221)
+#define FDIV                        1
+#define HDIV                        5
+#define PDIV                        1
+#define PRE_CLKSET1_VALUE           0x0080b3b6
+#define PLL1_CLOCK                  442368000
+#endif				/* (FCLOCK == 221) */
+
+/*
+ * PLL1 Clock =400  Mhz
+ *
+ * FClock    = 200  Mhz
+ * HCLock    = 100  Mhz
+ * PClock    = 50   Mhz
+ *
+ */
+#if (FCLOCK == 200)
+#define FDIV                        1
+#define HDIV                        2
+#define PDIV                        1
+#define PRE_CLKSET1_VALUE           0x0080a3d7
+#define PLL1_CLOCK                  399974400
+#endif				/* (FCLOCK == 200) */
+
+/*
+ * PLL1 Clock =368  Mhz
+ *
+ * FClock    = 184  Mhz
+ * HCLock    = 73   Mhz
+ * PClock    = 46   Mhz
+ *
+ */
+#if (FCLOCK == 183)
+#define FDIV                        1
+#define HDIV                        4
+#define PDIV                        1
+#define PRE_CLKSET1_VALUE           0x0080ab15
+#define PLL1_CLOCK                  368640000
+#endif				/* (FCLOCK == 183) */
+
+/*
+ * PLL1 Clock =332  Mhz
+ *
+ * FClock    = 166  Mhz
+ * HCLock    = 66   Mhz
+ * PClock    = 33   Mhz
+ *
+ */
+#if (FCLOCK == 166)
+#define FDIV                        1
+#define HDIV                        3
+#define PDIV                        1
+#define PRE_CLKSET1_VALUE           0x0080fa5a
+#define PLL1_CLOCK                  332049067
+#endif				/* (FCLOCK == 166) */
+
+#define CLKSET1_VALUE   ( PRE_CLKSET1_VALUE | \
+                        ( PDIV << SYSCON_CLKSET1_PCLK_DIV_SHIFT ) | \
+                        ( HDIV << SYSCON_CLKSET1_HCLK_DIV_SHIFT ) | \
+                        ( FDIV << SYSCON_CLKSET1_FCLK_DIV_SHIFT ) )
+
+/*
+ * Value for the PLL 2 register.
+ */
+#define CLKSET2_VALUE           0x300dc317
+#define PLL2_CLOCK              192000000
+
+#endif				/*  _H_CLOCKS  */
diff --git a/include/asm-arm/arch-ep93xx/crunch.h b/include/asm-arm/arch-ep93xx/crunch.h
new file mode 100644
index 0000000..db9fb2e
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/crunch.h
@@ -0,0 +1,48 @@
+#ifndef	__asm_crunch_h__
+#define	__asm_crunch_h__
+
+#define	CRUNCH_INIT	0x00900000
+#define	CRUNCH_IRQ	58
+
+#ifndef	__ASSEMBLY__
+
+/* enable the MaverickCrunch clock */
+static inline void crunch_enable(void)
+{
+	int tmp, aa = 0xAA;
+	int *lock = (int *)0xe09300c0;
+	int *syscfg = (int *)0xe0930080;
+
+	asm volatile ("str    %3, [%1]\n\t"
+		      "ldr    %0, [%2]\n\t"
+		      "orr    %0, %0, #(1 << 23)\n\t"
+		      "str    %0, [%2]":"=r" (tmp)
+		      :"r"(lock), "r"(syscfg), "r"(aa)
+		      :"memory");
+}
+
+/* disable the MaverickCrunch clock */
+static inline void crunch_disable(void)
+{
+	int tmp, aa = 0xAA;
+	int *lock = (int *)0xe09300c0;
+	int *syscfg = (int *)0xe0930080;
+
+	asm volatile ("str    %3, [%1]\n\t"
+		      "ldr    %0, [%2]\n\t"
+		      "bic    %0, %0, #(1 << 23)\n\t"
+		      "str    %0, [%2]":"=r" (tmp)
+		      :"r"(lock), "r"(syscfg), "r"(aa)
+		      :"memory");
+}
+
+unsigned int read_dspsc_low(void);
+unsigned int read_dspsc_high(void);
+void write_dspsc(unsigned int);
+void save_fpu(struct task_struct *);
+void restore_fpu(struct task_struct *);
+int setup_crunch(void);
+void crunch_init(void);
+#endif
+
+#endif				/* __asm_crunch_h__ */
diff --git a/include/asm-arm/arch-ep93xx/cx25871.h b/include/asm-arm/arch-ep93xx/cx25871.h
new file mode 100644
index 0000000..9d68ed9
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/cx25871.h
@@ -0,0 +1,69 @@
+/*
+ * Filename: cx25871.h
+ *
+ * Description: Regisister Definitions and function prototypes for
+ *             CX25871 NTSC/PAL encoder.
+ *
+ * Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved
+ *
+ * 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
+ */
+
+#ifndef _H_CX25871
+#define _H_CX25871
+
+/* CS25871 Device Address. */
+#define CX25871_DEV_ADDRESS                     0x88
+
+/* Register 0x32 */
+#define CX25871_REGx32_AUTO_CHK                 0x80
+#define CX25871_REGx32_DRVS_MASK                0x60
+#define CX25871_REGx32_DRVS_SHIFT               5
+#define CX25871_REGx32_SETUP_HOLD               0x10
+#define CX25871_REGx32_INMODE_                  0x08
+#define CX25871_REGx32_DATDLY_RE                0x04
+#define CX25871_REGx32_OFFSET_RGB               0x02
+#define CX25871_REGx32_CSC_SEL                  0x01
+
+/* Register 0xBA */
+#define CX25871_REGxBA_SRESET                   0x80
+#define CX25871_REGxBA_CHECK_STAT               0x40
+#define CX25871_REGxBA_SLAVER                   0x20
+#define CX25871_REGxBA_DACOFF                   0x10
+#define CX25871_REGxBA_DACDISD                  0x08
+#define CX25871_REGxBA_DACDISC                  0x04
+#define CX25871_REGxBA_DACDISB                  0x02
+#define CX25871_REGxBA_DACDISA                  0x01
+
+/* Register 0xC4 */
+#define CX25871_REGxC4_ESTATUS_MASK             0xC0
+#define CX25871_REGxC4_ESTATUS_SHIFT            6
+#define CX25871_REGxC4_ECCF2                    0x20
+#define CX25871_REGxC4_ECCF1                    0x10
+#define CX25871_REGxC4_ECCGATE                  0x08
+#define CX25871_REGxC4_ECBAR                    0x04
+#define CX25871_REGxC4_DCHROMA                  0x02
+#define CX25871_REGxC4_EN_OUT                   0x01
+
+/* Register 0xC6 */
+#define CX25871_REGxC6_EN_BLANKO                0x80
+#define CX25871_REGxC6_EN_DOT                   0x40
+#define CX25871_REGxC6_FIELDI                   0x20
+#define CX25871_REGxC6_VSYNCI                   0x10
+#define CX25871_REGxC6_HSYNCI                   0x08
+#define CX25871_REGxC6_INMODE_MASK              0x07
+#define CX25871_REGxC6_INMODE_SHIFT             0
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/debug-macro.S b/include/asm-arm/arch-ep93xx/debug-macro.S
new file mode 100644
index 0000000..3d97614
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/debug-macro.S
@@ -0,0 +1,56 @@
+/* linux/include/asm-arm/arch-ep93xx/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ray Lehtiniemi
+ *
+ * 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.
+ *
+*/
+
+                .macro  addruart,rx
+                mrc     p15, 0, \rx, c1, c0
+                tst     \rx, #1                         @ MMU enabled?
+                ldreq   \rx, =IO_BASE_PHYS              @ System peripherals (phys address)
+                ldrne   \rx, =IO_BASE_VIRT              @ System peripherals (virt address)
+                orr     \rx,\rx,#0x008c0000             @ Advance to UART1Base
+
+                @ We probe for the active serial port here.
+                @ We assume r1 can be clobbered.
+
+                @ see if UART1 is active
+                ldr     r1, [\rx, #0x14]                @UART1Ctrl
+                tst     r1, #1
+
+                @ if UART1 is inactive advance to UART2
+                addeq   \rx, \rx, #0x00010000
+                ldreq   r1, [\rx, #0x14]                @UART2Ctrl
+                tsteq   r1, #1
+
+                @ if UART2 is inactive advance to UART3
+                addeq   \rx, \rx, #0x00010000
+                ldreq   r1, [\rx, #0x14]                @UART3Ctrl
+                tsteq   r1, #1
+
+                @ if all ports are inactive, then there is nothing we can do
+                moveq   pc, lr
+                .endm
+
+                .macro  senduart,rd,rx
+                strb    \rd, [\rx]                      @ UARTxData
+                .endm
+
+                .macro  waituart,rd,rx
+1001:           ldr     \rd, [\rx, #0x18]               @ UARTxFlag
+                tst     \rd, #0x20                      @ TXFF = 0 when ok to transmit
+                bne     1001b
+                .endm
+
+                .macro  busyuart,rd,rx
+1001:           ldr     \rd, [\rx, #0x18]               @ UARTxFlag
+                tst     \rd, #0x08                      @ BUSY = 1 while transmitting
+                bne     1001b
+                .endm
diff --git a/include/asm-arm/arch-ep93xx/dma.h b/include/asm-arm/arch-ep93xx/dma.h
new file mode 100644
index 0000000..d3b6493
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/dma.h
@@ -0,0 +1,233 @@
+/*****************************************************************************
+ *  linux/include/asm-arm/arch-ep93xx/dma.h
+ *
+ *  Copyright (C) 2003 Cirrus Logic
+ *
+ * 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
+ *
+ ****************************************************************************/
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS     0xffffffff
+
+/*
+ *  Not using the regular generic DMA interface for ep93xx.
+ */
+#define MAX_DMA_CHANNELS   0
+
+/*
+ * The ep93xx dma controller has 5 memory to peripheral (TX) channels, 5
+ * peripheral to memory (RX) channels and 2 memory to memory channels.
+ */
+#define MAX_EP93XX_DMA_M2P_CHANNELS 10
+#define MAX_EP93XX_DMA_M2M_CHANNELS 2
+
+/*
+ * The generic arm linux api does not support the ep93xx dma model, therefore
+ * we use a set of dma support functions written specifically for this dma
+ * controller.
+ */
+#define MAX_EP93XX_DMA_CHANNELS (MAX_EP93XX_DMA_M2P_CHANNELS + MAX_EP93XX_DMA_M2M_CHANNELS)
+
+/*****************************************************************************
+ *
+ * Max DMA buffer size
+ *
+ ****************************************************************************/
+#define DMA_MAX_BUFFER_BYTES    0xFFFF
+
+/*****************************************************************************
+ *
+ * typedefs
+ *
+ ****************************************************************************/
+
+/*****************************************************************************
+ *
+ * All devices which can use a DMA channel
+ *
+ * NOTE: There exist two types of DMA channels, those that transfer
+ *       between an internal peripheral and memory (M2P/P2M), and
+ *       those that transfer between an external peripheral and memory (M2M).
+ *       This becomes a bit confusing when you take into account the fact
+ *       that the M2M channels can also transfer between two specific
+ *       internal peripherals and memory.
+ *       The first 20 enumerated devices use the first type of channel (M2P/
+ *       P2M).  The last six enumerations are specific to the M2M channels.
+ *
+ ****************************************************************************/
+typedef enum {
+	/*
+	 *  Hardware device options for the 10 M2P/P2M DMA channels.
+	 */
+	DMATx_I2S1 = 0x00000000,	/* TX peripheral ports can be allocated an  */
+	DMATx_I2S2 = 0x00000001,	/* even numbered DMA channel.               */
+	DMATx_AAC1 = 0x00000002,
+	DMATx_AAC2 = 0x00000003,
+	DMATx_AAC3 = 0x00000004,
+	DMATx_I2S3 = 0x00000005,
+	DMATx_UART1 = 0x00000006,
+	DMATx_UART2 = 0x00000007,
+	DMATx_UART3 = 0x00000008,
+	DMATx_IRDA = 0x00000009,
+	DMARx_I2S1 = 0x0000000A,	/* RX perhipheral ports can be allocated an */
+	DMARx_I2S2 = 0x0000000B,	/* odd numbered DMA channel.                */
+	DMARx_AAC1 = 0x0000000C,
+	DMARx_AAC2 = 0x0000000D,
+	DMARx_AAC3 = 0x0000000E,
+	DMARx_I2S3 = 0x0000000F,
+	DMARx_UART1 = 0x00000010,
+	DMARx_UART2 = 0x00000011,
+	DMARx_UART3 = 0x00000012,
+	DMARx_IRDA = 0x00000013,
+
+	/*
+	 *  Device options for the 2 M2M DMA channels
+	 */
+	DMA_MEMORY = 0x00000014,
+	DMA_IDE = 0x00000015,
+	DMARx_SSP = 0x00000016,
+	DMATx_SSP = 0x00000017,
+	DMATx_EXT_DREQ = 0x00000018,
+	DMARx_EXT_DREQ = 0x00000019,
+	UNDEF = 0x0000001A
+} ep93xx_dma_dev_t;
+
+/*****************************************************************************
+ *
+ * Enumerated type used as a parameter for a callback function.
+ * Indicates the type of interrupt.
+ *
+ ****************************************************************************/
+typedef enum {
+	/*
+	 *  Common interrupts
+	 */
+	STALL,
+	NFB,
+
+	/*
+	 *  Specific to M2P channels
+	 */
+	CHERROR,
+
+	/*
+	 *  Specific to M2M channels
+	 */
+	DONE,
+	UNDEF_INT
+} ep93xx_dma_int_t;
+
+/*****************************************************************************
+ *
+ * Init flag bit defintions for M2P/P2M flags.
+ *
+ ****************************************************************************/
+
+/*
+ *  Channel error interrupt enable.
+ */
+#define CHANNEL_ERROR_INT_ENABLE    0x00000001
+/*
+ *  Determines how the channel state machine behaves in the NEXT state and
+ *  in receipt of a peripheral error.
+ *  0 -> NEXT -> ON (ignore the peripheral error.)
+ *  1 -> NEXT -> STALL (effectively disable the channel.)
+ */
+#define EP93XX_DMA_ABORT                       0x00000002
+/*
+ *  Ignore channel error interrupt.
+ */
+#define IGNORE_CHANNEL_ERROR        0x00000004
+
+/*****************************************************************************
+ *
+ * Init flag bit defintions for M2M flags.
+ *
+ ****************************************************************************/
+
+/*
+ *  Destination address hold.  This should be set for IDE write transfers
+ */
+#define DESTINATION_HOLD            0x0000001
+/*
+ *  Source Address hold. This should be set for IDE read transfers
+ */
+#define SOURCE_HOLD                 0x0000002
+/*
+ *  Transfer mode.
+ *  00 - s/w initiated M2M transfer
+ *  01 - h/w initiated external peripheral transfer - memory to external
+ *       peripheral/IDE/SSP.
+ *  10 - h/w initiated external peripheral transfer - external
+ *        peripheral/IDE/SSP to memory.
+ *  11 - not used.
+ */
+#define TRANSFER_MODE_MASK          0x000000C
+#define TRANSFER_MODE_SHIFT         2
+#define TRANSFER_MODE_SW            0x0000000
+#define TRANSFER_MODE_HW_M2P        0x0000004
+#define TRANSFER_MODE_HW_P2M        0x0000008
+/*
+ *  Peripheral wait states count. Latency in HCLK cycles needed by the
+ *  peripheral to de-assert its request line once the transfer is
+ *  finished.
+ *
+ *  IDE Operation           Wait States
+ *  --------------          ------------
+ *  IDE MDMA read               0
+ *  IDE MDMA write              0
+ *  IDE UDMA read               1
+ *  IDE UDMA write              2
+ */
+#define WAIT_STATES_MASK            0x00007F0
+#define WAIT_STATES_SHIFT           4
+#define WS_IDE_MDMA_READ_WRITE      0
+#define WS_IDE_UDMA_READ            1
+#define WS_IDE_UDMA_WRITE           2
+
+/*****************************************************************************
+ *
+ * Type definition for the callback function
+ *
+ ****************************************************************************/
+typedef void (*dma_callback) (ep93xx_dma_int_t dma_int,
+			      ep93xx_dma_dev_t device, unsigned int user_data);
+
+/*****************************************************************************
+ *
+ * API function prototypes
+ *
+ ****************************************************************************/
+extern int ep93xx_dma_request(int *handle, const char *device_id,
+			      ep93xx_dma_dev_t device);
+extern int ep93xx_dma_free(int handle);
+extern int ep93xx_dma_config(int handle, unsigned int flags_m2p,
+			     unsigned int flags_m2m,
+			     dma_callback callback, unsigned int user_data);
+extern int ep93xx_dma_add_buffer(int handle, unsigned int source,
+				 unsigned int dest, unsigned int size,
+				 unsigned int last, unsigned int buf_id);
+extern int ep93xx_dma_remove_buffer(int handle, unsigned int *buf_id);
+extern int ep93xx_dma_start(int handle, unsigned int channels,
+			    unsigned int *handles);
+extern int ep93xx_dma_pause(int handle, unsigned int channels,
+			    unsigned int *handles);
+extern int ep93xx_dma_flush(int handle);
+extern int ep93xx_dma_queue_full(int handle);
+extern int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
+                	    unsigned int * total, unsigned int * current_frac);
+#endif				/* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-ep93xx/entry-macro.S b/include/asm-arm/arch-ep93xx/entry-macro.S
new file mode 100644
index 0000000..cab811e
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/entry-macro.S
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-ep93xx/entry-macro.S
+ *
+ * Low-level IRQ helper macros for EP93XX-based platforms
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+                .macro  disable_fiq
+                .endm
+
+                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+                ldr     \irqstat, =VIC0IRQSTATUS
+                ldr     \irqstat, [\irqstat, #0]                        @ get masked status
+
+                mov     \irqnr, #0
+1001:           tst     \irqstat, #1
+                bne     1003f
+                add     \irqnr, \irqnr, #1
+                mov     \irqstat, \irqstat, lsr #1
+                cmp     \irqnr, #32
+                bcc     1001b
+                /* EQ will be set if we reach 32 */
+
+                ldr     \irqstat, =VIC1IRQSTATUS
+                ldr     \irqstat, [\irqstat, #0]                        @ get masked status
+
+1002:           tst     \irqstat, #1
+                bne     1003f
+                add     \irqnr, \irqnr, #1
+                mov     \irqstat, \irqstat, lsr #1
+                cmp     \irqnr, #64
+                bcc     1002b
+                /* EQ will be set if we reach 64 */
+
+1003:
+                .endm
diff --git a/include/asm-arm/arch-ep93xx/hardware.h b/include/asm-arm/arch-ep93xx/hardware.h
new file mode 100644
index 0000000..f390858
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/hardware.h
@@ -0,0 +1,60 @@
+/*
+ *  File:   linux/include/asm-arm/arch-ep93xx/hardware.h
+ *
+ *  Copyright (C) 2003 Cirrus Logic, Inc
+ *
+ *  Copyright (C) 1999 ARM Limited.
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/arch/clocks.h>
+#include <asm/arch/memory.h>
+#include <asm/arch/regmap.h>
+
+/*
+ * When adding your regs-*.h file here, please be careful to not have any
+ * macros being doubly defined.  You may need to comment out a section of
+ * regmap.h to prevent that.
+ */
+#include <asm/arch/regs_ac97.h>
+#include <asm/arch/regs_dma.h>
+#include <asm/arch/regs_gpio.h>
+#include <asm/arch/regs_ide.h>
+#include <asm/arch/regs_i2s.h>
+#include <asm/arch/regs_irda.h>
+#include <asm/arch/regs_pcmcia.h>
+#include <asm/arch/regs_raster.h>
+#include <asm/arch/regs_spi.h>
+#include <asm/arch/regs_syscon.h>
+#include <asm/arch/regs_touch.h>
+#include <asm/arch/regs_uart.h>
+
+#include <asm/arch/regs_hardcode.h>
+
+#include <asm/arch/cx25871.h>
+
+/*
+ * Here's a safe way for calculating jiffies that won't break if the
+ * value of HZ changes.
+ */
+#ifndef	MSECS_TO_JIFFIES
+#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
+#endif
+
+#endif				/* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-ep93xx/ide.h b/include/asm-arm/arch-ep93xx/ide.h
new file mode 100644
index 0000000..7eb7faa
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/ide.h
@@ -0,0 +1,235 @@
+/*****************************************************************************
+ *  linux/include/asm-arm/arch-ep93xx/ide.h
+ *
+ *  IDE definitions for the EP93XX architecture
+ *
+ *
+ *  Copyright (c) 2003 Cirrus Logic, Inc., All rights reserved.
+ *
+ * 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
+ *
+ ****************************************************************************/
+#ifndef ASM_ARCH_IDE_H
+#define ASM_ARCH_IDE_H
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/scatterlist.h>
+
+/*
+ *  Maximum number of IDE interfaces for this architecture is 1.
+ */
+#ifdef CONFIG_BLK_DEV_EP93XX
+#undef  MAX_HWIFS
+#define MAX_HWIFS	1
+#endif
+/*
+ *  Default PIO mode used for setting up DMA commands
+ */
+#define DEFAULT_PIO_MODE	    4
+
+/*
+ *  ATA Command Register addresses.
+ */
+
+#define DATAREGISTER            0x00
+#define ERRORREGISTER           0x01
+#define FEATURESREGISTER        0x01
+#define SECTORCOUNTREGISTER     0x02
+#define SECTORNUMBERREGISTER    0x03
+#define CYLINDERLOWREGISTER     0x04
+#define CYLINDERHIGHREGISTER    0x05
+#define DEVICEHEADREGISTER      0x06
+#define COMMANDREGISTER         0x07
+#define STATUSREGISTER          0x07
+
+/*
+ *  ATA Control Register addresses.
+ */
+#define DEVICECONTROLREGISTER   0x06
+#define ALTERNATESTATUSREGISTER 0x06
+
+/*
+ *  ATA Register Bit Masks
+ */
+#define ATASRST  		        0x04
+#define ATAnIEN  		        0x02
+#define ATADEV   		        0x10
+#define ATAABRT  		        0x04
+#define ATABSY   		        0x80
+#define ATADRDY  		        0x40
+#define ATADRQ   		        0x08
+#define ATAERR   		        0x01
+#define ATADEVFAULT		        0x20
+#define	ATAWRITEFAULT	        0x20
+#define ATASERVICE 		        0x10
+#define ATACORRECTED	        0x04
+#define ATAINDEX		        0x02
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
+
+#define EP93XX_DMA_TODEVICE     1
+#define EP93XX_DMA_FROMDEVICE   2
+
+/****************************************************************************
+ *
+ * Map a set of buffers described by scatterlist in streaming
+ * mode for DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ *
+ ****************************************************************************/
+static inline int
+ep93xx_map_sg(struct scatterlist *sg, unsigned int entries,
+	      unsigned int direction)
+{
+	unsigned int loop;
+
+	for (loop = 0; loop < entries; loop++, sg++) {
+		consistent_sync(sg->__address, sg->length, direction);
+		sg->dma_address = virt_to_bus(sg->__address);
+	}
+
+	return entries;
+}
+
+#endif				/* CONFIG_BLK_DEV_IDEDMA_EP93XX */
+
+/*****************************************************************************
+ *
+ * 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
+old_ide_init_hwif_ports(hw_regs_t * hw, int data_port, int ctrl_port, int *irq)
+{
+	unsigned long reg;
+	int i;
+	printk("ide_init_hwif_ports\n");
+	printk("ide_init_hwif_ports(hw=%p data_port=%08x, ctrl_port=%08x \n",
+	       hw, data_port, ctrl_port);
+
+	/*
+	 *  Set up the IDE interface for PIO transfers, using the default PIO
+	 *  mode.
+	 */
+	ep93xx_ide_regs->IDECFG.Field.PIO = 1;
+	ep93xx_ide_regs->IDECFG.Field.MODE = DEFAULT_PIO_MODE;
+	ep93xx_ide_regs->IDECFG.Field.WST = 0;
+
+	/*
+	 *  Enable the IDE interface.
+	 */
+	ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
+
+	/*
+	 *  Set up the ide device command register offsets in the io_port array.
+	 *  This offset includes the register offset and the bit settings for
+	 *  CS0n and CS1n.
+	 */
+	reg = (unsigned long)data_port;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = (reg << 2) + 2;
+		reg += 1;
+
+		printk(" io_ports: %08lx\n", hw->io_ports[i]);
+	}
+
+	/*
+	 *  Set up the register offset for the device control registers.
+	 *  This offset includes the register offset and the bit settings for
+	 *  CS0n and CS1n.
+	 */
+	reg = (unsigned long)ctrl_port;
+	hw->io_ports[IDE_CONTROL_OFFSET] = (reg << 2) + 1;
+	printk("-io_ports: %08lx\n", hw->io_ports[IDE_CONTROL_OFFSET]);
+
+	if (irq)
+		*irq = 0;
+
+}
+
+extern void ep93xx_ide_init(struct hwif_s *hwif);
+
+/*****************************************************************************
+ *
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ *
+ ****************************************************************************/
+static __inline__ void old_ide_init_default_hwifs(void)
+{
+	hw_regs_t hw;
+
+	struct hwif_s *hwif;
+	unsigned int uiTemp;
+
+	/*
+	 *  Make sure the GPIO on IDE bits in the DEVCFG register are not set.
+	 */
+	uiTemp =
+	    readl(SYSCON_DEVCFG) & ~(SYSCON_DEVCFG_EonIDE |
+				     SYSCON_DEVCFG_GonIDE |
+				     SYSCON_DEVCFG_HonIDE);
+
+	SysconSetLocked(SYSCON_DEVCFG, uiTemp);
+
+	/*
+	 *  Initialize the IDE interface
+	 */
+	old_ide_init_hwif_ports(&hw, DATAREGISTER, DEVICECONTROLREGISTER, NULL);
+
+	/*
+	 *  Get the interrupt.
+	 */
+	hw.irq = IRQ_EIDE;
+
+	/*
+	 * This is the dma channel number assigned to this IDE interface. Until
+	 * dma is enabled for this interface, we set it to NO_DMA.
+	 */
+	hw.dma = NO_DMA;
+	
+	/*
+	 * Kernels > 2.6.15-rcX crash when leaving this uninitialized
+	 */	
+	hw.dev = NULL;
+	
+	/*
+	 *  Register the IDE interface, an ide_hwif_t pointer is passed in,
+	 *  which will get filled in with the hwif pointer for this interface.
+	 */
+	ide_register_hw(&hw, &hwif);
+
+	/*
+	 *  Set up a pointer to the ep93xx ideproc function.
+	 */
+	ep93xx_ide_init(hwif);
+
+	printk
+	    ("Cirrus Logic EP93XX IDE initialization - driver version 1.0, 5/21/03. \n");
+}
+#endif				/* ASM_ARCH_IDE_H */
diff --git a/include/asm-arm/arch-ep93xx/io.h b/include/asm-arm/arch-ep93xx/io.h
new file mode 100644
index 0000000..7e2e087
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/io.h
@@ -0,0 +1,29 @@
+/*
+ *  File:	linux/include/asm-arm/arch-ep93xx/io.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)			((void __iomem *)(a))
+#define __mem_pci(a)		(a)
+#define __mem_isa(a)		(a)
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
new file mode 100644
index 0000000..7a58d27
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/irqs.h
@@ -0,0 +1,150 @@
+/*
+ *  File:	linux/include/asm-arm/arch-ep93xx/irqs.h
+ *
+ * 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
+ */
+
+/*
+ *  Linux IRQ interrupts definitions here.
+ *	TBD not worth the effort to put duplicate bit defines in platform.h
+ *
+ *	Current IRQ implementation
+ *
+ *	1.  Current implementation does not support vectored
+ *          interrupts.  support for this feature may be
+ *          added later.
+ *	2.  FIQs are ignored.  None are assigned.
+ *	3.  All interrupts are assigned to IRQs.
+ *	5.  IRQ numbers are same as interrupt bit numbers.
+ *
+ */
+
+/* First two interrupt bit assignments are unused. */
+#define IRQ_RFU0	0
+#define IRQ_RFU1	1
+
+#define IRQ_COMMRX	2
+#define IRQ_COMMTX	3
+
+/* Renamed TCXOI to TIMERX for consistency */
+#define IRQ_TIMER1	4
+#define IRQ_TIMER2	5
+
+#define IRQ_AAC         6
+
+#define IRQ_DMAM2P0	7
+#define IRQ_DMAM2P1	8
+#define IRQ_DMAM2P2     9
+#define IRQ_DMAM2P3	10
+#define IRQ_DMAM2P4	11
+#define IRQ_DMAM2P5	12
+#define IRQ_DMAM2P6	13
+#define IRQ_DMAM2P7	14
+#define IRQ_DMAM2P8	15
+#define IRQ_DMAM2P9     16
+
+#define IRQ_DMAM2M0	17
+#define IRQ_DMAM2M1	18
+
+#define IRQ_GPIO0	19
+#define IRQ_GPIO1	20
+#define IRQ_GPIO2	21
+#define IRQ_GPIO3	22
+
+#define IRQ_UARTRX1	23
+#define IRQ_UARTTX1	24
+#define IRQ_UARTRX2	25
+#define IRQ_UARTTX2	26
+#define IRQ_UARTRX3	27
+#define IRQ_UARTTX3	28
+
+#define IRQ_KEY	        29
+#define IRQ_TOUCH	30
+#define IRQ_GRAPHICS	31
+
+/* TODO - this was IRQ_INTX, may need to make changes in code */
+#define IRQ_EXT0	32
+#define IRQ_EXT1	33
+#define IRQ_EXT2	34
+
+#define IRQ_64HZ	35
+#define IRQ_WEINT	36
+#define IRQ_RTC 	37
+
+#define IRQ_IRDA	38
+#define IRQ_MAC 	39
+
+#define IRQ_EXT3	40
+#define IRQ_EIDE	IRQ_EXT3
+
+#define IRQ_PROG	41
+#define IRQ_1HZ 	42
+#define IRQ_VSYNC	43
+#define IRQ_VIDEOFIFO	44
+
+#define IRQ_SSPRX	45
+#define IRQ_SSPTX	46
+
+#define IRQ_GPIO4	47
+
+#define IRQ_GPIO5	48
+#define IRQ_GPIO6	49
+#define IRQ_GPIO7	50
+
+#define IRQ_TIMER3	51
+
+#define IRQ_UART1	52
+#define IRQ_SSP 	53
+
+#define IRQ_UART2	54
+#define IRQ_UART3	55
+
+#define IRQ_USH 	56
+#define IRQ_PME 	57
+#define IRQ_DSP 	58
+#define IRQ_GPIO	59
+
+#define IRQ_RFU60	60
+#define IRQ_RFU61	61
+#define IRQ_RFU62	62
+#define IRQ_RFU63	63
+
+#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
+#define IRQ_TO_BIT(irq) (1 << ((irq - NR_GLBL_IRQS) % 16))
+
+#define NR_GLBL_IRQS    64
+
+#define GPIO_IRQ0	64
+#define GPIO_IRQ1	65
+#define GPIO_IRQ2	66
+#define GPIO_IRQ3	67
+#define GPIO_IRQ4	68
+#define GPIO_IRQ5	69
+#define GPIO_IRQ6	70
+#define GPIO_IRQ7	71
+#define GPIO_IRQ8	72
+#define GPIO_IRQ9	73
+#define GPIO_IRQ10	74
+#define GPIO_IRQ11	75
+#define GPIO_IRQ12	76
+#define GPIO_IRQ13	77
+#define GPIO_IRQ14	78
+#define GPIO_IRQ15	79
+
+#define IRQ_CHAINED_GPIO(x)   (NR_GLBL_IRQS + x)
+#define NR_IRQS               IRQ_CHAINED_GPIO(16) 		/* with GPIO IRQs EP9315 has 80 IRQs */
+#else
+#define NR_IRQS    64 						/* without GPIO IRQs EP9315 has 64 IRQs */
+#endif
diff --git a/include/asm-arm/arch-ep93xx/keyboard.h b/include/asm-arm/arch-ep93xx/keyboard.h
new file mode 100644
index 0000000..685ff17
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/keyboard.h
@@ -0,0 +1,54 @@
+/*
+ *  linux/include/asm-arm/arch-integrator/keyboard.h
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions 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.
+ *
+ * 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
+ *
+ *  Keyboard driver definitions for the Integrator architecture
+ */
+#include <asm/irq.h>
+
+/* Scancode mapping is as follows:
+ *
+ *      Scancode = keycode if key down event
+ *      Scancode = keycode|KBUP if key up event
+ *
+ *      Valid keycodes are 1..0x7F and are defined by the table
+ *      in keymap_dave.map.  Keycode 0 is reserved to mean invalid.
+ *
+ *      Keycodes are computed from scanned key matrix as follows:
+ */
+
+#define	KEYCODE( row, col)	( ((row)<<4) + (col) + 1)
+#define KBUP	0x80
+#define NR_SCANCODES 128	/*TBD used? */
+
+#ifdef CONFIG_EP93XX_KBD_SCANNED
+void __init ep93xx_scan_kbd_hw_init(void);
+#define kbd_init_hw()			ep93xx_scan_kbd_hw_init()
+#elif defined CONFIG_EP93XX_KBD_SPI
+void __init EP93XXSpiKbdInit(void);
+#define kbd_init_hw()			EP93XXSpiKbdInit()
+#elif defined CONFIG_EP93XX_KBD_USB
+void __init EP93XXUSBKbdInit(void);
+#define kbd_init_hw()			EP93XXUSBKbdInit()
+#endif
+
+#ifdef kbd_sysrq_xlate
+#undef kbd_sysrq_xlate
+#define kbd_sysrq_xlate			(1)
+#endif
+#define kbd_disable_irq()		disable_irq( IRQ_KEY)
+#define kbd_enable_irq()		enable_irq( IRQ_KEY)
diff --git a/include/asm-arm/arch-ep93xx/mach-edb9302.h b/include/asm-arm/arch-ep93xx/mach-edb9302.h
new file mode 100644
index 0000000..829883a
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/mach-edb9302.h
@@ -0,0 +1,20 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/mach-edb9302.h
+ *
+ *  Copyright 2004 Ray Lehtiniemi
+ *  Copyright 2004 Siconix, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __ASM_ARCH_MACHEDB9302_H
+#define __ASM_ARCH_MACHEDB9302_H
+
+#include <asm/arch/ssp2.h>
+
+extern struct ep93xx_ssp_slave ep93xx_ssp_flash;
+extern struct ep93xx_ssp_slave ep93xx_ssp_codec;
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/mach-ttml.h b/include/asm-arm/arch-ep93xx/mach-ttml.h
new file mode 100644
index 0000000..665873d
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/mach-ttml.h
@@ -0,0 +1,23 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/mach-ttml.h
+ *
+ *  Copyright 2004 Ray Lehtiniemi
+ *  Copyright 2004 Siconix, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __ASM_ARCH_MACHTTML_H
+#define __ASM_ARCH_MACHTTML_H
+
+#include <asm/arch/ssp2.h>
+
+extern struct ep93xx_ssp_slave ep93xx_ssp_micro;
+extern struct ep93xx_ssp_slave ep93xx_ssp_expansion;
+
+extern int ssp_do_ttml(struct ep93xx_ssp_slave *s, void *tx, int tlen, void *rx,
+		       int rlen);
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/memory.h b/include/asm-arm/arch-ep93xx/memory.h
new file mode 100644
index 0000000..57e266e
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/memory.h
@@ -0,0 +1,256 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/memory.h
+ *
+ *  ******************************************************
+ *	*    CONFUSED?  Read Documentation/IO-mapping.txt	 *
+ *  ******************************************************
+ *
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2002-2003 Cirrus Logic Corp.
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+/*
+ * For EP93xx, SDRAM can be discontiguous, in a set number of blocks
+ * of equal size and (usually) equal spacing.  The 9301 spacing isn't equal.
+ *
+ * SDRAM_START is the physical address of the start of SDRAM.
+ * SDRAM_NUMBER_OF_BLOCKS = # of blocks of SDRAM.
+ * Each block is of size SDRAM_BLOCK_SIZE and starts at a boundary
+ * of SDRAM_BLOCK_START_BOUNDARY.
+ *
+ * So memory blocks are at:
+ *  SDRAM_START
+ *  SDRAM_START + SDRAM_BLOCK_START_BOUNDARY
+ *  SDRAM_START + (SDRAM_BLOCK_START_BOUNDARY * 2)
+ *  SDRAM_START + (SDRAM_BLOCK_START_BOUNDARY * 3)
+ *  so on
+ */
+
+#ifndef CONFIG_DISCONTIGMEM
+
+/*
+ * Single 32Meg block of physical memory physically located at 0 .
+ */
+#define SDRAM_START                         0x00000000
+#define SDRAM_NUMBER_OF_BLOCKS              1
+#define SDRAM_BLOCK_SIZE                    0x02000000
+#define SDRAM_BLOCK_START_BOUNDARY          0x00000000
+
+#else				/* CONFIG_DISCONTIGMEM */
+
+#if defined(CONFIG_MACH_EDB9301)
+/*
+ * 4 8Meg blocks at 0x0n000000, n={0145}
+ */
+#define SDRAM_START                         0x00000000
+#define SDRAM_NUMBER_OF_BLOCKS              4
+#define SDRAM_BLOCK_SIZE                    0x00800000
+#define SDRAM_BLOCK_START_BOUNDARY          0x01000000
+#endif
+
+#if defined(CONFIG_MACH_TTML)
+#define SDRAM_START                         0x00000000
+#define SDRAM_NUMBER_OF_BLOCKS              1
+#define SDRAM_BLOCK_SIZE                    0x02000000
+#define SDRAM_BLOCK_START_BOUNDARY          0x02000000
+#endif
+
+#if defined(CONFIG_MACH_EDB9302)
+/*
+ * 4 8Meg blocks at 0x0n000000, n={0145}
+ */
+#define SDRAM_START                         0x00000000
+#define SDRAM_NUMBER_OF_BLOCKS              4
+#define SDRAM_BLOCK_SIZE                    0x00800000
+#define SDRAM_BLOCK_START_BOUNDARY          0x01000000
+#endif
+
+#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_ADSSPHERE)
+/*
+ * 2 32Meg blocks that are located physically at 0 and 64Meg.
+ */
+#define SDRAM_START                         0x00000000
+#define SDRAM_NUMBER_OF_BLOCKS              2
+#define SDRAM_BLOCK_SIZE                    0x02000000
+#define SDRAM_BLOCK_START_BOUNDARY          0x04000000
+#endif
+
+#if defined(CONFIG_MACH_DMA03)
+/*
+ * 2 32Meg blocks that are located physically at 0 and 64Meg.
+ */
+#define SDRAM_START                         0x00000000
+#define SDRAM_NUMBER_OF_BLOCKS              2
+#define SDRAM_BLOCK_SIZE                    0x02000000
+#define SDRAM_BLOCK_START_BOUNDARY          0x04000000
+#endif
+
+#if defined(CONFIG_MACH_ACC)
+/*
+ * 8 8Meg blocks that are located physically at 0xC0000000
+ * total 64Meg.
+ */
+#define SDRAM_START                         0xC0000000
+#define SDRAM_NUMBER_OF_BLOCKS              8
+#define SDRAM_BLOCK_SIZE                    0x00800000
+#define SDRAM_BLOCK_START_BOUNDARY          0x01000000
+#endif
+
+#if defined(CONFIG_MACH_ZEFEERDZB)
+/*
+ * 2 8Meg blocks
+ */
+#define SDRAM_START                         0xD0000000
+#define SDRAM_NUMBER_OF_BLOCKS              2
+#define SDRAM_BLOCK_SIZE                    0x00800000
+#define SDRAM_BLOCK_START_BOUNDARY          0x01000000
+#endif
+
+#if defined(CONFIG_MACH_ZEFEERDZQ)
+/*
+ * 2 32Meg blocks
+ */
+#define SDRAM_START                         0xD0000000
+#define SDRAM_NUMBER_OF_BLOCKS              2
+#define SDRAM_BLOCK_SIZE                    0x02000000
+#define SDRAM_BLOCK_START_BOUNDARY          0x04000000
+#endif
+
+/*
+ * Here we are assuming EP93xx is configured to have two 32MB SDRAM
+ * areas with 32MB of empty space between them.  So use 24 for the node
+ * max shift to get 64MB node sizes.
+ */
+#define NODE_MAX_MEM_SHIFT	26
+#define NODE_MAX_MEM_SIZE	(1<<NODE_MAX_MEM_SHIFT)
+
+#endif				/* CONFIG_DISCONTIGMEM */
+
+/*
+ * MEM_SIZE and PHYS_OFFSET are used to set size of SDRAM for
+ * initial page table in arch/arm/kernel/setup.c
+ * For ep93xx, PHYS_OFFSET is set to be SDRAM_START.
+ */
+#define MEM_SIZE                            (SDRAM_BLOCK_SIZE)
+
+/*
+ * If memory is not discontiguous, this is #defined	in
+ * arch/arm/mm/init.c to be 1.
+ */
+#ifdef CONFIG_DISCONTIGMEM
+#define NR_NODES 							(SDRAM_NUMBER_OF_BLOCKS)
+#endif
+
+/*
+ * Where to load the ramdisk (virtual address, not physical) and how
+ * big to make it. (used in arch/arm/kernel/setup.c
+ * In both cases, when redboot loads the ramdisk image to 0x01000000,
+ * the processor will find it because the linux map is funny.
+ */
+#ifdef CONFIG_ARCH_EP9301
+#define RAMDISK_START_VIRT      (0xC4000000)
+#else
+#define RAMDISK_START_VIRT      (0xC1000000)
+#endif
+
+/*
+ * The ramdisk size comes from a make menuconfig option.
+ */
+#define RAMDISK_SIZE            ((CONFIG_BLK_DEV_RAM_SIZE)<<10)
+
+/*
+ * Task size: 2GB (from 0 to base of IO in virtual space)
+ */
+#define TASK_SIZE		UL(0x7f000000)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (0x40000000)
+
+/*
+ * Page offset: 3GB (start of kernel memory in virtual space)
+ * Phys offset: 0   (start of kernel memory in physical space)
+ */
+#define PAGE_OFFSET		UL(0xC0000000)
+#define PHYS_OFFSET		(SDRAM_START)
+
+/*
+ * We take advantage of the fact that physical and virtual address can be the
+ * same.  The NUMA code is handling the large holes that might exist between
+ * all memory banks.
+ */
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
+
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_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 __virt_to_bus(x)	 __virt_to_phys(x)
+
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x)	 __phys_to_virt(x)
+
+/*
+ * Note that this file is included by include/asm-arm/memory.h so
+ * the macros in this file have to play nice with those.
+ */
+#ifdef CONFIG_DISCONTIGMEM
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) \
+		(((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
+
+/*
+ * Given a page frame number, convert it to a node id.
+ */
+#define PFN_TO_NID(pfn) \
+	(((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - 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((unsigned long)(kaddr)))
+
+#define PFN_TO_MAPBASE(pfn)	NODE_MEM_MAP(PFN_TO_NID(pfn))
+
+/*
+ * Given a kaddr, LOCAL_MAR_NR 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(kaddr) \
+	(((unsigned long)(kaddr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
+
+#endif				/* CONFIG_DISCONTIGMEM */
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/param.h b/include/asm-arm/arch-ep93xx/param.h
new file mode 100644
index 0000000..525face
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/param.h
@@ -0,0 +1,21 @@
+/*
+ *  linux/include/asm-arm/arch-integrator/param.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+
+/* #define HZ 100 */
diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h
new file mode 100644
index 0000000..d92833d
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/platform.h
@@ -0,0 +1,43 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/platform.h
+ *
+ *  Copyright (C) 2002-2003 Cirrus Logic, Inc.
+ *
+ * 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
+ */
+#ifndef ASM_ARCH_PLATFORM_H
+#define ASM_ARCH_PLATFORM_H
+
+/*
+ *  Timer definitions
+ *
+ *  Use timers 1, 2, and 3.  Do not use timer 4.
+ *  Timers run at 508 kHz.
+ */
+
+/*
+ *  These are useconds NOT ticks.
+ */
+#define mSEC_1                          1000
+#define mSEC_5                          (mSEC_1 * 5)
+#define mSEC_10                         (mSEC_1 * 10)
+#define mSEC_25                         (mSEC_1 * 25)
+#define SEC_1                           (mSEC_1 * 1000)
+
+#ifndef __ASSEMBLY__
+extern struct sys_timer ep93xx_timer;
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/regmap.h b/include/asm-arm/arch-ep93xx/regmap.h
new file mode 100644
index 0000000..7b3eeac
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regmap.h
@@ -0,0 +1,1125 @@
+/*
+ *  File:   linux/include/asm-arm/arch-ep93xx/regmap.h
+ *
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *  Copyright (C) 2003 Cirrus Logic, Inc
+ *  Copyright (C) 1999 ARM Limited.
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_REGMAP_H
+#define __ASM_ARCH_REGMAP_H
+
+/*
+ * Here's the rules:
+ * - EP93xx register addresses in regmap.h are physical addresses.
+ *
+ * - io_p2v translates a physical address to a virtual one for the
+ *   EP93xx's register space only.  Don't use it for actual memory.
+ *
+ */
+
+#define IO_BASE_VIRT        0xE0000000	/* Virtual address of IO */
+#define IO_BASE_PHYS        0x80000000	/* Physical address of IO */
+
+/*
+ * The HW_REG macro assumes that the param is a virtual address
+ */
+#define HW_REG(reg) ((unsigned int volatile *)reg)
+
+/*
+ * Macro to get at IO space when running virtually.
+ * (Translates a physical address to a virtual address)
+ * First cast the pa to an unsigned int in case we are using this
+ * on a macro that is already cast as a pointer.
+ */
+
+#define io_p2v(x) ((x) - (IO_BASE_PHYS - IO_BASE_VIRT))
+#define io_v2p(x) ((x) - (IO_BASE_VIRT - IO_BASE_PHYS))
+
+/******************************************************************/
+/*         EP93xx Memory Map and Register list                    */
+/******************************************************************/
+/*                                                                */
+/* 0000_0000 - 0000_ffff: Internal ROM/nSDCE3/nCS0                */
+/* 0001_0000 - 0fff_ffff: nSDCE3/nCS0                             */
+/* 1000_0000 - 1fff_ffff: nCS1                                    */
+/* 2000_0000 - 2fff_ffff: nCS2                                    */
+/* 3000_0000 - 3fff_ffff: nCS3                                    */
+/* 4000_0000 - 4fff_ffff: Reserved                                */
+/* 5000_0000 - 5fff_ffff: Reserved                                */
+/* 6000_0000 - 6fff_ffff: nCS6                                    */
+/* 7000_0000 - 7fff_ffff: nCS7                                    */
+/* 8000_0000 - 800f_ffff: AHB Registers                           */
+/* 8010_0000 - 807f_ffff: Reserved                                */
+/* 8080_0000 - 8fff_ffff: APB Registers                           */
+/* 9000_0000 - bfff_ffff: Not Used                                */
+/* c000_0000 - cfff_ffff: nSDCE0                                  */
+/* d000_0000 - dfff_ffff: nSDCE1                                  */
+/* e000_0000 - efff_ffff: nSDCE2                                  */
+/* f000_0000 - ffff_ffff: nCS0/nSDCE3                             */
+/*                                                                */
+/******************************************************************/
+
+/******************************************************************/
+/*         EP93xx AHB Blocks                                      */
+/******************************************************************/
+/*                                                                */
+/* Start     End         Usage                                    */
+/* 8000_0000 8000_FFFF:  DMA                                      */
+/* 8001_0000 8001_FFFF:  Ethernet MAC                             */
+/* 8002_0000 8002_FFFF:  USB Host                                 */
+/* 8003_0000 8003_FFFF:  Raster                                   */
+/* 8004_0000 8004_FFFF:  Reserved                                 */
+/* 8005_0000 8005_FFFF:  Reserved                                 */
+/* 8006_0000 8006_FFFF:  SDRAM                                    */
+/* 8007_0000 8007_FFFF:  Reserved                                 */
+/* 8008_0000 8008_FFFF:  SMC                                      */
+/* 8009_0000 8009_FFFF:  Boot ROM physical address                */
+/* 800A_0000 800A_FFFF:  IDE                                      */
+/* 800B_0000 800B_FFFF:  VIC1                                     */
+/* 800C_0000 800C_FFFF:  VIC2                                     */
+/* 800D_0000 800F_FFFF:  Reserved                                 */
+/*                                                                */
+/******************************************************************/
+
+#define EP93XX_AHB_BASE (IO_BASE_VIRT)
+
+/* 8000_0000 - 8000_ffff: DMA  */
+#define DMA_OFFSET              0x000000
+#define DMA_BASE                (EP93XX_AHB_BASE|DMA_OFFSET)
+#define DMAMP_TX_0_CONTROL      (DMA_BASE+0x0000)
+#define DMAMP_TX_0_INTERRUPT    (DMA_BASE+0x0004)
+#define DMAMP_TX_0_PPALLOC      (DMA_BASE+0x0008)
+#define DMAMP_TX_0_STATUS       (DMA_BASE+0x000C)
+#define DMAMP_TX_0_REMAIN       (DMA_BASE+0x0014)
+#define DMAMP_TX_0_MAXCNT0      (DMA_BASE+0x0020)
+#define DMAMP_TX_0_BASE0        (DMA_BASE+0x0024)
+#define DMAMP_TX_0_CURRENT0     (DMA_BASE+0x0028)
+#define DMAMP_TX_0_MAXCNT1      (DMA_BASE+0x0030)
+#define DMAMP_TX_0_BASE1        (DMA_BASE+0x0034)
+#define DMAMP_TX_0_CURRENT1     (DMA_BASE+0x0038)
+
+#define DMAMP_RX_1_CONTROL      (DMA_BASE+0x0040)
+#define DMAMP_RX_1_INTERRUPT    (DMA_BASE+0x0044)
+#define DMAMP_RX_1_PPALLOC      (DMA_BASE+0x0048)
+#define DMAMP_RX_1_STATUS       (DMA_BASE+0x004C)
+#define DMAMP_RX_1_REMAIN       (DMA_BASE+0x0054)
+#define DMAMP_RX_1_MAXCNT0      (DMA_BASE+0x0060)
+#define DMAMP_RX_1_BASE0        (DMA_BASE+0x0064)
+#define DMAMP_RX_1_CURRENT0     (DMA_BASE+0x0068)
+#define DMAMP_RX_1_MAXCNT1      (DMA_BASE+0x0070)
+#define DMAMP_RX_1_BASE1        (DMA_BASE+0x0074)
+#define DMAMP_RX_1_CURRENT1     (DMA_BASE+0x0078)
+
+#define DMAMP_TX_2_CONTROL      (DMA_BASE+0x0080)
+#define DMAMP_TX_2_INTERRUPT    (DMA_BASE+0x0084)
+#define DMAMP_TX_2_PPALLOC      (DMA_BASE+0x0088)
+#define DMAMP_TX_2_STATUS       (DMA_BASE+0x008C)
+#define DMAMP_TX_2_REMAIN       (DMA_BASE+0x0094)
+#define DMAMP_TX_2_MAXCNT0      (DMA_BASE+0x00A0)
+#define DMAMP_TX_2_BASE0        (DMA_BASE+0x00A4)
+#define DMAMP_TX_2_CURRENT0     (DMA_BASE+0x00A8)
+#define DMAMP_TX_2_MAXCNT1      (DMA_BASE+0x00B0)
+#define DMAMP_TX_2_BASE1        (DMA_BASE+0x00B4)
+#define DMAMP_TX_2_CURRENT1     (DMA_BASE+0x00B8)
+
+#define DMAMP_RX_3_CONTROL      (DMA_BASE+0x00C0)
+#define DMAMP_RX_3_INTERRUPT    (DMA_BASE+0x00C4)
+#define DMAMP_RX_3_PPALLOC      (DMA_BASE+0x00C8)
+#define DMAMP_RX_3_STATUS       (DMA_BASE+0x00CC)
+#define DMAMP_RX_3_REMAIN       (DMA_BASE+0x00D4)
+#define DMAMP_RX_3_MAXCNT0      (DMA_BASE+0x00E0)
+#define DMAMP_RX_3_BASE0        (DMA_BASE+0x00E4)
+#define DMAMP_RX_3_CURRENT0     (DMA_BASE+0x00E8)
+#define DMAMP_RX_3_MAXCNT1      (DMA_BASE+0x00F0)
+#define DMAMP_RX_3_BASE1        (DMA_BASE+0x00F4)
+#define DMAMP_RX_3_CURRENT1     (DMA_BASE+0x00F8)
+
+#define DMAMM_0_CONTROL         (DMA_BASE+0x0100)
+#define DMAMM_0_INTERRUPT       (DMA_BASE+0x0104)
+#define DMAMM_0_STATUS          (DMA_BASE+0x010C)
+#define DMAMM_0_BCR0            (DMA_BASE+0x0110)
+#define DMAMM_0_BCR1            (DMA_BASE+0x0114)
+#define DMAMM_0_SAR_BASE0       (DMA_BASE+0x0118)
+#define DMAMM_0_SAR_BASE1       (DMA_BASE+0x011C)
+#define DMAMM_0_SAR_CURRENT0    (DMA_BASE+0x0124)
+#define DMAMM_0_SAR_CURRENT1    (DMA_BASE+0x0128)
+#define DMAMM_0_DAR_BASE0       (DMA_BASE+0x012C)
+#define DMAMM_0_DAR_BASE1       (DMA_BASE+0x0130)
+#define DMAMM_0_DAR_CURRENT0    (DMA_BASE+0x0134)
+#define DMAMM_0_DAR_CURRENT1    (DMA_BASE+0x013C)
+
+#define DMAMM_1_CONTROL         (DMA_BASE+0x0140)
+#define DMAMM_1_INTERRUPT       (DMA_BASE+0x0144)
+#define DMAMM_1_STATUS          (DMA_BASE+0x014C)
+#define DMAMM_1_BCR0            (DMA_BASE+0x0150)
+#define DMAMM_1_BCR1            (DMA_BASE+0x0154)
+#define DMAMM_1_SAR_BASE0       (DMA_BASE+0x0158)
+#define DMAMM_1_SAR_BASE1       (DMA_BASE+0x015C)
+#define DMAMM_1_SAR_CURRENT0    (DMA_BASE+0x0164)
+#define DMAMM_1_SAR_CURRENT1    (DMA_BASE+0x0168)
+#define DMAMM_1_DAR_BASE0       (DMA_BASE+0x016C)
+#define DMAMM_1_DAR_BASE1       (DMA_BASE+0x0170)
+#define DMAMM_1_DAR_CURRENT0    (DMA_BASE+0x0174)
+#define DMAMM_1_DAR_CURRENT1    (DMA_BASE+0x017C)
+
+#define DMAMP_RX_5_CONTROL      (DMA_BASE+0x0200)
+#define DMAMP_RX_5_INTERRUPT    (DMA_BASE+0x0204)
+#define DMAMP_RX_5_PPALLOC      (DMA_BASE+0x0208)
+#define DMAMP_RX_5_STATUS       (DMA_BASE+0x020C)
+#define DMAMP_RX_5_REMAIN       (DMA_BASE+0x0214)
+#define DMAMP_RX_5_MAXCNT0      (DMA_BASE+0x0220)
+#define DMAMP_RX_5_BASE0        (DMA_BASE+0x0224)
+#define DMAMP_RX_5_CURRENT0     (DMA_BASE+0x0228)
+#define DMAMP_RX_5_MAXCNT1      (DMA_BASE+0x0230)
+#define DMAMP_RX_5_BASE1        (DMA_BASE+0x0234)
+#define DMAMP_RX_5_CURRENT1     (DMA_BASE+0x0238)
+
+#define DMAMP_TX_4_CONTROL      (DMA_BASE+0x0240)
+#define DMAMP_TX_4_INTERRUPT    (DMA_BASE+0x0244)
+#define DMAMP_TX_4_PPALLOC      (DMA_BASE+0x0248)
+#define DMAMP_TX_4_STATUS       (DMA_BASE+0x024C)
+#define DMAMP_TX_4_REMAIN       (DMA_BASE+0x0254)
+#define DMAMP_TX_4_MAXCNT0      (DMA_BASE+0x0260)
+#define DMAMP_TX_4_BASE0        (DMA_BASE+0x0264)
+#define DMAMP_TX_4_CURRENT0     (DMA_BASE+0x0268)
+#define DMAMP_TX_4_MAXCNT1      (DMA_BASE+0x0270)
+#define DMAMP_TX_4_BASE1        (DMA_BASE+0x0274)
+#define DMAMP_TX_4_CURRENT1     (DMA_BASE+0x0278)
+
+#define DMAMP_RX_7_CONTROL      (DMA_BASE+0x0280)
+#define DMAMP_RX_7_INTERRUPT    (DMA_BASE+0x0284)
+#define DMAMP_RX_7_PPALLOC      (DMA_BASE+0x0288)
+#define DMAMP_RX_7_STATUS       (DMA_BASE+0x028C)
+#define DMAMP_RX_7_REMAIN       (DMA_BASE+0x0294)
+#define DMAMP_RX_7_MAXCNT0      (DMA_BASE+0x02A0)
+#define DMAMP_RX_7_BASE0        (DMA_BASE+0x02A4)
+#define DMAMP_RX_7_CURRENT0     (DMA_BASE+0x02A8)
+#define DMAMP_RX_7_MAXCNT1      (DMA_BASE+0x02B0)
+#define DMAMP_RX_7_BASE1        (DMA_BASE+0x02B4)
+#define DMAMP_RX_7_CURRENT1     (DMA_BASE+0x02B8)
+
+#define DMAMP_TX_6_CONTROL      (DMA_BASE+0x02C0)
+#define DMAMP_TX_6_INTERRUPT    (DMA_BASE+0x02C4)
+#define DMAMP_TX_6_PPALLOC      (DMA_BASE+0x02C8)
+#define DMAMP_TX_6_STATUS       (DMA_BASE+0x02CC)
+#define DMAMP_TX_6_REMAIN       (DMA_BASE+0x02D4)
+#define DMAMP_TX_6_MAXCNT0      (DMA_BASE+0x02E0)
+#define DMAMP_TX_6_BASE0        (DMA_BASE+0x02E4)
+#define DMAMP_TX_6_CURRENT0     (DMA_BASE+0x02E8)
+#define DMAMP_TX_6_MAXCNT1      (DMA_BASE+0x02F0)
+#define DMAMP_TX_6_BASE1        (DMA_BASE+0x02F4)
+#define DMAMP_TX_6_CURRENT1     (DMA_BASE+0x02F8)
+
+#define DMAMP_RX_9_CONTROL      (DMA_BASE+0x0300)
+#define DMAMP_RX_9_INTERRUPT    (DMA_BASE+0x0304)
+#define DMAMP_RX_9_PPALLOC      (DMA_BASE+0x0308)
+#define DMAMP_RX_9_STATUS       (DMA_BASE+0x030C)
+#define DMAMP_RX_9_REMAIN       (DMA_BASE+0x0314)
+#define DMAMP_RX_9_MAXCNT0      (DMA_BASE+0x0320)
+#define DMAMP_RX_9_BASE0        (DMA_BASE+0x0324)
+#define DMAMP_RX_9_CURRENT0     (DMA_BASE+0x0328)
+#define DMAMP_RX_9_MAXCNT1      (DMA_BASE+0x0330)
+#define DMAMP_RX_9_BASE1        (DMA_BASE+0x0334)
+#define DMAMP_RX_9_CURRENT1     (DMA_BASE+0x0338)
+
+#define DMAMP_TX_8_CONTROL      (DMA_BASE+0x0340)
+#define DMAMP_TX_8_INTERRUPT    (DMA_BASE+0x0344)
+#define DMAMP_TX_8_PPALLOC      (DMA_BASE+0x0348)
+#define DMAMP_TX_8_STATUS       (DMA_BASE+0x034C)
+#define DMAMP_TX_8_REMAIN       (DMA_BASE+0x0354)
+#define DMAMP_TX_8_MAXCNT0      (DMA_BASE+0x0360)
+#define DMAMP_TX_8_BASE0        (DMA_BASE+0x0364)
+#define DMAMP_TX_8_CURRENT0     (DMA_BASE+0x0368)
+#define DMAMP_TX_8_MAXCNT1      (DMA_BASE+0x0370)
+#define DMAMP_TX_8_BASE1        (DMA_BASE+0x0374)
+#define DMAMP_TX_8_CURRENT1     (DMA_BASE+0x0378)
+
+#define DMA_ARBITRATION         (DMA_BASE+0x0380)
+#define DMA_INTERRUPT           (DMA_BASE+0x03C0)
+
+/*
+ * DMA Register Base addresses and Offsets
+ */
+#define DMA_M2P_TX_0_BASE       DMAMP_TX_0_CONTROL
+#define DMA_M2P_RX_1_BASE       DMAMP_RX_1_CONTROL
+#define DMA_M2P_TX_2_BASE       DMAMP_TX_2_CONTROL
+#define DMA_M2P_RX_3_BASE       DMAMP_RX_3_CONTROL
+#define DMA_M2M_0_BASE          DMAMM_0_CONTROL
+#define DMA_M2M_1_BASE          DMAMM_1_CONTROL
+#define DMA_M2P_RX_5_BASE       DMAMP_RX_5_CONTROL
+#define DMA_M2P_TX_4_BASE       DMAMP_TX_4_CONTROL
+#define DMA_M2P_RX_7_BASE       DMAMP_RX_7_CONTROL
+#define DMA_M2P_TX_6_BASE       DMAMP_TX_6_CONTROL
+#define DMA_M2P_RX_9_BASE       DMAMP_RX_9_CONTROL
+#define DMA_M2P_TX_8_BASE       DMAMP_TX_8_CONTROL
+
+#define M2P_OFFSET_CONTROL          0x0000
+#define M2P_OFFSET_INTERRUPT        0x0004
+#define M2P_OFFSET_PPALLOC          0x0008
+#define M2P_OFFSET_STATUS           0x000C
+#define M2P_OFFSET_REMAIN           0x0014
+#define M2P_OFFSET_MAXCNT0          0x0020
+#define M2P_OFFSET_BASE0            0x0024
+#define M2P_OFFSET_CURRENT0         0x0028
+#define M2P_OFFSET_MAXCNT1          0x0030
+#define M2P_OFFSET_BASE1            0x0034
+#define M2P_OFFSET_CURRENT1         0x0038
+
+#define M2M_OFFSET_CONTROL          0x0000
+#define M2M_OFFSET_INTERRUPT        0x0004
+#define M2M_OFFSET_STATUS           0x000C
+#define M2M_OFFSET_BCR0             0x0010
+#define M2M_OFFSET_BCR1             0x0014
+#define M2M_OFFSET_SAR_BASE0        0x0018
+#define M2M_OFFSET_SAR_BASE1        0x001C
+#define M2M_OFFSET_SAR_CURRENT0     0x0024
+#define M2M_OFFSET_SAR_CURRENT1     0x0028
+#define M2M_OFFSET_DAR_BASE0        0x002C
+#define M2M_OFFSET_DAR_BASE1        0x0030
+#define M2M_OFFSET_DAR_CURRENT0     0x0034
+#define M2M_OFFSET_DAR_CURRENT1     0x003C
+
+/*----------------------------------------------------------------*/
+/* 8001_0000 - 8001_ffff: Ether MAC                               */
+/*----------------------------------------------------------------*/
+#define MAC_OFFSET              0x010000
+#define MAC_BASE                (EP93XX_AHB_BASE|MAC_OFFSET)
+
+#define MAC_RXCTL               (MAC_BASE+0x00)
+#define MAC_TXCTL               (MAC_BASE+0x04)
+#define MAC_TESTCTL             (MAC_BASE+0x08)
+#define MAC_MIICMD              (MAC_BASE+0x10)
+#define MAC_MIIDATA             (MAC_BASE+0x14)
+#define MAC_MIISTS              (MAC_BASE+0x18)
+#define MAC_SELFCTL             (MAC_BASE+0x20)
+#define MAC_INTEN               (MAC_BASE+0x24)
+#define MAC_INTSTSP             (MAC_BASE+0x28)
+#define MAC_INTSTSC             (MAC_BASE+0x2C)
+#define MAC_DIAGAD              (MAC_BASE+0x38)
+#define MAC_DIAGDATA            (MAC_BASE+0x3C)
+#define MAC_GT                  (MAC_BASE+0x40)
+#define MAC_FCT                 (MAC_BASE+0x44)
+#define MAC_FCF                 (MAC_BASE+0x48)
+#define MAC_AFP                 (MAC_BASE+0x4C)
+#define MAC_HASHTBL             (MAC_BASE+0x50)
+#define MAC_INDAD               (MAC_BASE+0x50)
+#define MAC_INDAD_UPPER         (MAC_BASE+0x54)
+#define MAC_GIINTSTS            (MAC_BASE+0x60)
+#define MAC_GIINTMSK            (MAC_BASE+0x64)
+#define MAC_GIINTROSTS          (MAC_BASE+0x68)
+#define MAC_GIINTFRC            (MAC_BASE+0x6C)
+#define MAC_TXCOLLCNT           (MAC_BASE+0x70)
+#define MAC_RXMISSCNT           (MAC_BASE+0x74)
+#define MAC_RXRUNTCNT           (MAC_BASE+0x78)
+#define MAC_BMCTL               (MAC_BASE+0x80)
+#define MAC_BMSTS               (MAC_BASE+0x84)
+#define MAC_RXBCA               (MAC_BASE+0x88)
+#define MAC_RXDQBADD            (MAC_BASE+0x90)
+#define MAC_RXDQBLEN            (UINT16*)(MAC_BASE+0x94)
+#define MAC_RXDQCURLEN          (UINT16*)(MAC_BASE+0x96)
+#define MAC_RXDCURADD           (MAC_BASE+0x98)
+#define MAC_RXDENQ              (MAC_BASE+0x9C)
+#define MAC_RXSTSQBADD          (MAC_BASE+0xA0)
+#define MAC_RXSTSQBLEN          (UINT16*)(MAC_BASE+0xA4)
+#define MAC_RXSTSQCURLEN        (UINT16*)(MAC_BASE+0xA6)
+#define MAC_RXSTSQCURADD        (MAC_BASE+0xA8)
+#define MAC_RXSTSENQ            (MAC_BASE+0xAC)
+#define MAC_TXDQBADD            (MAC_BASE+0xB0)
+#define MAC_TXDQBLEN            (MAC_BASE+0xB4)
+#define MAC_TXDQCURLEN          (MAC_BASE+0xB6)
+#define MAC_TXDQCURADD          (MAC_BASE+0xB8)
+#define MAC_TXDENQ              (MAC_BASE+0xBC)
+#define MAC_TXSTSQBADD          (MAC_BASE+0xC0)
+#define MAC_TXSTSQBLEN          (MAC_BASE+0xC4)
+#define MAC_TXSTSQCURLEN        (MAC_BASE+0xC6)
+#define MAC_TXSTSQCURADD        (MAC_BASE+0xC8)
+#define MAC_RXBUFTHRSHLD        (MAC_BASE+0xD0)
+#define MAC_TXBUFTHRSHLD        (MAC_BASE+0xD4)
+#define MAC_RXSTSTHRSHLD        (MAC_BASE+0xD8)
+#define MAC_TXSTSTHRSHLD        (MAC_BASE+0xDC)
+#define MAC_RXDTHRSHLD          (MAC_BASE+0xE0)
+#define MAC_TXDTHRSHLD          (MAC_BASE+0xE4)
+#define MAC_MAXFRMLEN           (MAC_BASE+0xE8)
+#define MAC_RXHDRLEN            (MAC_BASE+0xEC)
+
+#define MAC_FIFO		(MAC_BASE+0x4000)
+#define MAC_FIFO_LEN		0xc000
+
+/*----------------------------------------------------------------*/
+/* 8002_0000 - 8002_ffff: USB                                     */
+/*----------------------------------------------------------------*/
+#define USB_OFFSET              0x020000
+#define USB_BASE                (EP93XX_AHB_BASE|USB_OFFSET)
+
+#define HCREVISION              (USB_BASE+0x00)
+#define HCCONTROL               (USB_BASE+0x04)
+#define HCCOMMANDSTATUS         (USB_BASE+0x08)
+#define HCINTERRUPTSTATUS       (USB_BASE+0x0C)
+#define HCINTERRUPTENABLE       (USB_BASE+0x10)
+#define HCINTERRUPTDISABLE      (USB_BASE+0x14)
+#define HCHCCA                  (USB_BASE+0x18)
+#define HCPERIODCURRENTED       (USB_BASE+0x1C)
+#define HCCONTROLHEADED         (USB_BASE+0x20)
+#define HCCONTROLCURRENTED      (USB_BASE+0x24)
+#define HCBULKHEADED            (USB_BASE+0x28)
+#define HCBULKCURRENTED         (USB_BASE+0x2C)
+#define HCDONEHEAD              (USB_BASE+0x30)
+#define HCFMINTERVAL            (USB_BASE+0x34)
+#define HCFMREMAINING           (USB_BASE+0x38)
+#define HCFMNUMBER              (USB_BASE+0x3C)
+#define HCPERIODICSTART         (USB_BASE+0x40)
+#define HCLSTHRESHOLD           (USB_BASE+0x44)
+#define HCRHDESCRIPTORA         (USB_BASE+0x48)
+#define HCRHDESCRIPTORB         (USB_BASE+0x4C)
+#define HCRHSTATUS              (USB_BASE+0x50)
+#define HCRHPORTSTATUS0         (USB_BASE+0x54)
+#define HCRHPORTSTATUS1         (USB_BASE+0x58)	/* not in 9301 */
+#define HCRHPORTSTATUS2         (USB_BASE+0x5C)
+
+/* additional non-OHCI registers for controlling the AHB-HCI interface */
+#define USBCTRL                 (USB_BASE+0x80)
+#define USBHCISTS               (USB_BASE+0x84)
+
+/* 8003_0000 - 8003_ffff: Raster */
+#define RASTER_OFFSET           0x030000
+#define RASTER_BASE             (EP93XX_AHB_BASE|RASTER_OFFSET)
+#define VLINESTOTAL             (RASTER_BASE+0x00)
+#define VSYNCSTRTSTOP           (RASTER_BASE+0x04)
+#define VACTIVESTRTSTOP         (RASTER_BASE+0x08)
+#define VCLKSTRTSTOP            (RASTER_BASE+0x0C)
+#define HCLKSTOTAL              (RASTER_BASE+0x10)
+#define HSYNCSTRTSTOP           (RASTER_BASE+0x14)
+#define HACTIVESTRTSTOP         (RASTER_BASE+0x18)
+#define HCLKSTRTSTOP            (RASTER_BASE+0x1C)
+#define BRIGHTNESS              (RASTER_BASE+0x20)
+#define VIDEOATTRIBS            (RASTER_BASE+0x24)
+#define VIDSCRNPAGE             (RASTER_BASE+0x28)
+#define VIDSCRNHPG              (RASTER_BASE+0x2C)
+#define SCRNLINES               (RASTER_BASE+0x30)
+#define LINELENGTH              (RASTER_BASE+0x34)
+#define VLINESTEP               (RASTER_BASE+0x38)
+#define LINECARRY               (RASTER_BASE+0x3C)
+#define BLINKRATE               (RASTER_BASE+0x40)
+#define BLINKMASK               (RASTER_BASE+0x44)
+#define BLINKPATTRN             (RASTER_BASE+0x48)
+#define PATTRNMASK              (RASTER_BASE+0x4C)
+#define BG_OFFSET               (RASTER_BASE+0x50)
+#define PIXELMODE               (RASTER_BASE+0x54)
+#define PARLLIFOUT              (RASTER_BASE+0x58)
+#define PARLLIFIN               (RASTER_BASE+0x5C)
+#define CURSOR_ADR_START        (RASTER_BASE+0x60)
+#define CURSOR_ADR_RESET        (RASTER_BASE+0x64)
+#define CURSORSIZE              (RASTER_BASE+0x68)
+#define CURSORCOLOR1            (RASTER_BASE+0x6C)
+#define CURSORCOLOR2            (RASTER_BASE+0x70)
+#define CURSORXYLOC             (RASTER_BASE+0x74)
+#define CURSOR_DHSCAN_LH_YLOC   (RASTER_BASE+0x78)
+#define REALITI_SWLOCK          (RASTER_BASE+0x7C)
+#define GS_LUT                  (RASTER_BASE+0x80)
+#define REALITI_TCR             (RASTER_BASE+0x100)
+#define REALITI_TISRA           (RASTER_BASE+0x104)
+#define REALITI_TISRB           (RASTER_BASE+0x108)
+#define CURSOR_TISR             (RASTER_BASE+0x10C)
+#define REALITI_TOCRA           (RASTER_BASE+0x110)
+#define REALITI_TOCRB           (RASTER_BASE+0x114)
+#define FIFO_TOCRA              (RASTER_BASE+0x118)
+#define FIFO_TOCRB              (RASTER_BASE+0x11C)
+#define BLINK_TISR              (RASTER_BASE+0x120)
+#define DAC_TISRA               (RASTER_BASE+0x124)
+#define DAC_TISRB               (RASTER_BASE+0x128)
+#define SHIFT_TISR              (RASTER_BASE+0x12C)
+#define DACMUX_TOCRA            (RASTER_BASE+0x130)
+#define DACMUX_TOCRB            (RASTER_BASE+0x134)
+#define PELMUX_TOCR             (RASTER_BASE+0x138)
+#define VIDEO_TOCRA             (RASTER_BASE+0x13C)
+#define VIDEO_TOCRB             (RASTER_BASE+0x140)
+#define YCRCB_TOCR              (RASTER_BASE+0x144)
+#define CURSOR_TOCR             (RASTER_BASE+0x148)
+#define VIDEO_TOCRC             (RASTER_BASE+0x14C)
+#define SHIFT_TOCR              (RASTER_BASE+0x150)
+#define BLINK_TOCR              (RASTER_BASE+0x154)
+#define REALITI_TCER            (RASTER_BASE+0x180)
+#define SIGVAL                  (RASTER_BASE+0x200)
+#define SIGCTL                  (RASTER_BASE+0x204)
+#define VSIGSTRTSTOP            (RASTER_BASE+0x208)
+#define HSIGSTRTSTOP            (RASTER_BASE+0x20C)
+#define SIGCLR                  (RASTER_BASE+0x210)
+#define ACRATE                  (RASTER_BASE+0x214)
+#define LUTCONT                 (RASTER_BASE+0x218)
+#define VBLANKSTRTSTOP          (RASTER_BASE+0x228)
+#define HBLANKSTRTSTOP          (RASTER_BASE+0x22C)
+#define LUT                     (RASTER_BASE+0x400)
+#define CURSORBLINK1            (RASTER_BASE+0x21C)
+#define CURSORBLINK2            (RASTER_BASE+0x220)
+#define CURSORBLINK             (RASTER_BASE+0x224)
+#define EOLOFFSET               (RASTER_BASE+0x230)
+#define FIFOLEVEL               (RASTER_BASE+0x234)
+#define GS_LUT2                 (RASTER_BASE+0x280)
+#define GS_LUT3                 (RASTER_BASE+0x300)
+#define COLOR_LUT               (RASTER_BASE+0x400)
+
+/* 8006_0000 - 8006_ffff: SDRAM  */
+#define SDRAM_OFFSET            0x060000
+#define SDRAM_BASE              (EP93XX_AHB_BASE|SDRAM_OFFSET)
+#define SDRAMGLOBALCFG          (SDRAM_BASE+0x04)
+#define SDRAMREFRESHTIME        (SDRAM_BASE+0x08)	/* Refresh Timer */
+#define SDRAMBOOTSTATUS         (SDRAM_BASE+0x0C)
+#define SDRAMCFG0               (SDRAM_BASE+0x10)	/* Configuration Register 0 (nSDCS0) */
+#define SDRAMCFG1               (SDRAM_BASE+0x14)	/* Configuration Register 1 (nSDCS1) */
+#define SDRAMCFG2               (SDRAM_BASE+0x18)	/* Configuration Register 2 (nSDCS2) */
+#define SDRAMCFG3               (SDRAM_BASE+0x1C)	/* Configuration Register 3 (nSDCS3) */
+
+/* 8008_0000 - 8008_ffff: SMC */
+#define SMC_OFFSET              0x080000
+#define SMC_BASE                (EP93XX_AHB_BASE|SMC_OFFSET)
+#define SMCBCR0                 (SMC_BASE+0x00)	/* 0x8008.0000  Bank config register 0 */
+#define SMCBCR1                 (SMC_BASE+0x04)	/* 0x8008.0004  Bank config register 1 */
+#define SMCBCR2                 (SMC_BASE+0x08)	/* 0x8008.0008  Bank config register 2 */
+#define SMCBCR3                 (SMC_BASE+0x0C)	/* 0x8008.000C  Bank config register 3 */
+#define SMCBCR6                 (SMC_BASE+0x18)	/* 0x8008.0018  Bank config register 6 */
+#define SMCBCR7                 (SMC_BASE+0x1C)	/* 0x8008.001C  Bank config register 7 */
+#define PC1ATTRIB               (SMC_BASE+0x20)	/* 0x8008.0020  PC1 Attribute Register */
+#define PC1COMMON               (SMC_BASE+0x24)	/* 0x8008.0024  PC1 Common Register    */
+#define PC1IO                   (SMC_BASE+0x28)	/* 0x8008.0028  PC1 IO Register        */
+#define PC2ATTRIB               (SMC_BASE+0x30)	/* 0x8008.0030 PC2 Attribute Register   */
+#define PC2COMMON               (SMC_BASE+0x34)	/* 0x8008.0034 PC2 Common Register     */
+#define PC2IO                   (SMC_BASE+0x38)	/* 0x8008.0038 PC2 IO Register         */
+#define PCMCIACNT               (SMC_BASE+0x40)	/* 0x8008.0040 PCMCIA control register */
+
+/* 8009_0000 - 8009_ffff: Boot ROM */
+#define BOOT_OFFSET             0x090000
+#define BOOT_BASE               (EP93XX_AHB_BASE|BOOT_OFFSET)
+
+/* 800A_0000 - 800A_ffff: IDE Interface  */
+#define IDE_OFFSET              0x0a0000
+#define IDE_BASE                (EP93XX_AHB_BASE|IDE_OFFSET)
+/*#define IDECR                   (IDE_BASE+0x00)
+ *#define IDECFG                  (IDE_BASE+0x04)
+ *#define IDEMDMAOP               (IDE_BASE+0x08)
+ *#define IDEUDMAOP               (IDE_BASE+0x0C)
+ *#define IDEDATAOUT              (IDE_BASE+0x10)
+ *#define IDEDATAIN               (IDE_BASE+0x14)
+ *#define IDEMDMADATAOUT          (IDE_BASE+0x18)
+ *#define IDEMDMADATAIN           (IDE_BASE+0x1C)
+ *#define IDEUDMADATAOUT          (IDE_BASE+0x20)
+ *#define IDEUDMADATAIN           (IDE_BASE+0x24)
+ *#define IDEUDMASTATUS           (IDE_BASE+0x28)
+ *#define IDEUDMADEBUG            (IDE_BASE+0x2C)
+ *#define IDEUDMAWFST             (IDE_BASE+0x30)
+ *#define IDEUDMARFST             (IDE_BASE+0x34)
+ */
+
+/* 800B_0000 - 800B_FFFF: VIC 0 */
+#define VIC0_OFFSET              0x0B0000
+#define VIC0_BASE                (EP93XX_AHB_BASE|VIC0_OFFSET)
+#define VIC0                     (VIC0_BASE+0x000)
+#define VIC0IRQSTATUS            (VIC0_BASE+0x000)	/* R   IRQ status register               */
+#define VIC0FIQSTATUS            (VIC0_BASE+0x004)	/* R   FIQ status register               */
+#define VIC0RAWINTR              (VIC0_BASE+0x008)	/* R   Raw interrupt status register     */
+#define VIC0INTSELECT            (VIC0_BASE+0x00C)	/* R/W Interrupt select register         */
+#define VIC0INTENABLE            (VIC0_BASE+0x010)	/* R/W Interrupt enable register         */
+#define VIC0INTENCLEAR           (VIC0_BASE+0x014)	/* W   Interrupt enable clear register   */
+#define VIC0SOFTINT              (VIC0_BASE+0x018)	/* R/W Software interrupt register       */
+#define VIC0SOFTINTCLEAR         (VIC0_BASE+0x01C)	/* R/W Software interrupt clear register */
+#define VIC0PROTECTION           (VIC0_BASE+0x020)	/* R/W Protection enable register        */
+#define VIC0VECTADDR             (VIC0_BASE+0x030)	/* R/W Vector address register           */
+#define VIC0DEFVECTADDR          (VIC0_BASE+0x034)	/* R/W Default vector address register   */
+#define VIC0VECTADDR00           (VIC0_BASE+0x100)	/* R/W Vector address 00 register        */
+#define VIC0VECTADDR01           (VIC0_BASE+0x104)	/* R/W Vector address 01 register        */
+#define VIC0VECTADDR02           (VIC0_BASE+0x108)	/* R/W Vector address 02 register        */
+#define VIC0VECTADDR03           (VIC0_BASE+0x10C)	/* R/W Vector address 03 register        */
+#define VIC0VECTADDR04           (VIC0_BASE+0x110)	/* R/W Vector address 04 register        */
+#define VIC0VECTADDR05           (VIC0_BASE+0x114)	/* R/W Vector address 05 register        */
+#define VIC0VECTADDR06           (VIC0_BASE+0x118)	/* R/W Vector address 06 register        */
+#define VIC0VECTADDR07           (VIC0_BASE+0x11C)	/* R/W Vector address 07 register        */
+#define VIC0VECTADDR08           (VIC0_BASE+0x120)	/* R/W Vector address 08 register        */
+#define VIC0VECTADDR09           (VIC0_BASE+0x124)	/* R/W Vector address 09 register        */
+#define VIC0VECTADDR10           (VIC0_BASE+0x128)	/* R/W Vector address 10 register        */
+#define VIC0VECTADDR11           (VIC0_BASE+0x12C)	/* R/W Vector address 11 register        */
+#define VIC0VECTADDR12           (VIC0_BASE+0x130)	/* R/W Vector address 12 register        */
+#define VIC0VECTADDR13           (VIC0_BASE+0x134)	/* R/W Vector address 13 register        */
+#define VIC0VECTADDR14           (VIC0_BASE+0x138)	/* R/W Vector address 14 register        */
+#define VIC0VECTADDR15           (VIC0_BASE+0x13C)	/* R/W Vector address 15 register        */
+#define VIC0VECTCNTL00           (VIC0_BASE+0x200)	/* R/W Vector control 00 register        */
+#define VIC0VECTCNTL01           (VIC0_BASE+0x204)	/* R/W Vector control 01 register        */
+#define VIC0VECTCNTL02           (VIC0_BASE+0x208)	/* R/W Vector control 02 register        */
+#define VIC0VECTCNTL03           (VIC0_BASE+0x20C)	/* R/W Vector control 03 register        */
+#define VIC0VECTCNTL04           (VIC0_BASE+0x210)	/* R/W Vector control 04 register        */
+#define VIC0VECTCNTL05           (VIC0_BASE+0x214)	/* R/W Vector control 05 register        */
+#define VIC0VECTCNTL06           (VIC0_BASE+0x218)	/* R/W Vector control 06 register        */
+#define VIC0VECTCNTL07           (VIC0_BASE+0x21C)	/* R/W Vector control 07 register        */
+#define VIC0VECTCNTL08           (VIC0_BASE+0x220)	/* R/W Vector control 08 register        */
+#define VIC0VECTCNTL09           (VIC0_BASE+0x224)	/* R/W Vector control 09 register        */
+#define VIC0VECTCNTL10           (VIC0_BASE+0x228)	/* R/W Vector control 10 register        */
+#define VIC0VECTCNTL11           (VIC0_BASE+0x22C)	/* R/W Vector control 11 register        */
+#define VIC0VECTCNTL12           (VIC0_BASE+0x230)	/* R/W Vector control 12 register        */
+#define VIC0VECTCNTL13           (VIC0_BASE+0x234)	/* R/W Vector control 13 register        */
+#define VIC0VECTCNTL14           (VIC0_BASE+0x238)	/* R/W Vector control 14 register        */
+#define VIC0VECTCNTL15           (VIC0_BASE+0x23C)	/* R/W Vector control 15 register        */
+#define VIC0ITCR                 (VIC0_BASE+0x300)	/* R/W Test control register             */
+#define VIC0ITIP1                (VIC0_BASE+0x304)	/* R   Test input register (nVICIRQIN/nVICFIQIN) */
+#define VIC0ITIP2                (VIC0_BASE+0x308)	/* R   Test input register (VICVECTADDRIN)      */
+#define VIC0ITOP1                (VIC0_BASE+0x30C)	/* R   Test output register (nVICIRQ/nVICFIQ)   */
+#define VIC0ITOP2                (VIC0_BASE+0x310)	/* R   Test output register (VICVECTADDROUT)    */
+#define VIC0PERIPHID0            (VIC0_BASE+0xFE0)	/* R   Peripheral ID register bits 7:0   */
+#define VIC0PERIPHID1            (VIC0_BASE+0xFE4)	/* R   Peripheral ID register bits 15:8  */
+#define VIC0PERIPHID2            (VIC0_BASE+0xFE8)	/* R   Peripheral ID register bits 23:16 */
+#define VIC0PERIPHID3            (VIC0_BASE+0xFEC)	/* R   Peripheral ID register bits 31:24 */
+
+/* 800C_0000 - 800C_FFFF: VIC 1 */
+#define VIC1_OFFSET              0x0C0000
+#define VIC1_BASE                (EP93XX_AHB_BASE|VIC1_OFFSET)
+#define VIC1                     (VIC1_BASE+0x000)
+#define VIC1IRQSTATUS            (VIC1_BASE+0x000)	/* R   IRQ status register               */
+#define VIC1FIQSTATUS            (VIC1_BASE+0x004)	/* R   FIQ status register               */
+#define VIC1RAWINTR              (VIC1_BASE+0x008)	/* R   Raw interrupt status register     */
+#define VIC1INTSELECT            (VIC1_BASE+0x00C)	/* R/W Interrupt select register         */
+#define VIC1INTENABLE            (VIC1_BASE+0x010)	/* R/W Interrupt enable register         */
+#define VIC1INTENCLEAR           (VIC1_BASE+0x014)	/* W   Interrupt enable clear register   */
+#define VIC1SOFTINT              (VIC1_BASE+0x018)	/* R/W Software interrupt register       */
+#define VIC1SOFTINTCLEAR         (VIC1_BASE+0x01C)	/* R/W Software interrupt clear register */
+#define VIC1PROTECTION           (VIC1_BASE+0x020)	/* R/W Protection enable register        */
+#define VIC1VECTADDR             (VIC1_BASE+0x030)	/* R/W Vector address register           */
+#define VIC1DEFVECTADDR          (VIC1_BASE+0x034)	/* R/W Default vector address register   */
+#define VIC1VECTADDR00           (VIC1_BASE+0x100)	/* R/W Vector address 00 register        */
+#define VIC1VECTADDR01           (VIC1_BASE+0x104)	/* R/W Vector address 01 register        */
+#define VIC1VECTADDR02           (VIC1_BASE+0x108)	/* R/W Vector address 02 register        */
+#define VIC1VECTADDR03           (VIC1_BASE+0x10C)	/* R/W Vector address 03 register        */
+#define VIC1VECTADDR04           (VIC1_BASE+0x110)	/* R/W Vector address 04 register        */
+#define VIC1VECTADDR05           (VIC1_BASE+0x114)	/* R/W Vector address 05 register        */
+#define VIC1VECTADDR06           (VIC1_BASE+0x118)	/* R/W Vector address 06 register        */
+#define VIC1VECTADDR07           (VIC1_BASE+0x11C)	/* R/W Vector address 07 register        */
+#define VIC1VECTADDR08           (VIC1_BASE+0x120)	/* R/W Vector address 08 register        */
+#define VIC1VECTADDR09           (VIC1_BASE+0x124)	/* R/W Vector address 09 register        */
+#define VIC1VECTADDR10           (VIC1_BASE+0x128)	/* R/W Vector address 10 register        */
+#define VIC1VECTADDR11           (VIC1_BASE+0x12C)	/* R/W Vector address 11 register        */
+#define VIC1VECTADDR12           (VIC1_BASE+0x130)	/* R/W Vector address 12 register        */
+#define VIC1VECTADDR13           (VIC1_BASE+0x134)	/* R/W Vector address 13 register        */
+#define VIC1VECTADDR14           (VIC1_BASE+0x138)	/* R/W Vector address 14 register        */
+#define VIC1VECTADDR15           (VIC1_BASE+0x13C)	/* R/W Vector address 15 register        */
+#define VIC1VECTCNTL00           (VIC1_BASE+0x200)	/* R/W Vector control 00 register        */
+#define VIC1VECTCNTL01           (VIC1_BASE+0x204)	/* R/W Vector control 01 register        */
+#define VIC1VECTCNTL02           (VIC1_BASE+0x208)	/* R/W Vector control 02 register        */
+#define VIC1VECTCNTL03           (VIC1_BASE+0x20C)	/* R/W Vector control 03 register        */
+#define VIC1VECTCNTL04           (VIC1_BASE+0x210)	/* R/W Vector control 04 register        */
+#define VIC1VECTCNTL05           (VIC1_BASE+0x214)	/* R/W Vector control 05 register        */
+#define VIC1VECTCNTL06           (VIC1_BASE+0x218)	/* R/W Vector control 06 register        */
+#define VIC1VECTCNTL07           (VIC1_BASE+0x21C)	/* R/W Vector control 07 register        */
+#define VIC1VECTCNTL08           (VIC1_BASE+0x220)	/* R/W Vector control 08 register        */
+#define VIC1VECTCNTL09           (VIC1_BASE+0x224)	/* R/W Vector control 09 register        */
+#define VIC1VECTCNTL10           (VIC1_BASE+0x228)	/* R/W Vector control 10 register        */
+#define VIC1VECTCNTL11           (VIC1_BASE+0x22C)	/* R/W Vector control 11 register        */
+#define VIC1VECTCNTL12           (VIC1_BASE+0x230)	/* R/W Vector control 12 register        */
+#define VIC1VECTCNTL13           (VIC1_BASE+0x234)	/* R/W Vector control 13 register        */
+#define VIC1VECTCNTL14           (VIC1_BASE+0x238)	/* R/W Vector control 14 register        */
+#define VIC1VECTCNTL15           (VIC1_BASE+0x23C)	/* R/W Vector control 15 register        */
+#define VIC1ITCR                 (VIC1_BASE+0x300)	/* R/W Test control register             */
+#define VIC1ITIP1                (VIC1_BASE+0x304)	/* R   Test input register (nVICIRQIN/nVICFIQIN) */
+#define VIC1ITIP2                (VIC1_BASE+0x308)	/* R   Test input register (VICVECTADDRIN)      */
+#define VIC1ITOP1                (VIC1_BASE+0x30C)	/* R   Test output register (nVICIRQ/nVICFIQ)   */
+#define VIC1ITOP2                (VIC1_BASE+0x310)	/* R   Test output register (VICVECTADDROUT)    */
+#define VIC1PERIPHID0            (VIC1_BASE+0xFE0)	/* R   Peripheral ID register bits 7:0   */
+#define VIC1PERIPHID1            (VIC1_BASE+0xFE4)	/* R   Peripheral ID register bits 15:8  */
+#define VIC1PERIPHID2            (VIC1_BASE+0xFE8)	/* R   Peripheral ID register bits 23:16 */
+#define VIC1PERIPHID3            (VIC1_BASE+0xFEC)	/* R   Peripheral ID register bits 31:24 */
+
+/******************************************************************/
+/*         EP93xx APB Blocks                                      */
+/******************************************************************/
+/*                                                                */
+/* Start     End         Usage                                    */
+/* 8080_0000 8080_FFFF:  Reserved                                 */
+/* 8081_0000 8081_FFFF:  Timer                                    */
+/* 8082_0000 8082_FFFF:  I2S                                      */
+/* 8083_0000 8083_FFFF:  Security                                 */
+/* 8084_0000 8084_FFFF:  GPIO                                     */
+/* 8085_0000 8085_FFFF:  Reserved                                 */
+/* 8086_0000 8086_FFFF:  Reserved                                 */
+/* 8087_0000 8087_FFFF:  Reserved                                 */
+/* 8088_0000 8088_FFFF:  AC97                                     */
+/* 8089_0000 8089_FFFF:  Reserved                                 */
+/* 808A_0000 808A_FFFF:  SPI                                      */
+/* 808B_0000 808B_FFFF:  IrDA                                     */
+/* 808C_0000 808C_FFFF:  UART1                                    */
+/* 808D_0000 808D_FFFF:  UART2                                    */
+/* 808E_0000 808E_FFFF:  UART3                                    */
+/* 808F_0000 808F_FFFF:  Key Matrix                               */
+/* 8090_0000 8090_FFFF:  Touch Screen                             */
+/* 8091_0000 8091_FFFF:  PWM                                      */
+/* 8092_0000 8092_FFFF:  Real Time Clock                          */
+/* 8093_0000 8093_FFFF:  Syscon                                   */
+/* 8094_0000 8094_FFFF:  Watchdog                                 */
+/* 8095_0000 8FFF_FFFF:  Reserved                                 */
+/*                                                                */
+/******************************************************************/
+
+#define EP93XX_APB_BASE (IO_BASE_VIRT | 0x00800000)
+
+/*----------------------------------------------------------------*/
+/* 8081_0000 - 8081_ffff: Timers                                  */
+/*----------------------------------------------------------------*/
+
+#define TIMERS_OFFSET           0x010000
+#define TIMERS_BASE             (EP93XX_APB_BASE|TIMERS_OFFSET)
+
+#define TIMER1LOAD              (TIMERS_BASE+0x00)
+#define TIMER1VALUE             (TIMERS_BASE+0x04)	/* RO */
+#define TIMER1CONTROL           (TIMERS_BASE+0x08)
+#define TIMER1CLEAR             (TIMERS_BASE+0x0C)	/* WO */
+
+#define TIMER2LOAD              (TIMERS_BASE+0x20)
+#define TIMER2VALUE             (TIMERS_BASE+0x24)	/* RO */
+#define TIMER2CONTROL           (TIMERS_BASE+0x28)
+#define TIMER2CLEAR             (TIMERS_BASE+0x2C)	/* WO */
+
+#define TIMER3LOAD              (TIMERS_BASE+0x80)
+#define TIMER3VALUE             (TIMERS_BASE+0x84)	/* RO */
+#define TIMER3CONTROL           (TIMERS_BASE+0x88)
+#define TIMER3CLEAR             (TIMERS_BASE+0x8C)	/* WO */
+
+#define TIMER4VALUELOW          (TIMERS_BASE+0x60)
+#define TIMER4VALUEHIGH         (TIMERS_BASE+0x64)
+
+/* 8082_0000 - 8082_ffff: I2S */
+#define I2S_OFFSET            0x020000
+#define I2S_BASE              (EP93XX_APB_BASE|I2S_OFFSET)
+
+#define I2STxClkCfg           (I2S_BASE+0x00)	/* 8082.0000 R/W Transmitter clock config register  */
+#define I2SRxClkCfg           (I2S_BASE+0x04)	/* 8082.0004 R/W Receiver clock config register     */
+#define I2SGlSts              (I2S_BASE+0x08)	/* 8082.0008 R/W SAI Global Status register.        */
+#define I2SGlCtrl             (I2S_BASE+0x0C)	/* 8082.000C R/W SAI Global Control register        */
+
+#define I2STX0Lft             (I2S_BASE+0x10)	/* 8082.0010 R/W Left  TX data reg for channel 0    */
+#define I2STX0Rt              (I2S_BASE+0x14)	/* 8082.0014 R/W Right TX data reg for channel 0    */
+#define I2STX1Lft             (I2S_BASE+0x18)	/* 8082.0018 R/W Left  TX data reg for channel 1    */
+#define I2STX1Rt              (I2S_BASE+0x1C)	/* 8082.001C R/W Right TX data reg for channel 1    */
+#define I2STX2Lft             (I2S_BASE+0x20)	/* 8082.0020 R/W Left  TX data reg for channel 2    */
+#define I2STX2Rt              (I2S_BASE+0x24)	/* 8082.0024 R/W Right TX data reg for channel 2    */
+
+#define I2STXLinCtrlData      (I2S_BASE+0x28)	/* 8082.0028 R/W TX Line Control data register      */
+#define I2STXCtrl             (I2S_BASE+0x2C)	/* 8082.002C R/W TX Control register                */
+#define I2STXWrdLen           (I2S_BASE+0x30)	/* 8082.0030 R/W TX Word Length                     */
+#define I2STX0En              (I2S_BASE+0x34)	/* 8082.0034 R/W TX0 Channel Enable                 */
+#define I2STX1En              (I2S_BASE+0x38)	/* 8082.0038 R/W TX1 Channel Enable                 */
+#define I2STX2En              (I2S_BASE+0x3C)	/* 8082.003C R/W TX2 Channel Enable                 */
+
+#define I2SRX0Lft             (I2S_BASE+0x40)	/* 8082.0040 R   Left  RX data reg for channel 0    */
+#define I2SRX0Rt              (I2S_BASE+0x44)	/* 8082.0044 R   Right RX data reg for channel 0    */
+#define I2SRX1Lft             (I2S_BASE+0x48)	/* 8082.0048 R   Left  RX data reg for channel 1    */
+#define I2SRX1Rt              (I2S_BASE+0x4C)	/* 8082.004c R   Right RX data reg for channel 1    */
+#define I2SRX2Lft             (I2S_BASE+0x50)	/* 8082.0050 R   Left  RX data reg for channel 2    */
+#define I2SRX2Rt              (I2S_BASE+0x54)	/* 8082.0054 R   Right RX data reg for channel 2    */
+
+#define I2SRXLinCtrlData      (I2S_BASE+0x58)	/* 8082.0058 R/W RX Line Control data register      */
+#define I2SRXCtrl             (I2S_BASE+0x5C)	/* 8082.005C R/W RX Control register                */
+#define I2SRXWrdLen           (I2S_BASE+0x60)	/* 8082.0060 R/W RX Word Length                     */
+#define I2SRX0En              (I2S_BASE+0x64)	/* 8082.0064 R/W RX0 Channel Enable                 */
+#define I2SRX1En              (I2S_BASE+0x68)	/* 8082.0068 R/W RX1 Channel Enable                 */
+#define I2SRX2En              (I2S_BASE+0x6C)	/* 8082.006C R/W RX2 Channel Enable                 */
+
+/* 8083_0000 - 8083_ffff: Security Block */
+#define SECURITY_OFFSET         0x030000
+#define SECURITY_BASE           (EP93XX_APB_BASE|SECURITY_OFFSET)
+#define SECFLG                  (SECURITY_BASE+0x2400)
+#define SECEN                   (SECURITY_BASE+0x2410)
+#define UNIQID                  (SECURITY_BASE+0x2440)
+#define UNIQCHK                 (SECURITY_BASE+0x2450)
+#define UNIQVAL                 (SECURITY_BASE+0x2460)
+#define CLINBOOT                (SECURITY_BASE+0x2480)
+#define CLINVADDR               (SECURITY_BASE+0x2484)
+#define CLSETSKRNL              (SECURITY_BASE+0x2488)
+#define CLSKRNL                 (SECURITY_BASE+0x248C)
+#define ITTMP                   (SECURITY_BASE+0x2490)
+#define ETBL1                   (SECURITY_BASE+0x24A0)
+#define ETCL1                   (SECURITY_BASE+0x24A4)
+#define ETAPL1                  (SECURITY_BASE+0x24A8)
+#define ETSPTREG1               (SECURITY_BASE+0x24B0)
+#define ETSPTREG2               (SECURITY_BASE+0x24B4)
+#define ETSPTREG3               (SECURITY_BASE+0x24B8)
+
+#define SECID1                  (SECURITY_BASE+0x2500)
+#define SECID2                  (SECURITY_BASE+0x2504)
+#define SECCHK1                 (SECURITY_BASE+0x2520)
+#define SECCHK2                 (SECURITY_BASE+0x2524)
+#define SECVAL1                 (SECURITY_BASE+0x2540)
+#define SECVAL2                 (SECURITY_BASE+0x2544)
+
+#define UNIQID2                 (SECURITY_BASE+0x2700)
+#define UNIQID3                 (SECURITY_BASE+0x2704)
+#define UNIQID4                 (SECURITY_BASE+0x2708)
+#define UNIQID5                 (SECURITY_BASE+0x270C)
+#define UNIQCHK2                (SECURITY_BASE+0x2710)
+#define USRFLG                  (SECURITY_BASE+0x2714)	/* llandre tells me this is also a CPU model flag */
+#define UNIQVAL2                (SECURITY_BASE+0x2720)
+#define UNIQVAL3                (SECURITY_BASE+0x2724)
+#define UNIQVAL4                (SECURITY_BASE+0x2728)
+#define TESTVAL                 (SECURITY_BASE+0x2744)
+#define TESTCHK                 (SECURITY_BASE+0x2754)
+#define ACHK1                   (SECURITY_BASE+0x27A0)
+#define ACHK2                   (SECURITY_BASE+0x27A4)
+#define PROCRESET               (SECURITY_BASE+0x27A8)
+#define TESTIDR                 (SECURITY_BASE+0x27AC)
+#define AVAL1                   (SECURITY_BASE+0x27B0)
+#define AVAL2                   (SECURITY_BASE+0x27B4)
+#define AID1                    (SECURITY_BASE+0x27C4)
+#define AID2                    (SECURITY_BASE+0x27C8)
+#define ADYNREMAP               (SECURITY_BASE+0x27D0)
+#define ALTTMP                  (SECURITY_BASE+0x27D4)
+#define PROCSIGN                (SECURITY_BASE+0x27F0)
+
+#define ECLIDX                  (SECURITY_BASE+0x2800)
+#define ECLINE0                 (SECURITY_BASE+0x2810)
+#define ECLINE1                 (SECURITY_BASE+0x2814)
+#define ECLINE2                 (SECURITY_BASE+0x2818)
+#define ECLINE3                 (SECURITY_BASE+0x281C)
+#define ECLINE4                 (SECURITY_BASE+0x2820)
+#define ECLINE5                 (SECURITY_BASE+0x2824)
+#define ECLINE6                 (SECURITY_BASE+0x2828)
+#define ECLINE7                 (SECURITY_BASE+0x282C)
+#define ETWIDX1                 (SECURITY_BASE+0x2840)
+#define ETWL1                   (SECURITY_BASE+0x2844)
+#define ETWIDX2                 (SECURITY_BASE+0x2848)
+#define ETWL2                   (SECURITY_BASE+0x284C)
+
+#define ETSPT10                 (SECURITY_BASE+0x4000)
+#define ETSPT11                 (SECURITY_BASE+0x4004)
+#define ETSPT12                 (SECURITY_BASE+0x4008)
+#define ETSPT13                 (SECURITY_BASE+0x400C)
+
+#define ETSPT2000               (SECURITY_BASE+0x6000)
+#define ETSPT2020               (SECURITY_BASE+0x6020)
+#define ETSPT2024               (SECURITY_BASE+0x6024)
+
+/* 8084_0000 - 8084_ffff: GPIO */
+#define GPIO_OFFSET              0x040000
+#define GPIO_BASE                (EP93XX_APB_BASE|GPIO_OFFSET)
+#define GPIO_PADR                (GPIO_BASE+0x00)
+#define GPIO_PBDR                (GPIO_BASE+0x04)
+#define GPIO_PCDR                (GPIO_BASE+0x08)
+
+/* For support EP9301 - EP9302 arch */
+
+#if !defined(CONFIG_ARCH_EP9301) && !defined (CONFIG_ARCH_EP9302)
+#define GPIO_PDDR                (GPIO_BASE+0x0C)
+#endif
+
+#define GPIO_PADDR               (GPIO_BASE+0x10)
+#define GPIO_PBDDR               (GPIO_BASE+0x14)
+#define GPIO_PCDDR               (GPIO_BASE+0x18)
+
+/* For support EP9301 - EP9302 arch */
+
+#if !defined(CONFIG_ARCH_EP9301) && !defined (CONFIG_ARCH_EP9302)
+#define GPIO_PDDDR               (GPIO_BASE+0x1C)
+#endif
+
+#define GPIO_PEDR                (GPIO_BASE+0x20)
+#define GPIO_PEDDR               (GPIO_BASE+0x24)
+#define GPIO_PFDR                (GPIO_BASE+0x30)
+#define GPIO_PFDDR               (GPIO_BASE+0x34)
+#define GPIO_PGDR                (GPIO_BASE+0x38)
+#define GPIO_PGDDR               (GPIO_BASE+0x3C)
+#define GPIO_PHDR                (GPIO_BASE+0x40)
+#define GPIO_PHDDR               (GPIO_BASE+0x44)
+#define GPIO_INTTYPE1            (GPIO_BASE+0x4C)
+#define GPIO_INTTYPE2            (GPIO_BASE+0x50)
+#define GPIO_FEOI                (GPIO_BASE+0x54)	/* WRITE ONLY - READ UNDEFINED */
+#define GPIO_INTEN               (GPIO_BASE+0x58)
+#define GPIO_INTSTATUS           (GPIO_BASE+0x5C)
+#define GPIO_RAWINTSTASUS        (GPIO_BASE+0x60)
+#define GPIO_FDB                 (GPIO_BASE+0x64)
+#define GPIO_PAPINDR             (GPIO_BASE+0x68)
+#define GPIO_PBPINDR             (GPIO_BASE+0x6C)
+#define GPIO_PCPINDR             (GPIO_BASE+0x70)
+#define GPIO_PDPINDR             (GPIO_BASE+0x74)
+#define GPIO_PEPINDR             (GPIO_BASE+0x78)
+#define GPIO_PFPINDR             (GPIO_BASE+0x7C)
+#define GPIO_PGPINDR             (GPIO_BASE+0x80)
+#define GPIO_PHPINDR             (GPIO_BASE+0x84)
+#define GPIO_AINTTYPE1           (GPIO_BASE+0x90)
+#define GPIO_AINTTYPE2           (GPIO_BASE+0x94)
+#define GPIO_AEOI                (GPIO_BASE+0x98)	/* WRITE ONLY - READ UNDEFINED */
+#define GPIO_AINTEN              (GPIO_BASE+0x9C)
+#define GPIO_INTSTATUSA          (GPIO_BASE+0xA0)
+#define GPIO_RAWINTSTSTISA       (GPIO_BASE+0xA4)
+#define GPIO_ADB                 (GPIO_BASE+0xA8)
+#define GPIO_BINTTYPE1           (GPIO_BASE+0xAC)
+#define GPIO_BINTTYPE2           (GPIO_BASE+0xB0)
+#define GPIO_BEOI                (GPIO_BASE+0xB4)	/* WRITE ONLY - READ UNDEFINED */
+#define GPIO_BINTEN              (GPIO_BASE+0xB8)
+#define GPIO_INTSTATUSB          (GPIO_BASE+0xBC)
+#define GPIO_RAWINTSTSTISB       (GPIO_BASE+0xC0)
+#define GPIO_BDB                 (GPIO_BASE+0xC4)
+#define GPIO_EEDRIVE             (GPIO_BASE+0xC8)
+/*#define Reserved               (GPIO_BASE+0xCC) */
+#define GPIO_TCR                 (GPIO_BASE+0xD0)	/* Test Registers */
+#define GPIO_TISRA               (GPIO_BASE+0xD4)	/* Test Registers */
+#define GPIO_TISRB               (GPIO_BASE+0xD8)	/* Test Registers */
+#define GPIO_TISRC               (GPIO_BASE+0xDC)	/* Test Registers */
+#define GPIO_TISRD               (GPIO_BASE+0xE0)	/* Test Registers */
+#define GPIO_TISRE               (GPIO_BASE+0xE4)	/* Test Registers */
+#define GPIO_TISRF               (GPIO_BASE+0xE8)	/* Test Registers */
+#define GPIO_TISRG               (GPIO_BASE+0xEC)	/* Test Registers */
+#define GPIO_TISRH               (GPIO_BASE+0xF0)	/* Test Registers */
+#define GPIO_TCER                (GPIO_BASE+0xF4)	/* Test Registers */
+
+/* 8088_0000 - 8088_ffff: Ac97 Controller (AAC) */
+#define AC97_OFFSET             0x080000
+#define AC97_BASE               (EP93XX_APB_BASE|AC97_OFFSET)
+#define AC97DR1                 (AC97_BASE+0x00)	/* 8088.0000 R/W Data read or written from/to FIFO1  */
+#define AC97RXCR1               (AC97_BASE+0x04)	/* 8088.0004 R/W Control register for receive        */
+#define AC97TXCR1               (AC97_BASE+0x08)	/* 8088.0008 R/W Control register for transmit       */
+#define AC97SR1                 (AC97_BASE+0x0C)	/* 8088.000C R   Status register                     */
+#define AC97RISR1               (AC97_BASE+0x10)	/* 8088.0010 R   Raw interrupt status register       */
+#define AC97ISR1                (AC97_BASE+0x14)	/* 8088.0014 R   Interrupt Status                    */
+#define AC97IE1                 (AC97_BASE+0x18)	/* 8088.0018 R/W Interrupt Enable                    */
+#define AC97DR2                 (AC97_BASE+0x20)	/* 8088.0020 R/W Data read or written from/to FIFO2  */
+#define AC97RXCR2               (AC97_BASE+0x24)	/* 8088.0024 R/W Control register for receive        */
+#define AC97TXCR2               (AC97_BASE+0x28)	/* 8088.0028 R/W Control register for transmit       */
+#define AC97SR2                 (AC97_BASE+0x2C)	/* 8088.002C R   Status register                     */
+#define AC97RISR2               (AC97_BASE+0x30)	/* 8088.0030 R   Raw interrupt status register       */
+#define AC97ISR2                (AC97_BASE+0x34)	/* 8088.0034 R   Interrupt Status                    */
+#define AC97IE2                 (AC97_BASE+0x38)	/* 8088.0038 R/W Interrupt Enable                    */
+#define AC97DR3                 (AC97_BASE+0x40)	/* 8088.0040 R/W Data read or written from/to FIFO3. */
+#define AC97RXCR3               (AC97_BASE+0x44)	/* 8088.0044 R/W Control register for receive        */
+#define AC97TXCR3               (AC97_BASE+0x48)	/* 8088.0048 R/W Control register for transmit       */
+#define AC97SR3                 (AC97_BASE+0x4C)	/* 8088.004C R   Status register                     */
+#define AC97RISR3               (AC97_BASE+0x50)	/* 8088.0050 R   Raw interrupt status register       */
+#define AC97ISR3                (AC97_BASE+0x54)	/* 8088.0054 R   Interrupt Status                    */
+#define AC97IE3                 (AC97_BASE+0x58)	/* 8088.0058 R/W Interrupt Enable                    */
+#define AC97DR4                 (AC97_BASE+0x60)	/* 8088.0060 R/W Data read or written from/to FIFO4. */
+#define AC97RXCR4               (AC97_BASE+0x64)	/* 8088.0064 R/W Control register for receive        */
+#define AC97TXCR4               (AC97_BASE+0x68)	/* 8088.0068 R/W Control register for transmit       */
+#define AC97SR4                 (AC97_BASE+0x6C)	/* 8088.006C R   Status register                     */
+#define AC97RISR4               (AC97_BASE+0x70)	/* 8088.0070 R   Raw interrupt status register       */
+#define AC97ISR4                (AC97_BASE+0x74)	/* 8088.0074 R   Interrupt Status                    */
+#define AC97IE4                 (AC97_BASE+0x78)	/* 8088.0078 R/W Interrupt Enable                    */
+#define AC97S1DATA              (AC97_BASE+0x80)	/* 8088.0080 R/W Data received/transmitted on SLOT1  */
+#define AC97S2DATA              (AC97_BASE+0x84)	/* 8088.0084 R/W Data received/transmitted on SLOT2  */
+#define AC97S12DATA             (AC97_BASE+0x88)	/* 8088.0088 R/W Data received/transmitted on SLOT12 */
+#define AC97RGIS                (AC97_BASE+0x8C)	/* 8088.008C R/W Raw Global interrupt status register */
+#define AC97GIS                 (AC97_BASE+0x90)	/* 8088.0090 R   Global interrupt status register    */
+#define AC97IM                  (AC97_BASE+0x94)	/* 8088.0094 R/W Interrupt mask register             */
+#define AC97EOI                 (AC97_BASE+0x98)	/* 8088.0098 W   Interrupt clear register            */
+#define AC97GCR                 (AC97_BASE+0x9C)	/* 8088.009C R/W Main Control register               */
+#define AC97RESET               (AC97_BASE+0xA0)	/* 8088.00A0 R/W RESET control register.             */
+#define AC97SYNC                (AC97_BASE+0xA4)	/* 8088.00A4 R/W SYNC control register.              */
+#define AC97GCIS                (AC97_BASE+0xA8)	/* 8088.00A8 R  Global chan FIFO int status register */
+
+/* 808A_0000 - 808A_ffff: SSP */
+#define SSP_OFFSET             0x0A0000
+#define SSP_BASE               (EP93XX_APB_BASE|SSP_OFFSET)
+#define SSPCR0                 (SSP_BASE+0x00)
+#define SSPCR1                 (SSP_BASE+0x04)
+#define SSPDR                  (SSP_BASE+0x08)
+#define SSPSR                  (SSP_BASE+0x0c)
+#define SSPCPSR                (SSP_BASE+0x10)
+#define SSPIIR                 (SSP_BASE+0x14)
+#define SSPICR                 (SSP_BASE+0x14)
+
+/* 808B_0000 - 808B_ffff: IrDA */
+#define IRDA_OFFSET             0x0B0000
+#define IRDA_BASE               (EP93XX_APB_BASE|IRDA_OFFSET)
+#define IrEnable                (IRDA_BASE+0x00)
+#define IrCtrl                  (IRDA_BASE+0x04)
+#define IrAdrMatchVal           (IRDA_BASE+0x08)
+#define IrFlag                  (IRDA_BASE+0x0C)
+#define IrData                  (IRDA_BASE+0x10)
+#define IrDataTail1             (IRDA_BASE+0x14)
+#define IrDataTail2             (IRDA_BASE+0x18)
+#define IrDataTail3             (IRDA_BASE+0x1c)
+#define IrRIB                   (IRDA_BASE+0x20)
+#define IrTR0                   (IRDA_BASE+0x24)
+#define IrDMACR                 (IRDA_BASE+0x28)
+#define SIRTR0                  (IRDA_BASE+0x30)
+#define MISR                    (IRDA_BASE+0x80)
+#define MIMR                    (IRDA_BASE+0x84)
+#define MIIR                    (IRDA_BASE+0x88)
+#define FISR                    (IRDA_BASE+0x180)
+#define FIMR                    (IRDA_BASE+0x184)
+#define FIIR                    (IRDA_BASE+0x188)
+
+/* 808C_0000 - 808C_ffff: UART1 */
+#define UART1_OFFSET            0x0C0000
+#define UART1_BASE              (EP93XX_APB_BASE|UART1_OFFSET)
+#define UART1DR                 (UART1_BASE+0x000)
+#define UART1RSR                (UART1_BASE+0x004)
+#define UART1ECR                (UART1_BASE+0x004)
+#define UART1CR_H               (UART1_BASE+0x008)
+#define UART1CR_M               (UART1_BASE+0x00C)
+#define UART1CR_L               (UART1_BASE+0x010)
+#define UART1CR                 (UART1_BASE+0x014)
+#define UART1FR                 (UART1_BASE+0x018)
+#define UART1IIR                (UART1_BASE+0x01C)
+#define UART1ICR                (UART1_BASE+0x01C)
+#define UART1ILPR               (UART1_BASE+0x020)
+#define UART1DMACR              (UART1_BASE+0x028)
+#define UART1TMR                (UART1_BASE+0x084)
+#define UART1MCR                (UART1_BASE+0x100)
+#define UART1MSR                (UART1_BASE+0x104)
+#define UART1TCR                (UART1_BASE+0x108)
+#define UART1TISR               (UART1_BASE+0x10C)
+#define UART1TOCR               (UART1_BASE+0x110)
+#define HDLC1CR                 (UART1_BASE+0x20c)
+#define HDLC1AMV                (UART1_BASE+0x210)
+#define HDLC1AMSK               (UART1_BASE+0x214)
+#define HDLC1RIB                (UART1_BASE+0x218)
+#define HDLC1SR                 (UART1_BASE+0x21c)
+
+/* 808d_0000 - 808d_ffff: UART2 */
+#define UART2_OFFSET            0x0D0000
+#define UART2_BASE              (EP93XX_APB_BASE|UART2_OFFSET)
+#define UART2DR                 (UART2_BASE+0x00)
+#define UART2RSR                (UART2_BASE+0x04)	/* Read */
+#define UART2ECR                (UART2_BASE+0x04)	/* Write */
+#define UART2CR_H               (UART2_BASE+0x08)
+#define UART2CR_M               (UART2_BASE+0x0C)
+#define UART2CR_L               (UART2_BASE+0x10)
+#define UART2CR                 (UART2_BASE+0x14)
+#define UART2FR                 (UART2_BASE+0x18)
+#define UART2IIR                (UART2_BASE+0x1C)	/* Read */
+#define UART2ICR                (UART2_BASE+0x1C)	/* Write */
+#define UART2ILPR               (UART2_BASE+0x20)
+#define UART2DMACR              (UART2_BASE+0x28)
+#define UART2TMR                (UART2_BASE+0x84)
+
+/* 808e_0000 - 808e_ffff: UART3 */
+#define UART3_OFFSET            0x0E0000
+#define UART3_BASE              (EP93XX_APB_BASE|UART3_OFFSET)
+#define UART3DR                 (UART3_BASE+0x00)
+#define UART3RSR                (UART3_BASE+0x04)	/* Read */
+#define UART3ECR                (UART3_BASE+0x04)	/* Write */
+#define UART3CR_H               (UART3_BASE+0x08)
+#define UART3CR_M               (UART3_BASE+0x0C)
+#define UART3CR_L               (UART3_BASE+0x10)
+#define UART3CR                 (UART3_BASE+0x14)
+#define UART3FR                 (UART3_BASE+0x18)
+#define UART3IIR                (UART3_BASE+0x1C)	/* Read */
+#define UART3ICR                (UART3_BASE+0x1C)	/* Write */
+#define UART3ILPR               (UART3_BASE+0x20)
+#define UART3DMACR              (UART3_BASE+0x28)
+#define UART3TCR                (UART3_BASE+0x80)
+#define UART3TISR               (UART3_BASE+0x88)
+#define UART3TOCR               (UART3_BASE+0x8C)
+#define UART3TMR                (UART3_BASE+0x84)
+#define UART3MCR                (UART3_BASE+0x100)	/* Modem Control Reg */
+#define UART3MSR                (UART3_BASE+0x104)	/* Modem Status Reg */
+#define UART3HDLCCR             (UART3_BASE+0x20C)	/* HDLC Registers */
+#define UART3HDLCAMV            (UART3_BASE+0x210)	/* HDLC Registers */
+#define UART3HDLCAMSK           (UART3_BASE+0x214)	/* HDLC Registers */
+#define UART3HDLCCRIB           (UART3_BASE+0x218)	/* HDLC Registers */
+#define UART3HDLCSR             (UART3_BASE+0x21C)	/* HDLC Registers */
+
+/* 808f_0000 - 808f_ffff: KEY Matrix */
+#define KEY_OFFSET              0x0F0000
+#define KEY_BASE                (EP93XX_APB_BASE|KEY_OFFSET)
+#define SCANINIT                (KEY_BASE+0x00)
+#define KEY_DIAG                (KEY_BASE+0x04)
+#define KEY_REG                 (KEY_BASE+0x08)
+#define KEY_TCR                 (KEY_BASE+0x10)
+#define KEY_TISR                (KEY_BASE+0x14)
+#define KEY_TOCR                (KEY_BASE+0x18)
+
+/* 8090_0000 - 8090_ffff: Analog Resistive Touchscreen  */
+#define TOUCH_OFFSET            0x100000
+#define TOUCH_BASE              (EP93XX_APB_BASE|TOUCH_OFFSET)
+#define TSSetup                 (TOUCH_BASE+0x00)	/* R/W touchscreen controller setup control register.     */
+#define TSXYMaxMin              (TOUCH_BASE+0x04)	/* R/W touchscreen controller max/min register.           */
+#define TSXYResult              (TOUCH_BASE+0x08)	/* R   touchscreen controller result register.            */
+#define TSDischarge             (TOUCH_BASE+0x0C)	/* LOCKED R/W touchscreen Switch Matrix control register. */
+#define TSXSample               (TOUCH_BASE+0x10)	/* LOCKED R/W touchscreen Switch Matrix control register. */
+#define TSYSample               (TOUCH_BASE+0x14)	/* LOCKED R/W touchscreen Switch Matrix control register. */
+#define TSDirect                (TOUCH_BASE+0x18)	/* LOCKED R/W touchscreen Switch Matrix control register. */
+#define TSDetect                (TOUCH_BASE+0x1C)	/* LOCKED R/W touchscreen Switch Matrix control register. */
+#define TSSWLock                (TOUCH_BASE+0x20)	/*  NA    R/W touchscreen software lock register.         */
+#define TSSetup2                (TOUCH_BASE+0x24)	/* R/W touchscreen setup control register #2.             */
+
+/* 8091_0000 - 8091_ffff: PWM */
+#define PWM_OFFSET              0x110000
+#define PWM_BASE                (EP93XX_APB_BASE|PWM_OFFSET)
+#define PWM0_TC                 (PWM_BASE+0x00)	/* 80910000 R/W PWM_0 Terminal Count */
+#define PWM0_DC                 (PWM_BASE+0x04)	/* 80910004 R/W PWM_0 Duty Cycle     */
+#define PWM0_EN                 (PWM_BASE+0x08)	/* 80910008 R/W PWM_0 Enable         */
+#define PWM0_INV                (PWM_BASE+0x0C)	/* 8091000C R/W PWM_0 Invert         */
+#define PWM0_SYNC               (PWM_BASE+0x10)	/* 80910010 R/W PWM_0 Synchronous    */
+#define PWM1_TC                 (PWM_BASE+0x20)	/* 80910020 R/W PWM_1 Terminal Count */
+#define PWM1_DC                 (PWM_BASE+0x24)	/* 80910024 R/W PWM_1 Duty Cycle     */
+#define PWM1_EN                 (PWM_BASE+0x28)	/* 80910028 R/W PWM_1 Enable         */
+#define PWM1_INV                (PWM_BASE+0x2C)	/* 8091002C R/W PWM_1 Invert         */
+#define PWM1_SYNC               (PWM_BASE+0x30)	/* 80910030 R/W PWM_1 Synchronous    */
+
+/* 8092_0000 - 8092_ffff: RTC */
+#define RTC_OFFSET              0x120000
+#define RTC_BASE                (EP93XX_APB_BASE|RTC_OFFSET)
+#define RTCDR                   (RTC_BASE+0x00)
+#define RTCMR                   (RTC_BASE+0x04)
+#define RTCSTAT                 (RTC_BASE+0x08)	/* Read */
+#define RTCEOI                  (RTC_BASE+0x08)	/* Write */
+#define RTCLR                   (RTC_BASE+0x0C)
+#define RTCCR                   (RTC_BASE+0x10)
+#define RTCSCOMP                (RTC_BASE+0x108)
+
+/* 8093_0000 - 8093_ffff: CSC/Syscon  PLL, clock control, & misc. stuff */
+#define SYSCON_OFFSET           0x130000
+#define SYSCON_BASE             (EP93XX_APB_BASE|SYSCON_OFFSET)
+#define SYSCON_PWRSR            (SYSCON_BASE+0x0000)
+#define SYSCON_PWRCNT           (SYSCON_BASE+0x0004)
+#define SYSCON_HALT             (SYSCON_BASE+0x0008)
+#define SYSCON_STBY             (SYSCON_BASE+0x000c)
+#define SYSCON_BLEOI            (SYSCON_BASE+0x0010)
+#define SYSCON_MCEOI            (SYSCON_BASE+0x0014)
+#define SYSCON_TEOI             (SYSCON_BASE+0x0018)
+#define SYSCON_STFCLR           (SYSCON_BASE+0x001c)
+#define SYSCON_CLKSET1          (SYSCON_BASE+0x0020)
+#define SYSCON_CLKSET2          (SYSCON_BASE+0x0024)
+#define SYSCON_RESV00           (SYSCON_BASE+0x0028)
+#define SYSCON_RESV01           (SYSCON_BASE+0x002c)
+#define SYSCON_RESV02           (SYSCON_BASE+0x0030)
+#define SYSCON_RESV03           (SYSCON_BASE+0x0034)
+#define SYSCON_RESV04           (SYSCON_BASE+0x0038)
+#define SYSCON_RESV05           (SYSCON_BASE+0x003c)
+#define SYSCON_SCRREG0          (SYSCON_BASE+0x0040)
+#define SYSCON_SCRREG1          (SYSCON_BASE+0x0044)
+#define SYSCON_CLKTEST          (SYSCON_BASE+0x0048)
+#define SYSCON_USBRESET         (SYSCON_BASE+0x004c)
+#define SYSCON_APBWAIT          (SYSCON_BASE+0x0050)
+#define SYSCON_BMAR             (SYSCON_BASE+0x0054)
+#define SYSCON_BOOTCLR          (SYSCON_BASE+0x0058)
+#define SYSCON_DEVCFG           (SYSCON_BASE+0x0080)
+#define SYSCON_VIDDIV           (SYSCON_BASE+0x0084)
+#define SYSCON_MIRDIV           (SYSCON_BASE+0x0088)
+#define SYSCON_I2SDIV           (SYSCON_BASE+0x008C)
+#define SYSCON_KTDIV            (SYSCON_BASE+0x0090)
+#define SYSCON_CHIPID           (SYSCON_BASE+0x0094)
+#define SYSCON_TSTCR            (SYSCON_BASE+0x0098)
+#define SYSCON_SYSCFG           (SYSCON_BASE+0x009C)
+#define SYSCON_SWLOCK           (SYSCON_BASE+0x00C0)
+
+#define SYSCON_DEVCFG_KEYS      0x00000002
+#define SYSCON_DEVCFG_RasOnP3   0x00000010
+#define SYSCON_DEVCFG_GONK      0x08000000
+
+#define SYSCON_KTDIV_KEN        0x00008000
+
+/* 8094_0000 - 8094_ffff: Watchdog */
+#define WATCHDOG_OFFSET         0x140000
+#define WATCHDOG_BASE           (EP93XX_APB_BASE|WATCHDOG_OFFSET)
+#define WATCHDOG                (WATCHDOG_BASE+0x00)
+#define WDSTATUS                (WATCHDOG_BASE+0x04)
+
+#endif				/* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-ep93xx/regs_ac97.h b/include/asm-arm/arch-ep93xx/regs_ac97.h
new file mode 100644
index 0000000..efe0015
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_ac97.h
@@ -0,0 +1,168 @@
+/*=============================================================================
+ *  FILE:           regs_ac97.h
+ *
+ *  DESCRIPTION:    Ac'97 Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ * 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
+ *=============================================================================
+ */
+#ifndef _REGS_AC97_H_
+#define _REGS_AC97_H_
+
+/* Bit definitionses */
+#define AC97ISR_RIS                     8
+#define AC97ISR_TIS                     4
+#define AC97ISR_RTIS                    2
+#define AC97ISR_TCIS                    1
+
+#define AC97RGIS_SLOT1TXCOMPLETE     0x01
+#define AC97RGIS_SLOT2RXVALID        0x02
+#define AC97RGIS_GPIOTXCOMPLETE      0x04
+#define AC97RGIS_GPIOINTRX           0x08
+#define AC97RGIS_RWIS                0x10
+#define AC97RGIS_CODECREADY          0x20
+#define AC97RGIS_SLOT2TXCOMPLETE     0x40
+
+#define AC97SR_RXFE                 0x0001
+#define AC97SR_TXFE                 0x0002
+#define AC97SR_RXFF                 0x0004
+#define AC97SR_TXFF                 0x0008
+#define AC97SR_TXBUSY               0x0010
+#define AC97SR_RXOE                 0x0020
+#define AC97SR_TXUE                 0x0040
+
+#define AC97GSR_IFE                     0x1
+#define AC97GSR_LOOP                    0x2
+#define AC97GSR_OVERRIDECODECREADY      0x4
+
+#define AC97RESET_TIMEDRESET            0x1
+#define AC97RESET_FORCEDRESET           0x2
+#define AC97RESET_EFORCER               0x4
+
+#define AC97RXCR_REN                    0x1
+
+#define AC97TXCR_TEN                    0x1
+
+/*
+ * The Ac97 Codec registers, accessable through the Ac-link.
+ * These are not controller registers and are not memory mapped.
+ * Includes registers specific to CS4202 (Beavis).
+ */
+#define AC97_REG_OFFSET_MASK                0x0000007E
+
+#define AC97_00_RESET                          0x00000000
+#define AC97_02_MASTER_VOL                     0x00000002
+#define AC97_04_HEADPHONE_VOL                  0x00000004
+#define AC97_06_MONO_VOL                       0x00000006
+#define AC97_08_TONE                           0x00000008
+#define AC97_0A_PC_BEEP_VOL                    0x0000000A
+#define AC97_0C_PHONE_VOL                      0x0000000C
+#define AC97_0E_MIC_VOL                        0x0000000E
+#define AC97_10_LINE_IN_VOL                    0x00000010
+#define AC97_12_CD_VOL                         0x00000012
+#define AC97_14_VIDEO_VOL                      0x00000014
+#define AC97_16_AUX_VOL                        0x00000016
+#define AC97_18_PCM_OUT_VOL                    0x00000018
+#define AC97_1A_RECORD_SELECT                  0x0000001A
+#define AC97_1C_RECORD_GAIN                    0x0000001C
+#define AC97_1E_RESERVED_1E                    0x0000001E
+#define AC97_20_GENERAL_PURPOSE                0x00000020
+#define AC97_22_3D_CONTROL                     0x00000022
+#define AC97_24_MODEM_RATE                     0x00000024
+#define AC97_26_POWERDOWN                      0x00000026
+#define AC97_28_EXT_AUDIO_ID                   0x00000028
+#define AC97_2A_EXT_AUDIO_POWER                0x0000002A
+#define AC97_2C_PCM_FRONT_DAC_RATE             0x0000002C
+#define AC97_2E_PCM_SURR_DAC_RATE              0x0000002E
+#define AC97_30_PCM_LFE_DAC_RATE               0x00000030
+#define AC97_32_PCM_LR_ADC_RATE                0x00000032
+#define AC97_34_MIC_ADC_RATE                   0x00000034
+#define AC97_36_6CH_VOL_C_LFE                  0x00000036
+#define AC97_38_6CH_VOL_SURROUND               0x00000038
+#define AC97_3A_SPDIF_CONTROL                  0x0000003A
+#define AC97_3C_EXT_MODEM_ID                   0x0000003C
+#define AC97_3E_EXT_MODEM_POWER                0x0000003E
+#define AC97_40_LINE1_CODEC_RATE               0x00000040
+#define AC97_42_LINE2_CODEC_RATE               0x00000042
+#define AC97_44_HANDSET_CODEC_RATE             0x00000044
+#define AC97_46_LINE1_CODEC_LEVEL              0x00000046
+#define AC97_48_LINE2_CODEC_LEVEL              0x00000048
+#define AC97_4A_HANDSET_CODEC_LEVEL            0x0000004A
+#define AC97_4C_GPIO_PIN_CONFIG                0x0000004C
+#define AC97_4E_GPIO_PIN_TYPE                  0x0000004E
+#define AC97_50_GPIO_PIN_STICKY                0x00000050
+#define AC97_52_GPIO_PIN_WAKEUP                0x00000052
+#define AC97_54_GPIO_PIN_STATUS                0x00000054
+#define AC97_56_RESERVED                       0x00000056
+#define AC97_58_RESERVED                       0x00000058
+#define AC97_5A_CRYSTAL_REV_N_FAB_ID           0x0000005A
+#define AC97_5C_TEST_AND_MISC_CTRL             0x0000005C
+#define AC97_5E_AC_MODE                        0x0000005E
+#define AC97_60_MISC_CRYSTAL_CONTROL           0x00000060
+#define AC97_62_VENDOR_RESERVED                0x00000062
+#define AC97_64_DAC_SRC_PHASE_INCR             0x00000064
+#define AC97_66_ADC_SRC_PHASE_INCR             0x00000066
+#define AC97_68_RESERVED_68                    0x00000068
+#define AC97_6A_SERIAL_PORT_CONTROL            0x0000006A
+#define AC97_6C_VENDOR_RESERVED                0x0000006C
+#define AC97_6E_VENDOR_RESERVED                0x0000006E
+#define AC97_70_BDI_CONFIG                     0x00000070
+#define AC97_72_BDI_WAKEUP                     0x00000072
+#define AC97_74_VENDOR_RESERVED                0x00000074
+#define AC97_76_CAL_ADDRESS                    0x00000076
+#define AC97_78_CAL_DATA                       0x00000078
+#define AC97_7A_VENDOR_RESERVED                0x0000007A
+#define AC97_7C_VENDOR_ID1                     0x0000007C
+#define AC97_7E_VENDOR_ID2                     0x0000007E
+
+#ifndef __ASSEMBLY__
+
+/* enum type for use with reg AC97_RECORD_SELECT */
+enum Ac97RecordSources {
+	RECORD_MIC = 0x0000,
+	RECORD_CD = 0x0101,
+	RECORD_VIDEO_IN = 0x0202,
+	RECORD_AUX_IN = 0x0303,
+	RECORD_LINE_IN = 0x0404,
+	RECORD_STEREO_MIX = 0x0505,
+	RECORD_MONO_MIX = 0x0606,
+	RECORD_PHONE_IN = 0x0707
+};
+
+#endif				/* __ASSEMBLY__ */
+
+/*
+ * Sample rates supported directly in AC97_PCM_FRONT_DAC_RATE and
+ * AC97_PCM_LR_ADC_RATE.
+ */
+#define Ac97_Fs_8000        0x1f40
+#define Ac97_Fs_11025       0x2b11
+#define Ac97_Fs_16000       0x3e80
+#define Ac97_Fs_22050       0x5622
+#define Ac97_Fs_32000       0x7d00
+#define Ac97_Fs_44100       0xac44
+#define Ac97_Fs_48000       0xbb80
+
+/*
+ * RSIZE and TSIZE in AC97RXCR and AC97TXCR
+ */
+#define Ac97_SIZE_20            2
+#define Ac97_SIZE_18            1
+#define Ac97_SIZE_16            0
+#define Ac97_SIZE_12            3
+
+#endif				/* _REGS_AC97_H_ */
diff --git a/include/asm-arm/arch-ep93xx/regs_dma.h b/include/asm-arm/arch-ep93xx/regs_dma.h
new file mode 100644
index 0000000..926965d
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_dma.h
@@ -0,0 +1,269 @@
+/*****************************************************************************
+ *
+ * linux/include/asm-arm/arch-ep93xx/regs_dma.h
+ *
+ *  Register definitions for the ep93xx dma channel registers.
+ *
+ *  Copyright (C) 2003 Cirrus Logic
+ *
+ * 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
+ *
+ ****************************************************************************/
+#ifndef _REGS_DMA_H_
+#define _REGS_DMA_H_
+
+/*****************************************************************************
+ * 0x8000.0000 -> 0x8000.003C M2P Channel 0 Registers (Tx)
+ * 0x8000.0040 -> 0x8000.007C M2P Channel 1 Registers (Rx)
+ * 0x8000.0080 -> 0x8000.00BC M2P Channel 2 Registers (Tx)
+ * 0x8000.00C0 -> 0x8000.00FC M2P Channel 3 Registers (Rx)
+ * 0x8000.0100 -> 0x8000.013C M2M Channel 0 Registers
+ * 0x8000.0140 -> 0x8000.017C M2M Channel 1 Registers
+ * 0x8000.0180 -> 0x8000.01BC Not Used
+ * 0x8000.01C0 -> 0x8000.01FC Not Used
+ * 0x8000.0200 -> 0x8000.023C M2P Channel 5 Registers (Rx)
+ * 0x8000.0240 -> 0x8000.027C M2P Channel 4 Registers (Tx)
+ * 0x8000.0280 -> 0x8000.02BC M2P Channel 7 Registers (Rx)
+ * 0x8000.02C0 -> 0x8000.02FC M2P Channel 6 Registers (Tx)
+ * 0x8000.0300 -> 0x8000.033C M2P Channel 9 Registers (Rx)
+ * 0x8000.0340 -> 0x8000.037C M2P Channel 8 Registers (Tx)
+ * 0x8000.0380 DMA Channel Arbitration register
+ * 0x8000.03C0 DMA Global Interrupt register
+ * 0x8000.03C4 -> 0x8000.03FC Not Used
+ *
+ *
+ * Internal M2P/P2M Channel Register Map
+ *
+ * Offset Name      Access  Bits Reset Value
+ * 0x00   CONTROL   R/W     6    0
+ * 0x04   INTERRUPT R/W TC* 3    0
+ * 0x08   PPALLOC   R/W     4    channel dependant
+ *                               (see reg description)
+ * 0x0C   STATUS    RO      8    0
+ * 0x10   reserved
+ * 0x14   REMAIN    RO      16   0
+ * 0X18   Reserved
+ * 0X1C   Reserved
+ * 0x20   MAXCNT0   R/W     16   0
+ * 0x24   BASE0     R/W     32   0
+ * 0x28   CURRENT0  RO      32   0
+ * 0x2C   Reserved
+ * 0x30   MAXCNT1   R/W     16   0
+ * 0x34   BASE1     R/W     32   0
+ * 0X38   CURRENT1  RO      32   0
+ * 0X3C   Reserved
+ *
+ * M2M Channel Register Map
+ * Offset Name         Access   Bits Reset Value
+ *
+ * 0x00   CONTROL      R/W      22   0
+ * 0x04   INTERRUPT    R/W TC*  3    0
+ * 0x08   Reserved
+ * 0x0C   STATUS       R/W TC*  14   0
+ * 0x10   BCR0         R/W      16   0
+ * 0x14   BCR1         R/W      16   0
+ * 0x18   SAR_BASE0    R/W      32   0
+ * 0x1C   SAR_BASE1    R/W      32   0
+ * 0x20   Reserved
+ * 0x24   SAR_CURRENT0 RO       32   0
+ * 0x28   SAR_CURRENT1 RO       32   0
+ * 0x2C   DAR_BASE0    R/W      32   0
+ * 0x30   DAR_BASE1    R/W      32   0
+ * 0x34   DAR_CURRENT0 RO       32   0
+ * 0X38   Reserved
+ * 0X3C   DAR_CURRENT1 RO       32   0
+ * * Write this location once to clear the bit (see
+ * Interrupt/Status register description for which bits
+ * this rule applies to).
+ *
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+/*
+ * DMA Register Base addresses
+ */
+static unsigned int const DMAM2PChannelBase[10] = {
+	DMA_M2P_TX_0_BASE,
+	DMA_M2P_RX_1_BASE,
+	DMA_M2P_TX_2_BASE,
+	DMA_M2P_RX_3_BASE,
+	DMA_M2P_TX_4_BASE,
+	DMA_M2P_RX_5_BASE,
+	DMA_M2P_TX_6_BASE,
+	DMA_M2P_RX_7_BASE,
+	DMA_M2P_TX_8_BASE,
+	DMA_M2P_RX_9_BASE
+};
+
+static unsigned int const DMAM2MChannelBase[2] = {
+	DMA_M2M_0_BASE,
+	DMA_M2M_1_BASE
+};
+
+#endif				/* __ASSEMBLY__ */
+
+/*----------------------------------------------------------------------------------*/
+/* M2P Registers                                                                    */
+/*----------------------------------------------------------------------------------*/
+/*
+ * M2P CONTROL register bit defines
+ */
+#define CONTROL_M2P_STALLINTEN      0x00000001	/* Enables the STALL interrupt  */
+#define CONTROL_M2P_NFBINTEN        0x00000002	/* Enables the NFB interrupt    */
+#define CONTROL_M2P_CHERRORINTEN    0x00000008	/* Enables the ChError interrupt */
+#define CONTROL_M2P_ENABLE		    0x00000010	/* Enables the channel          */
+#define CONTROL_M2P_ABRT		    0x00000020	/* Determines how DMA behaves in */
+								/* NEXT state with peripheral   */
+						    /* error                        */
+								/* 0: NEXT -> ON, ignore error  */
+								/* 1: NEXT -> STALL, disable ch. */
+#define CONTROL_M2P_ICE			    0x00000040	/* Ignore Channel Error         */
+
+/*
+ * M2P INTERRUPT register bit defines
+ */
+#define INTERRUPT_M2P_STALLINT      0x00000001	/* Indicates channel stalled.   */
+#define INTERRUPT_M2P_NFBINT        0x00000002	/* Indicates channel is hungry. */
+#define INTERRUPT_M2P_CHERRORINT    0x00000008	/* Peripheral detects error     */
+
+/*
+ * STATUS register bit defines
+ */
+#define STATUS_M2P_STALL            0x00000001	/* A '1' indicates channel is       */
+						    /* stalled                          */
+#define STATUS_M2P_NFB			    0x00000002	/* A '1' indicates channel has moved */
+								/* from NEXT state to ON state, but */
+								/* waiting for next buffer to be    */
+						    /* programmed.                      */
+#define STATUS_M2P_CHERROR		    0x00000008	/* Enables the ChError interrupt    */
+#define STATUS_M2P_CURRENT_MASK     0x00000030	/* Current state of the FSM         */
+#define STATUS_M2P_CURRENT_SHIFT    4
+#define STATUS_M2P_NEXTBUFFER	    0x00000040	/* Informs the int handler after an */
+								/* NFB int which pair of maxcnt and */
+						    /* base regs to update.             */
+#define STATUS_M2P_BYTES_MASK       0x0000f800	/* number of valid DMA data         */
+#define STATUS_M2P_BYTES_SHIFT      7	/* currently in                     */
+											    /* packer/unpacker                  */
+
+#define STATUS_M2P_DMA_NO_BUF		0x00000000
+#define STATUS_M2P_DMA_BUF_ON		0x00000010
+#define STATUS_M2P_DMA_BUF_NEXT		0x00000020
+
+/*
+ * Register masks to mask off reserved bits after reading register.
+ */
+#define M2P_MASK_PPALLOC            0x0000000f
+#define M2P_MASK_REMAIN             0x0000ffff
+#define M2P_MASK_MAXCNT0            0x0000ffff
+#define M2P_MASK_BASE0              0xffffffff
+#define M2P_MASK_CURRENT0           0xffffffff
+#define M2P_MASK_MAXCNT1            0x0000ffff
+#define M2P_MASK_BASE1              0xffffffff
+#define M2P_MASK_CURRENT1           0xffffffff
+
+/*----------------------------------------------------------------------------------*/
+/* M2M Registers                                                                    */
+/*----------------------------------------------------------------------------------*/
+
+#define CONTROL_M2M_STALLINTEN	0x00000001	/* Enables the STALL interrupt                     */
+#define CONTROL_M2M_SCT			0x00000002	/* Source Copy Transfer. Setup a                   */
+										    /* block transfer from 1 memory source             */
+										    /* location.                                       */
+#define CONTROL_M2M_DONEINTEN	0x00000004	/* Enables the DONE interrupt which                */
+										    /* indicates if the xfer completed                 */
+										    /* successfully                                    */
+#define CONTROL_M2M_ENABLE		0x00000008	/* Enables the channel                             */
+#define CONTROL_M2M_START		0x00000010	/* Initiates the xfer. 'software trigger'          */
+#define CONTROL_M2M_BWC_MASK	0x000001e0	/* Bandwidth control. Indicate number of           */
+#define CONTROL_M2M_BWC_SHIFT   5	/* bytes in a transfer.                            */
+#define CONTROL_M2M_PW_MASK		0x00000600	/* Peripheral width. Used for xfers                */
+#define CONTROL_M2M_PW_SHIFT    9	/* between memory and external peripheral.         */
+										    /* 00: byte, 01: halfword, 10: word.               */
+#define CONTROL_M2M_DAH			0x00000800	/* Destination Address Hold                        */
+#define CONTROL_M2M_SAH			0x00001000	/* Source Address Hold                             */
+#define CONTROL_M2M_TM_MASK     0x00006000	/* Transfer Mode. 00: sw triggered,                */
+#define CONTROL_M2M_TM_SHIFT    13	/* 01: hw initiated M2P, 01: hw initiated P2M      */
+#define CONTROL_M2M_ETDP_MASK	0x00018000	/* End-of-Transfer/Terminal Count pin              */
+#define CONTROL_M2M_ETDP_SHIFT  15	/* direction and polarity.                         */
+#define CONTROL_M2M_DACKP		0x00020000	/* DMA acknowledge pin polarity                    */
+
+#define CONTROL_M2M_DREQP_MASK  0x00180000	/* DMA request pin polarity. must be set           */
+#define CONTROL_M2M_DREQP_SHIFT 19	/* before enable bit.                              */
+#define CONTROL_M2M_NFBINTEN	0x00200000	/* Enables generation of the NFB interrupt.        */
+#define CONTROL_M2M_RSS_MASK    0x00c00000	/* Request source selection:                       */
+#define CONTROL_M2M_RSS_SHIFT	22	/*              000 - External DReq[0]                     */
+										    /*          001 - External DReq[1]                     */
+										    /*          01X - Internal SSPRx                       */
+										    /*          10X - Internal SSPTx                       */
+										    /*          11X - Internal IDE                         */
+#define CONTROL_M2M_NO_HDSK		0x01000000	/* No handshake.  When set the peripheral doesn't  */
+										    /* require the regular handshake protocal. Must    */
+										/* be set for SSP and IDE operations, optional     */
+										    /* for external peripherals.                       */
+#define CONTROL_M2M_PWSC_MASK   0xfe000000	/* Peripheral wait states count. Gives the latency */
+#define CONTROL_M2M_PWSC_SHIFT	25	/* (in PCLK cycles) needed by the peripheral to    */
+										/* deassert its' request once the M2M xfer w/ DMA  */
+										/* is complete.                                    */
+
+/*
+ * M2M INTERRUPT register bit defines
+ */
+#define INTERRUPT_M2M_STALLINT	0x00000001	/* Stall interrupt indicates channel stalled. */
+#define INTERRUPT_M2M_DONEINT	0x00000002	/* Transaction done.                          */
+#define INTERRUPT_M2M_NFBINT	0x00000004	/* Next frame buffer interrupt indicates      */
+											/* channel requires a new buffer              */
+
+/*
+ * M2M STATUS register bit defines
+ */
+#define STATUS_M2M_STALL		0x00000001	/* A '1' indicates channel is stalled           */
+#define STATUS_M2M_CURRENTSTATE_MASK  0x0000003e	/* Indicates state of M2M Channel control       */
+#define STATUS_M2M_CURRENTSTATE_SHIFT 1	/* FSM (0-2):                                   */
+										    /*  000 - IDLE, 001 - STALL, 010 - MEM_RD,      */
+										    /*  011 - MEM_WR, 100 - BWC_WAIT                */
+										    /* and M2M buffer FSM (3-2):                    */
+										    /*  00 - NO_BUF, 01 - BUF_ON, 10 - BUF_NEXT     */
+#define STATUS_M2M_DONE		    0x00000040	/* Transfer completed successfully if 1.        */
+#define STATUS_M2M_TCS_MASK		0x00000180	/* Terminal Count status. Indicates whether or  */
+#define STATUS_M2M_TCS_SHIFT    7	/* or not the actual byte count reached         */
+										/* programmed limit for buffer descriptor       */
+#define STATUS_M2M_EOTS_MASK    0x00000600	/* End-of-Transfer status for buffer            */
+#define STATUS_M2M_EOTS_SHIFT   9
+#define STATUS_M2M_NFB			0x00000800	/* A '1' indicates channel has moved            */
+										    /* from NEXT state to ON state, but the next    */
+										    /* byte count reg for next buffer has not been  */
+										    /* programmed yet.                              */
+#define STATUS_M2M_NB			0x00001000	/* NextBuffer status. Informs NFB service       */
+										    /* routine, after NFB int, which pair of buffer */
+										    /* descriptor registers is free to update.      */
+#define STATUS_M2M_DREQS		0x00002000	/* DREQ status.  Reflects the status of the     */
+										    /* synchronized external peripherals DMA        */
+										    /* request signal.                              */
+
+/*
+ * Register masks to mask off reserved bits after reading register.
+ */
+#define M2M_MASK_BCR0             0x0000ffff
+#define M2M_MASK_BCR1             0x0000ffff
+#define M2M_MASK_SAR_BASE0        0xffffffff
+#define M2M_MASK_SAR_BASE1        0xffffffff
+#define M2M_MASK_SAR_CURRENT0     0xffffffff
+#define M2M_MASK_SAR_CURRENT1     0xffffffff
+#define M2M_MASK_DAR_BASE0        0xffffffff
+#define M2M_MASK_DAR_BASE1        0xffffffff
+#define M2M_MASK_DAR_CURRENT0     0xffffffff
+#define M2M_MASK_DAR_CURRENT1     0xffffffff
+
+#endif				/* _REGS_DMA_H_ */
diff --git a/include/asm-arm/arch-ep93xx/regs_gpio.h b/include/asm-arm/arch-ep93xx/regs_gpio.h
new file mode 100644
index 0000000..12397be
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_gpio.h
@@ -0,0 +1,31 @@
+/*=======================================================================
+ *
+ *  FILE:       regs_gpio.h
+ *
+ *  DESCRIPTION:    GPIO Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ * 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
+ *=======================================================================
+ */
+#ifndef _REGS_GPIO_H_
+#define _REGS_GPIO_H_
+
+/*
+ * This file intentionally blank.
+ */
+
+#endif				/* _REGS_GPIO_H_ */
diff --git a/include/asm-arm/arch-ep93xx/regs_hardcode.h b/include/asm-arm/arch-ep93xx/regs_hardcode.h
new file mode 100644
index 0000000..ecbc512
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_hardcode.h
@@ -0,0 +1,110 @@
+/*
+ *  File:   linux/include/asm-arm/arch-ep93xx/regs_hardcode.h
+ *
+ *  Handle 'Must-be-zero' and 'Must-be-one' values for various
+ *  registers on different flavours of the EP93xx family.
+ *
+ *  Copyright (C) 2004 Ray Lehtiniemi
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_HARDCODE_H
+#define __ASM_ARCH_HARDCODE_H
+
+#if defined(CONFIG_ARCH_EP9301)
+#define ep93xx_SYSCON_DEVCFG(v)        (((v) & ~0x0460c220) | 0x08000d00)
+#define ep93xx_VIC0INTSELECT(v)        (((v) & ~0xf8080000) | 0x00000000)
+#define ep93xx_VIC1INTSELECT(v)        (((v) & ~0x06879a04) | 0x00000000)
+#define ep93xx_VIC0INTENABLE(v)        (((v) & ~0xf8080000) | 0x00000000)
+#define ep93xx_VIC1INTENABLE(v)        (((v) & ~0x06879a04) | 0x00000000)
+#define ep93xx_VIC0INTENCLEAR(v)       (((v) & ~0xf8080000) | 0x00000000)
+#define ep93xx_VIC1INTENCLEAR(v)       (((v) & ~0x06879a04) | 0x00000000)
+#define ep93xx_MAC_RXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_RXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_RXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_UART1MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
+#define ep93xx_UART2TMR(v)             (((v) & ~0x000000fd) | 0x00000000)
+#define ep93xx_IrCtrl(v)               (((v) & ~0x00000001) | 0x00000000)
+#define ep93xx_RTCSCOMP(v)             (((v) & ~0x00200000) | 0x00000000)
+
+/* cut'n'paste from 9301, verify this section... */
+#elif defined(CONFIG_ARCH_EP9302)
+#define ep93xx_SYSCON_DEVCFG(v)        (((v) & ~0x0460c220) | 0x08000d00)
+#define ep93xx_VIC0INTSELECT(v)        (((v) & ~0xf8080000) | 0x00000000)
+#define ep93xx_VIC1INTSELECT(v)        (((v) & ~0x06879a04) | 0x00000000)
+#define ep93xx_VIC0INTENABLE(v)        (((v) & ~0xf8080000) | 0x00000000)
+#define ep93xx_VIC1INTENABLE(v)        (((v) & ~0x06879a04) | 0x00000000)
+#define ep93xx_VIC0INTENCLEAR(v)       (((v) & ~0xf8080000) | 0x00000000)
+#define ep93xx_VIC1INTENCLEAR(v)       (((v) & ~0x06879a04) | 0x00000000)
+#define ep93xx_MAC_RXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_RXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_RXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_UART1MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
+#define ep93xx_UART2TMR(v)             (((v) & ~0x000000fd) | 0x00000000)
+#define ep93xx_IrCtrl(v)               (((v) & ~0x00000001) | 0x00000000)
+#define ep93xx_RTCSCOMP(v)             (((v) & ~0x00200000) | 0x00000000)
+
+#elif defined(CONFIG_ARCH_EP9312)
+#define ep93xx_SYSCON_DEVCFG(v)        (((v) & ~0x00000020) | 0x00000000)
+#define ep93xx_VIC0INTSELECT(v)        (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC1INTSELECT(v)        (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC0INTENABLE(v)        (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC1INTENABLE(v)        (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC0INTENCLEAR(v)       (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC1INTENCLEAR(v)       (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_PIXELMODE(v)            (((v) & ~0x00010000) | 0x00000000)
+#define ep93xx_MAC_RXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_RXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_RXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_UART1MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
+#define ep93xx_UART2TMR(v)             (((v) & ~0x000000fd) | 0x00000000)
+#define ep93xx_UART3MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
+#define ep93xx_IrCtrl(v)               (((v) & ~0x00000001) | 0x00000000)
+#define ep93xx_RTCSCOMP(v)             (((v) & ~0x00200000) | 0x00000000)
+
+#elif defined(CONFIG_ARCH_EP9315)
+#define ep93xx_SYSCON_DEVCFG(v)        (((v) & ~0x00000020) | 0x00000000)
+#define ep93xx_VIC0INTSELECT(v)        (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC1INTSELECT(v)        (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC0INTENABLE(v)        (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC1INTENABLE(v)        (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC0INTENCLEAR(v)       (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_VIC1INTENCLEAR(v)       (((v) & ~0x00000000) | 0x00000000)
+#define ep93xx_PIXELMODE(v)            (((v) & ~0x00010000) | 0x00000000)
+#define ep93xx_MAC_RXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_RXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_RXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_MAC_TXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
+#define ep93xx_UART1MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
+#define ep93xx_UART2TMR(v)             (((v) & ~0x000000fd) | 0x00000000)
+#define ep93xx_UART3MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
+#define ep93xx_IrCtrl(v)               (((v) & ~0x00000001) | 0x00000000)
+#define ep93xx_RTCSCOMP(v)             (((v) & ~0x00200000) | 0x00000000)
+
+#endif
+
+#endif				/* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-ep93xx/regs_i2s.h b/include/asm-arm/arch-ep93xx/regs_i2s.h
new file mode 100644
index 0000000..2ca60df
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_i2s.h
@@ -0,0 +1,91 @@
+/*=============================================================================
+ *
+ *  FILE:       	reg_i2s.h
+ *
+ *  DESCRIPTION:    ep93xx I2S Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ * 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
+ *
+ *=============================================================================
+ */
+#ifndef _REG_I2S_H_
+#define _REG_I2S_H_
+
+/* I2STXClkCfg bits */
+#define i2s_txcc_trls           0x00000001
+#define i2s_txcc_tckp           0x00000002
+#define i2s_txcc_trel           0x00000004
+#define i2s_txcc_mstr           0x00000008
+#define i2s_txcc_nbcg           0x00000010
+
+#define i2s_txcc_bcr_32x        0x00000020
+#define i2s_txcc_bcr_64x        0x00000040
+#define i2s_txcc_bcr_128x       0x00000060
+
+/* I2SRxClkCfg bits */
+#define i2s_rxcc_rrls           0x00000001
+#define i2s_rxcc_rckp           0x00000002
+#define i2s_rxcc_rrel           0x00000004
+#define i2s_rxcc_mstr           0x00000008
+#define i2s_rxcc_nbcg           0x00000010
+
+#define i2s_rxcc_bcr_32x        0x00000020
+#define i2s_rxcc_bcr_64x        0x00000040
+#define i2s_rxcc_bcr_128x       0x00000060
+
+/* I2SGlSts bits */
+#define TX0_UNDERFLOW           0x00000001
+#define TX1_UNDERFLOW           0x00000002
+#define TX2_UNDERFLOW           0x00000004
+
+#define RX0_OVERFLOW            0x00000008
+#define RX1_OVERFLOW            0x00000010
+#define RX2_OVERFLOW            0x00000020
+
+#define TX0_OVERFLOW            0x00000040
+#define TX1_OVERFLOW            0x00000080
+#define TX2_OVERFLOW            0x00000100
+
+#define RX0_UNDERFLOW           0x00000200
+#define RX1_UNDERFLOW           0x00000400
+#define RX2_UNDERFLOW           0x00000800
+
+#define TX0_FIFO_FULL           0x00001000
+#define TX0_FIFO_EMPTY          0x00002000
+#define TX0_FIFO_HALF_EMPTY     0x00004000
+
+#define RX0_FIFO_FULL           0x00008000
+#define RX0_FIFO_EMPTY          0x00010000
+#define RX0_FIFO_HALF_FULL      0x00020000
+
+#define TX1_FIFO_FULL           0x00040000
+#define TX1_FIFO_EMPTY          0x00080000
+#define TX1_FIFO_HALF_EMPTY     0x00100000
+
+#define RX1_FIFO_FULL           0x00200000
+#define RX1_FIFO_EMPTY          0x00400000
+#define RX1_FIFO_HALF_FULL      0x00800000
+
+#define TX2_FIFO_FULL           0x01000000
+#define TX2_FIFO_EMPTY          0x02000000
+#define TX2_FIFO_HALF_EMPTY     0x04000000
+
+#define RX2_FIFO_FULL           0x08000000
+#define RX2_FIFO_EMPTY          0x10000000
+#define RX2_FIFO_HALF_FULL      0x20000000
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/regs_ide.h b/include/asm-arm/arch-ep93xx/regs_ide.h
new file mode 100644
index 0000000..762ebfd
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_ide.h
@@ -0,0 +1,250 @@
+/*****************************************************************************
+ *
+ *  linux/include/asm-arm/arch-ep93xx/regs_ide.h
+ *
+ *  Register definitions for the ep93xx ide registers.
+ *
+ *  Copyright (C) 2003 Cirrus Logic
+ *
+ * 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
+
+ *
+ ****************************************************************************/
+#ifndef _REGS_IDE_H_
+#define _REGS_IDE_H_
+
+#ifndef __ASSEMBLY__
+
+/*****************************************************************************
+ *
+ * IDE register definitions
+ *
+ ****************************************************************************/
+typedef struct _ide_regs_s {
+	union {
+		unsigned int Value;
+	} IDECR;		/* 00 */
+
+	union {
+		struct {
+			unsigned int IDEEN:1;	/* IDE master enable                    */
+			unsigned int PIO:1;	/* Polled IO operation selection        */
+			unsigned int MDMA:1;	/* Multiword DMA operation selection    */
+			unsigned int UDMA:1;	/* Ultra DMA operation selection        */
+			unsigned int MODE:4;	/* Speed mode number (0 - 4 for PIO,    */
+			/* 0 - 2 for MDMA, 0 - 4 for UDMA)      */
+			unsigned int WST:2;	/* Wait State for Turn.  Number of      */
+			/* HCLK cycles to hold the data bus     */
+			/* after                                */
+			/* PIO write operation                  */
+			unsigned int RAZ:22;	/* read only always zero                */
+		} Field;
+		unsigned int Value;
+	} IDECFG;		/* 04 */
+
+	union {
+		struct {
+			unsigned int MEN:1;	/* Enable Multiword DMA operation.      */
+			/* 1 - start mdma, 0 - terminate        */
+			/* mdma operation by host.              */
+			unsigned int RWOP:1;	/* Read or write operation selection:   */
+			/* 0 = read, 1 = write.                 */
+			unsigned int RAZ:30;	/* read only always zero                */
+		} Field;
+		unsigned int Value;
+	} IDEMDMAOP;		/* 08 */
+
+	union {
+		struct {
+			unsigned int UEN:1;	/* Enable Ultra DMA operation           */
+			/* 1 - start udma, 0 - terminate        */
+			/* udma operation by host.              */
+			unsigned int RWOP:1;	/* Read or write operation selection:   */
+			/* 0 = read, 1 = write.                 */
+			unsigned int RAZ:30;	/* read only always zero                */
+		} Field;
+		unsigned int Value;
+	} IDEUDMAOP;		/* 0C */
+
+	union {
+		unsigned int Value;
+	} IDEDATAOUT;		/* 10 */
+
+	union {
+		unsigned int Value;
+	} IDEDATAIN;		/* 14 */
+
+	union {
+		struct {
+			unsigned int IDEDD:32;	/* IDE output data in the output buffer */
+			/* in MDMA mode.  This register should  */
+			/* only be written to by the DMA engine. */
+		} Field;
+		unsigned int Value;
+	} IDEMDMADATAOUT;	/* 18 */
+
+	union {
+		struct {
+			unsigned int IDEDD:32;	/* IDE input data in the input buffer   */
+			/* in MDMA mode.                        */
+		} Field;
+		unsigned int Value;
+	} IDEMDMADATAIN;	/* 1C */
+
+	union {
+		struct {
+			unsigned int IDEDD:32;	/* IDE output data at the tail of the   */
+			/* output buffer in UDMA mode.          */
+		} Field;
+		unsigned int Value;
+	} IDEUDMADATAOUT;	/* 20 */
+
+	union {
+		struct {
+			unsigned int IDEDD:32;	/* IDE input data at teh head of the    */
+			/* input buffer in UDMA mode.           */
+		} Field;
+		unsigned int Value;
+	} IDEUDMADATAIN;	/* 24 */
+
+	union {
+		struct {
+			unsigned int CS0n:1;	/* Chip select pin 0 status. Should     */
+			/* be driven to 1 (deasserted) in UDMA  */
+			unsigned int CS1n:1;	/* Chip select pin 1 status. Should     */
+			/* be driven to 1 (deasserted) in UDMA  */
+			unsigned int DA:3;	/* Device address status, should be     */
+			/* driven to 0 (deasserted) in UDMA     */
+			unsigned int HSHD:1;	/* HSTROBE (during data out) status,    */
+			/* HDMARDYn (during data in) status,    */
+			/* driven by UDMA state machine.        */
+			unsigned int STOP:1;	/* STOP (during data out) status, driven */
+			/* by UDMA state machine.               */
+			unsigned int DM:1;	/* DMACKn status, driven by UDMA state  */
+			/* machine.                             */
+			unsigned int DDOE:1;	/* DD bus output enable as controlled   */
+			/* by UDMA state machine.               */
+			unsigned int DMARQ:1;	/* Synchronized version of DMARQ input  */
+			/* from device.                         */
+			unsigned int DSDD:1;	/* DSTROBE (during data in) and DDMARDYn */
+			/* (during data out) status from device. */
+			unsigned int RAZ1:5;	/* reserved, always zero                */
+			unsigned int DMAIDE:1;	/* DMA request signal from UDMA state   */
+			/* machine.                             */
+			unsigned int INTIDE:1;	/* INT line generated by UDMA state     */
+			/* machine.                             */
+			unsigned int SBUSY:1;	/* UDMA state machine busy, not in idle */
+			/* state.                               */
+			unsigned int RAZ2:5;	/* Reserved, always zero.               */
+			unsigned int NDO:1;	/* Error for data out not completed     */
+			unsigned int NDI:1;	/* Error for data in not completed      */
+			unsigned int N4X:1;	/* Error for data transferred not       */
+			/* multiples of 4 32 bit words.         */
+			unsigned int RAZ3:5;	/* Reserved, always zero                */
+		} Field;
+		unsigned int Value;
+	} IDEUDMASTATUS;	/* 28 */
+
+	union {
+		struct {
+			unsigned int RWOE:1;	/* Reset UDMA write data out error.     */
+			unsigned int RWPTR:1;	/* Reset UDMA write buffer ptr to 0.    */
+			unsigned int RWDR:1;	/* Reset UDMA write DMA request.        */
+			unsigned int RROE:1;	/* Reset UDMA read data in error.       */
+			unsigned int RRPTR:1;	/* Reset UDMA read buffer ptr to 0.     */
+			unsigned int RRDR:1;	/* Reset UDMA read DMA request.         */
+			unsigned int RAZ:26;	/* reserved, always zero                */
+		} Field;
+		unsigned int Value;
+	} IDEUDMADEBUG;		/* 2C */
+
+	union {
+		struct {
+			unsigned int HPTR:4;	/* Head pointer in the write buffer     */
+			unsigned int TPTR:4;	/* Tail pointer in the write buffer     */
+			unsigned int EMPTY:1;	/* Write buffer empty status            */
+			unsigned int HOM:1;	/* Half or more entries in write buffer */
+			/* filled status                        */
+			unsigned int NFULL:1;	/* Write buffer near full status        */
+			unsigned int FULL:1;	/* Write buffer full status             */
+			unsigned int RAZ:4;	/* Reserved, always zero                */
+			unsigned int CRC:16;	/* CRC result for data operation        */
+			/* TODO: is there a CRC?                */
+		} Field;
+		unsigned int Value;
+	} IDEUDMAWFST;		/* 30 */
+
+	union {
+		struct {
+			unsigned int HPTR:4;	/* Head pointer in the read buffer      */
+			unsigned int TPTR:4;	/* Tail pointer in the read buffer      */
+			unsigned int EMPTY:1;	/* Read buffer empty status             */
+			unsigned int HOM:1;	/* Half or more entries in read buffer  */
+			/* filled status                        */
+			unsigned int NFULL:1;	/* Read buffer near full status         */
+			unsigned int FULL:1;	/* Read buffer full status              */
+			unsigned int RAZ:4;	/* Reserved, always zero                */
+			unsigned int CRC:16;	/* CRC result for data operation        */
+			/* TODO: is there a CRC?                */
+		} Field;
+		unsigned int Value;
+	} IDEUDMARFST;		/* 34 */
+
+} IDEREGISTERS;
+
+/*****************************************************************************
+ *
+ * Global Register Anchor Definitions (these address values will change)
+ *
+ ****************************************************************************/
+#ifdef CONFIG_BLK_DEV_EP93XX
+static volatile IDEREGISTERS *const ep93xx_ide_regs =
+    (IDEREGISTERS *) (IDE_BASE);
+#endif
+
+#endif				/* Not __ASSEMBLY__ */
+
+#define IDECtrl             HW_REG(io_p2v(0x800a0000))
+#define IDECfg              HW_REG(io_p2v(0x800a0004))
+#define IDEMDMAOp           HW_REG(io_p2v(0x800a0008))
+#define IDEUDMAOp           HW_REG(io_p2v(0x800a000c))
+#define IDEDataOut          HW_REG(io_p2v(0x800a0010))
+#define IDEDataIn           HW_REG(io_p2v(0x800a0014))
+#define IDEMDMADataOut      HW_REG(io_p2v(0x800a0018))
+#define IDEMDMADataIn       HW_REG(io_p2v(0x800a001c))
+#define IDEUDMADataOut      HW_REG(io_p2v(0x800a0020))
+#define IDEUDMADataIn       HW_REG(io_p2v(0x800a0024))
+#define IDEUDMASts          HW_REG(io_p2v(0x800a0028))
+#define IDEUDMADebug        HW_REG(io_p2v(0x800a002c))
+#define IDEUDMAWrBufSts     HW_REG(io_p2v(0x800a0030))
+#define IDEUDMARdBufSts     HW_REG(io_p2v(0x800a0034))
+
+/*****************************************************************************
+ *
+ *  Bit definitions for use with assembly code for the ide control register.
+ *
+ ****************************************************************************/
+#define IDECtrl_CS0n          0x00000001
+#define IDECtrl_CS1n          0x00000002
+#define IDECtrl_DA_MASK       0x0000001c
+#define IDECtrl_DA_SHIFT      2
+#define IDECtrl_DIORn         0x00000020
+#define IDECtrl_DIOWn         0x00000040
+#define IDECtrl_DASPn         0x00000080
+#define IDECtrl_DMARQ         0x00000100
+#define IDECtrl_INTRQ         0x00000200
+#define IDECtrl_IORDY         0x00000400
+
+#endif				/* _REGS_IDE_H_ */
diff --git a/include/asm-arm/arch-ep93xx/regs_irda.h b/include/asm-arm/arch-ep93xx/regs_irda.h
new file mode 100644
index 0000000..77edafa
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_irda.h
@@ -0,0 +1,24 @@
+/*=======================================================================
+ *
+ *  FILE:       regs_irda.h
+ *
+ *  DESCRIPTION:    IrDA Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ *=======================================================================
+ */
+#ifndef _REGS_IRDA_H_
+#define _REGS_IRDA_H_
+
+/* Bit definitions */
+
+#define IrEnable_EN_NONE	0x00
+#define IrEnable_EN_SIR		0x01
+#define IrEnable_EN_MIR		0x02
+#define IrEnable_EN_FIR		0x03
+#define IrEnable_LBM		0x04
+#define IrEnable_MD			0x08
+#define IrEnable_FD			0x10
+
+#endif				/* _REGS_IRDA_H_ */
diff --git a/include/asm-arm/arch-ep93xx/regs_pcmcia.h b/include/asm-arm/arch-ep93xx/regs_pcmcia.h
new file mode 100644
index 0000000..6f731e7
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_pcmcia.h
@@ -0,0 +1,72 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/regs-pcmcia.h
+ *
+ *  Derived from:
+ *  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.
+ */
+
+/*
+ * Personal Computer Memory Card International Association (PCMCIA) sockets
+ * (from pxa-regs.h for compatibility)
+ */
+#ifndef _REGS_PCMCIA_H_
+#define _REGS_PCMCIA_H_
+
+#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]                   */ \
+                	(0x40000000 + (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                 */
+
+#define PCATTRIB(sock) ((sock ==0) ? (PC1ATTRIB) : (PC2ATTRIB))
+#define PCCOMMON(sock) ((sock ==0) ? (PC1COMMON) : (PC2COMMON))
+#define PCIO(sock)     ((sock ==0) ? (PC1IO)     : (PC2IO))
+
+#define PC16BITSWIDE 0x80000000
+
+#define PCMCIA_WRPROT 0x01
+#define PCMCIA_DETECT 0x06
+#define PCMCIA_BVD1   0x08
+#define PCMCIA_BVD2   0x10
+#define PCMCIA_VS_3V  0x20
+#define PCMCIA_READY  0x40
+#define PCMCIA_VS_XV  0x80
+
+#endif /* _REGS_PCMCIA_H_ */
diff --git a/include/asm-arm/arch-ep93xx/regs_raster.h b/include/asm-arm/arch-ep93xx/regs_raster.h
new file mode 100644
index 0000000..bfab3ed
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_raster.h
@@ -0,0 +1,279 @@
+/*=============================================================================
+ *
+ *  FILE:       	regs_raster.h
+ *
+ *  DESCRIPTION:    ep93xx Raster Engine Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ * 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
+ *
+ *=============================================================================
+ */
+#ifndef _REGS_RASTER_H_
+#define _REGS_RASTER_H_
+
+/* VLINESTOTAL Register Definitions */
+#define VLINESTOTAL_MASK            0x000007ff
+
+/* VSYNCSTRTSTOP Register Definitions */
+#define VSYNCSTRTSTOP_STRT_MASK     0x07ff0000
+#define VSYNCSTRTSTOP_STRT_SHIFT    0
+#define VSYNCSTRTSTOP_STOP_MASK     0x000007ff
+#define VSYNCSTRTSTOP_STOP_SHIFT    16
+
+/* VACTIVESTRTSTOP Register Definitions */
+#define VACTIVESTRTSTOP_STRT_MASK   0x07ff0000
+#define VACTIVESTRTSTOP_STRT_SHIFT  0
+#define VACTIVESTRTSTOP_STOP_MASK   0x000007ff
+#define VACTIVESTRTSTOP_STOP_SHIFT  16
+
+/* VCLKSTRTSTOP Register Definitions */
+#define VCLKSTRTSTOP_STRT_MASK      0x07ff0000
+#define VCLKSTRTSTOP_STRT_SHIFT     0
+#define VCLKSTRTSTOP_STOP_MASK      0x000007ff
+#define VCLKSTRTSTOP_STOP_SHIFT     16
+
+/* VBLANKSTRTSTOP Register Definitions */
+#define VBLANKSTRTSTOP_STRT_MASK  0x07ff0000
+#define VBLANKSTRTSTOP_STRT_SHIFT 0
+#define VBLANKSTRTSTOP_STOP_MASK  0x000007ff
+#define VBLANKSTRTSTOP_STOP_SHIFT 16
+
+/* HSYNCSTRTSTOP Register Definitions */
+#define HSYNCSTRTSTOP_STRT_MASK      0x07ff0000
+#define HSYNCSTRTSTOP_STRT_SHIFT     0
+#define HSYNCSTRTSTOP_STOP_MASK      0x000007ff
+#define HSYNCSTRTSTOP_STOP_SHIFT     16
+
+/* HACTIVESTRTSTOP Register Definitions */
+#define HACTIVESTRTSTOP_STRT_MASK    0x07ff0000
+#define HACTIVESTRTSTOP_STRT_SHIFT   0
+#define HACTIVESTRTSTOP_STOP_MASK    0x000007ff
+#define HACTIVESTRTSTOP_STOP_SHIFT   16
+
+/* HCLKSTRTSTOP Register Definitions */
+#define HCLKSTRTSTOP_STRT_MASK      0x07ff0000
+#define HCLKSTRTSTOP_STRT_SHIFT     0
+#define HCLKSTRTSTOP_STOP_MASK      0x000007ff
+#define HCLKSTRTSTOP_STOP_SHIFT     16
+
+/* BRIGHTNESS Register Definitions */
+#define BRIGHTNESS_MASK             0x0000ffff
+#define BRIGHTNESS_CNT_MASK         0x000000ff
+#define BRIGHTNESS_CNT_SHIFT        0
+#define BRIGHTNESS_CMP_MASK         0x0000ff00
+#define BRIGHTNESS_CMP_SHIFT        8
+
+/* VIDEOATTRIBS Register Definitions */
+#define VIDEOATTRIBS_MASK           0x001fffff
+#define VIDEOATTRIBS_EN             0x00000001
+#define VIDEOATTRIBS_PCLKEN         0x00000002
+#define VIDEOATTRIBS_SYNCEN         0x00000004
+#define VIDEOATTRIBS_DATAEN         0x00000008
+#define VIDEOATTRIBS_CSYNC          0x00000010
+#define VIDEOATTRIBS_VCPOL          0x00000020
+#define VIDEOATTRIBS_HSPOL          0x00000040
+#define VIDEOATTRIBS_BLKPOL         0x00000080
+#define VIDEOATTRIBS_INVCLK         0x00000100
+#define VIDEOATTRIBS_ACEN           0x00000200
+#define VIDEOATTRIBS_LCDEN          0x00000400
+#define VIDEOATTRIBS_RGBEN          0x00000800
+#define VIDEOATTRIBS_CCIREN         0x00001000
+#define VIDEOATTRIBS_PIFEN          0x00002000
+#define VIDEOATTRIBS_INTEN          0x00004000
+#define VIDEOATTRIBS_INT            0x00008000
+#define VIDEOATTRIBS_INTRLC         0x00010000
+#define VIDEOATTRIBS_EQUSER         0x00020000
+#define VIDEOATTRIBS_DHORZ          0x00040000
+#define VIDEOATTRIBS_DVERT          0x00080000
+#define VIDEOATTRIBS_BKPXD          0x00100000
+
+#define VIDEOATTRIBS_SDSEL_MASK     0x00600000
+#define VIDEOATTRIBS_SDSEL_SHIFT    21
+
+/* HBLANKSTRTSTOP Register Definitions */
+#define HBLANKSTRTSTOP_STRT_MASK    0x07ff0000
+#define HBLANKSTRTSTOP_STRT_SHIFT   0
+#define HBLANKSTRTSTOP_STOP_MASK    0x000007ff
+#define HBLANKSTRTSTOP_STOP_SHIFT   16
+
+/* LINECARRY Register Definitions */
+#define LINECARRY_LCARY_MASK        0x000007ff
+#define LINECARRY_LCARY_SHIFT       0
+
+/* BLINKRATE Register Definitons */
+#define BLINKRATE_MASK              0x000000ff
+
+/* BLINKMASK Register Definitons */
+#define BLINKMASK_MASK              0x00ffffff
+
+/* VIDSCRNPAGE Register Definitons */
+#define VIDSCRNPAGE_PAGE_MASK       0x0ffffffc
+
+/* VIDSCRNHPG Register Definitons */
+#define VIDSCRNHPG_MASK             0x0ffffffc
+
+/* SCRNLINES Register Definitons */
+#define SCRNLINES_MASK              0x000007ff
+
+/* LINELENGTH Register Definitons */
+#define LINELENGTH_MASK             0x000007ff
+
+/* VLINESTEP Register Definitons */
+#define VLINESTEP_MASK              0x00000fff
+
+/* REALITI_SWLOCK Register Definitons */
+#define REALITI_SWLOCK_MASK_WR      0xff
+#define REALITI_SWLOCK_MASK_R       0x1
+#define REALITI_SWLOCK_VALUE        0xaa
+
+/* LUTCONT Register Definitions */
+#define LUTCONT_MASK                0x00000003
+#define LUTCONT_SWTCH               0x00000001
+#define LUTCONT_STAT                0x00000002
+#define LUTCONT_RAM0                0
+#define LUTCONT_RAM1                1
+
+/* CURSORBLINK1 Register Definitions */
+#define CURSORBLINK1_MASK           0x00ffffff
+/* CURSORBLINK2 Register Definitions */
+#define CURSORBLINK2_MASK           0x00ffffff
+
+/* CURSORBLINK Register Definitions */
+#define CURSORBLINK_MASK            0x000001ff
+#define CURSORBLINK_RATE_MASK       0x000000ff
+#define CURSORBLINK_RATE_SHIFT      0
+#define CURSORBLINK_EN              0x00000100
+
+/* BLINKPATRN Register Definitions */
+#define BLINKPATRN_MASK             0x00ffffff
+
+/* PATRNMASK Register Definitions */
+#define PATRNMASK_MASK              0x00ffffff
+
+/* BG_OFFSET Register Definitions */
+#define BG_OFFSET_MASK              0x00ffffff
+
+/* PIXELMODE Register Definitions */
+#define PIXELMODE_P_MASK            0x00000007
+#define PIXELMODE_P_MUX_DISABLE     0x00000000
+#define PIXELMODE_P_4BPP            0x00000001
+#define PIXELMODE_P_8BPP            0x00000002
+#define PIXELMODE_P_16BPP           0x00000004
+#define PIXELMODE_P_24BPP           0x00000006
+#define PIXELMODE_P_32BPP           0x00000007
+#define PIXELMODE_P_SHIFT           0
+
+#define PIXELMODE_S_MASK            0x00000038
+#define PIXELMODE_S_SHIFT           3
+#define PIXELMODE_S_1PPC            0x0
+#define PIXELMODE_S_1PPCMAPPED      0x1
+#define PIXELMODE_S_2PPC            0x2
+#define PIXELMODE_S_4PPC            0x3
+#define PIXELMODE_S_8PPC            0x4
+#define PIXELMODE_S_223PPC          0x5
+#define PIXELMODE_S_DS223PPC        0x6
+#define PIXELMODE_S_UNDEF           0x7
+
+#define PIXELMODE_M_MASK            0x000003c0
+#define PIXELMODE_M_SHIFT           6
+#define PIXELMODE_M_NOBLINK         0
+#define PIXELMODE_M_ANDBLINK        1
+#define PIXELMODE_M_ORBLINK         2
+#define PIXELMODE_M_XORBLINK        3
+#define PIXELMODE_M_BGBLINK         4
+#define PIXELMODE_M_OFFSINGBLINK    5
+#define PIXELMODE_M_OFF888BLINK     6
+#define PIXELMODE_M_DIMBLINK        0xc
+#define PIXELMODE_M_BRTBLINK        0xd
+#define PIXELMODE_M_DIM888BLINK     0xe
+#define PIXELMODE_M_BRT888BLINK     0xf
+
+#define PIXELMODE_C_MASK            0x00003c00
+#define PIXELMODE_C_SHIFT           10
+#define PIXELMODE_C_LUT             0
+#define PIXELMODE_C_888             4
+#define PIXELMODE_C_565             5
+#define PIXELMODE_C_555             6
+#define PIXELMODE_C_GSLUT           8
+
+#define PIXELMODE_DSCAN             0x00004000
+#define PIXELMODE_TRBSW             0x00008000
+#define PIXELMODE_P13951            0x00010000
+
+/*PARLLIFOUT Register Defintions */
+#define PARLLIFOUT_DAT_MASK         0x0000000f
+#define PARLLIFOUT_DAT_SHIFT        0
+#define PARLLIFOUT_RD               0x00000010
+
+/*PARLLIFIN Register Defintions */
+#define PARLLIFIN_DAT_MASK          0x0000000f
+#define PARLLIFIN_DAT_SHIFT         0
+#define PARLLIFIN_CNT_MASK          0x000f0000
+#define PARLLIFIN_CNT_SHIFT         16
+#define PARLLIFIN_ESTRT_MASK        0x00f00000
+#define PARLLIFIN_ESTRT_SHIFT       20
+
+/* CURSORADRSTART Register Defintions */
+#define CURSOR_ADR_START_MASK         0xfffffffc
+
+/* CURSORADRSTART Register Defintions */
+#define CURSOR_ADR_RESET_MASK         0xfffffffc
+
+/* CURSORCOLOR1 Register Definitions */
+#define CURSORCOLOR1_MASK               0x00ffffff
+/* CURSORCOLOR2 Register Definitions */
+#define CURSORCOLOR2_MASK               0x00ffffff
+
+/* CURSORXYLOC Register Definitions */
+#define CURSORXYLOC_MASK                0x07ff87ff
+#define CURSORXYLOC_XLOC_MASK           0x000007ff
+#define CURSORXYLOC_XLOC_SHIFT          0
+#define CURSORXYLOC_CEN                 0x00008000
+#define CURSORXYLOC_YLOC_MASK           0x07ff0000
+#define CURSORXYLOC_YLOC_SHIFT          16
+
+/* CURSOR_DSCAN_LH_YLOC Register Definitions */
+#define CURSOR_DSCAN_LH_YLOC_MASK       0x000087ff
+
+#define CURSOR_DSCAN_LH_YLOC_YLOC_MASK  0x000007ff
+#define CURSOR_DSCAN_LH_YLOC_YLOC_SHIFT 0
+#define CURSOR_DSCAN_LH_YLOC_CLHEN      0x00008000
+
+/* CURSORSIZE Register Definitions */
+#define CURSORSIZE_MASK                 0x0000ffff
+
+#define CURSORSIZE_CWID_MASK            0x00000003
+#define CURSORSIZE_CWID_SHIFT           0
+#define CURSORSIZE_CWID_1_WORD          0
+#define CURSORSIZE_CWID_2_WORD          1
+#define CURSORSIZE_CWID_3_WORD          2
+#define CURSORSIZE_CWID_4_WORD          3
+
+#define CURSORSIZE_CLINS_MASK           0x000000fc
+#define CURSORSIZE_CLINS_SHIFT          2
+
+#define CURSORSIZE_CSTEP_MASK           0x00000300
+#define CURSORSIZE_CSTEP_SHIFT          8
+#define CURSORSIZE_CSTEP_1_WORD         0
+#define CURSORSIZE_CSTEP_2_WORD         1
+#define CURSORSIZE_CSTEP_3_WORD         2
+#define CURSORSIZE_CSTEP_4_WORD         3
+
+#define CURSORSIZE_DLNS_MASK            0x0000fc00
+#define CURSORSIZE_DLNS_SHIFT           10
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/regs_spi.h b/include/asm-arm/arch-ep93xx/regs_spi.h
new file mode 100644
index 0000000..a51d3dc
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_spi.h
@@ -0,0 +1,76 @@
+/*=======================================================================
+ *
+ *  FILE:       regs_spi.h
+ *
+ *  DESCRIPTION:    SSP Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ * 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
+ *=======================================================================
+ */
+
+#ifndef _REGS_SSP_H_
+#define _REGS_SSP_H_
+
+/* Bits in SSPCR0 */
+#define SSPCR0_DSS_MASK             0x0000000f
+#define SSPCR0_DSS_4BIT             0x00000003
+#define SSPCR0_DSS_5BIT             0x00000004
+#define SSPCR0_DSS_6BIT             0x00000005
+#define SSPCR0_DSS_7BIT             0x00000006
+#define SSPCR0_DSS_8BIT             0x00000007
+#define SSPCR0_DSS_9BIT             0x00000008
+#define SSPCR0_DSS_10BIT            0x00000009
+#define SSPCR0_DSS_11BIT            0x0000000a
+#define SSPCR0_DSS_12BIT            0x0000000b
+#define SSPCR0_DSS_13BIT            0x0000000c
+#define SSPCR0_DSS_14BIT            0x0000000d
+#define SSPCR0_DSS_15BIT            0x0000000e
+#define SSPCR0_DSS_16BIT            0x0000000f
+
+/* Bits in SSPCR1 */
+#define SSPC1_RIE                   0x00000001
+#define SSPC1_TIE                   0x00000002
+#define SSPC1_RORIE		            0x00000004
+#define SSPC1_LBM                   0x00000008
+#define SSPC1_SSE                   0x00000010
+#define SSPC1_MS                    0x00000020
+#define SSPC1_SOD                   0x00000040
+
+#define SSPCR0_DSS_SHIFT            0
+#define SSPCR0_FRF_MASK             0x00000030
+#define SSPCR0_FRF_SHIFT            4
+#define SSPCR0_FRF_MOTOROLA         (0 << SSPCR0_FRF_SHIFT)
+#define SSPCR0_FRF_TI               (1 << SSPCR0_FRF_SHIFT)
+#define SSPCR0_FRF_NI               (2 << SSPCR0_FRF_SHIFT)
+#define SSPCR0_SPO                  0x00000040
+#define SSPCR0_SPH                  0x00000080
+#define SSPCR0_SCR_MASK             0x0000ff00
+#define SSPCR0_SCR_SHIFT            8
+
+/* Bits in SSPSR */
+#define SSPSR_TFE		    0x00000001	/* TX FIFO is empty */
+#define SSPSR_TNF    		0x00000002	/* TX FIFO is not full */
+#define SSPSR_RNE        	0x00000004	/* RX FIFO is not empty */
+#define SSPSR_RFF   		0x00000008	/* RX FIFO is full */
+#define SSPSR_BSY			0x00000010	/* SSP is busy */
+
+/* Bits in SSPIIR */
+#define SSPIIR_RIS			0x00000001	/* RX FIFO IRQ status */
+#define SSPIIR_TIS			0x00000002	/* TX FIFO is not full */
+#define SSPIIR_RORIS		0x00000004	/* RX FIFO is full */
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/regs_syscon.h b/include/asm-arm/arch-ep93xx/regs_syscon.h
new file mode 100644
index 0000000..271cfcd
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_syscon.h
@@ -0,0 +1,257 @@
+/*=============================================================================
+ *
+ *  FILE:       	reg_syscon.h
+ *
+ *  DESCRIPTION:    ep93xx Syscon Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ * 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
+ *
+ *=============================================================================
+ */
+#ifndef _REGS_SYSCON_H_
+#define _REGS_SYSCON_H_
+
+#ifndef __ASSEMBLY__
+
+#define SysconSetLocked(registername,value)     \
+    {                                           \
+        writel( 0xAA, SYSCON_SWLOCK);             \
+        writel( value, registername);             \
+    }
+
+#endif				/* Not __ASSEMBLY__ */
+
+/* SYSCON_CLKSET1 */
+#define SYSCON_CLKSET1_PLL1_X2IPD_SHIFT     0
+#define SYSCON_CLKSET1_PLL1_X2IPD_MASK      0x0000001f
+#define SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT    5
+#define SYSCON_CLKSET1_PLL1_X2FBD2_MASK     0x000007e0
+#define SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT    11
+#define SYSCON_CLKSET1_PLL1_X1FBD1_MASK     0x0000f800
+#define SYSCON_CLKSET1_PLL1_PS_SHIFT        16
+#define SYSCON_CLKSET1_PLL1_PS_MASK         0x00030000
+#define SYSCON_CLKSET1_PCLKDIV_SHIFT        18
+#define SYSCON_CLKSET1_PCLKDIV_MASK         0x000c0000
+#define SYSCON_CLKSET1_HCLKDIV_SHIFT        20
+#define SYSCON_CLKSET1_HCLKDIV_MASK         0x00700000
+#define SYSCON_CLKSET1_nBYP1                0x00800000
+#define SYSCON_CLKSET1_SMCROM               0x01000000
+#define SYSCON_CLKSET1_FCLKDIV_SHIFT        25
+#define SYSCON_CLKSET1_FCLKDIV_MASK         0x0e000000
+
+#define SYSCON_CLKSET1_HSEL                 0x00000001
+#define SYSCON_CLKSET1_PLL1_EXCLKSEL        0x00000002
+
+#define SYSCON_CLKSET1_PLL1_P_MASK          0x0000007C
+#define SYSCON_CLKSET1_PLL1_P_SHIFT         2
+
+#define SYSCON_CLKSET1_PLL1_M1_MASK         0x00000780
+#define SYSCON_CLKSET1_PLL1_M1_SHIFT        7
+#define SYSCON_CLKSET1_PLL1_M2_MASK         0x0000F800
+#define SYSCON_CLKSET1_PLL1_M2_SHIFT        11
+#define SYSCON_CLKSET1_PLL1_PS_MASK         0x00030000
+#define SYSCON_CLKSET1_PLL1_PS_SHIFT        16
+#define SYSCON_CLKSET1_PCLK_DIV_MASK        0x000C0000
+#define SYSCON_CLKSET1_PCLK_DIV_SHIFT       18
+#define SYSCON_CLKSET1_HCLK_DIV_MASK        0x00700000
+#define SYSCON_CLKSET1_HCLK_DIV_SHIFT       20
+#define SYSCON_CLKSET1_SMCROM               0x01000000
+#define SYSCON_CLKSET1_FCLK_DIV_MASK        0x0E000000
+#define SYSCON_CLKSET1_FCLK_DIV_SHIFT       25
+
+#define SYSCON_CLKSET2_PLL2_EN              0x00000001
+#define SYSCON_CLKSET2_PLL2EXCLKSEL         0x00000002
+#define SYSCON_CLKSET2_PLL2_P_MASK          0x0000007C
+#define SYSCON_CLKSET2_PLL2_P_SHIFT         2
+#define SYSCON_CLKSET2_PLL2_M2_MASK         0x00000F80
+#define SYSCON_CLKSET2_PLL2_M2_SHIFT        7
+#define SYSCON_CLKSET2_PLL2_M1_MASK         0x0001F000
+#define SYSCON_CLKSET2_PLL2_M1              12
+#define SYSCON_CLKSET2_PLL2_PS_MASK         0x000C0000
+#define SYSCON_CLKSET2_PLL2_PS_SHIFT        18
+#define SYSCON_CLKSET2_USBDIV_MASK          0xF0000000
+#define SYSCON_CLKSET2_USBDIV_SHIFT         28
+
+/* DEV_CFG Register Defines */
+#define SYSCON_DEVCFG_SHena            0x00000001
+#define SYSCON_DEVCFG_KEYS             0x00000002
+#define SYSCON_DEVCFG_ADCPD            0x00000004
+#define SYSCON_DEVCFG_RAS              0x00000008
+#define SYSCON_DEVCFG_RASonP3          0x00000010
+#define SYSCON_DEVCFG_TTIC             0x00000020
+#define SYSCON_DEVCFG_I2SonAC97        0x00000040
+#define SYSCON_DEVCFG_I2SonSSP         0x00000080
+#define SYSCON_DEVCFG_EonIDE           0x00000100
+#define SYSCON_DEVCFG_PonG             0x00000200
+#define SYSCON_DEVCFG_GonIDE           0x00000400
+#define SYSCON_DEVCFG_HonIDE           0x00000800
+#define SYSCON_DEVCFG_HC1CEN           0x00001000
+#define SYSCON_DEVCFG_HC1IN            0x00002000
+#define SYSCON_DEVCFG_HC3CEN           0x00004000
+#define SYSCON_DEVCFG_HC3IN            0x00008000
+#define SYSCON_DEVCFG_ADCEN            0x00010000
+#define SYSCON_DEVCFG_TIN              0x00020000
+#define SYSCON_DEVCFG_U1EN             0x00040000
+#define SYSCON_DEVCFG_EXVC             0x00080000
+#define SYSCON_DEVCFG_U2EN             0x00100000
+#define SYSCON_DEVCFG_A1onG            0x00200000
+#define SYSCON_DEVCFG_A2onG            0x00400000
+#define SYSCON_DEVCFG_CPENA            0x00800000
+#define SYSCON_DEVCFG_U3EN             0x01000000
+#define SYSCON_DEVCFG_MonG             0x02000000
+#define SYSCON_DEVCFG_TonG             0x04000000
+#define SYSCON_DEVCFG_GonK             0x08000000
+#define SYSCON_DEVCFG_IonU2            0x10000000
+#define SYSCON_DEVCFG_D0onG            0x20000000
+#define SYSCON_DEVCFG_D1onG            0x40000000
+#define SYSCON_DEVCFG_SWRST            0x80000000
+
+/* VIDDIV Register Defines */
+#define SYSCON_VIDDIV_VDIV_MASK         0x0000007f
+#define SYSCON_VIDDIV_VDIV_SHIFT        0
+#define SYSCON_VIDDIV_PDIV_MASK         0x00000300
+#define SYSCON_VIDDIV_PDIV_SHIFT        8
+#define SYSCON_VIDDIV_PSEL              0x00002000
+#define SYSCON_VIDDIV_ESEL              0x00004000
+#define SYSCON_VIDDIV_VENA              0x00008000
+
+/* MIRDIV Register Defines */
+#define SYSCON_MIRDIV_MDIV_MASK         0x0000003f
+#define SYSCON_MIRDIV_MDIV_SHIFT        0
+#define SYSCON_MIRDIV_PDIV_MASK         0x00000300
+#define SYSCON_MIRDIV_PDIV_SHIFT        8
+#define SYSCON_MIRDIV_PSEL              0x00002000
+#define SYSCON_MIRDIV_ESEL              0x00004000
+#define SYSCON_MIRDIV_MENA              0x00008000
+
+/* I2SDIV Register Defines */
+#define SYSCON_I2SDIV_MDIV_MASK         0x0000007f
+#define SYSCON_I2SDIV_MDIV_SHIFT        0
+#define SYSCON_I2SDIV_PDIV_MASK         0x00000300
+#define SYSCON_I2SDIV_PDIV_SHIFT        8
+#define SYSCON_I2SDIV_PSEL              0x00002000
+#define SYSCON_I2SDIV_ESEL              0x00004000
+#define SYSCON_I2SDIV_MENA              0x00008000
+#define SYSCON_I2SDIV_SDIV              0x00010000
+#define SYSCON_I2SDIV_LRDIV_MASK        0x00060000
+#define SYSCON_I2SDIV_LRDIV_SHIFT       17
+#define SYSCON_I2SDIV_SPOL              0x00080000
+#define SYSCON_I2SDIV_DROP              0x00100000
+#define SYSCON_I2SDIV_ORIDE             0x20000000
+#define SYSCON_I2SDIV_SLAVE             0x40000000
+#define SYSCON_I2SDIV_SENA              0x80000000
+
+#define SYSCON_I2SDIV_PDIV_OFF          0x00000000
+#define SYSCON_I2SDIV_PDIV_2            0x00000100
+#define SYSCON_I2SDIV_PDIV_25           0x00000200
+#define SYSCON_I2SDIV_PDIV_3            0x00000300
+
+#define SYSCON_I2SDIV_LRDIV_32          0x00000000
+#define SYSCON_I2SDIV_LRDIV_64          0x00020000
+#define SYSCON_I2SDIV_LRDIV_128         0x00040000
+
+/* KTDIV Register Defines */
+#define SYSCON_KTDIV_KDIV               0x00000001
+#define SYSCON_KTDIV_KEN                0x00008000
+#define SYSCON_KTDIV_ADIV               0x00010000
+#define SYSCON_KTDIV_TSEN               0x80000000
+
+/* CHIPID Register Defines */
+#define SYSCON_CHIPID_ID_MASK           0x0000ffff
+#define SYSCON_CHIPID_ID_SHIFT          0
+#define SYSCON_CHIPID_PKID              0x00010000
+#define SYSCON_CHIPID_BND               0x00040000
+#define SYSCON_CHIPID_FAB_MASK          0x0e000000
+#define SYSCON_CHIPID_FAB_SHIFT         25
+#define SYSCON_CHIPID_REV_MASK          0xf0000000
+#define SYSCON_CHIPID_REV_SHIFT         28
+
+/* TESTCR Register Defines */
+#define SYSCON_TESTCR_TMODE_MASK        0x000000ff
+#define SYSCON_TESTCR_TMODE_SHIFT       0
+#define SYSCON_TESTCR_BONDO             0x00000100
+#define SYSCON_TESTCR_PACKO             0x00000800
+#define SYSCON_TESTCR_ETOM              0x00002000
+#define SYSCON_TESTCR_TOM               0x00004000
+#define SYSCON_TESTCR_OVR               0x00008000
+#define SYSCON_TESTCR_TonIDE            0x00010000
+#define SYSCON_TESTCR_RonG              0x00020000
+
+/* SYSCFG Register Defines */
+#define SYSCON_SYSCFG_LCSn1             0x00000001
+#define SYSCON_SYSCFG_LCSn2             0x00000002
+#define SYSCON_SYSCFG_LCSn3             0x00000004
+#define SYSCON_SYSCFG_LEECK             0x00000008
+#define SYSCON_SYSCFG_LEEDA             0x00000010
+#define SYSCON_SYSCFG_LASDO             0x00000020
+#define SYSCON_SYSCFG_LCSn6             0x00000040
+#define SYSCON_SYSCFG_LCSn7             0x00000080
+#define SYSCON_SYSCFG_SBOOT             0x00000100
+#define SYSCON_SYSCFG_FAB_MASK          0x0e000000
+#define SYSCON_SYSCFG_FAB_SHIFT         25
+#define SYSCON_SYSCFG_REV_MASK          0xf0000000
+#define SYSCON_SYSCFG_REV_SHIFT         28
+
+/* PWRSR Register Defines */
+#define SYSCON_PWRSR_CHIPMAN_MASK       0xFF000000
+#define SYSCON_PWRSR_CHIPMAN_SHIFT      24
+#define SYSCON_PWRSR_CHIPID_MASK        0x00FF0000
+#define SYSCON_PWRSR_CHIPID_SHIFT       16
+#define SYSCON_PWRSR_WDTFLG             0x00008000
+#define SYSCON_PWRSR_CLDFLG             0x00002000
+#define SYSCON_PWRSR_TEST_RESET         0x00001000
+#define SYSCON_PWRSR_RSTFLG             0x00000800
+#define SYSCON_PWRSR_SWRESET            0x00000400
+#define SYSCON_PWRSR_PLL2_LOCKREG       0x00000200
+#define SYSCON_PWRSR_PLL2_LOCK          0x00000100
+#define SYSCON_PWRSR_PLL1_LOCKREG       0x00000080
+#define SYSCON_PWRSR_PLL1_LOCK          0x00000040
+#define SYSCON_PWRSR_RTCDIV             0x0000003F
+
+/* PWRCNT Register Defines */
+#define SYSCON_PWRCNT_FIREN             0x80000000
+#define SYSCON_PWRCNT_UARTBAUD          0x20000000
+#define SYSCON_PWRCNT_USHEN             0x10000000
+#define SYSCON_PWRCNT_DMA_M2MCH1        0x08000000
+#define SYSCON_PWRCNT_DMA_M2MCH0        0x04000000
+#define SYSCON_PWRCNT_DMA_M2PCH8        0x02000000
+#define SYSCON_PWRCNT_DMA_M2PCH9        0x01000000
+#define SYSCON_PWRCNT_DMA_M2PCH6        0x00800000
+#define SYSCON_PWRCNT_DMA_M2PCH7        0x00400000
+#define SYSCON_PWRCNT_DMA_M2PCH4        0x00200000
+#define SYSCON_PWRCNT_DMA_M2PCH5        0x00100000
+#define SYSCON_PWRCNT_DMA_M2PCH2        0x00080000
+#define SYSCON_PWRCNT_DMA_M2PCH3        0x00040000
+#define SYSCON_PWRCNT_DMA_M2PCH0        0x00020000
+#define SYSCON_PWRCNT_DMA_M2PCH1        0x00010000
+
+/* BMAR Register Defines */
+#define BMAR_PRIORD_00              0x00000000
+#define BMAR_PRIORD_01              0x00000001
+#define BMAR_PRIORD_02              0x00000002
+#define BMAR_PRIORD_03              0x00000003
+#define BMAR_PRI_CORE               0x00000008
+#define BMAR_DMA_ENIRQ              0x00000010
+#define BMAR_DMA_ENFIQ              0x00000020
+#define BMAR_USB_ENIRQ              0x00000040
+#define BMAR_USB_ENFIQ              0x00000080
+#define BMAR_MAC_ENIRQ              0x00000100
+#define BMAR_MAC_ENFIQ              0x00000200
+#define BMAR_GRAPHICS_ENIRQ         0x00000400
+#define BMAR_GRAPHICS_ENFIQ         0x00000800
+
+#endif				/* _REGS_SYSCON_H_ */
diff --git a/include/asm-arm/arch-ep93xx/regs_touch.h b/include/asm-arm/arch-ep93xx/regs_touch.h
new file mode 100644
index 0000000..aad8a99
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_touch.h
@@ -0,0 +1,94 @@
+/*=============================================================================
+ *
+ *  FILE:       regs_touch.h
+ *
+ *  DESCRIPTION:    Analog Touchscreen Register Definition
+ *
+ *  Copyright Cirrus Logic, 2001-2003
+ *
+ * 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
+ *=============================================================================
+ */
+#ifndef _REGS_TOUCH_H_
+#define _REGS_TOUCH_H_
+
+/*
+ *-----------------------------------------------------------------------------
+ * Individual bit #defines
+ *-----------------------------------------------------------------------------
+ */
+#define TSSETUP_SDLY_MASK           0x000003FF
+#define TSSETUP_SDLY_SHIFT          0
+#define TSSETUP_NSMP_4              0x00000000
+#define TSSETUP_NSMP_8              0x00000400
+#define TSSETUP_NSMP_16             0x00000800
+#define TSSETUP_NSMP_32             0x00000C00
+#define TSSETUP_NSMP_MASK           0x00000C00
+#define TSSETUP_DEV_4               0x00000000
+#define TSSETUP_DEV_8               0x00001000
+#define TSSETUP_DEV_12              0x00002000
+#define TSSETUP_DEV_16              0x00003000
+#define TSSETUP_DEV_24              0x00004000
+#define TSSETUP_DEV_32              0x00005000
+#define TSSETUP_DEV_64              0x00006000
+#define TSSETUP_DEV_128             0x00007000
+#define TSSETUP_ENABLE              0x00008000
+#define TSSETUP_DLY_MASK            0x03FF0000
+#define TSSETUP_DLY_SHIFT           16
+#define TSSETUP_TDTCT               0x80000000
+
+#define TSMAXMIN_XMIN_MASK          0x000000FF
+#define TSMAXMIN_XMIN_SHIFT         0
+#define TSMAXMIN_YMIN_MASK          0x0000FF00
+#define TSMAXMIN_YMIN_SHIFT         8
+#define TSMAXMIN_XMAX_MASK          0x00FF0000
+#define TSMAXMIN_XMAX_SHIFT         16
+#define TSMAXMIN_YMAX_MASK          0xFF000000
+#define TSMAXMIN_YMAX_SHIFT         24
+
+#define TSXYRESULT_X_MASK           0x00000FFF
+#define TSXYRESULT_X_SHIFT          0
+#define TSXYRESULT_AD_MASK          0x0000FFFF
+#define TSXYRESULT_AD_SHIFT         0
+#define TSXYRESULT_Y_MASK           0x0FFF0000
+#define TSXYRESULT_Y_SHIFT          16
+#define TSXYRESULT_SDR              0x80000000
+
+#define TSX_SAMPLE_MASK             0x00003FFF
+#define TSX_SAMPLE_SHIFT            0x00
+#define TSY_SAMPLE_MASK             0x3FFF0000
+#define TSY_SAMPLE_SHIFT            0x10
+
+#define TSSETUP2_TINT               0x00000001
+#define TSSETUP2_NICOR              0x00000002
+#define TSSETUP2_PINT               0x00000004
+#define TSSETUP2_PENSTS             0x00000008
+#define TSSETUP2_PINTEN             0x00000010
+#define TSSETUP2_DEVINT             0x00000020
+#define TSSETUP2_DINTEN             0x00000040
+#define TSSETUP2_DTMEN              0x00000080
+#define TSSETUP2_DISDEV             0x00000100
+#define TSSETUP2_NSIGND             0x00000200
+#define TSSETUP2_S28EN              0x00000400
+#define TSSETUP2_RINTEN             0x00000800
+
+#define TSXYRESULT_SDR     			0x80000000
+
+/*
+ *-----------------------------------------------------------------------------
+ *-----------------------------------------------------------------------------
+ */
+
+#endif				/* _REGS_TOUCH_H_ */
diff --git a/include/asm-arm/arch-ep93xx/regs_uart.h b/include/asm-arm/arch-ep93xx/regs_uart.h
new file mode 100644
index 0000000..cfadf4a
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/regs_uart.h
@@ -0,0 +1,84 @@
+/*
+ *  File:   linux/include/asm-arm/arch-ep93xx/regs_uart.h
+ *
+ *  Copyright (C) 2003 Cirrus Logic, Inc
+ *
+ * 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
+ */
+
+#ifndef _REGS_UART_H_
+#define _REGS_UART_H_
+
+/* Bits in UARTRSR */
+#define UARTRSR_FE              0x00000001	/* Framing error */
+#define UARTRSR_PE              0x00000002	/* Parity error */
+#define UARTRSR_BE              0x00000004	/* Break error */
+#define UARTRSR_OE              0x00000008	/* Overrun error */
+
+/* Bits in UARTCR - UART1CR, UART2CR, or UART3CR */
+#define UARTLCR_H_BRK           0x00000001
+#define UARTLCR_H_PEN           0x00000002
+#define UARTLCR_H_EPS           0x00000004
+#define UARTLCR_H_STP2          0x00000008
+#define UARTLCR_H_FEN           0x00000010
+#define UARTLCR_H_WLEN          0x00000060
+#define UARTLCR_H_WLEN_8_DATA   0x00000060
+#define UARTLCR_H_WLEN_7_DATA   0x00000040
+#define UARTLCR_H_WLEN_6_DATA   0x00000020
+#define UARTLCR_H_WLEN_5_DATA   0x00000000
+
+/* Bits in UARTFR - UART1FR, UART2FR, or UART3FR */
+#define UARTFR_RSR_ERRORS       0x0000000F
+#define UARTFR_CTS              0x00000001
+#define UARTFR_DSR              0x00000002
+#define UARTFR_DCD              0x00000004
+#define UARTFR_BUSY             0x00000008
+#define UARTFR_RXFE             0x00000010
+#define UARTFR_TXFF             0x00000020
+#define UARTFR_RXFF             0x00000040
+#define UARTFR_TXFE             0x00000080
+
+/* Bits in UARTIIR */
+#define UARTIIR_MIS             0x00000001
+#define UARTIIR_RIS             0x00000002
+#define UARTIIR_TIS             0x00000004
+#define UARTIIR_RTIS            0x00000008
+
+/* Bits in UARTCR */
+#define UARTCR_UARTE            0x00000001
+#define UARTCR_MSIE             0x00000008
+#define UARTCR_RIE              0x00000010
+#define UARTCR_TIE              0x00000020
+#define UARTCR_RTIE             0x00000040
+#define UARTCR_LBE              0x00000080
+
+/* Bits in UARTMCR */
+#define UARTMCR_DTR             0x00000001
+#define UARTMCR_RTS             0x00000002
+#define UARTMCR_OUT1            0x00000004
+#define UARTMCR_OUT2            0x00000008
+#define UARTMCR_LOOP            0x00000010
+
+/* Bits in UARTMSR */
+#define UARTMSR_DCTS            0x00000001
+#define UARTMSR_DDSR            0x00000002
+#define UARTMSR_TERI            0x00000004
+#define UARTMSR_DDCD            0x00000008
+#define UARTMSR_CTS             0x00000010
+#define UARTMSR_DSR             0x00000020
+#define UARTMSR_RI              0x00000040
+#define UARTMSR_DCD             0x00000080
+
+#endif				/* _REGS_UART_H_ */
diff --git a/include/asm-arm/arch-ep93xx/serial.h b/include/asm-arm/arch-ep93xx/serial.h
new file mode 100644
index 0000000..06ab737
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/serial.h
@@ -0,0 +1,49 @@
+/*
+ *  linux/include/asm-arm/arch-integrator/serial.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#include <asm/arch/platform.h>
+#include <asm/irq.h>
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD (1843200 / 16)
+
+#define _SER_IRQ0	IRQ_UARTINT0
+#define _SER_IRQ1	IRQ_UARTINT1
+
+#define RS_TABLE_SIZE	2
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+     /* UART CLK        PORT  IRQ     FLAGS        */
+#define STD_SERIAL_PORT_DEFNS \
+	{ 0, BASE_BAUD, 0x3F8, _SER_IRQ0, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8, _SER_IRQ1, STD_COM_FLAGS },	/* ttyS1 */
+
+#define EXTRA_SERIAL_PORT_DEFNS
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/ssp-cirrus.h b/include/asm-arm/arch-ep93xx/ssp-cirrus.h
new file mode 100644
index 0000000..e29dc9d
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/ssp-cirrus.h
@@ -0,0 +1,30 @@
+/*
+ *
+ *  FILE:           ssp.h
+ *
+ *  DESCRIPTION:    SSP Interface Driver Module implementation
+ *
+ *  Copyright Cirrus Logic Corporation, 2001-2003.  All rights reserved
+ *
+ */
+#ifndef _SSP_DRV_H_
+#define _SSP_DRV_H_
+
+enum SSPDeviceType {
+	PS2_KEYBOARD = 0,
+	I2S_CODEC = 1,
+	SERIAL_FLASH = 2
+};
+
+typedef void (*SSPDataCallback) (unsigned int Data);
+
+typedef struct _SSP_DRIVER_API {
+	int (*Open) (enum SSPDeviceType Device, SSPDataCallback Callback);
+	int (*Read) (int Handle, unsigned int Addr, unsigned int *pValue);
+	int (*Write) (int Handle, unsigned int Addr, unsigned int Value);
+	int (*Close) (int Handle);
+} SSP_DRIVER_API;
+
+extern SSP_DRIVER_API *SSPDriver;
+
+#endif				/* _SSP_DRV_H_ */
diff --git a/include/asm-arm/arch-ep93xx/ssp.h b/include/asm-arm/arch-ep93xx/ssp.h
new file mode 100644
index 0000000..9102233
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/ssp.h
@@ -0,0 +1,121 @@
+/*
+ *  ssp.h
+ *
+ *  Copyright (C) 2004 Ray Lehtiniemi, All Rights Reserved.
+ *  Copyright (C) 2004 Siconix, Inc., All Rights Reserved.
+ *
+ * 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 SSP_H
+#define SSP_H
+
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <asm/semaphore.h>
+
+struct ssp_master_ops;
+struct ssp_slave;
+
+struct ssp_transfer {
+
+	/* how many _bytes_ per unit of data */
+	int size;
+
+	/* how many units of data left to be clocked out */
+	int len;
+
+	/* how many units of data left to be clocked in */
+	int rlen;
+
+	/* buffer of units to shift out to slave */
+	void *tx;
+
+	/* buffer to hold units shifted in from slave */
+	void *rx;
+
+	/* signaled when complete */
+	struct completion *c;
+};
+
+struct ssp_master {
+
+	/* serialize access to the frontend */
+	struct semaphore sem;
+
+	/* synchronize the frontend and the backend */
+	struct completion completion;
+
+	/* the slave devices on this master */
+	struct list_head slave;
+
+	/* the active transfer on the bus  */
+	struct ssp_transfer transfer;
+
+	/* methods for different master controllers */
+	struct ssp_master_ops *ops;
+};
+
+struct ssp_master_ops {
+
+	/* configure the master for accessing a particular slave */
+	int (*configure) (struct ssp_slave *);
+
+	/* enable the backend to start the transfer */
+	int (*enable) (struct ssp_transfer *);
+
+	/* disable the backend to stop the transfer */
+	int (*disable) (void);
+};
+
+struct ssp_slave {
+
+	/* our link in the masters list of slaves */
+	struct list_head list;
+
+	/* our master */
+	struct ssp_master *master;
+#if 0
+	/* the upper level protocol spoken by the device */
+	struct ssp_protocol *protocol;
+#endif
+	/* the phase and polarity modes we support */
+	unsigned long supported_modes;
+
+	/* our maximum clock rate, in Hz */
+	unsigned long max_clock_rate;
+
+	/* our data unit size, in bits */
+	int word_size;
+
+	/* our data unit size, in bytes */
+	int nbytes;
+
+	/* assert or negate the chip select line for this device */
+	void (*chip_select) (struct ssp_slave *, int);
+};
+
+/* manage the master-slave list */
+extern int ssp_add_slave(struct ssp_master *, struct ssp_slave *);
+extern void ssp_remove_slave(struct ssp_master *, struct ssp_slave *);
+
+/* perform a single transaction */
+extern int ssp_do(struct ssp_slave *s, int len, void *tx, void *rx);
+
+/* perform each step of a transaction */
+extern int ssp_start(struct ssp_slave *s);	/* grab master, blocking */
+extern int ssp_trystart(struct ssp_slave *s);	/* grab master, non-blocking */
+extern void ssp_select(struct ssp_slave *s);	/* assert CS */
+extern int ssp_post(struct ssp_slave *s, int len, void *tx, void *rx);	/* start a transfer */
+extern int ssp_wait(struct ssp_slave *s);	/* wait for completion */
+						       /*extern int  ssp_disable (struct ssp_slave *s);    *//* stop a transfer */
+extern void ssp_deselect(struct ssp_slave *s);	/* negate CS */
+extern void ssp_finish(struct ssp_slave *s);	/* release master */
+
+/* module stuff */
+extern int ssp_init(void);
+extern void ssp_exit(void);
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/ssp2.h b/include/asm-arm/arch-ep93xx/ssp2.h
new file mode 100644
index 0000000..93823a0
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/ssp2.h
@@ -0,0 +1,29 @@
+/*
+ *  ssp.h
+ *
+ *  Copyright (C) 2004 Ray Lehtiniemi, All Rights Reserved.
+ *  Copyright (C) 2004 Siconix, Inc., All Rights Reserved.
+ *
+ * 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 SSP2_H
+#define SSP2_H
+
+#include <asm/arch/ssp.h>
+
+struct ep93xx_ssp_slave {
+	struct ssp_slave slave;
+	unsigned long cr0;
+	unsigned long cr1;
+	unsigned long cpsr;
+};
+
+extern struct ssp_master ep93xx_ssp_master;
+
+extern int ep93xx_ssp_init(void);
+extern void ep93xx_ssp_exit(void);
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/system.h b/include/asm-arm/arch-ep93xx/system.h
new file mode 100644
index 0000000..1030210
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/system.h
@@ -0,0 +1,68 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/system.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/arch/platform.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+static void arch_idle(void)
+{
+	unsigned long val = readl(SYSCON_DEVCFG);
+	val = ep93xx_SYSCON_DEVCFG(val | SYSCON_DEVCFG_SHena);
+	SysconSetLocked(SYSCON_DEVCFG, val);
+	readl(SYSCON_HALT);
+}
+
+#if defined(CONFIG_MACH_TTML)
+
+#include <asm/arch/mach-ttml.h>
+extern __inline__ void arch_reset(char mode)
+{
+	/* reboot using micro */
+	unsigned char msg[4] = { 0xaa, 0x90, 0xa0, 0x65 };
+	unsigned char reply[10];
+	(void)ssp_do_ttml(&ep93xx_ssp_micro, msg, 4, reply, 10);
+	while (1) ;
+}
+
+#else
+
+extern __inline__ void arch_reset(char mode)
+{
+#if 1
+	/* reboot using SW_RESET bit in devcfg register */
+	unsigned long val = readl(SYSCON_DEVCFG);
+	SysconSetLocked(SYSCON_DEVCFG,
+			ep93xx_SYSCON_DEVCFG(val | SYSCON_DEVCFG_SWRST));
+	SysconSetLocked(SYSCON_DEVCFG,
+			ep93xx_SYSCON_DEVCFG(val & ~SYSCON_DEVCFG_SWRST));
+
+#else
+	/* reboot using 0.250 second onboard watchdog timeout */
+	writel(0xaaaa, WATCHDOG);
+	while (1) ;
+#endif
+}
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/timex.h b/include/asm-arm/arch-ep93xx/timex.h
new file mode 100644
index 0000000..87a7628
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/timex.h
@@ -0,0 +1,26 @@
+/*
+ *  linux/include/asm-arm/arch-integrator/timex.h
+ *
+ *  Integrator architecture timex specifications
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+
+/*
+ * ??
+ */
+#define CLOCK_TICK_RATE		(50000000 / 16)
diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h
new file mode 100644
index 0000000..f76de3c
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/uncompress.h
@@ -0,0 +1,91 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/uncompress.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#if defined(CONFIG_MACH_ZEFEERDZA) || defined(CONFIG_MACH_ZEFEERDZB) || \
+    defined(CONFIG_MACH_ZEFEERDZG) || defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ)
+#	define BAUDRATE ((EP93XX_UART_CLK/(16 * 115200)) - 1)
+#else
+#	define BAUDRATE ((EP93XX_UART_CLK/(16 * 57600)) - 1)
+#endif
+
+#define HW_PREG(reg) ((unsigned int volatile *)(io_v2p(reg)))
+
+static void putstr(const char *s)
+{
+	while (*s) {
+		while (*HW_PREG(UART1FR) & UARTFR_TXFF) ;
+
+		*HW_PREG(UART1DR) = *s;
+
+		if (*s == '\n') {
+			while (*HW_PREG(UART1FR) & UARTFR_TXFF) ;
+
+			*HW_PREG(UART1DR) = '\r';
+		}
+		s++;
+	}
+	while (*HW_PREG(UART1FR) & UARTFR_BUSY) ;
+}
+
+static void EnableUart(void)
+{
+	/*
+	 * Ensure that the base clock to the UARTS is 14.7456Mhz
+	 * and that UART1 is enabled.
+	 */
+	*HW_PREG(SYSCON_PWRCNT) = SYSCON_PWRCNT_UARTBAUD;
+
+	*HW_PREG(SYSCON_SWLOCK) = 0xaa;
+	*HW_PREG(SYSCON_DEVCFG) = (*HW_PREG(SYSCON_DEVCFG)) | SYSCON_DEVCFG_U1EN;
+
+	/* Disable the UARTS and clear out the old settings. */
+	*HW_PREG(UART1MCR) = 0;
+	*HW_PREG(UART1CR) = 0;
+	*HW_PREG(UART1RSR) = 0;
+	*HW_PREG(UART1CR_L) = 0;
+	*HW_PREG(UART1CR_M) = 0;
+	*HW_PREG(UART1CR_H) = 0;
+
+	/* Set the baud rate and framing */
+	*HW_PREG(UART1CR_L) = (BAUDRATE & 0x0FF);
+	*HW_PREG(UART1CR_M) = ((BAUDRATE >> 8) & 0x0FF);
+
+	/* 8 Data bits, No Parity, 1 Stop bit. */
+	*HW_PREG(UART1CR_H) = (UARTLCR_H_WLEN_8_DATA | UARTLCR_H_FEN);
+
+	/* Enable Uart */
+	*HW_PREG(UART1CR) = UARTCR_UARTE;
+}
+
+#if defined(CONFIG_MACH_ADSSPHERE)
+#define arch_decomp_setup()
+#else
+
+/* Called early before the UART is used for output by the compressed loader. */
+static void arch_decomp_setup(void)
+{
+	EnableUart();
+}
+#endif
+
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-ep93xx/vmalloc.h b/include/asm-arm/arch-ep93xx/vmalloc.h
new file mode 100644
index 0000000..ec8f98d
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/vmalloc.h
@@ -0,0 +1,32 @@
+/*
+ *  linux/include/asm-arm/arch-integrator/vmalloc.h
+ *
+ *  Copyright (C) 2000 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * 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       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-ep93xx/zefeerevb.h b/include/asm-arm/arch-ep93xx/zefeerevb.h
new file mode 100644
index 0000000..2cb3f84
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/zefeerevb.h
@@ -0,0 +1,51 @@
+/*
+ *  linux/include/asm-arm/arch-ep93xx/platform.h
+ *
+ *  Copyright (C) 2004 DAVE Srl <www.dave-tech.it>
+ *
+ * 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
+ */
+#ifndef ASM_ARCH_ZEFEEREVB_H
+#define ASM_ARCH_ZEFEEREVB_H
+
+#ifdef CONFIG_MACH_ZEFEER_EVBL_107
+/* GPIO pins used to drive NAND chip mounted on old EVB */
+/*
+	nCE = EGPIO2
+	CLE = EGPIO0
+	ALE = EGPIO1
+	R/B = EGPIO3
+*/
+#	define NAND_EVB_nCE_GPIO_PIN 	(1 << 2)
+#	define NAND_EVB_CLE_GPIO_PIN 	(1 << 0)
+#	define NAND_EVB_ALE_GPIO_PIN 	(1 << 1)
+#	define NAND_EVB_RB_GPIO_PIN 	(1 << 3)
+#else
+/* GPIO pins used to drive NAND chip mounted on EVB */
+/*
+	nCE = EGPIO6
+	CLE = EGPIO4
+	ALE = EGPIO5
+	R/B = EGPIO7
+*/
+#	define NAND_EVB_nCE_GPIO_PIN 	(1 << 6)
+#	define NAND_EVB_CLE_GPIO_PIN 	(1 << 4)
+#	define NAND_EVB_ALE_GPIO_PIN 	(1 << 5)
+#	define NAND_EVB_RB_GPIO_PIN 	(1 << 7)
+#endif
+
+#define ZEFEEREVB_NAND_PADDR	0x20000000
+
+#endif /* ASM_ARCH_ZEFEEREVB_H */
diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h
index 59975ee..755d9de 100644
--- a/include/asm-arm/irq.h
+++ b/include/asm-arm/irq.h
@@ -38,6 +38,12 @@ extern void enable_irq(unsigned int);
 #define IRQT_HIGH	(__IRQT_HIGHLVL)
 #define IRQT_PROBE	(1 << 4)
 
+/*
+ * Flags for enable and disable debounce
+ */
+#define IRQT_DB 	( 1 << 5 )
+#define IRQT_NOTDB 	( 1 << 6 )
+
 int set_irq_type(unsigned int irq, unsigned int type);
 void disable_irq_wake(unsigned int irq);
 void enable_irq_wake(unsigned int irq);
diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h
index a9c75b2..556e5d8 100644
--- a/include/asm-arm/procinfo.h
+++ b/include/asm-arm/procinfo.h
@@ -56,5 +56,6 @@ extern unsigned int elf_hwcap;
 #define HWCAP_VFP	64
 #define HWCAP_EDSP	128
 #define HWCAP_JAVA	256
+#define	HWCAP_CRUNCH	512
 
 #endif
diff --git a/include/linux/can/oki_ml9620_ctrl.h b/include/linux/can/oki_ml9620_ctrl.h
new file mode 100644
index 0000000..d2cfbea
--- /dev/null
+++ b/include/linux/can/oki_ml9620_ctrl.h
@@ -0,0 +1,54 @@
+/*
+ * include/linux/can/oki_ml9620_ctrl.h
+ *
+ * OKI ML9620 CAN Controler driver
+ *
+ * Author: Manfred Gruber <manfred.gruber@contec.at>
+ *
+ * Copyright 2004 (c) Manfred Gruber
+ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
+ * Kufstein/Austria   www.contec.at
+ *
+ * This driver was written for Contec hypercontrol Micro9 Board
+ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
+ * 2. CAN Controller is on Hypercontrol Micro9 eval board
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _OKI_ML9620_CTRL_H_
+#define _OKI_ML9620_CTRL_H_
+
+#ifdef __KERNEL__
+struct can_msg {
+	unsigned short id;     	/* identifier                          */
+	unsigned short dlc : 4;	/* bitfield 4: data length code [0..8] */
+	unsigned short rtr : 1;	/* bitfield 1: rtr bit                 */
+	unsigned short ext : 1;	/* bitfield 1: extended ID             */
+	unsigned short pad : 10; /* workaround alignment issues: 
+				FIXME: completely remove that bitfield junk */
+	unsigned char  data[8];	/* data bytes                          */
+};
+#endif
+
+#define CAN_STS_CNTRL_OFF   0       /*!< set CAN controller off         */
+#define CAN_STS_CNTRL_ON    1       /*!< set CAN controller on          */
+#define CAN_STS_CNTRL_SLEEP 2       /*!< set CAN controller sleep mode  */
+#define CAN_STS_CNTRL_AWAKE 3       /*!< set CAN controller wake up     */
+#define CAN_STS_NORMAL      0x00    /*!< CAN controller status normal   */
+#define CAN_STS_RESET       0x01    /*!< CAN controller status reset    */
+#define CAN_STS_WARNING     0x02    /*!< CAN controller status warning  */
+#define CAN_STS_BUS_OFF     0x04    /*!< CAN controller status bus off  */
+#define CAN_STS_SLEEPING    0x08    /*!< CAN controller status sleeping */
+#define CAN_STS_OVERRUN     0x10    /*!< CAN controller status overrun  */
+#define CAN_STS_TXOK        0x20    /*!< CAN message transmitted        */
+
+#define COMMAND			0
+#define CONFIG			1
+#define SEND			2
+#define RECEIVE			3
+#define STATUS			4
+
+#endif
diff --git a/include/linux/input.h b/include/linux/input.h
index 3c58233..8ea2247 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -414,6 +414,7 @@ struct input_absinfo {
 #define BTN_STYLUS2		0x14c
 #define BTN_TOOL_DOUBLETAP	0x14d
 #define BTN_TOOL_TRIPLETAP	0x14e
+#define BTN_RAW			0x14f
 
 #define BTN_WHEEL		0x150
 #define BTN_GEAR_DOWN		0x150
diff --git a/include/linux/irda.h b/include/linux/irda.h
index 95dee17..3172c96 100644
--- a/include/linux/irda.h
+++ b/include/linux/irda.h
@@ -76,6 +76,7 @@ typedef enum {
 	IRDA_MCP2120_DONGLE      = 9,
 	IRDA_ACT200L_DONGLE      = 10,
 	IRDA_MA600_DONGLE        = 11,
+	IRDA_EP93XX_SIR          = 12,
 } IRDA_DONGLE;
 
 /* Protocol types to be used for SOCK_DGRAM */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b0ad6f3..2ee1652 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -883,6 +883,11 @@ extern void __put_task_struct(struct tas
 #define put_task_struct(tsk) \
 do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
 
+#ifdef	CONFIG_EP93XX_CRUNCH
+#define	PF_USEDCRUNCH	0x00200000	/* introduced to preserve PF_USEDFPU
+					   meaning across the architecture */
+#endif
+
 /*
  * Per process flags
  */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index e3710d7..a1c9b53 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -124,6 +124,9 @@
 /* Hilscher netx */
 #define PORT_NETX	71
 
+/* Cirrus EP93xx family */
+#define PORT_EP93XX	65
+
 #ifdef __KERNEL__
 
 #include <linux/config.h>
diff --git a/include/linux/ttml.h b/include/linux/ttml.h
new file mode 100644
index 0000000..2b0e327
--- /dev/null
+++ b/include/linux/ttml.h
@@ -0,0 +1,61 @@
+/*
+ * include/linux/ttml.h
+ *
+ * TTML TripDawg system devices.
+ *
+ * Copyright 2004, Ray Lehtiniemi
+ * Copyright 2004, Siconix, Inc
+ */
+
+#ifndef __TTML_H
+#define __TTML_H
+
+#define TTML_MAJOR         MISC_MAJOR
+
+#define TTML_MINOR_LED     240
+#define TTML_MINOR_BUZZER  241
+#define TTML_MINOR_SPEEDO  242
+#define TTML_MINOR_GPIO    243
+#define TTML_MINOR_BUTTON  244
+#define TTML_MINOR_WD      245
+
+#define MAX_TTML_MINORS 6
+
+struct ttml_ioctl_led {
+	int blue;
+	int red;
+	int yellow;
+};
+
+struct ttml_ioctl_buzzer {
+	int buzzer1;
+};
+
+struct ttml_ioctl_speedo {
+	int instant;
+	int average;
+};
+
+struct ttml_ioctl_gpio {
+	int pto;
+	int ignition;
+	int spare;
+};
+
+struct ttml_ioctl_button {
+	int button1;
+	int portf;
+};
+
+#define TTML_IOCTL 't'
+
+#define TTML_GET_LED      _IOR(TTML_IOCTL, 0, struct ttml_ioctl_led)
+#define TTML_GET_BUZZER   _IOR(TTML_IOCTL, 1, struct ttml_ioctl_buzzer)
+#define TTML_GET_SPEEDO   _IOR(TTML_IOCTL, 2, struct ttml_ioctl_speedo)
+#define TTML_GET_GPIO     _IOR(TTML_IOCTL, 3, struct ttml_ioctl_gpio)
+#define TTML_GET_BUTTON   _IOR(TTML_IOCTL, 4, struct ttml_ioctl_button)
+
+#define TTML_SET_LED      _IOW(TTML_IOCTL, 16, struct ttml_ioctl_led)
+#define TTML_SET_BUZZER   _IOW(TTML_IOCTL, 17, struct ttml_ioctl_buzzer)
+
+#endif
diff --git a/include/net/irda/ep93xx_irda.h b/include/net/irda/ep93xx_irda.h
new file mode 100644
index 0000000..0ee919d
--- /dev/null
+++ b/include/net/irda/ep93xx_irda.h
@@ -0,0 +1,261 @@
+ /*********************************************************************
+ *
+ * Filename:      ep93xx_irda.h
+ * Version:       0.2
+ * Description:   Header for the EP93xx SOC IrDA driver.
+ * Status:        Experimental.
+ *
+ * Copyright 2003 Cirrus Logic, Inc.
+ *
+ * Based on the ali-ircc.c implementation:
+ *      Author:        Benjamin Kong <benjamin_kong@ali.com.tw>
+ *      Created at:    2000/10/16 03:46PM
+ *      Modified at:   2001/1/3 02:55PM
+ *      Modified by:   Benjamin Kong <benjamin_kong@ali.com.tw>
+ *
+ *      Copyright (c) 2000 Benjamin Kong <benjamin_kong@ali.com.tw>
+ *      All Rights Reserved
+ *
+ *      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 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:
+ *      Free Software Foundation, Inc.
+ *      59 Temple Place, Suite 330
+ *      Boston, MA  02111-1307  USA
+ ********************************************************************/
+
+#ifndef EP93XX_IRDA_H
+#define EP93XX_IRDA_H
+
+#include <linux/time.h>
+
+#include <linux/spinlock.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+
+/*
+ * Number of DMA channels used
+ */
+#define DMA_COUNT 3
+
+/*
+ * TX/RX window queues
+ */
+#define MAX_TX_WINDOW 7
+#define MAX_RX_WINDOW 7
+
+struct ep93xx_chip {
+	char *name;
+	int iSIR_IRQ, iMFIR_IRQ;
+	ep93xx_dma_dev_t eSIR_DMATx;
+	ep93xx_dma_dev_t eMFIR_DMATx;
+	ep93xx_dma_dev_t eMFIR_DMARx;
+	int (*init) (struct ep93xx_chip * chip);
+};
+
+/* For storing entries in the status FIFO */
+
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+struct st_fifo {
+	struct st_fifo_entry entries[MAX_RX_WINDOW];
+	int pending_bytes;
+	int head;
+	int tail;
+	int len;
+};
+
+struct frame_cb {
+	void *start;		/* Start of frame in DMA mem */
+	int len;		/* Lenght of frame in DMA mem */
+};
+
+struct tx_fifo {
+	struct frame_cb queue[MAX_TX_WINDOW];	/* Info about frames in queue */
+	int ptr;		/* Currently being sent */
+	int len;		/* Length of queue */
+	int free;		/* Next free slot */
+	void *tail;		/* Next free start in DMA mem */
+};
+
+/* Private data for each instance */
+struct ep93xx_irda_cb {
+	struct st_fifo st_fifo;	/* Info about received frames */
+	struct tx_fifo tx_fifo;	/* Info about frames to be transmitted */
+
+	struct net_device *netdev;	/* Net device pointer */
+	struct net_device_stats stats;	/* Net device stats */
+
+	struct irlap_cb *irlap;	/* The link layer we are binded with */
+	struct qos_info qos;	/* QoS capabilities for this device */
+
+	int iSIR_irq, iMFIR_irq;	/* Interrupts used */
+
+	ep93xx_dma_dev_t ePorts[DMA_COUNT];	/* DMA port ids */
+
+	int iDMAh[DMA_COUNT];	/* handles for DMA channels */
+	dma_addr_t rx_dmaphysh, tx_dmaphysh;
+
+	int fifo_size;		/* FIFO size */
+	iobuff_t tx_buff;	/* Transmit buffer */
+	iobuff_t rx_buff;	/* Receive buffer */
+
+	char *conv_buf;		/* Buffer used for SIR conversion */
+
+	struct timeval stamp;	/* ? */
+	struct timeval now;	/* ? */
+
+	spinlock_t lock;	/* Used for serializing operations */
+
+	__u32 flags;		/* Interface flags */
+
+	__u8 direction;		/* TX/RX flag */
+
+	__u32 speed;		/* Currently used speed */
+	__u32 new_speed;	/* New target tx/rx speed */
+
+	int index;		/* Instance index */
+
+	int suspended;		/* APM suspend flag */
+	struct pm_dev *dev;	/* Power Management device */
+
+};
+
+/*
+ * DMA array handle index meanings
+ */
+#define DMA_SIR_TX                          0
+#define DMA_MFIR_TX                         1
+#define DMA_MFIR_RX                         2
+
+/*
+ * Directional defines
+ */
+#define DIR_TX                              0x01
+#define DIR_RX                              0x02
+#define DIR_BOTH                            0x03
+
+/*
+ * Modes support flag defines.
+ */
+#define CLK_SIR				    0x01
+#define CLK_MIR				    0x02
+#define CLK_FIR				    0x04
+
+/* Name friendly bit defines for register accesses */
+
+/* UART2/SIR */
+#define U2RSR_OvnErr                        0x08
+#define U2RSR_BrkErr                        0x04
+#define U2RSR_PtyErr                        0x02
+#define U2RSR_FrmErr                        0x01
+
+#define U2CRH_WLen                          0x60
+#define U2CRH_FEn                           0x10
+#define U2CRH_Stp2                          0x08
+#define U2CRH_EPS                           0x04
+#define U2CRH_PEn                           0x02
+#define U2CRH_Brk                           0x01
+
+#define U2CR_LoopBk                         0x80
+#define U2CR_RxTO                           0x40
+#define U2CR_TxIrq                          0x20
+#define U2CR_RxIrq                          0x10
+#define U2CR_MdmStsIrq                      0x08
+#define U2CR_SIRLowPwr                      0x04
+#define U2CR_SIR                            0x02
+#define U2CR_UART                           0x01
+
+#define U2FR_TXFE                           0x80
+#define U2FR_RXFF                           0x40
+#define U2FR_TXFF                           0x20
+#define U2FR_RXFE                           0x10
+#define U2FR_BUSY                           0x08
+#define U2FR_DCD                            0x04
+#define U2FR_DSR                            0x02
+#define U2FR_CTS                            0x01
+
+#define U2IICR_RXTOIRQ                      0x08
+#define U2IICR_TXIRQ                        0x04
+#define U2IICR_RXIRQ                        0x02
+#define U2IICR_MDMIRQ                       0x01
+
+#define U2DMACR_DMAErr                      0x04
+#define U2DMACR_TXDMA                       0x02
+#define U2DMACR_RXDMA                       0x01
+
+#define IrENABLE_SIR                        0x01
+
+/* IrDA block - MIR/FIR */
+#define IrENABLE_FIR                        0x03
+#define IrENABLE_MIR                        0x02
+
+#define IrCONTROL_RXRP                      0x40
+#define IrCONTROL_TXRP                      0x20
+#define IrCONTROL_RXON                      0x10
+#define IrCONTROL_TXON                      0x08
+#define IrCONTROL_TXUNDER                   0x04
+#define IrCONTROL_MIRBR                     0x02
+
+#define IrFLAG_TXBUSY                       0x200
+#define IrFLAG_RXINFRM                      0x100
+#define IrFLAG_RXSYNC                       0x80
+#define IrFLAG_EOF                          0x40
+#define IrFLAG_WIDTHST                      0x30
+#define IrFLAG_FIRFE                        0x08
+#define IrFLAG_RXOR                         0x04
+#define IrFLAG_CRCERR                       0x02
+#define IrFLAG_RXABORT                      0x01
+
+#define IrRIB_ByteCt                        0x7FF0
+#define IrRIB_BUFFE                         0x08
+#define IrRIB_BUFOR                         0x04
+#define IrRIB_BUFCRCERR                     0x02
+#define IrRIB_BUFRXABORT                    0x01
+
+#define IrDMACR_DMAERR                      0x04
+#define IrDMACR_DMATXE                      0x02
+#define IrDMACR_DMARXE                      0x01
+
+#define MFISR_RXFL                          0x40
+#define MFISR_RXIL                          0x20
+#define MFISR_RXFC                          0x10
+#define MFISR_RXFS                          0x08
+#define MFISR_TXFABORT                      0x04
+#define MFISR_TXFC                          0x02
+#define MFISR_TXSR                          0x01
+
+#define MFIMR_RXFL                          0x40
+#define MFIMR_RXIL                          0x20
+#define MFIMR_RXFC                          0x10
+#define MFIMR_RXFS                          0x08
+#define MFIMR_TXABORT                       0x04
+#define MFIMR_TXFC                          0x02
+#define MFIMR_TXFS                          0x01
+
+#define MFIIR_RXFL                          0x40
+#define MFIIR_RXIL                          0x20
+#define MFIIR_RXFC                          0x10
+#define MFIIR_RXFS                          0x08
+#define MFIIR_TXABORT                       0x04
+#define MFIIR_TXFC                          0x02
+#define MFIIR_TXFS                          0x01
+
+#endif				/* EP93XX_IRDA_H */
diff --git a/init/do_mounts.c b/init/do_mounts.c
index b27c110..29d2d52 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -410,7 +410,9 @@ void __init prepare_namespace(void)
 			root_device_name += 5;
 	}
 
-	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
+	/* llandre */
+	/* To retrieve ramdisk from MTD partition we must add major 31 as suggested by rmk */
+	is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31;
 
 	if (initrd_load())
 		goto out;
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 88e52dc..cda016b 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -1004,6 +1004,26 @@ config SOUND_AEDSP16
 	  <file:Documentation/sound/oss/AudioExcelDSP16> to get more information
 	  about this driver and its configuration.
 
+
+config SOUND_EP93XX_AC97
+	tristate "EP93xx AC97 Support"
+	depends on SOUND_OSS && ARCH_EP93XX
+	---help---
+	  AC97 sound support for Cirrus EP93xx
+
+config SOUND_EP93XX_AC97_CODEC_CS4297
+	bool "CS4297"
+	depends on SOUND_EP93XX_AC97
+	help
+	  Say Y here if you have CS4297 Codec.
+
+config SOUND_EP93XX_AUDIO_PIO
+	bool "EP93xx AC97 in PIO mode"
+	depends on SOUND_EP93XX_AC97
+	---help---
+	  Run EP93XX AC97 in PIO MODE.
+	  !!! NOT TESTED !!!
+
 config SC6600
 	bool "SC-6600 based audio cards (new Audio Excel DSP 16)"
 	depends on SOUND_AEDSP16
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 9bf3ee5..c7c1927 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -91,6 +91,9 @@ obj-$(CONFIG_SOUND_EMU10K1)	+= emu10k1/
 obj-$(CONFIG_SOUND_CS4281)	+= cs4281/
 obj-$(CONFIG_DMASOUND)		+= dmasound/
 
+obj-$(CONFIG_SOUND_EP93XX_I2S)	+= ep93xx-audio.o ep93xx-i2s.o
+obj-$(CONFIG_SOUND_EP93XX_AC97)	+= ep93xx-audio.o ep93xx-ac97.o
+
 # Declare multi-part drivers.
 
 sound-objs	:= 							\
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
index fd25aca..c7c9a02 100644
--- a/sound/oss/ac97_codec.c
+++ b/sound/oss/ac97_codec.c
@@ -156,6 +156,8 @@ static const struct {
 	{0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops},
 	{0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops},
 	{0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops},
+	{0x4352594d, "Cirrus Logic CS4201",	&crystal_digital_ops},
+	{0x43525973, "Cirrus Logic CS4202",	&crystal_digital_ops},
 	{0x43585430, "CXT48",			&default_ops,		AC97_DELUDED_MODEM },
 	{0x43585442, "CXT66",			&default_ops,		AC97_DELUDED_MODEM },
 	{0x44543031, "Diamond Technology DT0893", &default_ops},
diff --git a/sound/oss/ep93xx-ac97.c b/sound/oss/ep93xx-ac97.c
new file mode 100644
index 0000000..a967f19
--- /dev/null
+++ b/sound/oss/ep93xx-ac97.c
@@ -0,0 +1,1200 @@
+/*
+ * Glue audio driver for the Cirrus EP93xx Ac97 Controller
+ *
+ * Copyright (c) 2003 Cirrus Logic Corp.
+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ *
+ * This file taken from h3600-uda1341.c
+ * The mixer code is from ac97_codec.c
+ *
+ * History:
+ *
+ * 2000-05-21   Nicolas Pitre   Initial UDA1341 driver release.
+ *
+ * 2000-07-??   George France   Bitsy support.
+ *
+ * 2000-12-13   Deborah Wallach Fixed power handling for iPAQ/h3600
+ *
+ * 2001-06-03   Nicolas Pitre   Made this file a separate module, based on
+ *              the former sa1100-uda1341.c driver.
+ *
+ * 2001-07-13   Nicolas Pitre   Fixes for all supported samplerates.
+ *
+ * 2003-04-04   adt	Changes for Cirrus Logic EP93xx I2S
+ *
+ * 2003-04-25   adt	Changes for Cirrus Logic EP93xx Ac97
+ *
+ * 2005-05-11	Manfred Gruber  Ported this from Cirrus Logic Virgo 1-4-3 release
+ *                              to Kernel 2.6.11.X
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/bitops.h>
+
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+#include <asm/arch/clocks.h>
+#include <asm/io.h>
+#include <asm/arch/dma.h>
+#include <linux/dma-mapping.h>
+
+#include "ep93xx-audio.h"
+
+#undef DEBUG
+//#define DEBUG 1
+#ifdef DEBUG
+#define DPRINTK( x... )  printk( x )
+#else
+#define DPRINTK( x... )
+#endif
+
+#define AUDIO_NAME      "ep93xx_ac97"
+
+#ifdef CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297
+#define AUDIO_SAMPLE_RATE_DEFAULT   48000
+#else
+#define AUDIO_SAMPLE_RATE_DEFAULT   44100
+#endif
+
+/* original check is not good enough in case FOO is greater than
+ * SOUND_MIXER_NRDEVICES because the supported_mixers has exactly
+ * SOUND_MIXER_NRDEVICES elements.
+ * before matching the given mixer against the bitmask in supported_mixers we
+ * check if mixer number exceeds maximum allowed size which is as mentioned
+ * above SOUND_MIXER_NRDEVICES */
+#define supported_mixer(FOO) \
+	( (FOO >= 0) && \
+	(FOO < SOUND_MIXER_NRDEVICES) && \
+	codec_supported_mixers & (1<<FOO) )
+
+/*
+ * Available record sources.
+ * LINE1 refers to AUX in.
+ * IGAIN refers to input gain which means stereo mix.
+ */
+#define AC97_RECORD_MASK \
+	(SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN | SOUND_MASK_VIDEO |\
+	SOUND_MASK_LINE1 | SOUND_MASK_LINE | SOUND_MASK_PHONEIN)
+
+#define AC97_STEREO_MASK \
+	(SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_CD | \
+	SOUND_MASK_ALTPCM | SOUND_MASK_IGAIN | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO)
+
+#define AC97_SUPPORTED_MASK \
+	(AC97_STEREO_MASK | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
+	SOUND_MASK_SPEAKER | SOUND_MASK_MIC | \
+	SOUND_MASK_PHONEIN | SOUND_MASK_PHONEOUT)
+
+/*
+ * Function prototypes.
+ */
+static int peek(unsigned int uiAddress);
+static int poke(unsigned int uiAddress, unsigned int uiValue);
+static void ep93xx_setup_src(void);
+static void ep93xx_set_samplerate(struct audio_stream_t *stream,
+				  long lSampleRate);
+static void ep93xx_init_ac97_codec(void);
+static void ep93xx_set_hw_format(struct audio_stream_t *stream, long format);
+static void ep93xx_init_ac97_controller(void);
+static int ep93xx_mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
+			      ulong arg);
+static void ep93xx_audio_init(void *dummy);
+static int ep93xx_audio_ioctl(struct inode *inode, struct file *file, uint cmd,
+			      ulong arg);
+
+static int ep93xx_audio_open(struct inode *inode, struct file *file);
+static int __init ep93xx_ac97_init(void);
+static void __exit ep93xx_ac97_exit(void);
+static void ep93xx_init_mixer(void);
+static void ep93xx_audio_enable(struct audio_stream_t *stream);
+static void ep93xx_audio_disable(struct audio_stream_t *stream);
+
+/*
+ * Statics
+ */
+// KERNEL2.4
+//static long audio_samplerate = AUDIO_SAMPLE_RATE_DEFAULT;
+static int ac_link_enabled = 0;
+static int codec_supported_mixers;
+
+/* this table has default mixer values for all OSS mixers. */
+struct mixer_defaults_t {
+	int mixer;
+	unsigned int value;
+};
+
+/*
+ * Default mixer settings that are set up during boot.
+ *
+ * These values are 16 bit numbers in which the upper byte is right volume
+ * and the lower byte is left volume or mono volume for mono controls.
+ *
+ * OSS Range for each of left and right volumes is 0 to 100 (0x00 to 0x64).
+ *
+ */
+static struct mixer_defaults_t mixer_defaults[SOUND_MIXER_NRDEVICES] = {
+	/* Outputs */
+	{SOUND_MIXER_VOLUME, 0x6464},	/* 0 dB *//* -46.5dB to  0 dB */
+	{SOUND_MIXER_ALTPCM, 0x6464},	/* 0 dB *//* -46.5dB to  0 dB */
+	{SOUND_MIXER_PHONEOUT, 0x6464},	/* 0 dB *//* -46.5dB to  0 dB */
+
+	/* PCM playback gain */
+	{SOUND_MIXER_PCM, 0x4b4b},	/* 0 dB *//* -34.5dB to +12dB */
+
+	/* Record gain */
+	{SOUND_MIXER_IGAIN, 0x0000},	/* 0 dB *//*    0 to +22.5 dB */
+
+	/* Inputs */
+	{SOUND_MIXER_MIC, 0x0000},	/* mute *//* -34.5dB to +12dB */
+	{SOUND_MIXER_LINE, 0x4b4b},	/* 0 dB *//* -34.5dB to +12dB */
+
+	/* Inputs that are not connected. */
+	{SOUND_MIXER_SPEAKER, 0x0000},	/* mute *//* -45dB   to   0dB */
+	{SOUND_MIXER_PHONEIN, 0x0000},	/* mute *//* -34.5dB to +12dB */
+	{SOUND_MIXER_CD, 0x0000},	/* mute *//* -34.5dB to +12dB */
+	{SOUND_MIXER_VIDEO, 0x0000},	/* mute *//* -34.5dB to +12dB */
+	{SOUND_MIXER_LINE1, 0x0000},	/* mute *//* -34.5dB to +12dB */
+
+	{-1, 0}			/* last entry */
+};
+
+static unsigned int guiOSS_Volume[SOUND_MIXER_NRDEVICES];
+
+/* table to scale scale from OSS mixer value to AC97 mixer register value */
+struct ac97_mixer_hw_t {
+	unsigned int offset;
+	int scale;
+};
+
+static struct ac97_mixer_hw_t ac97_hw[SOUND_MIXER_NRDEVICES] = {
+	[SOUND_MIXER_VOLUME] = {AC97_02_MASTER_VOL, 64},
+	[SOUND_MIXER_BASS] = {0, 0},
+	[SOUND_MIXER_TREBLE] = {0, 0},
+	[SOUND_MIXER_SYNTH] = {0, 0},
+	[SOUND_MIXER_PCM] = {AC97_18_PCM_OUT_VOL, 32},
+	[SOUND_MIXER_SPEAKER] = {AC97_0A_PC_BEEP_VOL, 32},
+	[SOUND_MIXER_LINE] = {AC97_10_LINE_IN_VOL, 32},
+	[SOUND_MIXER_MIC] = {AC97_0E_MIC_VOL, 32},
+	[SOUND_MIXER_CD] = {AC97_12_CD_VOL, 32},
+	[SOUND_MIXER_IMIX] = {0, 0},
+	[SOUND_MIXER_ALTPCM] = {AC97_04_HEADPHONE_VOL, 64},
+	[SOUND_MIXER_RECLEV] = {0, 0},
+	[SOUND_MIXER_IGAIN] = {AC97_1C_RECORD_GAIN, 16},
+	[SOUND_MIXER_OGAIN] = {0, 0},
+	[SOUND_MIXER_LINE1] = {AC97_16_AUX_VOL, 32},
+	[SOUND_MIXER_LINE2] = {0, 0},
+	[SOUND_MIXER_LINE3] = {0, 0},
+	[SOUND_MIXER_DIGITAL1] = {0, 0},
+	[SOUND_MIXER_DIGITAL2] = {0, 0},
+	[SOUND_MIXER_DIGITAL3] = {0, 0},
+	[SOUND_MIXER_PHONEIN] = {AC97_0C_PHONE_VOL, 32},
+	[SOUND_MIXER_PHONEOUT] = {AC97_06_MONO_VOL, 64},
+	[SOUND_MIXER_VIDEO] = {AC97_14_VIDEO_VOL, 32},
+	[SOUND_MIXER_RADIO] = {0, 0},
+	[SOUND_MIXER_MONITOR] = {0, 0},
+};
+
+/* the following tables allow us to go from OSS <-> ac97 quickly. */
+enum ac97_recsettings {
+	AC97_REC_MIC = 0,
+	AC97_REC_CD,
+	AC97_REC_VIDEO,
+	AC97_REC_AUX,
+	AC97_REC_LINE,
+	AC97_REC_STEREO,	/* combination of all enabled outputs..  */
+	AC97_REC_MONO,		/*.. or the mono equivalent */
+	AC97_REC_PHONE
+};
+
+static const unsigned int ac97_rm2oss[] = {
+	[AC97_REC_MIC] = SOUND_MIXER_MIC,
+	[AC97_REC_CD] = SOUND_MIXER_CD,
+	[AC97_REC_VIDEO] = SOUND_MIXER_VIDEO,
+	[AC97_REC_AUX] = SOUND_MIXER_LINE1,
+	[AC97_REC_LINE] = SOUND_MIXER_LINE,
+	[AC97_REC_STEREO] = SOUND_MIXER_IGAIN,
+	[AC97_REC_PHONE] = SOUND_MIXER_PHONEIN
+};
+
+/* indexed by bit position */
+static const unsigned int ac97_oss_rm[] = {
+	[SOUND_MIXER_MIC] = AC97_REC_MIC,
+	[SOUND_MIXER_CD] = AC97_REC_CD,
+	[SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
+	[SOUND_MIXER_LINE1] = AC97_REC_AUX,
+	[SOUND_MIXER_LINE] = AC97_REC_LINE,
+	[SOUND_MIXER_IGAIN] = AC97_REC_STEREO,
+	[SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
+};
+
+static struct audio_stream_t ac97_output_stream0 = {
+      audio_num_channels:EP93XX_DEFAULT_NUM_CHANNELS,
+      audio_format:EP93XX_DEFAULT_FORMAT,
+      audio_stream_bitwidth:EP93XX_DEFAULT_BIT_WIDTH,
+      devicename:"Ac97_out",
+      dmachannel:{DMATx_AAC1, UNDEF, UNDEF},
+      sample_rate:0,
+      hw_bit_width:16,
+      bCompactMode:1,
+};
+
+static struct audio_stream_t ac97_input_stream0 = {
+      audio_num_channels:EP93XX_DEFAULT_NUM_CHANNELS,
+      audio_format:EP93XX_DEFAULT_FORMAT,
+      audio_stream_bitwidth:EP93XX_DEFAULT_BIT_WIDTH,
+      devicename:"Ac97_in",
+      dmachannel:{DMARx_AAC1, UNDEF, UNDEF},
+      sample_rate:0,
+      hw_bit_width:16,
+      bCompactMode:1,
+};
+
+static struct audio_hw_t ep93xx_ac97_hw = {
+      hw_enable:ep93xx_audio_enable,
+      hw_disable:ep93xx_audio_disable,
+      hw_clear_fifo:0,
+      client_ioctl:ep93xx_audio_ioctl,
+
+      set_hw_serial_format:ep93xx_set_hw_format,
+
+      txdmachannels:{DMATx_AAC1, DMATx_AAC2, DMATx_AAC3},
+      rxdmachannels:{DMARx_AAC1, DMARx_AAC2, DMARx_AAC3},
+
+      MaxTxDmaChannels:3,
+      MaxRxDmaChannels:3,
+
+      modcnt:0,
+};
+
+static struct audio_state_t ac97_audio_state0 = {
+      output_stream:&ac97_output_stream0,
+      input_stream:&ac97_input_stream0,
+	// KERNEL2.4 deleted internal sema intialisier, do it in function
+      hw:&ep93xx_ac97_hw,
+      wr_ref:0,
+      rd_ref:0,
+};
+
+/*
+ * peek
+ *
+ * Reads an AC97 codec register.  Returns -1 if there was an error.
+ */
+static int peek(unsigned int uiAddress)
+{
+	unsigned int uiAC97RGIS, uiTemp;
+
+	if (!ac_link_enabled) {
+		DPRINTK
+		    ("ep93xx ac97 peek: attempt to peek before enabling ac-link.\n");
+		return -1;
+	}
+
+	/*
+	 * Check to make sure that the address is aligned on a word boundary
+	 * and is 7E or less.
+	 */
+	if (((uiAddress & 0x1) != 0) || (uiAddress > 0x007e)) {
+		return -1;
+	}
+
+	/*
+	 * How it is supposed to work is:
+	 *  - The ac97 controller sends out a read addr in slot 1.
+	 *  - In the next frame, the codec will echo that address back in slot 1
+	 *    and send the data in slot 2.  SLOT2RXVALID will be set to 1.
+	 *
+	 * Read until SLOT2RXVALID goes to 1.  Reading the data in AC97S2DATA
+	 * clears SLOT2RXVALID.
+	 */
+
+	/*
+	 * First, delay one frame in case of back to back peeks/pokes.
+	 */
+	mdelay(1);
+
+	/*
+	 * Write the address to AC97S1DATA, delay 1 frame, read the flags.
+	 */
+	outl(uiAddress, AC97S1DATA);
+	uiTemp = inl(AC97GCR);	/* read to push write out the wrapper */
+
+	udelay(21 * 4);
+	uiAC97RGIS = inl(AC97RGIS);
+
+	/*
+	 * Return error if we timed out.
+	 */
+	if (((uiAC97RGIS & AC97RGIS_SLOT1TXCOMPLETE) == 0) &&
+	    ((uiAC97RGIS & AC97RGIS_SLOT2RXVALID) == 0)) {
+		DPRINTK("ep93xx-ac97 - peek failed reading reg 0x%02x.\n",
+			uiAddress);
+		return -1;
+	}
+
+	return (inl(AC97S2DATA) & 0x000fffff);
+}
+
+/*
+ * poke
+ *
+ * Writes an AC97 codec Register.  Return -1 if error.
+ */
+static int poke(unsigned int uiAddress, unsigned int uiValue)
+{
+	unsigned int uiAC97RGIS, uiTemp;
+
+	if (!ac_link_enabled) {
+		DPRINTK
+		    ("ep93xx ac97 poke: attempt to poke before enabling ac-link.\n");
+		return -1;
+	}
+
+	/*
+	 * Check to make sure that the address is align on a word boundary and
+	 * is 7E or less.  And that the value is a 16 bit value.
+	 */
+	if (((uiAddress & 0x1) != 0) || (uiAddress > 0x007e)) {
+		return -1;
+	}
+
+	/*
+	 * First, delay one frame in case of back to back peeks/pokes.
+	 */
+	mdelay(1);
+
+	/*
+	 * Write the data to AC97S2DATA, then the address to AC97S1DATA.
+	 */
+	outl(uiValue, AC97S2DATA);
+	outl(uiAddress, AC97S1DATA);
+	uiTemp = inl(AC97GCR);	/* read to push writes out the wrapper */
+
+	/*
+	 * Wait for the tx to complete, get status.
+	 */
+	udelay(42);
+	uiAC97RGIS = inl(AC97RGIS);
+
+	/*
+	 * Return error if we timed out.
+	 */
+	if (!(inl(AC97RGIS) & AC97RGIS_SLOT1TXCOMPLETE)) {
+		DPRINTK
+		    ("ep93xx-ac97: poke failed writing reg 0x%02x  value 0x%02x.\n",
+		     uiAddress, uiValue);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * When we get to the multichannel case the pre-fill and enable code
+ * will go to the dma driver's start routine.
+ */
+static void ep93xx_audio_enable(struct audio_stream_t *stream)
+{
+	unsigned int uiTemp;
+
+	DPRINTK("ep93xx_audio_enable\n");
+
+	/*
+	 * Enable the rx or tx channel
+	 */
+	if (stream->dmachannel[0] == DMATx_AAC1) {
+		uiTemp = inl(AC97TXCR1);
+		outl((uiTemp | AC97TXCR_TEN), AC97TXCR1);
+		uiTemp = inl(AC97TXCR1);
+#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
+		outl(inl(AC97IE1) | AC97ISR_TIS, AC97IE1);
+#endif
+	}
+
+	if (stream->dmachannel[0] == DMARx_AAC1) {
+		uiTemp = inl(AC97RXCR1);
+		outl((uiTemp | AC97RXCR_REN), AC97RXCR1);
+		uiTemp = inl(AC97RXCR1);
+#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
+		outl(inl(AC97IE1) | AC97ISR_RIS, AC97IE1);
+#endif
+	}
+	//DPRINTK("ep93xx_audio_enable - EXIT\n");
+}
+
+static void ep93xx_audio_disable(struct audio_stream_t *stream)
+{
+	unsigned int uiControl, uiStatus;
+
+	DPRINTK("ep93xx_audio_disable\n");
+
+	/*
+	 * Disable the rx or tx channel
+	 */
+	if (stream->dmachannel[0] == DMATx_AAC1) {
+		uiControl = inl(AC97TXCR1);
+		if (uiControl & AC97TXCR_TEN) {
+#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
+			outl(inl(AC97IE1) & ~AC97ISR_TIS, AC97IE1);
+#else
+			/*
+			 * Wait for fifo to empty.  We've shut down the dma
+			 * so that should happen soon.
+			 */
+			do {
+				uiStatus = inl(AC97SR1);
+			} while (((uiStatus & 0x82) == 0));
+			//} while( ((uiStatus & 0x20)!=0) ;&&
+			//((uiStatus & 0x82)==0) );
+#endif
+
+			outl((uiControl & ~AC97TXCR_TEN), AC97TXCR1);
+			uiControl = inl(AC97TXCR1);
+		}
+	}
+
+	if (stream->dmachannel[0] == DMARx_AAC1) {
+#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
+		outl(inl(AC97IE1) & ~AC97ISR_RIS, AC97IE1);
+#endif
+		uiControl = inl(AC97RXCR1);
+		outl((uiControl & ~AC97RXCR_REN), AC97RXCR1);
+		uiControl = inl(AC97RXCR1);
+	}
+	//DPRINTK("ep93xx_audio_disable - EXIT\n");
+}
+
+/*
+ * ep93xx_setup_src
+ *
+ * Once the ac-link is up and all is good, we want to set the codec to a
+ * usable mode.
+ */
+static void ep93xx_setup_src(void)
+{
+	int iTemp;
+
+	/*
+	 * Set the VRA bit to enable the SRC.
+	 */
+	iTemp = peek(AC97_2A_EXT_AUDIO_POWER);
+	poke(AC97_2A_EXT_AUDIO_POWER, (iTemp | 0x1));
+
+	/*
+	 * Set the DSRC/ASRC bits to enable the variable rate SRC.
+	 */
+	iTemp = peek(AC97_60_MISC_CRYSTAL_CONTROL);
+	poke(AC97_60_MISC_CRYSTAL_CONTROL, (iTemp | 0x0300));
+}
+
+/*
+ * ep93xx_set_samplerate
+ *
+ *   lFrequency		- Sample Rate in Hz
+ *   bTx			- 1 to set Tx sample rate
+ *   bRx			- 1 to set Rx sample rate
+ */
+static void ep93xx_set_samplerate(struct audio_stream_t *stream,
+				  long lSampleRate)
+{
+#ifndef CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297
+	unsigned short usDivider, usPhase;
+
+	DPRINTK("ep93xx_set_samplerate - Fs = %d\n", (int)lSampleRate);
+
+	if ((lSampleRate < 7200) || (lSampleRate > 48000)) {
+		DPRINTK("ep93xx_set_samplerate - invalid Fs = %d\n",
+			(int)lSampleRate);
+		return;
+	}
+
+	/*
+	 * Calculate divider and phase increment.
+	 *
+	 * divider = round( 0x1770000 / lSampleRate )
+	 *  Note that usually rounding is done by adding 0.5 to a floating
+	 *  value and then truncating.  To do this without using floating
+	 *  point, I multiply the fraction by two, do the division, then add one,
+	 *  then divide the whole by 2 and then truncate.
+	 *  Same effect, no floating point math.
+	 *
+	 * Ph incr = trunc( (0x1000000 / usDivider) + 1 )
+	 */
+
+	usDivider = (unsigned short)(((2 * 0x1770000 / lSampleRate) + 1) / 2);
+
+	usPhase = (0x1000000 / usDivider) + 1;
+
+	/*
+	 * Write them in the registers.  Spec says divider must be
+	 * written after phase incr.
+	 */
+	if (stream->dmachannel[0] == DMATx_AAC1) {
+		poke(AC97_2C_PCM_FRONT_DAC_RATE, usDivider);
+		poke(AC97_64_DAC_SRC_PHASE_INCR, usPhase);
+	}
+
+	if (stream->dmachannel[0] == DMARx_AAC1) {
+
+		poke(AC97_32_PCM_LR_ADC_RATE, usDivider);
+		poke(AC97_66_ADC_SRC_PHASE_INCR, usPhase);
+	}
+
+	DPRINTK("ep93xx_set_samplerate - phase = %d,  divider = %d\n",
+		(unsigned int)usPhase, (unsigned int)usDivider);
+
+	/*
+	 * We sorta should report the actual samplerate back to the calling
+	 * application.  But some applications freak out if they don't get
+	 * exactly what they asked for.  So we fudge and tell them what
+	 * they want to hear.
+	 */
+	stream->sample_rate = lSampleRate;
+
+	DPRINTK("ep93xx_set_samplerate - EXIT\n");
+#else
+	stream->sample_rate = AUDIO_SAMPLE_RATE_DEFAULT;
+#endif
+}
+
+/*
+ * ep93xx_set_hw_format
+ *
+ * Sets up whether the controller is expecting 20 bit data in 32 bit words
+ * or 16 bit data compacted to have a stereo sample in each 32 bit word.
+ */
+static void ep93xx_set_hw_format(struct audio_stream_t *stream, long format)
+{
+	int bCompactMode, uiTemp, iWidth;
+	unsigned long ulRegValue;
+
+	switch (format) {
+		/*
+		 * Here's all the <=16 bit formats.  We can squeeze both L and R
+		 * into one 32 bit sample so use compact mode.
+		 */
+	case AFMT_U8:
+	case AFMT_S8:
+	case AFMT_S16_LE:
+	case AFMT_U16_LE:
+		bCompactMode = 1;
+		ulRegValue = 0x00008018;
+		iWidth = 16;
+		break;
+
+		/*
+		 * Add any other >16 bit formats here...
+		 */
+	case AFMT_S32_BLOCKED:
+	default:
+		bCompactMode = 0;
+		ulRegValue = 0x00004018;
+		iWidth = 20;
+		break;
+	}
+
+	if (stream->dmachannel[0] == DMARx_AAC1) {
+		uiTemp = inl(AC97RXCR1);
+		if (ulRegValue != uiTemp) {
+			outl(ulRegValue, AC97RXCR1);
+			uiTemp = inl(AC97RXCR1);
+		}
+		stream->hw_bit_width = iWidth;
+		stream->bCompactMode = bCompactMode;
+	}
+
+	if (stream->dmachannel[0] == DMATx_AAC1) {
+		uiTemp = inl(AC97TXCR1);
+		if (ulRegValue != uiTemp) {
+			outl(ulRegValue, AC97TXCR1);
+			uiTemp = inl(AC97TXCR1);
+		}
+		stream->hw_bit_width = iWidth;
+		stream->bCompactMode = bCompactMode;
+	}
+
+}
+
+/*
+ * ep93xx_init_ac97_controller
+ *
+ * This routine sets up the Ac'97 Controller.
+ */
+static void ep93xx_init_ac97_controller(void)
+{
+	unsigned int uiDEVCFG, uiTemp;
+
+	DPRINTK("ep93xx_init_ac97_controller - enter\n");
+
+	/*
+	 * Configure the multiplexed Ac'97 pins to be Ac97 not I2s.
+	 * Configure the EGPIO4 and EGPIO6 to be GPIOS, not to be
+	 * SDOUT's for the second and third I2S controller channels.
+	 */
+	uiDEVCFG = inl(SYSCON_DEVCFG);
+
+	uiDEVCFG &= ~(SYSCON_DEVCFG_I2SonAC97 |
+		      SYSCON_DEVCFG_A1onG | SYSCON_DEVCFG_A2onG);
+
+	SysconSetLocked(SYSCON_DEVCFG, uiDEVCFG);
+
+	/*
+	 * Disable the AC97 controller internal loopback.
+	 * Disable Override codec ready.
+	 */
+	outl(0, AC97GCR);
+
+	/*
+	 * Enable the AC97 Link.
+	 */
+	uiTemp = inl(AC97GCR);
+	outl((uiTemp | AC97GSR_IFE), AC97GCR);
+	uiTemp = inl(AC97GCR);	/* read to push write out the wrapper */
+
+	/*
+	 * Set the TIMEDRESET bit.  Will cause a > 1uSec reset of the ac-link.
+	 * This bit is self resetting.
+	 */
+	outl(AC97RESET_TIMEDRESET, AC97RESET);
+	uiTemp = inl(AC97GCR);	/* read to push write out the wrapper */
+
+	/*
+	 *  Delay briefly, but let's not hog the processor.
+	 */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(5);	/* 50 mSec */
+
+	/*
+	 * Read the AC97 status register to see if we've seen a CODECREADY
+	 * signal from the AC97 codec.
+	 */
+	if (!(inl(AC97RGIS) & AC97RGIS_CODECREADY)) {
+		DPRINTK("ep93xx-ac97 - FAIL: CODECREADY still low!\n");
+		return;
+	}
+
+	/*
+	 *  Delay for a second, not hogging the processor
+	 */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ);	/* 1 Sec */
+
+	/*
+	 * Now the Ac-link is up.  We can read and write codec registers.
+	 */
+	ac_link_enabled = 1;
+
+	/*
+	 * Set up the rx and tx channels
+	 * Set the CM bit, data size=16 bits, enable tx slots 3 & 4.
+	 */
+	ep93xx_set_hw_format(&ac97_output_stream0, EP93XX_DEFAULT_FORMAT);
+	ep93xx_set_hw_format(&ac97_input_stream0, EP93XX_DEFAULT_FORMAT);
+
+	DPRINTK("ep93xx-ac97 -- AC97RXCR1:  %08x\n", inl(AC97RXCR1));
+	DPRINTK("ep93xx-ac97 -- AC97TXCR1:  %08x\n", inl(AC97TXCR1));
+
+	DPRINTK("ep93xx_init_ac97_controller - EXIT - success\n");
+
+}
+
+/*
+ * ep93xx_init_ac97_codec
+ *
+ * Program up the external Ac97 codec.
+ *
+ */
+static void ep93xx_init_ac97_codec(void)
+{
+	DPRINTK("ep93xx_init_ac97_codec - enter\n");
+
+	ep93xx_setup_src();
+	ep93xx_set_samplerate(&ac97_output_stream0, AUDIO_SAMPLE_RATE_DEFAULT);
+	ep93xx_set_samplerate(&ac97_input_stream0, AUDIO_SAMPLE_RATE_DEFAULT);
+	ep93xx_init_mixer();
+
+	DPRINTK("ep93xx_init_ac97_codec - EXIT\n");
+
+}
+
+#ifdef DEBUG
+static void ep93xx_dump_ac97_regs(void)
+{
+	int i;
+	unsigned int reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;
+
+	DPRINTK("---------------------------------------------\n");
+	DPRINTK("   :   0    2    4    6    8    A    C    E\n");
+
+	for (i = 0; i < 0x80; i += 0x10) {
+		reg0 = 0xffff & (unsigned int)peek(i);
+		reg1 = 0xffff & (unsigned int)peek(i + 0x2);
+		reg2 = 0xffff & (unsigned int)peek(i + 0x4);
+		reg3 = 0xffff & (unsigned int)peek(i + 0x6);
+		reg4 = 0xffff & (unsigned int)peek(i + 0x8);
+		reg5 = 0xffff & (unsigned int)peek(i + 0xa);
+		reg6 = 0xffff & (unsigned int)peek(i + 0xc);
+		reg7 = 0xffff & (unsigned int)peek(i + 0xe);
+
+		DPRINTK(" %02x : %04x %04x %04x %04x %04x %04x %04x %04x\n",
+			i, reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7);
+	}
+}
+#endif
+
+static void ep93xx_set_volume(unsigned int oss_channel, unsigned int oss_val) {
+	unsigned int left, right;
+	u16 val = 0;
+	struct ac97_mixer_hw_t *mh = &ac97_hw[oss_channel];
+
+	if (!mh->scale) {
+		DPRINTK
+		    ("ep93xx-ac97.c: ep93xx_set_volume - not a valid OSS channel\n");
+		return;
+	}
+
+	/* cleanse input a little */
+	right = ((oss_val >> 8) & 0xff);
+	left = (oss_val & 0xff);
+
+	if (right > 100)
+		right = 100;
+	if (left > 100)
+		left = 100;
+
+	DPRINTK("ac97_codec: wrote OSS channel#%2d (ac97 reg 0x%02x), "
+		"l:%2d, r:%2d:", oss_channel, mh->offset, left, right);
+
+	if (AC97_STEREO_MASK & (1 << oss_channel)) {
+		/* stereo mixers */
+		if (oss_channel == SOUND_MIXER_IGAIN) {
+			right = ((100 - right) * (mh->scale - 1)) / 100;
+			left = ((100 - left) * (mh->scale - 1)) / 100;
+			if (right >= mh->scale)
+				right = mh->scale - 1;
+			if (left >= mh->scale)
+				left = mh->scale - 1;
+			right = (mh->scale - 1) - right;
+			left = (mh->scale - 1) - left;
+			val = (left << 8) | right;
+		} else {
+			if (left == 0 && right == 0) {
+				val = 0x8000;
+			} else {
+				right = ((100 - right) * (mh->scale - 1)) / 100;
+				left = ((100 - left) * (mh->scale - 1)) / 100;
+				if (right >= mh->scale)
+					right = mh->scale - 1;
+				if (left >= mh->scale)
+					left = mh->scale - 1;
+				val = (left << 8) | right;
+			}
+		}
+	} else if (left == 0) {
+		val = 0x8000;
+	} else if ((oss_channel == SOUND_MIXER_SPEAKER) ||
+		   (oss_channel == SOUND_MIXER_PHONEIN) ||
+		   (oss_channel == SOUND_MIXER_PHONEOUT)) {
+		left = ((100 - left) * (mh->scale - 1)) / 100;
+		if (left >= mh->scale)
+			left = mh->scale - 1;
+		val = left;
+	} else if (oss_channel == SOUND_MIXER_MIC) {
+		val = peek(mh->offset) & ~0x801f;
+		left = ((100 - left) * (mh->scale - 1)) / 100;
+		if (left >= mh->scale)
+			left = mh->scale - 1;
+		val |= left;
+	}
+	/*
+	 * For bass and treble, the low bit is optional.  Masking it
+	 * lets us avoid the 0xf 'bypass'.
+	 * Do a read, modify, write as we have two contols in one reg.
+	 */
+	else if (oss_channel == SOUND_MIXER_BASS) {
+		val = peek(mh->offset) & ~0x0f00;
+		left = ((100 - left) * (mh->scale - 1)) / 100;
+		if (left >= mh->scale)
+			left = mh->scale - 1;
+		val |= (left << 8) & 0x0e00;
+	} else if (oss_channel == SOUND_MIXER_TREBLE) {
+		val = peek(mh->offset) & ~0x000f;
+		left = ((100 - left) * (mh->scale - 1)) / 100;
+		if (left >= mh->scale)
+			left = mh->scale - 1;
+		val |= left & 0x000e;
+	}
+
+	DPRINTK(" 0x%04x", val);
+
+	poke(mh->offset, val);
+
+#ifdef DEBUG
+	val = peek(mh->offset);
+	DPRINTK(" (read back 0x%04x)\n", val);
+#endif
+
+	guiOSS_Volume[oss_channel] = oss_val;
+}
+
+static void ep93xx_init_mixer(void)
+{
+	u16 cap;
+	int i;
+
+	/* mixer masks */
+	codec_supported_mixers = AC97_SUPPORTED_MASK;
+
+	cap = peek(AC97_00_RESET);
+	if (!(cap & 0x04)) {
+		codec_supported_mixers &=
+		    ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE);
+	}
+	if (!(cap & 0x10)) {
+		codec_supported_mixers &= ~SOUND_MASK_ALTPCM;
+	}
+
+	/*
+	 * Detect bit resolution of output volume controls by writing to the
+	 * 6th bit (not unmuting yet)
+	 */
+	poke(AC97_02_MASTER_VOL, 0xa020);
+	if (peek(AC97_02_MASTER_VOL) != 0xa020) {
+		ac97_hw[SOUND_MIXER_VOLUME].scale = 32;
+	}
+
+	poke(AC97_04_HEADPHONE_VOL, 0xa020);
+	if (peek(AC97_04_HEADPHONE_VOL) != 0xa020) {
+		ac97_hw[AC97_04_HEADPHONE_VOL].scale = 32;
+	}
+
+	poke(AC97_06_MONO_VOL, 0x8020);
+	if (peek(AC97_06_MONO_VOL) != 0x8020) {
+		ac97_hw[AC97_06_MONO_VOL].scale = 32;
+	}
+
+	/* initialize mixer channel volumes */
+	for (i = 0;
+	     (i < SOUND_MIXER_NRDEVICES) && (mixer_defaults[i].mixer != -1);
+	     i++) {
+		if (!supported_mixer(mixer_defaults[i].mixer)) {
+			continue;
+		}
+
+		ep93xx_set_volume(mixer_defaults[i].mixer,
+				  mixer_defaults[i].value);
+	}
+
+}
+
+/*
+ * ac97_recmask_io
+ *
+ * Read or write the record source.
+ */
+static int ep93xx_read_recsource(void)
+{
+	unsigned int val;
+
+	/* read it from the card */
+	val = peek(AC97_1A_RECORD_SELECT);
+
+	DPRINTK("ac97_codec: ac97 recmask to set to 0x%04x\n", val);
+
+	return (1 << ac97_rm2oss[val & 0x07]);
+}
+
+static int ep93xx_set_recsource(int mask)
+{
+	unsigned int val;
+
+	/* Arg contains a bit for each recording source */
+	if (mask == 0) {
+		return 0;
+	}
+
+	mask &= AC97_RECORD_MASK;
+
+	if (mask == 0) {
+		return -EINVAL;
+	}
+
+	/*
+	 * May have more than one bit set.  So clear out currently selected
+	 * record source value first (AC97 supports only 1 input)
+	 */
+	val = (1 << ac97_rm2oss[peek(AC97_1A_RECORD_SELECT) & 0x07]);
+	if (mask != val)
+		mask &= ~val;
+
+	val = ffs(mask);
+	val = ac97_oss_rm[val - 1];
+	val |= val << 8;	/* set both channels */
+
+	DPRINTK("ac97_codec: setting ac97 recmask to 0x%04x\n", val);
+
+	poke(AC97_1A_RECORD_SELECT, val);
+
+	return 0;
+}
+
+static int ep93xx_mixer_open(struct inode *inode, struct file *file)
+{
+	file->private_data = &ep93xx_ac97_hw;
+	return 0;
+}
+
+static int ep93xx_mixer_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int
+ep93xx_mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+	int val, nr;
+
+	struct audio_hw_t *hw = (struct audio_hw_t *)file->private_data;
+
+	DPRINTK("ep93xx_mixer_ioctl - enter.  IOC_TYPE is %c \n",
+		_IOC_TYPE(cmd));
+
+	if (cmd == SOUND_MIXER_INFO) {
+		mixer_info info;
+		strncpy(info.id, "CS4202", sizeof(info.id));
+		strncpy(info.name, "Cirrus CS4202", sizeof(info.name));
+		info.modify_counter = hw->modcnt;
+		if (copy_to_user((void *)arg, &info, sizeof(info))) {
+			return -EFAULT;
+		}
+		return 0;
+	}
+	if (cmd == SOUND_OLD_MIXER_INFO) {
+		_old_mixer_info info;
+		strncpy(info.id, "CS4202", sizeof(info.id));
+		strncpy(info.name, "Cirrus CS4202", sizeof(info.name));
+		if (copy_to_user((void *)arg, &info, sizeof(info))) {
+			return -EFAULT;
+		}
+		return 0;
+	}
+
+	if ((_IOC_TYPE(cmd) != 'M') || (_SIOC_SIZE(cmd) != sizeof(int)))
+		return -EINVAL;
+
+	if (cmd == OSS_GETVERSION)
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	nr = _IOC_NR(cmd);
+
+	if (_SIOC_DIR(cmd) == _SIOC_READ) {
+		switch (nr) {
+		case SOUND_MIXER_RECSRC:
+			/* Read the current record source */
+			val = ep93xx_read_recsource();
+			break;
+
+		case SOUND_MIXER_DEVMASK:
+			/* give them the supported mixers */
+			val = codec_supported_mixers;
+			break;
+
+		case SOUND_MIXER_RECMASK:
+			/* Arg contains a bit for each supported recording source */
+			val = AC97_RECORD_MASK;
+			break;
+
+		case SOUND_MIXER_STEREODEVS:
+			/* Mixer channels supporting stereo */
+			val = AC97_STEREO_MASK;
+			break;
+
+		case SOUND_MIXER_CAPS:
+			val = SOUND_CAP_EXCL_INPUT;
+			break;
+
+		default:
+			if (!supported_mixer(nr))
+				return -EINVAL;
+
+			val = guiOSS_Volume[nr];
+			break;
+
+		}		/* switch */
+
+		return put_user(val, (int *)arg);
+	}
+
+	if (_SIOC_DIR(cmd) == (_SIOC_WRITE | _SIOC_READ)) {
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+
+		switch (nr) {
+		case SOUND_MIXER_RECSRC:
+			return ep93xx_set_recsource(val);
+
+		default:
+			if (!supported_mixer(nr))
+				return -EINVAL;
+
+			ep93xx_set_volume(nr, val);
+			hw->modcnt++;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static struct file_operations ep93xx_mixer_fops = {
+      owner:THIS_MODULE,
+      llseek:no_llseek,
+      ioctl:ep93xx_mixer_ioctl,
+      open:ep93xx_mixer_open,
+      release:ep93xx_mixer_release,
+};
+
+/*
+ * Audio interface
+ */
+static void ep93xx_audio_init(void *dummy)
+{
+	DPRINTK("ep93xx_audio_init - enter\n");
+
+	/*
+	 * Init the controller, enable the ac-link.
+	 * Initialize the codec.
+	 */
+	ep93xx_init_ac97_controller();
+	ep93xx_init_ac97_codec();
+
+#ifdef DEBUG
+	ep93xx_dump_ac97_regs();
+#endif
+
+	DPRINTK("ep93xx_audio_init - EXIT\n");
+}
+
+static int ep93xx_audio_ioctl(struct inode *inode, struct file *file,
+			      uint cmd, ulong arg)
+{
+	struct audio_state_t *state =
+	    (struct audio_state_t *)file->private_data;
+	struct audio_stream_t *os = state->output_stream;
+	struct audio_stream_t *is = state->input_stream;
+	long val;
+	int ret = 0;
+
+	/*
+	 * These are platform dependent ioctls which are not handled by the
+	 * generic ep93xx-audio module.
+	 */
+	switch (cmd) {
+	case SNDCTL_DSP_SPEED:
+
+		DPRINTK("ep93xx_audio_ioctl - SNDCTL_DSP_SPEED\n");
+
+		if (get_user(val, (int *)arg)) {
+			return -EFAULT;
+		}
+
+		if ((file->f_mode & FMODE_WRITE) && (val != os->sample_rate)) {
+			ep93xx_set_samplerate(os, val);
+		}
+		if ((file->f_mode & FMODE_READ) && (val != is->sample_rate)) {
+			ep93xx_set_samplerate(is, val);
+		}
+
+		return put_user(val, (long *)arg);
+
+	case SOUND_PCM_READ_RATE:
+		DPRINTK("ep93xx_audio_ioctl - SOUND_PCM_READ_RATE\n");
+		if (file->f_mode & FMODE_WRITE) {
+			return put_user(os->sample_rate, (long *)arg);
+		}
+		return put_user(is->sample_rate, (long *)arg);
+
+	default:
+		DPRINTK("ep93xx_audio_ioctl-->ep93xx_mixer_ioctl\n");
+		/* Maybe this is meant for the mixer (As per OSS Docs) */
+		return ep93xx_mixer_ioctl(inode, file, cmd, arg);
+	}
+
+	return ret;
+}
+
+static int ep93xx_audio_open(struct inode *inode, struct file *file)
+{
+	DPRINTK("ep93xx_audio_open\n");
+	return ep93xx_audio_attach(inode, file, &ac97_audio_state0);
+}
+
+/*
+ * Missing fields of this structure will be patched with the call
+ * to ep93xx_audio_attach().
+ */
+static struct file_operations ep93xx_audio_fops = {
+      open:ep93xx_audio_open,
+      owner:THIS_MODULE
+};
+
+static int audio_dev_id, mixer_dev_id;
+
+static int __init ep93xx_ac97_init(void)
+{
+	DPRINTK("ep93xx_ac97_init - enter\n");
+
+	// KERNEL2.4
+	sema_init(&ac97_audio_state0.sem, 1);
+
+	/*
+	 * Enable audio early on, give the DAC time to come up.
+	 */
+	ep93xx_audio_init(0);
+
+	/*
+	 * Register devices using sound_core.c's devfs stuff
+	 */
+	audio_dev_id = register_sound_dsp(&ep93xx_audio_fops, -1);
+	if (audio_dev_id < 0) {
+		DPRINTK
+		    (" ep93xx_ac97_init: register_sound_dsp failed for dsp.\n");
+		return -ENODEV;
+	}
+
+	mixer_dev_id = register_sound_mixer(&ep93xx_mixer_fops, -1);
+	if (mixer_dev_id < 0) {
+		DPRINTK
+		    (" ep93xx_ac97_init: register_sound_dsp failed for mixer.\n");
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "EP93xx Ac97 audio support initialized.\n");
+	return 0;
+}
+
+static void __exit ep93xx_ac97_exit(void)
+{
+	unregister_sound_dsp(audio_dev_id);
+	unregister_sound_mixer(mixer_dev_id);
+}
+
+module_init(ep93xx_ac97_init);
+module_exit(ep93xx_ac97_exit);
+
+MODULE_DESCRIPTION("Audio driver for the Cirrus EP93xx Ac97 controller.");
+MODULE_LICENSE("GPL");
+/* EXPORT_NO_SYMBOLS; */
diff --git a/sound/oss/ep93xx-audio.c b/sound/oss/ep93xx-audio.c
new file mode 100644
index 0000000..7e00d6d
--- /dev/null
+++ b/sound/oss/ep93xx-audio.c
@@ -0,0 +1,3821 @@
+/*
+ * ep93xx-audio.c
+ *
+ * Common audio handling for the Cirrus EP93xx processor.
+ *
+ * Copyright (c) 2003 Cirrus Logic Corp.
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ *
+ * Taken from sa1100-audio.c
+ *
+ * This module handles the generic buffering/DMA/mmap audio interface for
+ * codecs connected to the EP93xx chip.  All features depending on specific
+ * hardware implementations like supported audio formats or samplerates are
+ * relegated to separate specific modules.
+ *
+ *
+ * History:
+ *
+ * 2000-05-21	Nicolas Pitre	Initial release.
+ *
+ * 2000-06-10	Erik Bunce	Add initial poll support.
+ *
+ * 2000-08-22	Nicolas Pitre	Removed all DMA stuff. Now using the
+ * 				generic SA1100 DMA interface.
+ *
+ * 2000-11-30	Nicolas Pitre	- Validation of opened instances;
+ * 				- Power handling at open/release time instead
+ * 				  of driver load/unload;
+ *
+ * 2001-06-03	Nicolas Pitre	Made this file a separate module, based on
+ * 				the former sa1100-uda1341.c driver.
+ *
+ * 2001-07-22	Nicolas Pitre	- added mmap() and realtime support
+ * 				- corrected many details to better comply
+ * 				  with the OSS API
+ *
+ * 2001-10-19	Nicolas Pitre	- brought DMA registration processing
+ * 				  into this module for better ressource
+ * 				  management.  This also fixes a bug
+ * 				  with the suspend/resume logic.
+ *
+ * 2003-04-04   Adapted for EP93xx I2S/Ac97 audio.
+ *
+ * 2004-04-23	Added support for multiple stereo streams.
+ *
+ * 2005-05-11	Manfred Gruber - Ported this from Cirrus Logic Virgo 1-4-3 release
+ * 				 to Kernel 2.6.11.X
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/kernel_stat.h>
+#include <asm/arch/dma.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/uaccess.h>
+//#include <asm/fiq.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/irqs.h>
+
+#include "ep93xx-audio.h"
+
+#undef DEBUG
+//#define DEBUG 1
+#ifdef DEBUG
+#define DPRINTK( fmt, arg... )  printk( fmt, ##arg )
+#else
+#define DPRINTK( fmt, arg... )
+#endif
+
+/* Mostly just prints what ioctls got called */
+//#define DEBUG 1
+#ifdef DEBUG
+#define DPRINTK_IOCTL( fmt, arg... )  printk( fmt, ##arg )
+#else
+#define DPRINTK_IOCTL( fmt, arg... )
+#endif
+
+/*
+ * Experiencing gaps in your audio?  Try upping the AUDIO_NBFRAGS_DEFAULT!
+ * Experiencing memory problems? Try lowering them. 
+ * DMA memory space is precious and rare on ARM.
+ * 
+ */
+
+//
+#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
+#define AUDIO_NBFRAGS_DEFAULT	31
+#define AUDIO_FRAGSIZE_DEFAULT	65536
+#define AUDIO_NBFRAGS_MAX	31
+#else
+#ifdef CONFIG_SOUND_EP93XX_AC97
+// Values changed from KERNEL2.4
+#define AUDIO_NBFRAGS_DEFAULT	4
+#define AUDIO_FRAGSIZE_DEFAULT	8192	// max is 65536
+#define AUDIO_NBFRAGS_MAX	4
+#else
+#define AUDIO_NBFRAGS_DEFAULT	16
+#define AUDIO_FRAGSIZE_DEFAULT	32768	// max is 65536
+#define AUDIO_NBFRAGS_MAX	16
+#endif
+#endif
+
+/*
+ * NEXT_BUF
+ *
+ * Translates to:
+ * 		stream->dma_buffer_index++;
+ * 		stream->dma_buffer_index %= stream->nbfrags;
+ *		stream->dma_buffer = stream->buffers + stream->dma_buffer_index;
+ *
+ * So stream->dma_buffer always points to the stream->dma_buffer_index-nth element
+ * of stream->buffers.
+ */
+#define NEXT_BUF(_s_,_b_) { \
+	(_s_)->_b_##_index++; \
+	(_s_)->_b_##_index %= (_s_)->nbfrags; \
+	(_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_index; }
+
+#define AUDIO_ACTIVE(state)	((state)->rd_ref || (state)->wr_ref)
+
+/* Function prototypes */
+static __inline__ int copy_to_user_with_conversion
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount);
+
+static __inline__ int copy_from_user_with_conversion
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount);
+
+static void audio_dma_start(struct audio_state_t *state,
+			    struct audio_stream_t *stream);
+static void audio_dma_pause(struct audio_state_t *state,
+			    struct audio_stream_t *stream);
+static void audio_prime_dma(struct audio_state_t *state,
+			    struct audio_stream_t *stream);
+
+#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
+#define DMA_ADD_BUFFER		pio_add_buffer
+#define DMA_CONFIG		pio_config
+#define DMA_FLUSH		pio_flush
+#define DMA_FREE		pio_free
+#define DMA_GET_POSITION	pio_get_position
+#define DMA_PAUSE		pio_pause
+#define DMA_REMOVE_BUFFER	pio_remove_buffer
+#define DMA_REQUEST		pio_request
+#define DMA_START		pio_start
+#else
+#define DMA_ADD_BUFFER		ep93xx_dma_add_buffer
+#define DMA_CONFIG		ep93xx_dma_config
+#define DMA_FLUSH		ep93xx_dma_flush
+#define DMA_FREE		ep93xx_dma_free
+#define DMA_GET_POSITION	ep93xx_dma_get_position
+#define DMA_PAUSE		ep93xx_dma_pause
+#define DMA_REMOVE_BUFFER	ep93xx_dma_remove_buffer
+#define DMA_REQUEST		ep93xx_dma_request
+#define DMA_START		ep93xx_dma_start
+#endif
+
+#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
+/*
+ * The maximum number of buffers accepted by the PIO interface.
+ */
+#define PIO_MAX_BUFFERS		32
+
+/*
+ * A convenienced macro to advance from one buffer to the next.
+ */
+#define PIO_NEXT(x)		(((x) + 1) % PIO_MAX_BUFFERS)
+
+/*
+ * A structure to remember information about a buffer.
+ */
+struct pio_buffer {
+	unsigned int source;
+	unsigned int pos;
+	unsigned int size;
+	int buf_id;
+};
+
+/*
+ * A structure to remember information about a stream.
+ */
+struct pio_stream {
+	int assigned;
+	struct pio_buffer queue[PIO_MAX_BUFFERS];
+	ep93xx_dma_dev_t device;
+	int first;
+	int cur;
+	int last;
+	int bytes;
+	int pause;
+	dma_callback callback;
+	unsigned int user_data;
+};
+
+/*
+ * The twelve streams that we can handle.
+ */
+static struct pio_stream pio_streams[12];
+
+/*
+ * Reference counts for the two interrupt handlers.
+ */
+static int pio_irq_ref_count[2];
+
+/*
+ * The registers that enable the three I2S transmitters.
+ */
+static const unsigned int i2s_txenable[3] = {
+	I2STX0En,
+	I2STX1En,
+	I2STX2En
+};
+
+/*
+ * The flag that indicates a FIFO full condition on the three I2S transmitters.
+ */
+static const unsigned int i2s_txflag[3] = {
+	TX0_FIFO_FULL,
+	TX1_FIFO_FULL,
+	TX2_FIFO_FULL
+};
+
+/*
+ * The register that contains the left channel data for the three I2S
+ * transmitters.
+ */
+static const unsigned int i2s_tx_lft[3] = {
+	I2STX0Lft,
+	I2STX1Lft,
+	I2STX2Lft
+};
+
+/*
+ * The register that contains the right channel data for the three I2S
+ * transmitters.
+ */
+static const unsigned int i2s_tx_rt[3] = {
+	I2STX0Rt,
+	I2STX1Rt,
+	I2STX2Rt
+};
+
+/*
+ * The registers that enable the three I2S receivers.
+ */
+static const unsigned int i2s_rxenable[3] = {
+	I2SRX0En,
+	I2SRX1En,
+	I2SRX2En
+};
+
+/*
+ * The flag that indicates a FIFO empty condition on the three I2S receivers.
+ */
+static const unsigned int i2s_rxflag[3] = {
+	RX0_FIFO_EMPTY,
+	RX1_FIFO_EMPTY,
+	RX2_FIFO_EMPTY
+};
+
+/*
+ * The register that contains the left channel data for the three I2S
+ * receivers.
+ */
+static const unsigned int i2s_rx_lft[3] = {
+	I2SRX0Lft,
+	I2SRX1Lft,
+	I2SRX2Lft
+};
+
+/*
+ * The register that contains the right channel data for the three I2S
+ * receivers.
+ */
+static const unsigned int i2s_rx_rt[3] = {
+	I2SRX0Rt,
+	I2SRX1Rt,
+	I2SRX2Rt
+};
+
+/*
+ * The registers that contain the status for the three AC'97 transceivers.
+ */
+static const unsigned int ac97_status[3] = {
+	AC97SR1,
+	AC97SR2,
+	AC97SR3
+};
+
+/*
+ * The registers that contain the audio data for the three AC'97 transceivers.
+ */
+static const unsigned int ac97_data[3] = {
+	AC97DR1,
+	AC97DR2,
+	AC97DR3
+};
+
+/*
+ * The registers that control the three AC'97 transmitters.
+ */
+static const unsigned int ac97_txctrl[3] = {
+	AC97TXCR1,
+	AC97TXCR2,
+	AC97TXCR3
+};
+
+/*
+ * The registers that control the three AC'97 receivers.
+ */
+static const unsigned int ac97_rxctrl[3] = {
+	AC97RXCR1,
+	AC97RXCR2,
+	AC97RXCR3
+};
+
+/*
+ * The descriptor for our FIQ handler.
+ */
+static struct fiq_handler fh = { NULL, "pio_audio", NULL, NULL };
+
+/*
+ * Stack space for our FIQ handler.
+ */
+static unsigned char fiq_stack[1024];
+
+/*
+ * References to the labels in the inline assembly.
+ */
+extern void i2s_fiq_begin;
+extern void i2s_fiq_end;
+extern void ac97_fiq_begin;
+extern void ac97_fiq_end;
+
+/*
+ * The FIQ handler for I2S audio.  This stub is copied into the vector area and
+ * simply calls the I2S interrupt handler.
+ */
+void pio_i2s_fiq_handler(void)
+{
+	__asm__ __volatile__("\n\
+i2s_fiq_begin:\n\
+		stmdb	r13!, {r0-r7, lr}\n\
+		ldr	r0, =pio_i2s_irq_handler\n\
+		mov	lr, pc\n\
+		mov	pc, r0\n\
+		ldmia	r13!, {r0-r7, lr}\n\
+		subs	pc, lr, #4\n\
+		.ltorg\n\
+i2s_fiq_end:");
+}
+
+/*
+ * The FIQ handler for AC'97 audio.  This stub is copied into the vector area
+ * and simply calls the AC'97 interrupt handler.
+ */
+void pio_ac97_fiq_handler(void)
+{
+	__asm__ __volatile__("\n\
+ac97_fiq_begin:\n\
+		stmdb	r13!, {r0-r7, lr}\n\
+		ldr	r0, =pio_ac97_irq_handler\n\
+		mov	lr, pc\n\
+		mov	pc, r0\n\
+		ldmia	r13!, {r0-r7, lr}\n\
+		subs	pc, lr, #4\n\
+		.ltorg\n\
+ac97_fiq_end:");
+}
+
+/*
+ * The interrupt handler for I2S audio.
+ */
+static void pio_i2s_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pio_stream *p;
+	struct pio_buffer *b;
+	int idx;
+
+	/*
+	 * Increment the count of interrupts.
+	 */
+	kstat.irqs[smp_processor_id()][IRQ_SAI]++;
+
+	/*
+	 * Loop through the three transmitters.
+	 */
+	for (idx = 0; idx < 3; idx++) {
+		/*
+		 * Do nothing if this transmitter is not enabled.
+		 */
+		if (!inl(i2s_txenable[idx]))
+			continue;
+
+		/*
+		 * Get a pointer to this stream's structure.
+		 */
+		p = &pio_streams[idx];
+
+		/*
+		 * Loop while the transmit FIFO is not full.
+		 */
+		while (!(inl(I2SGlSts) & i2s_txflag[idx])) {
+			/*
+			 * If the stream is not assigned, is paused, or has no
+			 * data, then write out silence.
+			 */
+			if (!p->assigned || p->pause || (p->cur == p->last)) {
+				outl(0, i2s_tx_lft[idx]);
+				outl(0, i2s_tx_rt[idx]);
+			} else {
+				/*
+				 * Get a pointer to the current buffer.
+				 */
+				b = &p->queue[p->cur];
+
+				/*
+				 * Write out the next sample.
+				 */
+				outl(*(unsigned long *)b->source,
+				     i2s_tx_lft[idx]);
+				outl(*(unsigned long *)(b->source + 4),
+				     i2s_tx_rt[idx]);
+
+				/*
+				 * Increment past the next sample.
+				 */
+				b->source += 8;
+				b->pos += 8;
+
+				/*
+				 * See if the buffer has been consumed.
+				 */
+				if (b->pos == b->size) {
+					/*
+					 * Increment the count of bytes
+					 * transmitted.
+					 */
+					p->bytes += b->size;
+
+					/*
+					 * Go to the next buffer.
+					 */
+					p->cur = PIO_NEXT(p->cur);
+
+					/*
+					 * Call the callback if there is one.
+					 */
+					if (p->callback)
+						p->callback(NFB, p->device,
+							    p->user_data);
+				}
+			}
+		}
+	}
+
+	/*
+	 * Loop through the three receivers.
+	 */
+	for (idx = 0; idx < 3; idx++) {
+		/*
+		 * Do nothing if this receiver is not enabled.
+		 */
+		if (!inl(i2s_rxenable[idx]))
+			continue;
+
+		/*
+		 * Get a pointer to this stream's structure.
+		 */
+		p = &pio_streams[idx + 3];
+
+		/*
+		 * Loop while the receive FIFO is not empty.
+		 */
+		while (!(inl(I2SGlSts) & i2s_rxflag[idx])) {
+			/*
+			 * If the stream is not assigned, is paused, or has no
+			 * buffer space, then throw away the data.
+			 */
+			if (!p->assigned || p->pause || (p->cur == p->last)) {
+				inl(i2s_rx_lft[idx]);
+				inl(i2s_rx_rt[idx]);
+			} else {
+				/*
+				 * Get a pointer to the current buffer.
+				 */
+				b = &p->queue[p->cur];
+
+				/*
+				 * Read in the next sample.
+				 */
+				*(unsigned long *)b->source =
+				    inl(i2s_rx_lft[idx]);
+				*(unsigned long *)(b->source + 4) =
+				    inl(i2s_rx_rt[idx]);
+
+				/*
+				 * Increment past the next sample.
+				 */
+				b->source += 8;
+				b->pos += 8;
+
+				/*
+				 * See if the buffer has been consumed.
+				 */
+				if (b->pos == b->size) {
+					/*
+					 * Increment the count of bytes
+					 * received.
+					 */
+					p->bytes += b->size;
+
+					/*
+					 * Go to the next buffer.
+					 */
+					p->cur = PIO_NEXT(p->cur);
+
+					/*
+					 * Call the callback if there is one.
+					 */
+					if (p->callback)
+						p->callback(NFB, p->device,
+							    p->user_data);
+				}
+			}
+		}
+	}
+
+	/*
+	 * Clear any overrun or underrun conditions that may exist.
+	 */
+	outl(0, I2SGlSts);
+}
+
+/*
+ * The interrupt handler for AC'97 audio.
+*/
+static void pio_ac97_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pio_stream *p;
+	struct pio_buffer *b;
+	int idx, cm;
+
+	/*
+	 * Increment the count of interrupts.
+	 */
+	kstat.irqs[smp_processor_id()][IRQ_AAC]++;
+
+	/*
+	 * Loop through the three transmitters.
+	 */
+	for (idx = 0; idx < 3; idx++) {
+		/*
+		 * Do nothing if this transmitter is not enabled.
+		 */
+		if (!(inl(ac97_txctrl[idx]) & AC97TXCR_TEN))
+			continue;
+
+		/*
+		 * Get a pointer to this stream's structure.
+		 */
+		p = &pio_streams[idx + 6];
+
+		/*
+		 * See if this transmitter is in compact mode.
+		 */
+		cm = inl(ac97_txctrl[idx]) & AC97TXCR_CM;
+
+		/*
+		 * Loop while the transmit FIFO is not full.
+		 */
+		while (!(inl(ac97_status[idx]) & AC97SR_TXFF)) {
+			/*
+			 * If the stream is not assigned, is paused, or has no
+			 * data, then write out silence.
+			 */
+			if (!p->assigned || p->pause || (p->cur == p->last)) {
+				outl(0, ac97_data[idx]);
+				if (!cm)
+					outl(0, ac97_data[idx]);
+			} else {
+				/*
+				 * Get a pointer to the current buffer.
+				 */
+				b = &p->queue[p->cur];
+
+				/*
+				 * Write out the next sample.
+				 */
+				outl(*(unsigned long *)b->source,
+				     ac97_data[idx]);
+
+				/*
+				 * Increment past the next sample.
+				 */
+				b->source += 4;
+				b->pos += 4;
+
+				/*
+				 * Write another sample if we are not in
+				 * compact mode.
+				 */
+				if (!cm) {
+					outl(*(unsigned long *)b->source,
+					     ac97_data[idx]);
+					b->source += 4;
+					b->pos += 4;
+				}
+
+				/*
+				 * See if the buffer has been consumed.
+				 */
+				if (b->pos == b->size) {
+					/*
+					 * Increment the count of bytes
+					 * transmitted.
+					 */
+					p->bytes += b->size;
+
+					/*
+					 * Go to the next buffer.
+					 */
+					p->cur = PIO_NEXT(p->cur);
+
+					/*
+					 * Call the callback if there is one.
+					 */
+					if (p->callback)
+						p->callback(NFB, p->device,
+							    p->user_data);
+				}
+			}
+		}
+	}
+
+	/*
+	 * Loop through the three receivers.
+	 */
+	for (idx = 0; idx < 3; idx++) {
+		/*
+		 * Do nothing if this receiver is not enabled.
+		 */
+		if (!(inl(ac97_rxctrl[idx]) & AC97RXCR_REN))
+			continue;
+
+		/*
+		 * Get a pointer to this stream's structure.
+		 */
+		p = &pio_streams[idx + 9];
+
+		/*
+		 * See if this receiver is in compact mode.
+		 */
+		cm = inl(ac97_rxctrl[idx]) & AC97RXCR_CM;
+
+		/*
+		 * Loop while the receive FIFO is not empty.
+		 */
+		while (!(inl(ac97_status[idx]) & AC97SR_RXFE)) {
+			/*
+			 * If the stream is not assigned, is paused, or has no
+			 * buffer space, then throw away the data.
+			 */
+			if (!p->assigned || p->pause || (p->cur == p->last)) {
+				inl(ac97_data[idx]);
+				if (!cm)
+					inl(ac97_data[idx]);
+			} else {
+				/*
+				 * Get a pointer to the current buffer.
+				 */
+				b = &p->queue[p->cur];
+
+				/*
+				 * Read in the next sample.
+				 */
+				*(unsigned long *)b->source =
+				    inl(ac97_data[idx]);
+
+				/*
+				 * Increment past the next sample.
+				 */
+				b->source += 4;
+				b->pos += 4;
+
+				/*
+				 * Read another sample if we are not in compact
+				 * mode.
+				 */
+				if (!cm) {
+					*(unsigned long *)b->source =
+					    inl(ac97_data[idx]);
+					b->source += 4;
+					b->pos += 4;
+				}
+
+				/*
+				 * See if the buffer has been consumed.
+				 */
+				if (b->pos == b->size) {
+					/*
+					 * Increment the count of bytes
+					 * received.
+					 */
+					p->bytes += b->size;
+
+					/*
+					 * Go to the next buffer.
+					 */
+					p->cur = PIO_NEXT(p->cur);
+
+					/*
+					 * Call the callback if there is one.
+					 */
+					if (p->callback)
+						p->callback(NFB, p->device,
+							    p->user_data);
+				}
+			}
+		}
+	}
+}
+
+/*
+ * Add a buffer to a PIO stream.
+ */
+static int
+pio_add_buffer(int handle, unsigned int source, unsigned int dest,
+	       unsigned int size, unsigned int last, unsigned int buf_id)
+{
+	struct pio_stream *p;
+	struct pio_buffer *b;
+
+	/*
+	 * Get a pointer to this stream's structure.
+	 */
+	p = &pio_streams[handle];
+
+	/*
+	 * Fail if there is not space for another buffer.
+	 */
+	if (PIO_NEXT(p->last) == p->first)
+		return -1;
+
+	/*
+	 * Get a pointer to the next buffer.
+	 */
+	b = &p->queue[p->last];
+
+	/*
+	 * Save the information about this buffer.
+	 */
+	b->source = (unsigned int)phys_to_virt(source);
+	b->pos = 0;
+	b->size = size;
+	b->buf_id = buf_id;
+
+	/*
+	 * Increment the last pointer.
+	 */
+	p->last = PIO_NEXT(p->last);
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+
+/*
+ * Configure a PIO stream.
+ */
+static int
+pio_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
+	   dma_callback callback, unsigned int user_data)
+{
+	struct pio_stream *p;
+
+	/*
+	 * Get a pointer to this stream's structure.
+	 */
+	p = &pio_streams[handle];
+
+	/*
+	 * This puts the stream into pause mode.
+	 */
+	p->pause = 1;
+
+	/*
+	 * Save the callback function information.
+	 */
+	p->callback = callback;
+	p->user_data = user_data;
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+
+/*
+ * Flush all data from a PIO stream.
+ */
+static int pio_flush(int handle)
+{
+	struct pio_stream *p;
+
+	/*
+	 * Get a pointer to this stream's structure.
+	 */
+	p = &pio_streams[handle];
+
+	/*
+	 * Disable interrupts.
+	 */
+	clf();
+
+	/*
+	 * Blast all buffer information from this stream.
+	 */
+	p->first = 0;
+	p->cur = 0;
+	p->last = 0;
+	p->bytes = 0;
+
+	/*
+	 * Enable interrupts.
+	 */
+	stf();
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+
+/*
+ * Free a PIO stream.
+ */
+static int pio_free(int handle)
+{
+	/*
+	 * See if this is a I2S or AC'97 stream.
+	 */
+	if (handle < 6) {
+		/*
+		 * Decrement the I2S reference count.
+		 */
+		pio_irq_ref_count[0]--;
+
+		/*
+		 * See if the reference count is now zero.
+		 */
+		if (pio_irq_ref_count[0] == 0) {
+			/*
+			 * Make the I2S interrupt an IRQ instead of a FIQ.
+			 */
+			outl(inl(VIC1INTSELECT) & ~(1 << (IRQ_SAI - 32)),
+			     VIC1INTSELECT);
+
+			/*
+			 * Disable I2S interrupts in the I2S block.
+			 */
+			outl(0, I2STXCtrl);
+			outl(0, I2SRXCtrl);
+
+			/*
+			 * Release the I2S interrupt.
+			 */
+			free_irq(IRQ_SAI, (void *)&pio_i2s_irq_handler);
+
+			/*
+			 * Release the FIQ.
+			 */
+			release_fiq(&fh);
+		}
+	} else {
+		/*
+		 * Decrement the AC'97 reference count.
+		 */
+		pio_irq_ref_count[1]--;
+
+		/*
+		 * See if the reference count is now zero.
+		 */
+		if (pio_irq_ref_count[1] == 0) {
+			/*
+			 * Make the AC'97 interrupt an IRQ instead of a FIQ.
+			 */
+			outl(inl(VIC0INTSELECT) & ~(1 << IRQ_AAC),
+			     VIC0INTSELECT);
+
+			/*
+			 * Release the AC'97 interrupt.
+			 */
+			free_irq(IRQ_AAC, (void *)&pio_ac97_irq_handler);
+
+			/*
+			 * Release the FIQ.
+			 */
+			release_fiq(&fh);
+		}
+	}
+
+	/*
+	 * Mark this stream as unassigned.
+	 */
+	pio_streams[handle].assigned = 0;
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+
+/*
+ * Get the current position in a PIO stream.
+ */
+static int
+pio_get_position(int handle, unsigned int *buf_id, unsigned int *total,
+		 unsigned int *current_frac)
+{
+	struct pio_stream *p;
+	struct pio_buffer *b;
+
+	/*
+	 * Get a pointer to this stream's structure.
+	 */
+	p = &pio_streams[handle];
+
+	/*
+	 * Disable interrupts.
+	 */
+	clf();
+
+	/*
+	 * Get a pointer to the current buffer.
+	 */
+	b = &p->queue[p->cur];
+
+	/*
+	 * If the buffer is is being requested, then return it.
+	 */
+	if (buf_id)
+		*buf_id = b->buf_id;
+
+	/*
+	 * If the total bytes transferred is being requested, then return it.
+	 */
+	if (total)
+		*total = p->bytes;
+
+	/*
+	 * If the bytes transferred from the current buffer is being requested,
+	 * then return it.
+	 */
+	if (current_frac)
+		*current_frac = b->size - b->pos;
+
+	/*
+	 * Enable interrupts.
+	 */
+	stf();
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+
+/*
+ * Pause a PIO stream.
+ */
+static int pio_pause(int handle, unsigned int channels, unsigned int *handles)
+{
+	struct pio_stream *p;
+
+	/*
+	 * Get a pointer to this stream's structure.
+	 */
+	p = &pio_streams[handle];
+
+	/*
+	 * Pause the stream.
+	 */
+	p->pause = 1;
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+
+/*
+ * Remove a consumed buffer from a PIO stream.
+ */
+static int pio_remove_buffer(int handle, unsigned int *buf_id)
+{
+	struct pio_stream *p;
+
+	/*
+	 * Get a pointer to this stream's structure.
+	 */
+	p = &pio_streams[handle];
+
+	/*
+	 * Fail if there are not consumed buffers.
+	 */
+	if (p->first == p->cur)
+		return -1;
+
+	/*
+	 * Return the ID of the next fully consumed buffer.
+	 */
+	*buf_id = p->queue[p->first].buf_id;
+
+	/*
+	 * Increment the first pointer.
+	 */
+	p->first = PIO_NEXT(p->first);
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+
+/*
+ * Request a PIO stream.
+ */
+static int
+pio_request(int *handle, const char *device_id, ep93xx_dma_dev_t device)
+{
+	struct pio_stream *p;
+	struct pt_regs regs;
+	int idx, error;
+
+	/*
+	 * Get the stream index from the DMA device we are emulating.
+	 */
+	switch (device) {
+	case DMATx_I2S1:
+		idx = 0;
+		break;
+	case DMATx_I2S2:
+		idx = 1;
+		break;
+	case DMATx_I2S3:
+		idx = 2;
+		break;
+	case DMARx_I2S1:
+		idx = 3;
+		break;
+	case DMARx_I2S2:
+		idx = 4;
+		break;
+	case DMARx_I2S3:
+		idx = 5;
+		break;
+	case DMATx_AAC1:
+		idx = 6;
+		break;
+	case DMATx_AAC2:
+		idx = 7;
+		break;
+	case DMATx_AAC3:
+		idx = 8;
+		break;
+	case DMARx_AAC1:
+		idx = 9;
+		break;
+	case DMARx_AAC2:
+		idx = 10;
+		break;
+	case DMARx_AAC3:
+		idx = 11;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	/*
+	 * Get a pointer to this stream's structure.
+	 */
+	p = &pio_streams[idx];
+
+	/*
+	 * Fail if this stream is already assigned.
+	 */
+	if (p->assigned)
+		return -EBUSY;
+
+	/*
+	 * Initialize this stream.
+	 */
+	memset(p->queue, 0, sizeof(p->queue));
+	p->device = device;
+	p->first = 0;
+	p->cur = 0;
+	p->last = 0;
+	p->bytes = 0;
+	p->pause = 0;
+	p->callback = 0;
+	p->user_data = 0;
+
+	/*
+	 * Mark this stream as assigned.
+	 */
+	p->assigned = 1;
+
+	/*
+	 * See if this is a I2S or AC'97 stream.
+	 */
+	if (idx < 6) {
+		/*
+		 * If there is already a AC'97 stream in use, then do not allow
+		 * I2S streams.
+		 */
+		if (pio_irq_ref_count[1])
+			return -EBUSY;
+
+		/*
+		 * See if there is another I2S stream.
+		 */
+		if (pio_irq_ref_count[0] == 0) {
+			/*
+			 * Claim the FIQ handler.
+			 */
+			if (claim_fiq(&fh))
+				return -EBUSY;
+
+			/*
+			 * Request the I2S interrupt.
+			 */
+			error = request_irq(IRQ_SAI, pio_i2s_irq_handler,
+					    SA_INTERRUPT, "i2s",
+					    (void *)&pio_i2s_irq_handler);
+			if (error) {
+				release_fiq(&fh);
+				return error;
+			}
+
+			/*
+			 * Set the FIQ mode registers.
+			 */
+			regs.ARM_sp = (long)fiq_stack + sizeof(fiq_stack);
+			set_fiq_regs(&regs);
+
+			/*
+			 * Set the FIQ handler.
+			 */
+			set_fiq_handler(&i2s_fiq_begin,
+					&i2s_fiq_end - &i2s_fiq_begin);
+
+			/*
+			 * Make the I2S interrupt a FIQ instead of an IRQ.
+			 */
+			outl(inl(VIC1INTSELECT) | (1 << (IRQ_SAI - 32)),
+			     VIC1INTSELECT);
+
+			/*
+			 * Enable transmit half empty and receive half full
+			 * interrupts in the I2S block.
+			 */
+			outl(2, I2STXCtrl);
+			outl(2, I2SRXCtrl);
+		}
+
+		/*
+		 * Increment the I2S interrupt reference count.
+		 */
+		pio_irq_ref_count[0]++;
+	} else {
+		/*
+		 * If there is already a I2S stream in use, then do not allow
+		 * AC'97 streams.
+		 */
+		if (pio_irq_ref_count[0])
+			return -EBUSY;
+
+		/*
+		 * See if there is another AC'97 stream.
+		 */
+		if (pio_irq_ref_count[1] == 0) {
+			/*
+			 * Claim the FIQ handler.
+			 */
+			if (claim_fiq(&fh))
+				return -EBUSY;
+
+			/*
+			 * Request the AC'97 interrupt.
+			 */
+			error = request_irq(IRQ_AAC, pio_ac97_irq_handler,
+					    SA_INTERRUPT, "ac-97",
+					    (void *)&pio_ac97_irq_handler);
+			if (error) {
+				release_fiq(&fh);
+				return error;
+			}
+
+			/*
+			 * Set the FIQ mode registers.
+			 */
+			regs.ARM_sp = (long)fiq_stack + sizeof(fiq_stack);
+			set_fiq_regs(&regs);
+
+			/*
+			 * Set the FIQ handler.
+			 */
+			set_fiq_handler(&ac97_fiq_begin,
+					&ac97_fiq_end - &ac97_fiq_begin);
+
+			/*
+			 * Make the AC'97 interrupt a FIQ instead of an IRQ.
+			 */
+			outl(inl(VIC0INTSELECT) | (1 << IRQ_AAC),
+			     VIC0INTSELECT);
+		}
+
+		/*
+		 * Increment the AC'97 interrupt reference count.
+		 */
+		pio_irq_ref_count[1]++;
+	}
+
+	/*
+	 * Return a handle to this stream.
+	 */
+	*handle = idx;
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+
+/*
+ * Start a PIO stream.
+ */
+static int pio_start(int handle, unsigned int channels, unsigned int *handles)
+{
+	struct pio_stream *p;
+
+	/*
+	 * Get a pointer to this stream's structure.
+	 */
+	p = &pio_streams[handle];
+
+	/*
+	 * Start the stream.
+	 */
+	p->pause = 0;
+
+	/*
+	 * Success.
+	 */
+	return 0;
+}
+#endif
+
+/*
+ *  calculate_dma2usr_ratio_etc()
+ *
+ *  For audio playback, we convert samples of arbitrary format to be 32 bit
+ *  for our hardware. We're scaling a user buffer to a dma buffer.  So when
+ *  report byte counts, we scale them acording to the ratio of DMA sample
+ *  size to user buffer sample size.  When we report # of DMA fragments,
+ *  we don't scale that.  So:
+ *   - The fragment size the app sees  = (stream->fragsize/stream->dma2usr_ratio)
+ *   - The # of fragments the app sees = stream->nbfrags
+ *
+ *	User sample type can be stereo/mono/8/16/32 bit.
+ *  DMA sample type will be either CM (compact mode) where two 16 bit
+ *  samples together in a 32 bit word become a stereo sample or non-CM
+ *  where each channel gets a 32 bit word.
+ *
+ *  Any time usr sample type changes, we need to call this function.
+ *
+ *  Also adjust the size and number of dma fragments if sample size changed.
+ *
+ *  Input format       Input sample     Output sample size    ratio (out:in)
+ *  bits   channels    size (bytes)	CM   non-CM          CM   non-CM
+ *   8       mono          1		4      8            4:1   8:1
+ *   8      stereo         2		4      8            2:1   4:1
+ *   16      mono          2		4      8            2:1   4:1
+ *   16     stereo         4		4      8            1:1   2:1
+ *
+ *   24      mono          3		4      8             X    8:3 not a real case
+ *   24     stereo         6		4      8             X    8:6 not a real case
+ *   32      mono          4		4      8             X    2:1
+ *   32     stereo         8		4      8             X    1:1
+ *
+ */
+static void calculate_dma2usr_ratio_etc(struct audio_stream_t *stream)
+{
+	unsigned int dma_sample_size, user_sample_size;
+
+	if (stream->bCompactMode)
+		dma_sample_size = 4;	/* each stereo sample is 2 * 16 bits */
+	else
+		dma_sample_size = 8;	/* each stereo sample is 2 * 32 bits */
+
+	if (stream->audio_num_channels != 1) {
+		// If stereo 16 bit, user sample is 4 bytes.
+		// If stereo  8 bit, user sample is 2 bytes.
+		user_sample_size = stream->audio_stream_bitwidth / 4;
+	} else {
+		// If mono 16 bit, user sample is 2 bytes.
+		// If mono  8 bit, user sample is 1 bytes.
+		user_sample_size = stream->audio_stream_bitwidth / 8;
+	}
+
+	/*
+	 * dma2usr_ratio = (4 or 8) / (4, 2, or 1) = 8, 4, 2, or 1
+	 */
+	stream->dma2usr_ratio = dma_sample_size / user_sample_size;
+
+	DPRINTK(" samplesize: dma %d  user %d  dma/usr ratio  %d\n",
+		dma_sample_size, user_sample_size, stream->dma2usr_ratio);
+	DPRINTK
+	    (" requested: fragsize %d  num frags %d  total bytes %d  total samples %d\n",
+	     stream->requested_fragsize, stream->requested_nbfrags,
+	     stream->requested_fragsize * stream->requested_nbfrags,
+	     (stream->requested_fragsize * stream->requested_nbfrags) /
+	     user_sample_size);
+	DPRINTK
+	    (" usr      : fragsize %d  num frags %d  total bytes %d  total samples %d\n",
+	     (stream->fragsize / stream->dma2usr_ratio), stream->nbfrags,
+	     stream->fragsize * stream->nbfrags / stream->dma2usr_ratio,
+	     (stream->fragsize * stream->nbfrags) / (stream->dma2usr_ratio *
+						     user_sample_size));
+	DPRINTK
+	    (" dma:       fragsize %d  num frags %d  total bytes %d  total samples %d\n",
+	     stream->fragsize, stream->nbfrags,
+	     stream->fragsize * stream->nbfrags,
+	     (stream->fragsize * stream->nbfrags) / dma_sample_size);
+
+}
+
+/*
+ * audio_deallocate_buffers
+ *
+ * This function frees all buffers
+ */
+static void audio_deallocate_buffers(struct audio_state_t *state,
+				     struct audio_stream_t *stream)
+{
+	int frag, i;
+
+	DPRINTK("EP93xx - audio_deallocate_buffers\n");
+
+	/* ensure DMA won't run anymore */
+	audio_dma_pause(state, stream);
+	stream->active = 0;
+	stream->stopped = 0;
+
+	for (i = 0; i < stream->NumDmaChannels; i++)
+		DMA_FLUSH(stream->dmahandles[i]);
+
+	if (stream->buffers) {
+		for (frag = 0; frag < stream->nbfrags; frag++) {
+			if (!stream->buffers[frag].master) {
+				continue;
+			}
+			// KERNEL2.4
+			//consistent_free(stream->buffers[frag].start,
+			//              stream->buffers[frag].master,
+			//              stream->buffers[frag].dma_addr);
+			dma_free_coherent(NULL, stream->buffers[frag].master,
+					  stream->buffers[frag].start,
+					  stream->buffers[frag].dma_addr);
+
+		}
+
+		/*
+		 * Free the space allocated to the array of dma_buffer structs.
+		 */
+		kfree(stream->buffers);
+		stream->buffers = NULL;
+	}
+
+	stream->buffered_bytes_to_play = 0;
+	stream->dma_buffer_index = 0;
+	stream->dma_buffer = NULL;
+	stream->bytecount = 0;
+	stream->getptrCount = 0;
+	stream->fragcount = 0;
+
+	DPRINTK("EP93xx - audio_deallocate_buffers - EXIT\n");
+}
+
+/*
+ * audio_allocate_buffers
+ *
+ * This function allocates the buffer structure array and buffer data space
+ * according to the current number of fragments and fragment size.
+ * Note that the output_stream and input_stream structs are allocated
+ * in ep93xx-ac97.c or ep93xx-i2s.c.
+ */
+static int audio_allocate_buffers(struct audio_state_t *state,
+				  struct audio_stream_t *stream)
+{
+	int frag;
+	int dmasize = 0;
+	char *dmabuf = NULL;
+	dma_addr_t dmaphys = 0;
+	int buf_num = 0;
+
+	if (stream->buffers)
+		return -EBUSY;
+
+	DPRINTK("EP93xx audio_allocate_buffers\n");
+
+	/*
+	 * Allocate space for the array of struct audio_buf_t structs.
+	 */
+	stream->buffers = (struct audio_buf_t *)
+	    kmalloc(sizeof(struct audio_buf_t) * stream->nbfrags, GFP_KERNEL);
+
+	if (!stream->buffers) {
+		DPRINTK("ep93xx-audio: unable to allocate audio memory\n ");
+		audio_deallocate_buffers(state, stream);
+		return -ENOMEM;
+	}
+
+	/*
+	 * If the audio app hasn't requested a specific fragsize and nbfrags,
+	 * we stay with our default.
+	 */
+	if ((stream->requested_fragsize != 0)
+	    && (stream->requested_nbfrags != 0)) {
+		/*
+		 * Adjust the fragsize to take into account how big actual samples in
+		 * the dma buffer are.  Max dma buf size is 64K.
+		 */
+		stream->fragsize =
+		    stream->requested_fragsize * stream->dma2usr_ratio;
+	}
+
+	if (stream->fragsize > 65536)
+		stream->fragsize = 65536;
+	if (stream->fragsize < 8192)
+		stream->fragsize = 8192;
+
+	/*
+	 * Adjust num of frags so we have as many samples of buffer as were requested
+	 * even if the fragment size changed.
+	 */
+	if ((stream->requested_fragsize != 0)
+	    && (stream->requested_nbfrags != 0)) {
+		stream->nbfrags =
+		    (stream->requested_fragsize * stream->requested_nbfrags *
+		     stream->dma2usr_ratio)
+		    / stream->fragsize;
+	}
+
+	if (stream->nbfrags < 2)
+		stream->nbfrags = 2;
+	if (stream->nbfrags > AUDIO_NBFRAGS_MAX)
+		stream->nbfrags = AUDIO_NBFRAGS_MAX;
+
+	memset(stream->buffers, 0,
+	       sizeof(struct audio_buf_t) * stream->nbfrags);
+
+	/*
+	 * 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 allocate more smaller buffers.
+	 */
+	for (frag = 0; frag < stream->nbfrags; frag++) {
+		struct audio_buf_t *dma_buffer = &stream->buffers[frag];
+
+		if (!dmasize) {
+			/*
+			 * First try to allocate enough for all the frags that
+			 * don't yet have memory allocated.
+			 */
+			dmasize = (stream->nbfrags - frag) * stream->fragsize;
+			do {
+				// GRM
+				//dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
+				//                        dmasize, &dmaphys);
+				dmabuf = dma_alloc_coherent(NULL,
+							    dmasize, &dmaphys,
+							    GFP_KERNEL |
+							    GFP_DMA);
+
+				/*
+				 * If that fails, try to allocate a chunk of memory
+				 * that is one less fragment is size.
+				 */
+				if (!dmabuf)
+					dmasize -= stream->fragsize;
+
+				/*
+				 * Keep trying but the minimum we'll attempt is one
+				 * fragment.  If we can't even get that, give up.
+				 */
+			} while (!dmabuf && dmasize);
+
+			/*
+			 * If we do fail to allocate enough for all the frags,
+			 * deallocate whatever we did get and quit.
+			 */
+			if (!dmabuf) {
+				DPRINTK
+				    ("ep93xx-audio: unable to allocate audio memory\n ");
+				audio_deallocate_buffers(state, stream);
+				return -ENOMEM;
+			}
+
+			DPRINTK
+			    ("EP93xx allocated %d bytes:  dmabuf=0x%08x  dmaphys=0x%08x\n",
+			     dmasize, (int)dmabuf, (int)dmaphys);
+
+			/*
+			 * Success!      Save the size of this chunk to use when we deallocate it.
+			 */
+			dma_buffer->master = dmasize;
+			memzero(dmabuf, dmasize);
+		}
+
+		/*
+		 * Save the start address of the dma_buffer fragment.
+		 * We know the size of the fragment is fragsize.
+		 */
+		dma_buffer->start = dmabuf;
+		dma_buffer->dma_addr = dmaphys;
+		dma_buffer->stream = stream;
+		dma_buffer->size = 0;
+		dma_buffer->sent = 0;
+		dma_buffer->num = buf_num++;
+
+		dma_buffer->owner = 0;
+
+		/*
+		 * Now if we only allocated the minimal one frag of space, the
+		 * dmasize will be ==0 after this subtraction so it will allocate more
+		 * for the next frag.  Otherwise, the next time(s) thru this for loop
+		 * will dole out frag sized pieces of this big master chunk.
+		 */
+		dmabuf += stream->fragsize;
+		dmaphys += stream->fragsize;
+		dmasize -= stream->fragsize;
+	}
+
+	/*
+	 * Initialize the stream.
+	 */
+	stream->buffered_bytes_to_play = 0;
+	stream->dma_buffer_index = 0;	/* Init the current buffer index.                       */
+	stream->dma_buffer = &stream->buffers[0];	/* Point dma_buffer to the current buffer struct.       */
+	stream->bytecount = 0;
+	stream->getptrCount = 0;
+	stream->fragcount = 0;
+
+	DPRINTK("EP93xx audio_allocate_buffers -- exit SUCCESS\n");
+	return 0;
+
+}
+
+/*
+ * audio_reset_buffers
+ *
+ * This function stops and flushes the dma, gets all buffers back
+ * from the DMA driver and resets them ready to be used again.
+ */
+static void audio_reset_buffers(struct audio_state_t *state,
+				struct audio_stream_t *stream)
+{
+	int frag, i;
+
+	audio_dma_pause(state, stream);
+	stream->active = 0;
+	stream->stopped = 0;
+
+	for (i = 0; i < stream->NumDmaChannels; i++)
+		DMA_FLUSH(stream->dmahandles[i]);
+
+	if (stream->buffers) {
+		for (frag = 0; frag < stream->nbfrags; frag++) {
+			struct audio_buf_t *dma_buffer = &stream->buffers[frag];
+			dma_buffer->size = 0;
+			dma_buffer->sent = 0;
+			dma_buffer->owner = 0;
+		}
+	}
+
+	stream->buffered_bytes_to_play = 0;
+	stream->bytecount = 0;
+	stream->getptrCount = 0;
+	stream->fragcount = 0;
+}
+
+/*
+ * DMA callback functions
+ */
+static void audio_dma_tx_callback
+    (ep93xx_dma_int_t DMAInt, ep93xx_dma_dev_t device, unsigned int user_data) {
+	unsigned int buf_id;
+	int handle, i;
+
+	struct audio_state_t *state = (struct audio_state_t *)user_data;
+	struct audio_stream_t *stream = state->output_stream;
+
+	/* DPRINTK( "audio_dma_tx_callback - %s\n", stream->devicename ); */
+
+	/*
+	 * Get the DMA handle that corresponds to the dma channel
+	 * that needs servicing.  A multichannel audio stream will
+	 * have a DMA handle for each stereo pair that it uses.
+	 */
+	for (i = 0;
+	     (i < stream->NumDmaChannels) && (stream->dmachannel[i] != device);
+	     i++) ;
+	handle = stream->dmahandles[i];
+
+	if (stream->mapped) {
+		/*
+		 * If we are mapped, get one dma buffer back and recycle it.
+		 */
+		if (DMA_REMOVE_BUFFER(handle, &buf_id) >= 0) {
+			struct audio_buf_t *dma_buffer =
+			    (struct audio_buf_t *)buf_id;
+
+			/*      DPRINTK( "audio_dma_tx_callback  - got dma buffer index=%d\n", buf_id); */
+
+			/* Accounting */
+			stream->buffered_bytes_to_play -= dma_buffer->size;
+
+			/* bytecount and fragcount will overflow */
+			stream->bytecount += dma_buffer->size;
+			if (stream->bytecount < 0)
+				stream->bytecount = 0;
+
+			stream->fragcount++;
+			if (stream->fragcount < 0)
+				stream->fragcount = 0;
+
+			dma_buffer->size = 0;
+
+			/* Recycle dma buffer */
+			dma_buffer->size = stream->fragsize;
+
+			DMA_ADD_BUFFER(handle,	/* dma instance                 */
+				       (unsigned int)dma_buffer->dma_addr,	/* source           */
+				       0,	/* dest                                 */
+				       stream->fragsize,	/* size                                 */
+				       0,	/* is the last chunk?   */
+				       (unsigned int)dma_buffer);	/* buf id                          */
+
+			dma_buffer->sent = 1;
+		}
+	} else {
+		/*
+		 * Get all buffers that are free'ed back and clear their semephores.
+		 */
+		while (DMA_REMOVE_BUFFER(handle, &buf_id) >= 0) {
+			struct audio_buf_t *dma_buffer =
+			    (struct audio_buf_t *)buf_id;
+
+			/*      DPRINTK( "audio_dma_tx_callback  - got dma buffer index=%d\n", buf_id); */
+
+			/* Accounting */
+			stream->buffered_bytes_to_play -= dma_buffer->size;
+
+			stream->bytecount += dma_buffer->size;
+			if (stream->bytecount < 0)
+				stream->bytecount = 0;
+
+			stream->fragcount++;
+			if (stream->fragcount < 0)
+				stream->fragcount = 0;
+
+			dma_buffer->size = 0;
+			dma_buffer->sent = 0;
+
+			/*
+			 * Release the semaphore on this dma_buffer.
+			 * If write is waiting on this dma_buffer then it can go
+			 * ahead and fill it and send it to the dma.
+			 */
+			dma_buffer->owner = 0;
+		}
+	}
+
+	/* And any process polling on write. */
+	wake_up(&stream->wq);
+}
+
+static void audio_dma_rx_callback
+    (ep93xx_dma_int_t DMAInt, ep93xx_dma_dev_t device, unsigned int user_data) {
+	unsigned int buf_id;
+	int handle, i;
+
+	struct audio_state_t *state = (struct audio_state_t *)user_data;
+	struct audio_stream_t *stream = state->input_stream;
+
+	//DPRINTK("audio_dma_rx_callback\n");
+
+	/*
+	 * Get the DMA handle that corresponds to the dma channel
+	 * that needs servicing.  A multichannel audio stream will
+	 * have a DMA handle for each stereo pair that it uses.
+	 */
+	for (i = 0;
+	     (i < stream->NumDmaChannels) && (stream->dmachannel[i] != device);
+	     i++) ;
+	handle = stream->dmahandles[i];
+
+	/*
+	 * Keep removing and recycling buffers as long as there are buffers
+	 * to remove.
+	 */
+	while (!DMA_REMOVE_BUFFER(handle, &buf_id)) {
+		struct audio_buf_t *dma_buffer = (struct audio_buf_t *)buf_id;
+
+		/* Accounting */
+		stream->bytecount += stream->fragsize;
+		if (stream->bytecount < 0)
+			stream->bytecount = 0;
+
+		stream->fragcount++;
+		if (stream->fragcount < 0)
+			stream->fragcount = 0;
+
+		/* Recycle dma buffer */
+		if (stream->mapped) {
+			DMA_ADD_BUFFER(handle,	/* dma instance                 */
+				       (unsigned int)dma_buffer->dma_addr,	/* source          */
+				       0,	/* dest                                 */
+				       stream->fragsize,	/* size                                 */
+				       0,	/* is the last chunk?   */
+				       (unsigned int)dma_buffer);	/* buf id                          */
+		} else {
+			dma_buffer->size = stream->fragsize;
+			dma_buffer->owner = 0;
+		}
+
+		/* And any process polling on write. */
+		wake_up(&stream->wq);
+	}
+}
+
+/*
+ * audio_sync
+ *
+ * Wait until the last byte written to this device has been played.
+ */
+static int audio_sync(struct file *file)
+{
+	struct audio_state_t *state =
+	    (struct audio_state_t *)file->private_data;
+	struct audio_stream_t *stream = state->output_stream;
+	struct audio_buf_t *dma_buffer;
+	int buf_wait_index;
+
+	DPRINTK("audio_sync - enter\n");
+
+	if (!(file->f_mode & FMODE_WRITE) || !stream->buffers || stream->mapped) {
+		DPRINTK("audio_sync - exit immediately.\n");
+		return 0;
+	}
+
+	/*
+	 * Send current dma buffer if it contains data and hasn't been sent.
+	 */
+	dma_buffer = stream->dma_buffer;
+
+	if (dma_buffer->size && !dma_buffer->sent) {
+		DPRINTK("audio_sync -- SENDING BUFFER index=%d size=%d\n",
+			stream->dma_buffer_index, dma_buffer->size);
+
+		while (dma_buffer->owner == 1)
+			schedule();
+		dma_buffer->owner = 1;
+		DMA_ADD_BUFFER(stream->dmahandles[0],	/* dma instance                 */
+			       (unsigned int)dma_buffer->dma_addr,	/* source               */
+			       0,	/* dest                                 */
+			       dma_buffer->size,	/* size                                 */
+			       0,	/* is the last chunk?   */
+			       (unsigned int)dma_buffer);	/* dma_buffer id                                */
+		dma_buffer->sent = 1;
+		NEXT_BUF(stream, dma_buffer);
+	}
+
+	/*
+	 * Let's wait for the last dma buffer we sent i.e. the one before the
+	 * current dma_buffer_index.  When we acquire the semaphore, this means either:
+	 * - DMA on the buffer completed or
+	 * - the buffer was already free thus nothing else to sync.
+	 */
+	buf_wait_index =
+	    ((stream->nbfrags + stream->dma_buffer_index -
+	      1) % stream->nbfrags);
+	dma_buffer = stream->buffers + buf_wait_index;
+
+	DPRINTK("audio_sync - waiting on down_interruptible\n");
+	while (dma_buffer->owner == 1) {
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+		schedule();
+	}
+
+	DPRINTK("audio_sync - EXIT\n");
+	return 0;
+}
+
+//static int iWriteCount = 0;
+
+/*
+ * Need to convert to 32 bit stereo format:
+ * 16 bit signed
+ * 16 bit unsigned
+ *  8 bit signed
+ *  8 bit unsigned
+ */
+static int audio_write
+    (struct file *file,
+     const char *user_buffer, size_t src_count, loff_t * ppos) {
+	const char *user_buffer_start = user_buffer;
+	struct audio_state_t *state =
+	    (struct audio_state_t *)file->private_data;
+	struct audio_stream_t *stream = state->output_stream;
+	unsigned int dma_xfer_count, src_xfer_count, expanded_count;
+	int ret = 0;
+//      int i,j;
+
+	/* DPRINTK_IOCTL( "EP93xx - audio_write: count=%d\n", src_count ); */
+
+	// KERNEL2.4
+	/*if (ppos != &file->f_pos)
+	   return -ESPIPE; */
+
+	if (stream->mapped)
+		return -ENXIO;
+
+	if (!access_ok(VERIFY_READ, user_buffer, src_count)) {
+		DPRINTK("access_ok failed for audio_write!!!!\n");
+		return -EFAULT;
+	}
+
+	/*
+	 * Allocate dma buffers if we haven't already done so.
+	 */
+	if (!stream->buffers && audio_allocate_buffers(state, stream))
+		return -ENOMEM;
+
+//      if( iWriteCount > 40 )
+//      {
+//              for( i=0; i<4 ; i++ )
+//              {
+//                      for( j=0; j<8 ; j++ )
+//                      {
+//                              printk("%02x ", user_buffer[(i*8)+j] );
+//                      }
+//                      printk("\n");
+//              }
+//              iWriteCount = 0;
+//      }
+//      iWriteCount++;
+
+	/*
+	 * Stay in this loop until we have copied all of the file
+	 * into user memory.
+	 */
+	while (src_count > 0) {
+		struct audio_buf_t *dma_buffer = stream->dma_buffer;
+
+		/* Wait for a dma buffer to become free */
+		if (file->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			if (dma_buffer->owner != 0)
+				break;
+		} else {
+			while (dma_buffer->owner == 1) {
+				if (signal_pending(current))
+					return -ERESTARTSYS;
+				schedule();
+			}
+		}
+
+		/*
+		 * Feed the current dma buffer (stream->dma_buffer)
+		 * This involves expanding sample size from the user_buffer
+		 * to be 32 bit stereo for our dma.
+		 */
+
+		/*
+		 * How much space is left in the current dma buffer?
+		 *
+		 * dma_xfer_count is # of bytes placed into the dma buffer
+		 * where each sample is 8 bytes (4 bytes left, 4 bytes right)
+		 * because that's what the I2S is set up for - 32 bit samples.
+		 */
+		dma_xfer_count = stream->fragsize - dma_buffer->size;
+
+		/*
+		 * user_buffer is src_count (bytes) of whatever format.
+		 * How big will src_count be when sample size is expanded
+		 * to 32 bit samples for our hardware?
+		 */
+		expanded_count = src_count * stream->dma2usr_ratio;
+
+		/*
+		 * See if we can fit all the remaining user_buffer in
+		 * the current dma buffer...
+		 */
+		if (dma_xfer_count > expanded_count)
+			dma_xfer_count = expanded_count;
+
+		//DPRINTK( "EP93xx - audio_write: %d to dma_buffer # %d\n", dma_xfer_count, stream->dma_buffer_index );
+
+		src_xfer_count = copy_from_user_with_conversion(state,
+								dma_buffer->
+								start +
+								dma_buffer->
+								size,
+								user_buffer,
+								dma_xfer_count);
+		if (src_xfer_count <= 0)
+			return -EFAULT;
+
+		/*
+		 * Increment dma buffer pointer.
+		 */
+		dma_buffer->size += dma_xfer_count;
+
+		/*
+		 * Increment user_buffer pointer.
+		 * Decrement the user_buffer size count.
+		 */
+		user_buffer += src_xfer_count;
+		src_count -= src_xfer_count;
+
+		/*
+		 * If we haven't already started the DMA start it.
+		 * But don't start it if we are waiting on a trigger.
+		 */
+		if (!stream->active && !stream->stopped) {
+			stream->active = 1;
+			audio_dma_start(state, stream);
+		}
+
+		/*
+		 * Note that we've 'downed' the semiphore for this buffer.  But the
+		 * dma driver doesn't know about it until we've added it to the DMA
+		 * driver's buffer queue.  So let's do that now.
+		 */
+		dma_buffer->owner = 1;
+		DMA_ADD_BUFFER(stream->dmahandles[0],	/* dma instance                 */
+			       (unsigned int)dma_buffer->dma_addr,	/* source           */
+			       0,	/* dest                                 */
+			       dma_buffer->size,	/* size                                 */
+			       0,	/* is the last chunk?   */
+			       (unsigned int)dma_buffer);	/* buf id                          */
+
+		/*
+		 * Note that we added a buffer to play for the benefit of calculating
+		 * ODELAY.
+		 */
+		stream->buffered_bytes_to_play += dma_buffer->size;
+
+		/*
+		 * Indicate that the dma buffer has been sent.  Not the same as the
+		 * buffer's semiphore.
+		 */
+		dma_buffer->sent = 1;
+
+		NEXT_BUF(stream, dma_buffer);
+	}
+
+	/*
+	 * Return the number of bytes transferred.
+	 */
+	if ((int)user_buffer - (int)user_buffer_start)
+		ret = (int)user_buffer - (int)user_buffer_start;
+
+/*	DPRINTK( "EP93xx - audio_write: return=%d\n", ret );*/
+	return ret;
+}
+
+/*
+ * audio_dma_start
+ *
+ * Our Ac97 has a specific start order that it likes.  Enable the
+ * Ac97 channel AFTER enabling DMA.  Our I2S is not so picky.
+ */
+void audio_dma_start(struct audio_state_t *state, struct audio_stream_t *stream)
+{
+	DMA_START(stream->dmahandles[0],
+		  stream->NumDmaChannels, stream->dmahandles);
+
+	if (state->hw->hw_enable)
+		state->hw->hw_enable(stream);
+
+}
+
+/*
+ * audio_dma_pause
+ */
+void audio_dma_pause(struct audio_state_t *state, struct audio_stream_t *stream)
+{
+	DPRINTK("audio_dma_pause - enter\n");
+
+	DMA_PAUSE(stream->dmahandles[0],
+		  stream->NumDmaChannels, stream->dmahandles);
+
+	if (state->hw->hw_disable)
+		state->hw->hw_disable(stream);
+
+	if (state->hw->hw_clear_fifo)
+		state->hw->hw_clear_fifo(stream);
+
+	DPRINTK("audio_dma_pause - EXIT\n");
+}
+
+static void audio_prime_dma(struct audio_state_t *state,
+			    struct audio_stream_t *stream)
+{
+	int i;
+
+	DPRINTK("audio_prime_dma\n");
+
+	/*
+	 * If we haven't already started the DMA start it.
+	 * But don't start it if we are waiting on a trigger.
+	 */
+	if (!stream->active && !stream->stopped) {
+		stream->active = 1;
+		audio_dma_start(state, stream);
+	}
+
+	for (i = 0; i < stream->nbfrags; i++) {
+		struct audio_buf_t *dma_buffer = stream->dma_buffer;
+
+		dma_buffer->owner = 1;
+		DMA_ADD_BUFFER(stream->dmahandles[0],	/* dma instance                 */
+			       (unsigned int)dma_buffer->dma_addr,	/* source           */
+			       0,	/* dest                                 */
+			       stream->fragsize,	/* size                                 */
+			       0,	/* is the last chunk?   */
+			       (unsigned int)dma_buffer);	/* buf id                          */
+		NEXT_BUF(stream, dma_buffer);
+	}
+}
+
+/*
+ * audio_read
+ *
+ * Audio capture function.
+ */
+static int audio_read
+    (struct file *file, char *user_buffer, size_t count, loff_t * ppos) {
+	char *user_buffer_start = user_buffer;
+	struct audio_state_t *state =
+	    (struct audio_state_t *)file->private_data;
+	struct audio_stream_t *stream = state->input_stream;
+	unsigned int user_buffer_xfer_count = 0, dma_buffer_xfer_count = 0;
+	int ret = 0;
+
+	DPRINTK("EP93xx - audio_read: count=%d\n", count);
+
+	// KERNEL2.4
+	/*if (ppos != &file->f_pos)
+	   return -ESPIPE; */
+
+	if (stream->mapped)
+		return -ENXIO;
+
+	if (!access_ok(VERIFY_WRITE, user_buffer, count)) {
+		DPRINTK("access_ok failed for audio_read!!!!\n");
+		return -EFAULT;
+	}
+
+	if (!stream->active) {
+		if (!stream->buffers && audio_allocate_buffers(state, stream))
+			return -ENOMEM;
+
+		audio_prime_dma(state, stream);
+	}
+
+	while (count > 0) {
+		/*
+		 * Get the current buffer.
+		 */
+		struct audio_buf_t *dma_buffer = stream->dma_buffer;
+
+		/*
+		 * Wait for a dma buffer to become full
+		 */
+		if (file->f_flags & O_NONBLOCK) {
+			//DPRINTK("file->f_flags & O_NONBLOCK\n");
+			ret = -EAGAIN;
+			if (dma_buffer->owner != 0)
+				break;
+		} else {
+			while (dma_buffer->owner == 1) {
+				if (signal_pending(current))
+					return -ERESTARTSYS;
+				schedule();
+			}
+		}
+
+		/*
+		 * If this is the first buffer captured,
+		 * dump the first 8 samples of the dma buffer.
+		 */
+		if (stream->bFirstCaptureBuffer) {
+			dma_buffer->size -= 64;
+			stream->bFirstCaptureBuffer = 0;
+		}
+
+		/*
+		 * How much user buffer would a whole DMA buffer fill?
+		 */
+		user_buffer_xfer_count =
+		    dma_buffer->size / stream->dma2usr_ratio;
+
+		if (user_buffer_xfer_count > count)
+			user_buffer_xfer_count = count;
+
+		dma_buffer_xfer_count =
+		    user_buffer_xfer_count * stream->dma2usr_ratio;
+
+		DPRINTK("dma_buffer: start=0x%08x fragsz=%d size=%d\n",
+			(int)dma_buffer->start, (int)stream->fragsize,
+			dma_buffer->size);
+
+		DPRINTK
+		    ("user_buffer=0x%08x  from=0x%08x  user_count=%d  dma_count=%d\n",
+		     (int)user_buffer,
+		     (int)dma_buffer->start + stream->fragsize -
+		     dma_buffer->size, user_buffer_xfer_count,
+		     dma_buffer_xfer_count);
+
+		if (copy_to_user_with_conversion(state,
+						 user_buffer,
+						 dma_buffer->start +
+						 stream->fragsize -
+						 dma_buffer->size,
+						 user_buffer_xfer_count) <= 0)
+			return -EFAULT;
+
+		dma_buffer->size -= dma_buffer_xfer_count;
+
+		user_buffer += user_buffer_xfer_count;
+		count -= user_buffer_xfer_count;
+
+		/*
+		 * Grab data from the current dma buffer
+		 */
+		//DPRINTK("Read: read %d bytes from %d.  dmabufsize=%d.  count=%d\n",
+		//                      user_buffer_xfer_count, stream->dma_buffer_index,
+		//                      dma_buffer->size, count);
+
+		/*
+		 * If there's still data in this buffer to be read, release
+		 * the semiphore and don't give it back yet.  We may come back
+		 * and read from it in a minute when the app calls for another read.
+		 */
+		if (dma_buffer->size > 0)
+			break;
+
+		/* Make current dma buffer available for DMA again */
+		dma_buffer->owner = 1;
+		DMA_ADD_BUFFER(stream->dmahandles[0],	/* dma instance  */
+			       (unsigned int)dma_buffer->dma_addr,	/* source */
+			       0,	/* dest  */
+			       stream->fragsize,	/* size  */
+			       0,	/* the last chunk? */
+			       (unsigned int)dma_buffer);	/* buf id */
+
+		NEXT_BUF(stream, dma_buffer);
+	}
+
+	if ((int)user_buffer - (int)user_buffer_start)
+		ret = (int)user_buffer - (int)user_buffer_start;
+
+	//DPRINTK("EP93xx - audio_read: return=%d\n", ret);
+
+	return ret;
+}
+
+static int audio_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct audio_state_t *state =
+	    (struct audio_state_t *)file->private_data;
+	struct audio_stream_t *stream = 0;
+	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;
+
+		stream = state->output_stream;
+	} else if (vma->vm_flags & VM_READ) {
+		if (!state->rd_ref)
+			return -EINVAL;
+
+		stream = state->input_stream;
+	} else {
+		return -EINVAL;
+	}
+
+	if (stream->mapped)
+		return -EINVAL;
+
+	size = vma->vm_end - vma->vm_start;
+
+	if (size != stream->fragsize * stream->nbfrags)
+		return -EINVAL;
+
+	if (!stream->buffers && audio_allocate_buffers(state, stream))
+		return -ENOMEM;
+
+	vma_addr = vma->vm_start;
+
+	for (i = 0; i < stream->nbfrags; i++) {
+		struct audio_buf_t *dma_buffer = &stream->buffers[i];
+
+		if (!dma_buffer->master) {
+			continue;
+		}
+		// KERNEL2.4
+		//ret = remap_page_range(vma_addr, dma_buffer->dma_addr, dma_buffer->master, vma->vm_page_prot);
+		ret =
+		    remap_pfn_range(vma, vma_addr, dma_buffer->dma_addr,
+				    dma_buffer->master, vma->vm_page_prot);
+
+		if (ret)
+			return ret;
+
+		vma_addr += dma_buffer->master;
+	}
+
+	stream->mapped = 1;
+
+	return 0;
+}
+
+static unsigned int audio_poll(struct file *file,
+			       struct poll_table_struct *wait)
+{
+	struct audio_state_t *state =
+	    (struct audio_state_t *)file->private_data;
+	struct audio_stream_t *is = state->input_stream;
+	struct audio_stream_t *os = state->output_stream;
+	unsigned int mask = 0;
+	int i;
+
+	DPRINTK("EP93xx - audio_poll(): mode=%s%s\n",
+		(file->f_mode & FMODE_READ) ? "r" : "",
+		(file->f_mode & FMODE_WRITE) ? "w" : "");
+
+	if (file->f_mode & FMODE_READ) {
+		/* Start audio input if not already active */
+		if (!is->active) {
+			if (!is->buffers && audio_allocate_buffers(state, is))
+				return -ENOMEM;
+
+			audio_prime_dma(state, is);
+		}
+
+		poll_wait(file, &is->wq, wait);
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		if (!os->buffers && audio_allocate_buffers(state, os))
+			return -ENOMEM;
+
+		poll_wait(file, &os->wq, wait);
+	}
+
+	if (file->f_mode & FMODE_READ) {
+		if (is->mapped) {
+			/*
+			 * if the buffer is mapped assume we care that there are
+			 * more bytes available than when we last asked using
+			 * SNDCTL_DSP_GETxPTR
+			 */
+			if (is->bytecount != is->getptrCount)
+				mask |= POLLIN | POLLRDNORM;
+		} else {
+			for (i = 0; i < is->nbfrags; i++) {
+				if (is->buffers[i].owner != 0) {
+					mask |= POLLIN | POLLRDNORM;
+					break;
+				}
+			}
+		}
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		if (os->mapped) {
+			if (os->bytecount != os->getptrCount)
+				mask |= POLLOUT | POLLWRNORM;
+		} else {
+			for (i = 0; i < os->nbfrags; i++) {
+				if (os->buffers[i].owner != 0) {
+					mask |= POLLOUT | POLLWRNORM;
+					break;
+				}
+			}
+		}
+	}
+
+	DPRINTK("EP93xx - audio_poll() returned mask of %s%s\n",
+		(mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : "");
+
+	return mask;
+}
+
+/*
+ * audio_set_fragments
+ *
+ * Used to process SNDCTL_DSP_SETFRAGMENT.
+ *
+ * Argument is 0xMMMMSSSS where:
+ *		MMMM sets number of fragments.
+ * 		SSSS sets dma fragment (dma_buffer) size.  size = 2^SSSS bytes
+ */
+static int audio_set_fragments(struct audio_state_t *state,
+			       struct audio_stream_t *stream, int val)
+{
+	if (stream->active)
+		return -EBUSY;
+
+	stream->requested_fragsize = 1 << (val & 0x000ffff);
+	stream->requested_nbfrags = (val >> 16) & 0x7FFF;
+
+	return 0;
+}
+
+static void print_audio_format(long format)
+{
+	switch (format) {
+	case AFMT_U8:
+		DPRINTK_IOCTL("AFMT_U8\n");
+		break;
+
+	case AFMT_S8:
+		DPRINTK_IOCTL("AFMT_S8\n");
+		break;
+
+	case AFMT_S32_BLOCKED:
+		DPRINTK_IOCTL("AFMT_S32_BLOCKED\n");
+		break;
+
+	case AFMT_S16_LE:
+		DPRINTK_IOCTL("AFMT_S16_LE\n");
+		break;
+
+	case AFMT_S16_BE:
+		DPRINTK_IOCTL("AFMT_S16_BE\n");
+		break;
+
+	case AFMT_U16_LE:
+		DPRINTK_IOCTL("AFMT_U16_LE\n");
+		break;
+
+	case AFMT_U16_BE:
+	default:
+		DPRINTK_IOCTL("AFMT_U16_BE\n");
+		break;
+	}
+}
+
+/*
+ * We convert to 24 bit samples that occupy 32 bits each.
+ * Formats we support:
+ *
+ * AFMT_U8
+ * AFMT_S16_LE	   	Little endian signed 16
+ * AFMT_S8
+ * AFMT_U16_LE	   	Little endian U16
+ * AFMT_S32_BLOCKED	32 bit little endian format, taken from the rme96xx driver.
+ *
+ */
+static long audio_set_format(struct audio_stream_t *stream, long val)
+{
+	DPRINTK_IOCTL("audio_set_format enter.  Format requested (%d) ",
+		      (int)val);
+	print_audio_format(val);
+
+	switch (val) {
+	case AFMT_QUERY:
+		break;
+
+	case AFMT_U8:
+		stream->audio_format = val;
+		stream->audio_stream_bitwidth = 8;
+		break;
+
+	case AFMT_S8:
+		stream->audio_format = val;
+		stream->audio_stream_bitwidth = 8;
+		break;
+
+	case AFMT_S32_BLOCKED:
+		stream->audio_format = val;
+		stream->audio_stream_bitwidth = 32;
+		break;
+
+	case AFMT_S16_LE:
+	case AFMT_S16_BE:
+		stream->audio_format = AFMT_S16_LE;
+		stream->audio_stream_bitwidth = 16;
+		break;
+
+	case AFMT_U16_LE:
+	case AFMT_U16_BE:
+	default:
+		stream->audio_format = AFMT_U16_LE;
+		stream->audio_stream_bitwidth = 16;
+		break;
+	}
+
+	DPRINTK_IOCTL("audio_set_format EXIT format set to be (%d) ",
+		      (int)stream->audio_format);
+	print_audio_format((long)stream->audio_format);
+
+	return stream->audio_format;
+}
+
+static __inline__ unsigned long copy_to_user_U16_LE_CM
+    (struct audio_state_t *state,
+     const char *to, const char *from, unsigned long to_count) {
+	int total_to_count = to_count;
+	unsigned short *user_ptr = (unsigned short *)to;	/* 16 bit user buffer */
+	short *dma_ptr = (short *)from;
+	short right, left;
+
+	/*
+	 * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
+	 */
+
+	if (state->input_stream->audio_num_channels != 1) {
+		while (to_count > 0) {
+			right = *dma_ptr++;
+			left = *dma_ptr++;
+			__put_user(left ^ 0x8000, user_ptr++);
+			__put_user(right ^ 0x8000, user_ptr++);
+			to_count -= 4;
+		}
+	} else {
+		while (to_count > 0) {
+			dma_ptr++;	/* skip right channel sample */
+			left = *dma_ptr++;
+			__put_user(left ^ 0x8000, user_ptr++);
+			to_count -= 2;
+		}
+	}
+
+	return total_to_count;
+}
+
+static __inline__ unsigned long copy_to_user_U16_LE
+    (struct audio_state_t *state,
+     const char *to, const char *from, unsigned long to_count) {
+	int total_to_count = to_count;
+	short *user_ptr = (short *)to;	/* 16 bit user buffer */
+	int *dma_ptr = (int *)from;	/* 32 bit dma buffer  */
+
+	int shift = state->input_stream->hw_bit_width - 16;
+
+	if (state->input_stream->audio_num_channels != 1) {
+		while (to_count > 0) {
+			__put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
+				   user_ptr++);
+			__put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
+				   user_ptr++);
+			to_count -= 4;
+		}
+	} else {
+		while (to_count > 0) {
+			__put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
+				   user_ptr++);
+			dma_ptr++;	/* skip right channel sample */
+			to_count -= 2;
+		}
+	}
+
+	return total_to_count;
+}
+
+static __inline__ unsigned long copy_to_user_S16_LE_CM
+    (struct audio_state_t *state,
+     const char *to, const char *from, unsigned long to_count) {
+	int total_to_count = to_count;
+	short *user_ptr = (short *)to;	/* 16 bit user buffer */
+	short *dma_ptr = (short *)from;
+	short left, right;
+
+	/*
+	 * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
+	 */
+
+	if (state->input_stream->audio_num_channels != 1) {
+		while (to_count > 0) {
+			right = *dma_ptr++;
+			left = *dma_ptr++;
+			__put_user(left, user_ptr++);
+			__put_user(right, user_ptr++);
+			to_count -= 4;
+		}
+	} else {
+		while (to_count > 0) {
+			dma_ptr++;	/* skip right sample */
+			left = *dma_ptr++;
+			__put_user(left, user_ptr++);
+			to_count -= 2;
+		}
+	}
+
+	return total_to_count;
+}
+
+static __inline__ unsigned long copy_to_user_S16_LE
+    (struct audio_state_t *state,
+     const char *to, const char *from, unsigned long to_count) {
+	int total_to_count = to_count;
+	short *user_ptr = (short *)to;	/* 16 bit user buffer */
+	int *dma_ptr = (int *)from;	/* 32 bit dma buffer  */
+
+	int shift = state->input_stream->hw_bit_width - 16;
+
+	if (state->input_stream->audio_num_channels != 1) {
+		while (to_count > 0) {
+			__put_user((short)((*dma_ptr++) >> shift), user_ptr++);
+			__put_user((short)((*dma_ptr++) >> shift), user_ptr++);
+			to_count -= 4;
+		}
+	} else {
+		while (to_count > 0) {
+			__put_user((short)((*dma_ptr++) >> shift), user_ptr++);
+			dma_ptr++;	/* skip right channel sample */
+			to_count -= 2;
+		}
+	}
+
+	return total_to_count;
+}
+
+static __inline__ unsigned long copy_to_user_S8_CM
+    (struct audio_state_t *state,
+     const char *to, const char *from, unsigned long to_count) {
+	int total_to_count = to_count;
+	char *user_ptr = (char *)to;	/*  8 bit user buffer */
+	unsigned short *dma_ptr = (unsigned short *)from;	/* 16 bit dma buffer  */
+	char right, left;
+
+	if (state->input_stream->audio_num_channels != 1) {
+		while (to_count > 0) {
+			right = ((char)(*dma_ptr++ >> 8));
+			left = ((char)(*dma_ptr++ >> 8));
+			__put_user(left, user_ptr++);
+			__put_user(right, user_ptr++);
+			to_count -= 2;
+		}
+	} else {
+		while (to_count > 0) {
+			dma_ptr++;	/* skip right channel sample */
+			left = ((char)(*dma_ptr++ >> 8));
+			__put_user(left, user_ptr++);
+			to_count--;
+		}
+	}
+
+	return total_to_count;
+}
+
+static __inline__ unsigned long copy_to_user_S8
+    (struct audio_state_t *state,
+     const char *to, const char *from, unsigned long to_count) {
+	int total_to_count = to_count;
+	char *user_ptr = (char *)to;	/*  8 bit user buffer */
+	int *dma_ptr = (int *)from;	/* 32 bit dma buffer  */
+
+	int shift = state->input_stream->hw_bit_width - 8;
+
+	if (state->input_stream->audio_num_channels != 1) {
+		while (to_count > 0) {
+			__put_user((char)((*dma_ptr++) >> shift), user_ptr++);
+			__put_user((char)((*dma_ptr++) >> shift), user_ptr++);
+			to_count -= 2;
+		}
+	} else {
+		while (to_count > 0) {
+			__put_user((char)((*dma_ptr++) >> shift), user_ptr++);
+			dma_ptr++;	/* skip right channel sample */
+			to_count--;
+		}
+	}
+
+	return total_to_count;
+}
+
+static __inline__ unsigned long copy_to_user_U8_CM
+    (struct audio_state_t *state,
+     const char *to, const char *from, unsigned long to_count) {
+	int total_to_count = to_count;
+	char *user_ptr = (char *)to;	/*  8 bit user buffer */
+	unsigned short *dma_ptr = (unsigned short *)from;	/* 16 bit dma buffer  */
+	char right, left;
+
+	if (state->input_stream->audio_num_channels != 1) {
+		while (to_count > 0) {
+			right = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
+			left = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
+			__put_user(left, user_ptr++);
+			__put_user(right, user_ptr++);
+			to_count -= 2;
+		}
+	} else {
+		while (to_count > 0) {
+			dma_ptr++;	/* skip right channel sample */
+			left = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
+			__put_user(left, user_ptr++);
+			to_count--;
+		}
+	}
+
+	return total_to_count;
+}
+
+static __inline__ unsigned long copy_to_user_U8
+    (struct audio_state_t *state,
+     const char *to, const char *from, unsigned long to_count) {
+	int total_to_count = to_count;
+	char *user_ptr = (char *)to;	/*  8 bit user buffer */
+	int *dma_ptr = (int *)from;	/* 32 bit dma buffer  */
+
+	int shift = state->input_stream->hw_bit_width - 8;
+
+	if (state->input_stream->audio_num_channels != 1) {
+		while (to_count > 0) {
+			__put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
+				   user_ptr++);
+			__put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
+				   user_ptr++);
+			to_count -= 2;
+		}
+	} else {
+		while (to_count > 0) {
+			__put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
+				   user_ptr++);
+			dma_ptr++;	/* skip right channel sample */
+			to_count--;
+		}
+	}
+
+	return total_to_count;
+}
+
+/*
+ * Returns negative for error
+ * Returns # of bytes transferred out of the from buffer
+ * for success.
+ */
+static __inline__ int copy_to_user_with_conversion
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	int ret = 0;
+
+	if (toCount == 0) {
+		DPRINTK("copy_to_user_with_conversion - nothing to copy!\n");
+	}
+
+	/*
+	 * Compact Mode means that each 32 bit word has both the
+	 * left and right sample in it.
+	 */
+	if (state->input_stream->bCompactMode) {
+		switch (state->input_stream->audio_format) {
+		case AFMT_U8:
+			ret = copy_to_user_U8_CM(state, to, from, toCount);
+			break;
+
+		case AFMT_S16_LE:
+			ret = copy_to_user_S16_LE_CM(state, to, from, toCount);
+			break;
+
+		case AFMT_S8:
+			ret = copy_to_user_S8_CM(state, to, from, toCount);
+			break;
+
+		case AFMT_U16_LE:
+			ret = copy_to_user_U16_LE_CM(state, to, from, toCount);
+			break;
+
+		case AFMT_S32_BLOCKED:
+		default:
+			break;
+		}
+	} else {
+		switch (state->input_stream->audio_format) {
+		case AFMT_U8:
+			ret = copy_to_user_U8(state, to, from, toCount);
+			break;
+
+		case AFMT_S16_LE:
+			ret = copy_to_user_S16_LE(state, to, from, toCount);
+			break;
+
+		case AFMT_S8:
+			ret = copy_to_user_S8(state, to, from, toCount);
+			break;
+
+		case AFMT_U16_LE:
+			ret = copy_to_user_U16_LE(state, to, from, toCount);
+			break;
+
+		case AFMT_S32_BLOCKED:
+		default:
+			__copy_to_user((char *)to, from, toCount);
+			ret = toCount;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static __inline__ int copy_from_user_U16_LE_CM
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	unsigned short *dma_buffer = (unsigned short *)to;
+	unsigned short *user_buffer = (unsigned short *)from;
+	unsigned short data;
+
+	int toCount0 = toCount;
+	int mono = (state->output_stream->audio_num_channels == 1);
+
+	/*
+	 * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
+	 */
+
+	if (!mono) {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = data ^ 0x8000;
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = data ^ 0x8000;
+			toCount -= 4;
+		}
+	} else {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			data = data ^ 0x8000;
+			*dma_buffer++ = data;
+			*dma_buffer++ = data;
+			toCount -= 4;
+		}
+	}
+
+	/*
+	 * Each mono or stereo 16 bit sample going in results
+	 * in one stereo 32 bit sample going out.  So
+	 * mono   = (2 bytes in)/(4 bytes out)
+	 * stereo = (4 bytes in)/(4 bytes out)
+	 */
+	if (mono) {
+		return toCount0 / 2;
+	}
+
+	return toCount0;
+}
+
+static __inline__ int copy_from_user_U16_LE
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	int *dma_buffer = (int *)to;
+	int val;
+	unsigned short *user_buffer = (unsigned short *)from;
+	unsigned short data;
+
+	int toCount0 = toCount;
+	int mono = (state->output_stream->audio_num_channels == 1);
+	int shift = state->output_stream->hw_bit_width - 16;
+
+	if (!mono) {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = ((unsigned int)data ^ 0x8000) << shift;
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = ((unsigned int)data ^ 0x8000) << shift;
+			toCount -= 8;
+		}
+	} else {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			val = ((unsigned int)data ^ 0x8000) << shift;
+			*dma_buffer++ = val;
+			*dma_buffer++ = val;
+			toCount -= 8;
+		}
+	}
+
+	/*
+	 * Each mono or stereo 16 bit sample going in results
+	 * in a two 32 bit (left & right) samples going out.  So
+	 * mono   = (2 bytes in)/(8 bytes out)
+	 * stereo = (4 bytes in)/(8 bytes out)
+	 */
+	if (mono)
+		return toCount0 / 4;
+
+	return toCount0 / 2;
+}
+
+static __inline__ int copy_from_user_S16_LE_CM
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	short *dma_buffer = (short *)to;
+	unsigned short *user_buffer = (unsigned short *)from;
+	unsigned short data;
+
+	int toCount0 = toCount;
+	int mono = (state->output_stream->audio_num_channels == 1);
+
+	/*
+	 * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
+	 */
+
+	if (!mono) {
+		__copy_from_user((char *)to, from, toCount);
+	} else {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = data;
+			*dma_buffer++ = data;
+			toCount -= 4;
+		}
+	}
+
+	/*
+	 * Each mono or stereo 16 bit sample going in results
+	 * in one stereo 32 bit sample going out.  So
+	 * mono   = (2 bytes in)/(4 bytes out)
+	 * stereo = (4 bytes in)/(4 bytes out)
+	 */
+	if (mono)
+		return toCount0 / 2;
+
+	return toCount0;
+}
+
+static __inline__ int copy_from_user_S16_LE
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	int *dma_buffer = (int *)to;
+	int val;
+	unsigned short *user_buffer = (unsigned short *)from;
+	unsigned short data;
+
+	int toCount0 = toCount;
+	int mono = (state->output_stream->audio_num_channels == 1);
+	int shift = state->output_stream->hw_bit_width - 16;
+
+	if (!mono) {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = (unsigned int)data << shift;
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = (unsigned int)data << shift;
+			toCount -= 8;
+		}
+	} else {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			val = (unsigned int)data << shift;
+			*dma_buffer++ = val;
+			*dma_buffer++ = val;
+			toCount -= 8;
+		}
+	}
+
+	/*
+	 * Each mono or stereo 16 bit sample going in results
+	 * in a two 32 bit samples (left & right) going out.  So
+	 * mono   = (2 bytes in)/(8 bytes out)
+	 * stereo = (4 bytes in)/(8 bytes out)
+	 */
+	if (mono)
+		return toCount0 / 4;
+
+	return toCount0 / 2;
+}
+
+static __inline__ int copy_from_user_S8_CM
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	short *dma_buffer = (short *)to;
+	short val;
+	unsigned char *user_buffer = (unsigned char *)from;
+	unsigned char data;
+
+	int toCount0 = toCount;
+	int mono = (state->output_stream->audio_num_channels == 1);
+
+	/*
+	 * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
+	 */
+
+	if (!mono) {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = (unsigned short)data << 8;
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = (unsigned short)data << 8;
+			toCount -= 4;
+		}
+	} else {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			val = (unsigned short)data << 8;
+			*dma_buffer++ = val;
+			*dma_buffer++ = val;
+			toCount -= 4;
+		}
+	}
+
+	/*
+	 * Each mono or stereo 8 bit sample going in results
+	 * in one stereo 32 bit sample going out.  So
+	 * mono   = (1 byte  in)/(4 bytes out)
+	 * stereo = (2 bytes in)/(4 bytes out)
+	 */
+	if (mono)
+		return toCount0 / 4;
+
+	return toCount0 / 2;
+}
+
+static __inline__ int copy_from_user_S8
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	int *dma_buffer = (int *)to;
+	int val;
+	unsigned char *user_buffer = (unsigned char *)from;
+	unsigned char data;
+
+	int toCount0 = toCount;
+	int mono = (state->output_stream->audio_num_channels == 1);
+	int shift = state->output_stream->hw_bit_width - 8;
+
+	if (!mono) {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = (unsigned int)data << shift;
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = (unsigned int)data << shift;
+			toCount -= 8;
+		}
+	} else {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			val = (unsigned int)data << shift;
+			*dma_buffer++ = val;
+			*dma_buffer++ = val;
+			toCount -= 8;
+		}
+	}
+
+	/*
+	 * Each mono or stereo 8 bit sample going in results
+	 * in a two 32 bit samples (left & right) going out.  So
+	 * mono   = (1 byte  in)/(8 bytes out)
+	 * stereo = (2 bytes in)/(8 bytes out)
+	 */
+	if (mono)
+		return toCount0 / 8;
+
+	return toCount0 / 4;
+}
+
+static __inline__ int copy_from_user_U8_CM
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	unsigned short *dma_buffer = (unsigned short *)to;
+	unsigned short val;
+	unsigned char *user_buffer = (unsigned char *)from;
+	unsigned char data;
+
+	int toCount0 = toCount;
+	int mono = (state->output_stream->audio_num_channels == 1);
+
+	if (!mono) {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = ((unsigned short)data ^ 0x80) << 8;
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = ((unsigned short)data ^ 0x80) << 8;
+			toCount -= 4;
+		}
+	} else {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			val = ((unsigned short)data ^ 0x80) << 8;
+			*dma_buffer++ = val;
+			*dma_buffer++ = val;
+			toCount -= 4;
+		}
+	}
+
+	/*
+	 * Each mono or stereo 8 bit sample going in results
+	 * in one stereo 32 bit sample going out.  So
+	 * mono   = (1 byte  in)/(4 bytes out)
+	 * stereo = (2 bytes in)/(4 bytes out)
+	 */
+	if (mono)
+		return toCount0 / 4;
+
+	return toCount0 / 2;
+}
+
+static __inline__ int copy_from_user_U8
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	unsigned int *dma_buffer = (unsigned int *)to;
+	unsigned int val;
+	unsigned char *user_buffer = (unsigned char *)from;
+	unsigned char data;
+
+	int toCount0 = toCount;
+	int mono = (state->output_stream->audio_num_channels == 1);
+	int shift = state->output_stream->hw_bit_width - 8;
+
+	if (!mono) {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = ((unsigned int)data ^ 0x80) << shift;
+			__get_user(data, user_buffer++);
+			*dma_buffer++ = ((unsigned int)data ^ 0x80) << shift;
+			toCount -= 8;
+		}
+	} else {
+		while (toCount > 0) {
+			__get_user(data, user_buffer++);
+			val = ((unsigned int)data ^ 0x80) << shift;
+			*dma_buffer++ = val;
+			*dma_buffer++ = val;
+			toCount -= 8;
+		}
+	}
+
+	/*
+	 * Each mono or stereo 8 bit sample going in results
+	 * in a two 32 bit samples (left & right) going out.  So
+	 * mono   = (1 byte  in)/(8 bytes out)
+	 * stereo = (2 bytes in)/(8 bytes out)
+	 */
+	if (mono)
+		return toCount0 / 8;
+
+	return toCount0 / 4;
+}
+
+/*
+ * Returns negative for error
+ * Returns # of bytes transferred out of the from buffer
+ * for success.
+ */
+static __inline__ int copy_from_user_with_conversion
+    (struct audio_state_t *state,
+     const char *to, const char *from, int toCount) {
+	int ret = 0;
+
+	if (toCount == 0) {
+		DPRINTK("copy_from_user_with_conversion - nothing to copy!\n");
+	}
+
+	/*
+	 * Compact Mode means that each 32 bit word has both the
+	 * left and right sample in it.
+	 */
+	if (state->output_stream->bCompactMode) {
+		switch (state->output_stream->audio_format) {
+		case AFMT_U8:
+			ret = copy_from_user_U8_CM(state, to, from, toCount);
+			break;
+
+		case AFMT_S16_LE:
+			ret =
+			    copy_from_user_S16_LE_CM(state, to, from, toCount);
+			break;
+
+		case AFMT_S8:
+			ret = copy_from_user_S8_CM(state, to, from, toCount);
+			break;
+
+		case AFMT_U16_LE:
+			ret =
+			    copy_from_user_U16_LE_CM(state, to, from, toCount);
+			break;
+
+		case AFMT_S32_BLOCKED:
+		default:
+			break;
+		}
+	} else {
+		switch (state->output_stream->audio_format) {
+		case AFMT_U8:
+			ret = copy_from_user_U8(state, to, from, toCount);
+			break;
+
+		case AFMT_S16_LE:
+			ret = copy_from_user_S16_LE(state, to, from, toCount);
+			break;
+
+		case AFMT_S8:
+			ret = copy_from_user_S8(state, to, from, toCount);
+			break;
+
+		case AFMT_U16_LE:
+			ret = copy_from_user_U16_LE(state, to, from, toCount);
+			break;
+
+		case AFMT_S32_BLOCKED:
+		default:
+			__copy_from_user((char *)to, from, toCount);
+			ret = toCount;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int audio_ioctl(struct inode *inode, struct file *file,
+		       uint cmd, ulong arg)
+{
+	struct audio_state_t *state =
+	    (struct audio_state_t *)file->private_data;
+	struct audio_stream_t *os = state->output_stream;
+	struct audio_stream_t *is = state->input_stream;
+	long val = 0;
+
+	switch (cmd) {
+	case SNDCTL_DSP_STEREO:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_STEREO\n");
+		if (get_user(val, (int *)arg) || (val > 1) || (val < 0))
+			return -EFAULT;
+
+		if (file->f_mode & FMODE_WRITE) {
+			if (os->audio_num_channels != (val + 1)) {
+				os->audio_num_channels = val + 1;
+				calculate_dma2usr_ratio_etc(os);
+			}
+		}
+
+		if (file->f_mode & FMODE_READ) {
+			if (is->audio_num_channels != (val + 1)) {
+				is->audio_num_channels = val + 1;
+				calculate_dma2usr_ratio_etc(is);
+			}
+		}
+
+		return put_user(val, (long *)arg);
+
+	case SNDCTL_DSP_CHANNELS:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_CHANNELS\n");
+		if (get_user(val, (int *)arg) || (val > 2) || (val < 0))
+			return -EFAULT;
+
+		// Calling with value of 0 is a query.
+		if (val == 0) {
+			if (file->f_mode & FMODE_WRITE)
+				val = os->audio_num_channels;
+			else
+				val = is->audio_num_channels;
+		} else {
+			if (file->f_mode & FMODE_WRITE) {
+				if (os->audio_num_channels != val) {
+					os->audio_num_channels = val;
+					calculate_dma2usr_ratio_etc(os);
+				}
+			}
+			if (file->f_mode & FMODE_READ) {
+				if (is->audio_num_channels != val) {
+					is->audio_num_channels = val;
+					calculate_dma2usr_ratio_etc(is);
+				}
+			}
+		}
+
+		return put_user(val, (long *)arg);
+
+	case SOUND_PCM_READ_CHANNELS:
+		DPRINTK_IOCTL("audio_ioctl - SOUND_PCM_READ_CHANNELS\n");
+		if (file->f_mode & FMODE_WRITE)
+			val = os->audio_num_channels;
+		else
+			val = is->audio_num_channels;
+		return put_user(val, (long *)arg);
+
+	case SNDCTL_DSP_SETFMT:
+		{
+			DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETFMT\n");
+
+			if (get_user(val, (int *)arg))
+				return -EFAULT;
+
+			if (val != AFMT_QUERY) {
+				if ((file->f_mode & FMODE_WRITE)
+				    && (val != os->audio_format)) {
+					audio_set_format(os, val);
+					calculate_dma2usr_ratio_etc(os);
+					if (state->hw->set_hw_serial_format)
+						state->hw->
+						    set_hw_serial_format(os,
+									 val);
+				}
+				if ((file->f_mode & FMODE_READ)
+				    && (val != is->audio_format)) {
+					audio_set_format(is, val);
+					calculate_dma2usr_ratio_etc(is);
+					if (state->hw->set_hw_serial_format)
+						state->hw->
+						    set_hw_serial_format(is,
+									 val);
+				}
+			}
+
+			if (file->f_mode & FMODE_WRITE)
+				return put_user(os->audio_format, (long *)arg);
+			return put_user(is->audio_format, (long *)arg);
+		}
+
+	case SNDCTL_DSP_GETFMTS:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETFMTS\n");
+		return put_user((AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE),
+				(long *)arg);
+
+	case OSS_GETVERSION:
+		DPRINTK_IOCTL("audio_ioctl - OSS_GETVERSION\n");
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	case SNDCTL_DSP_GETBLKSIZE:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETBLKSIZE\n");
+		if (file->f_mode & FMODE_WRITE)
+			return put_user(os->fragsize, (int *)arg);
+		return put_user(is->fragsize, (int *)arg);
+
+	case SNDCTL_DSP_GETCAPS:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETCAPS\n");
+		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:
+		{
+			int ret;
+			DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETFRAGMENT\n");
+			if (get_user(val, (long *)arg))
+				return -EFAULT;
+
+			if (file->f_mode & FMODE_READ) {
+				ret = audio_set_fragments(state, is, val);
+				if (ret < 0)
+					return ret;
+			}
+
+			if (file->f_mode & FMODE_WRITE) {
+				ret = audio_set_fragments(state, os, val);
+				if (ret < 0)
+					return ret;
+			}
+
+			return 0;
+		}
+
+	case SNDCTL_DSP_SYNC:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SYNC\n");
+		return audio_sync(file);
+
+	case SNDCTL_DSP_SETDUPLEX:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETDUPLEX\n");
+		return 0;
+
+	case SNDCTL_DSP_POST:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_POST\n");
+		return 0;
+
+	case SNDCTL_DSP_GETTRIGGER:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETTRIGGER\n");
+		val = 0;
+
+		if (file->f_mode & FMODE_READ && is->active && !is->stopped)
+			val |= PCM_ENABLE_INPUT;
+
+		if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
+			val |= PCM_ENABLE_OUTPUT;
+
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_SETTRIGGER:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETTRIGGER\n");
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+
+		if (file->f_mode & FMODE_READ) {
+			if (val & PCM_ENABLE_INPUT) {
+				if (!is->active) {
+					if (!is->buffers
+					    && audio_allocate_buffers(state,
+								      is))
+						return -ENOMEM;
+					audio_prime_dma(state, is);
+				}
+
+				if (is->stopped) {
+					is->stopped = 0;
+					os->active = 1;
+					audio_dma_start(state, is);
+				}
+			} else {
+				audio_dma_pause(state, is);
+				is->stopped = 1;
+				is->active = 0;
+			}
+		}
+
+		if (file->f_mode & FMODE_WRITE) {
+			if (val & PCM_ENABLE_OUTPUT) {
+				if (!os->active) {
+					if (!os->buffers
+					    && audio_allocate_buffers(state,
+								      os))
+						return -ENOMEM;
+
+					if (os->mapped)
+						audio_prime_dma(state, os);
+				}
+
+				if (os->stopped) {
+					os->stopped = 0;
+					os->active = 1;
+					audio_dma_start(state, os);
+				}
+			} else {
+				audio_dma_pause(state, os);
+				os->stopped = 1;
+				os->active = 0;
+			}
+		}
+		return 0;
+
+	case SNDCTL_DSP_GETOPTR:
+	case SNDCTL_DSP_GETIPTR:
+		{
+			count_info inf = { 0, };
+			struct audio_stream_t *stream =
+			    (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
+			int bytecount, fragcount, buf_num = 0;
+			unsigned int current_frac, buf_id;
+			// KERNEL2.4 SNIP
+			unsigned long flags;
+			unsigned int total = 0;
+			// KERNEL2.4 SNAP
+
+			DPRINTK_IOCTL
+			    ("audio_ioctl - called SNDCTL_DSP_GETOPTR.\n");
+
+			if ((stream == is && !(file->f_mode & FMODE_READ)) ||
+			    (stream == os && !(file->f_mode & FMODE_WRITE)))
+				return -EINVAL;
+
+			if (!stream->active)
+				return copy_to_user((void *)arg, &inf,
+						    sizeof(inf));
+
+			// KERNEL2.4
+			//save_flags_cli(flags);
+			local_irq_save(flags);
+
+			// KERNEL2.4
+			//DMA_GET_POSITION( stream->dmahandles[0], &buf_id, 0,
+			//                &current_frac );
+			DMA_GET_POSITION(stream->dmahandles[0], &buf_id, &total,
+					 &current_frac);
+
+			/*
+			 * Out of a set of nbfrags buffers, which one is the current one?
+			 */
+			if (buf_id)
+				buf_num = ((struct audio_buf_t *)buf_id)->num;
+
+			/*
+			 * The ep93xx-audio ISRs keep track of bytecount and fragcount.
+			 * This bytecount isn't cleared except when the driver is opened
+			 * or when it overflows.
+			 */
+			bytecount = stream->bytecount;
+
+			/* so poll can tell if it changes */
+			stream->getptrCount = stream->bytecount;
+
+			/*
+			 * Return the number of fragment transitions counted in our dma ISR
+			 * since the previous call to this ioctl, then clear that counter.
+			 */
+			fragcount = stream->fragcount;
+			stream->fragcount = 0;
+
+			// KERNEL2.4
+			//restore_flags(flags);
+			local_irq_restore(flags);
+
+			/*
+			 * When reporting position to user app, scale byte counts and the
+			 * ptr to reflect the difference in sample size between dma samples
+			 * and user samples.  But don't scale the # of fragments.
+			 */
+			inf.blocks = fragcount;
+			inf.bytes =
+			    (bytecount + current_frac) / stream->dma2usr_ratio;
+			inf.ptr =
+			    ((buf_num * stream->fragsize) +
+			     current_frac) / stream->dma2usr_ratio;
+
+			return copy_to_user((void *)arg, &inf, sizeof(inf));
+		}
+
+	case SNDCTL_DSP_GETODELAY:
+		{
+			int buffered_bytes_left, count;
+			//unsigned int current_frac;
+			// KERNEL2.4 SNIP
+			unsigned int current_frac = 0;
+			unsigned long flags;
+			unsigned int total = 0, buf_id = 0;
+			// KERNEL2.4SNAP
+
+			if (!(file->f_mode & FMODE_WRITE))
+				return -EINVAL;
+
+			DPRINTK_IOCTL
+			    ("audio_ioctl - called SNDCTL_DSP_GETODELAY.\n");
+
+			// KERNEL2.4
+			//save_flags_cli(flags);
+			local_irq_save(flags);
+
+			// KERNEL2.4
+			//DMA_GET_POSITION( os->dmahandles[0], 0, 0, &current_frac );
+			DMA_GET_POSITION(os->dmahandles[0], &buf_id, &total,
+					 &current_frac);
+
+			buffered_bytes_left = os->buffered_bytes_to_play;
+
+			// KERNEL2.4
+			//restore_flags(flags);
+			local_irq_restore(flags);
+
+			count =
+			    (buffered_bytes_left -
+			     current_frac) / os->dma2usr_ratio;
+
+			return put_user(count, (int *)arg);
+		}
+
+	case SNDCTL_DSP_GETOSPACE:
+		{
+			/*
+			 * It looks like this code is assuming that nobody
+			 * is writing the device while calling this ioctl
+			 * which may be a reasonable assumption.  I hope.
+			 * Maybe.
+			 */
+			audio_buf_info inf = { 0, };
+			int i;
+
+			DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETOSPACE\n");
+
+			if (!(file->f_mode & FMODE_WRITE))
+				return -EINVAL;
+			if (!os->buffers && audio_allocate_buffers(state, os))
+				return -ENOMEM;
+
+			for (i = 0; i < os->nbfrags; i++) {
+				/*
+				 * If the semaphore is 1, the buffer is available.
+				 */
+				if (os->buffers[i].owner != 0) {
+					if (os->buffers[i].size == 0)
+						inf.fragments++;
+
+					inf.bytes +=
+					    os->fragsize - os->buffers[i].size;
+				}
+			}
+
+			inf.fragsize = os->fragsize / os->dma2usr_ratio;
+			inf.fragstotal = os->nbfrags;
+			inf.bytes = inf.bytes / os->dma2usr_ratio;
+
+			return copy_to_user((void *)arg, &inf, sizeof(inf));
+		}
+
+	case SNDCTL_DSP_GETISPACE:
+		{
+			audio_buf_info inf = { 0, };
+			int i;
+
+			DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETISPACE\n");
+
+			if (!(file->f_mode & FMODE_READ))
+				return -EINVAL;
+			if (!is->buffers && audio_allocate_buffers(state, is))
+				return -ENOMEM;
+
+			for (i = 0; i < is->nbfrags; i++) {
+				if (is->buffers[i].owner != 0) {
+					if (is->buffers[i].size == is->fragsize)
+						inf.fragments++;
+
+					inf.bytes += is->buffers[i].size;
+				}
+			}
+
+			inf.fragsize = is->fragsize / is->dma2usr_ratio;
+			inf.fragstotal = is->nbfrags;
+			inf.bytes = inf.bytes / is->dma2usr_ratio;
+
+			return copy_to_user((void *)arg, &inf, sizeof(inf));
+		}
+
+	case SNDCTL_DSP_NONBLOCK:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_NONBLOCK\n");
+		file->f_flags |= O_NONBLOCK;
+		return 0;
+
+	case SNDCTL_DSP_RESET:
+		DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_RESET\n");
+		if (file->f_mode & FMODE_READ)
+			audio_reset_buffers(state, is);
+		if (file->f_mode & FMODE_WRITE)
+			audio_reset_buffers(state, os);
+		return 0;
+
+	default:
+		/*
+		 * Let the client of this module handle the
+		 * non generic ioctls
+		 */
+		return state->hw->client_ioctl(inode, file, cmd, arg);
+	}
+
+	return 0;
+}
+
+static int audio_release(struct inode *inode, struct file *file)
+{
+	struct audio_state_t *state =
+	    (struct audio_state_t *)file->private_data;
+	int i;
+
+	DPRINTK("EP93xx - audio_release -- enter.  Write=%d  Read=%d\n",
+		((file->f_mode & FMODE_WRITE) != 0),
+		((file->f_mode & FMODE_READ) != 0));
+
+	down(&state->sem);
+
+	if (file->f_mode & FMODE_READ) {
+		audio_deallocate_buffers(state, state->input_stream);
+
+		for (i = 0; i < state->input_stream->NumDmaChannels; i++)
+			DMA_FREE(state->input_stream->dmahandles[i]);
+
+		state->rd_ref = 0;
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		/*
+		 * Wait for all our buffers to play.
+		 */
+		audio_sync(file);
+
+		/*
+		 * audio_deallocate_buffers will pause and flush the dma
+		 * then deallocate the buffers.
+		 */
+		audio_deallocate_buffers(state, state->output_stream);
+		for (i = 0; i < state->output_stream->NumDmaChannels; i++)
+			DMA_FREE(state->output_stream->dmahandles[i]);
+
+		state->wr_ref = 0;
+	}
+
+	up(&state->sem);
+
+	DPRINTK("EP93xx - audio_release -- EXIT\n");
+
+	return 0;
+}
+
+/*
+ *  ep93xx_clear_stream_struct
+ *
+ *  Initialize stuff or at least clear it to zero for a stream structure.
+ */
+static void ep93xx_clear_stream_struct(struct audio_stream_t *stream)
+{
+
+	stream->dmahandles[0] = 0;	/* handles for dma driver instances */
+	stream->dmahandles[1] = 0;	/* handles for dma driver instances */
+	stream->dmahandles[2] = 0;	/* handles for dma driver instances */
+	stream->NumDmaChannels = 0;	/* 1, 2, or 3 DMA channels */
+	stream->TX_dma_ch_bitfield = 0;	/* which dma channels used for strm */
+	stream->RX_dma_ch_bitfield = 0;	/* which dma channels used for strm */
+	stream->buffers = 0;	/* array of audio buffer structures */
+	stream->dma_buffer = 0;	/* current buffer used by read/write */
+	stream->dma_buffer_index = 0;	/* index for the pointer above... */
+	stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;	/* fragment i.e. buffer size */
+	stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;	/* nbr of fragments i.e. buffers */
+	stream->requested_fragsize = 0;	/* This is ignored if 0 */
+	stream->requested_nbfrags = 0;	/* This is ignored if 0 */
+	stream->bytecount = 0;	/* nbr of processed bytes */
+	stream->getptrCount = 0;	/* value of bytecount last time */
+	/* anyone asked via GETxPTR */
+	stream->fragcount = 0;	/* nbr of fragment transitions */
+	stream->mapped = 0;	/* mmap()'ed buffers */
+	stream->active = 0;	/* actually in progress */
+	stream->stopped = 0;	/* might be active but stopped */
+	stream->bFirstCaptureBuffer = 1;	/* flag meaning there is junk in rx fifo */
+	stream->buffered_bytes_to_play = 0;
+
+	calculate_dma2usr_ratio_etc(stream);
+}
+
+/*
+ *	ep93xx_audio_attach
+ *
+ *  Initialize the state structure for read or write.  Allocate dma channels.
+ *  Currently each s is a stereo s (one dma channel).
+ *
+ */
+int ep93xx_audio_attach
+    (struct inode *inode, struct file *file, struct audio_state_t *state) {
+	int err, i;
+	struct audio_stream_t *os = state->output_stream;
+	struct audio_stream_t *is = state->input_stream;
+
+	DPRINTK("ep93xx_audio_attach -- enter.  Write=%d  Read=%d\n",
+		((file->f_mode & FMODE_WRITE) != 0),
+		((file->f_mode & FMODE_READ) != 0));
+
+	down(&state->sem);
+
+	/* access control */
+	if (((file->f_mode & FMODE_WRITE) && !os) ||
+	    ((file->f_mode & FMODE_READ) && !is)) {
+		up(&state->sem);
+		return -ENODEV;
+	}
+
+	if (((file->f_mode & FMODE_WRITE) && state->wr_ref) ||
+	    ((file->f_mode & FMODE_READ) && state->rd_ref)) {
+		up(&state->sem);
+		return -EBUSY;
+	}
+
+	/*
+	 * Request DMA channels
+	 */
+	if (file->f_mode & FMODE_WRITE) {
+		DPRINTK("ep93xx_audio_attach -- FMODE_WRITE\n");
+
+		state->wr_ref = 1;
+
+		ep93xx_clear_stream_struct(os);
+
+		err = DMA_REQUEST(&os->dmahandles[0],
+				  os->devicename, os->dmachannel[0]);
+		if (err) {
+			up(&state->sem);
+			DPRINTK
+			    ("ep93xx_audio_attach -- EXIT ERROR dma request failed\n");
+			return err;
+		}
+
+		err = DMA_CONFIG(os->dmahandles[0],
+				 IGNORE_CHANNEL_ERROR,
+				 0, audio_dma_tx_callback, (unsigned int)state);
+		if (err) {
+			DMA_FREE(os->dmahandles[0]);
+			up(&state->sem);
+			DPRINTK
+			    ("ep93xx_audio_attach -- EXIT ERROR dma config failed\n");
+			return err;
+		}
+
+		/*
+		 * Assuming each audio stream is mono or stereo.
+		 */
+		os->NumDmaChannels = 1;
+
+		/*
+		 * Automatically set up the bit field of dma channels used for
+		 * this stream.
+		 */
+		for (i = 0; (i < state->hw->MaxTxDmaChannels); i++) {
+			if (os->dmachannel[i] == state->hw->txdmachannels[0])
+				os->TX_dma_ch_bitfield |= 1;
+
+			if (os->dmachannel[i] == state->hw->txdmachannels[1])
+				os->TX_dma_ch_bitfield |= 2;
+
+			if (os->dmachannel[i] == state->hw->txdmachannels[2])
+				os->TX_dma_ch_bitfield |= 4;
+		}
+
+		DPRINTK("DMA Tx channel bitfield = %x\n",
+			os->TX_dma_ch_bitfield);
+
+		if (state->hw->hw_clear_fifo)
+			state->hw->hw_clear_fifo(os);
+
+		init_waitqueue_head(&os->wq);
+	}
+
+	if (file->f_mode & FMODE_READ) {
+		state->rd_ref = 1;
+
+		ep93xx_clear_stream_struct(is);
+
+		err = DMA_REQUEST(&is->dmahandles[0],
+				  is->devicename, is->dmachannel[0]);
+		if (err) {
+			up(&state->sem);
+			DPRINTK
+			    ("ep93xx_audio_attach -- EXIT ERROR dma request failed\n");
+			return err;
+		}
+
+		err = DMA_CONFIG(is->dmahandles[0],
+				 IGNORE_CHANNEL_ERROR,
+				 0, audio_dma_rx_callback, (unsigned int)state);
+		if (err) {
+			DMA_FREE(is->dmahandles[0]);
+			up(&state->sem);
+			DPRINTK
+			    ("ep93xx_audio_attach -- EXIT ERROR dma config failed\n");
+			return err;
+		}
+
+		is->NumDmaChannels = 1;
+
+		/*
+		 * Automatically set up the bit field of dma channels used for
+		 * this stream.
+		 */
+		for (i = 0; (i < state->hw->MaxRxDmaChannels); i++) {
+			if (is->dmachannel[i] == state->hw->rxdmachannels[0])
+				is->RX_dma_ch_bitfield |= 1;
+
+			if (is->dmachannel[i] == state->hw->rxdmachannels[1])
+				is->RX_dma_ch_bitfield |= 2;
+
+			if (is->dmachannel[i] == state->hw->rxdmachannels[2])
+				is->RX_dma_ch_bitfield |= 4;
+		}
+
+		DPRINTK("DMA Rx channel bitfield = %x\n",
+			is->RX_dma_ch_bitfield);
+
+		init_waitqueue_head(&is->wq);
+	}
+
+	/*
+	 * Fill out the rest of the file_operations struct.
+	 */
+	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;
+
+	up(&state->sem);
+
+	DPRINTK("ep93xx_audio_attach -- EXIT\n");
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ep93xx_audio_attach);
+
+MODULE_DESCRIPTION("Common audio handling for the Cirrus EP93xx processor");
+MODULE_LICENSE("GPL");
diff --git a/sound/oss/ep93xx-audio.h b/sound/oss/ep93xx-audio.h
new file mode 100644
index 0000000..04a0581
--- /dev/null
+++ b/sound/oss/ep93xx-audio.h
@@ -0,0 +1,149 @@
+/*
+ * ep93xx-audio.h
+ *
+ * Common audio handling for the Cirrus Logic EP93xx
+ *
+ * Copyright (c) 2003 Cirrus Logic Corp.
+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
+ *
+ * Taken from sa1100-audio.h
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+
+/*
+ *  Getting this from the rme96xx driver.  Has same numerical value
+ *  as AC3.  Hmmmm.
+ */
+#ifndef AFMT_S32_BLOCKED
+#define AFMT_S32_BLOCKED 0x0000400
+#endif
+
+#define EP93XX_DEFAULT_NUM_CHANNELS      2
+#define EP93XX_DEFAULT_FORMAT            AFMT_S16_LE
+#define EP93XX_DEFAULT_BIT_WIDTH         16
+
+/*
+ * Buffer Management
+ */
+
+struct audio_buf_t {
+
+	int size;		/* buffer size                                  */
+	int sent;		/* indicates that dma has the dma_buffer        */
+	char *start;		/* points to actual buffer                      */
+	dma_addr_t dma_addr;	/* physical buffer address                      */
+	int owner;
+	struct semaphore sem;	/* down before touching the buffer              */
+	int master;		/* owner for buffer allocation,                 */
+	/* contains size when true                      */
+	int num;		/* which out of nbfrags buffers is this?        */
+	struct audio_stream_t *stream;	/* owning stream                                */
+
+};
+
+#define MAX_DEVICE_NAME 20
+
+struct audio_stream_t {
+
+	/* dma stuff */
+	int dmahandles[3];	/* handles for dma driver instances     */
+	char devicename[MAX_DEVICE_NAME];	/* string - name of device              */
+	int NumDmaChannels;	/* 1, 2, or 3 DMA channels              */
+	ep93xx_dma_dev_t dmachannel[3];	/* dma channel numbers                  */
+
+	struct audio_buf_t *buffers;	/* array of audio buffer structures     */
+	struct audio_buf_t *dma_buffer;	/* current buffer used by read/write    */
+	u_int dma_buffer_index;	/* index for the pointer above...       */
+
+	u_int fragsize;		/* fragment i.e. buffer size            */
+	u_int nbfrags;		/* nbr of fragments i.e. buffers        */
+	u_int requested_fragsize;
+	u_int requested_nbfrags;
+
+	int bytecount;		/* nbr of processed bytes               */
+	int getptrCount;	/* value of bytecount last time         */
+	/* anyone asked via GETxPTR             */
+	int fragcount;		/* nbr of fragment transitions          */
+	wait_queue_head_t wq;	/* for poll                             */
+	int mapped:1;		/* mmap()'ed buffers                    */
+	int active:1;		/* actually in progress                 */
+	int stopped:1;		/* might be active but stopped          */
+	u_int TX_dma_ch_bitfield;	/* bit0 = txdma1, bit1= txdma2, etc     */
+	u_int RX_dma_ch_bitfield;	/* bit0 = rxdma1, bit1= rxdma2, etc     */
+	int bFirstCaptureBuffer;	/* flag meaning there is junk in rx fifo */
+
+	/*
+	 * Data about the file format that we are configured to play.
+	 */
+	long audio_num_channels;	/* Range: 1 to 6 */
+	long audio_format;
+	long audio_stream_bitwidth;	/* Range: 8, 16, 24, 32 */
+
+	long sample_rate;	/* Fs in Hz. */
+
+	/*
+	 * Data about how the audio controller and codec are set up.
+	 */
+	int hw_bit_width;	/* width of dac or adc */
+	int bCompactMode;	/* set if 32bits == a stereo sample */
+
+	/*
+	 * dma2usr_ratio = dma sample size (8 or 4 bytes) / usr sample size (8,4,2,1)
+	 */
+	int dma2usr_ratio;
+
+	/*
+	 * This provides a way of determining audio playback position that will not
+	 * overflow.  This is (size of buffers written) - (buffers we've gotten back)
+	 */
+	int buffered_bytes_to_play;
+
+};
+
+/*
+ * No matter how many streams are going, we are using one hardware device.
+ * This struct describes that hardware.
+ */
+struct audio_hw_t {
+
+	ep93xx_dma_dev_t txdmachannels[3];	/* all dma channels available for */
+	ep93xx_dma_dev_t rxdmachannels[3];	/* this audio ctrlr */
+
+	int MaxTxDmaChannels;	/* number of tx and rx channels */
+	int MaxRxDmaChannels;	/* number of tx and rx channels */
+
+	/*
+	 * Pointers to init, shutdown, and ioctl functions.
+	 */
+	void (*hw_enable) (struct audio_stream_t * stream);
+	void (*hw_disable) (struct audio_stream_t * stream);
+	void (*hw_clear_fifo) (struct audio_stream_t * stream);
+	int (*client_ioctl) (struct inode *, struct file *, uint, ulong);
+	void (*set_hw_serial_format) (struct audio_stream_t *, long);
+
+	unsigned int modcnt;	/* count the # of volume writes */
+
+};
+
+/*
+ * State structure for one instance
+ */
+struct audio_state_t {
+	struct audio_stream_t *output_stream;
+	struct audio_stream_t *input_stream;
+
+	struct audio_hw_t *hw;	/* hw info */
+
+	int rd_ref:1;		/* open reference for recording */
+	int wr_ref:1;		/* open reference for playback */
+
+	struct semaphore sem;	/* to protect against races in attach() */
+
+};
+
+/*
+ * Functions exported by this module
+ */
+extern int ep93xx_audio_attach(struct inode *inode, struct file *file,
+			       struct audio_state_t *state);