NET: sa11x0-ir: convert sa11x0-ir driver to use DMA engine API

Convert the sa11x0 IrDA driver to use the sa11x0 DMA engine driver
rather than our own platform specific DMA API.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index e535137..4680478 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -356,7 +356,7 @@
 
 config SA1100_FIR
 	tristate "SA1100 Internal IR"
-	depends on ARCH_SA1100 && IRDA
+	depends on ARCH_SA1100 && IRDA && DMA_SA11X0
 
 config VIA_FIR
 	tristate "VIA VT8231/VT1211 SIR/MIR/FIR"
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 9c748f3..620a48d 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -30,12 +30,13 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/sa11x0-dma.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/wrapper.h>
 #include <net/irda/irda_device.h>
 
-#include <mach/dma.h>
 #include <mach/hardware.h>
 #include <asm/mach/irda.h>
 
@@ -47,7 +48,8 @@
 	struct device		*dev;
 	struct sk_buff		*skb;
 	struct scatterlist	sg;
-	dma_regs_t		*regs;
+	struct dma_chan		*chan;
+	dma_cookie_t		cookie;
 };
 
 struct sa1100_irda {
@@ -79,6 +81,75 @@
 
 #define HPSIR_MAX_RXLEN		2047
 
+static struct dma_slave_config sa1100_irda_fir_rx = {
+	.direction	= DMA_FROM_DEVICE,
+	.src_addr	= __PREG(Ser2HSDR),
+	.src_addr_width	= DMA_SLAVE_BUSWIDTH_1_BYTE,
+	.src_maxburst	= 8,
+};
+
+static struct dma_slave_config sa1100_irda_fir_tx = {
+	.direction	= DMA_TO_DEVICE,
+	.dst_addr	= __PREG(Ser2HSDR),
+	.dst_addr_width	= DMA_SLAVE_BUSWIDTH_1_BYTE,
+	.dst_maxburst	= 8,
+};
+
+static unsigned sa1100_irda_dma_xferred(struct sa1100_buf *buf)
+{
+	struct dma_chan *chan = buf->chan;
+	struct dma_tx_state state;
+	enum dma_status status;
+
+	status = chan->device->device_tx_status(chan, buf->cookie, &state);
+	if (status != DMA_PAUSED)
+		return 0;
+
+	return sg_dma_len(&buf->sg) - state.residue;
+}
+
+static int sa1100_irda_dma_request(struct device *dev, struct sa1100_buf *buf,
+	const char *name, struct dma_slave_config *cfg)
+{
+	dma_cap_mask_t m;
+	int ret;
+
+	dma_cap_zero(m);
+	dma_cap_set(DMA_SLAVE, m);
+
+	buf->chan = dma_request_channel(m, sa11x0_dma_filter_fn, (void *)name);
+	if (!buf->chan) {
+		dev_err(dev, "unable to request DMA channel for %s\n",
+			name);
+		return -ENOENT;
+	}
+
+	ret = dmaengine_slave_config(buf->chan, cfg);
+	if (ret)
+		dev_warn(dev, "DMA slave_config for %s returned %d\n",
+			name, ret);
+
+	buf->dev = buf->chan->device->dev;
+
+	return 0;
+}
+
+static void sa1100_irda_dma_start(struct sa1100_buf *buf,
+	enum dma_transfer_direction dir, dma_async_tx_callback cb, void *cb_p)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *chan = buf->chan;
+
+	desc = chan->device->device_prep_slave_sg(chan, &buf->sg, 1, dir,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (desc) {
+		desc->callback = cb;
+		desc->callback_param = cb_p;
+		buf->cookie = dmaengine_submit(desc);
+		dma_async_issue_pending(chan);
+	}
+}
+
 /*
  * Allocate and map the receive buffer, unless it is already allocated.
  */
@@ -127,9 +198,9 @@
 	/*
 	 * Enable the DMA, receiver and receive interrupt.
 	 */
-	sa1100_clear_dma(si->dma_rx.regs);
-	sa1100_start_dma(si->dma_rx.regs, sg_dma_address(&si->dma_rx.sg),
-			 sg_dma_len(&si->dma_rx.sg));
+	dmaengine_terminate_all(si->dma_rx.chan);
+	sa1100_irda_dma_start(&si->dma_rx, DMA_DEV_TO_MEM, NULL, NULL);
+
 	Ser2HSCR0 = HSCR0_HSSP | HSCR0_RXE;
 }
 
@@ -326,8 +397,7 @@
 		return NETDEV_TX_OK;
 	}
 
-	sa1100_start_dma(si->dma_tx.regs, sg_dma_address(&si->dma_tx.sg),
-			 sg_dma_len(&si->dma_tx.sg));
+	sa1100_irda_dma_start(&si->dma_tx, DMA_MEM_TO_DEV, sa1100_irda_firtxdma_irq, dev);
 
 	/*
 	 * If we have a mean turn-around time, impose the specified
@@ -345,7 +415,6 @@
 static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev)
 {
 	struct sk_buff *skb = si->dma_rx.skb;
-	dma_addr_t dma_addr;
 	unsigned int len, stat, data;
 
 	if (!skb) {
@@ -356,8 +425,7 @@
 	/*
 	 * Get the current data position.
 	 */
-	dma_addr = sa1100_get_dma_pos(si->dma_rx.regs);
-	len = dma_addr - sg_dma_address(&si->dma_rx.sg);
+	len = sa1100_irda_dma_xferred(&si->dma_rx);
 	if (len > HPSIR_MAX_RXLEN)
 		len = HPSIR_MAX_RXLEN;
 	dma_unmap_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE);
@@ -421,7 +489,7 @@
 	/*
 	 * Stop RX DMA
 	 */
-	sa1100_stop_dma(si->dma_rx.regs);
+	dmaengine_pause(si->dma_rx.chan);
 
 	/*
 	 * Framing error - we throw away the packet completely.
@@ -476,11 +544,9 @@
 	case 57600:	case 115200:
 		brd = 3686400 / (16 * speed) - 1;
 
-		/*
-		 * Stop the receive DMA.
-		 */
+		/* Stop the receive DMA, and configure transmit. */
 		if (IS_FIR(si))
-			sa1100_stop_dma(si->dma_rx.regs);
+			dmaengine_terminate_all(si->dma_rx.chan);
 
 		local_irq_save(flags);
 
@@ -698,8 +764,8 @@
 	/*
 	 * Stop all DMA activity.
 	 */
-	sa1100_stop_dma(si->dma_rx.regs);
-	sa1100_stop_dma(si->dma_tx.regs);
+	dmaengine_terminate_all(si->dma_rx.chan);
+	dmaengine_terminate_all(si->dma_tx.chan);
 
 	/* Disable the port. */
 	Ser2UTCR3 = 0;
@@ -716,20 +782,16 @@
 
 	si->speed = 9600;
 
-	err = sa1100_request_dma(DMA_Ser2HSSPRd, "IrDA receive",
-				 NULL, NULL, &si->dma_rx.regs);
+	err = sa1100_irda_dma_request(si->dev, &si->dma_rx, "Ser2ICPRc",
+				&sa1100_irda_fir_rx);
 	if (err)
 		goto err_rx_dma;
 
-	err = sa1100_request_dma(DMA_Ser2HSSPWr, "IrDA transmit",
-				 sa1100_irda_firtxdma_irq, dev,
-				 &si->dma_tx.regs);
+	err = sa1100_irda_dma_request(si->dev, &si->dma_tx, "Ser2ICPTr",
+				&sa1100_irda_sir_tx);
 	if (err)
 		goto err_tx_dma;
 
-	si->dma_rx.dev = si->dev;
-	si->dma_tx.dev = si->dev;
-
 	/*
 	 * Setup the serial port for the specified speed.
 	 */
@@ -764,9 +826,9 @@
 	si->open = 0;
 	sa1100_irda_shutdown(si);
 err_startup:
-	sa1100_free_dma(si->dma_tx.regs);
+	dma_release_channel(si->dma_tx.chan);
 err_tx_dma:
-	sa1100_free_dma(si->dma_rx.regs);
+	dma_release_channel(si->dma_rx.chan);
 err_rx_dma:
 	return err;
 }
@@ -810,8 +872,8 @@
 	/*
 	 * Free resources
 	 */
-	sa1100_free_dma(si->dma_tx.regs);
-	sa1100_free_dma(si->dma_rx.regs);
+	dma_release_channel(si->dma_tx.chan);
+	dma_release_channel(si->dma_rx.chan);
 	free_irq(dev->irq, dev);
 
 	sa1100_set_power(si, 0);