linux 2.6.32: added Sim.One support
authorMarcin Juszkiewicz <marcin@juszkiewicz.com.pl>
Thu, 3 Dec 2009 17:37:47 +0000 (18:37 +0100)
committerMarcin Juszkiewicz <marcin@juszkiewicz.com.pl>
Thu, 3 Dec 2009 17:39:10 +0000 (18:39 +0100)
13 files changed:
recipes/linux/linux-2.6.32/ep93xx/edb9301-fix-machine-id.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/ep93xx-cpuinfo.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/ep93xx-dma.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/ep93xx-eth.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/ep93xx-i2c.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/ep93xx-regs.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/ep93xx-snd-ac97.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/ep93xx-spi.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/ep93xx-touchscreen.patch [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/series [new file with mode: 0644]
recipes/linux/linux-2.6.32/ep93xx/simone-board-def.patch [new file with mode: 0644]
recipes/linux/linux/simone/defconfig [new file with mode: 0644]
recipes/linux/linux_2.6.32.bb

diff --git a/recipes/linux/linux-2.6.32/ep93xx/edb9301-fix-machine-id.patch b/recipes/linux/linux-2.6.32/ep93xx/edb9301-fix-machine-id.patch
new file mode 100644 (file)
index 0000000..7fc04bd
--- /dev/null
@@ -0,0 +1,19 @@
+---
+ arch/arm/tools/mach-types |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.31.orig/arch/arm/tools/mach-types
++++ linux-2.6.31/arch/arm/tools/mach-types
+@@ -473,11 +473,11 @@ hawk                     MACH_HAWK               HAWK                    456
+ ccat91sbc001          MACH_CCAT91SBC001       CCAT91SBC001            457
+ expresso              MACH_EXPRESSO           EXPRESSO                458
+ h4000                 MACH_H4000              H4000                   459
+ dino                  MACH_DINO               DINO                    460
+ ml675k                        MACH_ML675K             ML675K                  461
+-edb9301                       MACH_EDB9301            EDB9301                 462
++edb9301                       MACH_EDB9301            EDB9301                 454
+ edb9315                       MACH_EDB9315            EDB9315                 463
+ reciva_tt             MACH_RECIVA_TT          RECIVA_TT               464
+ cstcb01                       MACH_CSTCB01            CSTCB01                 465
+ cstcb1                        MACH_CSTCB1             CSTCB1                  466
+ shadwell              MACH_SHADWELL           SHADWELL                467
diff --git a/recipes/linux/linux-2.6.32/ep93xx/ep93xx-cpuinfo.patch b/recipes/linux/linux-2.6.32/ep93xx/ep93xx-cpuinfo.patch
new file mode 100644 (file)
index 0000000..5409bf7
--- /dev/null
@@ -0,0 +1,43 @@
+---
+ arch/arm/kernel/setup.c |   12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- linux-2.6.32.orig/arch/arm/kernel/setup.c
++++ linux-2.6.32/arch/arm/kernel/setup.c
+@@ -41,10 +41,15 @@
+ #include <asm/mach/irq.h>
+ #include <asm/mach/time.h>
+ #include <asm/traps.h>
+ #include <asm/unwind.h>
++#if defined(CONFIG_ARCH_EP93XX)
++#include <mach/io.h>
++#include <mach/ep93xx-regs.h>
++#endif
++
+ #include "compat.h"
+ #include "atags.h"
+ #include "tcm.h"
+ #ifndef MEM_SIZE
+@@ -858,13 +863,20 @@ static int c_show(struct seq_file *m, vo
+       seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
+       seq_puts(m, "\n");
+       seq_printf(m, "Hardware\t: %s\n", machine_name);
++#if defined(CONFIG_ARCH_EP93XX)
++      seq_printf(m, "Revision\t: %04x\n",
++           *((unsigned int *)EP93XX_SYSCON_CHIP_ID) >> 28);
++      seq_printf(m, "Serial\t\t: %016x\n",
++           *((unsigned int *)EP93XX_SECURITY_UNIQID));
++#else
+       seq_printf(m, "Revision\t: %04x\n", system_rev);
+       seq_printf(m, "Serial\t\t: %08x%08x\n",
+                  system_serial_high, system_serial_low);
++#endif
+       return 0;
+ }
+ static void *c_start(struct seq_file *m, loff_t *pos)
diff --git a/recipes/linux/linux-2.6.32/ep93xx/ep93xx-dma.patch b/recipes/linux/linux-2.6.32/ep93xx/ep93xx-dma.patch
new file mode 100644 (file)
index 0000000..c8e6c0f
--- /dev/null
@@ -0,0 +1,3641 @@
+---
+ arch/arm/mach-ep93xx/Makefile     |    2 
+ arch/arm/mach-ep93xx/dma_ep93xx.c | 2940 ++++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-ep93xx/dma_ep93xx.h |  676 ++++++++
+ 3 files changed, 3617 insertions(+), 1 deletion(-)
+
+--- linux-2.6.31.orig/arch/arm/mach-ep93xx/Makefile
++++ linux-2.6.31/arch/arm/mach-ep93xx/Makefile
+@@ -1,9 +1,9 @@
+ #
+ # Makefile for the linux kernel.
+ #
+-obj-y                 := core.o clock.o dma-m2p.o gpio.o
++obj-y                 := core.o clock.o dma-m2p.o gpio.o dma_ep93xx.o
+ obj-m                 :=
+ obj-n                 :=
+ obj-                  :=
+ obj-$(CONFIG_MACH_ADSSPHERE)  += adssphere.o
+--- /dev/null
++++ linux-2.6.31/arch/arm/mach-ep93xx/dma_ep93xx.c
+@@ -0,0 +1,2940 @@
++/******************************************************************************
++ * 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/autoconf.h>
++#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( fmt, arg... )  printk( fmt, ##arg )
++#else
++#define DPRINTK( fmt, arg... )
++#endif
++
++/*****************************************************************************
++ *
++ * static global variables
++ *
++ ****************************************************************************/
++ep93xx_dma_t dma_chan[MAX_EP93XX_DMA_CHANNELS];
++
++/*
++ *  lock used to protect the list of dma channels while searching for a free
++ *  channel during dma_request.
++ */
++//static spinlock_t dma_list_lock;
++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);
++              return(-1);
++      }
++
++      /*
++       *  See if this instance is still open
++       */
++      if (!dma_chan[channel].ref_count )
++              return(-1);
++
++      return(channel);
++}
++
++static void dma_m2m_transfer_done(ep93xx_dma_t *dma)
++{
++      unsigned int uiCONTROL;
++      unsigned int M2M_reg_base = dma->reg_base;
++      unsigned int read_back;
++
++      DPRINTK("1  ");
++
++      outl( 0, M2M_reg_base+M2M_OFFSET_INTERRUPT );
++
++      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 buffer descriptor 0
++                       *
++                       * Set the SAR_BASE/DAR_BASE/BCR registers with values
++                       * from the next buffer in the queue.
++                       */
++                      outl( dma->buffer_queue[dma->current_buffer].source,
++                            M2M_reg_base + M2M_OFFSET_SAR_BASE0 );
++
++                      outl( dma->buffer_queue[dma->current_buffer].dest,
++                            M2M_reg_base + M2M_OFFSET_DAR_BASE0 );
++
++                      outl( dma->buffer_queue[dma->current_buffer].size,
++                            M2M_reg_base + M2M_OFFSET_BCR0 );
++
++                      DPRINTK("SAR_BASE0 - 0x%x\n", dma->buffer_queue[dma->current_buffer].source);
++                      DPRINTK("DAR_BASE0 - 0x%x\n", dma->buffer_queue[dma->current_buffer].dest);
++                      DPRINTK("BCR0 - 0x%x\n", dma->buffer_queue[dma->current_buffer].size);
++
++                      /*
++                       * Decrement the new buffer counter
++                       */
++                      dma->new_buffers--;
++
++                      /*
++                       * If there's a second new buffer, we program the
++                       * second buffer descriptor.
++                       */
++                      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 );
++
++                              uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++                              uiCONTROL |= CONTROL_M2M_NFBINTEN;
++                              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++
++                              dma->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
++                               * tranferred, 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 = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++                      uiCONTROL &= ~CONTROL_M2M_ENABLE;
++                      outl( 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;
++              }
++      } else {
++              /*
++               * No buffers to transfer, or old buffers to mark as used,
++               * so disable the channel
++               */
++              uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2M_ENABLE;
++              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++
++              /*
++               * Must read the control register back after a write.
++               */
++              read_back = inl(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;
++      }
++}
++
++static void dma_m2m_next_frame_buffer(ep93xx_dma_t *dma)
++{
++      int loop;
++      unsigned int uiCONTROL;
++      unsigned int M2M_reg_base = dma->reg_base;
++
++      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 complete the
++                       * transfer of the current buffer, move the FSB
++                       * directly to the STALL state where a STALL interrupt
++                       * will be generated.
++                       */
++                      uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++                      uiCONTROL &= ~CONTROL_M2M_NFBINTEN ;
++                      outl( 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("CONTROL - 0x%x \n",
++                                inl(M2M_reg_base+M2M_OFFSET_CONTROL) );
++                      DPRINTK("STATUS - 0x%x \n",
++                                inl(M2M_reg_base+M2M_OFFSET_STATUS) );
++                      DPRINTK("SAR_BASE0 - 0x%x \n",
++                                inl(M2M_reg_base+M2M_OFFSET_SAR_BASE0) );
++                      DPRINTK("SAR_CUR0 - 0x%x \n",
++                                inl(M2M_reg_base+M2M_OFFSET_SAR_CURRENT0) );
++                      DPRINTK("DAR_BASE0 - 0x%x \n",
++                                inl(M2M_reg_base+M2M_OFFSET_DAR_BASE0) );
++                      DPRINTK("DAR_CUR0 - 0x%x \n",
++                                inl(M2M_reg_base+M2M_OFFSET_DAR_CURRENT0) );
++
++                      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%p \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 ( inl(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.
++                               */
++                              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 );
++                      } else {
++                              /*
++                               * Set the SAR_BASE0/DAR_BASE0/BCR0 registers
++                               * with values from the next buffer in the
++                               * queue.
++                               */
++                              outl( dma->buffer_queue[(dma->current_buffer + 1) %
++                                                      MAX_EP93XX_DMA_BUFFERS].source,
++                                    M2M_reg_base+M2M_OFFSET_SAR_BASE0 );
++
++                              outl( dma->buffer_queue[(dma->current_buffer + 1) %
++                                                      MAX_EP93XX_DMA_BUFFERS].dest,
++                                    M2M_reg_base+M2M_OFFSET_DAR_BASE0 );
++
++                              outl( 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--;
++              }
++      } else {
++              /*
++               * Total number of buffers is 0 - really we should never get
++               * here, but just in case.
++               */
++              DPRINTK("9 \n");
++
++              /*
++               *  No new buffers to transfer, so Disable the channel
++               */
++              uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2M_ENABLE;
++              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++
++              /*
++               *  Indicate that the channel is paused by starvation.
++               */
++              dma->pause = 1;
++      }
++}
++
++/*****************************************************************************
++ *
++ * dma_m2m_irq_handler
++ *
++ ****************************************************************************/
++static irqreturn_t
++dma_m2m_irq_handler(int irq, void *dev_id)
++{
++      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;
++      int status;
++
++//    printk("+m2m irq=%d\n", irq);
++
++      /*
++       *  Determine what kind of dma interrupt this is.
++       */
++      status = inl(M2M_reg_base + M2M_OFFSET_INTERRUPT);
++      if ( status & INTERRUPT_M2M_DONEINT )
++              dma_int = DONE; // we're done with a requested dma
++      else if ( status & INTERRUPT_M2M_NFBINT )
++              dma_int = NFB;  // we're done with one dma buffer
++
++      DPRINTK("IRQ: b=%#x st=%#x\n", (int)dma->current_buffer, dma_int);
++
++      switch (dma_int) {
++      /*
++       *  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.
++       */
++      case NFB:
++              dma_m2m_next_frame_buffer(dma);
++              break;
++      /*
++       *  Done interrupt generated, indicating that the transfer is complete.
++       */
++      case DONE:
++              dma_m2m_transfer_done(dma);
++              break;
++
++      default:
++              break;
++      }
++
++      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)
++{
++      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 ( inl(M2P_reg_base+M2P_OFFSET_INTERRUPT) & INTERRUPT_M2P_STALLINT )
++              dma_int = STALL;
++      else if ( inl(M2P_reg_base+M2P_OFFSET_INTERRUPT) & INTERRUPT_M2P_NFBINT )
++              dma_int = NFB;
++      else if ( inl(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
++                               */
++                              outl( dma->buffer_queue[dma->current_buffer].size,
++                                        M2P_reg_base+M2P_OFFSET_MAXCNT0 );
++
++                              /*
++                               * Set the BASE0 register with the buffer base
++                               * address
++                               */
++                              outl( 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
++                                       */
++                                      outl( 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
++                                       */
++                                      outl( 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 = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++                                      uiCONTROL |= CONTROL_M2P_NFBINTEN;
++                                      outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );
++                              }
++                      } else {
++                              /*
++                               *  No new buffers.
++                               */
++                              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 = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++                              uiCONTROL &= ~CONTROL_M2P_ENABLE;
++                              outl( 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",      inl(M2P_reg_base+M2P_OFFSET_STATUS) );
++                              DPRINTK("CONTROL - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_CONTROL) );
++                              DPRINTK("REMAIN - 0x%x \n",      inl(M2P_reg_base+M2P_OFFSET_REMAIN) );
++                              DPRINTK("PPALLOC - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_PPALLOC) );
++                              DPRINTK("BASE0 - 0x%x \n",        inl(M2P_reg_base+M2P_OFFSET_BASE0) );
++                              DPRINTK("MAXCNT0 - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) );
++                              DPRINTK("CURRENT0 - 0x%x \n",   inl(M2P_reg_base+M2P_OFFSET_CURRENT0) );
++                              DPRINTK("BASE1 - 0x%x \n",        inl(M2P_reg_base+M2P_OFFSET_BASE1) );
++                              DPRINTK("MAXCNT1 - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) );
++                              DPRINTK("CURRENT1 - 0x%x \n",   inl(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%p \n", dma->callback);
++                      }
++              } else {
++                      /*
++                       *  No buffers to transfer, or old buffers to mark as used,
++                       *  so Disable the channel
++                       */
++                      uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++                      uiCONTROL &= ~CONTROL_M2P_ENABLE;
++                      outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );
++
++                      /*
++                       *  Must read the control register back after a write.
++                       */
++                      read_back = inl(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 = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++                              uiCONTROL &= ~CONTROL_M2P_NFBINTEN;
++                              outl( 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",      inl(M2P_reg_base+M2P_OFFSET_STATUS) );
++                              DPRINTK("CONTROL - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_CONTROL) );
++                              DPRINTK("REMAIN - 0x%x \n",      inl(M2P_reg_base+M2P_OFFSET_REMAIN) );
++                              DPRINTK("PPALLOC - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_PPALLOC) );
++                              DPRINTK("BASE0 - 0x%x \n",        inl(M2P_reg_base+M2P_OFFSET_BASE0) );
++                              DPRINTK("MAXCNT0 - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) );
++                              DPRINTK("CURRENT0 - 0x%x \n",   inl(M2P_reg_base+M2P_OFFSET_CURRENT0) );
++                              DPRINTK("BASE1 - 0x%x \n",        inl(M2P_reg_base+M2P_OFFSET_BASE1) );
++                              DPRINTK("MAXCNT1 - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) );
++                              DPRINTK("CURRENT1 - 0x%x \n",   inl(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%p \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 ( inl(M2P_reg_base+M2P_OFFSET_STATUS) & STATUS_M2P_NEXTBUFFER ) {
++                                      /*
++                                       *  Set the MAXCNT1 register with the buffer size
++                                       */
++                                      outl( 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
++                                       */
++                                      outl( 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
++                                       */
++                                      outl( 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
++                                       */
++                                      outl( 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--;
++                      }
++              } else {
++                      /*
++                       *  Total number of buffers is 0 - really we should never get here,
++                       *  but just in case.
++                       */
++                      DPRINTK("9 \n");
++
++                      /*
++                       *  No new buffers to transfer, so Disable the channel
++                       */
++                      uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++                      uiCONTROL &= ~CONTROL_M2P_ENABLE;
++                      outl( 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 = inl(M2P_reg_base+M2P_OFFSET_INTERRUPT);
++              uiINTERRUPT &= ~INTERRUPT_M2P_CHERRORINT;
++              outl( 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;
++      /*unsigned long flags;*/
++
++      DPRINTK("DMA Open M2P with hw dev %d\n", device);
++
++      /*
++       *  Lock the dma channel list.
++       */
++      //spin_lock_irqsave(&dma_list_lock, flags);
++      spin_lock(&dma_list_lock);
++
++      /*
++       * 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");
++                              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_irqrestore(&dma_list_lock, flags);
++      spin_unlock(&dma_list_lock);
++      /*
++       *  See if we got a valid channel.
++       */
++      if (channel < 0)
++              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 = inl(/*SYSCON_PWRCNT*/EP93XX_SYSCON_CLOCK_CONTROL);
++      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);
++      }
++      outl( uiPWRCNT, /*SYSCON_PWRCNT*/EP93XX_SYSCON_CLOCK_CONTROL );
++
++      /*
++       *  Clear out the control register before any further setup.
++       */
++      outl( 0, M2P_reg_base+M2P_OFFSET_CONTROL );
++
++      /*
++       *  Setup the peripheral port value in the DMA channel registers.
++       */
++      if (device < 10)
++              outl( (unsigned int)device, M2P_reg_base+M2P_OFFSET_PPALLOC );
++      else
++              outl( (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;
++      /*unsigned long flags;*/
++
++      DPRINTK("DMA Open M2M with hw dev %d\n", device);
++
++      /*
++       *  Lock the dma channel list.
++       */
++      //spin_lock_irqsave(&dma_list_lock, flags);
++      spin_lock(&dma_list_lock);
++
++
++      /*
++       *  Check if this device is already allocated a channel.
++       *  TODO: can one M2M device be allocated multiple channels?
++       */
++      for (loop = 10; loop < 12; 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_irqrestore(&dma_list_lock, flags);
++                              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);
++      spin_unlock(&dma_list_lock);
++      //spin_unlock_irqrestore(&dma_list_lock, flags);
++
++      /*
++       *  See if we got a valid channel.
++       */
++      if (channel < 0)
++              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 = inl(/*SYSCON_PWRCNT*/EP93XX_SYSCON_CLOCK_CONTROL);
++      switch (channel) {
++      case 10:
++              uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH0;
++              break;
++
++      case 11:
++              uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH1;
++              break;
++
++      default:
++              return(-1);
++      }
++      outl( uiPWRCNT, /*SYSCON_PWRCNT*/EP93XX_SYSCON_CLOCK_CONTROL);
++
++      DPRINTK("DMA Open - power control: 0x%x \n", inl(SYSCON_PWRCNT) );
++
++      /*
++       *  Clear out the control register before any further setup.
++       */
++      outl( 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 = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~(CONTROL_M2M_TM_MASK | CONTROL_M2M_RSS_MASK);
++              outl( 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 = inl(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);
++
++              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++              inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              break;
++
++      case DMARx_SSP:
++              /*
++               * Set RSS field to 1, Set NO_HDSK, Set TM field to 2
++               */
++              uiCONTROL = inl(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);
++              outl( 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 = inl(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);
++              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++              break;
++
++      case DMATx_EXT_DREQ:
++              /*
++               * Set TM field to 2, set RSS field to 0
++               */
++              uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~(CONTROL_M2M_RSS_MASK|CONTROL_M2M_TM_MASK);
++              uiCONTROL |= 1<<CONTROL_M2M_TM_SHIFT;
++              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++              break;
++
++      case DMARx_EXT_DREQ:
++              /*
++               * Set TM field to 2, set RSS field to 0
++               */
++              uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~(CONTROL_M2M_RSS_MASK|CONTROL_M2M_TM_MASK);
++              uiCONTROL |= 2<<CONTROL_M2M_TM_SHIFT;
++              outl( 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;
++
++      uiCONTROL = inl(M2M_reg_base + M2M_OFFSET_CONTROL);
++      outl(0, M2M_reg_base + M2M_OFFSET_CONTROL);
++      inl(M2M_reg_base + M2M_OFFSET_CONTROL);
++      outl(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       *  By default we disable the stall interrupt.
++       */
++      uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++      uiCONTROL &= ~CONTROL_M2M_STALLINTEN;
++      outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++
++      /*
++       *  By default we disable the done interrupt.
++       */
++      uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++      uiCONTROL &= ~CONTROL_M2M_DONEINTEN;
++      outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++
++      /*
++       *  Set up the transfer control fields based on values passed in
++       *  the flags_m2m field.
++       */
++      uiCONTROL = inl(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;
++
++      outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++      inl(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.
++       */
++      outl(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 disable the next frame buffer
++       *  interrupt on the channel.
++       */
++      uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++      uiCONTROL &= ~CONTROL_M2M_NFBINTEN;
++      outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++
++      /*
++       * enable the done interrupt.
++       */
++      uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++      uiCONTROL |= CONTROL_M2M_DONEINTEN;
++      outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++
++      /*
++       *  Update the dma channel instance transfer state.
++       */
++      dma->xfer_enable = TRUE;
++      dma->pause = FALSE;
++
++      /*
++       *  Program up the first buffer descriptor with a source and destination
++       *  and a byte count.
++       */
++      outl( dma->buffer_queue[dma->current_buffer].source,
++            M2M_reg_base+M2M_OFFSET_SAR_BASE0 );
++
++      outl( dma->buffer_queue[dma->current_buffer].dest,
++            M2M_reg_base+M2M_OFFSET_DAR_BASE0 );
++
++      outl( dma->buffer_queue[dma->current_buffer].size,
++            M2M_reg_base+M2M_OFFSET_BCR0 );
++
++      /*
++       *  Decrement the new buffers counter.
++       */
++      dma->new_buffers--;
++
++      /*
++       * 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 );
++
++              uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL |= CONTROL_M2M_NFBINTEN;
++              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++
++              dma->new_buffers--;
++      }
++
++      /*
++       *  Now we enable the channel.  This initiates the transfer.
++       */
++      uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++      uiCONTROL |= CONTROL_M2M_ENABLE;
++      outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++      inl(M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       *  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 = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL |= CONTROL_M2M_START;
++              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++      }
++
++      DPRINTK("DMA - It's been started!!");
++      DPRINTK("CONTROL - 0x%x \n",    inl(M2M_reg_base+M2M_OFFSET_CONTROL) );
++      DPRINTK("STATUS - 0x%x \n",      inl(M2M_reg_base+M2M_OFFSET_STATUS) );
++      DPRINTK("BCR0 - 0x%x \n",          dma->buffer_queue[dma->current_buffer].size);
++      DPRINTK("SAR_BASE0 - 0x%x \n",  inl(M2M_reg_base+M2M_OFFSET_SAR_BASE0) );
++      DPRINTK("SAR_CUR0 - 0x%x \n",   inl(M2M_reg_base+M2M_OFFSET_SAR_CURRENT0) );
++      DPRINTK("DAR_BASE0 - 0x%x \n",  inl(M2M_reg_base+M2M_OFFSET_DAR_BASE0) );
++      DPRINTK("DAR_CUR0 - 0x%x \n",   inl(M2M_reg_base+M2M_OFFSET_DAR_CURRENT0) );
++
++      /*
++       *  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");
++              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);
++              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 = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++      uiCONTROL |= CONTROL_M2P_STALLINTEN;
++      outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );
++
++      /*
++       *  Configure the channel for an error from the peripheral.
++       */
++      uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++      if ( flags_m2p && CHANNEL_ERROR_INT_ENABLE )
++              uiCONTROL |= CONTROL_M2P_CHERRORINTEN;
++      else
++              uiCONTROL &= ~CONTROL_M2P_CHERRORINTEN;
++      outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );
++
++      uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++      if ( flags_m2p && CHANNEL_ABORT )
++              uiCONTROL |= CONTROL_M2P_ABRT;
++      else
++              uiCONTROL &= ~CONTROL_M2P_ABRT;
++      outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );
++
++      uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++      if ( flags_m2p && IGNORE_CHANNEL_ERROR )
++              uiCONTROL |= CONTROL_M2P_ICE;
++      else
++              uiCONTROL &= ~CONTROL_M2P_ICE;
++      outl( 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");
++              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);
++      } 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);
++
++                      /*
++                       *  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++) {
++              /*
++               *  Check if we need to restore a paused transfer.
++               */
++              if (dma_pointers[loop]->pause_buf.buf_id != -1)
++                      outl( dma_pointers[loop]->pause_buf.size,
++                            M2P_reg_bases[loop]+M2P_OFFSET_MAXCNT0 );
++              else
++                      outl( 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 = inl(M2P_reg_bases[loop]+M2P_OFFSET_CONTROL);
++              uiCONTROL |= CONTROL_M2P_ENABLE;
++              outl( 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;
++      }
++
++      /*
++       *  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) {
++                      outl( 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 if(dma_pointers[loop]->new_buffers){
++                      outl( dma_pointers[loop]->buffer_queue[
++                                dma_pointers[loop]->current_buffer].source,
++                            M2P_reg_bases[loop]+M2P_OFFSET_BASE0 );
++            dma_pointers[loop]->new_buffers--;
++
++          }
++
++      /*
++       *  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) {
++              /*
++               *  By default we enable the next frame buffer interrupt.
++               */
++              uiCONTROL = inl(M2P_reg_bases[loop]+M2P_OFFSET_CONTROL);
++              uiCONTROL |= CONTROL_M2P_NFBINTEN;
++              outl( uiCONTROL, M2P_reg_bases[loop]+M2P_OFFSET_CONTROL );
++
++                      outl( dma_pointers[loop]->buffer_queue[
++                                (dma_pointers[loop]->current_buffer + 1) %
++                                MAX_EP93XX_DMA_BUFFERS].size,
++                            M2P_reg_bases[loop]+M2P_OFFSET_MAXCNT1 );
++
++                      outl( dma_pointers[loop]->buffer_queue[
++                                (dma_pointers[loop]->current_buffer + 1) %
++                                MAX_EP93XX_DMA_BUFFERS].source,
++                            M2P_reg_bases[loop]+M2P_OFFSET_BASE1 );
++            dma_pointers[loop]->new_buffers--;
++              }
++
++      /*
++        DPRINTK("DMA - It's been started!!");
++        DPRINTK("STATUS - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_STATUS) );
++        DPRINTK("CONTROL - 0x%x \n",  inl(M2P_reg_base+M2P_OFFSET_CONTROL) );
++        DPRINTK("REMAIN - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_REMAIN) );
++        DPRINTK("PPALLOC - 0x%x \n",  inl(M2P_reg_base+M2P_OFFSET_PPALLOC) );
++        DPRINTK("BASE0 - 0x%x \n",      inl(M2P_reg_base+M2P_OFFSET_BASE0) );
++        DPRINTK("MAXCNT0 - 0x%x \n",  inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) );
++        DPRINTK("CURRENT0 - 0x%x \n",   inl(M2P_reg_base+M2P_OFFSET_CURRENT0) );
++        DPRINTK("BASE1 - 0x%x \n",      inl(M2P_reg_base+M2P_OFFSET_BASE1) );
++        DPRINTK("MAXCNT1 - 0x%x \n",  inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) );
++        DPRINTK("CURRENT1 - 0x%x \n",   inl(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;
++#if 0
++      static int peak_total_buffers=0;
++#endif
++      /*
++       *  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");
++              return(-EINVAL);
++      }
++
++      /*
++       *  Get a pointer to the dma instance.
++       */
++      dma = &dma_chan[channel];
++
++#if 0
++      if( dma->total_buffers > peak_total_buffers )
++      {
++          peak_total_buffers=dma->total_buffers;
++          printk("peak_total_buffers=%d\n", peak_total_buffers );
++      }
++#endif
++      /*
++       *  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)
++      {
++              DPRINTK("too many dma buffers: MAX_EP93XX_DMA_BUFFERS set to low ?\n");
++              /*
++               *  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, 0);
++              }
++      }
++
++      /*
++       *  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");
++              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;
++
++      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];
++
++      /*
++       *  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,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 Flush: Invalid dma handle.\n");
++              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);
++
++      /*
++       *  Disable the dma channel
++       */
++      if (channel < 10) {
++              /*
++               *  M2P channel
++               */
++              uiCONTROL = inl(dma->reg_base+M2P_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2P_ENABLE;
++              outl( uiCONTROL, dma->reg_base+M2P_OFFSET_CONTROL );
++      } else {
++              /*
++               *  M2M channel
++               */
++              uiCONTROL = inl(dma->reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2M_ENABLE;
++              outl( uiCONTROL, dma->reg_base+M2M_OFFSET_CONTROL );
++      }
++
++      for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++)
++      {
++              dma->buffer_queue[loop].buf_id = -1;
++              dma->buffer_queue[loop].last = 0;
++      }
++
++      /*
++       *  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;
++
++    /*
++     * Reset the paused buffer.
++     */
++     dma->pause_buf.last = 0;
++     dma->pause_buf.buf_id = -1;
++
++      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");
++              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;
++
++//    DPRINTK("DMA buf_id %d, total %d, frac %d\n", buf_id1, total1, current_frac1);
++
++      /*
++       *  Success.
++       */
++      return(0);
++}
++
++/*****************************************************************************
++ *
++ *  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");
++              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);
++}
++
++/*****************************************************************************
++ *
++ *  int ep93xx_dma_is_done(int handle)
++ *
++ *  Description:      Determines if the specified channel is done
++ *                    transferring the requested data.
++ *
++ *  handle:    handle for the channel to query.
++ *
++ ****************************************************************************/
++int
++ep93xx_dma_is_done(int handle)
++{
++      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 "ep93xx_dma_is_done: Invalid dma handle.\n");
++              return(-EINVAL);
++      }
++
++        /*
++         * Get a pointer to the DMA channel state structure.
++         */
++        dma = &dma_chan[channel];
++
++        /*
++         * See if there are any buffers remaining to be provided to the HW.
++         */
++        if (dma->new_buffers)
++            return 0;
++
++        /*
++         * See if this is a M2P or M2M channel.
++         */
++        if (channel < 10) {
++            /*
++             * If the bytes remaining register of the HW is not zero, then
++             * there is more work to be done.
++             */
++            if (inl(dma->reg_base + M2P_OFFSET_REMAIN) != 0)
++                return 0;
++        } else {
++            /*
++             * If either byte count register in the HW is not zero, then there
++             * is more work to be done.
++             */
++            if ((inl(dma->reg_base + M2M_OFFSET_BCR0) != 0) ||
++                (inl(dma->reg_base + M2M_OFFSET_BCR1) != 0))
++                return 0;
++        }
++
++        /*
++         * The DMA is complete.
++         */
++        return 1;
++}
++
++/*****************************************************************************
++ * 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_DMA) || (device < 0))
++              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);
++              return(-EBUSY);
++      }
++
++      dma = &dma_chan[channel];
++
++        if(dma->terminated==1) {
++           free_irq(dma->irq, (void *) dma);
++           dma->terminated=0;
++        }
++
++      /*
++       *  Request the appropriate IRQ for the specified channel
++       */
++      if (channel < 10)
++              error = request_irq(dma->irq, dma_m2p_irq_handler,
++                                  IRQF_DISABLED, device_id, (void *) dma);
++      else
++              error = request_irq(dma->irq, &dma_m2m_irq_handler,
++                                  IRQF_DISABLED, 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);
++              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) )
++              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",      inl(M2P_reg_base+M2P_OFFSET_STATUS) );
++      DPRINTK("CONTROL - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_CONTROL) );
++      DPRINTK("REMAIN - 0x%x \n",      inl(M2P_reg_base+M2P_OFFSET_REMAIN) );
++      DPRINTK("PPALLOC - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_PPALLOC) );
++      DPRINTK("BASE0 - 0x%x \n",        inl(M2P_reg_base+M2P_OFFSET_BASE0) );
++      DPRINTK("MAXCNT0 - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) );
++      DPRINTK("CURRENT0 - 0x%x \n",   inl(M2P_reg_base+M2P_OFFSET_CURRENT0) );
++      DPRINTK("BASE1 - 0x%x \n",        inl(M2P_reg_base+M2P_OFFSET_BASE1) );
++      DPRINTK("MAXCNT1 - 0x%x \n",    inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) );
++      DPRINTK("CURRENT1 - 0x%x \n",   inl(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",   inl(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");
++              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 = inl(M2P_reg_base+M2P_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2P_ENABLE;
++              outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL );
++      } else {
++              /*
++               *  M2M channel
++               */
++              M2M_reg_base = dma->reg_base;
++
++              uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2M_ENABLE;
++              outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL );
++      }
++
++      /*
++       *  Free the interrupt servicing this dma channel
++       */
++      //free_irq(dma->irq, (void *) dma);
++        dma->terminated=1;
++
++      /*
++       *  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_EP93XX_DMAM2P0 + channel;
++
++                 dma_chan[channel].terminated = 0;
++
++              /*
++               *  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;
++}
++
++arch_initcall(ep93xx_dma_init);
++
++EXPORT_SYMBOL(ep93xx_dma_free);
++EXPORT_SYMBOL(ep93xx_dma_request);
++EXPORT_SYMBOL(ep93xx_dma_flush);
++EXPORT_SYMBOL(ep93xx_dma_pause);
++EXPORT_SYMBOL(ep93xx_dma_remove_buffer);
++EXPORT_SYMBOL(ep93xx_dma_add_buffer);
++EXPORT_SYMBOL(ep93xx_dma_start);
++EXPORT_SYMBOL(ep93xx_dma_config);
+--- /dev/null
++++ linux-2.6.31/arch/arm/mach-ep93xx/dma_ep93xx.h
+@@ -0,0 +1,676 @@
++/*****************************************************************************
++ *
++ * 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_
++
++// as it turns out the ide dma is the biggest dma buffer hog so far
++// in case the HDD is "thinking" (seek/buffer flush)
++// the continueing r/w DMAs to the HDD will be queued up to up to PRD_ENTRIES entries...
++#include <linux/ide.h>
++#define MAX_EP93XX_DMA_BUFFERS      PRD_ENTRIES
++
++#ifndef TRUE
++#define TRUE                        1
++#endif
++
++#ifndef FALSE
++#define FALSE                       0
++#endif
++
++#ifndef NULL
++#define NULL                        0
++#endif
++
++#define EP93XX_DMA_BASE                       (EP93XX_AHB_VIRT_BASE + 0x00000000)
++
++/*****************************************************************************
++ * 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).
++ *
++ ****************************************************************************/
++
++
++/*----------------------------------------------------------------------------------*/
++/* 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
++
++
++//
++/* 8000_0000 - 8000_ffff: DMA  */
++#define DMA_OFFSET              0x000000
++#define DMA_BASE                (EP93XX_DMA_BASE)
++#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
++
++
++
++//-----------------------------------------------------------------------------
++// 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
++
++#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__ */
++
++/*****************************************************************************
++ *
++ * 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 ep9312_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;
++
++    /*
++     * terminated indicates
++     */
++    unsigned int terminated;
++
++
++} 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 // _DMADRV_H_
diff --git a/recipes/linux/linux-2.6.32/ep93xx/ep93xx-eth.patch b/recipes/linux/linux-2.6.32/ep93xx/ep93xx-eth.patch
new file mode 100644 (file)
index 0000000..776cafc
--- /dev/null
@@ -0,0 +1,2718 @@
+Index: linux-2.6.24.7/drivers/net/arm/ep93xx_eth.c
+===================================================================
+--- linux-2.6.24.7.orig/drivers/net/arm/ep93xx_eth.c   2009-09-16 17:26:48.000000000 +0100
++++ linux-2.6.24.7/drivers/net/arm/ep93xx_eth.c        2009-09-16 17:38:23.000000000 +0100
+@@ -1,916 +1,1586 @@
+-/*
+- * EP93xx ethernet network device driver
+- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+- * Dedicated to Marija Kulikova.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- */
+-
+-#include <linux/dma-mapping.h>
++/*----------------------------------------------------------------------------
++ * 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.
++ *
++ * Theory of Operation
++ * Driver Configuration
++ *  - Getting MAC address from system
++ *     To setup identical MAC address for each target board, driver need
++ *      to get a MAC address from system.  Normally, system has a Serial
++ *      EEPROM or other media to store individual MAC address when
++ *      manufacturing.
++ *      The macro GET_MAC_ADDR is prepared to get the MAC address from
++ *      system and one should supply a routine for this purpose.
++ * Driver Initialization
++ * DMA Operation
++ * Cache Coherence
++ *
++ * 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
++ *--------------------------------------------------------------------------*/
+ #include <linux/module.h>
++#include <linux/version.h>
+ #include <linux/kernel.h>
+-#include <linux/netdevice.h>
+-#include <linux/mii.h>
+-#include <linux/etherdevice.h>
+-#include <linux/ethtool.h>
+-#include <linux/init.h>
+-#include <linux/moduleparam.h>
+-#include <linux/platform_device.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
+ #include <linux/delay.h>
+-#include <asm/arch/ep93xx-regs.h>
+-#include <asm/arch/platform.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <asm/system.h>
++#include <asm/bitops.h>
+ #include <asm/io.h>
++#include <asm/dma.h>
++#include <asm/irq.h>
++#include <linux/errno.h>
++#include <linux/init.h>
+-#define DRV_MODULE_NAME               "ep93xx-eth"
+-#define DRV_MODULE_VERSION    "0.1"
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
+-#define RX_QUEUE_ENTRIES      64
+-#define TX_QUEUE_ENTRIES      8
++#include <asm/arch/hardware.h>
+-#define MAX_PKT_SIZE          2044
+-#define PKT_BUF_SIZE          2048
++#include "ep93xx_eth.h"
+-#define REG_RXCTL             0x0000
+-#define  REG_RXCTL_DEFAULT    0x00073800
+-#define REG_TXCTL             0x0004
+-#define  REG_TXCTL_ENABLE     0x00000001
+-#define REG_MIICMD            0x0010
+-#define  REG_MIICMD_READ      0x00008000
+-#define  REG_MIICMD_WRITE     0x00004000
+-#define REG_MIIDATA           0x0014
+-#define REG_MIISTS            0x0018
+-#define  REG_MIISTS_BUSY      0x00000001
+-#define REG_SELFCTL           0x0020
+-#define  REG_SELFCTL_RESET    0x00000001
+-#define REG_INTEN             0x0024
+-#define  REG_INTEN_TX         0x00000008
+-#define  REG_INTEN_RX         0x00000007
+-#define REG_INTSTSP           0x0028
+-#define  REG_INTSTS_TX                0x00000008
+-#define  REG_INTSTS_RX                0x00000004
+-#define REG_INTSTSC           0x002c
+-#define REG_AFP                       0x004c
+-#define REG_INDAD0            0x0050
+-#define REG_INDAD1            0x0051
+-#define REG_INDAD2            0x0052
+-#define REG_INDAD3            0x0053
+-#define REG_INDAD4            0x0054
+-#define REG_INDAD5            0x0055
+-#define REG_GIINTMSK          0x0064
+-#define  REG_GIINTMSK_ENABLE  0x00008000
+-#define REG_BMCTL             0x0080
+-#define  REG_BMCTL_ENABLE_TX  0x00000100
+-#define  REG_BMCTL_ENABLE_RX  0x00000001
+-#define REG_BMSTS             0x0084
+-#define  REG_BMSTS_RX_ACTIVE  0x00000008
+-#define REG_RXDQBADD          0x0090
+-#define REG_RXDQBLEN          0x0094
+-#define REG_RXDCURADD         0x0098
+-#define REG_RXDENQ            0x009c
+-#define REG_RXSTSQBADD                0x00a0
+-#define REG_RXSTSQBLEN                0x00a4
+-#define REG_RXSTSQCURADD      0x00a8
+-#define REG_RXSTSENQ          0x00ac
+-#define REG_TXDQBADD          0x00b0
+-#define REG_TXDQBLEN          0x00b4
+-#define REG_TXDQCURADD                0x00b8
+-#define REG_TXDENQ            0x00bc
+-#define REG_TXSTSQBADD                0x00c0
+-#define REG_TXSTSQBLEN                0x00c4
+-#define REG_TXSTSQCURADD      0x00c8
+-#define REG_MAXFRMLEN         0x00e8
++/*----------------------------------------------------------------------------
++ * The name of the card.
++ * It is used for messages and in the requests for io regions, irqs and ...
++ * This device is not in a card but I used same name in skeleton.c file.
++ *--------------------------------------------------------------------------*/
++#define  cardname  "ep93xx-eth"
++
++
++/****  default MAC address   *************/
++static const U8  default_mac[6] = {0x00, 0xba, 0xd0, 0x0b, 0xad, 0x00};
++
++/*----------------------------------------------------------------------------
++ * 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  Default_IntSrc  (IntEn_RxMIE|IntEn_RxSQIE|IntEn_TxLEIE|IntEn_TIE|IntEn_TxSQIE|IntEn_RxEOFIE|IntEn_RxEOBIE|IntEn_RxHDRIE)
++*/
++#define  Default_IntSrc  (IntEn_TxSQIE|IntEn_RxEOFIE|IntEn_RxEOBIE|IntEn_RxHDRIE)
++
++/****  Length of Device Queue in number of entries
++       (must be less than or equal to 255)  ********************************/
++#define  LEN_QueRxDesc  64             /*length of Rx Descriptor Queue (4 or bigger) Must be power of 2.*/
++#define  LEN_QueRxSts   LEN_QueRxDesc  /*length of Rx Status Queue*/
++#define  LEN_QueTxDesc  8              /*length of Tx Descriptor Queue (4 or bigger) Must be power of 2.*/
++#define  LEN_QueTxSts   LEN_QueTxDesc  /*length of Tx Status Queue*/
++
++/****  Tx Queue fill-up level control  *************************************/
++#define  LVL_TxStop    LEN_QueTxDesc - 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 bytes  ******************************************/
++#define  LEN_RxBuf  (1518+2+16)  /*length of Rx buffer, must be 4-byte aligned*/
++#define  LEN_TxBuf   LEN_RxBuf
++
++/*----------------------------------------------------------------------------
++ * MACRO for ease
++ *--------------------------------------------------------------------------*/
++#define  Align32(a)  (((unsigned int)(a)+3)&~0x03)  /*32bit address alignment*/
++#define  IdxNext(idxCur,len)  (((idxCur)+1)%(len))  /*calc next array index number*/
++
++/****  malloc/free routine for DMA buffer  **********************************/
++ /*use non-cached DMA buffer*/
++#define  MALLOC_DMA(size, pPhyAddr)  dma_alloc_writecombine(NULL, (size), (dma_addr_t*)(pPhyAddr), GFP_KERNEL | GFP_DMA)
++//#define  FREE_DMA(size, vaddr, paddr)            dma_free_writecombine(NULL, (size), (vaddr), (paddr))
+-struct ep93xx_rdesc
+-{
+-      u32     buf_addr;
+-      u32     rdesc1;
+-};
++/*----------------------------------------------------------------------------
++ * DEBUGGING LEVELS
++ *
++ * 0 for normal operation
++ * 1 for slightly more details
++ * >2 for various levels of increasingly useless information
++ *    2 for interrupt tracking, status flags
++ *    3 for packet dumps, etc.
++ *--------------------------------------------------------------------------*/
++//#define _DBG_3
++//#define _DBG_2
++//#define _DBG_1
++//#define _DBG
++
++#ifdef _DBG_3
++#define PRINTK3( fmt, arg... )  printk( fmt, ##arg )
++#else
++#define PRINTK3( fmt, arg... )
++#endif
++
++#ifdef _DBG_2
++#define PRINTK2( fmt, arg... )  printk( fmt, ##arg )
++#else
++#define PRINTK2( fmt, arg... )
++#endif
++
++#ifdef _DBG_1
++#define PRINTK1( fmt, arg... )  printk( fmt, ##arg )
++#else
++#define PRINTK1( fmt, arg... )
++#endif
++
++#ifdef _DBG
++#define PRINTK(x) printk x
++#else
++#define PRINTK(x)
++#endif
++
++
++
++#define  _PRTK_ENTRY      PRINTK2   /*to trace function entries*/
++#define  _PRTK_SWERR      PRINTK    /*logical S/W error*/
++#define  _PRTK_SYSFAIL    PRINTK    /*system service failure*/
++#define  _PRTK_HWFAIL     PRINTK    /*H/W operation failure message*/
++#define  _PRTK_WARN       PRINTK1   /*warning information*/
++#define  _PRTK_INFO       PRINTK2   /*general information*/
++#define  _PRTK_ENTRY_ISR  PRINTK3   /*to trace function entries belong to ISR*/
++#define  _PRTK_WARN_ISR   PRINTK1   /*warning informations from ISR*/
++#define  _PRTK_INFO_ISR   PRINTK3   /*general informations from ISR*/
++#define  _PRTK_           PRINTK    /*for temporary print out*/
++
++#if 0
++# define  _PRTK_DUMP       PRINTK1   /*to dump large amount of debug info*/
++#endif
++
++/*----------------------------------------------------------------------------
++ * Custom Data Structures
++ *--------------------------------------------------------------------------*/
++
++/****  the information about the buffer passed to device.
++       there are matching bufferDescriptor informations
++       for each Tx/Rx Descriptor Queue entry to trace
++       the buffer within those queues.  ************************************/
++typedef  struct bufferDescriptor  {
++    void  *vaddr;                /*virtual address representing the buffer passed to device*/
++    int(*pFreeRtn)(void *pBuf);  /*free routine*/
++}  bufferDescriptor;
++
++/****  device privite informations
++       pointed by struct net_device::priv  *********************************/
++typedef  struct ep93xxEth_info  {
++    /****  static device informations  **********************************/
++    struct {
++        int                 id;            /*device instance ID (0 for 1st and so on)
++                                             must be first element of this structure*/
++        receiveDescriptor   *pQueRxDesc;   /*pointer to Rx Descriptor Queue*/
++        receiveStatus       *pQueRxSts;    /*pointer to Rx Status Queue*/
++        transmitDescriptor  *pQueTxDesc;   /*pointer to Tx Descriptor Queue*/
++        transmitStatus      *pQueTxSts;    /*pointer to Tx Status Queue*/
++        unsigned char       *pRxBuf;       /*base of Rx Buffer pool*/
++        unsigned char       *pTxBuf;       /*base of Tx Buffer pool*/
++        unsigned long       phyQueueBase;  /*physical address of device queues*/
++        unsigned long       phyQueRxDesc,  /*physical address of Rx Descriptor Queue*/
++                            phyQueRxSts,   /*physical address of Rx Status Queue*/
++                            phyQueTxDesc,  /*physical address of Tx Descriptor Queue*/
++                            phyQueTxSts,   /*physical address of Tx Status Queue*/
++                            phyRxBuf,      /*physical address of Rx Buffer pool*/
++                            phyTxBuf;      /*physical address of Tx Buffer pool*/
++        bufferDescriptor    *pRxBufDesc,   /*info of Rx Buffers*/
++                            *pTxBufDesc;   /*info of Tx Buffers*/
++        int                 miiIdPhy;      /*MII Bus ID of Ethernet PHY*/
++    }  s;
++    /****  dynamic information, subject to clear when device open  ******/
++    struct {
++        struct net_device_stats  stats;  /*statistic data*/
++        int  idxQueRxDesc,       /*next processing index of device queues*/
++             idxQueRxSts,
++             idxQueTxDescHead,
++             idxQueTxDescTail,
++             idxQueTxSts;
++        int  txStopped;          /*flag for Tx condition*/
++    }  d;
++}  ep93xxEth_info;
++
++/*----------------------------------------------------------------------------
++ * Global Variables
++ *--------------------------------------------------------------------------*/
++static int  numOfInstance = 0;  /*total number of device instance, 0 means the 1st instance.*/
++
++//static struct sk_buff gTxSkb;
++//static char gTxBuff[LEN_TxBuf];
+-#define RDESC1_NSOF           0x80000000
+-#define RDESC1_BUFFER_INDEX   0x7fff0000
+-#define RDESC1_BUFFER_LENGTH  0x0000ffff
++//static char gTxDataBuff[LEN_QueTxDesc][LEN_TxBuf];
+-struct ep93xx_rstat
+-{
+-      u32     rstat0;
+-      u32     rstat1;
+-};
++// To know if PHY auto-negotiation has done?
++static int gPhyAutoNegoDone=0;
+-#define RSTAT0_RFP            0x80000000
+-#define RSTAT0_RWE            0x40000000
+-#define RSTAT0_EOF            0x20000000
+-#define RSTAT0_EOB            0x10000000
+-#define RSTAT0_AM             0x00c00000
+-#define RSTAT0_RX_ERR         0x00200000
+-#define RSTAT0_OE             0x00100000
+-#define RSTAT0_FE             0x00080000
+-#define RSTAT0_RUNT           0x00040000
+-#define RSTAT0_EDATA          0x00020000
+-#define RSTAT0_CRCE           0x00010000
+-#define RSTAT0_CRCI           0x00008000
+-#define RSTAT0_HTI            0x00003f00
+-#define RSTAT1_RFP            0x80000000
+-#define RSTAT1_BUFFER_INDEX   0x7fff0000
+-#define RSTAT1_FRAME_LENGTH   0x0000ffff
++/*============================================================================
++ *
++ * Internal Routines
++ *
++ *==========================================================================*/
+-struct ep93xx_tdesc
++/*****************************************************************************
++* free_skb()
++*****************************************************************************/
++static int
++free_skb(void *pSkb)
+ {
+-      u32     buf_addr;
+-      u32     tdesc1;
+-};
++      dev_kfree_skb_irq((struct sk_buff*)pSkb);
++      return 0;
++}
+-#define TDESC1_EOF            0x80000000
+-#define TDESC1_BUFFER_INDEX   0x7fff0000
+-#define TDESC1_BUFFER_ABORT   0x00008000
+-#define TDESC1_BUFFER_LENGTH  0x00000fff
++/*****************************************************************************
++* waitOnReg32()
++*****************************************************************************/
++static int
++waitOnReg32(struct net_device *pD, int reg, unsigned long mask,
++          unsigned long expect, int tout)
++{
++      int  i;
++      int  dt;
++
++      for (i = 0; i < 10000; ) {
++              dt = RegRd32(reg);
++              dt = (dt ^ expect) & mask;
++              if (dt == 0)
++                      break;
++              if (tout)
++                      i++;
++      }
+-struct ep93xx_tstat
+-{
+-      u32     tstat0;
+-};
++      return dt;
++}
+-#define TSTAT0_TXFP           0x80000000
+-#define TSTAT0_TXWE           0x40000000
+-#define TSTAT0_FA             0x20000000
+-#define TSTAT0_LCRS           0x10000000
+-#define TSTAT0_OW             0x04000000
+-#define TSTAT0_TXU            0x02000000
+-#define TSTAT0_ECOLL          0x01000000
+-#define TSTAT0_NCOLL          0x001f0000
+-#define TSTAT0_BUFFER_INDEX   0x00007fff
+-
+-struct ep93xx_descs
+-{
+-      struct ep93xx_rdesc     rdesc[RX_QUEUE_ENTRIES];
+-      struct ep93xx_tdesc     tdesc[TX_QUEUE_ENTRIES];
+-      struct ep93xx_rstat     rstat[RX_QUEUE_ENTRIES];
+-      struct ep93xx_tstat     tstat[TX_QUEUE_ENTRIES];
+-};
++#define  phy_wr(reg,dt)  _phy_write(pD, ((ep93xxEth_info*)pD->priv)->s.miiIdPhy, (reg), (dt))
++#define  phy_rd(reg)     _phy_read(pD, ((ep93xxEth_info*)pD->priv)->s.miiIdPhy, (reg))
++#define  phy_waitRdy()  waitOnReg32(pD, REG_MIISts,MIISts_Busy, ~MIISts_Busy, 1)
+-struct ep93xx_priv
++/*****************************************************************************
++* _phy_write()
++*****************************************************************************/
++static void
++_phy_write(struct net_device *pD, int idPhy, int reg, U16 dt)
+ {
+-      struct resource         *res;
+-      void                    *base_addr;
+-      int                     irq;
++      phy_waitRdy();
++      RegWr32(REG_MIIData, dt);
++      RegWr32(REG_MIICmd, MIICmd_OP_WR | ((idPhy & 0x1f) << 5) |
++              ((reg & 0x1f) << 0));
++}
+-      struct ep93xx_descs     *descs;
+-      dma_addr_t              descs_dma_addr;
++/*****************************************************************************
++* _phy_read()
++*****************************************************************************/
++static U16
++_phy_read(struct net_device *pD,int idPhy,int reg)
++{
++      U16  dt;
+-      void                    *rx_buf[RX_QUEUE_ENTRIES];
+-      void                    *tx_buf[TX_QUEUE_ENTRIES];
++      phy_waitRdy();
++      RegWr32(REG_MIICmd, MIICmd_OP_RD | ((idPhy & 0x1f) << 5) |
++              ((reg & 0x1f) << 0));
++      phy_waitRdy();
++      dt = (unsigned short)RegRd32(REG_MIIData);
+-      spinlock_t              rx_lock;
+-      unsigned int            rx_pointer;
+-      unsigned int            tx_clean_pointer;
+-      unsigned int            tx_pointer;
+-      spinlock_t              tx_pending_lock;
+-      unsigned int            tx_pending;
++      return dt;
++}
+-      struct net_device       *dev;
+-      struct napi_struct      napi;
++#ifndef _PRTK_DUMP
++#define _dbg_phy_dumpReg(pD)
++#else
++/*****************************************************************************
++* _dbg_phy_dumpReg()
++*****************************************************************************/
++static void
++_dbg_phy_dumpReg(struct net_device *pD)
++{
++      _PRTK_DUMP(("Dumping registers of Ethernet PHY\n"));
++      _PRTK_DUMP((" pD:0x%p, Eth Base Address:0x%x\n", pD,
++                  (unsigned int)pD->base_addr));
+-      struct net_device_stats stats;
++      _PRTK_DUMP((" 0-3:0x%04x 0x%04x  0x%04x 0x%04x\n",
++                  phy_rd(0), phy_rd(1), phy_rd(2), phy_rd(3)));
++      _PRTK_DUMP((" 4-6:0x%04x 0x%04x  0x%04x\n",
++                  phy_rd(4), phy_rd(5), phy_rd(6)));
++      _PRTK_DUMP((" 16-19:0x%04x 0x%04x  0x%04x  0x%04x\n",
++                  phy_rd(16), phy_rd(17), phy_rd(18), phy_rd(19)));
++      _PRTK_DUMP((" 20:0x%04x\n", phy_rd(20)));
++}
++#endif
+-      struct mii_if_info      mii;
+-      u8                      mdc_divisor;
+-};
++/*****************************************************************************
++* phy_autoNegotiation()
++*****************************************************************************/
++static int
++phy_autoNegotiation(struct net_device *pD)
++{
++      U16 val;
++      U16 oldVal;
++      U16 count = 0;
+-#define rdb(ep, off)          __raw_readb((ep)->base_addr + (off))
+-#define rdw(ep, off)          __raw_readw((ep)->base_addr + (off))
+-#define rdl(ep, off)          __raw_readl((ep)->base_addr + (off))
+-#define wrb(ep, off, val)     __raw_writeb((val), (ep)->base_addr + (off))
+-#define wrw(ep, off, val)     __raw_writew((val), (ep)->base_addr + (off))
+-#define wrl(ep, off, val)     __raw_writel((val), (ep)->base_addr + (off))
++      phy_wr(4, 0x01e1);  /*Set 802.3, 100M/10M Full/Half ability*/
++      phy_wr(0, (1 << 12) | (1 << 9)); /* enable auto negotiation*/
++      while (1) {
++              val = phy_rd(1); /* read BM status Reg*/
++              if (val & 0x0020) /* if Auto_Neg_complete?*/
++                      break;
++              else {
++                      if (count >= 3)
++                              return -1;
++                      mdelay(1000);//delay 1 second.
++                      count++;
++              }
++      }
+-static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg);
++      //CS8952 PHY needs the delay.  Otherwise it won't send the 1st frame.
++      mdelay(1000);//delay 1 second.
+-static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      return &(ep->stats);
++      val = phy_rd(5); /* read ANLPAR Reg*/
++      if (val & 0x0140) { /* if 100M_FDX or 10M_FDX?*/
++              oldVal = RegRd16(REG_TestCTL);
++              /*Enable MAC's Full Duplex mode.*/
++              RegWr16(REG_TestCTL, oldVal | TestCTL_MFDX);
++      }
++
++      gPhyAutoNegoDone = 1;
++
++      return 0;
+ }
+-static int ep93xx_rx(struct net_device *dev, int processed, int budget)
++/*****************************************************************************
++* phy_init()
++*****************************************************************************/
++static int
++phy_init(struct net_device *pD)
++{
++      U32 oldVal;
++      int status = -1;
++      U16 val;
++
++      oldVal = RegRd32(REG_SelfCTL);
++
++      /*
++       * Set MDC clock to be divided by 8 and disable PreambleSuppress bit
++       */
++      RegWr32(REG_SelfCTL, 0x4e00);
++
++      /*
++       * read BM status Reg; Link Status Bit remains cleared until the Reg is
++       * read.
++       */
++      val = phy_rd(1);
++
++      /*
++       * read BMStaReg again to get the current link status
++       */
++      val = phy_rd(1);
++      if (val & 0x0004)
++              status = phy_autoNegotiation(pD);
++
++      RegWr32(REG_SelfCTL, oldVal);
++
++      return status;
++}
++
++/*****************************************************************************
++* phy_reset()
++*****************************************************************************/
++#if 0
++static int
++phy_reset(struct net_device *pD)
+ {
+-      struct ep93xx_priv *ep = netdev_priv(dev);
++      int i;
+-      while (processed < budget) {
+-              int entry;
+-              struct ep93xx_rstat *rstat;
+-              u32 rstat0;
+-              u32 rstat1;
+-              int length;
+-              struct sk_buff *skb;
+-              entry = ep->rx_pointer;
+-              rstat = ep->descs->rstat + entry;
++      phy_wr(0, 1 << 15);
+-              rstat0 = rstat->rstat0;
+-              rstat1 = rstat->rstat1;
+-              if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP))
++      for (i = 0; i < 1000; i++)
++              if ((phy_rd(0) & (1 << 15)) == 0)
+                       break;
+-              rstat->rstat0 = 0;
+-              rstat->rstat1 = 0;
++      if ((phy_rd(0) & (1 << 15)) != 0) {
++              _PRTK_HWFAIL(("phy_reset(): PHY reset does not self-clear\n"));
++              return -1;
++      }
+-              if (!(rstat0 & RSTAT0_EOF))
+-                      printk(KERN_CRIT "ep93xx_rx: not end-of-frame "
+-                                       " %.8x %.8x\n", rstat0, rstat1);
+-              if (!(rstat0 & RSTAT0_EOB))
+-                      printk(KERN_CRIT "ep93xx_rx: not end-of-buffer "
+-                                       " %.8x %.8x\n", rstat0, rstat1);
+-              if ((rstat1 & RSTAT1_BUFFER_INDEX) >> 16 != entry)
+-                      printk(KERN_CRIT "ep93xx_rx: entry mismatch "
+-                                       " %.8x %.8x\n", rstat0, rstat1);
+-
+-              if (!(rstat0 & RSTAT0_RWE)) {
+-                      ep->stats.rx_errors++;
+-                      if (rstat0 & RSTAT0_OE)
+-                              ep->stats.rx_fifo_errors++;
+-                      if (rstat0 & RSTAT0_FE)
+-                              ep->stats.rx_frame_errors++;
+-                      if (rstat0 & (RSTAT0_RUNT | RSTAT0_EDATA))
+-                              ep->stats.rx_length_errors++;
+-                      if (rstat0 & RSTAT0_CRCE)
+-                              ep->stats.rx_crc_errors++;
+-                      goto err;
+-              }
+-
+-              length = rstat1 & RSTAT1_FRAME_LENGTH;
+-              if (length > MAX_PKT_SIZE) {
+-                      printk(KERN_NOTICE "ep93xx_rx: invalid length "
+-                                       " %.8x %.8x\n", rstat0, rstat1);
+-                      goto err;
+-              }
+-
+-              /* Strip FCS.  */
+-              if (rstat0 & RSTAT0_CRCI)
+-                      length -= 4;
+-
+-              skb = dev_alloc_skb(length + 2);
+-              if (likely(skb != NULL)) {
+-                      skb_reserve(skb, 2);
+-                      dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr,
+-                                              length, DMA_FROM_DEVICE);
+-                      skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
+-                      skb_put(skb, length);
+-                      skb->protocol = eth_type_trans(skb, dev);
++      phy_wr(19, 0x00);
++      phy_wr(4, (1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (0x01 << 0));
++      phy_wr(0, (1 << 12) | (1 << 9));
+-                      dev->last_rx = jiffies;
++      return 0;
++}
++#endif
+-                      netif_receive_skb(skb);
++#ifndef _PRTK_DUMP
++# define _dbg_ep93xxEth_dumpQueues(pD)
++#else
++/*****************************************************************************
++* _dbg_ep93xxEth_dumpQueues()
++*****************************************************************************/
++static void
++_dbg_ep93xxEth_dumpQueues(struct net_device *pD)
++{
++      struct ep93xxEth_info *pP = pD->priv;
++      int i;
+-                      ep->stats.rx_packets++;
+-                      ep->stats.rx_bytes += length;
+-              } else {
+-                      ep->stats.rx_dropped++;
+-              }
++      _PRTK_DUMP(("Dumping Descriptor/Status Queues\n"));
++      _PRTK_DUMP((" pD:0x%p, Base Address:0x%x\n", pD,
++                  (unsigned int)pD->base_addr));
++
++      _PRTK_DUMP((" o Rx Status Queue: at 0x%p, %d entries\n",
++                  pP->s.pQueRxSts, LEN_QueRxSts));
++      for (i = 0; i < LEN_QueRxSts; i++)
++              _PRTK_DUMP(("  - %2d: 0x%08x 0x%08x \n", i,
++                          (unsigned int)pP->s.pQueRxSts[i].w.e0,
++                          (unsigned int)pP->s.pQueRxSts[i].w.e1));
++
++      _PRTK_DUMP((" o Rx Descriptor Queue: at 0x%p, %d entries\n",
++                  pP->s.pQueRxDesc, LEN_QueRxDesc));
++      for (i = 0; i < LEN_QueRxDesc; i++)
++              _PRTK_DUMP(("  - %2d: 0x%08x 0x%08x \n", i,
++                          (unsigned int)pP->s.pQueRxDesc[i].w.e0,
++                          (unsigned int)pP->s.pQueRxDesc[i].w.e1));
++
++      _PRTK_DUMP((" o Tx Status Queue: at 0x%p, %d entries\n",
++                  pP->s.pQueTxSts, LEN_QueTxSts));
++      for (i = 0; i < LEN_QueTxSts; i++)
++              _PRTK_DUMP(("  - %2d: 0x%08x \n", i,
++                          (unsigned int)pP->s.pQueTxSts[i].w.e0));
++
++      _PRTK_DUMP((" o Tx Descriptor Queue: at 0x%p, %d entries\n",
++                  pP->s.pQueTxDesc, LEN_QueTxDesc));
++      for (i = 0; i < LEN_QueTxDesc; i++)
++              _PRTK_DUMP(("  - %2d: 0x%08x 0x%08x \n", i,
++                          (unsigned int)pP->s.pQueTxDesc[i].w.e0,
++                          (unsigned int)pP->s.pQueTxDesc[i].w.e1));
++}
++#endif
++
++/*****************************************************************************
++* 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 *pD)
++{
++      int err;
++      struct ep93xxEth_info *pP = pD->priv;
++      int i;
++      void *pBuf;
++      U32 phyA;
+-err:
+-              ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1);
+-              processed++;
+-      }
++      RegWr32(REG_BMCtl, BMCtl_RxDis | BMCtl_TxDis | RegRd32(REG_BMCtl));
++      err = waitOnReg32(pD, REG_BMSts, BMSts_TxAct, ~BMSts_TxAct, 1);
++      err |= waitOnReg32(pD, REG_BMSts, BMSts_RxAct, ~BMSts_RxAct, 1);
++      if (err)
++              _PRTK_HWFAIL(("devQue_start(): BM does not stop\n"));
++
++      memset(pP->s.pQueTxSts, 0, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);
++      pP->d.idxQueTxSts = 0;
++      RegWr32(REG_TxSBA, pP->s.phyQueTxSts);
++      RegWr32(REG_TxSCA, pP->s.phyQueTxSts);
++      RegWr16(REG_TxSBL, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);
++      RegWr16(REG_TxSCL, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);
++
++      memset(pP->s.pQueTxDesc, 0,
++             sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc);
++      pP->d.idxQueTxDescHead = pP->d.idxQueTxDescTail = 0;
++      RegWr32(REG_TxDBA, pP->s.phyQueTxDesc);
++      RegWr32(REG_TxDCA, pP->s.phyQueTxDesc);
++      RegWr16(REG_TxDBL, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc);
++      RegWr16(REG_TxDCL, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc);
++
++      memset(pP->s.pQueRxSts, 0, sizeof(pP->s.pQueRxSts[0]) * LEN_QueRxSts);
++      pP->d.idxQueRxSts = 0;
++      RegWr32(REG_RxSBA, pP->s.phyQueRxSts);
++      RegWr32(REG_RxSCA, pP->s.phyQueRxSts);
++      RegWr16(REG_RxSBL, sizeof(pP->s.pQueRxSts[0]) * LEN_QueRxSts);
++      RegWr16(REG_RxSCL, sizeof(pP->s.pQueRxSts[0]) * LEN_QueRxSts);
++
++      memset(pP->s.pQueRxDesc, 0,
++             sizeof(pP->s.pQueRxDesc[0]) * LEN_QueRxDesc);
++      phyA = pP->s.phyRxBuf;
++      for (i = 0; i < LEN_QueRxDesc; i++) {
++              pP->s.pQueRxDesc[i].f.bi = i;
++              pP->s.pQueRxDesc[i].f.ba = phyA;
++              pP->s.pQueRxDesc[i].f.bl = LEN_RxBuf;
++              phyA += (LEN_RxBuf + 3) & ~0x03;
++      }
++      pP->d.idxQueRxDesc = 0;
++      RegWr32(REG_RxDBA, pP->s.phyQueRxDesc);
++      RegWr32(REG_RxDCA, pP->s.phyQueRxDesc);
++      RegWr16(REG_RxDBL, sizeof(pP->s.pQueRxDesc[0]) * LEN_QueRxDesc);
++      RegWr16(REG_RxDCL, sizeof(pP->s.pQueRxDesc[0]) * LEN_QueRxDesc);
++
++      pBuf = pP->s.pRxBuf;
++      for (i = 0; i < LEN_QueRxDesc; i++) {
++              pP->s.pRxBufDesc[i].vaddr = pBuf;
++              pP->s.pRxBufDesc[i].pFreeRtn = 0;
++              pBuf += (LEN_RxBuf + 3) & ~0x03;
++      }
++
++      memset(pP->s.pTxBufDesc, 0x0,
++             sizeof(*pP->s.pTxBufDesc) * LEN_QueTxDesc);
++      pBuf = pP->s.pTxBuf;// = &gTxDataBuff[0][0];
++      for (i = 0; i < LEN_QueTxDesc; i++) {
++              pP->s.pTxBufDesc[i].vaddr =  pBuf + (i*LEN_TxBuf);//&gTxDataBuff[i][0];
++              pP->s.pTxBufDesc[i].pFreeRtn = 0;
++      }
++
++      RegWr32(REG_BMCtl, BMCtl_TxEn | BMCtl_RxEn | RegRd32(REG_BMCtl));
++      err = waitOnReg32(pD, REG_BMSts, BMSts_TxAct | BMSts_TxAct,
++                        BMSts_TxAct | BMSts_TxAct, 1);
++      if(err)
++              _PRTK_HWFAIL(("devQue_start(): BM does not start\n"));
+-      if (processed) {
+-              wrw(ep, REG_RXDENQ, processed);
+-              wrw(ep, REG_RXSTSENQ, processed);
+-      }
++      RegWr32(REG_RxSEQ, LEN_QueRxSts);
++      RegWr32(REG_RxDEQ, LEN_QueRxDesc);
+-      return processed;
++      return 0;
+ }
+-static int ep93xx_have_more_rx(struct ep93xx_priv *ep)
+-{
+-      struct ep93xx_rstat *rstat = ep->descs->rstat + ep->rx_pointer;
+-      return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP));
+-}
++/*****************************************************************************
++* devQue_init()
++  init device descriptor queues at system level
++  device access is not recommended at this point
++*
++*****************************************************************************/
++static int
++devQue_init(struct net_device *pD)
++{
++      struct ep93xxEth_info *pP = pD->priv;
++      void *pBuf;
++      int size;
++
++      if (sizeof(receiveDescriptor) != 8) {
++              _PRTK_SWERR(("devQue_init(): size of receiveDescriptor is not 8 bytes!!!\n"));
++              return -1;
++      } else if (sizeof(receiveStatus) != 8) {
++              _PRTK_SWERR(("devQue_init(): size of receiveStatus is not 8 bytes!!!\n"));
++              return -1;
++      } else if (sizeof(transmitDescriptor) != 8) {
++              _PRTK_SWERR(("devQue_init(): size of transmitDescriptor is not 8 bytes!!!\n"));
++              return -1;
++      } else if (sizeof(transmitStatus) != 4) {
++              _PRTK_SWERR(("devQue_init(): size of transmitStatus is not 4 bytes!!!\n"));
++              return -1;
++      }
++
++      size = sizeof(receiveDescriptor) * (LEN_QueRxDesc + 1) +
++              sizeof(receiveStatus) * (LEN_QueRxSts + 1) +
++              sizeof(transmitDescriptor) * (LEN_QueTxDesc + 1) +
++              sizeof(transmitStatus) * (LEN_QueTxSts + 1) +
++              sizeof(unsigned long) * 4;
++
++      pBuf = MALLOC_DMA(size, &pP->s.phyQueueBase);
++      if(!pBuf)
++              return -1;
++
++      pP->s.pQueRxDesc = (void *)Align32(pBuf);
++      pBuf = (char *)pBuf + sizeof(receiveDescriptor) * (LEN_QueRxDesc + 1);
++      pP->s.pQueRxSts = (void *)Align32(pBuf);
++      pBuf = (char *)pBuf + sizeof(receiveStatus) * (LEN_QueRxSts + 1);
++      pP->s.pQueTxDesc = (void *)Align32(pBuf);
++      pBuf = (char *)pBuf + sizeof(transmitDescriptor) * (LEN_QueTxDesc + 1);
++      pP->s.pQueTxSts = (void *)Align32(pBuf);
++      pBuf = (char *)pBuf + sizeof(transmitStatus) * (LEN_QueTxSts + 1);
++
++      pP->s.phyQueRxDesc = Align32(pP->s.phyQueueBase);
++      pP->s.phyQueRxSts = pP->s.phyQueRxDesc + ((U32)pP->s.pQueRxSts -
++                                                (U32)pP->s.pQueRxDesc);
++      pP->s.phyQueTxDesc = pP->s.phyQueRxDesc + ((U32)pP->s.pQueTxDesc -
++                                                 (U32)pP->s.pQueRxDesc);
++      pP->s.phyQueTxSts = pP->s.phyQueRxDesc + ((U32)pP->s.pQueTxSts -
++                                                (U32)pP->s.pQueRxDesc);
++
++      memset(pP->s.pQueRxDesc, 0, sizeof(receiveDescriptor) * LEN_QueRxDesc);
++      memset(pP->s.pQueRxSts, 0, sizeof(receiveStatus) * LEN_QueRxSts);
++      memset(pP->s.pQueTxDesc, 0,
++             sizeof(transmitDescriptor) * LEN_QueTxDesc);
++      memset(pP->s.pQueTxSts, 0, sizeof(transmitStatus) * LEN_QueTxSts);
++
++      pP->s.pRxBuf = MALLOC_DMA(((LEN_RxBuf + 3) & ~0x03) * LEN_QueRxDesc,
++                                &pP->s.phyRxBuf);
++      if (!pP->s.pRxBuf) {
++              pP->s.pRxBuf = 0;
++              _PRTK_SYSFAIL(("devQue_init(): fail to allocate memory for RxBuf\n"));
++              return -1;
++      }
++
++        pP->s.pTxBuf = MALLOC_DMA(((LEN_TxBuf + 3) & ~0x03) * LEN_QueTxDesc,
++                                  &pP->s.phyTxBuf);
++        if (!pP->s.pTxBuf) {
++                pP->s.pTxBuf = 0;
++                _PRTK_SYSFAIL(("devQue_init(): fail to allocate memory for TxBuf\n"));
++                return -1;
++        }
++
++      size = sizeof(bufferDescriptor) * (LEN_QueRxDesc + LEN_QueTxDesc);
++      pBuf = kmalloc(size, GFP_KERNEL);
++      if(!pBuf) {
++              _PRTK_SYSFAIL(("devQue_initAll(): fail to allocate memory for buf desc\n"));
++              return -1;
++      }
++      memset(pBuf, 0x0, size);
++      pP->s.pRxBufDesc = pBuf;
++      pP->s.pTxBufDesc = pBuf + sizeof(bufferDescriptor) * LEN_QueRxDesc;
+-static int ep93xx_poll(struct napi_struct *napi, int budget)
+-{
+-      struct ep93xx_priv *ep = container_of(napi, struct ep93xx_priv, napi);
+-      struct net_device *dev = ep->dev;
+-      int rx = 0;
++      return 0;
++}
+-poll_some_more:
+-      rx = ep93xx_rx(dev, rx, budget);
+-      if (rx < budget) {
+-              int more = 0;
++#ifndef _PRTK_DUMP
++# define _dbg_ep93xxeth_dumpReg(pD)
++#else
++/*****************************************************************************
++* _dbg_ep93xxeth_dumpReg()
++*****************************************************************************/
++static void
++_dbg_ep93xxeth_dumpReg(struct net_device *pD)
++{
++      struct ep93xxEth_info  *pP = pD->priv;
++
++      _PRTK_DUMP(("Dumping registers of Ethernet Module Embedded within EP93xx\n"));
++      _PRTK_DUMP((" pD:0x%p, Base Address:0x%x\n", pD,
++                  (unsigned int)pD->base_addr));
++
++      _PRTK_DUMP((" RxCTL:0x%08x  TxCTL:0x%08x  TestCTL:0x%08x\n",
++                  (unsigned int)RegRd32(REG_RxCTL),
++                  (unsigned int)RegRd32(REG_TxCTL),
++                  (unsigned int)RegRd32(REG_TestCTL)));
++      _PRTK_DUMP((" SelfCTL:0x%08x  IntEn:0x%08x  IntStsP:0x%08x\n",
++                  (unsigned int)RegRd32(REG_SelfCTL),
++                  (unsigned int)RegRd32(REG_IntEn),
++                  (unsigned int)RegRd32(REG_IntStsP)));
++      _PRTK_DUMP((" GT:0x%08x  FCT:0x%08x  FCF:0x%08x\n",
++                  (unsigned int)RegRd32(REG_GT),
++                  (unsigned int)RegRd32(REG_FCT),
++                  (unsigned int)RegRd32(REG_FCF)));
++      _PRTK_DUMP((" AFP:0x%08x\n", (unsigned int)RegRd32(REG_AFP)));
++      _PRTK_DUMP((" TxCollCnt:0x%08x  RxMissCnt:0x%08x  RxRntCnt:0x%08x\n",
++                  (unsigned int)RegRd32(REG_TxCollCnt),
++                  (unsigned int)RegRd32(REG_RxMissCnt),
++                  (unsigned int)RegRd32(REG_RxRntCnt)));
++      _PRTK_DUMP((" BMCtl:0x%08x  BMSts:0x%08x\n",
++                  (unsigned int)RegRd32(REG_BMCtl),
++                  (unsigned int)RegRd32(REG_BMSts)));
++      _PRTK_DUMP((" RBCA:0x%08x  TBCA:0x%08x\n",
++                  (unsigned int)RegRd32(REG_RBCA),
++                  (unsigned int)RegRd32(REG_TBCA)));
++      _PRTK_DUMP((" RxDBA:0x%08x  RxDBL/CL:0x%08x  RxDCA:0x%08x\n",
++                  (unsigned int)RegRd32(REG_RxDBA),
++                  (unsigned int)RegRd32(REG_RxDBL),
++                  (unsigned int)RegRd32(REG_RxDCA)));
++      _PRTK_DUMP((" RxSBA:0x%08x  RxSBL/CL:0x%08x  RxSCA:0x%08x\n",
++                  (unsigned int)RegRd32(REG_RxSBA),
++                  (unsigned int)RegRd32(REG_RxSBL),
++                  (unsigned int)RegRd32(REG_RxSCA)));
++      _PRTK_DUMP((" RxDEQ:0x%08x  RxSEQ:0x%08x\n",
++                  (unsigned int)RegRd32(REG_RxDEQ),
++                  (unsigned int)RegRd32(REG_RxSEQ)));
++      _PRTK_DUMP((" TxDBA:0x%08x  TxDBL/CL:0x%08x  TxDCA:0x%08x\n",
++                  (unsigned int)RegRd32(REG_TxDBA),
++                  (unsigned int)RegRd32(REG_TxDBL),
++                  (unsigned int)RegRd32(REG_TxDCA)));
++      _PRTK_DUMP((" TxSBA:0x%08x  TxSBL/CL:0x%08x  TxSCA:0x%08x\n",
++                  (unsigned int)RegRd32(REG_TxSBA),
++                  (unsigned int)RegRd32(REG_TxSBL),
++                  (unsigned int)RegRd32(REG_TxSCA)));
++      _PRTK_DUMP((" TxDEQ:0x%08x\n",(unsigned int)RegRd32(REG_TxDEQ)));
++      _PRTK_DUMP((" RxBTH:0x%08x  TxBTH:0x%08x  RxSTH:0x%08x\n",
++                  (unsigned int)RegRd32(REG_RxBTH),
++                  (unsigned int)RegRd32(REG_TxBTH),
++                  (unsigned int)RegRd32(REG_RxSTH)));
++      _PRTK_DUMP((" TxSTH:0x%08x  RxDTH:0x%08x  TxDTH:0x%08x\n",
++                  (unsigned int)RegRd32(REG_TxSTH),
++                  (unsigned int)RegRd32(REG_RxDTH),
++                  (unsigned int)RegRd32(REG_TxDTH)));
++      _PRTK_DUMP((" MaxFL:0x%08x  RxHL:0x%08x\n",
++                  (unsigned int)RegRd32(REG_MaxFL),
++                  (unsigned int)RegRd32(REG_RxHL)));
++      _PRTK_DUMP((" MACCFG0-3:0x%08x 0x%08x 0x%08x 0x%08x\n",
++                  (unsigned int)RegRd32(REG_MACCFG0),
++                  (unsigned int)RegRd32(REG_MACCFG1),
++                  (unsigned int)RegRd32(REG_MACCFG2),
++                  (unsigned int)RegRd32(REG_MACCFG3)));
++
++      /*
++      _PRTK_DUMP((" ---INT Controller Reg---\n"));
++      _PRTK_DUMP((" RawIrqSts :0x%08x 0x%08x\n", _RegRd(U32,0x80800004),
++                  _RegRd(U32,0x80800018)));
++      _PRTK_DUMP((" IrqMask   :0x%08x 0x%08x\n", _RegRd(U32,0x80800008),
++                  _RegRd(U32,0x8080001c)));
++      _PRTK_DUMP((" MaskIrqSts:0x%08x 0x%08x\n", _RegRd(U32,0x80800000),
++                  _RegRd(U32,0x80800014)));
++      */
++
++
++      _PRTK_DUMP(("Dumping private data:\n"));
++      _PRTK_DUMP((" d.txStopped:%d  d.idxQueTxSts:%d  d.idxQueTxDescHead:%d  d.idxQueTxDescTail:%d\n",
++                  pP->d.txStopped, pP->d.idxQueTxSts, pP->d.idxQueTxDescHead,
++                  pP->d.idxQueTxDescTail));
++      _PRTK_DUMP((" d.idxQueRxDesc:%d  d.idxQueRxSts:%d\n",
++                  pP->d.idxQueRxDesc, pP->d.idxQueRxSts));
++}
++#endif
++
++#define CRC_PRIME 0xFFFFFFFF
++#define CRC_POLYNOMIAL 0x04C11DB6
++/*****************************************************************************
++* calculate_hash_index()
++*****************************************************************************/
++static unsigned char
++calculate_hash_index(char *pMulticastAddr)
++{
++      unsigned long CRC;
++      unsigned char HashIndex;
++      unsigned char AddrByte;
++      unsigned char *pC;
++      unsigned long HighBit;
++      int Byte;
++      int Bit;
++
++      CRC = CRC_PRIME;
++      pC = pMulticastAddr;
++
++      for (Byte = 0; Byte < 6; Byte++) {
++              AddrByte = *pC;
++              pC++;
++
++              for (Bit = 8; Bit > 0; Bit--)
++              {
++                      HighBit = CRC >> 31;
++                      CRC <<= 1;
++
++                      if (HighBit ^ (AddrByte & 1))
++                      {
++                              CRC ^= CRC_POLYNOMIAL;
++                              CRC |= 1;
++              }
+-              spin_lock_irq(&ep->rx_lock);
+-              __netif_rx_complete(dev, napi);
+-              wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
+-              if (ep93xx_have_more_rx(ep)) {
+-                      wrl(ep, REG_INTEN, REG_INTEN_TX);
+-                      wrl(ep, REG_INTSTSP, REG_INTSTS_RX);
+-                      more = 1;
++                      AddrByte >>= 1;
+               }
+-              spin_unlock_irq(&ep->rx_lock);
++      }
+-              if (more && netif_rx_reschedule(dev, napi))
+-                      goto poll_some_more;
++      for (Bit = 0, HashIndex = 0; Bit < 6; Bit++)
++      {
++              HashIndex <<= 1;
++              HashIndex |= (unsigned char)(CRC & 1);
++              CRC >>= 1;
+       }
+-      return rx;
++      return HashIndex;
+ }
+-static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
++/*****************************************************************************
++* eth_setMulticastTbl()
++*****************************************************************************/
++static void
++eth_setMulticastTbl(struct net_device *pD, U8 *pBuf)
+ {
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      int entry;
+-
+-      if (unlikely(skb->len > MAX_PKT_SIZE)) {
+-              ep->stats.tx_dropped++;
+-              dev_kfree_skb(skb);
+-              return NETDEV_TX_OK;
+-      }
+-
+-      entry = ep->tx_pointer;
+-      ep->tx_pointer = (ep->tx_pointer + 1) & (TX_QUEUE_ENTRIES - 1);
+-
+-      ep->descs->tdesc[entry].tdesc1 =
+-              TDESC1_EOF | (entry << 16) | (skb->len & 0xfff);
+-      skb_copy_and_csum_dev(skb, ep->tx_buf[entry]);
+-      dma_sync_single(NULL, ep->descs->tdesc[entry].buf_addr,
+-                              skb->len, DMA_TO_DEVICE);
+-      dev_kfree_skb(skb);
++      int i;
++      unsigned char position;
++      struct dev_mc_list *cur_addr;
+-      dev->trans_start = jiffies;
++      memset(pBuf, 0x00, 8);
+-      spin_lock_irq(&ep->tx_pending_lock);
+-      ep->tx_pending++;
+-      if (ep->tx_pending == TX_QUEUE_ENTRIES)
+-              netif_stop_queue(dev);
+-      spin_unlock_irq(&ep->tx_pending_lock);
++      cur_addr = pD->mc_list;
++      for (i = 0; i < pD->mc_count; i++, cur_addr = cur_addr->next) {
++              if (!cur_addr)
++                      break;
++              if (!(*cur_addr->dmi_addr & 1))
++                      continue;
++              position = calculate_hash_index(cur_addr->dmi_addr);
++              pBuf[position >> 3] |= 1 << (position & 0x07);
++      }
++}
+-      wrl(ep, REG_TXDENQ, 1);
++/*****************************************************************************
++* eth_indAddrWr()
++*****************************************************************************/
++static int
++eth_indAddrWr(struct net_device *pD, int afp, char *pBuf)
++{
++      U32 rxctl;
++      int i, len;
++
++      afp &= 0x07;
++      if (afp == 4 || afp == 5) {
++              _PRTK_SWERR(("eth_indAddrWr(): invalid afp value\n"));
++              return -1;
++      }
++      len = (afp == AFP_AFP_HASH) ? 8 : 6;
++
++      rxctl = RegRd32(REG_RxCTL);
++      RegWr32(REG_RxCTL, ~RxCTL_SRxON & rxctl);
++      RegWr32(REG_AFP, afp);
++      for (i = 0; i < len; i++)
++              RegWr8(REG_IndAD + i, pBuf[i]);
++      RegWr32(REG_RxCTL, rxctl);
+-      return NETDEV_TX_OK;
++      return 0;
+ }
+-static void ep93xx_tx_complete(struct net_device *dev)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      int wake;
++/*****************************************************************************
++* eth_indAddrRd()
++*****************************************************************************/
++#if 0
++static int
++eth_indAddrRd(struct net_device *pD, int afp, char *pBuf)
++{
++      int i, len;
++
++      afp &= 0x07;
++      if (afp == 4 || afp == 5) {
++              _PRTK_SWERR(("eth_indAddrRd(): invalid afp value\n"));
++              return -1;
++      }
++
++      RegWr32(REG_AFP, afp);
++      len = (afp == AFP_AFP_HASH) ? 8 : 6;
++      for (i = 0; i < len; i++)
++              pBuf[i] = RegRd8(REG_IndAD + i);
+-      wake = 0;
++      return 0;
++}
++#endif
+-      spin_lock(&ep->tx_pending_lock);
+-      while (1) {
+-              int entry;
+-              struct ep93xx_tstat *tstat;
+-              u32 tstat0;
++/*****************************************************************************
++* eth_rxCtl()
++*****************************************************************************/
++static int
++eth_rxCtl(struct net_device *pD, int sw)
++{
++      /*
++       * Workaround for MAC lost 60-byte-long frames: must enable
++       * Runt_CRC_Accept bit
++       */
++      RegWr32(REG_RxCTL,
++              sw ? RegRd32(REG_RxCTL) | RxCTL_SRxON | RxCTL_RCRCA :
++              RegRd32(REG_RxCTL) & ~RxCTL_SRxON);
+-              entry = ep->tx_clean_pointer;
+-              tstat = ep->descs->tstat + entry;
++      return 0;
++}
+-              tstat0 = tstat->tstat0;
+-              if (!(tstat0 & TSTAT0_TXFP))
+-                      break;
++/*****************************************************************************
++* eth_chkTxLvl()
++*****************************************************************************/
++static void
++eth_chkTxLvl(struct net_device *pD)
++{
++      struct ep93xxEth_info *pP = pD->priv;
++      int idxQTxDescHd;
++      int filled;
++
++      idxQTxDescHd = pP->d.idxQueTxDescHead;
++
++      filled = idxQTxDescHd - pP->d.idxQueTxDescTail;
++      if (filled < 0)
++              filled += LEN_QueTxDesc;
++
++      if (pP->d.txStopped && filled <= (LVL_TxResume + 1)) {
++              pP->d.txStopped = 0;
++              pD->trans_start = jiffies;
++              netif_wake_queue(pD);
++      }
++}
+-              tstat->tstat0 = 0;
++/*****************************************************************************
++* eth_cleanUpTx()
++*****************************************************************************/
++static int
++eth_cleanUpTx(struct net_device *pD)
++{
++      struct ep93xxEth_info *pP = pD->priv;
++      transmitStatus *pQTxSts;
++      int idxSts, bi;
++
++      while (pP->s.pQueTxSts[pP->d.idxQueTxSts].f.txfp) {
++              idxSts = pP->d.idxQueTxSts;
++
++              pP->d.idxQueTxSts = IdxNext(pP->d.idxQueTxSts,LEN_QueTxSts);
++              pQTxSts = &pP->s.pQueTxSts[idxSts];
++              if (!pQTxSts->f.txfp) {
++                      _PRTK_HWFAIL(("eth_cleanUpTx(): QueTxSts[%d]:x%08x is empty\n",
++                                    idxSts, (int)pQTxSts->w.e0));
++                      return -1;
++              }
+-              if (tstat0 & TSTAT0_FA)
+-                      printk(KERN_CRIT "ep93xx_tx_complete: frame aborted "
+-                                       " %.8x\n", tstat0);
+-              if ((tstat0 & TSTAT0_BUFFER_INDEX) != entry)
+-                      printk(KERN_CRIT "ep93xx_tx_complete: entry mismatch "
+-                                       " %.8x\n", tstat0);
++              pQTxSts->f.txfp = 0;
+-              if (tstat0 & TSTAT0_TXWE) {
+-                      int length = ep->descs->tdesc[entry].tdesc1 & 0xfff;
++              bi = pQTxSts->f.bi;
++#if 0
++              if (pP->d.idxQueTxDescTail != bi) {
++                      _PRTK_HWFAIL(("eth_cleanUpTx(): unmatching QTxSts[%d].BI:%d idxQTxDTail:%d\n",
++                                    idxSts,bi, pP->d.idxQueTxDescTail));
++      }
++#endif
++
++              if (pP->s.pTxBufDesc[bi].pFreeRtn) {
++                      (*pP->s.pTxBufDesc[bi].pFreeRtn)(pP->s.pTxBufDesc[bi].vaddr);
++                      pP->s.pTxBufDesc[bi].pFreeRtn = 0;
++              }
+-                      ep->stats.tx_packets++;
+-                      ep->stats.tx_bytes += length;
++              if (pQTxSts->f.txwe) {
++                      pP->d.stats.tx_packets++;
+               } else {
+-                      ep->stats.tx_errors++;
++                      pP->d.stats.tx_errors++;
++                      if (pQTxSts->f.lcrs)
++                              pP->d.stats.tx_carrier_errors++;
++                      if(pQTxSts->f.txu)
++                              pP->d.stats.tx_fifo_errors++;
++                      if(pQTxSts->f.ecoll)
++                              pP->d.stats.collisions++;
+               }
+-              if (tstat0 & TSTAT0_OW)
+-                      ep->stats.tx_window_errors++;
+-              if (tstat0 & TSTAT0_TXU)
+-                      ep->stats.tx_fifo_errors++;
+-              ep->stats.collisions += (tstat0 >> 16) & 0x1f;
+-
+-              ep->tx_clean_pointer = (entry + 1) & (TX_QUEUE_ENTRIES - 1);
+-              if (ep->tx_pending == TX_QUEUE_ENTRIES)
+-                      wake = 1;
+-              ep->tx_pending--;
++              pP->d.idxQueTxDescTail = IdxNext(pP->d.idxQueTxDescTail,
++                                               LEN_QueTxDesc);
+       }
+-      spin_unlock(&ep->tx_pending_lock);
+-      if (wake)
+-              netif_wake_queue(dev);
++      return 0;
+ }
+-static irqreturn_t ep93xx_irq(int irq, void *dev_id)
++/*****************************************************************************
++* eth_restartTx()
++*****************************************************************************/
++static int
++eth_restartTx(struct net_device *pD)
+ {
+-      struct net_device *dev = dev_id;
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      u32 status;
++      struct ep93xxEth_info *pP = pD->priv;
++      int i;
+-      status = rdl(ep, REG_INTSTSC);
+-      if (status == 0)
+-              return IRQ_NONE;
++      RegWr32(REG_GIntMsk, RegRd32(REG_GIntMsk) & ~GIntMsk_IntEn);
+-      if (status & REG_INTSTS_RX) {
+-              spin_lock(&ep->rx_lock);
+-              if (likely(netif_rx_schedule_prep(dev, &ep->napi))) {
+-                      wrl(ep, REG_INTEN, REG_INTEN_TX);
+-                      __netif_rx_schedule(dev, &ep->napi);
+-              }
+-              spin_unlock(&ep->rx_lock);
++      RegWr32(REG_TxCTL, RegRd32(REG_TxCTL) & ~TxCTL_STxON);
++      RegWr32(REG_BMCtl, RegRd32(REG_BMCtl) | BMCtl_TxDis);
++
++      RegWr32(REG_BMCtl, BMCtl_TxChR | RegRd32(REG_BMCtl));
++
++      for (i = 0; i < LEN_QueTxDesc; i++) {
++              if (pP->s.pTxBufDesc[i].pFreeRtn) {
++                      pP->s.pTxBufDesc[i].pFreeRtn(pP->s.pTxBufDesc[i].vaddr);
++                      pP->s.pTxBufDesc[i].pFreeRtn = 0;
++      }
++              pP->d.stats.tx_dropped++;
+       }
+-      if (status & REG_INTSTS_TX)
+-              ep93xx_tx_complete(dev);
++      memset(pP->s.pQueTxSts, 0, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);
+-      return IRQ_HANDLED;
+-}
++      pP->d.txStopped = 0;
++      pP->d.idxQueTxSts = pP->d.idxQueTxDescHead = pP->d.idxQueTxDescTail =
++              0;
+-static void ep93xx_free_buffers(struct ep93xx_priv *ep)
+-{
+-      int i;
++      waitOnReg32(pD, REG_BMSts, BMCtl_TxChR, ~BMCtl_TxChR, 1);
++      RegWr32(REG_TxSBA, pP->s.phyQueTxSts);
++      RegWr32(REG_TxSCA, pP->s.phyQueTxSts);
++      RegWr16(REG_TxSBL, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);
++      RegWr16(REG_TxSCL, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);
++      RegWr32(REG_TxDBA, pP->s.phyQueTxDesc);
++      RegWr32(REG_TxDCA, pP->s.phyQueTxDesc);
++      RegWr16(REG_TxDBL, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc);
++      RegWr16(REG_TxDCL, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc);
+-      for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) {
+-              dma_addr_t d;
++      RegWr32(REG_TxCTL, RegRd32(REG_TxCTL) | TxCTL_STxON);
++      RegWr32(REG_BMCtl, RegRd32(REG_BMCtl) | BMCtl_TxEn);
+-              d = ep->descs->rdesc[i].buf_addr;
+-              if (d)
+-                      dma_unmap_single(NULL, d, PAGE_SIZE, DMA_FROM_DEVICE);
++      RegWr32(REG_GIntMsk, RegRd32(REG_GIntMsk) | GIntMsk_IntEn);
+-              if (ep->rx_buf[i] != NULL)
+-                      free_page((unsigned long)ep->rx_buf[i]);
+-      }
++      return 0;
++}
+-      for (i = 0; i < TX_QUEUE_ENTRIES; i += 2) {
+-              dma_addr_t d;
++/*****************************************************************************
++* eth_reset()
++*****************************************************************************/
++static int
++eth_reset(struct net_device *pD)
++{
++      int err;
+-              d = ep->descs->tdesc[i].buf_addr;
+-              if (d)
+-                      dma_unmap_single(NULL, d, PAGE_SIZE, DMA_TO_DEVICE);
++      RegWr8(REG_SelfCTL, SelfCTL_RESET);
++      err = waitOnReg32(pD, REG_SelfCTL, SelfCTL_RESET, ~SelfCTL_RESET, 1);
++      if (err)
++              _PRTK_WARN(("eth_reset(): Soft Reset does not self-clear\n"));
+-              if (ep->tx_buf[i] != NULL)
+-                      free_page((unsigned long)ep->tx_buf[i]);
+-      }
++      //phy_reset(pD);
+-      dma_free_coherent(NULL, sizeof(struct ep93xx_descs), ep->descs,
+-                                                      ep->descs_dma_addr);
++      return 0;
+ }
+-/*
+- * The hardware enforces a sub-2K maximum packet size, so we put
+- * two buffers on every hardware page.
+- */
+-static int ep93xx_alloc_buffers(struct ep93xx_priv *ep)
++/*****************************************************************************
++ . Function: eth_shutDown()
++ . Purpose:  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 *pD)
+ {
+-      int i;
+-
+-      ep->descs = dma_alloc_coherent(NULL, sizeof(struct ep93xx_descs),
+-                              &ep->descs_dma_addr, GFP_KERNEL | GFP_DMA);
+-      if (ep->descs == NULL)
+-              return 1;
++      eth_reset(pD);
+-      for (i = 0; i < RX_QUEUE_ENTRIES; i += 2) {
+-              void *page;
+-              dma_addr_t d;
++      return 0;
++}
+-              page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
+-              if (page == NULL)
+-                      goto err;
++/*****************************************************************************
++*  eth_enable()
+-              d = dma_map_single(NULL, page, PAGE_SIZE, DMA_FROM_DEVICE);
+-              if (dma_mapping_error(d)) {
+-                      free_page((unsigned long)page);
+-                      goto err;
+-              }
++  Purpose:
++        Turn on device interrupt for interrupt driven operation.
++        Also turn on Rx but no Tx.
++*
++*****************************************************************************/
++static int
++eth_enable(struct net_device *pD)
++{
++      RegWr32(REG_IntEn, Default_IntSrc);
++      RegWr32(REG_GIntMsk, GIntMsk_IntEn);
++      eth_rxCtl(pD, 1);
+-              ep->rx_buf[i] = page;
+-              ep->descs->rdesc[i].buf_addr = d;
+-              ep->descs->rdesc[i].rdesc1 = (i << 16) | PKT_BUF_SIZE;
++      return 0;
++}
+-              ep->rx_buf[i + 1] = page + PKT_BUF_SIZE;
+-              ep->descs->rdesc[i + 1].buf_addr = d + PKT_BUF_SIZE;
+-              ep->descs->rdesc[i + 1].rdesc1 = ((i + 1) << 16) | PKT_BUF_SIZE;
+-      }
++/*****************************************************************************
++*  eth_init()
+-      for (i = 0; i < TX_QUEUE_ENTRIES; i += 2) {
+-              void *page;
+-              dma_addr_t d;
++  Purpose:
++        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 *pD)
++{
++      int status;
++
++      eth_reset(pD);
++
++      gPhyAutoNegoDone = 0;
++      status = phy_init(pD);
++      if (status != 0)
++              printk(KERN_WARNING "%s: No network cable detected!\n", pD->name);
++
++      RegWr32(REG_SelfCTL, 0x0f00);
++      RegWr32(REG_GIntMsk, 0x00);
++      RegWr32(REG_RxCTL, RxCTL_BA | RxCTL_IA0);
++      RegWr32(REG_TxCTL, 0x00);
++      RegWr32(REG_GT, 0x00);
++      RegWr32(REG_BMCtl, 0x00);
++      RegWr32(REG_RxBTH, (0x80 << 16) | (0x40 << 0));
++      RegWr32(REG_TxBTH, (0x80 << 16) | (0x40 << 0));
++      RegWr32(REG_RxSTH, (4 << 16) | (2 << 0));
++      RegWr32(REG_TxSTH, (4 << 16) | (2 << 0));
++      RegWr32(REG_RxDTH, (4 << 16) | (2 << 0));
++      RegWr32(REG_TxDTH, (4 << 16) | (2 << 0));
++      RegWr32(REG_MaxFL, ((1518 + 1) << 16) | (944 << 0));
++
++      RegRd32(REG_TxCollCnt);
++      RegRd32(REG_RxMissCnt);
++      RegRd32(REG_RxRntCnt);
+-              page = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
+-              if (page == NULL)
+-                      goto err;
++      RegRd32(REG_IntStsC);
+-              d = dma_map_single(NULL, page, PAGE_SIZE, DMA_TO_DEVICE);
+-              if (dma_mapping_error(d)) {
+-                      free_page((unsigned long)page);
+-                      goto err;
+-              }
++      RegWr32(REG_TxCTL, TxCTL_STxON | RegRd32(REG_TxCTL));
+-              ep->tx_buf[i] = page;
+-              ep->descs->tdesc[i].buf_addr = d;
++      eth_indAddrWr(pD, AFP_AFP_IA0, &pD->dev_addr[0]);
+-              ep->tx_buf[i + 1] = page + PKT_BUF_SIZE;
+-              ep->descs->tdesc[i + 1].buf_addr = d + PKT_BUF_SIZE;
+-      }
++      devQue_start(pD);
+       return 0;
+-
+-err:
+-      ep93xx_free_buffers(ep);
+-      return 1;
+ }
+-static int ep93xx_start_hw(struct net_device *dev)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      unsigned long addr;
+-      int i;
+-
+-      wrl(ep, REG_SELFCTL, REG_SELFCTL_RESET);
+-      for (i = 0; i < 10; i++) {
+-              if ((rdl(ep, REG_SELFCTL) & REG_SELFCTL_RESET) == 0)
+-                      break;
+-              msleep(1);
+-      }
+-
+-      if (i == 10) {
+-              printk(KERN_CRIT DRV_MODULE_NAME ": hw failed to reset\n");
+-              return 1;
+-      }
+-
+-      wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9));
+-
+-      /* Does the PHY support preamble suppress?  */
+-      if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0)
+-              wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8));
+-
+-      /* Receive descriptor ring.  */
+-      addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rdesc);
+-      wrl(ep, REG_RXDQBADD, addr);
+-      wrl(ep, REG_RXDCURADD, addr);
+-      wrw(ep, REG_RXDQBLEN, RX_QUEUE_ENTRIES * sizeof(struct ep93xx_rdesc));
+-
+-      /* Receive status ring.  */
+-      addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rstat);
+-      wrl(ep, REG_RXSTSQBADD, addr);
+-      wrl(ep, REG_RXSTSQCURADD, addr);
+-      wrw(ep, REG_RXSTSQBLEN, RX_QUEUE_ENTRIES * sizeof(struct ep93xx_rstat));
+-
+-      /* Transmit descriptor ring.  */
+-      addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, tdesc);
+-      wrl(ep, REG_TXDQBADD, addr);
+-      wrl(ep, REG_TXDQCURADD, addr);
+-      wrw(ep, REG_TXDQBLEN, TX_QUEUE_ENTRIES * sizeof(struct ep93xx_tdesc));
+-
+-      /* Transmit status ring.  */
+-      addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, tstat);
+-      wrl(ep, REG_TXSTSQBADD, addr);
+-      wrl(ep, REG_TXSTSQCURADD, addr);
+-      wrw(ep, REG_TXSTSQBLEN, TX_QUEUE_ENTRIES * sizeof(struct ep93xx_tstat));
+-
+-      wrl(ep, REG_BMCTL, REG_BMCTL_ENABLE_TX | REG_BMCTL_ENABLE_RX);
+-      wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
+-      wrl(ep, REG_GIINTMSK, 0);
++/*****************************************************************************
++* eth_isrRx()
++*
++*  Interrupt Service Routines
++*
++*****************************************************************************/
++static int
++eth_isrRx(struct net_device *pD)
++{
++      ep93xxEth_info *pP = pD->priv;
++      receiveStatus *pQRxSts;
++      int idxQRxStsHead;
++      int idxSts;
++      int cntStsProcessed, cntDescProcessed;
++      char *pDest;
++      struct sk_buff *pSkb;
++      int len;
++      UINT dt;
++
++      dt = RegRd32(REG_RxSCA);
++      idxQRxStsHead = (dt - pP->s.phyQueRxSts) / sizeof(pP->s.pQueRxSts[0]);
++      if (!(idxQRxStsHead >= 0 && idxQRxStsHead < LEN_QueRxSts)) {
++              _PRTK_HWFAIL(("eth_isrRx(): invalid REG_RxSCA:0x%x idx:%d (phyQueRxSts:0x%x Len:%x)\n",
++                            dt,idxQRxStsHead, (int)pP->s.phyQueRxSts,
++                            LEN_QueRxSts));
++              return -1;
++      }
++
++      cntStsProcessed = cntDescProcessed = 0;
++      while (idxQRxStsHead != pP->d.idxQueRxSts) {
++              idxSts = pP->d.idxQueRxSts;
++              pP->d.idxQueRxSts = IdxNext(pP->d.idxQueRxSts, LEN_QueRxSts);
++              pQRxSts = &pP->s.pQueRxSts[idxSts];
++              if (!pQRxSts->f.rfp) {
++                      _PRTK_HWFAIL(("eth_isrRx(): QueRxSts[%d] is empty; Hd:%d\n",
++                                    idxSts,idxQRxStsHead));
++                      return -1;
++              }
++              pQRxSts->f.rfp = 0;
+-      for (i = 0; i < 10; i++) {
+-              if ((rdl(ep, REG_BMSTS) & REG_BMSTS_RX_ACTIVE) != 0)
+-                      break;
+-              msleep(1);
+-      }
++              if(pQRxSts->f.eob) {
++                      if(pQRxSts->f.bi == pP->d.idxQueRxDesc) {
++                              pP->d.idxQueRxDesc =
++                                      IdxNext(pP->d.idxQueRxDesc,
++                                              LEN_QueRxDesc);
++                              cntDescProcessed++;
++                              if (pQRxSts->f.eof && pQRxSts->f.rwe) {
++                                      len = pQRxSts->f.fl;
++                                      pSkb = dev_alloc_skb(len + 5);
++                                      if (pSkb != NULL) {
++                                              skb_reserve(pSkb, 2);
++                                              pSkb->dev = pD;
++                                              pDest = skb_put(pSkb, len);
++
++                                              memcpy(pDest,
++                                                     pP->s.pRxBufDesc[pQRxSts->f.bi].vaddr,
++                                                     len);
++                                              pSkb->protocol =
++                                                      eth_type_trans(pSkb,
++                                                                     pD);
++                                              netif_rx(pSkb);
++                                              pP->d.stats.rx_packets++;
++                                              if(pQRxSts->f.am == 3)
++                                                      pP->d.stats.multicast++;
++                                      } else
++                                              _PRTK_SYSFAIL(("eth_isrRx(): Low Memory, Rx dropped\n"));
++                                              pP->d.stats.rx_dropped++;
++                              } else {
++                                      pP->d.stats.rx_errors++;
++                                      if (pQRxSts->f.oe)
++                                              pP->d.stats.rx_fifo_errors++;
++                                      if (pQRxSts->f.fe)
++                                              pP->d.stats.rx_frame_errors++;
++                                      if (pQRxSts->f.runt ||
++                                          pQRxSts->f.edata)
++                                              pP->d.stats.rx_length_errors++;
++                                      if (pQRxSts->f.crce)
++                                              pP->d.stats.rx_crc_errors++;
++                              }
++                      } else
++                              _PRTK_HWFAIL(("eth_isrRx(): unmatching QueRxSts[%d].BI:0x%x; idxQueRxDesc:0x%x\n",
++                                            idxSts, pQRxSts->f.bi,
++                                            pP->d.idxQueRxDesc));
++              }
+-      if (i == 10) {
+-              printk(KERN_CRIT DRV_MODULE_NAME ": hw failed to start\n");
+-              return 1;
++              cntStsProcessed++;
+       }
+-      wrl(ep, REG_RXDENQ, RX_QUEUE_ENTRIES);
+-      wrl(ep, REG_RXSTSENQ, RX_QUEUE_ENTRIES);
+-
+-      wrb(ep, REG_INDAD0, dev->dev_addr[0]);
+-      wrb(ep, REG_INDAD1, dev->dev_addr[1]);
+-      wrb(ep, REG_INDAD2, dev->dev_addr[2]);
+-      wrb(ep, REG_INDAD3, dev->dev_addr[3]);
+-      wrb(ep, REG_INDAD4, dev->dev_addr[4]);
+-      wrb(ep, REG_INDAD5, dev->dev_addr[5]);
+-      wrl(ep, REG_AFP, 0);
+-
+-      wrl(ep, REG_MAXFRMLEN, (MAX_PKT_SIZE << 16) | MAX_PKT_SIZE);
+-
+-      wrl(ep, REG_RXCTL, REG_RXCTL_DEFAULT);
+-      wrl(ep, REG_TXCTL, REG_TXCTL_ENABLE);
++      RegWr32(REG_RxSEQ, cntStsProcessed);
++      RegWr32(REG_RxDEQ, cntDescProcessed);
+       return 0;
+ }
+-static void ep93xx_stop_hw(struct net_device *dev)
++/*****************************************************************************
++* eth_isrTx()
++*****************************************************************************/
++static int
++eth_isrTx(struct net_device *pD)
+ {
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      int i;
++      eth_cleanUpTx(pD);
++      eth_chkTxLvl(pD);
++      return 0;
++}
+-      wrl(ep, REG_SELFCTL, REG_SELFCTL_RESET);
+-      for (i = 0; i < 10; i++) {
+-              if ((rdl(ep, REG_SELFCTL) & REG_SELFCTL_RESET) == 0)
+-                      break;
+-              msleep(1);
+-      }
++/*****************************************************************************
++* ep93xxEth_isr()
++*****************************************************************************/
++static irqreturn_t
++ep93xxEth_isr(int irq,void *pDev)
++{
++      struct net_device *pD = pDev;
++      int lpCnt;
++      U32 intS;
++
++      lpCnt = 0;
++      do {
++              intS = RegRd32(REG_IntStsC);
+-      if (i == 10)
+-              printk(KERN_CRIT DRV_MODULE_NAME ": hw failed to reset\n");
++              if (!intS)
++                      break;
++              if (intS & IntSts_RxSQ)
++                      eth_isrRx(pD);
++              if (intS & IntSts_TxSQ)
++                      eth_isrTx(pD);
++      } while (lpCnt++ < 64);
++
++      if (lpCnt)
++              return IRQ_HANDLED;
++      else
++              return IRQ_NONE;
+ }
+-static int ep93xx_open(struct net_device *dev)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      int err;
++/*=========================================================
++ *  Exposed Driver Routines to the Outside World
++ *=======================================================*/
++
++/*****************************************************************************
++* ep93xxEth_getStats()
++*****************************************************************************/
++static struct net_device_stats *
++ep93xxEth_getStats(struct net_device *pD)
++{
++      return &((struct ep93xxEth_info *)pD->priv)->d.stats;
++}
++
++/*****************************************************************************
++* ep93xxEth_setMulticastList()
++*****************************************************************************/
++static void
++ep93xxEth_setMulticastList(struct net_device *pD)
++{
++      U8 tblMulti[8 + 1];
++
++      if (pD->flags & IFF_PROMISC)
++              RegWr32(REG_RxCTL, RxCTL_PA | RegRd32(REG_RxCTL));
++      else if(pD->flags & IFF_ALLMULTI) {
++              RegWr32(REG_RxCTL, RxCTL_MA |
++                      (~RxCTL_PA & RegRd32(REG_RxCTL)));
++              eth_indAddrWr(pD, AFP_AFP_HASH,
++                            "\xff\xff\xff\xff\xff\xff\xff\xff");
++      } else if(pD->mc_count) {
++              RegWr32(REG_RxCTL, RxCTL_MA |
++                      (~RxCTL_PA & RegRd32(REG_RxCTL)));
++              eth_setMulticastTbl(pD, &tblMulti[0]);
++              eth_indAddrWr(pD, AFP_AFP_HASH, &tblMulti[0]);
++      } else
++              RegWr32(REG_RxCTL,
++                      ~(RxCTL_PA | RxCTL_MA) & RegRd32(REG_RxCTL));
++}
++
++/*****************************************************************************
++* ep93xxEth_txTimeout()
++*****************************************************************************/
++static void
++ep93xxEth_txTimeout(struct net_device *pD)
++{
++      int status;
++
++      _PRTK_WARN(("ep93xxEth_txTimeout(): transmit timed out\n"));
++
++      if (gPhyAutoNegoDone == 0) {
++              status = phy_init(pD);
++              if (status != 0)
++              {
++                      printk(KERN_WARNING "%s: No network cable detected!\n",
++                             pD->name);
++                      return;
++              }
++      }
+-      if (ep93xx_alloc_buffers(ep))
+-              return -ENOMEM;
++      eth_restartTx(pD);
+-      if (is_zero_ether_addr(dev->dev_addr)) {
+-              random_ether_addr(dev->dev_addr);
+-              printk(KERN_INFO "%s: generated random MAC address "
+-                      "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x.\n", dev->name,
+-                      dev->dev_addr[0], dev->dev_addr[1],
+-                      dev->dev_addr[2], dev->dev_addr[3],
+-                      dev->dev_addr[4], dev->dev_addr[5]);
+-      }
+-
+-      napi_enable(&ep->napi);
+-
+-      if (ep93xx_start_hw(dev)) {
+-              napi_disable(&ep->napi);
+-              ep93xx_free_buffers(ep);
+-              return -EIO;
+-      }
+-
+-      spin_lock_init(&ep->rx_lock);
+-      ep->rx_pointer = 0;
+-      ep->tx_clean_pointer = 0;
+-      ep->tx_pointer = 0;
+-      spin_lock_init(&ep->tx_pending_lock);
+-      ep->tx_pending = 0;
++      pD->trans_start = jiffies;
++      netif_wake_queue(pD);
++}
+-      err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev);
+-      if (err) {
+-              napi_disable(&ep->napi);
+-              ep93xx_stop_hw(dev);
+-              ep93xx_free_buffers(ep);
+-              return err;
++/*****************************************************************************
++* ep93xxEth_hardStartXmit()
++*****************************************************************************/
++static int
++ep93xxEth_hardStartXmit(struct sk_buff *pSkb, struct net_device *pD)
++{
++      struct ep93xxEth_info *pP = pD->priv;
++      transmitDescriptor *pQTxDesc;
++      int idxQTxDescHd;
++      int filled;
++      int status;
++
++      if (gPhyAutoNegoDone == 0) {
++              status = phy_init(pD);
++              if (status != 0)
++              {
++                      return 1;
++              }
+       }
+-      wrl(ep, REG_GIINTMSK, REG_GIINTMSK_ENABLE);
++      idxQTxDescHd = pP->d.idxQueTxDescHead;
++      pQTxDesc = &pP->s.pQueTxDesc[idxQTxDescHd];
++
++      filled = idxQTxDescHd - pP->d.idxQueTxDescTail;
++      if (filled < 0)
++              filled += LEN_QueTxDesc;
++      filled += 1;
++
++      if(filled >= LVL_TxStop) {
++              netif_stop_queue(pD);
++              pP->d.txStopped = 1;
++              if(filled > LVL_TxStop) {
++                      _PRTK_SYSFAIL(("ep93xxEth_hardStartXmit(): a Tx Request while stop\n"));
++                      return 1;
++              }
++      }
+-      netif_start_queue(dev);
++      if (pSkb->len < 60) {
++              pQTxDesc->f.bl = 60;
++              memset(pP->s.pTxBufDesc[idxQTxDescHd].vaddr, 0, 60);
++      } else
++              pQTxDesc->f.bl = pSkb->len;
++      pQTxDesc->f.ba = pP->s.phyTxBuf+(idxQTxDescHd * LEN_TxBuf);//virt_to_bus(pP->s.pTxBufDesc[idxQTxDescHd].vaddr);
++      pQTxDesc->f.bi = idxQTxDescHd;
++      pQTxDesc->f.af = 0;
++      pQTxDesc->f.eof = 1;
++
++      memcpy(pP->s.pTxBufDesc[idxQTxDescHd].vaddr, pSkb->data, pSkb->len);
++      pP->s.pTxBufDesc[idxQTxDescHd].pFreeRtn = 0;
++
++      free_skb(pSkb);
++
++      pP->d.idxQueTxDescHead = IdxNext(pP->d.idxQueTxDescHead,
++                                       LEN_QueTxDesc);
++      RegWr32(REG_TxDEQ, 1);
+       return 0;
+ }
+-static int ep93xx_close(struct net_device *dev)
++/*****************************************************************************
++ . ep93xxEth_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
++ep93xxEth_close(struct net_device *pD)
+ {
+-      struct ep93xx_priv *ep = netdev_priv(dev);
++      netif_stop_queue(pD);
++      eth_shutDown(pD);
+-      napi_disable(&ep->napi);
+-      netif_stop_queue(dev);
+-
+-      wrl(ep, REG_GIINTMSK, 0);
+-      free_irq(ep->irq, dev);
+-      ep93xx_stop_hw(dev);
+-      ep93xx_free_buffers(ep);
++      /*MOD_DEC_USE_COUNT;*/
+       return 0;
+ }
+-static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++/*******************************************************
++ * ep93xxEth_open()
++ *
++ * Open and Initialize the board
++ *
++ * Set up everything, reset the card, etc ..
++ *
++ ******************************************************/
++static int
++ep93xxEth_open(struct net_device *pD)
+ {
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      struct mii_ioctl_data *data = if_mii(ifr);
++      int status;
++      struct ep93xxEth_info  *pP = pD->priv;
+-      return generic_mii_ioctl(&ep->mii, data, cmd, NULL);
+-}
++      memset(&pP->d, 0, sizeof(pP->d));
+-static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      int data;
+-      int i;
++      /*MOD_INC_USE_COUNT;*/
+-      wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg);
++      status = eth_init(pD);
++      if (status != 0 )
++              return -EAGAIN;
+-      for (i = 0; i < 10; i++) {
+-              if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
+-                      break;
+-              msleep(1);
+-      }
++      eth_enable(pD);
+-      if (i == 10) {
+-              printk(KERN_INFO DRV_MODULE_NAME ": mdio read timed out\n");
+-              data = 0xffff;
+-      } else {
+-              data = rdl(ep, REG_MIIDATA);
+-      }
++#if 0
++      _dbg_phy_dumpReg(pD);
++      _dbg_ep93xxeth_dumpReg(pD);
++      _dbg_ep93xxEth_dumpQueues(pD);
++#endif
+-      return data;
++      netif_start_queue(pD);
++
++      return 0;
+ }
+-static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
++/*****************************************************************************
++ .
++ . ep93xxEth_probe( struct net_device * dev )
++ .   This is the first routine called to probe device existance
++ .   and initialize the driver if the device found.
++ .
++ .   Input parameters:
++ .    dev->base_addr == 0, try to find all possible locations
++ .    dev->base_addr == 1, return failure code
++ .    dev->base_addr == 2, always allocate space,  and return success
++ .    dev->base_addr == <anything else>   this is the address to check
++ .
++ .   Output:
++ .    0 --> there is a device
++ .    anything else, error
++
++*****************************************************************************/
++int ep93xxEth_probe(struct net_device *pD) {
++      struct ep93xxEth_info *pP;
++      int err;
+       int i;
+-      wrl(ep, REG_MIIDATA, data);
+-      wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg);
+-
+-      for (i = 0; i < 10; i++) {
+-              if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
+-                      break;
+-              msleep(1);
++      if (pD->priv == 0) {
++              pD->priv = kmalloc(sizeof(struct ep93xxEth_info), GFP_KERNEL);
++              if(pD->priv == 0)
++                      return -ENOMEM;
+       }
++      memset(pD->priv, 0x00, sizeof(struct ep93xxEth_info));
+-      if (i == 10)
+-              printk(KERN_INFO DRV_MODULE_NAME ": mdio write timed out\n");
+-}
++      pP = pD->priv;
++      pP->s.id = numOfInstance;
++      pP->s.miiIdPhy = 1;
+-static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+-{
+-      strcpy(info->driver, DRV_MODULE_NAME);
+-      strcpy(info->version, DRV_MODULE_VERSION);
+-}
++      for (i = 0; i < 6; i++)
++              pD->dev_addr[i] = default_mac[i];
+-static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      return mii_ethtool_gset(&ep->mii, cmd);
+-}
++      err = (int)request_irq(pD->irq, &ep93xxEth_isr, 0, cardname, pD);
++      if(err) {
++              kfree(pD->priv);
++              return -EAGAIN;
++      }
+-static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      return mii_ethtool_sset(&ep->mii, cmd);
+-}
++      pD->open               = &ep93xxEth_open;
++      pD->stop               = &ep93xxEth_close;
++      pD->hard_start_xmit    = &ep93xxEth_hardStartXmit;
++      pD->tx_timeout         = &ep93xxEth_txTimeout;
++      pD->watchdog_timeo     = HZ * 5;
++      pD->get_stats          = &ep93xxEth_getStats;
++      pD->set_multicast_list = &ep93xxEth_setMulticastList;
+-static int ep93xx_nway_reset(struct net_device *dev)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      return mii_nway_restart(&ep->mii);
+-}
++      ether_setup(pD);
+-static u32 ep93xx_get_link(struct net_device *dev)
+-{
+-      struct ep93xx_priv *ep = netdev_priv(dev);
+-      return mii_link_ok(&ep->mii);
+-}
++      devQue_init(pD);
++      eth_reset(pD);
+-static struct ethtool_ops ep93xx_ethtool_ops = {
+-      .get_drvinfo            = ep93xx_get_drvinfo,
+-      .get_settings           = ep93xx_get_settings,
+-      .set_settings           = ep93xx_set_settings,
+-      .nway_reset             = ep93xx_nway_reset,
+-      .get_link               = ep93xx_get_link,
+-};
++      numOfInstance++;
+-struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
+-{
+-      struct net_device *dev;
++      err = register_netdev(pD);
++      if (err) {
++              free_irq(pD->irq, pD);
++              kfree(pP);
++              return err;
++      }
+-      dev = alloc_etherdev(sizeof(struct ep93xx_priv));
+-      if (dev == NULL)
+-              return NULL;
++      return 0;
++}
+-      memcpy(dev->dev_addr, data->dev_addr, ETH_ALEN);
++static int ep93xxEth_drv_probe(struct platform_device *pdev)
++{
++      struct net_device *ndev;
++      struct resource *res;
++      int ret;
+-      dev->get_stats = ep93xx_get_stats;
+-      dev->ethtool_ops = &ep93xx_ethtool_ops;
+-      dev->hard_start_xmit = ep93xx_xmit;
+-      dev->open = ep93xx_open;
+-      dev->stop = ep93xx_close;
+-      dev->do_ioctl = ep93xx_ioctl;
++      PRINTK("ep93xxEth_drv_probe init\n");
+-      dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!res){
++              printk("platform_get_resource fail\n");
++              return -ENODEV;
++      }
+-      return dev;
+-}
++      if (!request_mem_region(res->start, 0x10000, cardname)){
++              printk("request_mem_region fail\n");
++              return -EBUSY;
++      }
++      ndev = alloc_etherdev(sizeof(struct ep93xxEth_info));
++      if (!ndev) {
++              release_mem_region(res->start, 0x10000);
++              printk("alloc_etherdev fail\n");
++              return -ENOMEM;
++      }
+-static int ep93xx_eth_remove(struct platform_device *pdev)
+-{
+-      struct net_device *dev;
+-      struct ep93xx_priv *ep;
+-      dev = platform_get_drvdata(pdev);
+-      if (dev == NULL)
+-              return 0;
+-      platform_set_drvdata(pdev, NULL);
++      SET_NETDEV_DEV(ndev, &pdev->dev);
+-      ep = netdev_priv(dev);
++      ndev->base_addr = (unsigned long)ioremap(res->start, 0x10000);
++      if (!ndev->base_addr) {
++              printk("ioremap failed\n");
++              release_mem_region(res->start, 0x10000);
++              return -ENOMEM;
++      }
++      ndev->irq = platform_get_irq(pdev, 0);
+-      /* @@@ Force down.  */
+-      unregister_netdev(dev);
+-      ep93xx_free_buffers(ep);
+-      if (ep->base_addr != NULL)
+-              iounmap(ep->base_addr);
++      dev_set_drvdata(&pdev->dev, ndev);
+-      if (ep->res != NULL) {
+-              release_resource(ep->res);
+-              kfree(ep->res);
++      ret = ep93xxEth_probe(ndev);
++      if (ret != 0) {
++              free_netdev(ndev);
++              release_mem_region(res->start, 0x10000);
++              printk("ep93xxEth_probe fail\n");
++              return ret;
+       }
+-      free_netdev(dev);
+-
+       return 0;
+ }
+-static int ep93xx_eth_probe(struct platform_device *pdev)
++static int ep93xxEth_drv_remove(struct platform_device *pdev)
+ {
+-      struct ep93xx_eth_data *data;
+-      struct net_device *dev;
+-      struct ep93xx_priv *ep;
+-      int err;
++      struct net_device *ndev = dev_get_drvdata(&pdev->dev);
++      struct resource *res;
+-      if (pdev == NULL)
+-              return -ENODEV;
+-      data = pdev->dev.platform_data;
++      dev_set_drvdata(&pdev->dev, NULL);
+-      dev = ep93xx_dev_alloc(data);
+-      if (dev == NULL) {
+-              err = -ENOMEM;
+-              goto err_out;
+-      }
+-      ep = netdev_priv(dev);
+-      ep->dev = dev;
+-      netif_napi_add(dev, &ep->napi, ep93xx_poll, 64);
+-
+-      platform_set_drvdata(pdev, dev);
+-
+-      ep->res = request_mem_region(pdev->resource[0].start,
+-                      pdev->resource[0].end - pdev->resource[0].start + 1,
+-                      pdev->dev.bus_id);
+-      if (ep->res == NULL) {
+-              dev_err(&pdev->dev, "Could not reserve memory region\n");
+-              err = -ENOMEM;
+-              goto err_out;
+-      }
+-
+-      ep->base_addr = ioremap(pdev->resource[0].start,
+-                      pdev->resource[0].end - pdev->resource[0].start);
+-      if (ep->base_addr == NULL) {
+-              dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+-              err = -EIO;
+-              goto err_out;
+-      }
+-      ep->irq = pdev->resource[1].start;
+-
+-      ep->mii.phy_id = data->phy_id;
+-      ep->mii.phy_id_mask = 0x1f;
+-      ep->mii.reg_num_mask = 0x1f;
+-      ep->mii.dev = dev;
+-      ep->mii.mdio_read = ep93xx_mdio_read;
+-      ep->mii.mdio_write = ep93xx_mdio_write;
+-      ep->mdc_divisor = 40;   /* Max HCLK 100 MHz, min MDIO clk 2.5 MHz.  */
++      unregister_netdev(ndev);
+-      err = register_netdev(dev);
+-      if (err) {
+-              dev_err(&pdev->dev, "Failed to register netdev\n");
+-              goto err_out;
+-      }
++      free_irq(ndev->irq, ndev);
+-      printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, "
+-                       "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x.\n", dev->name,
+-                      ep->irq, data->dev_addr[0], data->dev_addr[1],
+-                      data->dev_addr[2], data->dev_addr[3],
+-                      data->dev_addr[4], data->dev_addr[5]);
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      release_mem_region(res->start, 0x10000);
+-      return 0;
++      free_netdev(ndev);
+-err_out:
+-      ep93xx_eth_remove(pdev);
+-      return err;
++      return 0;
+ }
+-
+ static struct platform_driver ep93xx_eth_driver = {
+-      .probe          = ep93xx_eth_probe,
+-      .remove         = ep93xx_eth_remove,
++      .probe          = ep93xxEth_drv_probe,
++      .remove         = ep93xxEth_drv_remove,
+       .driver         = {
+-              .name   = "ep93xx-eth",
++              .name   = cardname,
++              .owner  = THIS_MODULE,
+       },
+ };
+-static int __init ep93xx_eth_init_module(void)
++static int __init ep93xxEth_init(void)
+ {
+-      printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
++      PRINTK("ep93xxEth_init\n");
+       return platform_driver_register(&ep93xx_eth_driver);
+ }
+-static void __exit ep93xx_eth_cleanup_module(void)
++static void __exit ep93xxEth_cleanup(void)
+ {
+       platform_driver_unregister(&ep93xx_eth_driver);
+ }
+-module_init(ep93xx_eth_init_module);
+-module_exit(ep93xx_eth_cleanup_module);
++module_init(ep93xxEth_init);
++module_exit(ep93xxEth_cleanup);
++
++MODULE_AUTHOR("Cirrus Logic");
++MODULE_DESCRIPTION("EP93xx ethernet driver");
+ MODULE_LICENSE("GPL");
+Index: linux-2.6.24.7/drivers/net/arm/ep93xx_eth.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.24.7/drivers/net/arm/ep93xx_eth.h        2009-09-16 17:37:41.000000000 +0100
+@@ -0,0 +1,402 @@
++/*------------------------------------------------------------------------
++ * 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 _EP9213_ETH_H_
++#define _EP9213_ETH_H_
++
++
++/*---------------------------------------------------------------
++ *  Definition of H/W Defects and Their Workarounds
++ *-------------------------------------------------------------*/
++
++
++
++/*---------------------------------------------------------------
++ *  Data types used in this driver
++ *-------------------------------------------------------------*/
++typedef  unsigned char   U8;
++typedef  unsigned short  U16;
++typedef  unsigned long   U32;
++typedef  unsigned int    UINT;
++
++
++
++/*---------------------------------------------------------------
++ * 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
++ *-------------------------------------------------------------*/
++
++typedef  union receiveDescriptor  {  /*data structure of Receive Descriptor Queue Entry*/
++    struct {        /*whole value*/
++        U32  e0,      /*1st dword entry*/
++             e1;      /*2nd dword entry*/
++    }  w;
++    struct {        /*bit field definitions*/
++        U32  ba:32,   /*Buffer Address (keep in mind this is physical address)*/
++             bl:16,   /*b15-0; Buffer Length*/
++             bi:15,   /*b30-16; Buffer Index*/
++             nsof:1;  /*b31; Not Start Of Frame*/
++    }  f;
++}  receiveDescriptor;
++
++
++typedef  union receiveStatus  {  /*data structure of Receive Status Queue Entry*/
++    struct {         /*whole word*/
++        U32  e0,       /*1st dword entry*/
++             e1;       /*2nd dword entry*/
++    }  w;
++    struct {         /*bit field*/
++        U32  rsrv1:8,  /*b7-0: reserved*/
++             hti:6,    /*b13-8: Hash Table Index*/
++             rsrv2:1,  /*b14: reserved*/
++             crci:1,   /*b15: CRC Included*/
++             crce:1,   /*b16: CRC Error*/
++             edata:1,  /*b17: Extra Data*/
++             runt:1,   /*b18: Runt Frame*/
++             fe:1,     /*b19: Framing Error*/
++             oe:1,     /*b20: Overrun Error*/
++             rxerr:1,  /*b21: Rx Error*/
++             am:2,     /*b23-22: Address Match*/
++             rsrv3:4,  /*b27-24: reserved*/
++             eob:1,    /*b28: End Of Buffer*/
++             eof:1,    /*b29: End Of Frame*/
++             rwe:1,    /*b30: Received Without Error*/
++             rfp:1,    /*b31: Receive Frame Processed*/
++             fl:16,    /*b15-0: frame length*/
++             bi:15,    /*b30-16: Buffer Index*/
++             rfp2:1;   /*b31: Receive Frame Processed at 2nd word*/
++    }  f;
++}  receiveStatus;
++
++
++typedef  union transmitDescriptor  {  /*data structure of Transmit Descriptor Queue Entry*/
++    struct {         /*whole value*/
++        U32  e0,       /*1st dword entry*/
++             e1;       /*2nd dword entry*/
++    }  w;
++    struct {         /*bit field*/
++        U32  ba:32,    /*b31-0: Buffer Address (keep in mind this is physical address)*/
++             bl:12,    /*b11-0: Buffer Length*/
++             rsrv1:3,  /*b14-12: reserved*/
++             af:1,     /*b15: Abort Frame*/
++             bi:15,    /*b30-16: Buffer Index*/
++             eof:1;    /*b31: End Of Frame*/
++
++    }  f;
++}  transmitDescriptor;
++
++
++typedef  union transmitStatus  {  /*data structure of Transmit Status Queue Entry*/
++    struct {         /*whole word*/
++        U32  e0;       /*1st dword entry*/
++    }  w;
++    struct {         /*bit field*/
++        U32  bi:15,    /*b14-0: Buffer Index*/
++             rsrv3:1,  /*b15: reserved*/
++             ncoll:5,  /*b20-16: Number of Collisions*/
++             rsrv2:3,  /*b23-21: reserved*/
++             ecoll:1,  /*b24: Excess Collisions*/
++             txu:1,    /*b25: Tx Underrun*/
++             ow:1,     /*b26: Out of Window*/
++             rsrv1:1,  /*b27: reserved*/
++             lcrs:1,   /*b28: Loss of CRS*/
++             fa:1,     /*b29: Frame Abort*/
++             txwe:1,   /*b30: Transmitted Without Error*/
++             txfp:1;   /*b31: Transmit Frame Processed*/
++    }  f;
++}  transmitStatus;
++
++
++
++/*---------------------------------------------------------------
++ *  Size of device registers occupied in memory/IO address map
++ *-------------------------------------------------------------*/
++#define  DEV_REG_SPACE  0x00010000
++
++/*
++#define U8 unsigned char
++#define U16 unsigned short
++#define U32 unsigned long
++*/
++
++/*---------------------------------------------------------------
++ * A definition of register access macros
++ *-------------------------------------------------------------*/
++#define  _RegRd(type,ofs)     (*(volatile type*)(ofs))
++#define  _RegWr(type,ofs,dt)  *(volatile type*)(ofs)=((type)(dt))
++
++#define  RegRd8(ofs)   _RegRd(U8,(char*)pD->base_addr+(ofs))
++#define  RegRd16(ofs)  _RegRd(U16,(char*)pD->base_addr+(ofs))
++#define  RegRd32(ofs)  _RegRd(U32,(char*)pD->base_addr+(ofs))
++#define  RegWr8(ofs,dt)   _RegWr(U8,(char*)pD->base_addr+(ofs),(dt))
++#define  RegWr16(ofs,dt)  _RegWr(U16,(char*)pD->base_addr+(ofs),(dt))
++#define  RegWr32(ofs,dt)  _RegWr(U32,(char*)pD->base_addr+(ofs),(dt))
++
++
++
++#endif  /* _EP9213_ETH_H_ */
++
diff --git a/recipes/linux/linux-2.6.32/ep93xx/ep93xx-i2c.patch b/recipes/linux/linux-2.6.32/ep93xx/ep93xx-i2c.patch
new file mode 100644 (file)
index 0000000..60b9af1
--- /dev/null
@@ -0,0 +1,234 @@
+---
+ drivers/i2c/busses/Kconfig      |    5 +
+ drivers/i2c/busses/Makefile     |    1 
+ drivers/i2c/busses/i2c-ep93xx.c |  194 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 200 insertions(+)
+
+--- linux-2.6.32.orig/drivers/i2c/busses/Kconfig
++++ linux-2.6.32/drivers/i2c/busses/Kconfig
+@@ -351,10 +351,15 @@ config I2C_DESIGNWARE
+         Synopsys DesignWare I2C adapter. Only master mode is supported.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-designware.
++config I2C_EP93XX
++      tristate "EP93XX I2C"
++      depends on I2C && ARCH_EP93XX
++      select I2C_ALGOBIT
++
+ config I2C_GPIO
+       tristate "GPIO-based bitbanging I2C"
+       depends on GENERIC_GPIO
+       select I2C_ALGOBIT
+       help
+--- linux-2.6.32.orig/drivers/i2c/busses/Makefile
++++ linux-2.6.32/drivers/i2c/busses/Makefile
+@@ -72,9 +72,10 @@ obj-$(CONFIG_I2C_PCA_PLATFORM)      += i2c-pc
+ obj-$(CONFIG_I2C_PMCMSP)      += i2c-pmcmsp.o
+ obj-$(CONFIG_I2C_SIBYTE)      += i2c-sibyte.o
+ obj-$(CONFIG_I2C_STUB)                += i2c-stub.o
+ obj-$(CONFIG_SCx200_ACB)      += scx200_acb.o
+ obj-$(CONFIG_SCx200_I2C)      += scx200_i2c.o
++obj-$(CONFIG_I2C_EP93XX)      += i2c-ep93xx.o
+ ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
+ EXTRA_CFLAGS += -DDEBUG
+ endif
+--- /dev/null
++++ linux-2.6.32/drivers/i2c/busses/i2c-ep93xx.c
+@@ -0,0 +1,194 @@
++/* ------------------------------------------------------------------------ *
++ * 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 <mach/hardware.h>
++
++//1/(2*clockfrequency)
++#define EE_DELAY_USEC       50
++#define GPIOG_EECLK 1
++#define GPIOG_EEDAT 2
++
++/* ----- I2C algorithm call-back functions and structures ----------------- */
++
++// TODO: optimize
++static void ep93xx_setscl(void *data, int state)
++{
++      unsigned int uiPGDR, uiPGDDR;
++
++      uiPGDR = inl(GPIO_PGDR);
++      uiPGDDR = inl(GPIO_PGDDR);
++
++      /* Configure the clock line as output. */
++      uiPGDDR |= GPIOG_EECLK;
++      outl(uiPGDDR, GPIO_PGDDR);
++
++      /* Set clock line to state */
++      if(state)
++              uiPGDR |= GPIOG_EECLK;
++      else
++              uiPGDR &= ~GPIOG_EECLK;
++
++      outl(uiPGDR, GPIO_PGDR);
++}
++
++static void ep93xx_setsda(void *data, int state)
++{
++      unsigned int uiPGDR, uiPGDDR;
++
++      uiPGDR = inl(GPIO_PGDR);
++      uiPGDDR = inl(GPIO_PGDDR);
++
++      /* Configure the data line as output. */
++      uiPGDDR |= GPIOG_EEDAT;
++      outl(uiPGDDR, GPIO_PGDDR);
++
++      /* Set data line to state */
++      if(state)
++              uiPGDR |= GPIOG_EEDAT;
++      else
++              uiPGDR &= ~GPIOG_EEDAT;
++
++      outl(uiPGDR, GPIO_PGDR);
++}
++
++static int ep93xx_getscl(void *data)
++{
++      unsigned int uiPGDR, uiPGDDR;
++
++      uiPGDR = inl(GPIO_PGDR);
++      uiPGDDR = inl(GPIO_PGDDR);
++
++      /* Configure the clock line as input */
++      uiPGDDR &= ~GPIOG_EECLK;
++      outl(uiPGDDR, GPIO_PGDDR);
++
++      /* Return state of the clock line */
++      return (inl(GPIO_PGDR) & GPIOG_EECLK) ? 1 : 0;
++}
++
++static int ep93xx_getsda(void *data)
++{
++      unsigned int uiPGDR, uiPGDDR;
++      uiPGDR = inl(GPIO_PGDR);
++      uiPGDDR = inl(GPIO_PGDDR);
++
++      /* Configure the data line as input */
++      uiPGDDR &= ~GPIOG_EEDAT;
++      outl(uiPGDDR, GPIO_PGDDR);
++
++      /* Return state of the data line */
++      return (inl(GPIO_PGDR) & GPIOG_EEDAT) ? 1 : 0;
++}
++
++/* ------------------------------------------------------------------------
++ * Encapsulate the above functions in the correct operations structure.
++ * This is only done when more than one hardware adapter is supported.
++ */
++
++/* last line (us, ms, timeout)
++ * us dominates the bit rate: 10us  means: 100Kbit/sec(25 means 40kbps)
++ *                            10ms  not known
++ *                            100ms timeout
++ */
++static struct i2c_algo_bit_data ep93xx_data = {
++      .setsda         = ep93xx_setsda,
++      .setscl         = ep93xx_setscl,
++      .getsda         = ep93xx_getsda,
++      .getscl         = ep93xx_getscl,
++      .udelay         = 10,
++      //.mdelay               = 10,
++      .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_data,
++      .name           = "EP93XX I2C bit-bang interface",
++};
++
++/* ----- Module loading, unloading and information ------------------------ */
++
++static int __init i2c_ep93xx_init(void)
++{
++      unsigned long uiPGDR, uiPGDDR;
++
++      /* Read the current value of the GPIO data and data direction registers. */
++      uiPGDR = inl(GPIO_PGDR);
++      uiPGDDR = inl(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. */
++      uiPGDR |= (GPIOG_EEDAT | GPIOG_EECLK);
++      outl(uiPGDR, GPIO_PGDR);
++
++      /* Delay to meet the EE Interface timing specification. */
++      udelay(EE_DELAY_USEC);
++
++
++      /* Configure the EE data and clock lines as outputs. */
++      uiPGDDR |= (GPIOG_EEDAT | GPIOG_EECLK);
++      outl(uiPGDDR, 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);
++      i2c_del_adapter(&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/recipes/linux/linux-2.6.32/ep93xx/ep93xx-regs.patch b/recipes/linux/linux-2.6.32/ep93xx/ep93xx-regs.patch
new file mode 100644 (file)
index 0000000..5b77633
--- /dev/null
@@ -0,0 +1,490 @@
+---
+ arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h |  440 ++++++++++++++++++++++++
+ 1 file changed, 440 insertions(+)
+
+--- linux-2.6.32.orig/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
++++ linux-2.6.32/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+@@ -60,10 +60,36 @@
+ #define EP93XX_APB_SIZE                       0x00200000
+ #define EP93XX_APB_PHYS(x)            (EP93XX_APB_PHYS_BASE + (x))
+ #define EP93XX_APB_IOMEM(x)           IOMEM(EP93XX_APB_VIRT_BASE + (x))
++/* 8081_0000 - 8081_ffff: Timers */
++#define TIMERS_OFFSET           0x010000
++#define TIMERS_BASE             (EP93XX_APB_VIRT_BASE|TIMERS_OFFSET)
++
++#define TIMER1LOAD              (TIMERS_BASE+0x00)
++#define TIMER1VALUE             (TIMERS_BASE+0x04)
++#define TIMER1CONTROL           (TIMERS_BASE+0x08)
++#define TIMER1CLEAR             (TIMERS_BASE+0x0C)
++#define TIMER1TEST              (TIMERS_BASE+0x10)
++
++#define TIMER2LOAD              (TIMERS_BASE+0x20)
++#define TIMER2VALUE             (TIMERS_BASE+0x24)
++#define TIMER2CONTROL           (TIMERS_BASE+0x28)
++#define TIMER2CLEAR             (TIMERS_BASE+0x2C)
++#define TIMER2TEST              (TIMERS_BASE+0x30)
++
++#define TIMER3LOAD              (TIMERS_BASE+0x80)
++#define TIMER3VALUE             (TIMERS_BASE+0x84)
++#define TIMER3CONTROL           (TIMERS_BASE+0x88)
++#define TIMER3CLEAR             (TIMERS_BASE+0x8C)
++#define TIMER3TEST              (TIMERS_BASE+0x90)
++
++#define TTIMERBZCONT            (TIMERS_BASE+0x40)
++
++#define TIMER4VALUELOW          (TIMERS_BASE+0x60)
++#define TIMER4VALUEHIGH         (TIMERS_BASE+0x64)
+ /* AHB peripherals */
+ #define EP93XX_DMA_BASE                       EP93XX_AHB_IOMEM(0x00000000)
+ #define EP93XX_ETHERNET_PHYS_BASE     EP93XX_AHB_PHYS(0x00010000)
+@@ -109,10 +135,12 @@
+ #define EP93XX_TIMER3_CLEAR           EP93XX_TIMER_REG(0x8c)
+ #define EP93XX_I2S_BASE                       EP93XX_APB_IOMEM(0x00020000)
+ #define EP93XX_SECURITY_BASE          EP93XX_APB_IOMEM(0x00030000)
++#define EP93XX_SECURITY_REG(x)                (EP93XX_SECURITY_BASE + (x))
++#define EP93XX_SECURITY_UNIQID                EP93XX_SECURITY_REG(0x2440)
+ #define EP93XX_GPIO_BASE              EP93XX_APB_IOMEM(0x00040000)
+ #define EP93XX_GPIO_REG(x)            (EP93XX_GPIO_BASE + (x))
+ #define EP93XX_GPIO_F_INT_STATUS      EP93XX_GPIO_REG(0x5c)
+ #define EP93XX_GPIO_A_INT_STATUS      EP93XX_GPIO_REG(0xa0)
+@@ -120,10 +148,11 @@
+ #define EP93XX_GPIO_EEDRIVE           EP93XX_GPIO_REG(0xc8)
+ #define EP93XX_AAC_BASE                       EP93XX_APB_IOMEM(0x00080000)
+ #define EP93XX_SPI_BASE                       EP93XX_APB_IOMEM(0x000a0000)
++#define EP93XX_SPI_BASE_PHYS          (EP93XX_APB_PHYS_BASE + 0x000a0000)
+ #define EP93XX_IRDA_BASE              EP93XX_APB_IOMEM(0x000b0000)
+ #define EP93XX_UART1_PHYS_BASE                EP93XX_APB_PHYS(0x000c0000)
+ #define EP93XX_UART1_BASE             EP93XX_APB_IOMEM(0x000c0000)
+@@ -219,10 +248,421 @@
+ #define EP93XX_SYSCON_SYSCFG_LEEDA    (1<<4)
+ #define EP93XX_SYSCON_SYSCFG_LEECLK   (1<<3)
+ #define EP93XX_SYSCON_SYSCFG_LCSN2    (1<<1)
+ #define EP93XX_SYSCON_SYSCFG_LCSN1    (1<<0)
+ #define EP93XX_SYSCON_SWLOCK          EP93XX_SYSCON_REG(0xc0)
++#define EP93XX_SYSCON_CHIP_ID         EP93XX_SYSCON_REG(0x94)
++#define EP93XX_SYSCON_BMAR              EP93XX_SYSCON_REG(0x54)
++#define EP93XX_SYSCON_I2SDIV            EP93XX_SYSCON_REG(0x8C)
++#define EP93XX_SYSCON_DEVCFG_CONFIG_Mong      0x02000000
++#define EP93XX_SYSCON_DEVCFG_CONFIG_Tong      0x04000000
++#define EP93XX_SYSCON_DEVCFG_CONFIG_I2SONSSP          0x00000080
++#define EP93XX_SYSCON_DEVCFG_CONFIG_I2SONAC97         0x00000040
++#define EP93XX_SYSCON_DEVCFG_RasOnP3            0x00000010
++#define EP93XX_SYSCON_DEVCFG_A1onG              0x00200000
++#define EP93XX_SYSCON_DEVCFG_A2onG              0x00400000
+ #define EP93XX_WATCHDOG_BASE          EP93XX_APB_IOMEM(0x00140000)
++#define SYSCON_PWRCNT           (EP93XX_SYSCON_BASE+0x0004)
++#define SYSCON_VIDDIV           (EP93XX_SYSCON_BASE+0x0084)
++#define SYSCON_MIRDIV           (EP93XX_SYSCON_BASE+0x0088)
++#define SYSCON_KTDIV            (EP93XX_SYSCON_BASE+0x0090)
++#define SYSCON_KTDIV_TSEN       0x80000000
++//-----------------------------------------------------------------------------
++// 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
++
++//-----------------------------------------------------------------------------
++// 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
++
++//-----------------------------------------------------------------------------
++// 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
++
++/* 8082_0000 - 8082_ffff: I2S */
++#define I2S_OFFSET            0x020000
++#define I2S_BASE              (EP93XX_APB_VIRT_BASE|I2S_OFFSET)
++#define I2S_PHYS_BASE         (EP93XX_APB_PHYS_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                 */
++
++/* 8084_0000 - 8084_ffff: GPIO */
++#define GPIO_OFFSET              0x040000
++#define GPIO_BASE                (EP93XX_APB_VIRT_BASE|GPIO_OFFSET)
++#define GPIO_PADR                (GPIO_BASE+0x00)
++#define GPIO_PBDR                (GPIO_BASE+0x04)
++#define GPIO_PCDR                (GPIO_BASE+0x08)
++#define GPIO_PDDR                (GPIO_BASE+0x0C)
++#define GPIO_PADDR               (GPIO_BASE+0x10)
++#define GPIO_PBDDR               (GPIO_BASE+0x14)
++#define GPIO_PCDDR               (GPIO_BASE+0x18)
++#define GPIO_PDDDR               (GPIO_BASE+0x1C)
++#define GPIO_PEDR                (GPIO_BASE+0x20)
++#define GPIO_PEDDR               (GPIO_BASE+0x24)
++// #define 0x8084.0028 Reserved
++// #define 0x8084.002C Reserved
++#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 0x8084.0048 RAZ RAZ
++#define GPIO_FINTTYPE1           (GPIO_BASE+0x4C)
++#define GPIO_FINTTYPE2           (GPIO_BASE+0x50)
++#define GPIO_FEOI                (GPIO_BASE+0x54) /* WRITE ONLY - READ UNDEFINED */
++#define GPIO_FINTEN              (GPIO_BASE+0x58)
++#define GPIO_INTSTATUSF          (GPIO_BASE+0x5C)
++#define GPIO_RAWINTSTASUSF       (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_VIRT_BASE|AC97_OFFSET)
++#define EP93XX_AC97_PHY_BASE    (EP93XX_APB_PHYS_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                    */
++                                                               /* 8088.001C Reserved - RAZ                          */
++#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                    */
++                                                               /* 8088.003C Reserved - RAZ                          */
++#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                    */
++                                                               /* 8088.005C Reserved - RAZ                          */
++#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                    */
++                                                               /* 8088.003C Reserved - RAZ                          */
++#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                    */
++                                                               /* 8088.005C Reserved - RAZ                          */
++#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                    */
++                                                               /* 8088.007C Reserved - RAZ                          */
++#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 */
++
++
++/* 800B_0000 - 800B_FFFF: VIC 0 */
++#define VIC0_OFFSET              0x0B0000
++#define VIC0_BASE                (EP93XX_AHB_VIRT_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   */
++
++/* 8003_0000 - 8003_ffff: Raster */
++#define RASTER_OFFSET           0x030000
++#define RASTER_BASE             (EP93XX_AHB_VIRT_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 RASTER_SWLOCK           (RASTER_BASE+0x7C)
++#define GS_LUT                  (RASTER_BASE+0x80)
++#define RASTER_TCR              (RASTER_BASE+0x100)
++#define RASTER_TISRA            (RASTER_BASE+0x104)
++#define RASTER_TISRB            (RASTER_BASE+0x108)
++#define CURSOR_TISR             (RASTER_BASE+0x10C)
++#define RASTER_TOCRA            (RASTER_BASE+0x110)
++#define RASTER_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 RASTER_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)
++
++/* 8004_0000 - 8004_ffff: Graphics */
++#define GRAPHICS_OFFSET         0x040000
++#define GRAPHICS_BASE           (EP93XX_AHB_VIRT_BASE|GRAPHICS_OFFSET)
++#define SRCPIXELSTRT            (GRAPHICS_BASE+0x00)
++#define DESTPIXELSTRT           (GRAPHICS_BASE+0x04)
++#define BLKSRCSTRT              (GRAPHICS_BASE+0x08)
++#define BLKDSTSTRT              (GRAPHICS_BASE+0x0C)
++#define BLKSRCWIDTH             (GRAPHICS_BASE+0x10)
++#define SRCLINELENGTH           (GRAPHICS_BASE+0x14)
++#define BLKDESTWIDTH            (GRAPHICS_BASE+0x18)
++#define BLKDESTHEIGHT           (GRAPHICS_BASE+0x1C)
++#define DESTLINELENGTH          (GRAPHICS_BASE+0x20)
++#define BLOCKCTRL               (GRAPHICS_BASE+0x24)
++#define TRANSPATTRN             (GRAPHICS_BASE+0x28)
++#define BLOCKMASK               (GRAPHICS_BASE+0x2C)
++#define BACKGROUND              (GRAPHICS_BASE+0x30)
++#define LINEINC                 (GRAPHICS_BASE+0x34)
++#define LINEINIT                (GRAPHICS_BASE+0x38)
++#define LINEPATTRN              (GRAPHICS_BASE+0x3C)
++
++#define EP93XX_GRAPHICS_ACCEL_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00040000)
++
++#ifndef __ASSEMBLY__
++
++#define SysconSetLocked(registername,value)     \
++    {                                           \
++        local_irq_disable();                  \
++      outl( 0xAA, EP93XX_SYSCON_SWLOCK);             \
++        outl( value, registername);             \
++      local_irq_enable();                    \
++    }
++
++#endif /* Not __ASSEMBLY__ */
++
+ #endif
diff --git a/recipes/linux/linux-2.6.32/ep93xx/ep93xx-snd-ac97.patch b/recipes/linux/linux-2.6.32/ep93xx/ep93xx-snd-ac97.patch
new file mode 100644 (file)
index 0000000..226310e
--- /dev/null
@@ -0,0 +1,3829 @@
+---
+ arch/arm/mach-ep93xx/include/mach/hardware.h  |    1 
+ arch/arm/mach-ep93xx/include/mach/regs_ac97.h |  180 +
+ sound/arm/Kconfig                             |   17 
+ sound/arm/Makefile                            |    3 
+ sound/arm/ep93xx-ac97.c                       | 3482 ++++++++++++++++++++++++++
+ sound/arm/ep93xx-ac97.h                       |   89 
+ 6 files changed, 3772 insertions(+)
+
+--- linux-2.6.31.orig/arch/arm/mach-ep93xx/include/mach/hardware.h
++++ linux-2.6.31/arch/arm/mach-ep93xx/include/mach/hardware.h
+@@ -3,10 +3,11 @@
+  */
+ #ifndef __ASM_ARCH_HARDWARE_H
+ #define __ASM_ARCH_HARDWARE_H
+ #include "ep93xx-regs.h"
++#include "regs_ac97.h"
+ #define pcibios_assign_all_busses()   0
+ #include "regs_raster.h"
+ #include "regs_touch.h"
+--- /dev/null
++++ linux-2.6.31/arch/arm/mach-ep93xx/include/mach/regs_ac97.h
+@@ -0,0 +1,180 @@
++/*=============================================================================
++ *  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
++//
++typedef enum{
++    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
++} Ac97RecordSources;
++
++#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_ */
+--- linux-2.6.31.orig/sound/arm/Kconfig
++++ linux-2.6.31/sound/arm/Kconfig
+@@ -9,10 +9,27 @@ menuconfig SND_ARM
+         Drivers that are implemented on ASoC can be found in
+         "ALSA for SoC audio support" section.
+ if SND_ARM
++config SND_EP93XX_AC97
++      tristate "AC97 driver for the Cirrus EP93xx chip"
++      depends on ARCH_EP93XX && SND
++      select SND_EP93XX_PCM
++      select SND_AC97_CODEC
++      help
++        Say Y here to use AC'97 audio with a Cirrus Logic EP93xx chip.
++
++        To compile this driver as a module, choose M here: the module
++        will be called snd-ep93xx-ac97.
++
++config SND_EP93XX_PCM
++      tristate
++      select SND_PCM
++      help
++       Generic PCM module for EP93xx
++
+ config SND_ARMAACI
+       tristate "ARM PrimeCell PL041 AC Link support"
+       depends on ARM_AMBA
+       select SND_PCM
+       select SND_AC97_CODEC
+--- linux-2.6.31.orig/sound/arm/Makefile
++++ linux-2.6.31/sound/arm/Makefile
+@@ -3,10 +3,13 @@
+ #
+ obj-$(CONFIG_SND_ARMAACI)     += snd-aaci.o
+ snd-aaci-objs                 := aaci.o devdma.o
++obj-$(CONFIG_SND_EP93XX_AC97) += snd-ep93xx-ac97.o
++snd-ep93xx-ac97-objs          := ep93xx-ac97.o
++
+ obj-$(CONFIG_SND_PXA2XX_PCM)  += snd-pxa2xx-pcm.o
+ snd-pxa2xx-pcm-objs           := pxa2xx-pcm.o
+ obj-$(CONFIG_SND_PXA2XX_LIB)  += snd-pxa2xx-lib.o
+ snd-pxa2xx-lib-y              := pxa2xx-pcm-lib.o
+--- /dev/null
++++ linux-2.6.31/sound/arm/ep93xx-ac97.c
+@@ -0,0 +1,3482 @@
++/*
++ * linux/sound/arm/ep93xx-ac97.c -- ALSA PCM interface for the edb93xx ac97 audio
++ */
++
++#include <linux/autoconf.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/soundcard.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/control.h>
++#include <sound/initval.h>
++#include <sound/ac97_codec.h>
++
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/arch/dma.h>
++#include "ep93xx-ac97.h"
++
++#define       DRIVER_VERSION  "01/05/2009"
++#define       DRIVER_DESC     "EP93xx AC97 Audio driver"
++static int ac_link_enabled = 0;
++static int codec_supported_mixers;
++
++//#define DEBUG 1
++#ifdef DEBUG
++#define DPRINTK( fmt, arg... )  printk( fmt, ##arg )
++#else
++#define DPRINTK( fmt, arg... )
++#endif
++
++#define WL16  0
++#define WL24  1
++
++#define AUDIO_NAME                    "ep93xx-ac97"
++#define AUDIO_SAMPLE_RATE_DEFAULT       44100
++#define AUDIO_DEFAULT_VOLUME            0
++#define AUDIO_MAX_VOLUME              181
++#define AUDIO_DEFAULT_DMACHANNELS       3
++#define PLAYBACK_DEFAULT_DMACHANNELS    3
++#define CAPTURE_DEFAULT_DMACHANNELS     3
++
++#define CHANNEL_FRONT                 (1<<0)
++#define CHANNEL_REAR                          (1<<1)
++#define CHANNEL_CENTER_LFE              (1<<2)
++
++static void snd_ep93xx_dma_tx_callback( ep93xx_dma_int_t DMAInt,
++                                      ep93xx_dma_dev_t device,
++                                      unsigned int user_data);
++static void snd_ep93xx_dma_rx_callback( ep93xx_dma_int_t DMAInt,
++                                      ep93xx_dma_dev_t device,
++                                      unsigned int user_data);
++
++static const struct snd_pcm_hardware ep93xx_ac97_pcm_hardware = {
++
++
++    .info             = ( SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE  ),
++    .formats          = ( SNDRV_PCM_FMTBIT_U8     | SNDRV_PCM_FMTBIT_S8     |
++                          SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
++                          SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
++                          SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
++                          SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE ),
++    .rates            = ( SNDRV_PCM_RATE_8000  | SNDRV_PCM_RATE_11025 |
++                          SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
++                          SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
++                          SNDRV_PCM_RATE_48000 ),
++    .rate_min         = 8000,
++    .rate_max         = 48000,
++    .channels_min     = 1,/*2,*/
++    .channels_max     = 2,
++
++    .period_bytes_min = 1 * 1024,
++    .period_bytes_max = 32 * 1024,
++    .periods_min      = 1,
++    .periods_max      = 32,
++    .buffer_bytes_max = 32 * 1024,
++    .fifo_size                = 0,
++};
++
++static audio_stream_t output_stream;
++static audio_stream_t input_stream;
++
++static audio_state_t audio_state =
++{
++    .output_stream            =&output_stream,
++    .output_dma[0]            =DMATx_AAC1,
++    .output_id[0]             ="Ac97 out",
++
++    .input_stream             =&input_stream,
++    .input_dma[0]             =DMARx_AAC1,
++    .input_id[0]              ="Ac97 in",
++
++    .sem                    = __SEMAPHORE_INIT(audio_state.sem,1),
++    .codec_set_by_playback  = 0,
++    .codec_set_by_capture   = 0,
++    .DAC_bit_width             =16,
++    .bCompactMode              =0,
++};
++
++
++
++/*
++ * peek
++ *
++ * Reads an AC97 codec register.  Returns -1 if there was an error.
++ */
++static int peek(unsigned int uiAddress)
++{
++      unsigned int uiAC97RGIS;
++
++      if( !ac_link_enabled )
++      {
++              printk("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);
++      udelay( 21 * 4 );
++      uiAC97RGIS = inl( AC97RGIS );
++
++      /*
++       * Return error if we timed out.
++       */
++      if( ((uiAC97RGIS & AC97RGIS_SLOT1TXCOMPLETE) == 0 ) &&
++              ((uiAC97RGIS & AC97RGIS_SLOT2RXVALID) == 0 ) )
++      {
++              printk( "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;
++
++      if( !ac_link_enabled )
++      {
++              printk("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))
++      {
++              printk("ep93xx ac97 poke: address error.\n");
++              return -1;
++      }
++
++      /*stop the audio loop from the input to the output directly*/
++
++      if((uiAddress==AC97_0E_MIC_VOL)||(uiAddress==AC97_10_LINE_IN_VOL))
++      {
++              uiValue = (uiValue | 0x8000);
++
++      }
++
++      /*
++       * 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 );
++
++      /*
++       * Wait for the tx to complete, get status.
++       */
++      udelay( 30 );/*21*/
++      uiAC97RGIS = inl(AC97RGIS);
++
++      /*
++       * Return error if we timed out.
++       */
++      if( !(inl(AC97RGIS) & AC97RGIS_SLOT1TXCOMPLETE) )
++      {
++              printk( "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( int input_or_output_stream )
++{
++      unsigned int uiTemp;
++
++      DPRINTK("ep93xx_audio_enable :%x\n",input_or_output_stream);
++
++      /*
++       * Enable the rx or tx channel depending on the value of
++       * input_or_output_stream
++       */
++      if( input_or_output_stream )
++      {
++              uiTemp = inl(AC97TXCR1);
++              outl( (uiTemp | AC97TXCR_TEN), AC97TXCR1 );
++      }
++      else
++      {
++              uiTemp = inl(AC97RXCR1);
++              outl( (uiTemp | AC97RXCR_REN), AC97RXCR1 );
++      }
++
++
++      //DDEBUG("ep93xx_audio_enable - EXIT\n");
++}
++
++static void ep93xx_audio_disable( int input_or_output_stream )
++{
++      unsigned int uiTemp;
++
++      DPRINTK("ep93xx_audio_disable\n");
++
++      /*
++       * Disable the rx or tx channel depending on the value of
++       * input_or_output_stream
++       */
++      if( input_or_output_stream )
++      {
++              uiTemp = inl(AC97TXCR1);
++              outl( (uiTemp & ~AC97TXCR_TEN), AC97TXCR1 );
++      }
++      else
++      {
++              uiTemp = inl(AC97RXCR1);
++              outl( (uiTemp & ~AC97RXCR_REN), AC97RXCR1 );
++      }
++
++      //DDEBUG("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
++ *   bCapture       - 0 to set Tx sample rate; 1 to set Rx sample rate
++ */
++static void ep93xx_set_samplerate( long lSampleRate, int bCapture )
++{
++      unsigned short usDivider, usPhase;
++
++      DPRINTK( "ep93xx_set_samplerate - Fs = %d\n", (int)lSampleRate );
++
++      if( (lSampleRate <  7200) || (lSampleRate > 48000)  )
++      {
++              printk( "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(!bCapture)
++      {
++              poke( AC97_2C_PCM_FRONT_DAC_RATE, usDivider);
++              poke( AC97_64_DAC_SRC_PHASE_INCR, usPhase);
++      }
++      else
++      {
++
++              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.
++       */
++      //audio_samplerate = lSampleRate;
++
++      DPRINTK( "ep93xx_set_samplerate - EXIT\n" );
++}
++
++/*
++ * 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( long format,long channel )
++{
++      int bCompactMode;
++
++      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 SNDRV_PCM_FORMAT_U8:
++              case SNDRV_PCM_FORMAT_S8:
++              case SNDRV_PCM_FORMAT_S16_LE:
++              case SNDRV_PCM_FORMAT_U16_LE:
++                      bCompactMode = 1;
++                      break;
++
++              /*
++               * Add any other >16 bit formats here...
++               */
++              case SNDRV_PCM_FORMAT_S32_LE:
++              default:
++                      bCompactMode = 0;
++                      break;
++      }
++
++      if( bCompactMode )
++      {
++              DPRINTK("ep93xx_set_hw_format - Setting serial mode to 16 bit compact.\n");
++
++              /*
++               * Turn on Compact Mode so we can fit each stereo sample into
++               * a 32 bit word.  Twice as efficent for DMA and FIFOs.
++               */
++              if(channel==2){
++                      outl( 0x00008018, AC97RXCR1 );
++                      outl( 0x00008018, AC97TXCR1 );
++              }
++              else {
++                      outl( 0x00008018, AC97RXCR1 );
++                        outl( 0x00008018, AC97TXCR1 );
++                }
++
++
++              audio_state.DAC_bit_width = 16;
++              audio_state.bCompactMode = 1;
++      }
++      else
++      {
++              DPRINTK("ep93xx_set_hw_format - Setting serial mode to 20 bit non-CM.\n");
++
++              /*
++               * Turn off Compact Mode so we can do > 16 bits per channel
++               */
++              if(channel==2){
++                      outl( 0x00004018, AC97RXCR1 );
++                      outl( 0x00004018, AC97TXCR1 );
++              }
++              else{
++                        outl( 0x00004018, AC97RXCR1 );
++                        outl( 0x00004018, AC97TXCR1 );
++              }
++
++              audio_state.DAC_bit_width = 20;
++              audio_state.bCompactMode = 0;
++      }
++
++}
++
++/*
++ * ep93xx_stop_loop
++ *
++ * Once the ac-link is up and all is good, we want to set the codec to a
++ * usable mode.
++ */
++static void ep93xx_stop_loop(void)
++{
++        int iTemp;
++
++        /*
++         * Set the AC97_0E_MIC_VOL MUTE bit to enable the LOOP.
++         */
++        iTemp = peek( AC97_0E_MIC_VOL );
++        poke( AC97_0E_MIC_VOL,  (iTemp | 0x8000) );
++
++        /*
++         * Set the AC97_10_LINE_IN_VOL MUTE bit to enable the LOOP.
++         */
++        iTemp = peek( AC97_10_LINE_IN_VOL  );
++        poke( AC97_10_LINE_IN_VOL, (iTemp  | 0x8000) );
++}
++
++/*
++ * 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(EP93XX_SYSCON_DEVICE_CONFIG);
++
++      uiDEVCFG &= ~(EP93XX_SYSCON_DEVCFG_CONFIG_I2SONAC97 |
++                                EP93XX_SYSCON_DEVCFG_A1onG |
++                                EP93XX_SYSCON_DEVCFG_A2onG);
++
++      SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, 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 );
++
++      /*
++       * Set the TIMEDRESET bit.  Will cause a > 1uSec reset of the ac-link.
++       * This bit is self resetting.
++       */
++      outl( AC97RESET_TIMEDRESET, AC97RESET );
++
++      /*
++       *  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))
++      {
++              printk( "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( EP93XX_DEFAULT_FORMAT,EP93XX_DEFAULT_NUM_CHANNELS );
++
++      DPRINTK( "ep93xx-ac97 -- AC97RXCR1:  %08x\n", inl(AC97RXCR1) );
++      DPRINTK( "ep93xx-ac97 -- AC97TXCR1:  %08x\n", inl(AC97TXCR1) );
++
++      DPRINTK("ep93xx_init_ac97_controller - EXIT - success\n");
++
++}
++
++#ifdef alsa_ac97_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);
++      }
++
++      DPRINTK( "---------------------------------------------\n");
++}
++#endif
++
++
++#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)
++
++
++
++
++/* this table has default mixer values for all OSS mixers. */
++typedef struct  {
++      int mixer;
++      unsigned int value;
++} mixer_defaults_t;
++
++/*
++ * 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 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 */  /* -34.5dB to +12dB */
++
++      /* 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 */
++};
++
++/* table to scale scale from OSS mixer value to AC97 mixer register value */
++typedef struct {
++      unsigned int offset;
++      int scale;
++} ac97_mixer_hw_t;
++
++static 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
++};
++
++
++/*
++ * ep93xx_write_mixer
++ *
++ */
++static void ep93xx_write_mixer
++(
++      int oss_channel,
++      unsigned int left,
++      unsigned int right
++)
++{
++      u16 val = 0;
++      ac97_mixer_hw_t * mh = &ac97_hw[oss_channel];
++
++      DPRINTK("ac97_codec: wrote OSS %2d (ac97 0x%02x), "
++             "l:%2d, r:%2d:",
++             oss_channel, mh->offset, left, right);
++
++      if( !mh->scale )
++      {
++              printk( "ep93xx-ac97.c: ep93xx_write_mixer - not a valid OSS channel\n");
++              return;
++      }
++
++      if( AC97_STEREO_MASK & (1 << oss_channel) )
++      {
++              /* stereo mixers */
++              if (left == 0 && right == 0)
++              {
++                      val = 0x8000;
++              }
++              else
++              {
++                      if (oss_channel == SOUND_MIXER_IGAIN)
++                      {
++                              right = (right * mh->scale) / 100;
++                              left = (left * mh->scale) / 100;
++                              if (right >= mh->scale)
++                                      right = mh->scale-1;
++                              if (left >= mh->scale)
++                                      left = mh->scale-1;
++                      }
++                      else
++                      {
++                              right = ((100 - right) * mh->scale) / 100;
++                              left = ((100 - left) * mh->scale) / 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) / 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) / 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) / 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) / 100;
++              if (left >= mh->scale)
++                      left = mh->scale-1;
++              val |= left & 0x000e;
++      }
++
++      DPRINTK(" 0x%04x", val);
++
++      poke( mh->offset, val );
++
++#ifdef alsa_ac97_debug
++      val = peek( mh->offset );
++      DEBUG(" -> 0x%04x\n", val);
++#endif
++
++}
++
++/* a thin wrapper for write_mixer */
++static void ep93xx_set_mixer
++(
++      unsigned int oss_mixer,
++      unsigned int val
++)
++{
++      unsigned int left,right;
++
++      /* cleanse input a little */
++      right = ((val >> 8)  & 0xff) ;
++      left = (val  & 0xff) ;
++
++      if (right > 100) right = 100;
++      if (left > 100) left = 100;
++
++      /*mixer_state[oss_mixer] = (right << 8) | left;*/
++      ep93xx_write_mixer( oss_mixer, left, right);
++}
++
++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_mixer( mixer_defaults[i].mixer, mixer_defaults[i].value);
++      }
++
++}
++
++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 */
++
++      /*
++       *
++       */
++        val = peek( AC97_1A_RECORD_SELECT ) & 0x0707;
++        if ((val&0x0404)!=0)
++          val=0x0404;
++        else if((val&0x0000)!=0)
++          val=0x0101;
++
++
++      DPRINTK("ac97_codec: setting ac97 recmask to 0x%04x\n", val);
++
++      poke( AC97_1A_RECORD_SELECT, val);
++
++      return 0;
++}
++
++/*
++ * 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( AUDIO_SAMPLE_RATE_DEFAULT, 0 );
++      ep93xx_set_samplerate( AUDIO_SAMPLE_RATE_DEFAULT, 1 );
++      ep93xx_init_mixer();
++
++      DPRINTK("ep93xx_init_ac97_codec - EXIT\n");
++
++}
++
++
++/*
++ * ep93xx_audio_init
++ * Audio interface
++ */
++static void ep93xx_audio_init(void)
++{
++      DPRINTK("ep93xx_audio_init - enter\n");
++      /*
++       * Init the controller, enable the ac-link.
++       * Initialize the codec.
++       */
++      ep93xx_init_ac97_controller();
++      ep93xx_init_ac97_codec();
++      /*stop the audio loop from the input to the output directly*/
++      ep93xx_stop_loop();
++
++#ifdef alsa_ac97_debug
++      ep93xx_dump_ac97_regs();
++#endif
++      DPRINTK("ep93xx_audio_init - EXIT\n");
++}
++
++/*====================================================================================*/
++
++
++static void print_audio_format( long format )
++{
++    switch( format ){
++      case SNDRV_PCM_FORMAT_S8:
++              DPRINTK( "AFMT_S8\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_U8:
++              DPRINTK( "AFMT_U8\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_S16_LE:
++              DPRINTK( "AFMT_S16_LE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_S16_BE:
++              DPRINTK( "AFMT_S16_BE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_U16_LE:
++              DPRINTK( "AFMT_U16_LE\n" );
++              break;
++      case SNDRV_PCM_FORMAT_U16_BE:
++              DPRINTK( "AFMT_U16_BE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_S24_LE:
++              DPRINTK( "AFMT_S24_LE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_S24_BE:
++              DPRINTK( "AFMT_S24_BE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_U24_LE:
++              DPRINTK( "AFMT_U24_LE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_U24_BE:
++              DPRINTK( "AFMT_U24_BE\n" );
++              break;
++      case SNDRV_PCM_FORMAT_S32_LE:
++              DPRINTK( "AFMT_S24_LE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_S32_BE:
++              DPRINTK( "AFMT_S24_BE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_U32_LE:
++              DPRINTK( "AFMT_U24_LE\n" );
++              break;
++
++      case SNDRV_PCM_FORMAT_U32_BE:
++              DPRINTK( "AFMT_U24_BE\n" );
++              break;
++      default:
++              DPRINTK( "ep93xx_i2s_Unsupported Audio Format\n" );
++              break;
++    }
++}
++
++static void audio_set_format( audio_stream_t * s, long val )
++{
++    DPRINTK( "ep93xx_i2s_audio_set_format enter.  Format requested (%d) %d ",
++                              (int)val,SNDRV_PCM_FORMAT_S16_LE);
++    print_audio_format( val );
++
++    switch( val ){
++      case SNDRV_PCM_FORMAT_S8:
++              s->audio_format = SNDRV_PCM_FORMAT_S8;
++              s->audio_stream_bitwidth = 8;
++              break;
++
++      case SNDRV_PCM_FORMAT_U8:
++              s->audio_format = SNDRV_PCM_FORMAT_U8;
++              s->audio_stream_bitwidth = 8;
++              break;
++
++      case SNDRV_PCM_FORMAT_S16_LE:
++      case SNDRV_PCM_FORMAT_S16_BE:
++              s->audio_format = SNDRV_PCM_FORMAT_S16_LE;
++              s->audio_stream_bitwidth = 16;
++              break;
++
++      case SNDRV_PCM_FORMAT_U16_LE:
++      case SNDRV_PCM_FORMAT_U16_BE:
++              s->audio_format = SNDRV_PCM_FORMAT_U16_LE;
++              s->audio_stream_bitwidth = 16;
++              break;
++
++      case SNDRV_PCM_FORMAT_S24_LE:
++      case SNDRV_PCM_FORMAT_S24_BE:
++              s->audio_format = SNDRV_PCM_FORMAT_S24_LE;
++              s->audio_stream_bitwidth = 24;
++              break;
++
++      case SNDRV_PCM_FORMAT_U24_LE:
++      case SNDRV_PCM_FORMAT_U24_BE:
++              s->audio_format = SNDRV_PCM_FORMAT_U24_LE;
++              s->audio_stream_bitwidth = 24;
++              break;
++
++      case SNDRV_PCM_FORMAT_U32_LE:
++      case SNDRV_PCM_FORMAT_U32_BE:
++      case SNDRV_PCM_FORMAT_S32_LE:
++      case SNDRV_PCM_FORMAT_S32_BE:
++              s->audio_format = SNDRV_PCM_FORMAT_S32_LE;
++              s->audio_stream_bitwidth = 32;
++              break;
++      default:
++              DPRINTK( "ep93xx_i2s_Unsupported Audio Format\n" );
++              break;
++    }
++
++    DPRINTK( "ep93xx_i2s_audio_set_format EXIT format set to be (%d) ", (int)s->audio_format );
++    print_audio_format( (long)s->audio_format );
++}
++
++static __inline__ unsigned long copy_to_user_S24_LE
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++
++    int total_to_count = to_count;
++    int *user_ptr = (int *)to;        /* 32 bit user buffer */
++    int count;
++
++    count = 8 * stream->dma_num_channels;
++
++    while (to_count > 0){
++
++      __put_user( (int)( *dma_buffer_0++ ), user_ptr++ );
++      __put_user( (int)( *dma_buffer_0++ ), user_ptr++ );
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( (int)( *dma_buffer_1++ ), user_ptr++ );
++          __put_user( (int)( *dma_buffer_1++ ), user_ptr++ );
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __put_user( (int)( *dma_buffer_2++ ), user_ptr++ );
++          __put_user( (int)( *dma_buffer_2++ ), user_ptr++ );
++      }
++      to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U24_LE
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++
++    int total_to_count = to_count;
++    unsigned int * user_ptr = (unsigned int *)to;     /* 32 bit user buffer */
++    int count;
++
++    count = 8 * stream->dma_num_channels;
++
++    while (to_count > 0){
++      __put_user( ((unsigned int)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
++      __put_user( ((unsigned int)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( ((unsigned int)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
++          __put_user( ((unsigned int)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __put_user( ((unsigned int)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
++          __put_user( ((unsigned int)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
++      }
++      to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S16_LE
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    int total_to_count = to_count;
++    short * user_ptr = (short *)to;   /* 16 bit user buffer */
++    int count;
++
++    count = 4 * stream->dma_num_channels;
++
++    while (to_count > 0){
++
++      __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
++      __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
++
++        if( stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( (short)( *dma_buffer_1++ ), user_ptr++ );
++          __put_user( (short)( *dma_buffer_1++ ), user_ptr++ );
++      }
++
++        if( stream->audio_channels_flag  & CHANNEL_CENTER_LFE ){
++          __put_user( (short)( *dma_buffer_2++ ), user_ptr++ );
++          __put_user( (short)( *dma_buffer_2++ ), user_ptr++ );
++      }
++      to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U16_LE
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    int count;
++    int total_to_count = to_count;
++    short * user_ptr = (short *)to;   /* 16 bit user buffer */
++
++    count = 4 * stream->dma_num_channels;
++
++    while (to_count > 0){
++
++      __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
++      __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
++          __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
++          __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
++      }
++      to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S8
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    char *dma_buffer_0 = (char *)stream->hwbuf[0];
++    char *dma_buffer_1 = (char *)stream->hwbuf[1];
++    char *dma_buffer_2 = (char *)stream->hwbuf[2];
++    int count;
++    int total_to_count = to_count;
++    char * user_ptr = (char *)to;  /*  8 bit user buffer */
++
++    count = 2 * stream->dma_num_channels;
++
++    dma_buffer_0++;
++    dma_buffer_1++;
++    dma_buffer_2++;
++
++    while (to_count > 0){
++
++      __put_user( (char)( *dma_buffer_0 ), user_ptr++ );
++      dma_buffer_0 += 4;
++      __put_user( (char)( *dma_buffer_0 ), user_ptr++ );
++      dma_buffer_0 += 4;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( (char)( *dma_buffer_1 ), user_ptr++ );
++            dma_buffer_1 += 4;
++          __put_user( (char)( *dma_buffer_1 ), user_ptr++ );
++          dma_buffer_1 += 4;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __put_user( (char)( *dma_buffer_2 ), user_ptr++ );
++          dma_buffer_2 += 4;
++          __put_user( (char)( *dma_buffer_2 ), user_ptr++ );
++          dma_buffer_2 += 4;
++      }
++      to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U8
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    char *dma_buffer_0 = (char *)stream->hwbuf[0];
++    char *dma_buffer_1 = (char *)stream->hwbuf[1];
++    char *dma_buffer_2 = (char *)stream->hwbuf[2];
++    int count;
++    int total_to_count = to_count;
++    char * user_ptr = (char *)to;  /*  8 bit user buffer */
++
++    count = 2 * stream->dma_num_channels;
++
++    dma_buffer_0++;
++    dma_buffer_1++;
++    dma_buffer_2++;
++
++    while (to_count > 0){
++
++      __put_user( (char)( *dma_buffer_0 ) ^ 0x80, user_ptr++ );
++      dma_buffer_0 += 4;
++      __put_user( (char)( *dma_buffer_0 ) ^ 0x80, user_ptr++ );
++      dma_buffer_0 += 4;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ );
++          dma_buffer_1 += 4;
++          __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ );
++          dma_buffer_1 += 4;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ );
++          dma_buffer_2 += 4;
++          __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ );
++          dma_buffer_2 += 4;
++      }
++      to_count -= count;
++    }
++    return total_to_count;
++}
++
++
++
++
++static __inline__ unsigned long copy_to_user_S16_LE_CM
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    short *dma_buffer_0 = (short *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    int total_to_count = to_count;
++    short * user_ptr = (short *)to;   /* 16 bit user buffer */
++    int count;
++
++
++    count = 4 * stream->dma_num_channels;
++
++    while (to_count > 0){
++      if(stream->audio_num_channels == 2){
++              __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
++              __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
++              to_count -= count;
++      }
++      else{
++              dma_buffer_0++;
++              __put_user( (short)( *dma_buffer_0++ ), user_ptr++ );
++              to_count -= 2;
++      }
++
++        if( stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( (short)( *dma_buffer_1++ ), user_ptr++ );
++          __put_user( (short)( *dma_buffer_1++ ), user_ptr++ );
++      }
++
++        if( stream->audio_channels_flag  & CHANNEL_CENTER_LFE ){
++          __put_user( (short)( *dma_buffer_2++ ), user_ptr++ );
++          __put_user( (short)( *dma_buffer_2++ ), user_ptr++ );
++      }
++      //to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U16_LE_CM
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    int count;
++    int total_to_count = to_count;
++    unsigned short * user_ptr = (unsigned short *)to; /* 16 bit user buffer */
++
++    count = 4 * stream->dma_num_channels;
++
++    while (to_count > 0){
++
++      if(stream->audio_num_channels == 2){
++              __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
++              __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
++              to_count -= count;
++      }
++      else{
++              dma_buffer_0++;
++              __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ );
++              to_count -= 2;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
++          __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ );
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
++          __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ );
++      }
++      //to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S8_CM
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0];
++    char *dma_buffer_1 = (char *)stream->hwbuf[1];
++    char *dma_buffer_2 = (char *)stream->hwbuf[2];
++    int count;
++    int total_to_count = to_count;
++    char * user_ptr = (char *)to;  /*  8 bit user buffer */
++
++    count = 2 * stream->dma_num_channels;
++
++    dma_buffer_0++;
++    dma_buffer_1++;
++    dma_buffer_2++;
++
++    while (to_count > 0){
++      if(stream->audio_num_channels == 2){
++              __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ );
++              //dma_buffer_0 += 4;
++              __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ );
++              //dma_buffer_0 += 4;
++              to_count -= count;
++      }
++      else{
++              dma_buffer_0++ ;
++              __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ );
++
++              to_count -= 1;
++      }
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( (char)( *dma_buffer_1 ), user_ptr++ );
++            dma_buffer_1 += 4;
++          __put_user( (char)( *dma_buffer_1 ), user_ptr++ );
++          dma_buffer_1 += 4;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __put_user( (char)( *dma_buffer_2 ), user_ptr++ );
++          dma_buffer_2 += 4;
++          __put_user( (char)( *dma_buffer_2 ), user_ptr++ );
++          dma_buffer_2 += 4;
++      }
++      //to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U8_CM
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0];
++    char *dma_buffer_1 = (char *)stream->hwbuf[1];
++    char *dma_buffer_2 = (char *)stream->hwbuf[2];
++    int count;
++    int total_to_count = to_count;
++    char * user_ptr = (char *)to;  /*  8 bit user buffer */
++
++    count = 2 * stream->dma_num_channels;
++
++    dma_buffer_0++;
++    dma_buffer_1++;
++    dma_buffer_2++;
++
++    while (to_count > 0){
++      if(stream->audio_num_channels == 2){
++              __put_user( (char)( *dma_buffer_0++  >>8) ^ 0x80, user_ptr++ );
++              //dma_buffer_0 += 4;
++              __put_user( (char)( *dma_buffer_0++  >>8) ^ 0x80, user_ptr++ );
++              //dma_buffer_0 += 4;
++              to_count -= count;
++      }
++      else{
++              dma_buffer_0++;
++              __put_user( (char)( *dma_buffer_0++  >>8) ^ 0x80, user_ptr++ );
++              //dma_buffer_0 += 4;
++              to_count--;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ );
++          dma_buffer_1 += 4;
++          __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ );
++          dma_buffer_1 += 4;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ );
++          dma_buffer_2 += 4;
++          __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ );
++          dma_buffer_2 += 4;
++      }
++      //to_count -= count;
++    }
++    return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U32
++(
++    audio_stream_t *stream,
++    const char *to,
++    unsigned long to_count
++)
++{
++    char *dma_buffer_0 = (char *)stream->hwbuf[0];
++
++    if(__copy_to_user( (char *)to, dma_buffer_0, to_count))
++    {
++      return -EFAULT;
++    }
++    return to_count;
++}
++
++static __inline__ int copy_to_user_with_conversion
++(
++    audio_stream_t *stream,
++    const char *to,
++    int toCount,
++    int bCompactMode
++)
++{
++    int ret = 0;
++
++    if( toCount == 0 ){
++      DPRINTK("ep93xx_i2s_copy_to_user_with_conversion - nothing to copy!\n");
++    }
++
++    if( bCompactMode == 1 ){
++
++        switch( stream->audio_format ){
++
++      case SNDRV_PCM_FORMAT_S8:
++              ret = copy_to_user_S8_CM( stream, to, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_U8:
++              ret = copy_to_user_U8_CM( stream, to, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_S16_LE:
++              ret = copy_to_user_S16_LE_CM( stream, to, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_U16_LE:
++              ret = copy_to_user_U16_LE_CM( stream, to, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_S24_LE:
++              //ret = copy_to_user_S24_LE( stream, to, toCount );
++              //break;
++
++      case SNDRV_PCM_FORMAT_U24_LE:
++              //ret = copy_to_user_U24_LE( stream, to, toCount );
++              //break;
++
++      case SNDRV_PCM_FORMAT_S32_LE:
++        default:
++                DPRINTK( "ep93xx_i2s copy to user unsupported audio format %x\n",stream->audio_format );
++              break;
++        }
++
++    }
++    else{
++
++        switch( stream->audio_format ){
++
++      case SNDRV_PCM_FORMAT_S8:
++              ret = copy_to_user_S8( stream, to, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_U8:
++              ret = copy_to_user_U8( stream, to, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_S16_LE:
++              ret = copy_to_user_S16_LE( stream, to, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_U16_LE:
++              ret = copy_to_user_U16_LE( stream, to, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_S24_LE:
++              //ret = copy_to_user_S24_LE( stream, to, toCount );
++              //break;
++
++      case SNDRV_PCM_FORMAT_U24_LE:
++              //ret = copy_to_user_U24_LE( stream, to, toCount );
++              //break;
++              DPRINTK( "ep93xx_i2s copy to user unsupported audio format %x\n",stream->audio_format );
++              break;
++
++      case SNDRV_PCM_FORMAT_S32_LE:
++
++              //__copy_to_user( (char *)to, from, toCount);
++              ret = copy_to_user_U32( stream, to, toCount );
++              break;
++        default:
++                DPRINTK( "ep93xx_i2s copy to user unsupported audio format\n" );
++              break;
++        }
++
++    }
++    return ret;
++}
++
++static __inline__ int copy_from_user_S24_LE
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    int count;
++
++    unsigned int * user_buffer = (unsigned int *)from;
++    unsigned int data;
++
++    int toCount0 = toCount;
++    count = 8 * stream->dma_num_channels;
++
++    while (toCount > 0){
++
++      __get_user(data, user_buffer++);
++      *dma_buffer_0++ = (unsigned int)data;
++      __get_user(data, user_buffer++);
++      *dma_buffer_0++ = (unsigned int)data;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_1++ = (unsigned int)data;
++          __get_user(data, user_buffer++);
++          *dma_buffer_1++ = (unsigned int)data;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = (unsigned int)data;
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = (unsigned int)data;
++        }
++      toCount -= count;
++    }
++    return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_U24_LE
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    int count;
++    unsigned int * user_buffer = (unsigned int *)from;
++    unsigned int data;
++
++    int toCount0 = toCount;
++    count = 8 * stream->dma_num_channels;
++
++    while (toCount > 0){
++
++      __get_user(data, user_buffer++);
++      *dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
++      __get_user(data, user_buffer++);
++      *dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
++          __get_user(data, user_buffer++);
++          *dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
++      }
++      toCount -= count;
++    }
++    return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_S16_LE
++(
++      audio_stream_t *stream,
++      const char *from,
++      int toCount
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    unsigned short *user_buffer = (unsigned short *)from;
++    unsigned short data;
++
++    int toCount0 = toCount;
++    int count;
++    count = 8 * stream->dma_num_channels;
++
++    while (toCount > 0){
++
++      __get_user(data, user_buffer++);
++      *dma_buffer_0++ = data;
++      if(stream->audio_num_channels == 2){
++          __get_user(data, user_buffer++);
++      }
++      *dma_buffer_0++ = data;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_1++ = data;
++          __get_user(data, user_buffer++);
++          *dma_buffer_1++ = data;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = data;
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = data;
++      }
++      toCount -= count;
++    }
++
++    if(stream->audio_num_channels == 1){
++      return toCount0 / 4;
++    }
++    return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_U16_LE
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    int count;
++    unsigned short * user_buffer = (unsigned short *)from;
++    unsigned short data;
++
++    int toCount0 = toCount;
++    count = 8 * stream->dma_num_channels;
++
++    while (toCount > 0){
++
++      __get_user(data, user_buffer++);
++      *dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
++      if(stream->audio_num_channels == 2){
++          __get_user(data, user_buffer++);
++      }
++      *dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
++          __get_user(data, user_buffer++);
++            *dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
++      }
++      toCount -= count;
++    }
++
++    if(stream->audio_num_channels == 1){
++        return toCount0 / 4;
++    }
++    return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_S8
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount
++)
++{
++    char *dma_buffer_0 = (char *)stream->hwbuf[0];
++    char *dma_buffer_1 = (char *)stream->hwbuf[1];
++    char *dma_buffer_2 = (char *)stream->hwbuf[2];
++    int count;
++    unsigned char * user_buffer = (unsigned char *)from;
++    unsigned char data;
++
++    int toCount0 = toCount;
++    count = 8 * stream->dma_num_channels;
++
++    dma_buffer_0++;
++    dma_buffer_1++;
++    dma_buffer_2++;
++
++    while (toCount > 0){
++      __get_user(data, user_buffer++);
++      *dma_buffer_0 = data;
++      dma_buffer_0 += 4;
++      if(stream->audio_num_channels == 2){
++          __get_user(data, user_buffer++);
++      }
++      *dma_buffer_0 = data;
++      dma_buffer_0 += 4;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_1 = data;
++            dma_buffer_1 += 4;
++          __get_user(data, user_buffer++);
++            *dma_buffer_1 = data;
++          dma_buffer_1 += 4;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_2 = data;
++          dma_buffer_2 += 4;
++          __get_user(data, user_buffer++);
++          *dma_buffer_2 = data;
++            dma_buffer_2 += 4;
++      }
++      toCount -= count;
++    }
++
++    if(stream->audio_num_channels == 1){
++      return toCount0 / 8;
++    }
++    return toCount0 / 4;
++}
++
++static __inline__ int copy_from_user_U8
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount
++)
++{
++    char *dma_buffer_0 = (char *)stream->hwbuf[0];
++    char *dma_buffer_1 = (char *)stream->hwbuf[1];
++    char *dma_buffer_2 = (char *)stream->hwbuf[2];
++    int count;
++    unsigned char *user_buffer = (unsigned char *)from;
++    unsigned char data;
++
++    int toCount0 = toCount;
++    count = 8 * stream->dma_num_channels;
++
++    dma_buffer_0 ++;
++    dma_buffer_1 ++;
++    dma_buffer_2 ++;
++
++    while (toCount > 0){
++
++      __get_user(data, user_buffer++);
++      *dma_buffer_0 = ((unsigned char)data ^ 0x80);
++      dma_buffer_0 += 4;
++      if(stream->audio_num_channels == 2){
++          __get_user(data, user_buffer++);
++      }
++      *dma_buffer_0 = ((unsigned char)data ^ 0x80);
++      dma_buffer_0 += 4;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_1 = ((unsigned char)data ^ 0x80);
++            dma_buffer_1 += 4;
++          __get_user(data, user_buffer++);
++            *dma_buffer_1 = ((unsigned char)data ^ 0x80);
++            dma_buffer_1 += 4;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_2 = ((unsigned char)data ^ 0x80);
++          dma_buffer_2 += 4;
++          __get_user(data, user_buffer++);
++          *dma_buffer_2 = ((unsigned char)data ^ 0x80);
++            dma_buffer_2 += 4;
++      }
++      toCount -= count;
++    }
++
++    if(stream->audio_num_channels == 1){
++      return toCount0 / 8;
++    }
++    return toCount0 / 4;
++}
++
++static __inline__ int copy_from_user_S16_LE_CM
++(
++      audio_stream_t *stream,
++      const char *from,
++      int toCount
++)
++{
++    unsigned int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    unsigned int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    unsigned int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    unsigned short *user_buffer = (unsigned short *)from;
++    short data;
++    unsigned int val;
++    int toCount0 = toCount;
++    int count;
++    count = 4 * stream->dma_num_channels;
++
++      //printk("count=%x tocount\n",count,toCount);
++    while (toCount > 0){
++
++      __get_user(data, user_buffer++);
++      //*dma_buffer_0++ = data;
++      val = (unsigned int)data & 0x0000ffff;
++      if(stream->audio_num_channels == 2){
++          __get_user(data, user_buffer++);
++        }
++      *dma_buffer_0++ = ((unsigned int)data << 16) | val;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          //*dma_buffer_1++ = data;
++          val = (unsigned int)data & 0x0000ffff;
++          __get_user(data, user_buffer++);
++          *dma_buffer_1++ = ((unsigned int)data << 16) | val;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          //*dma_buffer_2++ = data;
++          val = (unsigned int)data & 0x0000ffff;
++          __get_user(data, user_buffer++);
++          *dma_buffer_2++ = ((unsigned int)data << 16) | val;
++      }
++      toCount -= count;
++    }
++
++    if(stream->audio_num_channels == 1){
++        return toCount0 /2 ;
++    }
++
++    return toCount0 ;
++}
++
++static __inline__ int copy_from_user_U16_LE_CM
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount
++)
++{
++    int *dma_buffer_0 = (int *)stream->hwbuf[0];
++    int *dma_buffer_1 = (int *)stream->hwbuf[1];
++    int *dma_buffer_2 = (int *)stream->hwbuf[2];
++    int count;
++    unsigned short * user_buffer = (unsigned short *)from;
++    unsigned short data;
++    unsigned int val;
++    int toCount0 = toCount;
++    count = 4 * stream->dma_num_channels;
++
++    while (toCount > 0){
++
++      __get_user(data, user_buffer++);
++      //*dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
++      val = (unsigned int)data & 0x0000ffff;
++      if(stream->audio_num_channels == 2){
++          __get_user(data, user_buffer++);
++        }
++      //*dma_buffer_0++ = ((unsigned int)data ^ 0x8000);
++        *dma_buffer_0++ = (((unsigned int)data << 16) | val) ^ 0x80008000;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          //*dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
++          val = (unsigned int)data & 0x0000ffff;
++          __get_user(data, user_buffer++);
++            //*dma_buffer_1++ = ((unsigned int)data ^ 0x8000);
++            *dma_buffer_1++ = (((unsigned int)data << 16) | val) ^ 0x80008000;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          //*dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
++          val = (unsigned int)data & 0x0000ffff;
++          __get_user(data, user_buffer++);
++          //*dma_buffer_2++ = ((unsigned int)data ^ 0x8000);
++          *dma_buffer_2++ = (((unsigned int)data << 16) | val) ^ 0x80008000;
++      }
++      toCount -= count;
++    }
++
++    if(stream->audio_num_channels == 1){
++        return toCount0/2;
++    }
++    return toCount0 ;
++}
++
++static __inline__ int copy_from_user_S8_CM
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount
++)
++{
++    char *dma_buffer_0 = (char *)stream->hwbuf[0];
++    char *dma_buffer_1 = (char *)stream->hwbuf[1];
++    char *dma_buffer_2 = (char *)stream->hwbuf[2];
++    int count;
++    unsigned char * user_buffer = (unsigned char *)from;
++    unsigned char data;
++    int toCount0 = toCount;
++    count = 4 * stream->dma_num_channels;
++
++    dma_buffer_0++;
++    dma_buffer_1++;
++    dma_buffer_2++;
++
++    while (toCount > 0){
++      __get_user(data, user_buffer++);
++      *dma_buffer_0 = data;
++      *(dma_buffer_0 +1 ) = 0;
++      dma_buffer_0 += 2;
++
++      if(stream->audio_num_channels == 2){
++          __get_user(data, user_buffer++);
++      }
++      *dma_buffer_0 = data;
++      *(dma_buffer_0 +1 ) = 0;
++      dma_buffer_0 += 2;
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_1 = data;
++          dma_buffer_1 += 2;
++          __get_user(data, user_buffer++);
++            *dma_buffer_1 = data;
++            dma_buffer_1 += 2;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_2 = data;
++          dma_buffer_2 += 2;
++          __get_user(data, user_buffer++);
++          *dma_buffer_2 = data;
++          dma_buffer_2 += 2;
++      }
++      toCount -= count;
++    }
++
++    if(stream->audio_num_channels == 1){
++        return toCount0 / 4;
++    }
++
++    return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_U8_CM
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount
++)
++{
++    unsigned char *dma_buffer_0 = (unsigned char *)stream->hwbuf[0];
++    unsigned char *dma_buffer_1 = (unsigned char *)stream->hwbuf[1];
++    unsigned char *dma_buffer_2 = (unsigned char *)stream->hwbuf[2];
++    int count;
++    unsigned char *user_buffer = (unsigned char *)from;
++    unsigned char data;
++
++    int toCount0 = toCount;
++    count = 4 * stream->dma_num_channels;
++
++    dma_buffer_0 ++;
++    dma_buffer_1 ++;
++    dma_buffer_2 ++;
++
++    while (toCount > 0){
++
++      __get_user(data, user_buffer++);
++      *dma_buffer_0 = ((unsigned char)data ^ 0x80);
++      *(dma_buffer_0 +1 ) = 0;
++      dma_buffer_0 += 2;
++
++      if(stream->audio_num_channels == 2){
++          __get_user(data, user_buffer++);
++      }
++      *dma_buffer_0 = ((unsigned char)data ^ 0x80);
++      *(dma_buffer_0 +1 ) = 0;
++      dma_buffer_0 += 2;
++
++
++        if(stream->audio_channels_flag & CHANNEL_REAR ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_1 = ((unsigned char)data ^ 0x80);
++          dma_buffer_1 += 2;
++          __get_user(data, user_buffer++);
++            *dma_buffer_1 = ((unsigned char)data ^ 0x80);
++            dma_buffer_1 += 2;
++      }
++
++        if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){
++          __get_user(data, user_buffer++);
++          *dma_buffer_2 = ((unsigned char)data ^ 0x80);
++          dma_buffer_2 += 2;
++          __get_user(data, user_buffer++);
++          *dma_buffer_2 = ((unsigned char)data ^ 0x80);
++            dma_buffer_2 += 2;
++      }
++      toCount -= count;
++    }
++
++    if(stream->audio_num_channels == 1){
++        return toCount0 / 4;
++    }
++
++    return toCount0 / 2;
++}
++
++static int copy_from_user_U32
++(
++      audio_stream_t *stream,
++      const char *from,
++      int toCount
++)
++{
++    char *dma_buffer_0 = (char *)stream->hwbuf[0];
++
++    if (copy_from_user( (char *)dma_buffer_0, from, toCount))
++    {
++      return -EFAULT;
++    }
++
++    return toCount;
++
++}
++
++/*
++ * Returns negative for error
++ * Returns # of bytes transferred out of the from buffer
++ * for success.
++ */
++static __inline__ int copy_from_user_with_conversion
++(
++    audio_stream_t *stream,
++    const char *from,
++    int toCount,
++    int bCompactMode
++)
++{
++    int ret = 0;
++//    DPRINTK("copy_from_user_with_conversion\n");
++    if( toCount == 0 ){
++      DPRINTK("ep93xx_i2s_copy_from_user_with_conversion - nothing to copy!\n");
++    }
++
++    if( bCompactMode == 1){
++
++      switch( stream->audio_format ){
++
++              case SNDRV_PCM_FORMAT_S8:
++                      DPRINTK("SNDRV_PCM_FORMAT_S8 CM\n");
++                      ret = copy_from_user_S8_CM( stream, from, toCount );
++                      break;
++
++              case SNDRV_PCM_FORMAT_U8:
++                      DPRINTK("SNDRV_PCM_FORMAT_U8 CM\n");
++                      ret = copy_from_user_U8_CM( stream, from, toCount );
++                      break;
++
++              case SNDRV_PCM_FORMAT_S16_LE:
++                      DPRINTK("SNDRV_PCM_FORMAT_S16_LE CM\n");
++                      ret = copy_from_user_S16_LE_CM( stream, from, toCount );
++                      break;
++
++              case SNDRV_PCM_FORMAT_U16_LE:
++                      DPRINTK("SNDRV_PCM_FORMAT_U16_LE CM\n");
++                      ret = copy_from_user_U16_LE_CM( stream, from, toCount );
++                      break;
++
++              case SNDRV_PCM_FORMAT_S24_LE:
++                      DPRINTK("SNDRV_PCM_FORMAT_S24_LE CM\n");
++                      //ret = copy_from_user_S24_LE( stream, from, toCount );
++                      //break;
++
++              case SNDRV_PCM_FORMAT_U24_LE:
++                      DPRINTK("SNDRV_PCM_FORMAT_U24_LE CM\n");
++                      //ret = copy_from_user_U24_LE( stream, from, toCount );
++                      //break;
++              case SNDRV_PCM_FORMAT_S32_LE:
++                      DPRINTK("SNDRV_PCM_FORMAT_S32_LE CM\n");
++                      //break;
++              default:
++                      DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" );
++                      break;
++      }
++    }
++    else{
++        switch( stream->audio_format ){
++
++      case SNDRV_PCM_FORMAT_S8:
++              DPRINTK("SNDRV_PCM_FORMAT_S8\n");
++              ret = copy_from_user_S8( stream, from, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_U8:
++              DPRINTK("SNDRV_PCM_FORMAT_U8\n");
++              ret = copy_from_user_U8( stream, from, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_S16_LE:
++              DPRINTK("SNDRV_PCM_FORMAT_S16_LE\n");
++              ret = copy_from_user_S16_LE( stream, from, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_U16_LE:
++              DPRINTK("SNDRV_PCM_FORMAT_U16_LE\n");
++              ret = copy_from_user_U16_LE( stream, from, toCount );
++              break;
++
++      case SNDRV_PCM_FORMAT_S24_LE:
++              DPRINTK("SNDRV_PCM_FORMAT_S24_LE\n");
++              //ret = copy_from_user_S24_LE( stream, from, toCount );
++              //break;
++
++      case SNDRV_PCM_FORMAT_U24_LE:
++              DPRINTK("SNDRV_PCM_FORMAT_U24_LE\n");
++              //ret = copy_from_user_U24_LE( stream, from, toCount );
++              //break;
++              DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" );
++              break;
++      case SNDRV_PCM_FORMAT_S32_LE:
++              DPRINTK("SNDRV_PCM_FORMAT_S32_LE\n");
++              ret = copy_from_user_U32( stream, from, toCount );
++              break;
++        default:
++                DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" );
++              break;
++      }
++    }
++
++    return ret;
++}
++
++
++
++/*
++ *  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:
++ *
++ *  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      stereo         2             4      8            2:1   4:1
++ *   16     stereo         4             4      8            1:1   2:1
++ *   24     stereo         6             4      8             X    8:6 not a real case
++ *
++ */
++static void snd_ep93xx_dma2usr_ratio( audio_stream_t * stream,int bCompactMode )
++{
++    unsigned int dma_sample_size, user_sample_size;
++
++    if(bCompactMode == 1){
++      dma_sample_size = 4;    /* each stereo sample is 2 * 32 bits */
++    }
++    else{
++      dma_sample_size = 8;
++    }
++
++    // If stereo 16 bit, user sample is 4 bytes.
++    // If stereo  8 bit, user sample is 2 bytes.
++    if(stream->audio_num_channels == 1){
++      user_sample_size = stream->audio_stream_bitwidth / 8;
++    }
++    else{
++      user_sample_size = stream->audio_stream_bitwidth / 4;
++    }
++
++    stream->dma2usr_ratio = dma_sample_size / user_sample_size;
++}
++
++/*---------------------------------------------------------------------------------------------*/
++
++static int snd_ep93xx_dma_free(struct snd_pcm_substream *substream ){
++
++
++    audio_state_t *state = substream->private_data;
++    audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++                              state->output_stream:state->input_stream;
++    int i;
++
++
++    DPRINTK("snd_ep93xx_dma_free - enter\n");
++    for( i = 0 ; i < stream->dma_num_channels ;i++ ){
++      ep93xx_dma_free( stream->dmahandles[i] );
++    }
++    DPRINTK("snd_ep93xx_dma_free - exit\n");
++    return 0;
++}
++
++static int snd_ep93xx_dma_config(struct snd_pcm_substream *substream ){
++
++    audio_state_t *state = substream->private_data;
++    audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++                               state->output_stream:state->input_stream;
++    int i,err = 0;
++
++    DPRINTK("snd_ep93xx_dma_config - enter\n");
++
++    for( i = 0 ; i < stream->dma_num_channels ;i++ ){
++
++        err = ep93xx_dma_request(&stream->dmahandles[i],
++                              stream->devicename,
++                              (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++                              state->output_dma[i]:state->input_dma[i] );
++        if (err){
++          printk("snd_ep93xx_dma_config - exit ERROR dma request failed\n");
++          return err;
++        }
++      err = ep93xx_dma_config( stream->dmahandles[i],
++                              IGNORE_CHANNEL_ERROR,
++                              0,
++                              (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++                              snd_ep93xx_dma_tx_callback:snd_ep93xx_dma_rx_callback,
++                              (unsigned int)substream );
++        if (err){
++          printk("snd_ep93xx_dma_config - exit ERROR dma request failed\n");
++          return err;
++      }
++    }
++
++    DPRINTK("snd_ep93xx_dma_config - enter\n");
++    return err;
++}
++
++static void snd_ep93xx_dma_start( audio_state_t * state, audio_stream_t * stream )
++{
++    int err,i;
++
++    DPRINTK("snd_ep93xx_dma_start - enter\n");
++
++    for(i = 0 ;i < stream->dma_num_channels;i++)
++      err = ep93xx_dma_start( stream->dmahandles[i], 1,(unsigned int *) stream->dmahandles );
++
++    stream->active = 1;
++
++    DPRINTK("snd_ep93xx_dma_start - exit\n");
++}
++
++static void snd_ep93xx_dma_pause( audio_state_t * state, audio_stream_t * stream )
++{
++    int i;
++
++    DPRINTK("snd_ep93xx_dma_pause - enter\n");
++
++    for(i = 0 ;i < stream->dma_num_channels;i++)
++      ep93xx_dma_pause( stream->dmahandles[i], 1,(unsigned int *)stream->dmahandles );
++
++    stream->active = 0;
++    DPRINTK("snd_ep93xx_dma_pause - exit\n");
++
++}
++
++static void snd_ep93xx_dma_flush( audio_state_t * state, audio_stream_t * stream ){
++
++    int i;
++
++    DPRINTK("snd_ep93xx_dma_flush - enter\n");
++
++    for( i = 0 ; i < stream->dma_num_channels ; i++ )
++      ep93xx_dma_flush( stream->dmahandles[i] );
++
++    DPRINTK("snd_ep93xx_dma_flush - exit\n");
++}
++
++static void snd_ep93xx_deallocate_buffers( struct snd_pcm_substream *substream, audio_stream_t *stream )
++{
++    int i;
++    audio_channel_t *dma_chan;
++
++    DPRINTK("snd_ep93xx_deallocate_buffers - enter\n");
++
++    if( stream->dma_channels ){
++
++        for(i = 0;i < stream->dma_num_channels;i++){
++
++          dma_chan = &stream->dma_channels[i];
++
++          if( dma_chan->area ){
++
++              if( dma_chan->audio_buffers ){
++
++                  kfree(dma_chan->audio_buffers);
++                  dma_chan->audio_buffers = NULL;
++
++              }
++
++              kfree(dma_chan->area);
++              dma_chan->area = NULL;
++          }
++      }
++      kfree(stream->dma_channels);
++      stream->dma_channels = NULL;
++    }
++    DPRINTK("snd_ep93xx_deallocate_buffers - exit\n");
++}
++
++static int snd_ep93xx_allocate_buffers(struct snd_pcm_substream *substream, audio_stream_t *stream)
++{
++    audio_channel_t *channel;
++    unsigned int size,tmpsize,bufsize,bufextsize;
++    int i,j;
++
++
++    DPRINTK("snd_ep93xx_allocate_buffers - enter\n" );
++
++    if (stream->dma_channels){
++      printk("ep93xx_i2s  %s BUSY\n",__FUNCTION__);
++        return -EBUSY;
++    }
++
++    stream->dma_channels = (audio_channel_t *)kmalloc(sizeof(audio_channel_t) * stream->dma_num_channels , GFP_KERNEL);
++
++    if (!stream->dma_channels){
++      printk(AUDIO_NAME ": unable to allocate dma_channels memory\n");
++      return - ENOMEM;
++    }
++
++    size = ( stream->dmasize / stream->dma_num_channels ) * stream->dma2usr_ratio;
++
++    for( i = 0; i < stream->dma_num_channels;i++){
++      channel = &stream->dma_channels[i];
++
++      channel->area = kmalloc( size, GFP_DMA );
++
++      if(!channel->area){
++          printk(AUDIO_NAME ": unable to allocate audio memory\n");
++          return -ENOMEM;
++      }
++      channel->bytes = size;
++      channel->addr = __virt_to_phys((int) channel->area);
++        memset( channel->area, 0, channel->bytes );
++
++      bufsize = ( stream->fragsize / stream->dma_num_channels ) * stream->dma2usr_ratio;
++      channel->audio_buff_count = size / bufsize;
++      bufextsize = size % bufsize;
++
++      if( bufextsize > 0 ){
++          channel->audio_buff_count++;
++      }
++
++      channel->audio_buffers = (audio_buf_t *)kmalloc(sizeof(audio_buf_t) * channel->audio_buff_count , GFP_KERNEL);
++
++      if (!channel->audio_buffers){
++          printk(AUDIO_NAME ": unable to allocate audio memory\n ");
++          return -ENOMEM;
++      }
++
++      tmpsize = size;
++
++      for( j = 0; j < channel->audio_buff_count; j++){
++
++          channel->audio_buffers[j].dma_addr = channel->addr + j * bufsize;
++
++          if( tmpsize >= bufsize ){
++              tmpsize -= bufsize;
++              channel->audio_buffers[j].bytes = bufsize;
++              channel->audio_buffers[j].reportedbytes = bufsize / stream->dma2usr_ratio;
++          }
++          else{
++                channel->audio_buffers[j].bytes = bufextsize;
++                channel->audio_buffers[j].reportedbytes = bufextsize / stream->dma2usr_ratio;
++          }
++      }
++    }
++
++    DPRINTK("snd_ep93xx_allocate_buffers -- exit SUCCESS\n" );
++    return 0;
++}
++
++/*
++ * DMA callback functions
++ */
++
++static void snd_ep93xx_dma_tx_callback
++(
++      ep93xx_dma_int_t DMAInt,
++      ep93xx_dma_dev_t device,
++      unsigned int user_data
++)
++{
++    int handle;
++    int i,chan;
++    unsigned int buf_id;
++
++    struct snd_pcm_substream *substream = (struct snd_pcm_substream *)user_data;
++    audio_state_t *state = (audio_state_t *)(substream->private_data);
++    audio_stream_t *stream = state->output_stream;
++    audio_buf_t *buf;
++
++    switch( device )
++    {
++      case DMATx_I2S3:
++          DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S3\n");
++          i = 2;
++          break;
++      case DMATx_I2S2:
++          DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S2\n");
++                  i = 1;
++          break;
++      case DMATx_I2S1:
++          default:
++          DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S1\n");
++                  i = 0;
++          break;
++    }
++
++    if(stream->audio_num_channels == 1){
++      chan = 0;
++    }
++    else{
++        chan = stream->audio_num_channels / 2 - 1;
++    }
++    handle = stream->dmahandles[i];
++
++    if(stream->stopped == 0){
++
++      if( ep93xx_dma_remove_buffer( handle, &buf_id ) >= 0 ){
++
++          buf = (audio_buf_t *)buf_id;
++            stream->bytecount += buf->reportedbytes;
++          ep93xx_dma_add_buffer( stream->dmahandles[i],
++                                  (unsigned int)buf->dma_addr,
++                                  0,
++                                  buf->bytes,
++                                  0,
++                                  (unsigned int) buf );
++            if(chan == i)
++              snd_pcm_period_elapsed(substream);
++      }
++    }
++}
++
++static void snd_ep93xx_dma_rx_callback
++(
++      ep93xx_dma_int_t DMAInt,
++      ep93xx_dma_dev_t device,
++      unsigned int user_data
++)
++{
++    int handle,i,chan;
++    unsigned int buf_id;
++    audio_buf_t *buf;
++
++    struct snd_pcm_substream *substream = (struct snd_pcm_substream *)user_data;
++    audio_state_t *state = (audio_state_t *)(substream->private_data);
++    audio_stream_t *stream = state->input_stream;
++
++    switch( device ){
++
++      case DMARx_I2S3:
++          DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S3\n");
++          i = 2;
++          break;
++      case DMARx_I2S2:
++          DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S2\n");
++          i = 1;
++          break;
++      case DMARx_I2S1:
++          default:
++          DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S1\n");
++          i = 0;
++          break;
++    }
++
++    if(stream->audio_num_channels == 1){
++      chan = 0;
++    }
++    else{
++        chan = stream->audio_num_channels / 2 - 1;
++    }
++    handle = stream->dmahandles[i];
++
++    if( stream->stopped == 0 ){
++
++        if( ep93xx_dma_remove_buffer( handle, &buf_id ) >= 0 ){
++
++          buf = (audio_buf_t *)buf_id;
++          stream->bytecount += buf->reportedbytes;
++          ep93xx_dma_add_buffer( stream->dmahandles[i],
++                                  (unsigned int)buf->dma_addr,
++                                  0,
++                                  buf->bytes,
++                                  0,
++                                  (unsigned int) buf );
++            if( i == chan )
++                snd_pcm_period_elapsed(substream);
++      }
++    }
++}
++
++static int snd_ep93xx_release(struct snd_pcm_substream *substream)
++{
++    audio_state_t *state = (audio_state_t *)substream->private_data;
++    audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++                             state->output_stream : state->input_stream;
++
++    DPRINTK("snd_ep93xx_release - enter\n");
++
++    down(&state->sem);
++    stream->active = 0;
++    stream->stopped = 0;
++    snd_ep93xx_deallocate_buffers(substream, stream);
++    up(&state->sem);
++
++    DPRINTK("snd_ep93xx_release - exit\n");
++
++    return 0;
++}
++
++static int ep93xx_ac97_pcm_startup(struct snd_pcm_substream *substream)
++{
++      struct snd_pcm_runtime *runtime = substream->runtime;
++      int r;
++      int iTempMasterVol,iTempHeadphoneVol,iTempMonoVol,iTempRecordSelect;
++        /*save the old mixer*/
++              iTempRecordSelect       = peek(AC97_1A_RECORD_SELECT);
++        iTempMasterVol                = peek( AC97_02_MASTER_VOL);
++        iTempHeadphoneVol     = peek( AC97_04_HEADPHONE_VOL);
++        iTempMonoVol          = peek( AC97_06_MONO_VOL);
++
++      runtime->hw.channels_min = 1;
++      runtime->hw.channels_max = 2;
++
++      ep93xx_audio_init();
++      /*ep93xx_init_ac97_controller();*/
++
++        /*reset the old output mixer*/
++        poke( AC97_02_MASTER_VOL, iTempMasterVol);
++        poke( AC97_04_HEADPHONE_VOL,iTempHeadphoneVol );
++        poke( AC97_06_MONO_VOL, iTempMonoVol);
++      poke( AC97_1A_RECORD_SELECT,iTempRecordSelect);
++
++      r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++          AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
++
++      DPRINTK(" ep93xx_ac97_pcm_startup=%x\n",r);
++
++              return 0;
++}
++
++
++static int snd_ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
++                              struct snd_pcm_hw_params *params)
++{
++        DPRINTK("snd_ep93xx_pcm_hw_params - enter\n");
++      return snd_pcm_lib_malloc_pages(substream,params_buffer_bytes(params));
++}
++
++static int snd_ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++
++      DPRINTK("snd_ep93xx_pcm_hw_free - enter\n");
++      return snd_pcm_lib_free_pages(substream);
++}
++
++/*
++ *snd_ep93xx_pcm_prepare: need to finish these functions as lower
++ *chip_set_sample_format
++ *chip_set_sample_rate
++ *chip_set_channels
++ *chip_set_dma_setup
++ */
++
++static int snd_ep93xx_pcm_prepare_playback( struct snd_pcm_substream *substream)
++{
++    audio_state_t *state = (audio_state_t *) substream->private_data;
++    struct snd_pcm_runtime *runtime = substream->runtime;
++    audio_stream_t *stream = state->output_stream;
++
++    DPRINTK("snd_ep93xx_pcm_prepare_playback - enter\n");
++
++    ep93xx_audio_disable(1);
++    ep93xx_ac97_pcm_startup(substream);
++
++    snd_ep93xx_deallocate_buffers(substream,stream);
++
++    //if(runtime->channels % 2 != 0)
++    //        return -1;
++
++    DPRINTK("The runtime item : \n");
++    DPRINTK("runtime->dma_addr    = 0x%x\n", runtime->dma_addr);
++    DPRINTK("runtime->dma_area    = 0x%x\n", runtime->dma_area);
++    DPRINTK("runtime->dma_bytes   = %d\n",   runtime->dma_bytes);
++    DPRINTK("runtime->frame_bits  = %d\n",   runtime->frame_bits);
++    DPRINTK("runtime->buffer_size = %d\n",   runtime->buffer_size);
++    DPRINTK("runtime->period_size = %d\n",   runtime->period_size);
++    DPRINTK("runtime->periods     = %d\n",   runtime->periods);
++    DPRINTK("runtime->rate        = %d\n",   runtime->rate);
++    DPRINTK("runtime->format      = %d\n",   runtime->format);
++    DPRINTK("runtime->channels    = %d\n",   runtime->channels);
++
++    /* set requestd format when available */
++    stream->audio_num_channels = runtime->channels;
++    if(stream->audio_num_channels == 1){
++      stream->dma_num_channels = 1;
++    }
++    else{
++      stream->dma_num_channels = runtime->channels / 2;
++    }
++
++    stream->audio_channels_flag = CHANNEL_FRONT;
++    if(stream->dma_num_channels == 2)
++        stream->audio_channels_flag |= CHANNEL_REAR;
++    if(stream->dma_num_channels == 3)
++        stream->audio_channels_flag |= CHANNEL_REAR | CHANNEL_CENTER_LFE;
++
++    stream->dmasize = runtime->dma_bytes;
++    stream->nbfrags = runtime->periods;
++    stream->fragsize = frames_to_bytes (runtime, runtime->period_size);
++    stream->bytecount = 0;
++
++    if( !state->codec_set_by_capture ){
++      state->codec_set_by_playback = 1;
++
++      if( stream->audio_rate != runtime->rate ){
++          ep93xx_set_samplerate( runtime->rate,0 );
++      }
++      //if( stream->audio_format != runtime->format ){
++      //    snd_ep93xx_i2s_init((stream->audio_stream_bitwidth == 24));
++      //}
++    }
++    else{
++        audio_stream_t *s = state->input_stream;
++        if( runtime->format != s->audio_format)
++          return -1;
++      if( runtime->rate != s->audio_rate )
++          return -1;
++    }
++
++    stream->audio_format = runtime->format ;
++    ep93xx_set_hw_format(stream->audio_format,stream->audio_num_channels);
++
++
++    stream->audio_rate = runtime->rate;
++    audio_set_format( stream, runtime->format );
++    snd_ep93xx_dma2usr_ratio( stream,state->bCompactMode );
++
++    if( snd_ep93xx_allocate_buffers( substream, stream ) != 0 ){
++        snd_ep93xx_deallocate_buffers( substream, stream );
++        return -1;
++    }
++
++    ep93xx_audio_enable(1);
++
++    DPRINTK("snd_ep93xx_pcm_prepare_playback - exit\n");
++    return 0;
++}
++
++static int snd_ep93xx_pcm_prepare_capture( struct snd_pcm_substream *substream)
++{
++    audio_state_t *state = (audio_state_t *) substream->private_data;
++    struct snd_pcm_runtime *runtime = substream->runtime;
++    audio_stream_t *stream = state->input_stream;
++
++    ep93xx_audio_disable(0);
++    ep93xx_ac97_pcm_startup(substream);
++
++    snd_ep93xx_deallocate_buffers(substream,stream);
++
++    //if(runtime->channels % 2 != 0)
++      //return -1;
++
++    DPRINTK("snd_ep93xx_pcm_prepare_capture - enter\n");
++
++//    printk("The runtime item : \n");
++//    printk("runtime->dma_addr    = 0x%x\n", runtime->dma_addr);
++//    printk("runtime->dma_area    = 0x%x\n", runtime->dma_area);
++//    printk("runtime->dma_bytes   = %d\n",   runtime->dma_bytes);
++//    printk("runtime->frame_bits  = %d\n",   runtime->frame_bits);
++//    printk("runtime->buffer_size = %d\n",   runtime->buffer_size);
++//    printk("runtime->period_size = %d\n",   runtime->period_size);
++//    printk("runtime->periods     = %d\n",   runtime->periods);
++//    printk("runtime->rate        = %d\n",   runtime->rate);
++//    printk("runtime->format      = %d\n",   runtime->format);
++//    printk("runtime->channels    = %d\n",   runtime->channels);
++
++    /* set requestd format when available */
++    stream->audio_num_channels = runtime->channels;
++    if(stream->audio_num_channels == 1){
++      stream->dma_num_channels = 1;
++    }
++    else{
++      stream->dma_num_channels = runtime->channels / 2;
++    }
++
++    stream->audio_channels_flag = CHANNEL_FRONT;
++    if(stream->dma_num_channels == 2)
++      stream->audio_channels_flag |= CHANNEL_REAR;
++    if(stream->dma_num_channels == 3)
++      stream->audio_channels_flag |= CHANNEL_REAR | CHANNEL_CENTER_LFE;
++
++    stream->dmasize = runtime->dma_bytes;
++    stream->nbfrags = runtime->periods;
++    stream->fragsize = frames_to_bytes (runtime, runtime->period_size);
++    stream->bytecount = 0;
++
++    if( !state->codec_set_by_playback ){
++      state->codec_set_by_capture = 1;
++
++      /*rate*/
++      if( stream->audio_rate != runtime->rate ){
++          ep93xx_set_samplerate( runtime->rate,1 );
++      }
++
++      /*mixer*/
++      ep93xx_set_recsource(SOUND_MASK_MIC|SOUND_MASK_LINE1 | SOUND_MASK_LINE);
++      poke( AC97_1C_RECORD_GAIN, 0);
++
++      /*format*/
++        //if( stream->audio_format != runtime->format ){
++      //    snd_ep93xx_i2s_init((stream->audio_stream_bitwidth == 24));
++      //}
++    }
++    else{
++        audio_stream_t *s = state->output_stream;
++        if( runtime->format != s->audio_format)
++          return -1;
++      if( runtime->rate != s->audio_rate )
++          return -1;
++    }
++
++    stream->audio_format = runtime->format ;
++    ep93xx_set_hw_format(stream->audio_format,stream->audio_num_channels);
++
++
++    stream->audio_rate = runtime->rate;
++    audio_set_format( stream, runtime->format );
++    snd_ep93xx_dma2usr_ratio( stream,state->bCompactMode );
++
++    if( snd_ep93xx_allocate_buffers( substream, stream ) != 0 ){
++        snd_ep93xx_deallocate_buffers( substream, stream );
++      return -1;
++    }
++
++    ep93xx_audio_enable(0);
++
++    DPRINTK("snd_ep93xx_pcm_prepare_capture - exit\n");
++    return 0;
++}
++/*
++ *start/stop/pause dma translate
++ */
++static int snd_ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++    audio_state_t  *state = (audio_state_t *)substream->private_data;
++    audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++                              state->output_stream:state->input_stream;
++    audio_buf_t *buf;
++    audio_channel_t *dma_channel;
++    int i,count,ret = 0;
++    unsigned long flags;
++
++    DPRINTK("snd_ep93xx_pcm_triger %d - enter \n",cmd);
++
++    switch (cmd){
++
++      case SNDRV_PCM_TRIGGER_START:
++
++          snd_ep93xx_dma_config( substream );
++
++            stream->stopped = 0;
++
++            if( !stream->active && !stream->stopped ){
++              stream->active = 1;
++              snd_ep93xx_dma_start( state, stream );
++            }
++
++            local_irq_save(flags);
++
++          for (i = 0; i < stream->dma_num_channels; i++){
++              dma_channel = &stream->dma_channels[i];
++
++              for(count = 0 ;count < dma_channel->audio_buff_count; count++){
++
++                  buf = &dma_channel->audio_buffers[count];
++                  ep93xx_dma_add_buffer( stream->dmahandles[i],
++                                          (unsigned int)buf->dma_addr,
++                                          0,
++                                          buf->bytes,
++                                          0,
++                                          (unsigned int) buf );
++              }
++          }
++
++          local_irq_restore(flags);
++          break;
++
++      case SNDRV_PCM_TRIGGER_STOP:
++          stream->stopped = 1;
++          snd_ep93xx_dma_pause( state, stream );
++          snd_ep93xx_dma_flush( state, stream );
++          snd_ep93xx_dma_free( substream );
++          break;
++
++      case SNDRV_PCM_TRIGGER_SUSPEND:
++          break;
++      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++          break;
++      case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++          break;
++
++          default:
++          ret = -EINVAL;
++    }
++    DPRINTK("snd_ep93xx_pcm_triger %d - exit \n",cmd);
++    return ret;
++}
++
++static snd_pcm_uframes_t snd_ep93xx_pcm_pointer_playback(struct snd_pcm_substream *substream)
++{
++    audio_state_t *state = (audio_state_t *)(substream->private_data);
++    struct snd_pcm_runtime *runtime = substream->runtime;
++    audio_stream_t *stream = state->output_stream;
++    snd_pcm_uframes_t pointer = 0;
++
++    pointer = bytes_to_frames( runtime,stream->bytecount );
++
++    if (pointer >= runtime->buffer_size){
++      pointer = 0;
++      stream->bytecount = 0;
++    }
++
++    DPRINTK("snd_ep93xx_pcm_pointer_playback - exit\n");
++    return pointer;
++}
++
++static snd_pcm_uframes_t snd_ep93xx_pcm_pointer_capture(struct snd_pcm_substream *substream)
++{
++    audio_state_t *state = (audio_state_t *)(substream->private_data);
++    struct snd_pcm_runtime *runtime = substream->runtime;
++    audio_stream_t *stream = state->input_stream;
++    snd_pcm_uframes_t pointer = 0;
++
++    pointer = bytes_to_frames( runtime,stream->bytecount );
++
++    if (pointer >= runtime->buffer_size){
++      pointer = 0;
++      stream->bytecount = 0;
++    }
++
++    DPRINTK("snd_ep93xx_pcm_pointer_capture - exit\n");
++    return pointer;
++}
++
++static int snd_ep93xx_pcm_open(struct snd_pcm_substream *substream)
++{
++    audio_state_t *state = substream->private_data;
++    struct snd_pcm_runtime *runtime = substream->runtime;
++    audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++                                state->output_stream:state->input_stream;
++
++    DPRINTK("snd_ep93xx_pcm_open - enter\n");
++
++    down(&state->sem);
++
++    runtime->hw = ep93xx_ac97_pcm_hardware;
++
++    stream->dma_num_channels = AUDIO_DEFAULT_DMACHANNELS;
++    stream->dma_channels = NULL;
++    stream->audio_rate = 0;
++    stream->audio_stream_bitwidth = 0;
++
++    up(&state->sem);
++
++    DPRINTK("snd_ep93xx_pcm_open - exit\n");
++    return 0;
++}
++
++/*
++ *free the HW dma channel
++ *free the HW dma buffer
++ *free the Hw dma decrotion using function :kfree
++ */
++static int snd_ep93xx_pcm_close(struct snd_pcm_substream *substream)
++{
++    audio_state_t *state = (audio_state_t *)(substream->private_data);
++
++    DPRINTK("snd_ep93xx_pcm_close - enter\n");
++
++    snd_ep93xx_release(substream);
++
++    if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++      state->codec_set_by_playback = 0;
++    else
++      state->codec_set_by_capture = 0;
++
++    DPRINTK("snd_ep93xx_pcm_close - exit\n");
++    return 0;
++}
++
++static int snd_ep93xx_pcm_copy_playback(struct snd_pcm_substream * substream,int channel,
++                              snd_pcm_uframes_t pos,void __user *src, snd_pcm_uframes_t count)
++{
++
++    audio_state_t *state = (audio_state_t *)substream->private_data;
++    struct snd_pcm_runtime *runtime = substream->runtime;
++    audio_stream_t *stream = state->output_stream ;
++    audio_channel_t *dma_channel;
++    int i;
++    int tocount = frames_to_bytes(runtime,count);
++
++    for( i = 0; i < stream->dma_num_channels; i++ ){
++
++      dma_channel = &stream->dma_channels[i];
++      stream->hwbuf[i] = dma_channel->area + ( frames_to_bytes(runtime,pos) * stream->dma2usr_ratio / stream->dma_num_channels );
++
++    }
++
++    if(copy_from_user_with_conversion(stream ,(const char*)src,(tocount * stream->dma2usr_ratio),state->bCompactMode) <=0 ){
++      DPRINTK(KERN_ERR "copy_from_user_with_conversion() failed\n");
++      return -EFAULT;
++    }
++
++    DPRINTK("snd_ep93xx_pcm_copy_playback - exit\n");
++    return 0;
++}
++
++
++static int snd_ep93xx_pcm_copy_capture(struct snd_pcm_substream * substream,int channel,
++                              snd_pcm_uframes_t pos,void __user *src, snd_pcm_uframes_t count)
++{
++    audio_state_t *state = (audio_state_t *)substream->private_data;
++    struct snd_pcm_runtime *runtime = substream->runtime;
++    audio_stream_t *stream = state->input_stream ;
++    audio_channel_t *dma_channel;
++    int i;
++
++    int tocount = frames_to_bytes(runtime,count);
++
++    for( i = 0; i < stream->dma_num_channels; i++ ){
++
++      dma_channel = &stream->dma_channels[i];
++      stream->hwbuf[i] = dma_channel->area + ( frames_to_bytes(runtime,pos) * stream->dma2usr_ratio / stream->dma_num_channels );
++
++    }
++
++    if(copy_to_user_with_conversion(stream,(const char*)src,tocount,state->bCompactMode) <=0 ){
++
++      DPRINTK(KERN_ERR "copy_to_user_with_conversion() failed\n");
++      return -EFAULT;
++    }
++
++    DPRINTK("snd_ep93xx_pcm_copy_capture - exit\n");
++    return 0;
++}
++
++/*----------------------------------------------------------------------------------*/
++static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
++{
++      int val = -1;
++      /*volatile u32 *reg_addr;*/
++
++      DPRINTK(" number of codec:%x reg=%x\n",ac97->num,reg);
++      val=peek(reg);
++      if(val==-1){
++              printk(KERN_ERR "%s: read error (ac97_reg=%d )val=%x\n",
++                              __FUNCTION__, reg, val);
++              return 0;
++      }
++
++      return val;
++}
++
++static void ep93xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
++{
++      /*volatile u32 *reg_addr;*/
++      int ret;
++
++      DPRINTK(" number of codec:%x rge=%x val=%x\n",ac97->num,reg,val);
++      ret=poke(reg, val);
++      if(ret!=0){
++              printk(KERN_ERR "%s: write error (ac97_reg=%d val=%x)\n",
++                              __FUNCTION__, reg, val);
++      }
++
++}
++
++static void ep93xx_ac97_reset(struct snd_ac97 *ac97)
++{
++
++      DPRINTK(" ep93xx_ac97_reset\n");
++      ep93xx_audio_init();
++
++}
++
++static struct snd_ac97_bus_ops ep93xx_ac97_ops = {
++      .read   = ep93xx_ac97_read,
++      .write  = ep93xx_ac97_write,
++      .reset  = ep93xx_ac97_reset,
++};
++
++static struct snd_pcm *ep93xx_ac97_pcm;
++static struct snd_ac97 *ep93xx_ac97_ac97;
++
++static struct snd_pcm_ops snd_ep93xx_pcm_playback_ops = {
++      .open           = snd_ep93xx_pcm_open,
++      .close          = snd_ep93xx_pcm_close,
++      .ioctl          = snd_pcm_lib_ioctl,
++      .hw_params      = snd_ep93xx_pcm_hw_params,
++      .hw_free        = snd_ep93xx_pcm_hw_free,
++      .prepare        = snd_ep93xx_pcm_prepare_playback,
++      .trigger        = snd_ep93xx_pcm_trigger,
++      .pointer        = snd_ep93xx_pcm_pointer_playback,
++      .copy           = snd_ep93xx_pcm_copy_playback,
++
++};
++
++static struct snd_pcm_ops snd_ep93xx_pcm_capture_ops = {
++      .open           = snd_ep93xx_pcm_open,
++      .close          = snd_ep93xx_pcm_close,
++      .ioctl          = snd_pcm_lib_ioctl,
++      .hw_params      = snd_ep93xx_pcm_hw_params,
++      .hw_free        = snd_ep93xx_pcm_hw_free,
++      .prepare        = snd_ep93xx_pcm_prepare_capture,
++      .trigger        = snd_ep93xx_pcm_trigger,
++      .pointer        = snd_ep93xx_pcm_pointer_capture,
++      .copy           = snd_ep93xx_pcm_copy_capture,
++};
++
++/*--------------------------------------------------------------------------*/
++
++
++static int snd_ep93xx_pcm_new(struct snd_card *card, audio_state_t *state, struct snd_pcm **rpcm)
++{
++    struct snd_pcm *pcm;
++    int play = state->output_stream? 1 : 0;/*SNDRV_PCM_STREAM_PLAYBACK*/
++    int capt = state->input_stream ? 1 : 0;/*SNDRV_PCM_STREAM_CAPTURE*/
++    int ret = 0;
++
++    DPRINTK("snd_ep93xx_pcm_new - enter\n");
++
++    /* Register the new pcm device interface */
++    ret = snd_pcm_new(card, "EP93xx-AC97-PCM", 0, play, capt, &pcm);
++
++    if (ret){
++      DPRINTK("%s--%x:card=%x,play=%x,capt=%x,&pcm=%x\n",__FUNCTION__,ret,(int)card,play,capt,(int)pcm);
++      goto out;
++    }
++
++    /* allocate the pcm(DMA) memory */
++    ret = snd_pcm_lib_preallocate_pages_for_all(pcm, /*SNDRV_DMA_TYPE_DEV,0,*/SNDRV_DMA_TYPE_CONTINUOUS,snd_dma_continuous_data(GFP_KERNEL),128*1024,128*1024);
++
++    DPRINTK("The substream item : \n");
++    DPRINTK("pcm->streams[0].substream->dma_buffer.addr  = 0x%x\n", pcm->streams[0].substream->dma_buffer.addr);
++    DPRINTK("pcm->streams[0].substream->dma_buffer.area  = 0x%x\n", pcm->streams[0].substream->dma_buffer.area);
++    DPRINTK("pcm->streams[0].substream->dma_buffer.bytes = 0x%x\n", pcm->streams[0].substream->dma_buffer.bytes);
++    DPRINTK("pcm->streams[1].substream->dma_buffer.addr  = 0x%x\n", pcm->streams[1].substream->dma_buffer.addr);
++    DPRINTK("pcm->streams[1].substream->dma_buffer.area  = 0x%x\n", pcm->streams[1].substream->dma_buffer.area);
++    DPRINTK("pcm->streams[1].substream->dma_buffer.bytes = 0x%x\n", pcm->streams[1].substream->dma_buffer.bytes);
++
++    pcm->private_data = state;
++
++    /* seem to free the pcm data struct-->self dma buffer */
++    pcm->private_free = (void*) snd_pcm_lib_preallocate_free_for_all;
++
++    /* alsa pcm ops setting for SNDRV_PCM_STREAM_PLAYBACK */
++    if (play) {
++      int stream = SNDRV_PCM_STREAM_PLAYBACK;
++      snd_pcm_set_ops(pcm, stream, &snd_ep93xx_pcm_playback_ops);
++    }
++
++    /* alsa pcm ops setting for SNDRV_PCM_STREAM_CAPTURE */
++    if (capt) {
++      int stream = SNDRV_PCM_STREAM_CAPTURE;
++      snd_pcm_set_ops(pcm, stream, &snd_ep93xx_pcm_capture_ops);
++    }
++
++    if (rpcm)
++      *rpcm = pcm;
++    DPRINTK("snd_ep93xx_pcm_new - exit\n");
++out:
++    return ret;
++}
++
++#ifdef CONFIG_PM
++
++int ep93xx_ac97_do_suspend(struct snd_card *card, unsigned int state)
++{
++      if (card->power_state != SNDRV_CTL_POWER_D3cold) {
++              snd_pcm_suspend_all(ep93xx_ac97_pcm);
++              snd_ac97_suspend(ep93xx_ac97_ac97);
++              snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
++      }
++
++      return 0;
++}
++
++int ep93xx_ac97_do_resume(struct snd_card *card, unsigned int state)
++{
++      if (card->power_state != SNDRV_CTL_POWER_D0) {
++
++              snd_ac97_resume(ep93xx_ac97_ac97);
++              snd_power_change_state(card, SNDRV_CTL_POWER_D0);
++      }
++
++      return 0;
++}
++
++int ep93xx_ac97_suspend(struct platform_device *_dev, u32 state, u32 level)
++{
++      struct snd_card *card = platform_get_drvdata(_dev);
++      int ret = 0;
++
++      if (card && level == SUSPEND_DISABLE)
++              ret = ep93xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold);
++
++      return ret;
++}
++
++int ep93xx_ac97_resume(struct platform_device *_dev, u32 level)
++{
++      struct snd_card *card = platform_get_drvdata(_dev);
++      int ret = 0;
++
++      if (card && level == RESUME_ENABLE)
++              ret = ep93xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0);
++
++      return ret;
++}
++
++#else
++/*
++#define ep93xx_ac97_do_suspend                NULL
++#define ep93xx_ac97_do_resume         NULL
++#define ep93xx_ac97_suspend           NULL
++#define ep93xx_ac97_resume            NULL
++*/
++
++int ep93xx_ac97_do_suspend(struct snd_card *card, unsigned int state)
++{
++        return 0;
++}
++
++int ep93xx_ac97_do_resume(struct snd_card *card, unsigned int state)
++{
++        return 0;
++}
++
++int ep93xx_ac97_resume(struct platform_device *_dev, u32 level)
++{
++        struct snd_card *card = platform_get_drvdata(_dev);
++        int ret = 0;
++
++        //if (card && level == RESUME_ENABLE)
++                ret = ep93xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0);
++
++        return ret;
++}
++
++int ep93xx_ac97_suspend(struct platform_device *_dev, u32 state, u32 level)
++{
++        struct snd_card *card = platform_get_drvdata(_dev);
++        int ret = 0;
++
++        //if (card && level == SUSPEND_DISABLE)
++                ret = ep93xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold);
++
++        return ret;
++}
++
++#endif
++
++
++
++/* module init & exit */
++static int __devinit ep93xx_ac97_probe(struct platform_device *dev)
++{
++    struct snd_card *card;
++    struct snd_ac97_bus *ac97_bus;
++    struct snd_ac97_template ac97_template;
++    int err = -ENOMEM;
++    struct resource *res = NULL;
++
++    DPRINTK("snd_ep93xx_probe - enter\n");
++
++    /* Enable audio early on, give the DAC time to come up. */
++    res = platform_get_resource( dev, IORESOURCE_MEM, 0);
++
++    if(!res) {
++      printk("error : platform_get_resource \n");
++        return -ENODEV;
++    }
++
++    if (!request_mem_region(res->start,res->end - res->start + 1, "snd-ac97-cs4202" )){
++      printk("error : request_mem_region\n");
++        return -EBUSY;
++    }
++
++    /*enable ac97 codec*/
++    ep93xx_audio_init();
++
++    /* register the soundcard */
++    card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
++                          THIS_MODULE, 0);
++    if (!card){
++      printk("AC97: snd_card_new error\n");
++      goto error;
++    }
++
++    card->dev = &dev->dev;
++    /*regist the new pcm device*/
++    err = snd_ep93xx_pcm_new(card, &audio_state, &ep93xx_ac97_pcm);
++    if (err){
++      printk("AC97: ep93xx_ac97_pcm_new error\n");
++      goto error;
++    }
++    if (card == NULL) {
++      DPRINTK(KERN_ERR "snd_card_new() failed\n");
++      goto error;
++    }
++
++    /*driver name*/
++    strcpy(card->driver, "CS4202A");
++    strcpy(card->shortname, "Cirrus Logic AC97 Audio ");
++    strcpy(card->longname, "Cirrus Logic AC97 Audio with CS4202A");
++
++    /*regist the new ac97 device*/
++    err = snd_ac97_bus(card, 0, &ep93xx_ac97_ops, NULL, &ac97_bus);
++    if (err){
++      printk("AC97: snd_ac97_bus error\n");
++      goto error;
++    }
++
++    memset(&ac97_template, 0, sizeof(ac97_template));
++    err = snd_ac97_mixer(ac97_bus, &ac97_template, &ep93xx_ac97_ac97);
++    if (err){
++      printk("AC97: snd_ac97_mixer error\n");
++      goto error;
++    }
++
++    /**/
++    ep93xx_audio_init();
++    /*setting the card device callback*/
++    //err = snd_card_set_pm_callback(card, ep93xx_ac97_do_suspend,ep93xx_ac97_do_resume, (void*)NULL);
++    //if(err != 0){
++    //        printk("snd_card_set_pm_callback error\n");
++    //}
++
++    /*regist the new CARD device*/
++    err = snd_card_register(card);
++    if (err == 0) {
++      printk( KERN_INFO "Cirrus Logic ep93xx ac97 audio initialized\n" );
++      platform_set_drvdata(dev,card);
++      DPRINTK("snd_ep93xx_probe - exit\n");
++      return 0;
++    }
++
++error:
++    snd_card_free(card);
++    printk("snd_ep93xx_probe - error\n");
++    return err;
++
++return 0;
++}
++
++static int __devexit ep93xx_ac97_remove(struct platform_device *dev)
++{
++    struct resource *res;
++    struct snd_card *card = platform_get_drvdata(dev);
++
++    res = platform_get_resource( dev, IORESOURCE_MEM, 0);
++    release_mem_region(res->start, res->end - res->start + 1);
++
++    DPRINTK("snd_ep93xx_ac97_remove - enter\n");
++
++    if (card) {
++      snd_card_free(card);
++      platform_set_drvdata(dev, NULL);
++    }
++    DPRINTK("snd_ep93xx_remove - exit\n");
++
++return 0;
++}
++
++
++static struct platform_driver ep93xx_ac97_driver = {
++      .probe          = ep93xx_ac97_probe,
++      .remove         = __devexit_p (ep93xx_ac97_remove),
++      .suspend        = ep93xx_ac97_suspend,
++      .resume         = ep93xx_ac97_resume,
++      .driver         = {
++              .name   = "ep93xx-ac97",
++      },
++};
++
++
++static int __init ep93xx_ac97_init(void)
++{
++    int ret;
++
++    DPRINTK(KERN_INFO "%s: version %s\n", DRIVER_DESC, DRIVER_VERSION);
++    DPRINTK("snd_ep93xx_AC97_init - enter\n");
++    ret = platform_driver_register(&ep93xx_ac97_driver);
++    DPRINTK("snd_ep93xx_AC97_init - exit\n");
++    return ret;
++}
++
++static void __exit ep93xx_ac97_exit(void)
++{
++    DPRINTK("ep93xx_ac97_exit  - enter\n");
++    return platform_driver_unregister(&ep93xx_ac97_driver);
++}
++
++module_init(ep93xx_ac97_init);
++module_exit(ep93xx_ac97_exit);
++
++MODULE_DESCRIPTION("Cirrus Logic audio module");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ linux-2.6.31/sound/arm/ep93xx-ac97.h
+@@ -0,0 +1,89 @@
++/*
++ * linux/sound/arm/ep93xx-ac97.h -- ALSA PCM interface for the edb93xx ac97 audio
++ *
++ * Author:      Fred Wei
++ * Created:     July 19, 2005
++ * Copyright:   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.
++ */
++
++#define EP93XX_DEFAULT_NUM_CHANNELS     2
++#define EP93XX_DEFAULT_FORMAT           SNDRV_PCM_FORMAT_S16_LE
++#define EP93XX_DEFAULT_BIT_WIDTH        16
++#define MAX_DEVICE_NAME               20
++
++/*
++ * Buffer Management
++ */
++
++typedef struct {
++
++    unsigned char     *area;          /* virtual pointer */
++    dma_addr_t                dma_addr;       /* physical address */
++    size_t            bytes;
++    size_t            reportedbytes;  /* buffer size */
++    int               sent;           /* indicates that dma has the buf */
++    char              *start;         /* points to actual buffer */
++
++} audio_buf_t;
++
++
++typedef struct {
++
++    unsigned char     *area;                  /* virtual pointer */
++    dma_addr_t                addr;                   /* physical address */
++    size_t            bytes;                  /* buffer size in bytes */
++    unsigned char             *buff_pos;              /* virtual pointer */
++    audio_buf_t               *audio_buffers;         /* array of audio buffer structures */
++    int               audio_buff_count;
++
++
++} audio_channel_t;
++
++typedef struct audio_stream_s {
++
++    /* dma stuff */
++    int                       dmahandles[3];          /* handles for dma driver instances */
++    char              devicename[MAX_DEVICE_NAME]; /* string - name of device */
++    int                       dma_num_channels;               /* 1, 2, or 3 DMA channels */
++    audio_channel_t   *dma_channels;
++    u_int             nbfrags;                /* nbr of fragments i.e. buffers */
++    u_int             fragsize;               /* fragment i.e. buffer size */
++    u_int             dmasize;
++    int               bytecount;              /* nbr of processed bytes */
++    int               externedbytecount;      /* nbr of processed bytes */
++    volatile int        active;                 /* actually in progress                 */
++    volatile int        stopped;                /* might be active but stopped          */
++    char              *hwbuf[3];
++    long              audio_rate;
++    long              audio_num_channels;             /* Range: 1 to 6 */
++    int                       audio_channels_flag;
++    long              audio_format;
++    long              audio_stream_bitwidth;          /* Range: 8, 16, 24 */
++    int                       dma2usr_ratio;
++
++} audio_stream_t;
++
++
++/*
++ * State structure for one instance
++ */
++typedef struct {
++
++    audio_stream_t    *output_stream;
++    audio_stream_t    *input_stream;
++    ep93xx_dma_dev_t  output_dma[3];
++    ep93xx_dma_dev_t  input_dma[3];
++    char              *output_id[3];
++    char              *input_id[3];
++    struct              semaphore sem;          /* to protect against races in attach() */
++    int                       codec_set_by_playback;
++    int                 codec_set_by_capture;
++    int                 DAC_bit_width;          /* 16, 20, 24 bits */
++    int                 bCompactMode;           /* set if 32bits = a stereo sample */
++
++} audio_state_t;
++
diff --git a/recipes/linux/linux-2.6.32/ep93xx/ep93xx-spi.patch b/recipes/linux/linux-2.6.32/ep93xx/ep93xx-spi.patch
new file mode 100644 (file)
index 0000000..6effac1
--- /dev/null
@@ -0,0 +1,721 @@
+---
+ drivers/spi/Kconfig      |    6 
+ drivers/spi/Makefile     |    1 
+ drivers/spi/spi_ep93xx.c |  679 +++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 686 insertions(+)
+
+--- linux-2.6.32.orig/drivers/spi/Kconfig
++++ linux-2.6.32/drivers/spi/Kconfig
+@@ -98,10 +98,16 @@ config SPI_BUTTERFLY
+         This uses a custom parallel port cable to connect to an AVR
+         Butterfly <http://www.atmel.com/products/avr/butterfly>, an
+         inexpensive battery powered microcontroller evaluation board.
+         This same cable can be used to flash new firmware.
++config SPI_EP93XX
++      tristate "EP93xx SSP SPI master"
++      depends on SPI_MASTER && ARCH_EP93XX && EXPERIMENTAL
++      help
++        This enables the EP93xx SPI master controller.
++
+ config SPI_GPIO
+       tristate "GPIO-based bitbanging SPI Master"
+       depends on GENERIC_GPIO
+       select SPI_BITBANG
+       help
+--- linux-2.6.32.orig/drivers/spi/Makefile
++++ linux-2.6.32/drivers/spi/Makefile
+@@ -31,10 +31,11 @@ obj-$(CONFIG_SPI_S3C24XX_GPIO)             += spi_s
+ obj-$(CONFIG_SPI_S3C24XX)             += spi_s3c24xx.o
+ obj-$(CONFIG_SPI_TXX9)                        += spi_txx9.o
+ obj-$(CONFIG_SPI_XILINX)              += xilinx_spi.o
+ obj-$(CONFIG_SPI_SH_SCI)              += spi_sh_sci.o
+ obj-$(CONFIG_SPI_STMP3XXX)            += spi_stmp.o
++obj-$(CONFIG_SPI_EP93XX)              += spi_ep93xx.o
+ #     ... add above this line ...
+ # SPI protocol drivers (device/link on bus)
+ obj-$(CONFIG_SPI_SPIDEV)      += spidev.o
+ obj-$(CONFIG_SPI_TLE62X0)     += tle62x0.o
+--- /dev/null
++++ linux-2.6.32/drivers/spi/spi_ep93xx.c
+@@ -0,0 +1,679 @@
++/*
++ * linux/drivers/spi/spi_ep93xx.c
++ *
++ * Copyright (C) 2007 Manfred Gruber <m.gruber@tirol.com>
++ * Small changes by Peter Ivanov <ivanovp@gmail.com> to support MMC over SPI, 2008
++ * SIM.ONE changes by Nuccio Raciti Simplemachine <nuccio.raciti@gmail.com>
++ *
++ * Based on pxa2xx_spi.c/spi_imx.c and bitbang.c driver
++ *
++ * 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/blkdev.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/err.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/workqueue.h>
++
++#include <linux/spi/spi.h>
++
++#include <mach/hardware.h>
++#include <mach/ep93xx-regs.h>
++#include <mach/gpio.h>
++
++/* #define SPI_EP93XX_DEBUG */
++
++#define DEFINE_SSP_REG(reg, off)                      \
++      static inline u32 read_##reg(void *p)           \
++              { return __raw_readl(p + (off)); }      \
++      static inline void write_##reg(u32 v, void *p)  \
++              { __raw_writel(v, p + (off)); }
++
++DEFINE_SSP_REG(SSPCR0, 0x00)
++DEFINE_SSP_REG(SSPCR1, 0x04)
++DEFINE_SSP_REG(SSPDR, 0x08)
++DEFINE_SSP_REG(SSPSR, 0x0c)
++DEFINE_SSP_REG(SSPCPSR, 0x10)
++DEFINE_SSP_REG(SSPIIR, 0x14)
++DEFINE_SSP_REG(SSPICR, 0x14)
++
++/* Bits in SSPCR0 */
++#define SSPCR0_DSS_MASK               0x0000000f
++#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 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
++
++/* 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 */
++#define SSPSR_MASK            0x0000001F      /* SSP is busy */
++
++/* Bits in SSPCPSR */
++#define SSPCPSR_SCR_MASK      0x000000ff
++
++/* 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 */
++
++#define SPI_SSPCLK            7.4e6
++#define SPI_SSPCLK_REV_E2     14.8e6          /* only for chip Rev E2 */
++#define SPI_MAX_SPEED         3.7e6
++#define SPI_MAX_SPEED_REV_E2  7.4e6           /* only for chip Rev E2 */
++#define SPI_CPSDVR_DIV_MIN    2
++#define SPI_CPSDVR_DIV_MAX    254
++#define SPI_SCR_DIV_MIN               0
++#define SPI_SCR_DIV_MAX               255
++#define SPI_DATARATE_OK               0
++#define SPI_DATARATE_NOK      -1
++
++struct driver_data {
++      /* Driver model hookup */
++      struct platform_device *pdev;
++
++      /* SPI framework hookup */
++      struct spi_master *master;
++
++      /* SSP register addresses */
++      void *ioaddr;
++
++      /* SSP irq */
++      int irq;
++
++      struct list_head queue;
++
++      /* SSP spinlock */
++      spinlock_t lock;
++
++      struct workqueue_struct *workqueue;
++      struct work_struct      work;
++
++      u8 busy;
++      u8 use_dma;
++};
++
++static unsigned ep93xx_txrx_8(struct spi_device *spi, struct spi_transfer *t)
++{
++      struct driver_data *drv_data;
++      const u8 *tx = t->tx_buf;
++      u8 *rx = t->rx_buf;
++      unsigned count = t->len;
++      u8 byte;
++      int busy;
++
++      drv_data = spi_master_get_devdata(spi->master);
++
++#ifdef SPI_EP93XX_DEBUG
++      dev_info(&spi->dev,
++              "ep93xx_txrx_8: t->len %u \n", t->len);
++#endif
++
++      while (likely(count > 0)) {
++              byte = 0;
++              if (tx) {
++                      byte = *tx++;
++#ifdef SPI_EP93XX_DEBUG
++                      dev_info(&spi->dev,
++                              "ep93xx_txrx_8: write 0x%x \n", byte);
++#endif
++              }
++
++              write_SSPDR(byte, drv_data->ioaddr);
++              busy = read_SSPSR(drv_data->ioaddr);
++              while (busy & SSPSR_BSY) {
++                      cpu_relax();
++                      busy = read_SSPSR(drv_data->ioaddr);
++#ifdef SPI_EP93XX_DEBUG
++                      dev_info(&spi->dev,
++                              "ep93xx_txrx_8: delay. SSPSR: 0x%X\n", busy);
++#endif
++              }
++              byte = read_SSPDR(drv_data->ioaddr);
++
++              if (rx) {
++                      *rx++ = byte;
++#ifdef SPI_EP93XX_DEBUG
++                      dev_info(&spi->dev,
++                              "ep93xx_txrx_8: read 0x%x \n", byte);
++#endif
++              }
++              count -= 1;
++      }
++      return t->len - count;
++}
++
++
++static unsigned ep93xx_txrx_16(struct spi_device *spi, struct spi_transfer *t)
++{
++
++      struct driver_data *drv_data;
++      const u16 *tx = t->tx_buf;
++      u16 *rx = t->rx_buf;
++      unsigned count = t->len;
++      u16 word;
++      int busy;
++
++      drv_data = spi_master_get_devdata(spi->master);
++
++#ifdef SPI_EP93XX_DEBUG
++      dev_info(&spi->dev,
++              "ep93xx_txrx_16: t->len %u \n", t->len);
++#endif
++      while (likely(count > 0)) {
++              word = 0;
++              if (tx) {
++                      word = *tx++;
++#ifdef SPI_EP93XX_DEBUG
++                      dev_info(&spi->dev,
++                              "ep93xx_txrx_16: write 0x%x \n", word);
++#endif
++              }
++
++              write_SSPDR(word, drv_data->ioaddr);
++              busy = read_SSPSR(drv_data->ioaddr);
++              while (busy & SSPSR_BSY) {
++                      cpu_relax();
++                      busy = read_SSPSR(drv_data->ioaddr);
++#ifdef SPI_EP93XX_DEBUG
++                      dev_info(&spi->dev,
++                              "ep93xx_txrx_8: delay.\n");
++#endif
++              }
++
++              word = read_SSPDR(drv_data->ioaddr);
++
++              if (rx) {
++                      *rx++ = word;
++#ifdef SPI_EP93XX_DEBUG
++                      dev_info(&spi->dev,
++                              "ep93xx_txrx_16: read 0x%x \n", word);
++#endif
++              }
++              count -= 2;
++      }
++      return t->len - count;
++}
++
++static u32 spi_data_rate(u32 speed_hz, u32 *div_cpsdvr, u32 *div_scr,
++      struct driver_data *drv_data, struct spi_device *spi)
++{
++      unsigned int spi_sspclk = SPI_SSPCLK;
++      unsigned int bus_speed_max = SPI_MAX_SPEED;
++      unsigned int bus_hz_tmp = 0;
++      u32 div_cpsdvr_tmp;
++      u32 div_scr_tmp;
++      u32 rv = SPI_DATARATE_NOK;
++      int chip_rev;
++
++      /* Checking CHIP_ID */
++      chip_rev = (__raw_readl (EP93XX_SYSCON_CHIP_ID) >> 28) & 0xF;
++      if (chip_rev == 7)
++      {
++              /* Chip version: Rev E2 */
++              /* This device has double speed SSP clock */
++              spi_sspclk = SPI_SSPCLK_REV_E2;
++              bus_speed_max = SPI_MAX_SPEED_REV_E2;
++#ifdef SPI_EP93XX_DEBUG
++              dev_info(&spi->dev,
++                              "Chip Rev E2 detected! This device has double speed SSP clock.\n");
++#endif
++      }
++
++      *div_cpsdvr = SPI_CPSDVR_DIV_MAX;
++      *div_scr = SPI_SCR_DIV_MAX;
++
++      for (div_cpsdvr_tmp = SPI_CPSDVR_DIV_MIN;
++                      div_cpsdvr_tmp <= SPI_CPSDVR_DIV_MAX && rv; div_cpsdvr_tmp++) {
++              for (div_scr_tmp = SPI_SCR_DIV_MIN;
++                              div_scr_tmp <= SPI_SCR_DIV_MAX && rv; div_scr_tmp++) {
++                      bus_hz_tmp = spi_sspclk / (div_cpsdvr_tmp * (1 + div_scr_tmp));
++                      if (bus_hz_tmp <= speed_hz && bus_hz_tmp <= bus_speed_max) {
++                              *div_cpsdvr = div_cpsdvr_tmp;
++                              *div_scr = div_scr_tmp;
++                              rv = SPI_DATARATE_OK;
++                      }
++              }
++      }
++#ifdef SPI_EP93XX_DEBUG
++      dev_info(&spi->dev,
++                      "Needed SPI bus frequency: %i Hz\n", speed_hz);
++      dev_info(&spi->dev,
++                      "Actual SPI bus frequency: %i Hz\n", bus_hz_tmp);
++#endif
++      return rv;
++}
++
++/* Supported modes (returns -EINVAL if not supported mode requested) */
++#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
++
++static int ep93xx_spi_setup(struct spi_device *spi)
++{
++      struct driver_data *drv_data;
++      u16 val;
++      u32 div_scr;
++      u32 div_cpsdvr;
++      unsigned int bits = spi->bits_per_word;
++      unsigned long speed_hz = spi->max_speed_hz;
++
++      drv_data = spi_master_get_devdata(spi->master);
++
++      /* enable SSP */
++      write_SSPCR1(SSPC1_SSE, drv_data->ioaddr);
++      /* Enable SSP and loopback mode (only for testing!) */
++      /* write_SSPCR1(SSPC1_SSE | SSPC1_LBM, drv_data->ioaddr);  */
++
++      if (bits == 0)
++              bits = 8;
++      if (bits < 4 || bits > 16) {
++              dev_err(&spi->dev,
++                      "setup invalid bits_per_word %u (4 to 16)\n", bits);
++              return -EINVAL;
++      } else {
++              val = read_SSPCR0(drv_data->ioaddr);
++              val = val & ~SSPCR0_DSS_MASK ;
++              val = val | (bits-1);
++              write_SSPCR0(val, drv_data->ioaddr);
++#ifdef SPI_EP93XX_DEBUG
++              dev_info (&spi->dev, "Bits per word: %i\n", bits);
++#endif
++      }
++
++      if (spi->mode & ~MODEBITS) {
++              dev_err(&spi->dev, "unsupported mode bits: %x\n",
++                      spi->mode & ~MODEBITS);
++              return -EINVAL;
++      } else {
++              val = read_SSPCR0(drv_data->ioaddr);
++              val = val & ~SSPCR0_SPO;
++              val = val & ~SSPCR0_SPH;
++              if (spi->mode & SPI_CPOL)
++              {
++                      val = val | SSPCR0_SPO;
++              }
++#ifdef SPI_EP93XX_DEBUG
++              dev_info (&spi->dev, "Clock polarity (CPOL): %s\n", (spi->mode & SPI_CPHA) ? "1" : "0");
++#endif
++              if (spi->mode & SPI_CPHA)
++              {
++                      val = val | SSPCR0_SPH;
++              }
++#ifdef SPI_EP93XX_DEBUG
++              dev_info (&spi->dev, "Clock phase (CPHA): %s\n", (spi->mode & SPI_CPHA) ? "1" : "0");
++#endif
++              write_SSPCR0(val, drv_data->ioaddr);
++      }
++
++      if (SPI_DATARATE_OK == (spi_data_rate(speed_hz, &div_cpsdvr,
++              &div_scr, drv_data, spi))) {
++
++              val = read_SSPCPSR(drv_data->ioaddr);
++              val = val & ~SSPCPSR_SCR_MASK;
++              val = val | div_cpsdvr;
++#ifdef SPI_EP93XX_DEBUG
++              dev_info (&spi->dev, "SSPCPSR: 0x%X\n", val);
++#endif
++              write_SSPCPSR(val, drv_data->ioaddr);
++
++              val = read_SSPCR0(drv_data->ioaddr);
++              val = val & ~SSPCR0_SCR_MASK;
++              val = val | (div_scr << SSPCR0_SCR_SHIFT);
++#ifdef SPI_EP93XX_DEBUG
++              dev_info (&spi->dev, "SSPCR0: 0x%X (div_scr: 0x%X)\n", val, div_scr);
++#endif
++              write_SSPCR0(val, drv_data->ioaddr);
++      } else
++              return -EINVAL;
++
++      /* reenable */
++      val = read_SSPCR1(drv_data->ioaddr);
++      val = val & ~SSPC1_SSE;
++      write_SSPCR1(val, drv_data->ioaddr);
++      val = read_SSPCR1(drv_data->ioaddr);
++      val = val | SSPC1_SSE;
++      write_SSPCR1(val, drv_data->ioaddr);
++#ifdef SPI_EP93XX_DEBUG
++      dev_info (&spi->dev, "Loopback mode: %s\n", (val & SSPC1_LBM) ? "On" : "Off");
++#endif
++
++      return 0;
++}
++
++static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
++{
++      struct driver_data *drv_data;
++      unsigned long flags;
++      int status = 0;
++
++      m->actual_length = 0;
++      m->status = -EINPROGRESS;
++
++      drv_data = spi_master_get_devdata(spi->master);
++
++      spin_lock_irqsave(&drv_data->lock, flags);
++      if (!spi->max_speed_hz)
++              status = -ENETDOWN;
++      else {
++              list_add_tail(&m->queue, &drv_data->queue);
++              queue_work(drv_data->workqueue, &drv_data->work);
++      }
++      spin_unlock_irqrestore(&drv_data->lock, flags);
++      return status;
++}
++
++static void ep93xx_work(struct work_struct *work)
++{
++      struct driver_data *drv_data =
++              container_of(work, struct driver_data, work);
++      unsigned long flags;
++
++      spin_lock_irqsave(&drv_data->lock, flags);
++      drv_data->busy = 1;
++
++      while (!list_empty(&drv_data->queue)) {
++              struct spi_message *m;
++              struct spi_device *spi;
++              struct spi_transfer *t = NULL;
++              int status;
++
++              m = container_of(drv_data->queue.next, struct spi_message,
++                      queue);
++              list_del_init(&m->queue);
++              spin_unlock_irqrestore(&drv_data->lock, flags);
++
++              spi = m->spi;
++              status = 0;
++
++              list_for_each_entry(t, &m->transfers, transfer_list) {
++
++                      if (!t->tx_buf && !t->rx_buf && t->len) {
++                              status = -EINVAL;
++                              break;
++                      }
++
++                      if (t->len) {
++                              if (!m->is_dma_mapped) {
++                                      t->rx_dma = 0;
++                                      t->tx_dma = 0;
++                              }
++                              if (t->bits_per_word <= 8)
++                                      status = ep93xx_txrx_8(spi, t);
++                              else
++                                      status = ep93xx_txrx_16(spi, t);
++                      }
++
++                      if (status != t->len) {
++                              if (status > 0)
++                                      status = -EMSGSIZE;
++                              break;
++                      }
++                      m->actual_length += status;
++                      status = 0;
++
++                      /* protocol tweaks before next transfer */
++                      if (t->delay_usecs)
++                              udelay(t->delay_usecs);
++
++                      if (t->transfer_list.next == &m->transfers)
++                              break;
++              }
++
++              m->status = status;
++              m->complete(m->context);
++
++              spin_lock_irqsave(&drv_data->lock, flags);
++      }
++      drv_data->busy = 0;
++      spin_unlock_irqrestore(&drv_data->lock, flags);
++}
++
++static irqreturn_t ssp_int(int irq, void *dev_id)
++{
++      struct driver_data *drv_data = dev_id;
++      u8 status;
++      status = read_SSPIIR(drv_data->ioaddr);
++
++      if (status & SSPIIR_RORIS) {
++              dev_err(&drv_data->pdev->dev, "SPI rx overrun.\n");
++
++              /* We clear the overrun here ! */
++              write_SSPICR(0, drv_data->ioaddr);
++      }
++
++      /* RX interrupt */
++      if (status & SSPIIR_RIS)
++              dev_info(&drv_data->pdev->dev, "SPI RX interrupt\n");
++
++      /* TX interrupt */
++      if (status & SSPIIR_TIS)
++              dev_info(&drv_data->pdev->dev, "SPI TX interrupt\n");
++
++      write_SSPICR(0, drv_data->ioaddr);
++      return IRQ_HANDLED;
++}
++
++static int __init ep93xx_spi_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct spi_master *master;
++      struct driver_data *drv_data = 0;
++      struct resource *memory_resource;
++      int status = 0;
++      u16 val;
++
++      /* Allocate master with space for drv_data and null dma buffer */
++      master = spi_alloc_master(dev, sizeof(struct driver_data));
++      if (!master) {
++              dev_err(&pdev->dev, "cannot alloc spi_master\n");
++              return -ENOMEM;
++      }
++      drv_data = spi_master_get_devdata(master);
++      drv_data->master = master;
++      drv_data->pdev = pdev;
++
++        master->num_chipselect = EP93XX_GPIO_LINE_H(7) + 1;
++      master->bus_num = pdev->id;
++      master->setup = ep93xx_spi_setup;
++      master->transfer = ep93xx_spi_transfer;
++
++      spin_lock_init(&drv_data->lock);
++      INIT_LIST_HEAD(&drv_data->queue);
++
++      /* Setup register addresses */
++      memory_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!memory_resource) {
++          dev_err(&pdev->dev, "memory resources not defined\n");
++          status = -EIO;
++          goto out_error_master_alloc;
++      } else {
++          drv_data->ioaddr = ioremap(memory_resource->start,
++                              memory_resource->end - memory_resource->start);
++          if (drv_data->ioaddr == NULL) {
++                  dev_err(&pdev->dev, "ioremap failed\n");
++                  status = -EIO;
++                  goto out_error_master_alloc;
++          }
++      }
++
++      /* Attach to IRQ */
++      drv_data->irq = platform_get_irq(pdev, 0);
++      if (drv_data->irq < 0)
++              return drv_data->irq;
++
++      if (drv_data->irq <= 0) {
++              dev_err(&pdev->dev, "IRQ resource not defined\n");
++              status = -ENODEV;
++              goto out_error_master_alloc;
++      }
++
++      status = request_irq(drv_data->irq, ssp_int, 0, "ep93xx-spi", drv_data);
++      if (status < 0) {
++              dev_err(&pdev->dev, "cannot get SPI IRQ 0\n");
++              goto out_error_master_alloc;
++      }
++
++      /* SSP default configuration, enable */
++      write_SSPCR1(SSPC1_SSE, drv_data->ioaddr);
++
++      /* run as master */
++      val = read_SSPCR1(drv_data->ioaddr);
++      val = val & ~SSPC1_MS;
++      write_SSPCR1(val, drv_data->ioaddr);
++
++      /* frame format to Motorola SPI Format */
++      val = read_SSPCR0(drv_data->ioaddr);
++      val = val & ~SSPCR0_FRF_MASK ;
++      val = val | SSPCR0_FRF_MOTOROLA;
++      write_SSPCR0(val, drv_data->ioaddr);
++
++      /* enable interrupts */
++      val = read_SSPCR1(drv_data->ioaddr);
++      /* for now only overrun is handled */
++      /* val = val | SSPC1_RIE | SSPC1_TIE | SSPC1_RORIE; */
++      val = val | SSPC1_RORIE;
++      write_SSPCR1(val, drv_data->ioaddr);
++
++      /* SSP default configuration, re enable */
++      val = read_SSPCR1(drv_data->ioaddr);
++      val = val & ~SSPC1_SSE;
++      write_SSPCR1(val, drv_data->ioaddr);
++      val = read_SSPCR1(drv_data->ioaddr);
++      val = val | SSPC1_SSE;
++      write_SSPCR1(val, drv_data->ioaddr);
++
++      /* Register with the SPI framework */
++      platform_set_drvdata(pdev, drv_data);
++      status = spi_register_master(master);
++      if (status != 0) {
++              dev_err(&pdev->dev, "cannot register SPI master\n");
++              goto out_error_master_alloc;
++      } else
++              dev_info(&pdev->dev, "SPI Controller initalized\n");
++
++      INIT_WORK(&drv_data->work, ep93xx_work);
++      spin_lock_init(&drv_data->lock);
++      INIT_LIST_HEAD(&drv_data->queue);
++
++      /* this task is the only thing to touch the SPI bits */
++      drv_data->busy = 0;
++      drv_data->workqueue = create_singlethread_workqueue(
++              dev_name(drv_data->master->dev.parent));
++      if (drv_data->workqueue == NULL) {
++              status = -EBUSY;
++              goto out_error_free_irq;
++      }
++
++      return status;
++
++out_error_free_irq:
++      free_irq(drv_data->irq, master);
++out_error_master_alloc:
++      if (drv_data->ioaddr != NULL)
++              iounmap(drv_data->ioaddr);
++      spi_master_put(master);
++      return status;
++}
++
++static int __exit ep93xx_spi_remove(struct platform_device *pdev)
++{
++      struct driver_data *drv_data = platform_get_drvdata(pdev);
++      u8 val;
++
++      WARN_ON(!list_empty(&drv_data->queue));
++
++      destroy_workqueue(drv_data->workqueue);
++
++      /* switch off SSP*/
++      val = read_SSPCR1(drv_data->ioaddr);
++      val = val & ~SSPC1_SSE;
++      write_SSPCR1(val, drv_data->ioaddr);
++
++      /* release irqs */
++      if (drv_data->irq > 0)
++              free_irq(drv_data->irq, drv_data);
++
++      /* Disconnect from the SPI framework */
++      spi_unregister_master(drv_data->master);
++      spi_master_put(drv_data->master);
++
++      if (drv_data->ioaddr != NULL)
++              iounmap(drv_data->ioaddr);
++
++      /* Prevent double remove */
++      platform_set_drvdata(pdev, NULL);
++      return 0;
++}
++
++#ifdef CONFIG_PM
++static int ep93xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
++{
++      return 0;
++}
++
++static int ep93xx_spi_resume(struct platform_device *pdev)
++{
++      return 0;
++}
++
++#else
++#define ep93xx_spi_suspend NULL
++#define ep93xx_spi_resume  NULL
++#endif
++
++struct platform_driver ep93xx_spi_device = {
++      .remove         = __exit_p(ep93xx_spi_remove),
++#ifdef CONFIG_PM
++      .suspend        = ep93xx_spi_suspend,
++      .resume         = ep93xx_spi_resume,
++#endif
++      .driver         = {
++              .name   = "ep93xx-spi",
++              .bus    = &spi_bus_type,
++              .owner  = THIS_MODULE,
++      },
++};
++
++int __init ep93xx_spi_init(void)
++{
++      return platform_driver_probe(&ep93xx_spi_device, ep93xx_spi_probe);
++}
++
++void __exit ep93xx_spi_exit(void)
++{
++      platform_driver_unregister(&ep93xx_spi_device);
++}
++
++module_init(ep93xx_spi_init);
++module_exit(ep93xx_spi_exit);
++
++MODULE_DESCRIPTION("EP93XX SPI Driver");
++MODULE_AUTHOR("Manfred Gruber, <m.gruber@tirol.com>");
++MODULE_LICENSE("GPL");
diff --git a/recipes/linux/linux-2.6.32/ep93xx/ep93xx-touchscreen.patch b/recipes/linux/linux-2.6.32/ep93xx/ep93xx-touchscreen.patch
new file mode 100644 (file)
index 0000000..b7e209c
--- /dev/null
@@ -0,0 +1,1320 @@
+---
+ arch/arm/mach-ep93xx/include/mach/hardware.h   |    1 
+ arch/arm/mach-ep93xx/include/mach/regs_touch.h |   95 ++
+ drivers/input/touchscreen/Kconfig              |    5 
+ drivers/input/touchscreen/Makefile             |    1 
+ drivers/input/touchscreen/ep93xx_ts.c          | 1117 +++++++++++++++++++++++++
+ drivers/input/touchscreen/ep93xx_ts.h          |   53 +
+ 6 files changed, 1272 insertions(+)
+
+--- linux-2.6.32.orig/arch/arm/mach-ep93xx/include/mach/hardware.h
++++ linux-2.6.32/arch/arm/mach-ep93xx/include/mach/hardware.h
+@@ -6,10 +6,11 @@
+ #include <mach/ep93xx-regs.h>
+ #include <mach/platform.h>
+ #define pcibios_assign_all_busses()   0
++#include "regs_touch.h"
+ /*
+  * The EP93xx has two external crystal oscillators.  To generate the
+  * required high-frequency clocks, the processor uses two phase-locked-
+  * loops (PLLs) to multiply the incoming external clock signal to much
+--- /dev/null
++++ linux-2.6.32/arch/arm/mach-ep93xx/include/mach/regs_touch.h
+@@ -0,0 +1,95 @@
++/*=============================================================================
++ *
++ *  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_ */
+--- linux-2.6.32.orig/drivers/input/touchscreen/Kconfig
++++ linux-2.6.32/drivers/input/touchscreen/Kconfig
+@@ -528,6 +528,11 @@ config TOUCHSCREEN_PCAP
+         Say Y here if you have a Motorola EZX telephone and
+         want to enable support for the built-in touchscreen.
+         To compile this driver as a module, choose M here: the
+         module will be called pcap_ts.
++
++config TOUCHSCREEN_EP93XX
++      tristate "EP93xx Touchscreen"
++      depends on ARM && INPUT && ARCH_EP93XX
++
+ endif
+--- linux-2.6.32.orig/drivers/input/touchscreen/Makefile
++++ linux-2.6.32/drivers/input/touchscreen/Makefile
+@@ -40,5 +40,6 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713)       +
+ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL)        += atmel-wm97xx.o
+ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)    += mainstone-wm97xx.o
+ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)     += zylonite-wm97xx.o
+ obj-$(CONFIG_TOUCHSCREEN_W90X900)     += w90p910_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_PCAP)                += pcap_ts.o
++obj-$(CONFIG_TOUCHSCREEN_EP93XX)      += ep93xx_ts.o
+--- /dev/null
++++ linux-2.6.32/drivers/input/touchscreen/ep93xx_ts.c
+@@ -0,0 +1,1117 @@
++/*
++ *  linux/drivers/input/touchscreen/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/wait.h>
++#include <linux/fs.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <linux/compiler.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <linux/syscalls.h>
++#include <linux/input.h>
++#include <asm/irq.h>
++#include <mach/hardware.h>
++#include <asm/io.h>
++
++#define TOUCH_OFFSET            0x100000
++#define TOUCH_BASE              (EP93XX_APB_VIRT_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.             */
++
++//
++// 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 0xFE0 //C00
++#define   TS_LIGHT_INV_PRESSURE 0xFFF //e00
++
++//
++// 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_XY_CHANGE 0x300
++#define   TS_MAX_VALID_PRESSURE_CHANGE  0x100
++
++//
++// 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.
++ */
++/* #define UART_HACK_DEBUG 1 */
++#if 0
++#ifdef UART_HACK_DEBUG
++static char szBuf[256];
++void UARTWriteString(char * msg);
++#define DPRINTK( x... )   \
++    sprintf( szBuf, ##x ); \
++    UARTWriteString( szBuf );
++#else
++static char szBuf[256];
++#define DPRINTK( x... )  \
++    sprintf( szBuf, ##x ); \
++    printk( szBuf );
++#endif
++#endif // 0
++#define DPRINTK( x... )
++
++//-----------------------------------------------------------------------------
++// A few more macros...
++//-----------------------------------------------------------------------------
++#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)
++
++//
++// For now, we use one of the minor numbers from the local/experimental
++// range.
++//
++#define EP93XX_TS_MINOR 240
++
++//-----------------------------------------------------------------------------
++// Static Declarations
++//-----------------------------------------------------------------------------
++static unsigned int   guiLastX, guiLastY;
++static unsigned int   guiLastInvPressure;
++
++struct TouchScreenSample
++{
++    int     currentX;
++    int     currentY;
++    int     currentButton;
++    int     currentPressure;
++    struct timeval currentTime;
++};
++
++//
++// This must match the structure in tslib.
++//
++struct ts_sample {
++    int     x;
++    int     y;
++    unsigned int    pressure;
++    struct timeval  tv;
++};
++
++
++static struct TouchScreenSample gSample;
++
++// static int currentX, currentY, currentButton;
++// static int gPressure;
++// static struct timeval  gtime;
++
++static int bFreshTouchData;
++static int bCurrentPenDown;
++
++
++
++static DECLARE_WAIT_QUEUE_HEAD(queue);
++static DECLARE_MUTEX(open_sem);
++static spinlock_t event_buffer_lock = SPIN_LOCK_UNLOCKED;
++static struct fasync_struct *ep93xx_fasync;
++
++//-----------------------------------------------------------------------------
++// Typedef Declarations
++//-----------------------------------------------------------------------------
++typedef enum {
++    TS_MODE_UN_INITIALIZED,
++    TS_MODE_HARDWARE_SCAN,
++    TS_MODE_SOFT_SCAN
++} ts_mode_t;
++
++static ts_mode_t      gScanningMode;
++
++typedef enum{
++    TS_STATE_STOPPED = 0,
++    TS_STATE_Z1,
++    TS_STATE_Z2,
++    TS_STATE_Y,
++    TS_STATE_X,
++    TS_STATE_DONE
++} ts_states_t;
++
++typedef struct
++{
++    unsigned int   uiX;
++    unsigned int   uiY;
++    unsigned int   uiZ1;
++    unsigned int   uiZ2;
++    ts_states_t    state;
++} ts_struct_t;
++
++static ts_struct_t sTouch;
++
++/*
++ * From the spec, here's how to set up the touch screen's switch registers.
++ */
++typedef struct
++{
++    unsigned int uiDetect;
++    unsigned int uiDischarge;
++    unsigned int uiXSample;
++    unsigned int uiYSample;
++    unsigned int uiSwitchZ1;
++    unsigned int uiSwitchZ2;
++}SwitchStructType;
++
++//
++// 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 SwitchStructType sSwitchSettings =
++/*     s28en=0
++ *   TSDetect    TSDischarge  TSXSample  TSYSample    SwitchZ1   SwitchZ2
++ */
++    {0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608};
++
++
++//-----------------------------------------------------------------------------
++// Function Declarations
++//-----------------------------------------------------------------------------
++static void ep93xx_ts_set_direct( unsigned int uiADCSwitch );
++static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id);
++static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id);
++static void ee93xx_ts_evt_add( int button, int dX, int dY, int Pressure );
++static ssize_t ep93xx_ts_read(struct file *filp, char *buf,
++        size_t count, loff_t *l);
++static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait);
++static int ep93xx_ts_open(struct inode *inode, struct file *filp);
++static int ep93xx_ts_fasync(int fd, struct file *filp, int on);
++static int ep93xx_ts_release(struct inode *inode, struct file *filp);
++static ssize_t ep93xx_ts_write(struct file *file, const char *buffer,
++                size_t count, loff_t *ppos);
++static void ep93xx_ts_setup(void);
++static void ep93xx_ts_shutdown(void);
++int __init ep93xx_ts_init(void);
++void __exit ep93xx_ts_exit(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(void);
++static void Set_Timer2_uSec( unsigned int Delay_mSec );
++static void Stop_Timer2(void);
++
++
++
++//-----------------------------------------------------------------------------
++//  Debug stuff...
++//-----------------------------------------------------------------------------
++
++#ifdef UART_HACK_DEBUG
++
++// This "array" is a cheap-n-easy way of getting access to the UART registers.
++static unsigned int * const pDebugUART=(unsigned int *)IO_ADDRESS(UART1_BASE);
++//static unsigned int * const pDebugUART=(unsigned int *)IO_ADDRESS(UART3_BASE);
++static int bUartInitialized = 0;
++
++void SendChar(char value)
++{
++    // wait for Tx fifo full flag to clear.
++    while (pDebugUART[0x18>>2] & 0x20);
++
++    // send a char to the uart
++    pDebugUART[0] = value;
++}
++
++void UARTWriteString(char * msg)
++{
++    int index = 0;
++    unsigned int uiTemp;
++
++    //if((pDebugUART[0x14>>2] & 0x1) == 0)
++    if( bUartInitialized == 0 )
++    {
++        uiTemp = inl(EP93XX_SYSCON_DEVCFG);
++        uiTemp |= EP93XX_SYSCON_DEVCFG_U1E;
++        //uiTemp |= EP93XX_SYSCON_DEVCFG_U3E;
++        SysconSetLocked(EP93XX_SYSCON_DEVCFG, uiTemp);
++        pDebugUART[0x10>>2] = 0xf;
++        pDebugUART[0xc>>2] = 0;
++        pDebugUART[0x8>>2] = 0x70;
++        pDebugUART[0x14>>2] = 0x1;
++        bUartInitialized = 1;
++    }
++    while (msg[index] != 0)
++    {
++        if (msg[index] == '\n')
++        {
++            SendChar('\r');
++            SendChar('\n');
++        }
++        else
++        {
++            SendChar(msg[index]);
++        }
++        index++;
++    }
++}
++#endif // UART_HACK_DEBUG
++
++/*
++ *  ep93xx_ts_isr
++ */
++static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id)
++{
++    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);
++}
++
++/*
++ * Save the current ts 'event' in an atomic fashion.
++ */
++static void ee93xx_ts_evt_add( int buttons, int iX, int iY, int iPressure )
++{
++#ifdef PRINT_CALIBRATION_FACTORS
++    if( iX > iMaxX ) iMaxX = iX;
++    if( iX < iMinX ) iMinX = iX;
++    if( iY > iMaxY ) iMaxY = iY;
++    if( iY < iMinY ) iMinY = iY;
++#endif
++
++
++    // printk("ee93xx_ts_evt_add\n");
++    //DPRINTK("cb\n");
++    /*
++     * Note the event, but use spinlocks to keep it from getting
++     * halfway read if we get interrupted.
++     */
++
++    spin_lock(&event_buffer_lock);
++    gSample.currentX        = iX;
++    gSample.currentY        = iY;
++    gSample.currentButton   = buttons;
++    gSample.currentPressure = iPressure;
++    bFreshTouchData         = 1;
++    do_gettimeofday(&gSample.currentTime);
++
++
++    spin_unlock(&event_buffer_lock);
++
++    kill_fasync(&ep93xx_fasync, SIGIO, POLL_IN);
++    wake_up_interruptible(&queue);
++
++}
++
++
++static ssize_t ep93xx_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
++{
++
++    unsigned short data[3];
++    struct  ts_sample   ts_data;
++    int     iReturn = -EFAULT;
++    // printk("ep93xx_ts_read\n");
++
++#ifdef PRINT_CALIBRATION_FACTORS
++    static int lala=0;
++    if( bFreshTouchData && (lala++ > 9) )
++    {
++        DPRINTK("%4d, %4d - range [%4d to %4d],[%4d to %4d]\n",
++            f, currentY, iMinX, iMaxX, iMinY, iMaxY );
++        lala = 0;
++    }
++#endif
++    if( !bFreshTouchData)
++    {
++        iReturn = 0;
++    }
++    else if( (count == sizeof(data)) )
++    {
++        spin_lock_irq(&event_buffer_lock);
++        bFreshTouchData = 0;
++        data[0] = gSample.currentX;
++        data[1] = gSample.currentY;
++        data[2] = gSample.currentButton;
++
++        spin_unlock_irq(&event_buffer_lock);
++
++        if (copy_to_user(buf, data, sizeof data))
++            return -EFAULT;
++
++        count -= sizeof(data);
++
++        /* return the # of bytes that got read */
++        iReturn = sizeof(data) ;
++    }
++    else if (count == sizeof(struct ts_sample) )
++    {
++        spin_lock_irq(&event_buffer_lock);
++        bFreshTouchData = 0;
++        ts_data.x           = gSample.currentX;
++        ts_data.y           = gSample.currentY;
++        ts_data.pressure    = gSample.currentPressure;
++        ts_data.tv          = gSample.currentTime;
++        spin_unlock_irq(&event_buffer_lock);
++
++        if (copy_to_user(buf, &ts_data, sizeof(struct ts_sample)))
++        {
++            iReturn = -EFAULT;
++        }
++        else
++        {
++            count -= sizeof(ts_data);
++            iReturn = sizeof(ts_data);
++        }
++
++    }
++
++    return iReturn;
++}
++
++static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait)
++{
++    // printk("ep93xx_ts_poll\n");
++    poll_wait(filp, &queue, wait);
++
++    if( bFreshTouchData )
++    {
++        return POLLIN | POLLRDNORM;
++    }
++
++    return 0;
++}
++
++static int ep93xx_ts_open(struct inode *inode, struct file *filp)
++{
++     printk("ep93xx_ts_open");
++
++    if( down_trylock(&open_sem) )
++    {
++        return -EBUSY;
++    }
++
++    ep93xx_ts_setup();
++
++    return 0;
++}
++
++/*
++ * Asynchronous I/O support.
++ */
++static int ep93xx_ts_fasync(int fd, struct file *filp, int on)
++{
++    int retval;
++
++    retval = fasync_helper(fd, filp, on, &ep93xx_fasync);
++    if (retval < 0)
++    {
++        return retval;
++    }
++
++    return 0;
++}
++
++static int ep93xx_ts_release(struct inode *inode, struct file *filp)
++{
++    Stop_Timer2();
++
++    /*
++     * Call our async I/O support to request that this file
++     * cease to be used for async I/O.
++     */
++    ep93xx_ts_fasync(-1, filp, 0);
++
++    ep93xx_ts_shutdown();
++
++    up(&open_sem);
++
++    return 0;
++}
++
++static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, size_t count,
++               loff_t *ppos)
++{
++    return -EINVAL;
++}
++
++
++static int ep93xx_ts_ioctl(struct inode *inode, struct file *file, uint command, ulong u)
++{
++    static const int         version = EV_VERSION;
++    static const u_int32_t   bit =(1 << EV_ABS);
++    static const u_int32_t   absbit = (1 << ABS_X) | (1 << ABS_Y) | (1 << ABS_PRESSURE);
++    int         iReturn ;
++    int         i = 0;
++
++    switch(command)
++    {
++        case EVIOCGVERSION:
++            DPRINTK("ep93xx_ts_ioctl command = EVIOCGVERSION\r\n");
++            i = copy_to_user((void __user *)u, (void *)version, sizeof(version));
++            iReturn = i ? -EFAULT : 0;
++            break;
++
++        case EVIOCGBIT(0,sizeof(u_int32_t) * 8) :
++            DPRINTK("ep93xx_ts_ioctl command = EVIOCGBIT(0,sizeof(uint32) * 8)\r\n");
++            i = copy_to_user((void __user *)u, (void *)bit, sizeof(bit));
++            iReturn = i ? -EFAULT : 0;
++            break;
++
++        case EVIOCGBIT(EV_ABS, sizeof(absbit) * 8):
++            DPRINTK("ep93xx_ts_ioctl command = EVIOCGBIT(0,sizeof(uint32) * 8)\r\n");
++            copy_to_user((void __user *)u, (void *)absbit, sizeof(absbit));
++            iReturn = i ? -EFAULT : 0;
++            break;
++        default:
++            DPRINTK(" ep93xx_ts_ioctl unknown command = %d\n",u);
++            iReturn = -1;
++            break;
++    }
++
++    return iReturn;
++}
++
++static struct file_operations ep93xx_ts_fops = {
++    owner:      THIS_MODULE,
++    read:       ep93xx_ts_read,
++    write:      ep93xx_ts_write,
++    poll:       ep93xx_ts_poll,
++    open:       ep93xx_ts_open,
++    ioctl:      ep93xx_ts_ioctl,
++    release:    ep93xx_ts_release,
++    fasync:     ep93xx_ts_fasync,
++};
++
++static struct miscdevice ep93xx_ts_miscdev =
++{
++        EP93XX_TS_MINOR,
++        "ep93xx_ts",
++        &ep93xx_ts_fops
++};
++
++void ep93xx_ts_setup(void)
++{
++    unsigned int uiKTDIV, uiTSXYMaxMin;
++    // printk("ep93xx_hw_setup\n");
++
++    /*
++     * Set the TSEN bit in KTDIV so that we are enabling the clock
++     * for the touchscreen.
++     */
++    uiKTDIV = inl(SYSCON_KTDIV);
++    uiKTDIV |= SYSCON_KTDIV_TSEN;
++    SysconSetLocked( SYSCON_KTDIV, uiKTDIV );
++
++    //
++    // Program the TSSetup and TSSetup2 registers.
++    //
++    outl( TSSETUP_DEFAULT, TSSetup );
++    outl( TSSETUP2_DEFAULT, TSSetup2 );
++
++    //
++    // Set the the touch settings.
++    //
++    outl( 0xaa, TSSWLock );
++    outl( sSwitchSettings.uiDischarge, TSDirect );
++
++    outl( 0xaa, TSSWLock );
++    outl( sSwitchSettings.uiDischarge, TSDischarge );
++
++    outl( 0xaa, TSSWLock );
++    outl( sSwitchSettings.uiSwitchZ1, TSXSample );
++
++    outl( 0xaa, TSSWLock );
++    outl( sSwitchSettings.uiSwitchZ2, TSYSample );
++
++    outl( 0xaa, TSSWLock );
++    outl( 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;
++    outl( uiTSXYMaxMin, TSXYMaxMin );
++
++    bCurrentPenDown = 0;
++    bFreshTouchData = 0;
++    guiLastX = 0;
++    guiLastY = 0;
++    guiLastInvPressure = 0xffffff;
++
++    //
++    // Enable the touch screen scanning engine.
++    //
++    TS_Hardware_Scan_Mode();
++}
++
++/*
++ * ep93xx_ts_shutdown
++ *
++ */
++static void
++ep93xx_ts_shutdown(void)
++{
++    unsigned int uiKTDIV;
++
++    DPRINTK("ep93xx_ts_shutdown\n");
++
++    sTouch.state = TS_STATE_STOPPED;
++    Stop_Timer2();
++
++    /*
++     * Disable the scanning engine.
++     */
++    outl( 0, TSSetup );
++    outl( 0, TSSetup2 );
++
++    /*
++     * Clear the TSEN bit in KTDIV so that we are disabling the clock
++     * for the touchscreen.
++     */
++    uiKTDIV = inl(SYSCON_KTDIV);
++    uiKTDIV &= ~SYSCON_KTDIV_TSEN;
++    SysconSetLocked( SYSCON_KTDIV, uiKTDIV );
++
++} /* ep93xx_ts_shutdown */
++
++static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id)
++{
++    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 );
++
++            outl( 0xaa, TSSWLock );
++            outl( sSwitchSettings.uiDischarge, TSDirect );
++
++            sTouch.state = TS_STATE_DONE;
++
++            /*
++             * Process this set of ADC readings.
++             */
++            ProcessPointData();
++
++            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.
++    //
++    outl( 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(void)
++{
++    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;
++                ee93xx_ts_evt_add( 0, guiLastX, guiLastY, 0 );
++        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;
++            ee93xx_ts_evt_add( 1, sTouch.uiX, sTouch.uiY, (0x7000000 /uiInvPressure) );
++        }
++
++        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.
++    //
++    outl( 0xaa, TSSWLock );
++    outl( uiADCSwitch, TSDirect );
++
++    //
++    // Read and throw away the first sample.
++    //
++    do {
++        uiResult = inl(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 = inl(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 = inl( EP93XX_SYSCON_DEVCFG );
++    SysconSetLocked( EP93XX_SYSCON_DEVCFG, (uiDevCfg & ~EP93XX_SYSCON_DEVCFG_TIN) );
++
++    //
++    // Enable the touch screen scanning state machine by setting
++    // the ENABLE bit.
++    //
++    outl( (TSSETUP_DEFAULT | TSSETUP_ENABLE), TSSetup );
++
++    //
++    // Set the flag to show that we are in interrupt mode.
++    //
++    gScanningMode = TS_MODE_HARDWARE_SCAN;
++
++    //
++    // Initialize TSSetup2 register.
++    //
++    outl( TSSETUP2_DEFAULT, TSSetup2 );
++
++}
++
++//****************************************************************************
++// TS_Soft_Scan_Mode
++//****************************************************************************
++// Sets 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.
++        //
++        outl( TSSETUP_DEFAULT, TSSetup );
++
++        //
++        // Set the TIN bit so we can do manual touchscreen polling.
++        //
++        uiDevCfg = inl(EP93XX_SYSCON_DEVCFG );
++        SysconSetLocked( EP93XX_SYSCON_DEVCFG, (uiDevCfg | EP93XX_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
++     */
++    outl( 0, TIMER2CONTROL );
++
++    uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000;
++    outl( uiClockTicks, TIMER2LOAD );
++    outl( uiClockTicks, TIMER2VALUE );
++
++    /*
++     * Set up Timer 2 for 508 kHz clock and periodic mode.
++     */
++    outl( 0xC8, TIMER2CONTROL );
++
++}
++
++static void Stop_Timer2(void)
++{
++    outl( 0, TIMER2CONTROL );
++}
++
++/*
++ * Initialization and exit routines
++ */
++int __init ep93xx_ts_init(void)
++{
++    int retval;
++
++    //printk("ep93xx_ts_init\n");
++
++    // printk("request Touchscreen interrupt.\n");
++    retval = request_irq( IRQ_EP93XX_TOUCH, ep93xx_ts_isr, IRQF_DISABLED, "ep93xx_ts", 0);
++    if( retval )
++    {
++        printk(KERN_WARNING "ep93xx_ts: failed to get touchscreen IRQ\n");
++        return retval;
++    }
++
++    // printk("Request Timer interrupt.\n");
++    retval = request_irq( IRQ_EP93XX_TIMER2, ep93xx_timer2_isr,
++                        IRQF_DISABLED, "ep93xx_timer2", 0);
++    if( retval )
++    {
++        printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n");
++        return retval;
++    }
++
++    // printk("Register Touchscreen Driver\n");
++    misc_register(&ep93xx_ts_miscdev);
++
++    sTouch.state = TS_STATE_STOPPED;
++    gScanningMode = TS_MODE_UN_INITIALIZED;
++
++    printk(KERN_NOTICE "ep93xx touchscreen driver configured for 4-wire operation\n");
++
++    return 0;
++}
++void __exit
++ep93xx_ts_exit(void)
++{
++    DPRINTK("ep93xx_ts_exit\n");
++
++    Stop_Timer2();
++
++    free_irq(IRQ_EP93XX_TOUCH, 0);
++    free_irq(IRQ_EP93XX_TIMER2, 0);
++
++    misc_deregister(&ep93xx_ts_miscdev);
++}
++
++module_init(ep93xx_ts_init);
++module_exit(ep93xx_ts_exit);
++
++MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver");
++MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx");
+--- /dev/null
++++ linux-2.6.32/drivers/input/touchscreen/ep93xx_ts.h
+@@ -0,0 +1,53 @@
++/*
++ * ep93xx_ts.h
++ *
++ * The contents of this file are subject to the Mozilla Public License
++ * Version 1.1 (the "License"); you may not use this file except in
++ * compliance with the License. You may obtain a copy of the License
++ * at http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS"
++ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
++ * the License for the specific language governing rights and
++ * limitations under the License.
++ *
++ * The initial developer of the original code is David A. Hinds
++ * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
++ * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
++ *
++ * Alternatively, the contents of this file may be used under the
++ * terms of the GNU General Public License version 2 (the "GPL"), in
++ * which case the provisions of the GPL are applicable instead of the
++ * above.  If you wish to allow the use of your version of this file
++ * only under the terms of the GPL and not to allow others to use
++ * your version of this file under the MPL, indicate your decision by
++ * deleting the provisions above and replace them with the notice and
++ * other provisions required by the GPL.  If you do not delete the
++ * provisions above, a recipient may use your version of this file
++ * under either the MPL or the GPL.
++ */
++
++#ifndef _LINUX_EP93XX_TS_H
++#define _LINUX_EP93XX_TS_H
++
++/*touchscreen register defines*/
++#define SYSCON_KTDIV  EP93XX_SYSCON_KEY_TOUCH_CLOCK_DIV
++#define SYSCON_SWLOCK EP93XX_SYSCON_SWLOCK
++#define TSSetup       EP93XX_TOUCHSCREEN_TSSetup
++#define TSXYMaxMin    EP93XX_TOUCHSCREEN_TSXYMaxMin
++#define TSXYResult    EP93XX_TOUCHSCREEN_TSDischarge
++#define TSDischarge   EP93XX_TOUCHSCREEN_TSDischarge
++#define TSXSample     EP93XX_TOUCHSCREEN_TSXSample
++#define TSYSample     EP93XX_TOUCHSCREEN_TSYSample
++#define TSDirect      EP93XX_TOUCHSCREEN_TSDirect
++#define TSDetect      EP93XX_TOUCHSCREEN_TSDetect
++#define TSSWLock      EP93XX_TOUCHSCREEN_TSSWLock
++#define TSSetup2      EP93XX_TOUCHSCREEN_TSSetup2
++
++
++//#define SYSCON_DEVCFG       EP93XX_SYSCON_DEVICE_CONFIG
++#define TIMER2CONTROL EP93XX_TIMER2_CONTROL
++#define TIMER2LOAD    EP93XX_TIMER2_LOAD
++#define TIMER2VALUE   EP93XX_TIMER2_VALUE
++#define TIMER2CLEAR   EP93XX_TIMER2_CLEAR
++#endif
diff --git a/recipes/linux/linux-2.6.32/ep93xx/series b/recipes/linux/linux-2.6.32/ep93xx/series
new file mode 100644 (file)
index 0000000..0ae7785
--- /dev/null
@@ -0,0 +1,7 @@
+edb9301-fix-machine-id.patch -p1
+simone-board-def.patch -p1
+ep93xx-regs.patch -p1
+ep93xx-i2c.patch -p1
+ep93xx-touchscreen.patch
+ep93xx-spi.patch -p1
+ep93xx-cpuinfo.patch -p1
diff --git a/recipes/linux/linux-2.6.32/ep93xx/simone-board-def.patch b/recipes/linux/linux-2.6.32/ep93xx/simone-board-def.patch
new file mode 100644 (file)
index 0000000..463a73b
--- /dev/null
@@ -0,0 +1,1653 @@
+---
+ arch/arm/configs/simone_defconfig  | 1380 +++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-ep93xx/Kconfig       |    7 
+ arch/arm/mach-ep93xx/Makefile      |    1 
+ arch/arm/mach-ep93xx/Makefile.boot |    2 
+ arch/arm/mach-ep93xx/simone.c      |  217 +++++
+ 5 files changed, 1607 insertions(+)
+
+--- /dev/null
++++ linux-2.6.32/arch/arm/configs/simone_defconfig
+@@ -0,0 +1,1380 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24.7
++# Tue May 12 17:49:25 2009
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++# CONFIG_GENERIC_GPIO is not set
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++CONFIG_IOSCHED_DEADLINE=y
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++CONFIG_DEFAULT_DEADLINE=y
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="deadline"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# 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_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 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_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Cirrus EP93xx Implementation Options
++#
++CONFIG_CRUNCH=y
++
++#
++# EP93xx Platforms
++#
++# CONFIG_MACH_ADSSPHERE is not set
++# CONFIG_MACH_EDB9302 is not set
++# CONFIG_MACH_EDB9302A is not set
++# CONFIG_MACH_EDB9307 is not set
++# CONFIG_MACH_EDB9312 is not set
++# CONFIG_MACH_EDB9315 is not set
++# CONFIG_MACH_EDB9315A is not set
++# CONFIG_MACH_GESBC9312 is not set
++# CONFIG_MACH_MICRO9 is not set
++# CONFIG_MACH_MICRO9H is not set
++# CONFIG_MACH_MICRO9M is not set
++# CONFIG_MACH_MICRO9L is not set
++CONFIG_MACH_SIM_ONE=y
++# CONFIG_MACH_TS72XX is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4T=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
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=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
++# CONFIG_OUTER_CACHE is not set
++CONFIG_ARM_VIC=y
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++CONFIG_PREEMPT=y
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=100
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttyAM0,115200 root=/dev/ram"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC 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
++CONFIG_SUSPEND_UP_POSSIBLE=y
++
++#
++# 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_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++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_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=y
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET6_XFRM_MODE_BEET is not set
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++# CONFIG_IPV6_SIT is not set
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC 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_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++CONFIG_CFG80211=y
++CONFIG_NL80211=y
++CONFIG_WIRELESS_EXT=y
++CONFIG_MAC80211=m
++CONFIG_MAC80211_RCSIMPLE=y
++# CONFIG_MAC80211_DEBUG is not set
++CONFIG_IEEE80211=m
++# CONFIG_IEEE80211_DEBUG is not set
++CONFIG_IEEE80211_CRYPT_WEP=m
++CONFIG_IEEE80211_CRYPT_CCMP=m
++CONFIG_IEEE80211_CRYPT_TKIP=m
++# CONFIG_IEEE80211_SOFTMAC is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++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_BLKDEVS=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
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS 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 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_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++CONFIG_MTD_CFI_STAA=y
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# 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=0x0
++CONFIG_MTD_PHYSMAP_LEN=0x0
++CONFIG_MTD_PHYSMAP_BANKWIDTH=1
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM 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
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=y
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_EEPROM_93CX6=m
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++# 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
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETH=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++CONFIG_WLAN_80211=y
++# CONFIG_LIBERTAS is not set
++# CONFIG_USB_ZD1201 is not set
++CONFIG_RTL8187=m
++# CONFIG_HOSTAP is not set
++# CONFIG_B43 is not set
++# CONFIG_B43LEGACY is not set
++# CONFIG_RT2X00 is not set
++
++#
++# USB Network Adapters
++#
++CONFIG_USB_CATC=y
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++CONFIG_USB_RTL8150=y
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++CONFIG_PPP=m
++# CONFIG_PPP_MULTILINK is not set
++# CONFIG_PPP_FILTER is not set
++# CONFIG_PPP_ASYNC is not set
++CONFIG_PPP_SYNC_TTY=m
++# CONFIG_PPP_DEFLATE is not set
++CONFIG_PPP_BSDCOMP=m
++# CONFIG_PPP_MPPE is not set
++CONFIG_PPPOE=m
++# CONFIG_PPPOL2TP is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=m
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# 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_STOWAWAY is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++# CONFIG_MOUSE_PS2_LOGIPS2PP is not set
++# CONFIG_MOUSE_PS2_SYNAPTICS is not set
++# CONFIG_MOUSE_PS2_LIFEBOOK is not set
++# CONFIG_MOUSE_PS2_TRACKPOINT is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_ADS7846 is not set
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# 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_PENMOUNT is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++# CONFIG_SERIO_SERPORT 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_VT_HW_CONSOLE_BINDING 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=y
++CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=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_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++CONFIG_SENSORS_DS1337=y
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 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_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 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
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_EP93XX=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++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
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_EP93XX_MONO is not set
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++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 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++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=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_PCM_OSS_PLUGINS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++CONFIG_SND_AC97_CODEC=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++CONFIG_SND_EP93XX_AC97=y
++CONFIG_SND_EP93XX_PCM=y
++# CONFIG_SND_ARMAACI is not set
++
++#
++# SPI devices
++#
++
++#
++# USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_CAIAQ is not set
++
++#
++# System on Chip audio support
++#
++# CONFIG_SND_SOC is not set
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=y
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++CONFIG_USB_DYNAMIC_MINORS=y
++# 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_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++CONFIG_USB_ACM=m
++CONFIG_USB_PRINTER=m
++
++#
++# 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
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++CONFIG_USB_SERIAL=y
++CONFIG_USB_SERIAL_CONSOLE=y
++# CONFIG_USB_SERIAL_GENERIC is not set
++# CONFIG_USB_SERIAL_AIRCABLE is not set
++# CONFIG_USB_SERIAL_AIRPRIME is not set
++# CONFIG_USB_SERIAL_ARK3116 is not set
++# CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_CH341 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_FUNSOFT 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_MOS7720 is not set
++# CONFIG_USB_SERIAL_MOS7840 is not set
++# CONFIG_USB_SERIAL_NAVMAN is not set
++CONFIG_USB_SERIAL_PL2303=y
++# CONFIG_USB_SERIAL_OTI6858 is not set
++# CONFIG_USB_SERIAL_HP4X is not set
++# CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_SIERRAWIRELESS 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_OPTION is not set
++# CONFIG_USB_SERIAL_OMNINET is not set
++# CONFIG_USB_SERIAL_DEBUG is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX 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_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++# CONFIG_MMC_ARMMMCI is not set
++CONFIG_MMC_SPI=y
++#
++# SimOne LCD support
++#
++CONFIG_LCD_LINUX=m
++CONFIG_LCD_HD44780=m
++#
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_EP93XX=y
++CONFIG_RTC_DRV_EP93XX_DS1337=y
++# CONFIG_RTC_DRV_PL031 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_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++# CONFIG_EXT3_FS_XATTR is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++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_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++CONFIG_ROMFS_FS=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++CONFIG_AUTOFS4_FS=y
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++# CONFIG_ZISOFS is not set
++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_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# 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_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++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
++CONFIG_NETWORK_FILESYSTEMS=y
++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_SUNRPC_BIND34 is not set
++# 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_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++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
++# CONFIG_DLM is not set
++# CONFIG_INSTRUMENTATION is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++# CONFIG_ENABLE_MUST_CHECK is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++# 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_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=m
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++CONFIG_CRYPTO_AES=y
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++CONFIG_CRYPTO_ARC4=y
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++CONFIG_CRYPTO_MICHAEL_MIC=y
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++CONFIG_CRC_ITU_T=y
++CONFIG_CRC32=y
++CONFIG_CRC7=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+--- linux-2.6.32.orig/arch/arm/mach-ep93xx/Kconfig
++++ linux-2.6.32/arch/arm/mach-ep93xx/Kconfig
+@@ -166,10 +166,17 @@ config MACH_TS72XX
+       depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+       help
+         Say 'Y' here if you want your kernel to support the
+         Technologic Systems TS-72xx board.
++config MACH_SIM_ONE
++      bool "Support SIM.ONE board "
++      depends on EP93XX_SDCE0_PHYS_OFFSET
++      help
++        Say 'Y' here if you want your kernel to support the
++        Simplemachines SIM.ONE board.
++
+ choice
+       prompt "Select a UART for early kernel messages"
+ config EP93XX_EARLY_UART1
+       bool "UART1"
+--- linux-2.6.32.orig/arch/arm/mach-ep93xx/Makefile
++++ linux-2.6.32/arch/arm/mach-ep93xx/Makefile
+@@ -8,6 +8,7 @@ obj-                   :=
+ obj-$(CONFIG_MACH_ADSSPHERE)  += adssphere.o
+ obj-$(CONFIG_MACH_EDB93XX)    += edb93xx.o
+ obj-$(CONFIG_MACH_GESBC9312)  += gesbc9312.o
+ obj-$(CONFIG_MACH_MICRO9)     += micro9.o
++obj-$(CONFIG_MACH_SIM_ONE)    += simone.o
+ obj-$(CONFIG_MACH_TS72XX)     += ts72xx.o
+--- linux-2.6.32.orig/arch/arm/mach-ep93xx/Makefile.boot
++++ linux-2.6.32/arch/arm/mach-ep93xx/Makefile.boot
+@@ -1,7 +1,9 @@
+    zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)   := 0x00008000
+ params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)   := 0x00000100
++   zreladdr-$(CONFIG_MACH_SIM_ONE)    := 0xc0008000
++params_phys-$(CONFIG_MACH_SIM_ONE)    := 0xc0000100
+    zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)                := 0xc0008000
+ params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)                := 0xc0000100
+    zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)                := 0xd0008000
+--- /dev/null
++++ linux-2.6.32/arch/arm/mach-ep93xx/simone.c
+@@ -0,0 +1,217 @@
++/*
++ * arch/arm/mach-ep93xx/simone.c
++ * Simplemachines SIM.ONE support.
++ *
++ * Copyright (C) 2009 Simplemachines
++ * MMC support by Peter Ivanov <ivanovp@gmail.com>, 2007
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/mmc_spi.h>
++#include <linux/mmc/host.h>
++#include <linux/jiffies.h>
++#include <linux/irq.h>
++
++#include <asm/io.h>
++#include <mach/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/gpio.h>
++
++static struct physmap_flash_data simone_flash_data = {
++      .width          = 2,
++};
++
++static struct resource simone_flash_resource = {
++      .start          = 0x60000000,
++      .end            = 0x60000000+ SZ_8M - 1,
++      .flags          = IORESOURCE_MEM,
++};
++
++static struct platform_device simone_flash = {
++      .name           = "physmap-flash",
++      .id             = 0,
++      .dev            = {
++              .platform_data  = &simone_flash_data,
++      },
++      .num_resources  = 1,
++      .resource       = &simone_flash_resource,
++};
++
++
++static struct resource ep93xx_ac97_resources[] = {
++      [0] = {
++                .start          = EP93XX_AC97_PHY_BASE,
++                .end            = EP93XX_AC97_PHY_BASE + 0x6C,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++                .start          = NO_IRQ,
++                .end            = NO_IRQ,
++                .flags          = IORESOURCE_IRQ,
++        },
++};
++
++static u64 ep93xx_ac97_dma_mask = 0xffffffffUL;
++
++static struct platform_device ep93xx_ac97_device = {
++        .name           = "ep93xx-ac97",
++        .id             = 0,
++        .num_resources  = 2,
++        .resource       = ep93xx_ac97_resources,
++        .dev = {
++                .dma_mask               = &ep93xx_ac97_dma_mask,
++                .coherent_dma_mask      = 0xffffffffUL,
++        },
++};
++
++
++#ifdef CONFIG_SPI
++static struct resource ep93xx_spi_resources[] = {
++      [0] = {
++              .start  = EP93XX_SPI_BASE_PHYS,
++              .end    = EP93XX_SPI_BASE_PHYS + 0x0fff,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = IRQ_EP93XX_SSP,
++              .end    = IRQ_EP93XX_SSP,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device ep93xx_spi_device = {
++      .name           = "ep93xx-spi",
++      .id             = 0,
++      .resource       = ep93xx_spi_resources,
++      .num_resources  = ARRAY_SIZE(ep93xx_spi_resources),
++};
++
++
++#define EP93XX_MMC_SPI_CARD_PRESENT   EP93XX_GPIO_LINE_A(0)
++
++/*
++ * Initializes SPI system to communicate with MMC/SD card
++ */
++int ep93xx_mmc_spi_init (struct device *pdev, irqreturn_t (*card_det_irq_handler)(int, void *),
++              void *mmc)
++{
++      int rv;
++
++      rv = gpio_request(EP93XX_MMC_SPI_CARD_PRESENT, "ep93xx-mmc-spi");
++      if (rv) {
++              dev_info(pdev, "failed to request MMC/SD gpio pin\n");
++              return rv;
++      }
++
++      gpio_direction_input (EP93XX_MMC_SPI_CARD_PRESENT);
++
++      if ((rv = request_irq (gpio_to_irq( EP93XX_MMC_SPI_CARD_PRESENT),
++                                      card_det_irq_handler,
++                                      IRQF_DISABLED | IRQ_TYPE_EDGE_FALLING, /* flags */
++                                      "ep93xx-mmc-spi",       /* devname */
++                                      mmc                     /* void *devid */
++                            )) == 0)
++      {
++              dev_info (pdev, "MMC/SD card detection IRQ %i assigned.\n",
++                              gpio_to_irq(EP93XX_MMC_SPI_CARD_PRESENT));
++      }
++      else
++      {
++              dev_err (pdev, "Cannot assign MMC/SD card detection IRQ (%i)!\n",
++                              gpio_to_irq(EP93XX_MMC_SPI_CARD_PRESENT));
++              return rv;
++      }
++      return 0;
++}
++
++void ep93xx_mmc_spi_exit (struct device *pdev, void *mmc)
++{
++      free_irq (EP93XX_MMC_SPI_CARD_PRESENT, mmc);
++}
++
++static struct mmc_spi_platform_data ep93xx_spi_pdata = {
++      .init = &ep93xx_mmc_spi_init,
++      .exit = &ep93xx_mmc_spi_exit,
++      .get_ro = NULL,
++      .detect_delay = 500,                    /* card detection delay in msec */
++      .ocr_mask = MMC_VDD_33_34,
++};
++
++static struct spi_board_info ep93xx_spi_board_info[] __initdata = {
++      {
++              .modalias = "mmc_spi",
++              .max_speed_hz = 7.4E6,                          /* max spi clock (SCK) speed in HZ */
++              .bus_num = 0,
++              .chip_select = 0,
++              .platform_data = (void*) &ep93xx_spi_pdata,
++              .controller_data = NULL,
++              .mode = SPI_MODE_0,
++      }
++};
++#endif
++static struct ep93xx_eth_data ep93xx_eth_data = {
++      .dev_addr       = { 0x00, 0xba, 0xd0, 0x0b, 0xad, 0x00 },
++};
++
++static struct resource ep93xx_eth_resource[] = {
++      {
++              .start  = EP93XX_ETHERNET_PHYS_BASE,
++              .end    = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = IRQ_EP93XX_ETHERNET,
++              .end    = IRQ_EP93XX_ETHERNET,
++              .flags  = IORESOURCE_IRQ,
++      }
++};
++
++static struct platform_device ep93xx_eth_device = {
++      .name           = "ep93xx-eth",
++      .id             = -1,
++      .dev            = {
++              .platform_data  = &ep93xx_eth_data,
++      },
++      .num_resources  = ARRAY_SIZE(ep93xx_eth_resource),
++      .resource       = ep93xx_eth_resource,
++};
++
++static void __init simone_init_machine(void)
++{
++      ep93xx_init_devices();
++        /* Switch off the LCD backlight*/
++      gpio_request(EP93XX_GPIO_LINE_B(5), "lcd");
++        gpio_direction_output (EP93XX_GPIO_LINE_B(5), 0);
++      platform_device_register(&simone_flash);
++        platform_device_register(&ep93xx_ac97_device);
++      platform_device_register(&ep93xx_eth_device);
++#if defined(CONFIG_SPI_EP93XX) || defined(CONFIG_SPI_EP93XX_MODULE)
++      dev_set_name(&ep93xx_spi_device.dev, "apb:spi");
++      platform_device_register(&ep93xx_spi_device);
++      spi_register_board_info(ep93xx_spi_board_info,ARRAY_SIZE(ep93xx_spi_board_info));
++#endif
++}
++
++MACHINE_START(SIM_ONE, "Simplemachine SimONE Board")
++      /* Maintainer: Nuccio Raciti Simplemachine <nuccio.raciti@gmail.com>*/
++      .phys_io        = EP93XX_APB_PHYS_BASE,
++      .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
++      .boot_params    = 0x00000100,
++      .map_io         = ep93xx_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .timer          = &ep93xx_timer,
++      .init_machine   = simone_init_machine,
++MACHINE_END
diff --git a/recipes/linux/linux/simone/defconfig b/recipes/linux/linux/simone/defconfig
new file mode 100644 (file)
index 0000000..72e6c48
--- /dev/null
@@ -0,0 +1,1751 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32
+# Thu Dec  3 18:28:09 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_SLOW_WORK=y
+# CONFIG_SLOW_WORK_DEBUG is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+
+#
+# Cirrus EP93xx Implementation Options
+#
+CONFIG_CRUNCH=y
+
+#
+# EP93xx Platforms
+#
+# CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET is not set
+CONFIG_EP93XX_SDCE0_PHYS_OFFSET=y
+# CONFIG_EP93XX_SDCE1_PHYS_OFFSET is not set
+# CONFIG_EP93XX_SDCE2_PHYS_OFFSET is not set
+# CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET is not set
+CONFIG_MACH_EDB93XX=y
+CONFIG_MACH_EDB9302A=y
+CONFIG_MACH_EDB9307A=y
+CONFIG_MACH_EDB9315A=y
+CONFIG_MACH_SIM_ONE=y
+CONFIG_EP93XX_EARLY_UART1=y
+# CONFIG_EP93XX_EARLY_UART2 is not set
+# CONFIG_EP93XX_EARLY_UART3 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4T=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=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
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_APM_EMULATION=y
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+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_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+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_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+# CONFIG_BT_HIDP is not set
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_LIB80211=m
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS 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 is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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 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_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+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_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM 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
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+CONFIG_ATA_OVER_ETH=m
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+CONFIG_EP93XX_PWM=m
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# 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=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETH=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_USB_ZD1201=m
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# 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=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_DM9601=m
+# CONFIG_USB_NET_SMSC95XX is not set
+# CONFIG_USB_NET_GL620A is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_APMPOWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_EP93XX is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+CONFIG_TOUCHSCREEN_EP93XX=y
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=m
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AMBA_PL010=y
+CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
+# CONFIG_SERIAL_AMBA_PL011 is not set
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_TSL2550 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
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_EP93XX=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_PL022 is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_PL061 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+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_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_FB_EP93XX=y
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+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_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
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP210X is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT 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_IUU 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_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL 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_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+CONFIG_MMC_SPI=y
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_EP93XX=y
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING 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_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=y
+# CONFIG_FSCACHE_STATS is not set
+# CONFIG_FSCACHE_HISTOGRAM is not set
+# CONFIG_FSCACHE_DEBUG is not set
+# CONFIG_FSCACHE_OBJECT_LIST is not set
+# CONFIG_CACHEFILES is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# 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_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_FSCACHE is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+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=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL 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_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf-8"
+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=y
+# 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=y
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+# 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=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
index a196506..7f2ef0a 100644 (file)
@@ -1,13 +1,26 @@
 require linux.inc
 
+PR = "r1"
+
 S = "${WORKDIR}/linux-${PV}"
 
 # Mark archs/machines that this kernel supports
 DEFAULT_PREFERENCE = "-1"
-
+DEFAULT_PREFERENCE_simone = "1"
 
 SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-${PV}.tar.bz2;name=kernel \
            file://defconfig"
 
 SRC_URI[kernel.md5sum] = "260551284ac224c3a43c4adac7df4879"
 SRC_URI[kernel.sha256sum] = "5099786d80b8407d98a619df00209c2353517f22d804fdd9533b362adcb4504e"
+
+# part of 2.6.24.7 patchset from Sim.One project
+# other patches needs work
+SRC_URI_append_simone = " \
+                       file://ep93xx/edb9301-fix-machine-id.patch;patch=1 \
+                       file://ep93xx/simone-board-def.patch;patch=1 \
+                       file://ep93xx/ep93xx-regs.patch;patch=1 \
+                       file://ep93xx/ep93xx-i2c.patch;patch=1 \
+                       file://ep93xx/ep93xx-touchscreen.patch;patch=1 \
+                       file://ep93xx/ep93xx-spi.patch;patch=1 \
+                       file://ep93xx/ep93xx-cpuinfo.patch;patch=1 "