summaryrefslogtreecommitdiff
path: root/recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff')
-rw-r--r--recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff43746
1 files changed, 43746 insertions, 0 deletions
diff --git a/recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff b/recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff
new file mode 100644
index 0000000000..3dc6b004b8
--- /dev/null
+++ b/recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff
@@ -0,0 +1,43746 @@
+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);