Index: linux-2.6.33/drivers/dma/Kconfig
===================================================================
--- linux-2.6.33.orig/drivers/dma/Kconfig
+++ linux-2.6.33/drivers/dma/Kconfig
@@ -20,6 +20,37 @@ comment "DMA Devices"
 config ASYNC_TX_DISABLE_CHANNEL_SWITCH
 	bool
 
+config INTEL_LNW_DMAC1
+	bool "Intel MID DMA support for LPE DMA"
+	depends on PCI && X86 && (SND_INTEL_SST||SND_INTEL_LPE)
+	select DMA_ENGINE
+	help
+	  Enable support for the Intel(R) MID DMA1 engine present
+	  in Intel MID chipsets.
+
+	  Say Y here if you have such a chipset.
+
+	  If unsure, say N.
+
+config INTEL_LNW_DMAC2
+	bool "Intel MID DMA support for SC DMA"
+	depends on PCI && X86
+	select DMA_ENGINE
+	help
+	  Enable support for the Intel(R) MID DMA2 engine present
+	  in Intel MID chipsets.
+
+	  Say Y here if you have such a chipset.
+
+	  If unsure, say N.
+
+config LNW_DMA_DEBUG
+	bool "LNW DMA Debugging Enable"
+	depends on INTEL_LNW_DMAC1 || INTEL_LNW_DMAC2
+	default N
+	help
+	  Enable logging in the LNW DMA drivers
+
 config INTEL_IOATDMA
 	tristate "Intel I/OAT DMA support"
 	depends on PCI && X86
Index: linux-2.6.33/drivers/dma/Makefile
===================================================================
--- linux-2.6.33.orig/drivers/dma/Makefile
+++ linux-2.6.33/drivers/dma/Makefile
@@ -1,5 +1,7 @@
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
+obj-$(CONFIG_INTEL_LNW_DMAC2) += lnw_dmac2.o
+obj-$(CONFIG_INTEL_LNW_DMAC1) += lnw_dmac1.o
 obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
Index: linux-2.6.33/drivers/dma/lnw_dma_regs.h
===================================================================
--- /dev/null
+++ linux-2.6.33/drivers/dma/lnw_dma_regs.h
@@ -0,0 +1,176 @@
+/*
+ *  lnw_dma.c - Intel Langwell DMA Drivers
+ *
+ *  Copyright (C) 2008-09 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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; version 2 of the License.
+ *
+ *  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 __LNW_DMA_REGS_H__
+#define __LNW_DMA_REGS_H__
+
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/pci_ids.h>
+
+#define LNW_DMA_DRIVER_VERSION "0.3.1"
+
+#define DMA_DEBUG
+
+#define	REG_BIT0 		0x00000001
+#define	REG_BIT8 		0x00000100
+
+#define UNMASK_INTR_REG(chan_num) \
+	((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num))
+#define MASK_INTR_REG(chan_num) (REG_BIT8 << chan_num)
+
+#define ENABLE_CHANNEL(chan_num) \
+	((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num))
+
+#define DESCS_PER_CHANNEL 	16
+/*DMA Registers*/
+/*registers associated with channel programming*/
+#define DMA_REG_SIZE 		0x400
+#define DMA_CH_SIZE		0x58
+
+/*CH X REG = (DMA_CH_SIZE)*CH_NO + REG*/
+#define SAR			0x00 /* Source Address Register*/
+#define DAR			0x08 /* Destination Address Register*/
+#define CTL_LOW  		0x18 /* Control Register*/
+#define CTL_HIGH		0x1C /* Control Register*/
+#define CFG_LOW 		0x40 /* Configuration Register Low*/
+#define CFG_HIGH		0x44 /* Configuration Register high*/
+
+#define STATUS_TFR		0x2E8
+#define STATUS_BLOCK 		0x2F0
+#define STATUS_ERR		0x308
+
+#define RAW_TFR 		0x2C0
+#define RAW_BLOCK		0x2C8
+#define RAW_ERR   		0x2E0
+
+#define MASK_TFR		0x310
+#define MASK_BLOCK		0x318
+#define MASK_SRC_TRAN  		0x320
+#define MASK_DST_TRAN  		0x328
+#define MASK_ERR		0x330
+
+#define CLEAR_TFR		0x338
+#define CLEAR_BLOCK		0x340
+#define CLEAR_SRC_TRAN  	0x348
+#define CLEAR_DST_TRAN  	0x350
+#define CLEAR_ERR		0x358
+
+#define INTR_STATUS		0x360
+#define DMA_CFG    		0x398
+#define DMA_CHAN_EN		0x3A0
+
+/**
+ * struct lnw_dma_chan - internal representation of a DMA channel
+ */
+struct lnw_dma_chan {
+	struct dma_chan  	chan;
+	void __iomem		*ch_regs;
+	void __iomem		*dma_base;
+	int			ch_id;
+	spinlock_t		lock;
+	dma_cookie_t		completed;
+	struct list_head	active_list;
+	struct list_head	queue;
+	struct list_head	free_list;
+	struct lnw_dma_slave	*slave;
+	unsigned int		descs_allocated;
+	struct lnwdma_device	*dma;
+	bool			in_use;
+};
+static inline struct lnw_dma_chan *to_lnw_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct lnw_dma_chan, chan);
+}
+
+/**
+ * struct lnwdma_device - internal representation of a DMA device
+ * @pdev: PCI device
+ * @dma_base: MMIO register space base address of DMA
+ * @lpe_base: MMIO register space base address of LPE
+ * @dma_pool: for allocating DMA descriptors
+ * @common: embedded struct dma_device
+ * @idx: per channel data
+ */
+struct lnwdma_device {
+	struct pci_dev  	*pdev;
+	void __iomem		*dma_base;
+	struct pci_pool 	*dma_pool;
+	struct dma_device 	common;
+	struct tasklet_struct   tasklet;
+	struct lnw_dma_chan 	ch[MAX_CHAN];
+};
+
+static inline struct lnwdma_device *to_lnwdma_device(struct dma_device *common)
+{
+	return container_of(common, struct lnwdma_device, common);
+}
+
+struct lnw_dma_desc {
+	void __iomem			*block; /*ch ptr*/
+	struct list_head		desc_node;
+	struct dma_async_tx_descriptor	txd;
+	size_t				len;
+	dma_addr_t			sar;
+	dma_addr_t			dar;
+	u32				cfg_hi;
+	u32				cfg_lo;
+	u32				ctl_lo;
+	u32				ctl_hi;
+	dma_addr_t			next;
+	enum dma_data_direction  	dirn;
+	enum dma_status  		status;
+	dma_async_tx_callback   	callback;
+	void 				*callback_param;
+	enum lnw_dma_width		width; /*width of DMA txn*/
+	enum lnw_dma_mode		cfg_mode; /*mode configuration*/
+
+};
+
+static inline int test_ch_en(void __iomem *dma, u32 ch_no)
+{
+	u32 en_reg = ioread32(dma + DMA_CHAN_EN);
+	return (en_reg >> ch_no) & 0x1;
+}
+
+static inline struct lnw_dma_desc *to_lnw_dma_desc
+		(struct dma_async_tx_descriptor *txd)
+{
+	return container_of(txd, struct lnw_dma_desc, txd);
+}
+
+#define _dma_printk(level, format, arg...)  \
+	printk(level "LNW_DMA: %s %d " format, __func__, __LINE__, ## arg)
+
+#ifdef CONFIG_LNW_DMA_DEBUG
+#define dma_dbg(format, arg...) _dma_printk(KERN_DEBUG, "DBG " format , ## arg)
+#else
+#define dma_dbg(format, arg...) do {} while (0);
+#endif
+
+#define dma_err(format, arg...) _dma_printk(KERN_ERR, "ERR " format , ## arg)
+#define dma_info(format, arg...) \
+	_dma_printk(KERN_INFO , "INFO " format , ## arg)
+
+#endif /*__LNW_DMA_REGS_H__*/
Index: linux-2.6.33/drivers/dma/lnw_dmac1.c
===================================================================
--- /dev/null
+++ linux-2.6.33/drivers/dma/lnw_dmac1.c
@@ -0,0 +1,957 @@
+/*
+ *  lnw_dmac1.c - Intel Langwell DMA Drivers
+ *
+ *  Copyright (C) 2008-09 Intel Corp
+ *  Authhor: Vinod Koul <vinod.koul@intel.com>
+ *  The driver design is based on dw_dmac driver
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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; version 2 of the License.
+ *
+ *  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/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <sound/intel_lpe.h>
+#include <linux/lnw_dma.h>
+
+#define MAX_CHAN 	2
+#include "lnw_dma_regs.h"
+
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_DESCRIPTION("Intel (R) Moorestown Langwell DMAC1 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(LNW_DMA_DRIVER_VERSION);
+
+#define DMA_CH0		6
+#define DMA_CH1		7
+#define CH_BLOCK_SIZE	4095
+
+static int __devinit lnw_dma1_probe(struct pci_dev *pdev,
+				const struct pci_device_id *id);
+static void __devexit lnw_dma1_remove(struct pci_dev *pdev);
+static void enable_dma1_interrupt(struct lnw_dma_chan *lnwc);
+static void disable_dma1_interrupt(struct lnw_dma_chan *lnwc);
+
+struct lnw_device {
+	struct pci_dev		*pdev;
+	void __iomem		*dma_base;
+	struct lnwdma_device	*dma;
+};
+
+/*CH dep code, if ch no's mapping changes only change here*/
+static int get_ch_id(int index)
+{
+	if (index == 0)
+		return DMA_CH0;
+	else if (index == 1)
+		return DMA_CH1;
+	else
+		return -1;
+}
+
+static int get_ch_index(int ch_id)
+{
+	if (ch_id == DMA_CH0)
+		return 0;
+	if (ch_id == DMA_CH1)
+		return 1;
+	else
+		return -1;
+}
+
+static int get_ch_num(int *status)
+{
+	if (*status & (1 << DMA_CH0)) {
+		*status = *status & (~(1 << DMA_CH0));
+		return DMA_CH0;
+	} else if (*status & (1 << DMA_CH1)) {
+		*status = *status & (~(1 << DMA_CH1));
+		return DMA_CH1;
+	} else
+		return -1;
+}
+
+static int get_block_ts(int len, int tx_width)
+{
+	int byte_width = 0, block_ts = 0;
+
+	switch (tx_width) {
+	case LNW_DMA_WIDTH_8BIT:
+		byte_width = 1;
+		break;
+	case LNW_DMA_WIDTH_16BIT:
+		byte_width = 2;
+		break;
+	case LNW_DMA_WIDTH_32BIT:
+	default:
+		byte_width = 4;
+		break;
+	}
+
+	block_ts = len/byte_width;
+	if (block_ts > CH_BLOCK_SIZE)
+		block_ts = 0xFFFF;
+	return block_ts;
+}
+
+static struct lnw_dma_desc *lnwc_desc_get1(struct lnw_dma_chan *lnwc)
+{
+	struct lnw_dma_desc *desc, *_desc;
+	struct lnw_dma_desc *ret = NULL;
+
+	dma_dbg("called \n");
+	spin_lock_bh(&lnwc->lock);
+	list_for_each_entry_safe(desc, _desc, &lnwc->free_list, desc_node) {
+		if (async_tx_test_ack(&desc->txd)) {
+			list_del(&desc->desc_node);
+			ret = desc;
+			dma_dbg("got free desc \n");
+			break;
+		}
+	}
+	spin_unlock_bh(&lnwc->lock);
+	return ret;
+}
+
+
+static void lnwc_desc_put1(struct lnw_dma_chan *lnwc, struct lnw_dma_desc *desc)
+{
+	if (desc) {
+		spin_lock_bh(&lnwc->lock);
+		list_add_tail(&desc->desc_node, &lnwc->free_list);
+		spin_unlock_bh(&lnwc->lock);
+	}
+}
+
+/* Called with dwc->lock held and bh disabled */
+static void lnwc_dostart1(struct lnw_dma_chan *lnwc, struct lnw_dma_desc *first)
+{
+	struct lnwdma_device *lnw = to_lnwdma_device(lnwc->chan.device);
+
+	dma_dbg("called \n");
+	/* ASSERT:  channel is idle */
+	if (lnwc->in_use && test_ch_en(lnwc->dma_base, lnwc->ch_id)) {
+		/*error*/
+		dma_err("channel is busy \n");
+		/* The tasklet will hopefully advance the queue... */
+		return;
+	}
+
+	/*write registers and en*/
+	iowrite32(first->sar, lnwc->ch_regs + SAR);
+	iowrite32(first->dar, lnwc->ch_regs + DAR);
+	iowrite32(first->cfg_hi, lnwc->ch_regs + CFG_HIGH);
+	iowrite32(first->cfg_lo, lnwc->ch_regs + CFG_LOW);
+	iowrite32(first->ctl_lo, lnwc->ch_regs + CTL_LOW);
+	iowrite32(first->ctl_hi, lnwc->ch_regs + CTL_HIGH);
+	dma_dbg("TX SAR %lx, DAR %lx, CFGL %x, CFGH %x, CTLH %x, CTLL %x \n",
+		first->sar, first->dar, first->cfg_hi,
+		first->cfg_lo, first->ctl_hi, first->ctl_lo);
+
+	iowrite32(ENABLE_CHANNEL(lnwc->ch_id), lnw->dma_base + DMA_CHAN_EN);
+	first->status = DMA_IN_PROGRESS;
+}
+
+static void
+lnwc_descriptor_complete1(struct lnw_dma_chan *lnwc, struct lnw_dma_desc *desc)
+{
+	struct dma_async_tx_descriptor	*txd = &desc->txd;
+	dma_async_tx_callback callback = NULL;
+	dma_async_tx_callback callback_txd = NULL;
+	void *param = NULL;
+	void *param_txd = NULL;
+	u32 sar, dar, len;
+	union lnw_dma_ctl_hi ctl_hi;
+
+	dma_dbg("called \n");
+
+	/*check if full tx is complete or not*/
+	sar = ioread32(lnwc->ch_regs + SAR);
+	dar = ioread32(lnwc->ch_regs + DAR);
+
+	if (desc->dirn == DMA_FROM_DEVICE)
+		len = dar - desc->dar;
+	else
+		len = sar - desc->sar;
+
+	dma_dbg("SAR %x DAR %x, DMA done: %x \n", sar, dar, len);
+	if (desc->len > len) {
+		dma_dbg("dirn = %d\n", desc->dirn);
+		dma_dbg("SAR %x DAR %x, len: %x \n", sar, dar, len);
+		/*we have to copy more bytes*/
+		desc->len -= len;
+		ctl_hi.ctl_hi = desc->ctl_hi;
+		ctl_hi.ctlx.block_ts = get_block_ts(desc->len, desc->width);
+		dma_dbg("setting for %x bytes \n", ctl_hi.ctlx.block_ts);
+		desc->ctl_hi = ctl_hi.ctl_hi;
+		if (desc->cfg_mode == LNW_DMA_MEM_TO_MEM) {
+			sar++;
+			dar++;
+		} else if (desc->dirn == DMA_TO_DEVICE)
+			sar++;
+		else if (desc->dirn == DMA_FROM_DEVICE)
+			dar++;
+		desc->sar = sar;
+		desc->dar = dar;
+		dma_dbg("New SAR %x DAR %x \n", sar, dar);
+		lnwc_dostart1(lnwc, desc);
+		return;
+	}
+
+	lnwc->completed = txd->cookie;
+	callback = desc->callback;
+	param = desc->callback_param;
+	callback_txd = txd->callback;
+	param_txd = txd->callback_param;
+
+	list_move(&desc->desc_node, &lnwc->free_list);
+
+	spin_unlock_bh(&lnwc->lock);
+	dma_dbg("Now we are calling callback \n");
+	if (callback_txd) {
+		dma_dbg("lnw TXD callback set ... calling \n");
+		callback_txd(param_txd);
+		spin_lock_bh(&lnwc->lock);
+		return;
+	}
+	if (callback) {
+		dma_dbg("lnw callback set ... calling \n");
+		callback(param);
+	}
+	spin_lock_bh(&lnwc->lock);
+}
+
+/*check desc, mark as complete when tx is complete*/
+static void
+lnwc_scan_descriptors1(struct lnwdma_device *lnw, struct lnw_dma_chan *lnwc)
+{
+	struct lnw_dma_desc *desc = NULL, *_desc = NULL;
+	u32 status_xfer;
+
+	dma_dbg("called \n");
+	status_xfer = ioread32(lnwc->dma_base + RAW_BLOCK);
+	status_xfer = (status_xfer >> lnwc->ch_id) & 0x1;
+	dma_dbg("ch[%d]:  status_xfer %x \n", lnwc->ch_id, status_xfer);
+	if (!status_xfer)
+		return;
+
+	list_for_each_entry_safe(desc, _desc, &lnwc->active_list, desc_node) {
+		if (desc == NULL)
+			continue;
+		if (desc->status == DMA_IN_PROGRESS)  {
+			desc->status = DMA_SUCCESS;
+			lnwc_descriptor_complete1(lnwc, desc);
+		}
+	}
+	return;
+}
+
+/*****************************************************************************
+DMA Functions*/
+static dma_cookie_t lnw_dma1_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct lnw_dma_desc	*desc = to_lnw_dma_desc(tx);
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(tx->chan);
+	dma_cookie_t		cookie;
+
+	dma_dbg("called \n");
+	spin_lock_bh(&lnwc->lock);
+	cookie = lnwc->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	lnwc->chan.cookie = cookie;
+	desc->txd.cookie = cookie;
+
+
+	if (list_empty(&lnwc->active_list)) {
+		lnwc_dostart1(lnwc, desc);
+		list_add_tail(&desc->desc_node, &lnwc->active_list);
+	} else {
+		list_add_tail(&desc->desc_node, &lnwc->queue);
+	}
+	spin_unlock_bh(&lnwc->lock);
+
+	return cookie;
+}
+
+static void lnw_dma1_issue_pending(struct dma_chan *chan)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+
+	spin_lock_bh(&lnwc->lock);
+	if (!list_empty(&lnwc->queue))
+		lnwc_scan_descriptors1(to_lnwdma_device(chan->device), lnwc);
+	spin_unlock_bh(&lnwc->lock);
+}
+
+static enum dma_status
+lnw_dma1_tx_is_complete(struct dma_chan *chan,
+		dma_cookie_t cookie,
+		dma_cookie_t *done,
+		dma_cookie_t *used)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+	dma_cookie_t		last_used;
+	dma_cookie_t		last_complete;
+	int				ret;
+
+	last_complete = lnwc->completed;
+	last_used = chan->cookie;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret != DMA_SUCCESS) {
+		lnwc_scan_descriptors1(to_lnwdma_device(chan->device), lnwc);
+
+		last_complete = lnwc->completed;
+		last_used = chan->cookie;
+
+		ret = dma_async_is_complete(cookie, last_complete, last_used);
+	}
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return ret;
+}
+
+static void lnw_dma1_terminate_all(struct dma_chan *chan)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+	struct lnwdma_device	*lnw = to_lnwdma_device(chan->device);
+	struct lnw_dma_desc	*desc, *_desc;
+	LIST_HEAD(list);
+
+	/* ASSERT:  channel is idle */
+	if (lnwc->in_use == false) {
+		/*ch is not in use, wrong call*/
+		return;
+	}
+	spin_lock_bh(&lnwc->lock);
+	list_splice_init(&lnwc->free_list, &list);
+	lnwc->descs_allocated = 0;
+	lnwc->slave = NULL;
+
+	/* Disable interrupts */
+	disable_dma1_interrupt(lnwc);
+
+	spin_unlock_bh(&lnwc->lock);
+	list_for_each_entry_safe(desc, _desc, &list, desc_node) {
+		dma_dbg("freeing descriptor %p\n", desc);
+		pci_pool_free(lnw->dma_pool, desc, desc->txd.phys);
+	}
+	return;
+}
+
+static struct dma_async_tx_descriptor *
+lnw_dma1_prep_slave_sg(struct dma_chan *chan,
+		struct scatterlist *sgl, unsigned int sg_len,
+		enum dma_data_direction direction,
+		unsigned long flags)
+{
+	/*not supported now*/
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+lnw_dma1_prep_memcpy(struct dma_chan *chan, dma_addr_t dest,
+		dma_addr_t src, size_t len, unsigned long flags)
+{
+	struct lnw_dma_chan *lnwc;
+	struct lnw_dma_desc *desc = NULL;
+	struct lnw_dma_slave *lnws;
+	union lnw_dma_ctl_lo ctl_lo;
+	union lnw_dma_ctl_hi ctl_hi;
+	union lnw_dma_cfg_lo cfg_lo;
+	union lnw_dma_cfg_hi cfg_hi;
+	enum lnw_dma_width width = 0;
+
+	dma_dbg("called \n");
+	WARN_ON(!chan);
+	if (!len)
+		return NULL;
+
+	lnws = chan->private;
+	WARN_ON(!lnws);
+
+	lnwc = to_lnw_dma_chan(chan);
+	WARN_ON(!lnwc);
+
+	dma_dbg("called for CH %d\n", lnwc->ch_id);
+	dma_dbg("Cfg passed Mode %x, Dirn %x, HS %x, Width %x \n",
+		lnws->cfg_mode, lnws->dirn, lnws->hs_mode, lnws->src_width);
+
+	/*calculate CFG_LO*/
+	if (lnws->hs_mode == LNW_DMA_SW_HS) {
+		cfg_lo.cfg_lo = 0;
+		cfg_lo.cfgx.hs_sel_dst = 1;
+		cfg_lo.cfgx.hs_sel_src = 1;
+	} else if (lnws->hs_mode == LNW_DMA_HW_HS)
+		cfg_lo.cfg_lo = 0x00000;
+
+	/*calculate CFG_HI*/
+	if (lnws->cfg_mode == LNW_DMA_MEM_TO_MEM) {
+		/*SW HS only*/
+		dma_dbg("CFG: Mem to mem dma \n");
+		cfg_hi.cfg_hi = 0;
+	} else {
+		dma_dbg("HW DMA \n");
+		cfg_hi.cfg_hi = 0;
+		cfg_hi.cfgx.protctl = 0x0; /*default value*/
+		cfg_hi.cfgx.fifo_mode = 1;
+		if (lnws->dirn == DMA_TO_DEVICE) {
+			cfg_hi.cfgx.src_per = 0;
+			cfg_hi.cfgx.dst_per = 3;
+		} else if (lnws->dirn == DMA_FROM_DEVICE) {
+			cfg_hi.cfgx.src_per = 2;
+			cfg_hi.cfgx.dst_per = 0;
+		}
+	}
+
+	/*calculate CTL_HI*/
+	ctl_hi.ctlx.reser = 0;
+	width = lnws->src_width;
+
+	ctl_hi.ctlx.block_ts = get_block_ts(len, width);
+
+	/*calculate CTL_LO*/
+	ctl_lo.ctl_lo = 0;
+	ctl_lo.ctlx.int_en = 1;
+	ctl_lo.ctlx.dst_tr_width = lnws->dst_width;
+	ctl_lo.ctlx.src_tr_width = lnws->src_width;
+	ctl_lo.ctlx.dst_msize = lnws->src_msize;
+	ctl_lo.ctlx.src_msize = lnws->dst_msize;
+
+	if (lnws->cfg_mode == LNW_DMA_MEM_TO_MEM) {
+		dma_dbg("CTL: Mem to mem dma \n");
+		ctl_lo.ctlx.tt_fc = 0;
+		ctl_lo.ctlx.sinc = 0;
+		ctl_lo.ctlx.dinc = 0;
+	} else {
+		if (lnws->dirn == DMA_TO_DEVICE) {
+			dma_dbg("CTL: DMA_TO_DEVICE \n");
+			ctl_lo.ctlx.sinc = 0;
+			ctl_lo.ctlx.dinc = 2;
+			ctl_lo.ctlx.tt_fc = 1;
+		} else if (lnws->dirn == DMA_FROM_DEVICE) {
+			dma_dbg("CTL: DMA_FROM_DEVICE \n");
+			ctl_lo.ctlx.sinc = 2;
+			ctl_lo.ctlx.dinc = 0;
+			ctl_lo.ctlx.tt_fc = 2;
+		}
+	}
+
+	dma_dbg("Calc CTL LO %x, CTL HI %x, CFG LO %x, CFG HI %x\n",
+		ctl_lo.ctl_lo, ctl_hi.ctl_hi, cfg_lo.cfg_lo, cfg_hi.cfg_hi);
+
+	enable_dma1_interrupt(lnwc);
+
+	desc = lnwc_desc_get1(lnwc);
+	if (desc == NULL)
+		goto err_desc_get;
+	desc->sar = src;
+	desc->dar = dest ;
+	desc->len = len;
+	desc->cfg_hi = cfg_hi.cfg_hi;
+	desc->cfg_lo = cfg_lo.cfg_lo;
+	desc->ctl_lo = ctl_lo.ctl_lo;
+	desc->ctl_hi = ctl_hi.ctl_hi;
+	desc->width = width;
+	desc->dirn = lnws->dirn;
+	if (lnws->callback) {
+		desc->callback = lnws->callback;
+		desc->callback_param = lnws->callback_param;
+		dma_dbg("Callback passed... setting\n");
+	} else
+		desc->callback = NULL;
+	return &desc->txd;
+
+err_desc_get:
+	dma_err("Failed to get desc \n");
+	lnwc_desc_put1(lnwc, desc);
+	return NULL;
+}
+
+static void lnw_dma1_free_chan_resources(struct dma_chan *chan)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+	struct lnwdma_device	*lnw = to_lnwdma_device(chan->device);
+	struct lnw_dma_desc	*desc, *_desc;
+
+	dma_dbg("..called for ch_id %d, lnwch_id %d\n",
+			chan->chan_id, lnwc->ch_id);
+	if (true == lnwc->in_use) {
+		/*trying to free ch in use!!!!!*/
+		dma_err("trying to free ch in use \n");
+	}
+
+	spin_lock_bh(&lnwc->lock);
+	lnwc->descs_allocated = 0;
+	list_for_each_entry_safe(desc, _desc, &lnwc->active_list, desc_node) {
+		dma_dbg("del active \n");
+		list_del(&desc->desc_node);
+		pci_pool_free(lnw->dma_pool, desc, desc->txd.phys);
+	}
+	list_for_each_entry_safe(desc, _desc, &lnwc->free_list, desc_node) {
+		list_del(&desc->desc_node);
+		pci_pool_free(lnw->dma_pool, desc, desc->txd.phys);
+	}
+	list_for_each_entry_safe(desc, _desc, &lnwc->queue, desc_node) {
+		dma_dbg("del queue \n");
+		list_del(&desc->desc_node);
+		pci_pool_free(lnw->dma_pool, desc, desc->txd.phys);
+	}
+	spin_unlock_bh(&lnwc->lock);
+	lnwc->in_use = false;
+	chan->client_count--;
+	/* Disable CH interrupts */
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnw->dma_base + MASK_BLOCK);
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnw->dma_base + MASK_ERR);
+	dma_dbg("done \n");
+}
+
+static int lnw_dma1_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+	struct lnwdma_device	*lnw = to_lnwdma_device(chan->device);
+	struct lnw_dma_desc	*desc;
+	dma_addr_t		phys;
+	int	i = 0;
+
+	dma_dbg("called \n");
+
+	/* ASSERT:  channel is idle */
+	if (test_ch_en(lnw->dma_base, lnwc->ch_id)) {
+		/*ch is not idle*/
+		dma_err(".ch not idle\n");
+		return -EIO;
+	}
+	dma_dbg("..called for ch_id %d, lnwch_id %d\n",
+			chan->chan_id, lnwc->ch_id);
+	lnwc->completed = chan->cookie = 1;
+
+	chan->client_count++;
+
+	spin_lock_bh(&lnwc->lock);
+	while (lnwc->descs_allocated < DESCS_PER_CHANNEL) {
+		spin_unlock_bh(&lnwc->lock);
+		desc = pci_pool_alloc(lnw->dma_pool, GFP_KERNEL, &phys);
+		if (!desc) {
+			dma_err("desc failed\n");
+			return -ENOMEM;
+			/*check*/
+		}
+		dma_async_tx_descriptor_init(&desc->txd, chan);
+		desc->txd.tx_submit = lnw_dma1_tx_submit;
+		desc->txd.flags = DMA_CTRL_ACK;
+		desc->txd.phys = phys;
+		spin_lock_bh(&lnwc->lock);
+		i = ++lnwc->descs_allocated;
+		list_add_tail(&desc->desc_node, &lnwc->free_list);
+	}
+	spin_unlock_bh(&lnwc->lock);
+	lnwc->in_use = false;
+	dma_dbg("Desc alloc done ret: %d desc\n", i);
+	return i;
+}
+
+static void lnwc_handle_error1(struct lnwdma_device *lnw,
+		struct lnw_dma_chan *lnwc)
+{
+	lnwc_scan_descriptors1(lnw, lnwc);
+}
+
+/******************************************************************************
+* PCI stuff
+*/
+static struct pci_device_id lnw_dma1_ids[] = {
+	{ PCI_VENDOR_ID_INTEL, 0x0814, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, lnw_dma1_ids);
+
+static struct pci_driver lnw_dma1_pci = {
+	.name 		=	"Intel LNW DMA1",
+	.id_table 	=	lnw_dma1_ids,
+	.probe 		=	lnw_dma1_probe,
+	.remove 	=	__devexit_p(lnw_dma1_remove),
+};
+
+static void dma_tasklet1(unsigned long data)
+{
+	struct lnwdma_device *lnw = NULL;
+	struct lnw_dma_chan *lnwc = NULL;
+	u32 status;
+	int i, ch_no;
+
+	dma_dbg("called \n");
+	lnw = (struct lnwdma_device *)data;
+	if (lnw == NULL) {
+		dma_err("Null param \n");
+		return;
+	}
+	status = ioread32(lnw->dma_base + RAW_BLOCK);
+	dma_dbg("RAW_TFR %x \n", status);
+	status &= 0xC0;
+	while (status) {
+		/*txn interrupt*/
+		ch_no = get_ch_num(&status);
+		if (ch_no < 0) {
+			dma_err("Ch no is invalid %x, abort!\n", ch_no);
+			return;
+		}
+		dma_dbg("Got Ch %x, new Status %x \n", ch_no, status);
+		i = get_ch_index(ch_no);
+		if (i < 0) {
+			dma_err("Invalid ch index %x\n", i);
+			return;
+		}
+		dma_dbg("Tx complete interrupt %x, Ch No %d Index %d \n",
+				status, ch_no, i);
+		lnwc = &lnw->ch[i];
+		if (lnwc == NULL) {
+			dma_err("Null param lnwc\n");
+			return;
+		}
+		dma_dbg("CH %x \n", lnwc->ch_id);
+		spin_lock_bh(&lnwc->lock);
+		lnwc_scan_descriptors1(lnw, lnwc);
+		dma_dbg("Scan of desc... complete, unmasking\n");
+		iowrite32((1 << lnwc->ch_id),
+				lnw->dma_base + CLEAR_TFR);
+		dma_dbg("Wrote to clear %x\n", (1 << lnwc->ch_id));
+		iowrite32((1 << lnwc->ch_id),
+				lnw->dma_base + CLEAR_BLOCK);
+		iowrite32(UNMASK_INTR_REG(lnwc->ch_id),
+				lnw->dma_base + MASK_TFR);
+		spin_unlock_bh(&lnwc->lock);
+	}
+
+	dma_dbg("Trf interrupt done... \n");
+	status = ioread32(lnw->dma_base + RAW_ERR);
+	status &= 0xC0;
+	while (status) {
+		/*err interrupt*/
+		ch_no = get_ch_num(&status);
+		if (ch_no < 0) {
+			dma_err("Ch no is invalid %x, abort!\n", ch_no);
+			return;
+		}
+		dma_dbg("Got Ch %x, new Status %x \n", ch_no, status);
+		i = get_ch_index(ch_no);
+		if (i < 0) {
+			dma_err("Invalid CH lnwc\n");
+			return;
+		}
+		dma_dbg("Tx error interrupt %x, No %d Index %d \n",
+				status, ch_no, i);
+		lnwc = &lnw->ch[i];
+		if (lnwc == NULL) {
+			dma_err("Null param lnwc\n");
+			return;
+		}
+		spin_lock_bh(&lnwc->lock);
+		lnwc_handle_error1(lnw, lnwc);
+		iowrite32((1 << lnwc->ch_id),
+				lnw->dma_base + CLEAR_ERR);
+		iowrite32(UNMASK_INTR_REG(lnwc->ch_id),
+				lnw->dma_base + MASK_ERR);
+		spin_unlock_bh(&lnwc->lock);
+	}
+	dma_dbg("Exiting takslet... \n");
+	return;
+}
+
+static irqreturn_t lnw_dma1_interrupt(int irq, void *data)
+{
+	struct lnw_device *lnw = data;
+	u32 status;
+	int call_tasklet = 0;
+
+	/*check interrupt src*/
+	lpe_periphral_intr_status(LPE_DMA, &status);
+	if (!status) {
+		/*not our interrupt*/
+		return IRQ_NONE;
+	}
+
+	/*DMA Interrupt*/
+	status = ioread32(lnw->dma_base + RAW_TFR);
+	status &= 0xC0;
+	if (status) {
+		iowrite32((status << 8), lnw->dma_base + MASK_TFR);
+		call_tasklet = 1;
+	}
+	status = ioread32(lnw->dma_base + RAW_ERR);
+	status &= 0xC0;
+	if (status) {
+		iowrite32(MASK_INTR_REG(status), lnw->dma_base + MASK_ERR);
+		call_tasklet = 1;
+	}
+
+	if (call_tasklet)
+		tasklet_schedule(&lnw->dma->tasklet);
+
+	return IRQ_HANDLED;
+}
+
+static void enable_dma1_interrupt(struct lnw_dma_chan *lnwc)
+{
+	dma_dbg("Called for ch_id %d\n", lnwc->ch_id);
+
+	lpe_unmask_periphral_intr(LPE_DMA);
+
+	/*en ch interrupts*/
+	iowrite32(UNMASK_INTR_REG(lnwc->ch_id), lnwc->dma_base + MASK_TFR);
+	iowrite32(UNMASK_INTR_REG(lnwc->ch_id), lnwc->dma_base + MASK_ERR);
+	return;
+}
+
+static void disable_dma1_interrupt(struct lnw_dma_chan *lnwc)
+{
+	/*Check LPE PISR, make sure fwd is disabled*/
+	lpe_mask_periphral_intr(LPE_DMA);
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnwc->dma_base + MASK_BLOCK);
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnwc->dma_base + MASK_TFR);
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnwc->dma_base + MASK_ERR);
+	dma_dbg(" called \n");
+	return;
+}
+
+static int lnw_setup_dma1(struct pci_dev *pdev)
+{
+	struct lnw_device *device = pci_get_drvdata(pdev);
+	struct lnwdma_device *dma = NULL;
+	int err, i;
+
+	dma_dbg("setup_dma called \n");
+	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
+	if (NULL == dma) {
+		dma_err("kzalloc failed \n");
+		err = -ENOMEM;
+		goto err_kzalloc;
+	}
+	device->dma = dma;
+	dma->pdev = pdev;
+	dma->dma_base = device->dma_base;
+
+	/* DMA coherent memory pool for DMA descriptor allocations */
+	dma->dma_pool = pci_pool_create("dma_desc_pool", pdev,
+					sizeof(struct lnw_dma_desc),
+					32, 0);
+	if (NULL == dma->dma_pool) {
+		dma_err("pci_pool_create failed \n");
+		err = -ENOMEM;
+		kfree(dma);
+		goto err_dma_pool;
+	}
+
+	INIT_LIST_HEAD(&dma->common.channels);
+
+
+	/*init CH structures*/
+	for (i = 0; i < MAX_CHAN; i++) {
+		struct lnw_dma_chan *lnwch = &dma->ch[i];
+
+		lnwch->chan.device = &dma->common;
+		lnwch->chan.cookie =  1;
+		lnwch->chan.chan_id = i;
+		lnwch->ch_id = get_ch_id(i);
+		dma_dbg("Init CH %d, ID %d \n", i, lnwch->ch_id);
+
+		lnwch->dma_base = dma->dma_base;
+		lnwch->ch_regs = dma->dma_base + DMA_CH_SIZE * lnwch->ch_id;
+		lnwch->dma = dma;
+		spin_lock_init(&lnwch->lock);
+
+		INIT_LIST_HEAD(&lnwch->active_list);
+		INIT_LIST_HEAD(&lnwch->queue);
+		INIT_LIST_HEAD(&lnwch->free_list);
+		/*mask interrupts*/
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_BLOCK);
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_SRC_TRAN);
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_DST_TRAN);
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_ERR);
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_TFR);
+
+		disable_dma1_interrupt(lnwch);
+		list_add_tail(&lnwch->chan.device_node, &dma->common.channels);
+	}
+
+	/*init dma structure*/
+	dma_cap_zero(dma->common.cap_mask);
+	dma_cap_set(DMA_MEMCPY, dma->common.cap_mask);
+	dma_cap_set(DMA_SLAVE, dma->common.cap_mask);
+	dma_cap_set(DMA_PRIVATE, dma->common.cap_mask);
+	dma->common.dev = &pdev->dev;
+	dma->common.chancnt = MAX_CHAN;
+
+	dma->common.device_alloc_chan_resources =
+					lnw_dma1_alloc_chan_resources;
+	dma->common.device_free_chan_resources =
+					lnw_dma1_free_chan_resources;
+
+	dma->common.device_is_tx_complete = lnw_dma1_tx_is_complete;
+	dma->common.device_prep_dma_memcpy = lnw_dma1_prep_memcpy;
+	dma->common.device_issue_pending = lnw_dma1_issue_pending;
+	dma->common.device_prep_slave_sg = lnw_dma1_prep_slave_sg;
+	dma->common.device_terminate_all = lnw_dma1_terminate_all;
+
+	/*enable dma cntrl*/
+	iowrite32(REG_BIT0, dma->dma_base + DMA_CFG);
+
+	/*register irq*/
+	err = request_irq(pdev->irq, lnw_dma1_interrupt,
+			IRQF_SHARED, lnw_dma1_pci.name, device);
+	if (0 != err)
+		goto err_irq;
+
+	/*register device w/ engine*/
+	err = dma_async_device_register(&dma->common);
+	if (0 != err) {
+		dma_err("device_register failed: %d \n", err);
+		goto err_engine;
+	}
+	tasklet_init(&dma->tasklet, dma_tasklet1, (unsigned long)dma);
+	dma_dbg("...done \n");
+	return 0;
+
+err_engine:
+	free_irq(pdev->irq, device);
+err_irq:
+	pci_pool_destroy(dma->dma_pool);
+	kfree(dma);
+err_dma_pool:
+err_kzalloc:
+	dma_err("setup_dma failed: %d \n", err);
+	return err;
+
+}
+
+static void lnwdma_shutdown1(struct pci_dev *pdev)
+{
+	struct lnw_device *device = pci_get_drvdata(pdev);
+
+	dma_dbg("shutdown called \n");
+	dma_async_device_unregister(&device->dma->common);
+	pci_pool_destroy(device->dma->dma_pool);
+	if (device->dma_base)
+		iounmap(device->dma_base);
+	free_irq(pdev->irq, device);
+	return;
+}
+
+static int __devinit
+lnw_dma1_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct lnw_device *device = NULL;
+	u32 base_addr = 0, bar_size = 0;
+	int err = 0;
+
+	dma_info("probe called for %x \n", pdev->device);
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_enable_device;
+
+	err = pci_request_regions(pdev, lnw_dma1_pci.name);
+	if (err)
+		goto err_request_regions;
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err)
+		goto err_set_dma_mask;
+
+	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err)
+		goto err_set_dma_mask;
+
+	device = kzalloc(sizeof(*device), GFP_KERNEL);
+	if (!device) {
+		dma_err("kzalloc failed \n");
+		err = -ENOMEM;
+		goto err_kzalloc;
+	}
+	device->pdev = pci_dev_get(pdev);
+
+	base_addr = pci_resource_start(pdev, 0);
+	bar_size  = pci_resource_len(pdev, 0);
+	dma_dbg("BAR0 %x Size %x \n", base_addr, bar_size);
+	device->dma_base = ioremap_nocache(base_addr, DMA_REG_SIZE);
+	if (!device->dma_base) {
+		dma_err("ioremap failed \n");
+		err = -ENOMEM;
+		goto err_ioremap1;
+	}
+	pci_set_drvdata(pdev, device);
+	pci_set_master(pdev);
+
+	err = lnw_setup_dma1(pdev);
+	if (err)
+		goto err_dma;
+
+	return 0;
+
+err_dma:
+	iounmap(device->dma_base);
+err_ioremap1:
+	pci_dev_put(pdev);
+	kfree(device);
+err_kzalloc:
+err_set_dma_mask:
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+err_request_regions:
+err_enable_device:
+	dma_err("Probe failed %d\n", err);
+	return err;
+}
+
+static void __devexit lnw_dma1_remove(struct pci_dev *pdev)
+{
+	struct lnw_device *device = pci_get_drvdata(pdev);
+
+	lnwdma_shutdown1(pdev);
+	pci_dev_put(pdev);
+	kfree(device);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static int __init lnw_dma1_init(void)
+{
+	dma_info("LNW DMA Driver\n Version %s \n", LNW_DMA_DRIVER_VERSION);
+	return pci_register_driver(&lnw_dma1_pci);
+}
+late_initcall(lnw_dma1_init);
+
+static void __exit lnw_dma1_exit(void)
+{
+	pci_unregister_driver(&lnw_dma1_pci);
+}
+module_exit(lnw_dma1_exit);
+
Index: linux-2.6.33/drivers/dma/lnw_dmac2.c
===================================================================
--- /dev/null
+++ linux-2.6.33/drivers/dma/lnw_dmac2.c
@@ -0,0 +1,947 @@
+/*
+ *  lnw_dmac2.c - Intel Langwell DMA Drivers
+ *
+ *  Copyright (C) 2008-09 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  The driver design is based on dw_dmac driver
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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; version 2 of the License.
+ *
+ *  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/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/lnw_dma.h>
+
+#define MAX_CHAN 	2
+#include "lnw_dma_regs.h"
+
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_DESCRIPTION("Intel (R) Moorestown Langwell DMAC2 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(LNW_DMA_DRIVER_VERSION);
+
+#define DMA_CH0		0
+#define DMA_CH1		1
+#define CH_BLOCK_SIZE	2047
+
+static int __devinit lnw_dma2_probe(struct pci_dev *pdev,
+				const struct pci_device_id *id);
+static void __devexit lnw_dma2_remove(struct pci_dev *pdev);
+static void enable_dma2_interrupt(struct lnw_dma_chan *lnwc);
+
+struct lnw_device {
+	struct pci_dev 		*pdev;
+	void __iomem		*dma_base;
+	struct lnwdma_device	*dma;
+};
+
+/*CH dep code, if ch no's mapping changes only change here*/
+static int get_ch_id(int index)
+{
+	if (index == 0)
+		return DMA_CH0;
+	else if (index == 1)
+		return DMA_CH1;
+	else
+		return -1;
+}
+
+static int get_ch_index(int ch_id)
+{
+	if (ch_id == DMA_CH0)
+		return 0;
+	if (ch_id == DMA_CH1)
+		return 1;
+	else
+		return -1;
+}
+
+static int get_ch_num(int *status)
+{
+	if (*status & (1 << DMA_CH0)) {
+		*status = *status & (~(1 << DMA_CH0));
+		return DMA_CH0;
+	} else if (*status & (1 << DMA_CH1)) {
+		*status = *status & (~(1 << DMA_CH1));
+		return DMA_CH1;
+	} else
+		return -1;
+}
+
+static int get_block_ts(int len, int tx_width)
+{
+	int byte_width = 0, block_ts = 0;
+
+	switch (tx_width) {
+	case LNW_DMA_WIDTH_8BIT:
+		byte_width = 1;
+		break;
+	case LNW_DMA_WIDTH_16BIT:
+		byte_width = 2;
+		break;
+	case LNW_DMA_WIDTH_32BIT:
+	default:
+		byte_width = 4;
+		break;
+	}
+
+	block_ts = len/byte_width;
+	if (block_ts > CH_BLOCK_SIZE)
+		block_ts = 0xFFFF;
+	return block_ts;
+}
+
+static struct lnw_dma_desc *lnwc_desc_get(struct lnw_dma_chan *lnwc)
+{
+	struct lnw_dma_desc *desc, *_desc;
+	struct lnw_dma_desc *ret = NULL;
+
+	dma_dbg("called \n");
+	spin_lock_bh(&lnwc->lock);
+	list_for_each_entry_safe(desc, _desc, &lnwc->free_list, desc_node) {
+		if (async_tx_test_ack(&desc->txd)) {
+			list_del(&desc->desc_node);
+			ret = desc;
+			dma_dbg("got free desc \n");
+			break;
+		}
+	}
+	spin_unlock_bh(&lnwc->lock);
+	return ret;
+}
+
+static void lnwc_desc_put(struct lnw_dma_chan *lnwc, struct lnw_dma_desc *desc)
+{
+	if (desc) {
+		spin_lock_bh(&lnwc->lock);
+		list_add_tail(&desc->desc_node, &lnwc->free_list);
+		spin_unlock_bh(&lnwc->lock);
+	}
+}
+
+/* Called with lock held and bh disabled */
+static void lnwc_dostart(struct lnw_dma_chan *lnwc, struct lnw_dma_desc *first)
+{
+	struct lnwdma_device *lnw = to_lnwdma_device(lnwc->chan.device);
+
+	dma_dbg("called \n");
+	/*  channel is idle */
+	if (lnwc->in_use && test_ch_en(lnwc->dma_base, lnwc->ch_id)) {
+		/*error*/
+		dma_err("channel is busy \n");
+		/* The tasklet will hopefully advance the queue... */
+		return;
+	}
+
+	/*write registers and en*/
+	iowrite32(first->sar, lnwc->ch_regs + SAR);
+	iowrite32(first->dar, lnwc->ch_regs + DAR);
+	iowrite32(first->cfg_hi, lnwc->ch_regs + CFG_HIGH);
+	iowrite32(first->cfg_lo, lnwc->ch_regs + CFG_LOW);
+	iowrite32(first->ctl_lo, lnwc->ch_regs + CTL_LOW);
+	iowrite32(first->ctl_hi, lnwc->ch_regs + CTL_HIGH);
+	dma_dbg("TX SAR %lx, DAR %lx, CFGL %x, CFGH %x, CTLH %x, CTLL %x \n",
+		first->sar, first->dar, first->cfg_hi,
+		first->cfg_lo, first->ctl_hi, first->ctl_lo);
+
+	iowrite32(ENABLE_CHANNEL(lnwc->ch_id), lnw->dma_base + DMA_CHAN_EN);
+	first->status = DMA_IN_PROGRESS;
+}
+
+static void
+lnwc_descriptor_complete(struct lnw_dma_chan *lnwc, struct lnw_dma_desc *desc)
+{
+	struct dma_async_tx_descriptor	*txd = &desc->txd;
+	dma_async_tx_callback callback = NULL;
+	dma_async_tx_callback callback_txd = NULL;
+	void *param = NULL;
+	void *param_txd = NULL;
+	u32 sar, dar, len;
+	union lnw_dma_ctl_hi ctl_hi;
+
+	dma_dbg("called \n");
+
+	/*check if full tx is complete or not*/
+	sar = ioread32(lnwc->ch_regs + SAR);
+	dar = ioread32(lnwc->ch_regs + DAR);
+
+	if (desc->dirn == DMA_FROM_DEVICE)
+		len = dar - desc->dar;
+	else
+		len = sar - desc->sar;
+
+	dma_dbg("SAR %x DAR %x, DMA done: %x \n", sar, dar, len);
+	if (desc->len > len) {
+		dma_dbg("dirn = %d\n", desc->dirn);
+		dma_dbg("SAR %x DAR %x, len: %x \n", sar, dar, len);
+		/*we have to copy more bytes*/
+		desc->len -= len;
+		ctl_hi.ctl_hi = desc->ctl_hi;
+		ctl_hi.ctlx.block_ts = get_block_ts(desc->len, desc->width);
+		dma_dbg("setting for %x bytes \n", ctl_hi.ctlx.block_ts);
+		desc->ctl_hi = ctl_hi.ctl_hi;
+		if (desc->cfg_mode == LNW_DMA_MEM_TO_MEM) {
+			sar++;
+			dar++;
+		} else if (desc->dirn == DMA_TO_DEVICE)
+			sar++;
+		else if (desc->dirn == DMA_FROM_DEVICE)
+			dar++;
+		desc->sar = sar;
+		desc->dar = dar;
+		dma_dbg("New SAR %x DAR %x \n", sar, dar);
+		lnwc_dostart(lnwc, desc);
+		return;
+	}
+
+	lnwc->completed = txd->cookie;
+	callback = desc->callback;
+	param = desc->callback_param;
+	callback_txd = txd->callback;
+	param_txd = txd->callback_param;
+
+	list_move(&desc->desc_node, &lnwc->free_list);
+
+	spin_unlock_bh(&lnwc->lock);
+	dma_dbg("Now we are calling callback \n");
+	if (callback_txd) {
+		dma_dbg("lnw TXD callback set ... calling \n");
+		callback_txd(param_txd);
+		spin_lock_bh(&lnwc->lock);
+		return;
+	}
+	if (callback) {
+		dma_dbg("lnw callback set ... calling \n");
+		callback(param);
+	}
+	spin_lock_bh(&lnwc->lock);
+
+}
+
+/*check desc, mark as complete when tx is complete*/
+static void
+lnwc_scan_descriptors(struct lnwdma_device *lnw, struct lnw_dma_chan *lnwc)
+{
+	struct lnw_dma_desc *desc = NULL, *_desc = NULL;
+	u32 status_xfer;
+
+	dma_dbg("called \n");
+	status_xfer = ioread32(lnwc->dma_base + RAW_TFR);
+	status_xfer = (status_xfer >> lnwc->ch_id) & 0x1;
+	dma_dbg("ch[%d]:  status_xfer %x \n", lnwc->ch_id, status_xfer);
+	if (!status_xfer)
+		return;
+
+	/*tx is complete*/
+	list_for_each_entry_safe(desc, _desc, &lnwc->active_list, desc_node) {
+		if (desc == NULL)
+			continue;
+		if (desc->status == DMA_IN_PROGRESS)  {
+			desc->status = DMA_SUCCESS;
+			lnwc_descriptor_complete(lnwc, desc);
+		}
+	}
+	return;
+}
+
+/*****************************************************************************
+DMA Functions*/
+static dma_cookie_t lnw_dma2_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct lnw_dma_desc	*desc = to_lnw_dma_desc(tx);
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(tx->chan);
+	dma_cookie_t		cookie;
+
+	dma_dbg("called \n");
+
+	spin_lock_bh(&lnwc->lock);
+	cookie = lnwc->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	lnwc->chan.cookie = cookie;
+	desc->txd.cookie = cookie;
+
+	if (list_empty(&lnwc->active_list)) {
+		lnwc_dostart(lnwc, desc);
+		list_add_tail(&desc->desc_node, &lnwc->active_list);
+	} else {
+		list_add_tail(&desc->desc_node, &lnwc->queue);
+	}
+	spin_unlock_bh(&lnwc->lock);
+
+	return cookie;
+}
+
+static void lnw_dma2_issue_pending(struct dma_chan *chan)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+
+	spin_lock_bh(&lnwc->lock);
+	if (!list_empty(&lnwc->queue))
+		lnwc_scan_descriptors(to_lnwdma_device(chan->device), lnwc);
+	spin_unlock_bh(&lnwc->lock);
+}
+
+static enum dma_status
+lnw_dma2_tx_is_complete(struct dma_chan *chan,
+		dma_cookie_t cookie,
+		dma_cookie_t *done,
+		dma_cookie_t *used)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+	dma_cookie_t		last_used;
+	dma_cookie_t		last_complete;
+	int				ret;
+
+	last_complete = lnwc->completed;
+	last_used = chan->cookie;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret != DMA_SUCCESS) {
+		lnwc_scan_descriptors(to_lnwdma_device(chan->device), lnwc);
+
+		last_complete = lnwc->completed;
+		last_used = chan->cookie;
+
+		ret = dma_async_is_complete(cookie, last_complete, last_used);
+	}
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return ret;
+}
+
+static void lnw_dma2_terminate_all(struct dma_chan *chan)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+	struct lnwdma_device	*lnw = to_lnwdma_device(chan->device);
+	struct lnw_dma_desc	*desc, *_desc;
+	LIST_HEAD(list);
+
+	/* ASSERT:  channel is idle */
+	if (lnwc->in_use == false) {
+		/*ch is not in use, wrong call*/
+		return;
+	}
+	spin_lock_bh(&lnwc->lock);
+	list_splice_init(&lnwc->free_list, &list);
+	lnwc->descs_allocated = 0;
+	lnwc->slave = NULL;
+
+	/* Disable interrupts*/
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnw->dma_base + MASK_BLOCK);
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnw->dma_base + MASK_ERR);
+
+	spin_unlock_bh(&lnwc->lock);
+	list_for_each_entry_safe(desc, _desc, &list, desc_node) {
+		dma_dbg("freeing descriptor %p\n", desc);
+		pci_pool_free(lnw->dma_pool, desc, desc->txd.phys);
+	}
+
+	return;
+}
+
+static struct dma_async_tx_descriptor *
+lnw_dma2_prep_slave_sg(struct dma_chan *chan,
+		struct scatterlist *sgl, unsigned int sg_len,
+		enum dma_data_direction direction,
+		unsigned long flags)
+{
+	/*not supported now*/
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+lnw_dma2_prep_memcpy(struct dma_chan *chan, dma_addr_t dest,
+		dma_addr_t src, size_t len, unsigned long flags)
+{
+	struct lnw_dma_chan *lnwc;
+	struct lnw_dma_desc *desc = NULL;
+	struct lnw_dma_slave *lnws;
+	union lnw_dma_ctl_lo ctl_lo;
+	union lnw_dma_ctl_hi ctl_hi;
+	union lnw_dma_cfg_lo cfg_lo;
+	union lnw_dma_cfg_hi cfg_hi;
+	enum lnw_dma_width width = 0;
+
+	dma_dbg("called \n");
+	WARN_ON(!chan);
+	if (!len)
+		return NULL;
+
+	lnws = chan->private;
+	WARN_ON(!lnws);
+
+	lnwc = to_lnw_dma_chan(chan);
+	WARN_ON(!lnwc);
+
+	dma_dbg("called for CH %d\n", lnwc->ch_id);
+	dma_dbg("Cfg passed Mode %x, Dirn %x, HS %x, Width %x \n",
+		lnws->cfg_mode, lnws->dirn, lnws->hs_mode, lnws->src_width);
+
+	/*calculate CFG_LO*/
+	if (lnws->hs_mode == LNW_DMA_SW_HS) {
+		cfg_lo.cfg_lo = 0;
+		cfg_lo.cfgx.hs_sel_dst = 1;
+		cfg_lo.cfgx.hs_sel_src = 1;
+	} else if (lnws->hs_mode == LNW_DMA_HW_HS)
+		cfg_lo.cfg_lo = 0x00000;
+
+	/*calculate CFG_HI*/
+	if (lnws->cfg_mode == LNW_DMA_MEM_TO_MEM) {
+		/*SW HS only*/
+		dma_dbg("CFG: Mem to mem dma \n");
+		cfg_hi.cfg_hi = 0;
+	} else {
+		dma_dbg("HW DMA \n");
+		cfg_hi.cfg_hi = 0;
+		cfg_hi.cfgx.protctl = 0x1; /*default value*/
+		cfg_hi.cfgx.src_per = get_ch_index(lnwc->ch_id);
+		cfg_hi.cfgx.dst_per = get_ch_index(lnwc->ch_id);
+	}
+
+	/*calculate CTL_HI*/
+	ctl_hi.ctlx.reser = 0;
+		width = lnws->src_width;
+	ctl_hi.ctlx.block_ts = get_block_ts(len, width);
+
+	/*calculate CTL_LO*/
+	ctl_lo.ctl_lo = 0;
+	ctl_lo.ctlx.int_en = 1;
+	ctl_lo.ctlx.dst_tr_width = lnws->dst_width;
+	ctl_lo.ctlx.src_tr_width = lnws->src_width;
+	ctl_lo.ctlx.dst_msize = lnws->src_msize;
+	ctl_lo.ctlx.src_msize = lnws->dst_msize;
+
+	if (lnws->cfg_mode == LNW_DMA_MEM_TO_MEM) {
+		dma_dbg("CTL: Mem to mem dma \n");
+		ctl_lo.ctlx.tt_fc = 0;
+		ctl_lo.ctlx.sinc = 0;
+		ctl_lo.ctlx.dinc = 0;
+	} else {
+		if (lnws->dirn == DMA_TO_DEVICE) {
+			dma_dbg("CTL: DMA_TO_DEVICE \n");
+			ctl_lo.ctlx.sinc = 0;
+			ctl_lo.ctlx.dinc = 2;
+			ctl_lo.ctlx.tt_fc = 1;
+		} else if (lnws->dirn == DMA_FROM_DEVICE) {
+			dma_dbg("CTL: DMA_FROM_DEVICE \n");
+			ctl_lo.ctlx.sinc = 2;
+			ctl_lo.ctlx.dinc = 0;
+			ctl_lo.ctlx.tt_fc = 2;
+		}
+	}
+
+	dma_dbg("Calc CTL LO %x, CTL HI %x, CFG LO %x, CFG HI %x\n",
+		ctl_lo.ctl_lo, ctl_hi.ctl_hi, cfg_lo.cfg_lo, cfg_hi.cfg_hi);
+
+	enable_dma2_interrupt(lnwc);
+
+	desc = lnwc_desc_get(lnwc);
+	if (desc == NULL)
+		goto err_desc_get;
+	desc->sar = src;
+	desc->dar = dest ;
+	desc->len = len;
+	desc->cfg_hi = cfg_hi.cfg_hi;
+	desc->cfg_lo = cfg_lo.cfg_lo;
+	desc->ctl_lo = ctl_lo.ctl_lo;
+	desc->ctl_hi = ctl_hi.ctl_hi;
+	desc->width = width;
+	desc->dirn = lnws->dirn;
+	if (lnws->callback) {
+		desc->callback = lnws->callback;
+		desc->callback_param = lnws->callback_param;
+		dma_dbg("Callback passed... setting\n");
+	} else
+		desc->callback = NULL;
+	return &desc->txd;
+
+err_desc_get:
+	dma_err("Failed to get desc \n");
+	lnwc_desc_put(lnwc, desc);
+	return NULL;
+}
+
+
+static void lnw_dma2_free_chan_resources(struct dma_chan *chan)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+	struct lnwdma_device	*lnw = to_lnwdma_device(chan->device);
+	struct lnw_dma_desc	*desc, *_desc;
+
+	dma_dbg("..called for ch_id %d, lnwch_id %d\n",
+			chan->chan_id, lnwc->ch_id);
+	if (true == lnwc->in_use) {
+		/*trying to free ch in use!!!!!*/
+		dma_err("trying to free ch in use \n");
+	}
+
+	spin_lock_bh(&lnwc->lock);
+	lnwc->descs_allocated = 0;
+	list_for_each_entry_safe(desc, _desc, &lnwc->active_list, desc_node) {
+		dma_dbg("del active \n");
+		list_del(&desc->desc_node);
+		pci_pool_free(lnw->dma_pool, desc, desc->txd.phys);
+	}
+	list_for_each_entry_safe(desc, _desc, &lnwc->free_list, desc_node) {
+		list_del(&desc->desc_node);
+		pci_pool_free(lnw->dma_pool, desc, desc->txd.phys);
+	}
+	list_for_each_entry_safe(desc, _desc, &lnwc->queue, desc_node) {
+		dma_dbg("del queue \n");
+		list_del(&desc->desc_node);
+		pci_pool_free(lnw->dma_pool, desc, desc->txd.phys);
+	}
+	spin_unlock_bh(&lnwc->lock);
+	lnwc->in_use = false;
+	chan->client_count--;
+	/* Disable CH interrupts*/
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnw->dma_base + MASK_BLOCK);
+	iowrite32(MASK_INTR_REG(lnwc->ch_id), lnw->dma_base + MASK_ERR);
+	dma_dbg("done \n");
+}
+
+static int lnw_dma2_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct lnw_dma_chan	*lnwc = to_lnw_dma_chan(chan);
+	struct lnwdma_device	*lnw = to_lnwdma_device(chan->device);
+	struct lnw_dma_desc	*desc;
+	dma_addr_t		phys;
+	int	i = 0;
+
+	dma_dbg("called \n");
+
+	/* ASSERT:  channel is idle */
+	if (test_ch_en(lnw->dma_base, lnwc->ch_id)) {
+		/*ch is not idle*/
+		dma_err(".ch not idle\n");
+		return -EIO;
+	}
+	dma_dbg("..called for ch_id %d, lnwch_id %d\n",
+			chan->chan_id, lnwc->ch_id);
+	lnwc->completed = chan->cookie = 1;
+
+	chan->client_count++;
+
+	spin_lock_bh(&lnwc->lock);
+	while (lnwc->descs_allocated < DESCS_PER_CHANNEL) {
+		spin_unlock_bh(&lnwc->lock);
+		desc = pci_pool_alloc(lnw->dma_pool, GFP_KERNEL, &phys);
+		if (!desc) {
+			dma_err("desc failed\n");
+			return -ENOMEM;
+			/*check*/
+		}
+		dma_async_tx_descriptor_init(&desc->txd, chan);
+		desc->txd.tx_submit = lnw_dma2_tx_submit;
+		desc->txd.flags = DMA_CTRL_ACK;
+		desc->txd.phys = phys;
+		spin_lock_bh(&lnwc->lock);
+		i = ++lnwc->descs_allocated;
+		list_add_tail(&desc->desc_node, &lnwc->free_list);
+	}
+	spin_unlock_bh(&lnwc->lock);
+	lnwc->in_use = false;
+	dma_dbg("Desc alloc done ret: %d desc\n", i);
+	return i;
+}
+
+static void lnwc_handle_error(struct lnwdma_device *lnw,
+		struct lnw_dma_chan *lnwc)
+{
+	lnwc_scan_descriptors(lnw, lnwc);
+}
+
+/******************************************************************************
+* PCI stuff
+*/
+static struct pci_device_id lnw_dma2_ids[] = {
+	{ PCI_VENDOR_ID_INTEL, 0x0813, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, lnw_dma2_ids);
+
+static struct pci_driver lnw_dma2_pci = {
+	.name		=	"Intel LNW DMA2",
+	.id_table	=	lnw_dma2_ids,
+	.probe		=	lnw_dma2_probe,
+	.remove		=	__devexit_p(lnw_dma2_remove),
+};
+
+static void dma_tasklet(unsigned long data)
+{
+	struct lnwdma_device *lnw = NULL;
+	struct lnw_dma_chan *lnwc = NULL;
+	u32 status;
+	int i, ch_no;
+
+	dma_dbg("called \n");
+	lnw = (struct lnwdma_device *)data;
+	if (lnw == NULL) {
+		dma_err("Null param \n");
+		return;
+	}
+
+	status = ioread32(lnw->dma_base + RAW_TFR);
+	dma_dbg("RAW_TFR %x \n", status);
+	while (status) {
+		/*txn interrupt*/
+		ch_no = get_ch_num(&status);
+		if (ch_no < 0) {
+			dma_err("Ch no is invalid %x, abort!\n", ch_no);
+			return;
+		}
+		dma_dbg("Got Ch %x, new Status %x \n", ch_no, status);
+		i = get_ch_index(ch_no);
+		if (i < 0) {
+			dma_err("Invalid ch index %x\n", i);
+			return;
+		}
+		dma_dbg("Tx complete interrupt %x, Ch No %d Index %d \n",
+				status, ch_no, i);
+		lnwc = &lnw->ch[i];
+		if (lnwc == NULL) {
+			dma_err("Null param lnwc\n");
+			return;
+		}
+		dma_dbg("CH %x \n", lnwc->ch_id);
+		spin_lock_bh(&lnwc->lock);
+		lnwc_scan_descriptors(lnw, lnwc);
+		dma_dbg("Scan of desc... complete, unmasking\n");
+		iowrite32((1 << lnwc->ch_id),
+				lnw->dma_base + CLEAR_TFR);
+		dma_dbg("Wrote to clear %x\n", (1 << lnwc->ch_id));
+		iowrite32((1 << lnwc->ch_id),
+				lnw->dma_base + CLEAR_BLOCK);
+		iowrite32(UNMASK_INTR_REG(lnwc->ch_id),
+				lnw->dma_base + MASK_TFR);
+		spin_unlock_bh(&lnwc->lock);
+	}
+
+	dma_dbg("Trf interrupt done... \n");
+	status = ioread32(lnw->dma_base + RAW_ERR);
+	while (status) {
+		/*err interrupt*/
+		ch_no = get_ch_num(&status);
+		if (ch_no < 0) {
+			dma_err("Ch no is invalid %x, abort!\n", ch_no);
+			return;
+		}
+		dma_dbg("Got Ch %x, new Status %x \n", ch_no, status);
+		i = get_ch_index(ch_no);
+		if (i < 0) {
+			dma_err("Invalid CH lnwc\n");
+			return;
+		}
+		dma_dbg("Tx error interrupt %x, No %d Index %d \n",
+				status, ch_no, i);
+		lnwc = &lnw->ch[i];
+		if (lnwc == NULL) {
+			dma_err("Null param lnwc\n");
+			return;
+		}
+		spin_lock_bh(&lnwc->lock);
+		lnwc_handle_error(lnw, lnwc);
+		iowrite32((1 << lnwc->ch_id),
+				lnw->dma_base + CLEAR_ERR);
+		iowrite32(UNMASK_INTR_REG(lnwc->ch_id),
+				lnw->dma_base + MASK_ERR);
+		spin_unlock_bh(&lnwc->lock);
+	}
+	dma_dbg("Exiting takslet... \n");
+	return;
+}
+
+static irqreturn_t lnw_dma2_interrupt(int irq, void *data)
+{
+	struct lnw_device *lnw = data;
+	u32 status;
+	int call_tasklet = 0;
+
+	/*will mask interrupt for now and schedule tasklet
+	tasklet shud unmask and clear*/
+	status = ioread32(lnw->dma_base + STATUS_TFR);
+	status &= 0x03;
+	if (status) {
+		iowrite32((status << 8), lnw->dma_base + MASK_TFR);
+		call_tasklet = 1;
+	}
+	status = ioread32(lnw->dma_base + STATUS_ERR);
+	status &= 0x03;
+	if (status) {
+		iowrite32(MASK_INTR_REG(status), lnw->dma_base + MASK_ERR);
+		call_tasklet = 1;
+	}
+
+	if (call_tasklet)
+		tasklet_schedule(&lnw->dma->tasklet);
+
+	return IRQ_HANDLED;
+}
+
+static void enable_dma2_interrupt(struct lnw_dma_chan *lnwc)
+{
+	dma_dbg("Called for ch_id %d\n", lnwc->ch_id);
+
+	iowrite32(REG_BIT0, lnwc->dma->dma_base + DMA_CFG);
+	/*en ch interrupts */
+	iowrite32(UNMASK_INTR_REG(lnwc->ch_id), lnwc->dma_base + MASK_TFR);
+	iowrite32(UNMASK_INTR_REG(lnwc->ch_id), lnwc->dma_base + MASK_ERR);
+	return;
+}
+
+static void disable_dma2_interrupt(struct lnw_device *device)
+{
+	u32 status = 0;
+
+	/*todo*/
+	dma_dbg(" called \n");
+	status = 1;
+	return;
+
+}
+
+static int lnw_setup_dma2(struct pci_dev *pdev)
+{
+	struct lnw_device *device = pci_get_drvdata(pdev);
+	struct lnwdma_device *dma = NULL;
+	int err, i;
+
+	dma_dbg("setup_dma called \n");
+	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
+	if (NULL == dma) {
+		dma_err("kzalloc failed \n");
+		err = -ENOMEM;
+		goto err_kzalloc;
+	}
+	device->dma = dma;
+	dma->pdev = pdev;
+	dma->dma_base = device->dma_base;
+
+	/* DMA coherent memory pool for DMA descriptor allocations */
+	dma->dma_pool = pci_pool_create("dma_desc_pool", pdev,
+					sizeof(struct lnw_dma_desc),
+					32, 0);
+	if (NULL == dma->dma_pool) {
+		dma_err("pci_pool_create failed \n");
+		err = -ENOMEM;
+		kfree(dma);
+		goto err_dma_pool;
+	}
+
+	INIT_LIST_HEAD(&dma->common.channels);
+
+
+	/*init CH structures*/
+	for (i = 0; i < MAX_CHAN; i++) {
+		struct lnw_dma_chan *lnwch = &dma->ch[i];
+
+		lnwch->chan.device = &dma->common;
+		lnwch->chan.cookie =  1;
+		lnwch->chan.chan_id = i;
+		lnwch->ch_id = get_ch_id(i);
+		dma_dbg("Init CH %d, ID %d \n", i, lnwch->ch_id);
+
+		lnwch->dma_base = dma->dma_base;
+		lnwch->ch_regs = dma->dma_base + DMA_CH_SIZE * lnwch->ch_id;
+		lnwch->dma = dma;
+		spin_lock_init(&lnwch->lock);
+
+		INIT_LIST_HEAD(&lnwch->active_list);
+		INIT_LIST_HEAD(&lnwch->queue);
+		INIT_LIST_HEAD(&lnwch->free_list);
+
+		/*mask interrupts*/
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_BLOCK);
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_SRC_TRAN);
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_DST_TRAN);
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_ERR);
+		iowrite32(MASK_INTR_REG(lnwch->ch_id),
+			dma->dma_base + MASK_TFR);
+
+		dma_dbg("Init CH %d, ID %d \n", i, lnwch->ch_id);
+		list_add_tail(&lnwch->chan.device_node, &dma->common.channels);
+	}
+
+	/*init dma structure*/
+	dma_cap_zero(dma->common.cap_mask);
+	dma_cap_set(DMA_MEMCPY, dma->common.cap_mask);
+	dma_cap_set(DMA_SLAVE, dma->common.cap_mask);
+	dma_cap_set(DMA_PRIVATE, dma->common.cap_mask);
+	dma->common.dev = &pdev->dev;
+	dma->common.chancnt = MAX_CHAN;
+
+	dma->common.device_alloc_chan_resources =
+					lnw_dma2_alloc_chan_resources;
+	dma->common.device_free_chan_resources =
+					lnw_dma2_free_chan_resources;
+
+	dma->common.device_is_tx_complete = lnw_dma2_tx_is_complete;
+	dma->common.device_prep_dma_memcpy = lnw_dma2_prep_memcpy;
+	dma->common.device_issue_pending = lnw_dma2_issue_pending;
+	dma->common.device_prep_slave_sg = lnw_dma2_prep_slave_sg;
+	dma->common.device_terminate_all = lnw_dma2_terminate_all;
+
+	/*enable dma cntrl*/
+	iowrite32(REG_BIT0, dma->dma_base + DMA_CFG);
+
+	disable_dma2_interrupt(device);
+
+	/*register irq*/
+	err = request_irq(pdev->irq, lnw_dma2_interrupt,
+			0, lnw_dma2_pci.name, device);
+	if (0 != err)
+		goto err_irq;
+
+	/*register device w/ engine*/
+	err = dma_async_device_register(&dma->common);
+	if (0 != err) {
+		dma_err("device_register failed: %d \n", err);
+		goto err_engine;
+	}
+	tasklet_init(&dma->tasklet, dma_tasklet, (unsigned long)dma);
+	dma_dbg("...done\n");
+	return 0;
+
+err_engine:
+	free_irq(pdev->irq, device);
+err_irq:
+	pci_pool_destroy(dma->dma_pool);
+	kfree(dma);
+err_dma_pool:
+err_kzalloc:
+	dma_err("setup_dma failed: %d \n", err);
+	return err;
+
+}
+
+static void lnwdma_shutdown(struct pci_dev *pdev)
+{
+	struct lnw_device *device = pci_get_drvdata(pdev);
+
+	dma_dbg("shutdown called \n");
+	dma_async_device_unregister(&device->dma->common);
+	pci_pool_destroy(device->dma->dma_pool);
+	if (device->dma_base)
+		iounmap(device->dma_base);
+	free_irq(pdev->irq, device);
+	return;
+}
+static int __devinit
+lnw_dma2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct lnw_device *device = NULL;
+	u32 base_addr = 0, bar_size = 0;
+	int err = 0;
+
+	dma_info("probe called for %x \n", pdev->device);
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_enable_device;
+
+	err = pci_request_regions(pdev, lnw_dma2_pci.name);
+	if (err)
+		goto err_request_regions;
+
+	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (err)
+		goto err_set_dma_mask;
+
+	err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+	if (err)
+		goto err_set_dma_mask;
+
+	device = kzalloc(sizeof(*device), GFP_KERNEL);
+	if (!device) {
+		dma_err("kzalloc failed \n");
+		err = -ENOMEM;
+		goto err_kzalloc;
+	}
+	device->pdev = pci_dev_get(pdev);
+
+	base_addr = pci_resource_start(pdev, 0);
+	bar_size  = pci_resource_len(pdev, 0);
+	dma_dbg("BAR0 %x Size %x \n", base_addr, bar_size);
+	device->dma_base = ioremap_nocache(base_addr, DMA_REG_SIZE);
+	if (!device->dma_base) {
+		dma_err("ioremap failed \n");
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	pci_set_drvdata(pdev, device);
+	pci_set_master(pdev);
+
+	err = lnw_setup_dma2(pdev);
+	if (err)
+		goto err_dma;
+
+	return 0;
+
+err_dma:
+	iounmap(device->dma_base);
+err_ioremap:
+	pci_dev_put(pdev);
+	kfree(device);
+err_kzalloc:
+err_set_dma_mask:
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+err_request_regions:
+err_enable_device:
+	dma_err("Probe failed %d\n", err);
+	return err;
+}
+
+static void __devexit lnw_dma2_remove(struct pci_dev *pdev)
+{
+	struct lnw_device *device = pci_get_drvdata(pdev);
+
+	lnwdma_shutdown(pdev);
+	pci_dev_put(pdev);
+	kfree(device);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static int __init lnw_dma2_init(void)
+{
+	dma_info("LNW DMA Driver\n Version %s \n", LNW_DMA_DRIVER_VERSION);
+	return pci_register_driver(&lnw_dma2_pci);
+}
+fs_initcall(lnw_dma2_init);
+
+static void __exit lnw_dma2_exit(void)
+{
+	pci_unregister_driver(&lnw_dma2_pci);
+}
+module_exit(lnw_dma2_exit);
+
Index: linux-2.6.33/include/linux/lnw_dma.h
===================================================================
--- /dev/null
+++ linux-2.6.33/include/linux/lnw_dma.h
@@ -0,0 +1,166 @@
+/*
+ *  lnw_dma.c - Intel Langwell DMA Drivers
+ *
+ *  Copyright (C) 2008i-09 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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; version 2 of the License.
+ *
+ *  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 __LNW_DMA_H__
+#define __LNW_DMA_H__
+
+#include <linux/dmaengine.h>
+
+/*DMA transaction width, src and dstn width would be same
+The DMA length must be width aligned,
+for 32 bit width the length must be 32 bit (4bytes) aligned only*/
+enum lnw_dma_width {
+	LNW_DMA_WIDTH_8BIT = 0x0,
+	LNW_DMA_WIDTH_16BIT = 0x1,
+	LNW_DMA_WIDTH_32BIT = 0x2,
+};
+
+/*DMA mode configurations*/
+enum lnw_dma_mode {
+	LNW_DMA_PER_TO_MEM = 0, /*periphral to memory configuration*/
+	LNW_DMA_MEM_TO_PER,	/*memory to periphral configuration*/
+	LNW_DMA_MEM_TO_MEM,	/*mem to mem confg (testing only)*/
+};
+
+/*DMA handshaking*/
+enum lnw_dma_hs_mode {
+	LNW_DMA_HW_HS = 0,	/*HW Handshaking only*/
+	LNW_DMA_SW_HS = 1,	/*SW Handshaking not recommended*/
+};
+
+/*Burst size configuration*/
+enum lnw_dma_msize {
+	LNW_DMA_MSIZE_1 = 0x0,
+	LNW_DMA_MSIZE_4 = 0x1,
+	LNW_DMA_MSIZE_8 = 0x2,
+	LNW_DMA_MSIZE_16 = 0x3,
+	LNW_DMA_MSIZE_32 = 0x4,
+	LNW_DMA_MSIZE_64 = 0x5,
+};
+
+/**
+ * struct lnw_dma_slave - DMA slave structure
+ *
+ * @dma_dev: DMA master client
+ * @tx_reg: physical address of data register used for
+ *	memory-to-peripheral transfers
+ * @rx_reg: physical address of data register used for
+ *	peripheral-to-memory transfers
+ * @tx_width: tx register width
+ * @rx_width: rx register width
+ * @dirn: DMA trf direction
+
+ * @cfg_hi: Platform-specific initializer for the CFG_HI register
+ * @cfg_lo: Platform-specific initializer for the CFG_LO register
+
+ * @ tx_width: width of src and dstn
+ * @ hs_mode: SW or HW handskaking mode
+ * @ cfg_mode: Mode configuration, DMA mem to mem to dev & mem
+ */
+struct lnw_dma_slave {
+	enum dma_data_direction	dirn;
+	enum lnw_dma_width	src_width; /*width of DMA src txn*/
+	enum lnw_dma_width	dst_width; /*width of DMA dst txn*/
+	enum lnw_dma_hs_mode	hs_mode;  /*handshaking*/
+	enum lnw_dma_mode	cfg_mode; /*mode configuration*/
+	enum lnw_dma_msize	src_msize; /*size if src burst*/
+	enum lnw_dma_msize	dst_msize; /*size of dst burst*/
+	dma_async_tx_callback 	callback; /*callback function*/
+	void 			*callback_param; /*param for callback*/
+};
+
+/*DMA channel control registers*/
+union lnw_dma_ctl_lo {
+	struct 	{
+		u32	int_en:1;	/*enable or disable interrupts*/
+					/*should be 0*/
+		u32	dst_tr_width:3;	/*destination transfer width*/
+					/*usually 32 bits = 010*/
+		u32	src_tr_width:3; /*source transfer width*/
+					/*usually 32 bits = 010*/
+		u32	dinc:2;		/*destination address inc/dec*/
+					/*For mem:INC=00, Periphral NoINC=11*/
+		u32	sinc:2;		/*source address inc or dec, as above*/
+		u32	dst_msize:3;	/*destination burst transaction length*/
+					/*always = 16 ie 011*/
+		u32	src_msize:3;	/*source burst transaction length*/
+					/*always = 16 ie 011*/
+		u32	reser1:3;
+		u32	tt_fc:3;	/*transfer type and flow controller*/
+					/*M-M = 000
+					  P-M = 010
+					  M-P = 001*/
+		u32	dms:2;		/*destination master select = 0*/
+		u32	sms:2;		/*source master select = 0*/
+		u32	llp_dst_en:1;	/*enable/disable destination LLP = 0*/
+		u32	llp_src_en:1;	/*enable/disable source LLP = 0*/
+		u32	reser2:3;
+	} ctlx;
+	u32	ctl_lo;
+};
+
+union lnw_dma_ctl_hi {
+	struct {
+		u32	block_ts:12;	/*block transfer size*/
+					/*configured by DMAC*/
+		u32	reser:20;
+	} ctlx;
+	u32	ctl_hi;
+
+};
+
+/*DMA channel configuration registers*/
+union lnw_dma_cfg_lo {
+	struct {
+		u32	reser1:5;
+		u32	ch_prior:3;	/*channel priority = 0*/
+		u32	ch_susp:1;	/*channel suspend = 0*/
+		u32	fifo_empty:1;	/*FIFO empty or not R bit = 0*/
+		u32	hs_sel_dst:1;	/*select HW/SW destn handshaking*/
+					/*HW = 0, SW = 1*/
+		u32	hs_sel_src:1;	/*select HW/SW src handshaking*/
+		u32	reser2:6;
+		u32	dst_hs_pol:1;	/*dest HS interface polarity*/
+		u32	src_hs_pol:1;	/*src HS interface polarity*/
+		u32	max_abrst:10;	/*max AMBA burst len = 0 (no sw limit*/
+		u32	reload_src:1;	/*auto reload src addr =1 if src is P*/
+		u32	reload_dst:1;	/*AR destn addr =1 if dstn is P*/
+	} cfgx;
+	u32	cfg_lo;
+};
+
+union lnw_dma_cfg_hi {
+	struct {
+		u32	fcmode:1;	/*flow control mode = 1*/
+		u32	fifo_mode:1;	/*FIFO mode select = 1*/
+		u32	protctl:3;	/*protection control = 0*/
+		u32	rsvd:2;
+		u32	src_per:4;	/*src hw HS interface*/
+		u32	dst_per:4;	/*dstn hw HS interface*/
+		u32	reser2:17;
+	} cfgx;
+	u32	cfg_hi;
+};
+
+#endif /*__LNW_DMA_H__*/
Index: linux-2.6.33/include/linux/intel_mid.h
===================================================================
--- /dev/null
+++ linux-2.6.33/include/linux/intel_mid.h
@@ -0,0 +1,144 @@
+/*
+ *  intel_mid.h - Netlink multicast interface definition for OSPM.
+ *
+ *  Copyright (C) 2009 Intel Corp
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Authors: 	Sujith Thomas
+ *		Rajeev D Muralidhar
+ *		Vishwesh M Rudramuni
+ *		Nithish Mahalingam
+ * Contact information:
+ *		Sujith Thomas <sujith.thomas@intel.com>
+ *		Rajeev D Muralidhar <rajeev.d.muralidhar@intel.com>
+ * 		Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>
+ * 		Nithish Mahalingam <nithish.mahalingam@intel.com>
+ *
+ */
+
+#ifndef INTEL_MID_H
+#define INTEL_MID_H
+
+#define PMU1_MAX_DEVS   2
+#define PMU2_MAX_DEVS   12
+#define PERIPH_MAX_DEVS 3
+#define MAX_DEVICES   	(PMU1_MAX_DEVS + PMU2_MAX_DEVS + PERIPH_MAX_DEVS)
+#define WAKE_CAPABLE	0x80000000
+
+struct pci_dev_info {
+	u16 vendor_id;
+	u16 device_id;
+	u16 log_subsysid;
+	u16 phy_susbsysid;
+	u32 capability;
+	struct pci_dev *dev_driver;
+	char *dev_name;
+};
+
+struct mid_ospm {
+	u32 *pmu1_base;
+	u32 *pmu1_pm_base;
+	void __iomem *pmu2_base;
+	u32 *pm_table_base;
+	u32 pmu1_sub_systems;
+	u32 pmu2_sub_systems;
+	u32 pmu_wake_cfg;
+	u32 pmu_wake_ss_states;
+	u32 perepheral_sub_systems;
+	int pmu2_states;
+	int platform_sx_state;
+	int s0ix_retry_enb;
+	int fast_retry_exit;
+	u32 pmode;
+};
+
+extern struct pci_dev_info platform_pci_devices[MAX_DEVICES];
+extern unsigned long g_intel_mid_wakeup_address;
+
+enum pmu_ss_state {
+	SS_STATE_D0I0 = 0,
+	SS_STATE_D0I1 = 1,
+	SS_STATE_D0I2 = 2,
+	SS_STATE_D0I3 = 3
+};
+
+enum eospm_events {
+	OSPM_EVENT_SUBSYS_INACTIVITY,
+	OSPM_EVENT_SUBSYS_WAKE,
+	OSPM_EVENT_SUBSYS_START_PLAY,
+	OSPM_EVENT_SUBSYS_STOP_PLAY,
+	OSPM_EVENT_CMD_SUCCESS,
+	OSPM_EVENT_CMD_ERROR,
+	OSPM_EVENT_CMD_NO_C6_ERROR,
+	OSPM_EVENT_AUDIO_BUF_EMPTY,
+	OSPM_EVENT_AUDIO_BUF_FULL,
+	OSPM_EVENT_THERMAL_AUX0,
+	OSPM_EVENT_THERMAL_AUX1,
+	OSPM_EVENT_THERMAL_CRITICAL,
+	OSPM_EVENT_THERMAL_DEV_FAULT,
+	__OSPM_EVENT_COUNT,
+};
+
+#define AUDIO_SUBSYTEM_ID	25
+#define MID_S0I1_STATE  	1
+#define MID_S0I3_STATE  	3
+/* Thermal device Id */
+#define TEMP_DEV_ID1     40
+#define TEMP_DEV_ID2     41
+#define TEMP_DEV_ID3     42
+
+/* First 32 (0-31) originators are subsystems
+   Next 8 (0-7) are cmd IDs */
+#define OSPM_CMDID_OFFSET 32
+#define OSPM_MAX_CMD_ID 8
+
+struct ospm_genl_event {
+	u32 orig;
+	enum eospm_events event;
+};
+
+/* attributes of ospm_genl_family */
+enum {
+	OSPM_GENL_ATTR_UNSPEC,
+	OSPM_GENL_ATTR_EVENT,	/* OSPM event info needed by user space */
+	__OSPM_GENL_ATTR_MAX,
+};
+#define OSPM_GENL_ATTR_MAX (__OSPM_GENL_ATTR_MAX - 1)
+
+/* commands supported by the ospm_genl_family */
+
+enum {
+	OSPM_GENL_CMD_UNSPEC,
+	OSPM_GENL_CMD_EVENT,	/* kernel->user notifications for OSPM events */
+	__OSPM_GENL_CMD_MAX,
+};
+#define OSPM_GENL_CMD_MAX (__OSPM_GENL_CMD_MAX - 1)
+
+#define OSPM_GENL_FAMILY_NAME		"ospm_event"
+#define OSPM_GENL_VERSION		0x01
+#define OSPM_GENL_MCAST_GROUP_NAME 	"ospm_mc_group"
+
+int ospm_generate_netlink_event(u32 orig, enum eospm_events event);
+int ospm_event_genetlink_init(void);
+void ospm_event_genetlink_exit(void);
+
+extern void intel_mid_reserve_bootmem(void);
+extern unsigned long g_intel_mid_wakeup_address;
+extern void find_pci_info(u32 device_id, u32 vendor_id, u32 *index);
+extern int s0ix_non_bsp_init(void);
+
+#endif
