aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch')
-rw-r--r--target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch3622
1 files changed, 0 insertions, 3622 deletions
diff --git a/target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch b/target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch
deleted file mode 100644
index 3664132021..0000000000
--- a/target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch
+++ /dev/null
@@ -1,3622 +0,0 @@
---- /dev/null
-+++ b/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
-+++ b/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_