All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device
@ 2010-11-24 12:51 G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 01/14] OMAP: DMA: Replace read/write macros with functions G, Manjunath Kondaiah
                   ` (14 more replies)
  0 siblings, 15 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Patch series to convert DMA library into platform driver using platform
device model and adapting hwmod for omap2+.
	
The initial patches in the patch series(first 6 patches) prepares 
existing DMA library for getting converted into platform driver.

steps used:
1. The low level read/write macros are converted into static inline functions
so that, these functions can be moved to respective mach-omap driver
files later.
(Thanks to Tony and Kevin for their suggestions on handling all omap register
offset without adding extra enums)
2. Implements generic errata handling for all OMAP DMA errata.
3. DMA hwmod data is updated for respective hwmod db files.
4. The DMA library is split into two layers.
   a. The generic code is retained in plat-omap/dma.c
   b. The machine specific code and API's are moved to
      respective mach-omap dma files.
5. All cpu_*is_* checks are replaced with device attributes and cpu_*is_*
are used only in mach-omap init functions.
6. Desriptor autoloading feature is added and followed by applicable erratum 
for the same.
7. The sysconfig register access for errata handling is replaced with API's
Note: This feature has dependency on the patch:
https://patchwork.kernel.org/patch/352481/
8. PM runtime API's are used.

Patch series applies on top of latest linux omap master branch:
*************************************************************************
git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
Branch: master
commit 25f7615faa843731af4eda7d05077f1c5132e1a9
Merge: 784bee8 8973a21
Author: Tony Lindgren <tony@atomide.com>

    Linux-omap rebuilt: Updated to -rc3
*************************************************************************

Test Report:
************
Build:
omap2plus_defconfig    : Success
omap_h2_1610_defconfig : Success

Boot:
OMAP2430SDP            : Success
OMAP3630Zoom3          : Success
OMAP4430Blaze(ES2.1)   : Success          
OMAP1                  : Not tested

Unit tests:
Test results are same as v4 test results which can be acccessed at:
OMAP4BLAZE   : http://pastebin.com/HVnim30G
OMAP3630ZOOM3: http://pastebin.com/JJwrtP4F
OMAP243SDP   : http://pastebin.com/mz7cVQL3

Test cases executed:
1. All applicable TI DMA tests which are located at:
http://dev.omapzoom.org/?p=richo/device_driver_test.git;a=tree;f=dma/test_code;h=0d00de3c0fe6933b405c62da63f694883f3e4b8f;hb=2c50a5a58dea0ffc2d31b827935aeef9b9d11253

2. Use case tests :  TI MMC tests are executed with different types of
file systems such as DOS, ext2, ext3 etc on omap4 blaze and omap3630 zoom3. 
More information can be found at:
http://dev.omapzoom.org/?p=richo/device_driver_test.git;a=tree;f=mmc/test_code;h=d0bc1984eef46ac45719efb02b5c1f4193422a1b;hb=2c50a5a58dea0ffc2d31b827935aeef9b9d11253

Dependencies:
************
This patch series has dependency on omap_device patch:
https://patchwork.kernel.org/patch/352481/

Changelist summary:
v4: Review comments fixed:
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg37879.html 
https://patchwork.kernel.org/patch/308362/
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg38268.html

v3:
Review comments fixed:
http://www.listware.net/201008/linux-omap/89002-patch-v2-0011-omap-dma-hwmod-and-dma-as-platform-driver.html
 - created and tested on latest linux-omap master branch(2.6.36 kernel)

v2:
The review comments which are fixed can be found at:
http://www.spinics.net/lists/linux-omap/msg34291.html
http://www.spinics.net/lists/linux-omap/msg34292.html
http://www.spinics.net/lists/linux-omap/msg34078.html
http://www.spinics.net/lists/linux-omap/msg34083.html

v1:
These changes are based on comments received during internal discussions which has changes(compared to previous version) such as:
 - Code optimization
 - Patches are rearranged in more meaningful way so that git bisect works at any
   intermediate patch in the series.
 - Build tested for all omap's(OMAP1 and OMAP2PLUS)
 - Boot tested for OMAP3 and OMAP4(appreciate if some one tests on OMAP1/2)
 - Applicalbe tests are executed on OMAP3 and OMAP4 boards
 - Rebased and added descriptor autoloading feature(only for omap3630 and omap4)

Patch Summary:
**************

Benoit Cousson (1):
  OMAP4: hwmod data: add system DMA

G, Manjunath Kondaiah (12):
  OMAP: DMA: Replace read/write macros with functions
  OMAP: DMA: Introduce errata handling feature
  OMAP2420: hwmod data: add system DMA
  OMAP2430: hwmod data: add system DMA
  OMAP3: hwmod data: add system DMA
  OMAP1: DMA: Implement in platform device model
  OMAP2+: DMA: hwmod: Device registration
  OMAP: DMA: Convert DMA library into platform driver
  OMAP: DMA: Use DMA device attributes
  OMAP3630: DMA: Add work around for erratum i557
  OMAP2+: DMA: Replace sysconfig register access with API's
  OMAP: PM: DMA: Enable runtime pm

Venkatraman S (1):
  OMAP2+: DMA: descriptor autoloading feature

 arch/arm/mach-omap1/Makefile               |    2 +-
 arch/arm/mach-omap1/dma.c                  |  691 +++++++++++
 arch/arm/mach-omap2/Makefile               |    2 +-
 arch/arm/mach-omap2/dma.c                  | 1608 ++++++++++++++++++++++++
 arch/arm/mach-omap2/include/mach/dma.h     |  143 +++
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   87 ++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   87 ++
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   96 ++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |  100 ++
 arch/arm/plat-omap/dma.c                   | 1822 +++-------------------------
 arch/arm/plat-omap/include/plat/dma.h      |  420 ++++---
 11 files changed, 3250 insertions(+), 1808 deletions(-)
 create mode 100644 arch/arm/mach-omap1/dma.c
 create mode 100644 arch/arm/mach-omap2/dma.c
 create mode 100644 arch/arm/mach-omap2/include/mach/dma.h

Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 01/14] OMAP: DMA: Replace read/write macros with functions
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 02/14] OMAP: DMA: Introduce errata handling feature G, Manjunath Kondaiah
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Prepare DMA library to get converted into DMA driver using platform
device model using hwmod infrastucture for omap2+ and resource structures
for omap1.

The low level read/write macros are replaced with static inline
functions and register offsets are handled through static register
offset tables mapped through  enumeration constants.

These low level read/write functions along with static register offset
tables will be moved to respective mach-omap dma files in the later
patches of this series.

There are no functionality changes with these changes except change in
logic for handling 16bit registers of OMAP1.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/plat-omap/dma.c              |  517 ++++++++++++++++++++-------------
 arch/arm/plat-omap/include/plat/dma.h |  151 ++--------
 2 files changed, 345 insertions(+), 323 deletions(-)

diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 2c28265..df0f326 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -40,6 +40,96 @@
 
 #undef DEBUG
 
+static u16 reg_map_omap1[] = {
+	[GCR]		= 0x400,
+	[GSCR]		= 0x404,
+	[GRST1]		= 0x408,
+	[HW_ID]		= 0x442,
+	[PCH2_ID]	= 0x444,
+	[PCH0_ID]	= 0x446,
+	[PCH1_ID]	= 0x448,
+	[PCHG_ID]	= 0x44a,
+	[PCHD_ID]	= 0x44c,
+	[CAPS_0]	= 0x44e,
+	[CAPS_1]	= 0x452,
+	[CAPS_2]	= 0x456,
+	[CAPS_3]	= 0x458,
+	[CAPS_4]	= 0x45a,
+	[PCH2_SR]	= 0x460,
+	[PCH0_SR]	= 0x480,
+	[PCH1_SR]	= 0x482,
+	[PCHD_SR]	= 0x4c0,
+
+	/* Common Registers */
+	[CSDP]		= 0x00,
+	[CCR]		= 0x02,
+	[CICR]		= 0x04,
+	[CSR]		= 0x06,
+	[CEN]		= 0x10,
+	[CFN]		= 0x12,
+	[CSFI]		= 0x14,
+	[CSEI]		= 0x16,
+	[CPC]		= 0x18,	/* 15xx only */
+	[CSAC]		= 0x18,
+	[CDAC]		= 0x1a,
+	[CDEI]		= 0x1c,
+	[CDFI]		= 0x1e,
+	[CLNK_CTRL]	= 0x28,
+
+	/* Channel specific register offsets */
+	[CSSA]		= 0x08,
+	[CDSA]		= 0x0c,
+	[COLOR]		= 0x20,
+	[CCR2]		= 0x24,
+	[LCH_CTRL]	= 0x2a,
+};
+
+static u16 reg_map_omap2[] = {
+	[REVISION]		= 0x00,
+	[GCR]			= 0x78,
+	[IRQSTATUS_L0]		= 0x08,
+	[IRQSTATUS_L1]		= 0x0c,
+	[IRQSTATUS_L2]		= 0x10,
+	[IRQSTATUS_L3]		= 0x14,
+	[IRQENABLE_L0]		= 0x18,
+	[IRQENABLE_L1]		= 0x1c,
+	[IRQENABLE_L2]		= 0x20,
+	[IRQENABLE_L3]		= 0x24,
+	[SYSSTATUS]		= 0x28,
+	[OCP_SYSCONFIG]		= 0x2c,
+	[CAPS_0]		= 0x64,
+	[CAPS_2]		= 0x6c,
+	[CAPS_3]		= 0x70,
+	[CAPS_4]		= 0x74,
+
+	/* Common register offsets */
+	[CCR]			= 0x80,
+	[CLNK_CTRL]		= 0x84,
+	[CICR]			= 0x88,
+	[CSR]			= 0x8c,
+	[CSDP]			= 0x90,
+	[CEN]			= 0x94,
+	[CFN]			= 0x98,
+	[CSEI]			= 0xa4,
+	[CSFI]			= 0xa8,
+	[CDEI]			= 0xac,
+	[CDFI]			= 0xb0,
+	[CSAC]			= 0xb4,
+	[CDAC]			= 0xb8,
+
+	/* Channel specific register offsets */
+	[CSSA]			= 0x9c,
+	[CDSA]			= 0xa0,
+	[CCEN]			= 0xbc,
+	[CCFN]			= 0xc0,
+	[COLOR]			= 0xc4,
+
+	/* OMAP4 specific registers */
+	[CDP]			= 0xd0,
+	[CNDP]			= 0xd4,
+	[CCDN]			= 0xd8,
+};
+
 #ifndef CONFIG_ARCH_OMAP1
 enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
 	DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
@@ -138,6 +228,9 @@ static int omap_dma_reserve_channels;
 static spinlock_t dma_chan_lock;
 static struct omap_dma_lch *dma_chan;
 static void __iomem *omap_dma_base;
+static u16 *reg_map;
+static u8 dma_stride;
+static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
 
 static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = {
 	INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
@@ -154,23 +247,48 @@ static inline void omap_enable_channel_irq(int lch);
 #define REVISIT_24XX()		printk(KERN_ERR "FIXME: no %s on 24xx\n", \
 						__func__);
 
-#define dma_read(reg)							\
-({									\
-	u32 __val;							\
-	if (cpu_class_is_omap1())					\
-		__val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg);	\
-	else								\
-		__val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg);	\
-	__val;								\
-})
-
-#define dma_write(val, reg)						\
-({									\
-	if (cpu_class_is_omap1())					\
-		__raw_writew((u16)(val), omap_dma_base + OMAP1_DMA_##reg); \
-	else								\
-		__raw_writel((val), omap_dma_base + OMAP_DMA4_##reg);	\
-})
+static inline void dma_write(u32 val, int reg, int lch)
+{
+	u8  stride;
+	u32 offset;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+
+	if (dma_stride  == 0x40) {
+		__raw_writew(val, omap_dma_base + offset);
+		if ((reg > CLNK_CTRL && reg < CCEN) ||
+				(reg > PCHD_ID && reg < CAPS_2)) {
+			u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+			__raw_writew(val >> 16, omap_dma_base + offset2);
+		}
+	} else {
+		__raw_writel(val, omap_dma_base + offset);
+	}
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+	u8 stride;
+	u32 offset, val;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+
+	if (dma_stride  == 0x40) {
+		val = __raw_readw(omap_dma_base + offset);
+		if ((reg > CLNK_CTRL && reg < CCEN) ||
+				(reg > PCHD_ID && reg < CAPS_2)) {
+			u16 upper;
+			u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+			upper = __raw_readw(omap_dma_base + offset2);
+			val |= (upper << 16);
+		}
+	} else {
+		val = __raw_readl(omap_dma_base + offset);
+	}
+	return val;
+}
 
 #ifdef CONFIG_ARCH_OMAP15XX
 /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
@@ -209,11 +327,10 @@ static inline void set_gdma_dev(int req, int dev)
 /* Omap1 only */
 static void clear_lch_regs(int lch)
 {
-	int i;
-	void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch);
+	int i = dma_common_ch_start;
 
-	for (i = 0; i < 0x2c; i += 2)
-		__raw_writew(0, lch_base + i);
+	for (; i <= dma_common_ch_end; i += 1)
+		dma_write(0, i, lch);
 }
 
 void omap_set_dma_priority(int lch, int dst_port, int priority)
@@ -248,12 +365,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
 	if (cpu_class_is_omap2()) {
 		u32 ccr;
 
-		ccr = dma_read(CCR(lch));
+		ccr = dma_read(CCR, lch);
 		if (priority)
 			ccr |= (1 << 6);
 		else
 			ccr &= ~(1 << 6);
-		dma_write(ccr, CCR(lch));
+		dma_write(ccr, CCR, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_priority);
@@ -264,31 +381,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 {
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = dma_read(CSDP, lch);
 	l &= ~0x03;
 	l |= data_type;
-	dma_write(l, CSDP(lch));
+	dma_write(l, CSDP, lch);
 
 	if (cpu_class_is_omap1()) {
 		u16 ccr;
 
-		ccr = dma_read(CCR(lch));
+		ccr = dma_read(CCR, lch);
 		ccr &= ~(1 << 5);
 		if (sync_mode == OMAP_DMA_SYNC_FRAME)
 			ccr |= 1 << 5;
-		dma_write(ccr, CCR(lch));
+		dma_write(ccr, CCR, lch);
 
-		ccr = dma_read(CCR2(lch));
+		ccr = dma_read(CCR2, lch);
 		ccr &= ~(1 << 2);
 		if (sync_mode == OMAP_DMA_SYNC_BLOCK)
 			ccr |= 1 << 2;
-		dma_write(ccr, CCR2(lch));
+		dma_write(ccr, CCR2, lch);
 	}
 
 	if (cpu_class_is_omap2() && dma_trigger) {
 		u32 val;
 
-		val = dma_read(CCR(lch));
+		val = dma_read(CCR, lch);
 
 		/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
 		val &= ~((1 << 23) | (3 << 19) | 0x1f);
@@ -313,11 +430,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 		} else {
 			val &= ~(1 << 24);	/* dest synch */
 		}
-		dma_write(val, CCR(lch));
+		dma_write(val, CCR, lch);
 	}
 
-	dma_write(elem_count, CEN(lch));
-	dma_write(frame_count, CFN(lch));
+	dma_write(elem_count, CEN, lch);
+	dma_write(frame_count, CFN, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 
@@ -328,7 +445,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 	if (cpu_class_is_omap1()) {
 		u16 w;
 
-		w = dma_read(CCR2(lch));
+		w = dma_read(CCR2, lch);
 		w &= ~0x03;
 
 		switch (mode) {
@@ -343,23 +460,22 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 		default:
 			BUG();
 		}
-		dma_write(w, CCR2(lch));
+		dma_write(w, CCR2, lch);
 
-		w = dma_read(LCH_CTRL(lch));
+		w = dma_read(LCH_CTRL, lch);
 		w &= ~0x0f;
 		/* Default is channel type 2D */
 		if (mode) {
-			dma_write((u16)color, COLOR_L(lch));
-			dma_write((u16)(color >> 16), COLOR_U(lch));
+			dma_write(color, COLOR, lch);
 			w |= 1;		/* Channel type G */
 		}
-		dma_write(w, LCH_CTRL(lch));
+		dma_write(w, LCH_CTRL, lch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		u32 val;
 
-		val = dma_read(CCR(lch));
+		val = dma_read(CCR, lch);
 		val &= ~((1 << 17) | (1 << 16));
 
 		switch (mode) {
@@ -374,10 +490,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 		default:
 			BUG();
 		}
-		dma_write(val, CCR(lch));
+		dma_write(val, CCR, lch);
 
 		color &= 0xffffff;
-		dma_write(color, COLOR(lch));
+		dma_write(color, COLOR, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_color_mode);
@@ -387,10 +503,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
 	if (cpu_class_is_omap2()) {
 		u32 csdp;
 
-		csdp = dma_read(CSDP(lch));
+		csdp = dma_read(CSDP, lch);
 		csdp &= ~(0x3 << 16);
 		csdp |= (mode << 16);
-		dma_write(csdp, CSDP(lch));
+		dma_write(csdp, CSDP, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_write_mode);
@@ -400,10 +516,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
 	if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
 		u32 l;
 
-		l = dma_read(LCH_CTRL(lch));
+		l = dma_read(LCH_CTRL, lch);
 		l &= ~0x7;
 		l |= mode;
-		dma_write(l, LCH_CTRL(lch));
+		dma_write(l, LCH_CTRL, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_channel_mode);
@@ -418,27 +534,21 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 	if (cpu_class_is_omap1()) {
 		u16 w;
 
-		w = dma_read(CSDP(lch));
+		w = dma_read(CSDP, lch);
 		w &= ~(0x1f << 2);
 		w |= src_port << 2;
-		dma_write(w, CSDP(lch));
+		dma_write(w, CSDP, lch);
 	}
 
-	l = dma_read(CCR(lch));
+	l = dma_read(CCR, lch);
 	l &= ~(0x03 << 12);
 	l |= src_amode << 12;
-	dma_write(l, CCR(lch));
+	dma_write(l, CCR, lch);
 
-	if (cpu_class_is_omap1()) {
-		dma_write(src_start >> 16, CSSA_U(lch));
-		dma_write((u16)src_start, CSSA_L(lch));
-	}
+	dma_write(src_start, CSSA, lch);
 
-	if (cpu_class_is_omap2())
-		dma_write(src_start, CSSA(lch));
-
-	dma_write(src_ei, CSEI(lch));
-	dma_write(src_fi, CSFI(lch));
+	dma_write(src_ei, CSEI, lch);
+	dma_write(src_fi, CSFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_params);
 
@@ -466,8 +576,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx)
 	if (cpu_class_is_omap2())
 		return;
 
-	dma_write(eidx, CSEI(lch));
-	dma_write(fidx, CSFI(lch));
+	dma_write(eidx, CSEI, lch);
+	dma_write(fidx, CSFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_index);
 
@@ -475,11 +585,11 @@ void omap_set_dma_src_data_pack(int lch, int enable)
 {
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = dma_read(CSDP, lch);
 	l &= ~(1 << 6);
 	if (enable)
 		l |= (1 << 6);
-	dma_write(l, CSDP(lch));
+	dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_data_pack);
 
@@ -488,7 +598,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	unsigned int burst = 0;
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = dma_read(CSDP, lch);
 	l &= ~(0x03 << 7);
 
 	switch (burst_mode) {
@@ -524,7 +634,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	}
 
 	l |= (burst << 7);
-	dma_write(l, CSDP(lch));
+	dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
 
@@ -536,27 +646,21 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
 	u32 l;
 
 	if (cpu_class_is_omap1()) {
-		l = dma_read(CSDP(lch));
+		l = dma_read(CSDP, lch);
 		l &= ~(0x1f << 9);
 		l |= dest_port << 9;
-		dma_write(l, CSDP(lch));
+		dma_write(l, CSDP, lch);
 	}
 
-	l = dma_read(CCR(lch));
+	l = dma_read(CCR, lch);
 	l &= ~(0x03 << 14);
 	l |= dest_amode << 14;
-	dma_write(l, CCR(lch));
-
-	if (cpu_class_is_omap1()) {
-		dma_write(dest_start >> 16, CDSA_U(lch));
-		dma_write(dest_start, CDSA_L(lch));
-	}
+	dma_write(l, CCR, lch);
 
-	if (cpu_class_is_omap2())
-		dma_write(dest_start, CDSA(lch));
+	dma_write(dest_start, CDSA, lch);
 
-	dma_write(dst_ei, CDEI(lch));
-	dma_write(dst_fi, CDFI(lch));
+	dma_write(dst_ei, CDEI, lch);
+	dma_write(dst_fi, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_params);
 
@@ -565,8 +669,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx)
 	if (cpu_class_is_omap2())
 		return;
 
-	dma_write(eidx, CDEI(lch));
-	dma_write(fidx, CDFI(lch));
+	dma_write(eidx, CDEI, lch);
+	dma_write(fidx, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_index);
 
@@ -574,11 +678,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable)
 {
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = dma_read(CSDP, lch);
 	l &= ~(1 << 13);
 	if (enable)
 		l |= 1 << 13;
-	dma_write(l, CSDP(lch));
+	dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
 
@@ -587,7 +691,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	unsigned int burst = 0;
 	u32 l;
 
-	l = dma_read(CSDP(lch));
+	l = dma_read(CSDP, lch);
 	l &= ~(0x03 << 14);
 
 	switch (burst_mode) {
@@ -620,7 +724,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 		return;
 	}
 	l |= (burst << 14);
-	dma_write(l, CSDP(lch));
+	dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
 
@@ -630,18 +734,18 @@ static inline void omap_enable_channel_irq(int lch)
 
 	/* Clear CSR */
 	if (cpu_class_is_omap1())
-		status = dma_read(CSR(lch));
+		status = dma_read(CSR, lch);
 	else if (cpu_class_is_omap2())
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
+		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
 
 	/* Enable some nice interrupts. */
-	dma_write(dma_chan[lch].enabled_irqs, CICR(lch));
+	dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
 }
 
 static void omap_disable_channel_irq(int lch)
 {
 	if (cpu_class_is_omap2())
-		dma_write(0, CICR(lch));
+		dma_write(0, CICR, lch);
 }
 
 void omap_enable_dma_irq(int lch, u16 bits)
@@ -660,7 +764,7 @@ static inline void enable_lnk(int lch)
 {
 	u32 l;
 
-	l = dma_read(CLNK_CTRL(lch));
+	l = dma_read(CLNK_CTRL, lch);
 
 	if (cpu_class_is_omap1())
 		l &= ~(1 << 14);
@@ -675,18 +779,18 @@ static inline void enable_lnk(int lch)
 			l = dma_chan[lch].next_linked_ch | (1 << 15);
 #endif
 
-	dma_write(l, CLNK_CTRL(lch));
+	dma_write(l, CLNK_CTRL, lch);
 }
 
 static inline void disable_lnk(int lch)
 {
 	u32 l;
 
-	l = dma_read(CLNK_CTRL(lch));
+	l = dma_read(CLNK_CTRL, lch);
 
 	/* Disable interrupts */
 	if (cpu_class_is_omap1()) {
-		dma_write(0, CICR(lch));
+		dma_write(0, CICR, lch);
 		/* Set the STOP_LNK bit */
 		l |= 1 << 14;
 	}
@@ -697,7 +801,7 @@ static inline void disable_lnk(int lch)
 		l &= ~(1 << 15);
 	}
 
-	dma_write(l, CLNK_CTRL(lch));
+	dma_write(l, CLNK_CTRL, lch);
 	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
@@ -710,9 +814,9 @@ static inline void omap2_enable_irq_lch(int lch)
 		return;
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
-	val = dma_read(IRQENABLE_L0);
+	val = dma_read(IRQENABLE_L0, lch);
 	val |= 1 << lch;
-	dma_write(val, IRQENABLE_L0);
+	dma_write(val, IRQENABLE_L0, lch);
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -725,9 +829,9 @@ static inline void omap2_disable_irq_lch(int lch)
 		return;
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
-	val = dma_read(IRQENABLE_L0);
+	val = dma_read(IRQENABLE_L0, lch);
 	val &= ~(1 << lch);
-	dma_write(val, IRQENABLE_L0);
+	dma_write(val, IRQENABLE_L0, lch);
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -792,17 +896,17 @@ int omap_request_dma(int dev_id, const char *dev_name,
 		 * Disable the 1510 compatibility mode and set the sync device
 		 * id.
 		 */
-		dma_write(dev_id | (1 << 10), CCR(free_ch));
+		dma_write(dev_id | (1 << 10), CCR, free_ch);
 	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
-		dma_write(dev_id, CCR(free_ch));
+		dma_write(dev_id, CCR, free_ch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		omap2_enable_irq_lch(free_ch);
 		omap_enable_channel_irq(free_ch);
 		/* Clear the CSR register and IRQ status register */
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch));
-		dma_write(1 << free_ch, IRQSTATUS_L0);
+		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch);
+		dma_write(1 << free_ch, IRQSTATUS_L0, 0);
 	}
 
 	*dma_ch_out = free_ch;
@@ -823,23 +927,23 @@ void omap_free_dma(int lch)
 
 	if (cpu_class_is_omap1()) {
 		/* Disable all DMA interrupts for the channel. */
-		dma_write(0, CICR(lch));
+		dma_write(0, CICR, lch);
 		/* Make sure the DMA transfer is stopped. */
-		dma_write(0, CCR(lch));
+		dma_write(0, CCR, lch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		omap2_disable_irq_lch(lch);
 
 		/* Clear the CSR register and IRQ status register */
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
-		dma_write(1 << lch, IRQSTATUS_L0);
+		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+		dma_write(1 << lch, IRQSTATUS_L0, lch);
 
 		/* Disable all DMA interrupts for the channel. */
-		dma_write(0, CICR(lch));
+		dma_write(0, CICR, lch);
 
 		/* Make sure the DMA transfer is stopped. */
-		dma_write(0, CCR(lch));
+		dma_write(0, CCR, lch);
 		omap_clear_dma(lch);
 	}
 
@@ -880,7 +984,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
 	reg |= (0x3 & tparams) << 12;
 	reg |= (arb_rate & 0xff) << 16;
 
-	dma_write(reg, GCR);
+	dma_write(reg, GCR, 0);
 }
 EXPORT_SYMBOL(omap_dma_set_global_params);
 
@@ -903,14 +1007,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
 		printk(KERN_ERR "Invalid channel id\n");
 		return -EINVAL;
 	}
-	l = dma_read(CCR(lch));
+	l = dma_read(CCR, lch);
 	l &= ~((1 << 6) | (1 << 26));
 	if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
 		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
 	else
 		l |= ((read_prio & 0x1) << 6);
 
-	dma_write(l, CCR(lch));
+	dma_write(l, CCR, lch);
 
 	return 0;
 }
@@ -929,19 +1033,18 @@ void omap_clear_dma(int lch)
 	if (cpu_class_is_omap1()) {
 		u32 l;
 
-		l = dma_read(CCR(lch));
+		l = dma_read(CCR, lch);
 		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR(lch));
+		dma_write(l, CCR, lch);
 
 		/* Clear pending interrupts */
-		l = dma_read(CSR(lch));
+		l = dma_read(CSR, lch);
 	}
 
 	if (cpu_class_is_omap2()) {
-		int i;
-		void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch);
-		for (i = 0; i < 0x44; i += 4)
-			__raw_writel(0, lch_base + i);
+		int i = dma_common_ch_start;
+		for (; i <= dma_common_ch_end; i += 1)
+			dma_write(0, i, lch);
 	}
 
 	local_irq_restore(flags);
@@ -957,9 +1060,9 @@ void omap_start_dma(int lch)
 	 * before starting dma transfer.
 	 */
 	if (cpu_is_omap15xx())
-		dma_write(0, CPC(lch));
+		dma_write(0, CPC, lch);
 	else
-		dma_write(0, CDAC(lch));
+		dma_write(0, CDAC, lch);
 
 	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
 		int next_lch, cur_lch;
@@ -989,12 +1092,12 @@ void omap_start_dma(int lch)
 		(cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0)) {
 
 		/* Errata: Need to write lch even if not using chaining */
-		dma_write(lch, CLNK_CTRL(lch));
+		dma_write(lch, CLNK_CTRL, lch);
 	}
 
 	omap_enable_channel_irq(lch);
 
-	l = dma_read(CCR(lch));
+	l = dma_read(CCR, lch);
 
 	/*
 	 * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
@@ -1010,7 +1113,7 @@ void omap_start_dma(int lch)
 		l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
 
 	l |= OMAP_DMA_CCR_EN;
-	dma_write(l, CCR(lch));
+	dma_write(l, CCR, lch);
 
 	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 }
@@ -1022,41 +1125,41 @@ void omap_stop_dma(int lch)
 
 	/* Disable all interrupts on the channel */
 	if (cpu_class_is_omap1())
-		dma_write(0, CICR(lch));
+		dma_write(0, CICR, lch);
 
-	l = dma_read(CCR(lch));
+	l = dma_read(CCR, lch);
 	/* OMAP3 Errata i541: sDMA FIFO draining does not finish */
 	if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
 		int i = 0;
 		u32 sys_cf;
 
 		/* Configure No-Standby */
-		l = dma_read(OCP_SYSCONFIG);
+		l = dma_read(OCP_SYSCONFIG, lch);
 		sys_cf = l;
 		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
 		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
-		dma_write(l , OCP_SYSCONFIG);
+		dma_write(l , OCP_SYSCONFIG, 0);
 
-		l = dma_read(CCR(lch));
+		l = dma_read(CCR, lch);
 		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR(lch));
+		dma_write(l, CCR, lch);
 
 		/* Wait for sDMA FIFO drain */
-		l = dma_read(CCR(lch));
+		l = dma_read(CCR, lch);
 		while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
 					OMAP_DMA_CCR_WR_ACTIVE))) {
 			udelay(5);
 			i++;
-			l = dma_read(CCR(lch));
+			l = dma_read(CCR, lch);
 		}
 		if (i >= 100)
 			printk(KERN_ERR "DMA drain did not complete on "
 					"lch %d\n", lch);
 		/* Restore OCP_SYSCONFIG */
-		dma_write(sys_cf, OCP_SYSCONFIG);
+		dma_write(sys_cf, OCP_SYSCONFIG, lch);
 	} else {
 		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR(lch));
+		dma_write(l, CCR, lch);
 	}
 
 	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
@@ -1122,19 +1225,19 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 	dma_addr_t offset = 0;
 
 	if (cpu_is_omap15xx())
-		offset = dma_read(CPC(lch));
+		offset = dma_read(CPC, lch);
 	else
-		offset = dma_read(CSAC(lch));
+		offset = dma_read(CSAC, lch);
 
 	/*
 	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
 	 * read before the DMA controller finished disabling the channel.
 	 */
 	if (!cpu_is_omap15xx() && offset == 0)
-		offset = dma_read(CSAC(lch));
+		offset = dma_read(CSAC, lch);
 
 	if (cpu_class_is_omap1())
-		offset |= (dma_read(CSSA_U(lch)) << 16);
+		offset |= (dma_read(CSSA, lch) & 0xFFFF0000);
 
 	return offset;
 }
@@ -1153,19 +1256,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
 	dma_addr_t offset = 0;
 
 	if (cpu_is_omap15xx())
-		offset = dma_read(CPC(lch));
+		offset = dma_read(CPC, lch);
 	else
-		offset = dma_read(CDAC(lch));
+		offset = dma_read(CDAC, lch);
 
 	/*
 	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
 	 * read before the DMA controller finished disabling the channel.
 	 */
 	if (!cpu_is_omap15xx() && offset == 0)
-		offset = dma_read(CDAC(lch));
+		offset = dma_read(CDAC, lch);
 
 	if (cpu_class_is_omap1())
-		offset |= (dma_read(CDSA_U(lch)) << 16);
+		offset |= (dma_read(CDSA, lch) & 0xFFFF0000);
 
 	return offset;
 }
@@ -1173,7 +1276,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos);
 
 int omap_get_dma_active_status(int lch)
 {
-	return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0;
+	return (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;
 }
 EXPORT_SYMBOL(omap_get_dma_active_status);
 
@@ -1186,7 +1289,7 @@ int omap_dma_running(void)
 			return 1;
 
 	for (lch = 0; lch < dma_chan_count; lch++)
-		if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN)
+		if (dma_read(CCR, lch) & OMAP_DMA_CCR_EN)
 			return 1;
 
 	return 0;
@@ -1201,8 +1304,8 @@ void omap_dma_link_lch(int lch_head, int lch_queue)
 {
 	if (omap_dma_in_1510_mode()) {
 		if (lch_head == lch_queue) {
-			dma_write(dma_read(CCR(lch_head)) | (3 << 8),
-								CCR(lch_head));
+			dma_write(dma_read(CCR, lch_head) | (3 << 8),
+								CCR, lch_head);
 			return;
 		}
 		printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1228,8 +1331,8 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
 {
 	if (omap_dma_in_1510_mode()) {
 		if (lch_head == lch_queue) {
-			dma_write(dma_read(CCR(lch_head)) & ~(3 << 8),
-								CCR(lch_head));
+			dma_write(dma_read(CCR, lch_head) & ~(3 << 8),
+								CCR, lch_head);
 			return;
 		}
 		printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1281,15 +1384,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue)
 					lch_queue;
 	}
 
-	l = dma_read(CLNK_CTRL(lch_head));
+	l = dma_read(CLNK_CTRL, lch_head);
 	l &= ~(0x1f);
 	l |= lch_queue;
-	dma_write(l, CLNK_CTRL(lch_head));
+	dma_write(l, CLNK_CTRL, lch_head);
 
-	l = dma_read(CLNK_CTRL(lch_queue));
+	l = dma_read(CLNK_CTRL, lch_queue);
 	l &= ~(0x1f);
 	l |= (dma_chan[lch_queue].next_linked_ch);
-	dma_write(l, CLNK_CTRL(lch_queue));
+	dma_write(l, CLNK_CTRL, lch_queue);
 }
 
 /**
@@ -1565,13 +1668,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 
 	/* Set the params to the free channel */
 	if (src_start != 0)
-		dma_write(src_start, CSSA(lch));
+		dma_write(src_start, CSSA, lch);
 	if (dest_start != 0)
-		dma_write(dest_start, CDSA(lch));
+		dma_write(dest_start, CDSA, lch);
 
 	/* Write the buffer size */
-	dma_write(elem_count, CEN(lch));
-	dma_write(frame_count, CFN(lch));
+	dma_write(elem_count, CEN, lch);
+	dma_write(frame_count, CFN, lch);
 
 	/*
 	 * If the chain is dynamically linked,
@@ -1605,7 +1708,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 				dma_chan[lch].state = DMA_CH_QUEUED;
 				start_dma = 0;
 				if (0 == ((1 << 7) & dma_read(
-					CCR(dma_chan[lch].prev_linked_ch)))) {
+					CCR, dma_chan[lch].prev_linked_ch))) {
 					disable_lnk(dma_chan[lch].
 						    prev_linked_ch);
 					pr_debug("\n prev ch is stopped\n");
@@ -1621,7 +1724,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 			}
 			omap_enable_channel_irq(lch);
 
-			l = dma_read(CCR(lch));
+			l = dma_read(CCR, lch);
 
 			if ((0 == (l & (1 << 24))))
 				l &= ~(1 << 25);
@@ -1632,12 +1735,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 					l |= (1 << 7);
 					dma_chan[lch].state = DMA_CH_STARTED;
 					pr_debug("starting %d\n", lch);
-					dma_write(l, CCR(lch));
+					dma_write(l, CCR, lch);
 				} else
 					start_dma = 0;
 			} else {
 				if (0 == (l & (1 << 7)))
-					dma_write(l, CCR(lch));
+					dma_write(l, CCR, lch);
 			}
 			dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 		}
@@ -1682,7 +1785,7 @@ int omap_start_dma_chain_transfers(int chain_id)
 		omap_enable_channel_irq(channels[0]);
 	}
 
-	l = dma_read(CCR(channels[0]));
+	l = dma_read(CCR, channels[0]);
 	l |= (1 << 7);
 	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
 	dma_chan[channels[0]].state = DMA_CH_STARTED;
@@ -1691,7 +1794,7 @@ int omap_start_dma_chain_transfers(int chain_id)
 		l &= ~(1 << 25);
 	else
 		l |= (1 << 25);
-	dma_write(l, CCR(channels[0]));
+	dma_write(l, CCR, channels[0]);
 
 	dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
 
@@ -1730,18 +1833,18 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	 * DMA Errata:
 	 * Special programming model needed to disable DMA before end of block
 	 */
-	sys_cf = dma_read(OCP_SYSCONFIG);
+	sys_cf = dma_read(OCP_SYSCONFIG, 0);
 	l = sys_cf;
 	/* Middle mode reg set no Standby */
 	l &= ~((1 << 12)|(1 << 13));
-	dma_write(l, OCP_SYSCONFIG);
+	dma_write(l, OCP_SYSCONFIG, 0);
 
 	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
 
 		/* Stop the Channel transmission */
-		l = dma_read(CCR(channels[i]));
+		l = dma_read(CCR, channels[i]);
 		l &= ~(1 << 7);
-		dma_write(l, CCR(channels[i]));
+		dma_write(l, CCR, channels[i]);
 
 		/* Disable the link in all the channels */
 		disable_lnk(channels[i]);
@@ -1754,7 +1857,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	OMAP_DMA_CHAIN_QINIT(chain_id);
 
 	/* Errata - put in the old value */
-	dma_write(sys_cf, OCP_SYSCONFIG);
+	dma_write(sys_cf, OCP_SYSCONFIG, 0);
 
 	return 0;
 }
@@ -1796,8 +1899,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	*ei = dma_read(CCEN(lch));
-	*fi = dma_read(CCFN(lch));
+	*ei = dma_read(CCEN, lch);
+	*fi = dma_read(CCFN, lch);
 
 	return 0;
 }
@@ -1834,7 +1937,7 @@ int omap_get_dma_chain_dst_pos(int chain_id)
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	return dma_read(CDAC(lch));
+	return dma_read(CDAC, lch);
 }
 EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
 
@@ -1868,7 +1971,7 @@ int omap_get_dma_chain_src_pos(int chain_id)
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	return dma_read(CSAC(lch));
+	return dma_read(CSAC, lch);
 }
 EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
 #endif	/* ifndef CONFIG_ARCH_OMAP1 */
@@ -1885,7 +1988,7 @@ static int omap1_dma_handle_ch(int ch)
 		csr = dma_chan[ch].saved_csr;
 		dma_chan[ch].saved_csr = 0;
 	} else
-		csr = dma_read(CSR(ch));
+		csr = dma_read(CSR, ch);
 	if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
 		dma_chan[ch + 6].saved_csr = csr >> 7;
 		csr &= 0x7f;
@@ -1938,13 +2041,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
 
 static int omap2_dma_handle_ch(int ch)
 {
-	u32 status = dma_read(CSR(ch));
+	u32 status = dma_read(CSR, ch);
 
 	if (!status) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
 				ch);
-		dma_write(1 << ch, IRQSTATUS_L0);
+		dma_write(1 << ch, IRQSTATUS_L0, ch);
 		return 0;
 	}
 	if (unlikely(dma_chan[ch].dev_id == -1)) {
@@ -1968,9 +2071,9 @@ static int omap2_dma_handle_ch(int ch)
 			 */
 			u32 ccr;
 
-			ccr = dma_read(CCR(ch));
+			ccr = dma_read(CCR, ch);
 			ccr &= ~OMAP_DMA_CCR_EN;
-			dma_write(ccr, CCR(ch));
+			dma_write(ccr, CCR, ch);
 			dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
 		}
 	}
@@ -1981,16 +2084,16 @@ static int omap2_dma_handle_ch(int ch)
 		printk(KERN_INFO "DMA misaligned error with device %d\n",
 		       dma_chan[ch].dev_id);
 
-	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch));
-	dma_write(1 << ch, IRQSTATUS_L0);
+	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
+	dma_write(1 << ch, IRQSTATUS_L0, ch);
 	/* read back the register to flush the write */
-	dma_read(IRQSTATUS_L0);
+	dma_read(IRQSTATUS_L0, ch);
 
 	/* If the ch is not chained then chain_id will be -1 */
 	if (dma_chan[ch].chain_id != -1) {
 		int chain_id = dma_chan[ch].chain_id;
 		dma_chan[ch].state = DMA_CH_NOTSTARTED;
-		if (dma_read(CLNK_CTRL(ch)) & (1 << 15))
+		if (dma_read(CLNK_CTRL, ch) & (1 << 15))
 			dma_chan[dma_chan[ch].next_linked_ch].state =
 							DMA_CH_STARTED;
 		if (dma_linked_lch[chain_id].chain_mode ==
@@ -2000,10 +2103,10 @@ static int omap2_dma_handle_ch(int ch)
 		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
 			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 
-		status = dma_read(CSR(ch));
+		status = dma_read(CSR, ch);
 	}
 
-	dma_write(status, CSR(ch));
+	dma_write(status, CSR, ch);
 
 	if (likely(dma_chan[ch].callback != NULL))
 		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
@@ -2017,13 +2120,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
 	u32 val, enable_reg;
 	int i;
 
-	val = dma_read(IRQSTATUS_L0);
+	val = dma_read(IRQSTATUS_L0, 0);
 	if (val == 0) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "Spurious DMA IRQ\n");
 		return IRQ_HANDLED;
 	}
-	enable_reg = dma_read(IRQENABLE_L0);
+	enable_reg = dma_read(IRQENABLE_L0, 0);
 	val &= enable_reg; /* Dispatch only relevant interrupts */
 	for (i = 0; i < dma_lch_count && val != 0; i++) {
 		if (val & 1)
@@ -2049,21 +2152,21 @@ static struct irqaction omap24xx_dma_irq;
 void omap_dma_global_context_save(void)
 {
 	omap_dma_global_context.dma_irqenable_l0 =
-		dma_read(IRQENABLE_L0);
+		dma_read(IRQENABLE_L0, 0);
 	omap_dma_global_context.dma_ocp_sysconfig =
-		dma_read(OCP_SYSCONFIG);
-	omap_dma_global_context.dma_gcr = dma_read(GCR);
+		dma_read(OCP_SYSCONFIG, 0);
+	omap_dma_global_context.dma_gcr = dma_read(GCR, 0);
 }
 
 void omap_dma_global_context_restore(void)
 {
 	int ch;
 
-	dma_write(omap_dma_global_context.dma_gcr, GCR);
+	dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
 	dma_write(omap_dma_global_context.dma_ocp_sysconfig,
-		OCP_SYSCONFIG);
+		OCP_SYSCONFIG, 0);
 	dma_write(omap_dma_global_context.dma_irqenable_l0,
-		IRQENABLE_L0);
+		IRQENABLE_L0, 0);
 
 	/*
 	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
@@ -2072,7 +2175,7 @@ void omap_dma_global_context_restore(void)
 	 * affects only secure devices.
 	 */
 	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
-		dma_write(0x3 , IRQSTATUS_L0);
+		dma_write(0x3 , IRQSTATUS_L0, 0);
 
 	for (ch = 0; ch < dma_chan_count; ch++)
 		if (dma_chan[ch].dev_id != -1)
@@ -2106,6 +2209,21 @@ static int __init omap_init_dma(void)
 	omap_dma_base = ioremap(base, SZ_4K);
 	BUG_ON(!omap_dma_base);
 
+	if (cpu_class_is_omap1()) {
+		dma_stride		= 0x40;
+		reg_map			= reg_map_omap1;
+		dma_common_ch_start	= CPC;
+		dma_common_ch_end	= COLOR;
+	} else {
+		dma_stride		= 0x60;
+		reg_map			= reg_map_omap2;
+		dma_common_ch_start	= CSDP;
+		if (cpu_is_omap3630() || cpu_is_omap4430())
+			dma_common_ch_end = CCDN;
+		else
+			dma_common_ch_end = CCFN;
+	}
+
 	if (cpu_class_is_omap2() && omap_dma_reserve_channels
 			&& (omap_dma_reserve_channels <= dma_lch_count))
 		dma_lch_count = omap_dma_reserve_channels;
@@ -2132,26 +2250,23 @@ static int __init omap_init_dma(void)
 		enable_1510_mode = 1;
 	} else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
 		printk(KERN_INFO "OMAP DMA hardware version %d\n",
-		       dma_read(HW_ID));
+		       dma_read(HW_ID, 0));
 		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
-		       (dma_read(CAPS_0_U) << 16) |
-		       dma_read(CAPS_0_L),
-		       (dma_read(CAPS_1_U) << 16) |
-		       dma_read(CAPS_1_L),
-		       dma_read(CAPS_2), dma_read(CAPS_3),
-		       dma_read(CAPS_4));
+		       dma_read(CAPS_0, 0), dma_read(CAPS_1, 0),
+		       dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
+		       dma_read(CAPS_4, 0));
 		if (!enable_1510_mode) {
 			u16 w;
 
 			/* Disable OMAP 3.0/3.1 compatibility mode. */
-			w = dma_read(GSCR);
+			w = dma_read(GSCR, 0);
 			w |= 1 << 3;
-			dma_write(w, GSCR);
+			dma_write(w, GSCR, 0);
 			dma_chan_count = 16;
 		} else
 			dma_chan_count = 9;
 	} else if (cpu_class_is_omap2()) {
-		u8 revision = dma_read(REVISION) & 0xff;
+		u8 revision = dma_read(REVISION, 0) & 0xff;
 		printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
 		       revision >> 4, revision & 0xf);
 		dma_chan_count = dma_lch_count;
@@ -2210,14 +2325,14 @@ static int __init omap_init_dma(void)
 
 	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
 		/* Enable smartidle idlemodes and autoidle */
-		u32 v = dma_read(OCP_SYSCONFIG);
+		u32 v = dma_read(OCP_SYSCONFIG, 0);
 		v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
 				DMA_SYSCONFIG_SIDLEMODE_MASK |
 				DMA_SYSCONFIG_AUTOIDLE);
 		v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
 			DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
 			DMA_SYSCONFIG_AUTOIDLE);
-		dma_write(v , OCP_SYSCONFIG);
+		dma_write(v , OCP_SYSCONFIG, 0);
 		/* reserve dma channels 0 and 1 in high security devices */
 		if (cpu_is_omap34xx() &&
 			(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 0cce4ca..dfb1b10 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -27,136 +27,14 @@
 /* Hardware registers for omap1 */
 #define OMAP1_DMA_BASE			(0xfffed800)
 
-#define OMAP1_DMA_GCR			0x400
-#define OMAP1_DMA_GSCR			0x404
-#define OMAP1_DMA_GRST			0x408
-#define OMAP1_DMA_HW_ID			0x442
-#define OMAP1_DMA_PCH2_ID		0x444
-#define OMAP1_DMA_PCH0_ID		0x446
-#define OMAP1_DMA_PCH1_ID		0x448
-#define OMAP1_DMA_PCHG_ID		0x44a
-#define OMAP1_DMA_PCHD_ID		0x44c
-#define OMAP1_DMA_CAPS_0_U		0x44e
-#define OMAP1_DMA_CAPS_0_L		0x450
-#define OMAP1_DMA_CAPS_1_U		0x452
-#define OMAP1_DMA_CAPS_1_L		0x454
-#define OMAP1_DMA_CAPS_2		0x456
-#define OMAP1_DMA_CAPS_3		0x458
-#define OMAP1_DMA_CAPS_4		0x45a
-#define OMAP1_DMA_PCH2_SR		0x460
-#define OMAP1_DMA_PCH0_SR		0x480
-#define OMAP1_DMA_PCH1_SR		0x482
-#define OMAP1_DMA_PCHD_SR		0x4c0
-
 /* Hardware registers for omap2 and omap3 */
 #define OMAP24XX_DMA4_BASE		(L4_24XX_BASE + 0x56000)
 #define OMAP34XX_DMA4_BASE		(L4_34XX_BASE + 0x56000)
 #define OMAP44XX_DMA4_BASE		(L4_44XX_BASE + 0x56000)
 
-#define OMAP_DMA4_REVISION		0x00
-#define OMAP_DMA4_GCR			0x78
-#define OMAP_DMA4_IRQSTATUS_L0		0x08
-#define OMAP_DMA4_IRQSTATUS_L1		0x0c
-#define OMAP_DMA4_IRQSTATUS_L2		0x10
-#define OMAP_DMA4_IRQSTATUS_L3		0x14
-#define OMAP_DMA4_IRQENABLE_L0		0x18
-#define OMAP_DMA4_IRQENABLE_L1		0x1c
-#define OMAP_DMA4_IRQENABLE_L2		0x20
-#define OMAP_DMA4_IRQENABLE_L3		0x24
-#define OMAP_DMA4_SYSSTATUS		0x28
-#define OMAP_DMA4_OCP_SYSCONFIG		0x2c
-#define OMAP_DMA4_CAPS_0		0x64
-#define OMAP_DMA4_CAPS_2		0x6c
-#define OMAP_DMA4_CAPS_3		0x70
-#define OMAP_DMA4_CAPS_4		0x74
-
 #define OMAP1_LOGICAL_DMA_CH_COUNT	17
 #define OMAP_DMA4_LOGICAL_DMA_CH_COUNT	32	/* REVISIT: Is this 32 + 2? */
 
-/* Common channel specific registers for omap1 */
-#define OMAP1_DMA_CH_BASE(n)		(0x40 * (n) + 0x00)
-#define OMAP1_DMA_CSDP(n)		(0x40 * (n) + 0x00)
-#define OMAP1_DMA_CCR(n)		(0x40 * (n) + 0x02)
-#define OMAP1_DMA_CICR(n)		(0x40 * (n) + 0x04)
-#define OMAP1_DMA_CSR(n)		(0x40 * (n) + 0x06)
-#define OMAP1_DMA_CEN(n)		(0x40 * (n) + 0x10)
-#define OMAP1_DMA_CFN(n)		(0x40 * (n) + 0x12)
-#define OMAP1_DMA_CSFI(n)		(0x40 * (n) + 0x14)
-#define OMAP1_DMA_CSEI(n)		(0x40 * (n) + 0x16)
-#define OMAP1_DMA_CPC(n)		(0x40 * (n) + 0x18)	/* 15xx only */
-#define OMAP1_DMA_CSAC(n)		(0x40 * (n) + 0x18)
-#define OMAP1_DMA_CDAC(n)		(0x40 * (n) + 0x1a)
-#define OMAP1_DMA_CDEI(n)		(0x40 * (n) + 0x1c)
-#define OMAP1_DMA_CDFI(n)		(0x40 * (n) + 0x1e)
-#define OMAP1_DMA_CLNK_CTRL(n)		(0x40 * (n) + 0x28)
-
-/* Common channel specific registers for omap2 */
-#define OMAP_DMA4_CH_BASE(n)		(0x60 * (n) + 0x80)
-#define OMAP_DMA4_CCR(n)		(0x60 * (n) + 0x80)
-#define OMAP_DMA4_CLNK_CTRL(n)		(0x60 * (n) + 0x84)
-#define OMAP_DMA4_CICR(n)		(0x60 * (n) + 0x88)
-#define OMAP_DMA4_CSR(n)		(0x60 * (n) + 0x8c)
-#define OMAP_DMA4_CSDP(n)		(0x60 * (n) + 0x90)
-#define OMAP_DMA4_CEN(n)		(0x60 * (n) + 0x94)
-#define OMAP_DMA4_CFN(n)		(0x60 * (n) + 0x98)
-#define OMAP_DMA4_CSEI(n)		(0x60 * (n) + 0xa4)
-#define OMAP_DMA4_CSFI(n)		(0x60 * (n) + 0xa8)
-#define OMAP_DMA4_CDEI(n)		(0x60 * (n) + 0xac)
-#define OMAP_DMA4_CDFI(n)		(0x60 * (n) + 0xb0)
-#define OMAP_DMA4_CSAC(n)		(0x60 * (n) + 0xb4)
-#define OMAP_DMA4_CDAC(n)		(0x60 * (n) + 0xb8)
-
-/* Channel specific registers only on omap1 */
-#define OMAP1_DMA_CSSA_L(n)		(0x40 * (n) + 0x08)
-#define OMAP1_DMA_CSSA_U(n)		(0x40 * (n) + 0x0a)
-#define OMAP1_DMA_CDSA_L(n)		(0x40 * (n) + 0x0c)
-#define OMAP1_DMA_CDSA_U(n)		(0x40 * (n) + 0x0e)
-#define OMAP1_DMA_COLOR_L(n)		(0x40 * (n) + 0x20)
-#define OMAP1_DMA_COLOR_U(n)		(0x40 * (n) + 0x22)
-#define OMAP1_DMA_CCR2(n)		(0x40 * (n) + 0x24)
-#define OMAP1_DMA_LCH_CTRL(n)		(0x40 * (n) + 0x2a)	/* not on 15xx */
-#define OMAP1_DMA_CCEN(n)		0
-#define OMAP1_DMA_CCFN(n)		0
-
-/* Channel specific registers only on omap2 */
-#define OMAP_DMA4_CSSA(n)		(0x60 * (n) + 0x9c)
-#define OMAP_DMA4_CDSA(n)		(0x60 * (n) + 0xa0)
-#define OMAP_DMA4_CCEN(n)		(0x60 * (n) + 0xbc)
-#define OMAP_DMA4_CCFN(n)		(0x60 * (n) + 0xc0)
-#define OMAP_DMA4_COLOR(n)		(0x60 * (n) + 0xc4)
-
-/* Additional registers available on OMAP4 */
-#define OMAP_DMA4_CDP(n)		(0x60 * (n) + 0xd0)
-#define OMAP_DMA4_CNDP(n)		(0x60 * (n) + 0xd4)
-#define OMAP_DMA4_CCDN(n)		(0x60 * (n) + 0xd8)
-
-/* Dummy defines to keep multi-omap compiles happy */
-#define OMAP1_DMA_REVISION		0
-#define OMAP1_DMA_IRQSTATUS_L0		0
-#define OMAP1_DMA_IRQENABLE_L0		0
-#define OMAP1_DMA_OCP_SYSCONFIG		0
-#define OMAP_DMA4_HW_ID			0
-#define OMAP_DMA4_CAPS_0_L		0
-#define OMAP_DMA4_CAPS_0_U		0
-#define OMAP_DMA4_CAPS_1_L		0
-#define OMAP_DMA4_CAPS_1_U		0
-#define OMAP_DMA4_GSCR			0
-#define OMAP_DMA4_CPC(n)		0
-
-#define OMAP_DMA4_LCH_CTRL(n)		0
-#define OMAP_DMA4_COLOR_L(n)		0
-#define OMAP_DMA4_COLOR_U(n)		0
-#define OMAP_DMA4_CCR2(n)		0
-#define OMAP1_DMA_CSSA(n)		0
-#define OMAP1_DMA_CDSA(n)		0
-#define OMAP_DMA4_CSSA_L(n)		0
-#define OMAP_DMA4_CSSA_U(n)		0
-#define OMAP_DMA4_CDSA_L(n)		0
-#define OMAP_DMA4_CDSA_U(n)		0
-#define OMAP1_DMA_COLOR(n)		0
-
-/*----------------------------------------------------------------------------*/
-
 /* DMA channels for omap1 */
 #define OMAP_DMA_NO_DEVICE		0
 #define OMAP_DMA_MCSI1_TX		1
@@ -405,6 +283,35 @@
 #define DMA_CH_PRIO_HIGH		0x1
 #define DMA_CH_PRIO_LOW			0x0 /* Def */
 
+enum omap_reg_offsets {
+
+GCR,		GSCR,		GRST1,		HW_ID,
+PCH2_ID,	PCH0_ID,	PCH1_ID,	PCHG_ID,
+PCHD_ID,	CAPS_0,		CAPS_1,		CAPS_2,
+CAPS_3,		CAPS_4,		PCH2_SR,	PCH0_SR,
+PCH1_SR,	PCHD_SR,	REVISION,	IRQSTATUS_L0,
+IRQSTATUS_L1,	IRQSTATUS_L2,	IRQSTATUS_L3,	IRQENABLE_L0,
+IRQENABLE_L1,	IRQENABLE_L2,	IRQENABLE_L3,	SYSSTATUS,
+OCP_SYSCONFIG,
+
+/* omap1+ specific */
+CPC, CCR2, LCH_CTRL,
+
+/* Common registers for all omap's */
+CSDP,		CCR,		CICR,		CSR,
+CEN,		CFN,		CSFI,		CSEI,
+CSAC,		CDAC,		CDEI,
+CDFI,		CLNK_CTRL,
+
+/* Channel specific registers */
+CSSA,		CDSA,		COLOR,
+CCEN,		CCFN,
+
+/* omap3630 and omap4 specific */
+CDP,		CNDP,		CCDN,
+
+};
+
 enum omap_dma_burst_mode {
 	OMAP_DMA_DATA_BURST_DIS = 0,
 	OMAP_DMA_DATA_BURST_4,
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 02/14] OMAP: DMA: Introduce errata handling feature
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 01/14] OMAP: DMA: Replace read/write macros with functions G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 03/14] OMAP2420: hwmod data: add system DMA G, Manjunath Kondaiah
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, Peter Ujfalusi, linux-arm-kernel,
	Kevin Hilman, Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Implement errata handling to use flags instead of cpu_is_* and
cpu_class_* in the code.

The errata flags are initialized at init time and during runtime we are
using the errata variable (via the IS_DMA_ERRATA macro) to execute the
required errata workaround.

Reused errata handling patch from: Peter Ujfalusi
<peter.ujfalusi@nokia.com>
https://patchwork.kernel.org/patch/231191/

Changes to above patch:
1. Changes are done for converting all the existing errata work arounds
to use this feature.
2. Detailed description for each errata is added.
3. Fixed bug in SET_DMA_ERRATA macro
4. Bit shifting in macro definitions are replaced with BIT() macro

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/plat-omap/dma.c              |  152 ++++++++++++++++++++++-----------
 arch/arm/plat-omap/include/plat/dma.h |   12 +++
 2 files changed, 114 insertions(+), 50 deletions(-)

diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index df0f326..f73b302 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -144,6 +144,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
 
 static int enable_1510_mode;
+static u32 errata;
 
 static struct omap_dma_global_context_registers {
 	u32 dma_irqenable_l0;
@@ -1088,31 +1089,17 @@ void omap_start_dma(int lch)
 
 			cur_lch = next_lch;
 		} while (next_lch != -1);
-	} else if (cpu_is_omap242x() ||
-		(cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0)) {
-
-		/* Errata: Need to write lch even if not using chaining */
+	} else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
 		dma_write(lch, CLNK_CTRL, lch);
-	}
 
 	omap_enable_channel_irq(lch);
 
 	l = dma_read(CCR, lch);
 
-	/*
-	 * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
-	 * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and
-	 * bursting is enabled. This might result in data gets stalled in
-	 * FIFO at the end of the block.
-	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
-	 * guarantee no data will stay in the DMA FIFO in case inter frame
-	 * buffering occurs.
-	 */
-	if (cpu_is_omap2420() ||
-	    (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0)))
-		l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
-
+	if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
+			l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
 	l |= OMAP_DMA_CCR_EN;
+
 	dma_write(l, CCR, lch);
 
 	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
@@ -1128,8 +1115,8 @@ void omap_stop_dma(int lch)
 		dma_write(0, CICR, lch);
 
 	l = dma_read(CCR, lch);
-	/* OMAP3 Errata i541: sDMA FIFO draining does not finish */
-	if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
+	if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
+			(l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
 		int i = 0;
 		u32 sys_cf;
 
@@ -1229,11 +1216,7 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 	else
 		offset = dma_read(CSAC, lch);
 
-	/*
-	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
-	 * read before the DMA controller finished disabling the channel.
-	 */
-	if (!cpu_is_omap15xx() && offset == 0)
+	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
 		offset = dma_read(CSAC, lch);
 
 	if (cpu_class_is_omap1())
@@ -1814,7 +1797,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
 {
 	int *channels;
 	u32 l, i;
-	u32 sys_cf;
+	u32 sys_cf = 0;
 
 	/* Check for input params */
 	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
@@ -1829,15 +1812,13 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	}
 	channels = dma_linked_lch[chain_id].linked_dmach_q;
 
-	/*
-	 * DMA Errata:
-	 * Special programming model needed to disable DMA before end of block
-	 */
-	sys_cf = dma_read(OCP_SYSCONFIG, 0);
-	l = sys_cf;
-	/* Middle mode reg set no Standby */
-	l &= ~((1 << 12)|(1 << 13));
-	dma_write(l, OCP_SYSCONFIG, 0);
+	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
+		sys_cf = dma_read(OCP_SYSCONFIG, 0);
+		l = sys_cf;
+		/* Middle mode reg set no Standby */
+		l &= ~((1 << 12)|(1 << 13));
+		dma_write(l, OCP_SYSCONFIG, 0);
+	}
 
 	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
 
@@ -1856,8 +1837,8 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	/* Reset the Queue pointers */
 	OMAP_DMA_CHAIN_QINIT(chain_id);
 
-	/* Errata - put in the old value */
-	dma_write(sys_cf, OCP_SYSCONFIG, 0);
+	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+		dma_write(sys_cf, OCP_SYSCONFIG, 0);
 
 	return 0;
 }
@@ -2063,12 +2044,7 @@ static int omap2_dma_handle_ch(int ch)
 	if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
 		printk(KERN_INFO "DMA transaction error with device %d\n",
 		       dma_chan[ch].dev_id);
-		if (cpu_class_is_omap2()) {
-			/*
-			 * Errata: sDMA Channel is not disabled
-			 * after a transaction error. So we explicitely
-			 * disable the channel
-			 */
+		if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
 			u32 ccr;
 
 			ccr = dma_read(CCR, ch);
@@ -2168,13 +2144,7 @@ void omap_dma_global_context_restore(void)
 	dma_write(omap_dma_global_context.dma_irqenable_l0,
 		IRQENABLE_L0, 0);
 
-	/*
-	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
-	 * after secure sram context save and restore. Hence we need to
-	 * manually clear those IRQs to avoid spurious interrupts. This
-	 * affects only secure devices.
-	 */
-	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
+	if (IS_DMA_ERRATA(DMA_ROMCODE_BUG))
 		dma_write(0x3 , IRQSTATUS_L0, 0);
 
 	for (ch = 0; ch < dma_chan_count; ch++)
@@ -2182,6 +2152,87 @@ void omap_dma_global_context_restore(void)
 			omap_clear_dma(ch);
 }
 
+static void configure_dma_errata(void)
+{
+
+	/*
+	 * Errata applicable for OMAP2430ES1.0 and all omap2420
+	 *
+	 * I.
+	 * Erratum ID: Not Available
+	 * Inter Frame DMA buffering issue DMA will wrongly
+	 * buffer elements if packing and bursting is enabled. This might
+	 * result in data gets stalled in FIFO at the end of the block.
+	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+	 * guarantee no data will stay in the DMA FIFO in case inter frame
+	 * buffering occurs
+	 *
+	 * II.
+	 * Erratum ID: Not Available
+	 * DMA may hang when several channels are used in parallel
+	 * In the following configuration, DMA channel hanging can occur:
+	 * a. Channel i, hardware synchronized, is enabled
+	 * b. Another channel (Channel x), software synchronized, is enabled.
+	 * c. Channel i is disabled before end of transfer
+	 * d. Channel i is reenabled.
+	 * e. Steps 1 to 4 are repeated a certain number of times.
+	 * f. A third channel (Channel y), software synchronized, is enabled.
+	 * Channel x and Channel y may hang immediately after step 'f'.
+	 * Workaround:
+	 * For any channel used - make sure NextLCH_ID is set to the value j.
+	 */
+	if (cpu_is_omap2420() || (cpu_is_omap2430() &&
+				(omap_type() == OMAP2430_REV_ES1_0))) {
+		SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
+		SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
+	}
+
+	/*
+	 * Erratum ID: i378: OMAP2plus: sDMA Channel is not disabled
+	 * after a transaction error.
+	 * Workaround: SW should explicitely disable the channel.
+	 */
+	if (cpu_class_is_omap2())
+		SET_DMA_ERRATA(DMA_ERRATA_i378);
+
+	/*
+	 * Erratum ID: i541: sDMA FIFO draining does not finish
+	 * If sDMA channel is disabled on the fly, sDMA enters standby even
+	 * through FIFO Drain is still in progress
+	 * Workaround: Put sDMA in NoStandby more before a logical channel is
+	 * disabled, then put it back to SmartStandby right after the channel
+	 * finishes FIFO draining.
+	 */
+	if (cpu_is_omap34xx())
+		SET_DMA_ERRATA(DMA_ERRATA_i541);
+
+	/*
+	 * Erratum ID: i88 : Special programming model needed to disable DMA
+	 * before end of block.
+	 * Workaround: software must ensure that the DMA is configured in No
+	 * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
+	 */
+	if (omap_type() == OMAP3430_REV_ES1_0)
+		SET_DMA_ERRATA(DMA_ERRATA_i88);
+
+	/*
+	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+	 * read before the DMA controller finished disabling the channel.
+	 */
+	if (!cpu_is_omap15xx())
+		SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+	/*
+	 * Erratum ID: Not Available
+	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
+	 * after secure sram context save and restore.
+	 * Work around: Hence we need to manually clear those IRQs to avoid
+	 * spurious interrupts. This affects only secure devices.
+	 */
+	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
+		SET_DMA_ERRATA(DMA_ROMCODE_BUG);
+}
+
 /*----------------------------------------------------------------------------*/
 
 static int __init omap_init_dma(void)
@@ -2342,6 +2393,7 @@ static int __init omap_init_dma(void)
 			dma_chan[1].dev_id = 1;
 		}
 	}
+	configure_dma_errata();
 
 	return 0;
 
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index dfb1b10..2378399 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -283,6 +283,18 @@
 #define DMA_CH_PRIO_HIGH		0x1
 #define DMA_CH_PRIO_LOW			0x0 /* Def */
 
+/* Errata handling */
+#define IS_DMA_ERRATA(id)		(errata & (id))
+#define SET_DMA_ERRATA(id)		(errata |= (id))
+
+#define DMA_ERRATA_IFRAME_BUFFERING	BIT(0x0)
+#define DMA_ERRATA_PARALLEL_CHANNELS	BIT(0x1)
+#define DMA_ERRATA_i378			BIT(0x2)
+#define DMA_ERRATA_i541			BIT(0x3)
+#define DMA_ERRATA_i88			BIT(0x4)
+#define DMA_ERRATA_3_3			BIT(0x5)
+#define DMA_ROMCODE_BUG			BIT(0x6)
+
 enum omap_reg_offsets {
 
 GCR,		GSCR,		GRST1,		HW_ID,
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 03/14] OMAP2420: hwmod data: add system DMA
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 01/14] OMAP: DMA: Replace read/write macros with functions G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 02/14] OMAP: DMA: Introduce errata handling feature G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 04/14] OMAP2430: " G, Manjunath Kondaiah
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Add OMAP2420 DMA hwmod data and also add required
DMA device attributes.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   87 ++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/dma.h      |   11 ++++
 2 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index a1a3dd6..81aa0d9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -38,6 +38,7 @@ static struct omap_hwmod omap2420_iva_hwmod;
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
 static struct omap_hwmod omap2420_wd_timer2_hwmod;
+static struct omap_hwmod omap2420_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -557,6 +558,89 @@ static struct omap_hwmod omap2420_i2c2_hwmod = {
 	.flags		= HWMOD_16BIT_REG,
 };
 
+/* system dma */
+static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap2420_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+						IS_CSSA_32 | IS_CDSA_32,
+	.lch_count = 32,
+};
+
+static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = {
+	.master		= &omap2420_dma_system_hwmod,
+	.slave		= &omap2420_l3_main_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap2420_dma_system_masters[] = {
+	&omap2420_dma_system__l3,
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dma_system_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap2420_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = {
+	&omap2420_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap2420_dma_system_hwmod = {
+	.name		= "dma",
+	.class		= &omap2420_dma_hwmod_class,
+	.mpu_irqs	= omap2420_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dma_system_irqs),
+	.main_clk	= "l3_div_ck",
+	.slaves		= omap2420_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dma_system_slaves),
+	.masters	= omap2420_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2420_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 	&omap2420_l3_main_hwmod,
 	&omap2420_l4_core_hwmod,
@@ -569,6 +653,9 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 	&omap2420_uart3_hwmod,
 	&omap2420_i2c1_hwmod,
 	&omap2420_i2c2_hwmod,
+
+	/* dma_system class*/
+	&omap2420_dma_system_hwmod,
 	NULL,
 };
 
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 2378399..c466566 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -295,6 +295,13 @@
 #define DMA_ERRATA_3_3			BIT(0x5)
 #define DMA_ROMCODE_BUG			BIT(0x6)
 
+/* Attributes for OMAP DMA Contrller */
+#define DMA_LINKED_LCH			BIT(0x0)
+#define GLOBAL_PRIORITY			BIT(0x1)
+#define RESERVE_CHANNEL			BIT(0x2)
+#define IS_CSSA_32			BIT(0x3)
+#define IS_CDSA_32			BIT(0x4)
+
 enum omap_reg_offsets {
 
 GCR,		GSCR,		GRST1,		HW_ID,
@@ -389,6 +396,10 @@ struct omap_dma_channel_params {
 #endif
 };
 
+struct omap_dma_dev_attr {
+	u32 dev_caps;
+	u16 lch_count;
+};
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 04/14] OMAP2430: hwmod data: add system DMA
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (2 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 03/14] OMAP2420: hwmod data: add system DMA G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 05/14] OMAP3: " G, Manjunath Kondaiah
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Add OMAP2430 DMA hwmod data and also add required
DMA device attributes.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   87 ++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/dma.h      |    1 +
 2 files changed, 88 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 7cf0d3a..bf5c029 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -38,6 +38,7 @@ static struct omap_hwmod omap2430_iva_hwmod;
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
 static struct omap_hwmod omap2430_wd_timer2_hwmod;
+static struct omap_hwmod omap2430_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -569,6 +570,89 @@ static struct omap_hwmod omap2430_i2c2_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
+/* dma_system */
+static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap2430_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+	.lch_count = 32,
+};
+
+static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
+	.master		= &omap2430_dma_system_hwmod,
+	.slave		= &omap2430_l3_main_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = {
+	&omap2430_dma_system__l3,
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dma_system_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap2430_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = {
+	&omap2430_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap2430_dma_system_hwmod = {
+	.name		= "dma",
+	.class		= &omap2430_dma_hwmod_class,
+	.mpu_irqs	= omap2430_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dma_system_irqs),
+	.main_clk	= "l3_div_ck",
+	.slaves		= omap2430_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dma_system_slaves),
+	.masters	= omap2430_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 	&omap2430_l3_main_hwmod,
 	&omap2430_l4_core_hwmod,
@@ -581,6 +665,9 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 	&omap2430_uart3_hwmod,
 	&omap2430_i2c1_hwmod,
 	&omap2430_i2c2_hwmod,
+
+	/* dma_system class*/
+	&omap2430_dma_system_hwmod,
 	NULL,
 };
 
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index c466566..4b51d2b 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -301,6 +301,7 @@
 #define RESERVE_CHANNEL			BIT(0x2)
 #define IS_CSSA_32			BIT(0x3)
 #define IS_CDSA_32			BIT(0x4)
+#define IS_RW_PRIORITY			BIT(0x5)
 
 enum omap_reg_offsets {
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 05/14] OMAP3: hwmod data: add system DMA
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (3 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 04/14] OMAP2430: " G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 06/14] OMAP4: " G, Manjunath Kondaiah
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Add OMAP3 DMA hwmod data

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   96 ++++++++++++++++++++++++++++
 1 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index a8bed84..a928024 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -45,6 +45,7 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
 static struct omap_hwmod omap3xxx_i2c1_hwmod;
 static struct omap_hwmod omap3xxx_i2c2_hwmod;
 static struct omap_hwmod omap3xxx_i2c3_hwmod;
+static struct omap_hwmod omap3xxx_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -739,6 +740,98 @@ static struct omap_hwmod omap3xxx_i2c3_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = {
+	.master		= &omap3xxx_dma_system_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.clk		= "core_l3_ick",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+	.lch_count = 32,
+};
+
+static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap3xxx_dma_sysc,
+};
+
+/* dma_system */
+static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = {
+	&omap3xxx_dma_system__l3,
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dma_system_hwmod,
+	.clk		= "core_l4_ick",
+	.addr		= omap3xxx_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
+	&omap3xxx_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap3xxx_dma_system_hwmod = {
+	.name		= "dma",
+	.class		= &omap3xxx_dma_hwmod_class,
+	.mpu_irqs	= omap3xxx_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dma_system_irqs),
+	.main_clk	= "core_l3_ick",
+	.prcm = {
+		.omap2 = {
+			.module_offs		= CORE_MOD,
+			.prcm_reg_id		= 1,
+			.module_bit		= OMAP3430_ST_SDMA_SHIFT,
+			.idlest_reg_id		= 1,
+			.idlest_idle_bit	= OMAP3430_ST_SDMA_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves),
+	.masters	= omap3xxx_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l3_main_hwmod,
 	&omap3xxx_l4_core_hwmod,
@@ -754,6 +847,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_i2c1_hwmod,
 	&omap3xxx_i2c2_hwmod,
 	&omap3xxx_i2c3_hwmod,
+
+	/* dma_system class*/
+	&omap3xxx_dma_system_hwmod,
 	NULL,
 };
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 06/14] OMAP4: hwmod data: add system DMA
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (4 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 05/14] OMAP3: " G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 07/14] OMAP1: DMA: Implement in platform device model G, Manjunath Kondaiah
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, G, Manjunath Kondaiah, linux-arm-kernel,
	Kevin Hilman, Tony Lindgren, Santosh Shilimkar

From: Benoit Cousson <b-cousson@ti.com>

Add OMAP4 DMA hwmod data

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |  100 ++++++++++++++++++++++++++++
 1 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 0d5c6eb..7197204 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -22,6 +22,7 @@
 
 #include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
+#include <plat/dma.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -35,6 +36,7 @@
 #define OMAP44XX_DMA_REQ_START  1
 
 /* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_dma_system_hwmod;
 static struct omap_hwmod omap44xx_dmm_hwmod;
 static struct omap_hwmod omap44xx_emif_fw_hwmod;
 static struct omap_hwmod omap44xx_l3_instr_hwmod;
@@ -215,6 +217,14 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* dma_system -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
+	.master		= &omap44xx_dma_system_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_cfg -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
 	.master		= &omap44xx_l4_cfg_hwmod,
@@ -226,6 +236,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
 /* l3_main_2 slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
 	&omap44xx_l3_main_1__l3_main_2,
+	&omap44xx_dma_system__l3_main_2,
 	&omap44xx_l4_cfg__l3_main_2,
 };
 
@@ -1043,6 +1054,92 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
+/*
+ * 'dma' class
+ * dma controller for data exchange between memory to memory (i.e. internal or
+ * external memory) and gp peripherals to memory or memory to gp peripherals
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap44xx_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+	.lch_count = 32,
+};
+
+/* dma_system */
+static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "1", .irq = 13 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "2", .irq = 14 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "3", .irq = 15 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x4a056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = {
+	&omap44xx_dma_system__l3_main_2,
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_dma_system_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = {
+	&omap44xx_l4_cfg__dma_system,
+};
+
+static struct omap_hwmod omap44xx_dma_system_hwmod = {
+	.name		= "dma_system",
+	.class		= &omap44xx_dma_hwmod_class,
+	.mpu_irqs	= omap44xx_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dma_system_irqs),
+	.main_clk	= "l3_div_ck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dma_system_slaves),
+	.masters	= omap44xx_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	/* dmm class */
 	&omap44xx_dmm_hwmod,
@@ -1077,6 +1174,9 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	&omap44xx_uart2_hwmod,
 	&omap44xx_uart3_hwmod,
 	&omap44xx_uart4_hwmod,
+
+	/* dma class */
+	&omap44xx_dma_system_hwmod,
 	NULL,
 };
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 07/14] OMAP1: DMA: Implement in platform device model
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (5 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 06/14] OMAP4: " G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 08/14] OMAP2+: DMA: hwmod: Device registration G, Manjunath Kondaiah
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Implement OMAP1 DMA as platform device and add support for
registering through platform device layer using resource
structures.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap1/dma.c |  179 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 179 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap1/dma.c

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
new file mode 100644
index 0000000..b56ee21
--- /dev/null
+++ b/arch/arm/mach-omap1/dma.c
@@ -0,0 +1,179 @@
+/*
+ * OMAP1/OMAP7xx - specific DMA driver
+ *
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
+ * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into platform driver
+ *                   - G, Manjunath Kondaiah <manjugk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <plat/dma.h>
+#include <plat/tc.h>
+#include <plat/irqs.h>
+
+#define OMAP1_DMA_BASE			(0xfffed800)
+
+static struct resource res[] __initdata = {
+	[0] = {
+		.start	= OMAP1_DMA_BASE,
+		.end	= OMAP1_DMA_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name   = "0",
+		.start  = INT_DMA_CH0_6,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.name   = "1",
+		.start  = INT_DMA_CH1_7,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.name   = "2",
+		.start  = INT_DMA_CH2_8,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[4] = {
+		.name   = "3",
+		.start  = INT_DMA_CH3,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[5] = {
+		.name   = "4",
+		.start  = INT_DMA_CH4,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[6] = {
+		.name   = "5",
+		.start  = INT_DMA_CH5,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[7] = {
+		.name   = "6",
+		.start  = INT_DMA_LCD,
+		.flags  = IORESOURCE_IRQ,
+	},
+	/* irq's for omap16xx and omap7xx */
+	[8] = {
+		.name   = "7",
+		.start  = 53 + IH2_BASE,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[9] = {
+		.name   = "8",
+		.start  = 54 + IH2_BASE,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[10] = {
+		.name  = "9",
+		.start = 55 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[11] = {
+		.name  = "10",
+		.start = 56 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[12] = {
+		.name  = "11",
+		.start = 57 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[13] = {
+		.name  = "12",
+		.start = 58 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[14] = {
+		.name  = "13",
+		.start = 59 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[15] = {
+		.name  = "14",
+		.start = 60 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[16] = {
+		.name  = "15",
+		.start = 61 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[17] = {
+		.name  = "16",
+		.start = 62 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static int __init omap1_system_dma_init(void)
+{
+	struct omap_system_dma_plat_info	*p;
+	struct platform_device			*pdev;
+	int ret;
+
+	pdev = platform_device_alloc("omap_dma_system", 0);
+	if (!pdev) {
+		pr_err("%s: Unable to device alloc for dma\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+			__func__, pdev->name, pdev->id);
+		goto exit_device_del;
+	}
+
+	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+	if (!p) {
+		dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
+			__func__, pdev->name);
+		ret = -ENOMEM;
+		goto exit_device_put;
+	}
+
+	ret = platform_device_add_data(pdev, p, sizeof(*p));
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+			__func__, pdev->name, pdev->id);
+		goto exit_device_put;
+	}
+
+	ret = platform_device_add(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+			__func__, pdev->name, pdev->id);
+		goto exit_device_put;
+	}
+
+	return ret;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit_device_del:
+	platform_device_del(pdev);
+
+	return ret;
+}
+arch_initcall(omap1_system_dma_init);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 08/14] OMAP2+: DMA: hwmod: Device registration
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (6 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 07/14] OMAP1: DMA: Implement in platform device model G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver G, Manjunath Kondaiah
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Prepare OMAP2+ DMA to use hwmod infrastructure so that DMA can register
as platform device.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap2/dma.c |   74 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/dma.c

diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
new file mode 100644
index 0000000..e2c897a
--- /dev/null
+++ b/arch/arm/mach-omap2/dma.c
@@ -0,0 +1,74 @@
+/*
+ * OMAP2+ DMA driver
+ *
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
+ * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into platform driver
+ *	- G, Manjunath Kondaiah <manjugk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/dma.h>
+
+static struct omap_device_pm_latency omap2_dma_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func	 = omap_device_enable_hwmods,
+		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+};
+
+/* One time initializations */
+static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
+{
+	struct omap_device			*od;
+	struct omap_system_dma_plat_info	*p;
+	char					*name = "omap_dma_system";
+
+	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+	if (!p) {
+		pr_err("%s: Unable to allocate pdata for %s:%s\n",
+			__func__, name, oh->name);
+		return -ENOMEM;
+	}
+
+	od = omap_device_build(name, 0, oh, p, sizeof(*p),
+			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+	kfree(p);
+	if (IS_ERR(od)) {
+		pr_err("%s: Cant build omap_device for %s:%s.\n",
+			__func__, name, oh->name);
+		return IS_ERR(od);
+	}
+
+	return 0;
+}
+
+static int __init omap2_system_dma_init(void)
+{
+	return (omap_hwmod_for_each_by_class("dma",
+			omap2_system_dma_init_dev, NULL));
+}
+arch_initcall(omap2_system_dma_init);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (7 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 08/14] OMAP2+: DMA: hwmod: Device registration G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-12-02 18:44     ` Tony Lindgren
  2010-11-24 12:51 ` [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes G, Manjunath Kondaiah
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Convert DMA library into DMA platform driver and make use of
platform data provided by hwmod data base for OMAP2+ onwards.

For OMAP1 processors, the DMA driver in mach-omap uses resource
structures for getting platform data.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap1/Makefile          |    2 +-
 arch/arm/mach-omap1/dma.c             |  198 ++++++++-
 arch/arm/mach-omap2/Makefile          |    2 +-
 arch/arm/mach-omap2/dma.c             |  223 +++++++++
 arch/arm/plat-omap/dma.c              |  792 ++++++++++-----------------------
 arch/arm/plat-omap/include/plat/dma.h |   57 ++-
 6 files changed, 710 insertions(+), 564 deletions(-)

diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index de3cc13..14f69cb 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o
+obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o dma.o
 obj-y += clock.o clock_data.o opp_data.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index b56ee21..06af97a 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -30,6 +30,57 @@
 #include <plat/irqs.h>
 
 #define OMAP1_DMA_BASE			(0xfffed800)
+#define OMAP1_LOGICAL_DMA_CH_COUNT	17
+#define OMAP1_DMA_STRIDE		0x40
+
+static u32 errata;
+static u32 enable_1510_mode;
+static u8 dma_stride;
+static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
+
+static u16 reg_map[] = {
+	[GCR]		= 0x400,
+	[GSCR]		= 0x404,
+	[GRST1]		= 0x408,
+	[HW_ID]		= 0x442,
+	[PCH2_ID]	= 0x444,
+	[PCH0_ID]	= 0x446,
+	[PCH1_ID]	= 0x448,
+	[PCHG_ID]	= 0x44a,
+	[PCHD_ID]	= 0x44c,
+	[CAPS_0]	= 0x44e,
+	[CAPS_1]	= 0x452,
+	[CAPS_2]	= 0x456,
+	[CAPS_3]	= 0x458,
+	[CAPS_4]	= 0x45a,
+	[PCH2_SR]	= 0x460,
+	[PCH0_SR]	= 0x480,
+	[PCH1_SR]	= 0x482,
+	[PCHD_SR]	= 0x4c0,
+
+	/* Common Registers */
+	[CSDP]		= 0x00,
+	[CCR]		= 0x02,
+	[CICR]		= 0x04,
+	[CSR]		= 0x06,
+	[CEN]		= 0x10,
+	[CFN]		= 0x12,
+	[CSFI]		= 0x14,
+	[CSEI]		= 0x16,
+	[CPC]		= 0x18,	/* 15xx only */
+	[CSAC]		= 0x18,
+	[CDAC]		= 0x1a,
+	[CDEI]		= 0x1c,
+	[CDFI]		= 0x1e,
+	[CLNK_CTRL]	= 0x28,
+
+	/* Channel specific register offsets */
+	[CSSA]		= 0x08,
+	[CDSA]		= 0x0c,
+	[COLOR]		= 0x20,
+	[CCR2]		= 0x24,
+	[LCH_CTRL]	= 0x2a,
+};
 
 static struct resource res[] __initdata = {
 	[0] = {
@@ -125,9 +176,100 @@ static struct resource res[] __initdata = {
 	},
 };
 
+static void __iomem *dma_base;
+static inline void dma_write(u32 val, int reg, int lch)
+{
+	u8  stride;
+	u32 offset;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+
+	__raw_writew(val, dma_base + offset);
+	if ((reg > CLNK_CTRL && reg < CCEN) ||
+			(reg > PCHD_ID && reg < CAPS_2)) {
+		u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+		__raw_writew(val >> 16, dma_base + offset2);
+	}
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+	u8 stride;
+	u32 offset, val;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+
+	val = __raw_readw(dma_base + offset);
+	if ((reg > CLNK_CTRL && reg < CCEN) ||
+			(reg > PCHD_ID && reg < CAPS_2)) {
+		u16 upper;
+		u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+		upper = __raw_readw(dma_base + offset2);
+		val |= (upper << 16);
+	}
+	return val;
+}
+
+static void omap1_clear_lch_regs(int lch)
+{
+	int i = dma_common_ch_start;
+
+	for (; i <= dma_common_ch_end; i += 1)
+		dma_write(0, i, lch);
+}
+
+static void omap1_clear_dma(int lch)
+{
+	u32 l;
+
+	l = dma_read(CCR, lch);
+	l &= ~OMAP_DMA_CCR_EN;
+	dma_write(l, CCR, lch);
+
+	/* Clear pending interrupts */
+	l = dma_read(CSR, lch);
+}
+
+static void omap1_show_dma_caps(void)
+{
+	if (enable_1510_mode) {
+		printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
+	} else {
+		u16 w;
+		printk(KERN_INFO "OMAP DMA hardware version %d\n",
+							dma_read(HW_ID, 0));
+		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
+			dma_read(CAPS_0, 0), dma_read(CAPS_1, 0),
+			dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
+			dma_read(CAPS_4, 0));
+
+		/* Disable OMAP 3.0/3.1 compatibility mode. */
+		w = dma_read(GSCR, 0);
+		w |= 1 << 3;
+		dma_write(w, GSCR, 0);
+	}
+	return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+	/*
+	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+	 * read before the DMA controller finished disabling the channel.
+	 */
+	if (!cpu_is_omap15xx())
+		SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+	return errata;
+}
+
 static int __init omap1_system_dma_init(void)
 {
 	struct omap_system_dma_plat_info	*p;
+	struct omap_dma_dev_attr		*d;
 	struct platform_device			*pdev;
 	int ret;
 
@@ -153,22 +295,74 @@ static int __init omap1_system_dma_init(void)
 		goto exit_device_put;
 	}
 
+	d = p->dma_attr;
+	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->lch_count), GFP_KERNEL);
+	if (!d->chan) {
+		dev_err(&pdev->dev, "%s: Memory allocation failed"
+					"for d->chan!!!\n", __func__);
+		goto exit_release_p;
+	}
+
+	/* Valid attributes for omap1 plus processors */
+	if (cpu_is_omap15xx())
+		d->dev_caps = ENABLE_1510_MODE;
+	enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
+
+	d->dev_caps		|= SRC_PORT;
+	d->dev_caps		|= DST_PORT;
+	d->dev_caps		|= SRC_INDEX;
+	d->dev_caps		|= DST_INDEX;
+	d->dev_caps		|= IS_BURST_ONLY4;
+	d->dev_caps		|= CLEAR_CSR_ON_READ;
+	d->dev_caps		|= IS_WORD_16;
+
+	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
+
+	if (cpu_is_omap15xx())
+		d->chan_count = 9;
+	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+		if (!(d->dev_caps & ENABLE_1510_MODE))
+			d->chan_count = 16;
+		else
+			d->chan_count = 9;
+	}
+
+	dma_base		= (void __iomem *)res[0].start;
+
+	p->show_dma_caps	= omap1_show_dma_caps;
+	p->clear_lch_regs	= omap1_clear_lch_regs;
+	p->clear_dma		= omap1_clear_dma;
+	p->dma_write		= dma_write;
+	p->dma_read		= dma_read;
+	p->disable_irq_lch	= NULL;
+
+	p->errata = configure_dma_errata();
+
 	ret = platform_device_add_data(pdev, p, sizeof(*p));
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
-		goto exit_device_put;
+		goto exit_release_chan;
 	}
 
 	ret = platform_device_add(pdev);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
-		goto exit_device_put;
+		goto exit_release_chan;
 	}
 
+	dma_stride		= OMAP1_DMA_STRIDE;
+	dma_common_ch_start	= CPC;
+	dma_common_ch_end	= COLOR;
+
 	return ret;
 
+exit_release_chan:
+	kfree(d->chan);
+exit_release_p:
+	kfree(p);
 exit_device_put:
 	platform_device_put(pdev);
 exit_device_del:
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index eb31c9c..adecd04 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
-	 common.o
+	 common.o dma.o
 
 omap-2-3-common				= irq.o sdrc.o prm2xxx_3xxx.o
 hwmod-common				= omap_hwmod.o \
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index e2c897a..4a9a56a 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -32,6 +32,61 @@
 #include <plat/omap_device.h>
 #include <plat/dma.h>
 
+#define OMAP2_DMA_STRIDE	0x60
+
+static u32 errata;
+static u8 dma_stride;
+
+static struct omap_dma_dev_attr *d;
+
+static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
+
+static u16 reg_map[] = {
+	[REVISION]		= 0x00,
+	[GCR]			= 0x78,
+	[IRQSTATUS_L0]		= 0x08,
+	[IRQSTATUS_L1]		= 0x0c,
+	[IRQSTATUS_L2]		= 0x10,
+	[IRQSTATUS_L3]		= 0x14,
+	[IRQENABLE_L0]		= 0x18,
+	[IRQENABLE_L1]		= 0x1c,
+	[IRQENABLE_L2]		= 0x20,
+	[IRQENABLE_L3]		= 0x24,
+	[SYSSTATUS]		= 0x28,
+	[OCP_SYSCONFIG]		= 0x2c,
+	[CAPS_0]		= 0x64,
+	[CAPS_2]		= 0x6c,
+	[CAPS_3]		= 0x70,
+	[CAPS_4]		= 0x74,
+
+	/* Common register offsets */
+	[CCR]			= 0x80,
+	[CLNK_CTRL]		= 0x84,
+	[CICR]			= 0x88,
+	[CSR]			= 0x8c,
+	[CSDP]			= 0x90,
+	[CEN]			= 0x94,
+	[CFN]			= 0x98,
+	[CSEI]			= 0xa4,
+	[CSFI]			= 0xa8,
+	[CDEI]			= 0xac,
+	[CDFI]			= 0xb0,
+	[CSAC]			= 0xb4,
+	[CDAC]			= 0xb8,
+
+	/* Channel specific register offsets */
+	[CSSA]			= 0x9c,
+	[CDSA]			= 0xa0,
+	[CCEN]			= 0xbc,
+	[CCFN]			= 0xc0,
+	[COLOR]			= 0xc4,
+
+	/* OMAP4 specific registers */
+	[CDP]			= 0xd0,
+	[CNDP]			= 0xd4,
+	[CCDN]			= 0xd8,
+};
+
 static struct omap_device_pm_latency omap2_dma_latency[] = {
 	{
 		.deactivate_func = omap_device_idle_hwmods,
@@ -40,13 +95,151 @@ static struct omap_device_pm_latency omap2_dma_latency[] = {
 	},
 };
 
+static void __iomem *dma_base;
+static inline void dma_write(u32 val, int reg, int lch)
+{
+	u8  stride;
+	u32 offset;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+	__raw_writel(val, dma_base + offset);
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+	u8 stride;
+	u32 offset, val;
+
+	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+	offset = reg_map[reg] + (stride * lch);
+	val = __raw_readl(dma_base + offset);
+	return val;
+}
+
+static inline void omap2_disable_irq_lch(int lch)
+{
+	u32 val;
+
+	val = dma_read(IRQENABLE_L0, lch);
+	val &= ~(1 << lch);
+	dma_write(val, IRQENABLE_L0, lch);
+}
+
+static void omap2_clear_dma(int lch)
+{
+	int i = dma_common_ch_start;
+
+	for (; i <= dma_common_ch_end; i += 1)
+		dma_write(0, i, lch);
+}
+
+static void omap2_show_dma_caps(void)
+{
+	u8 revision = dma_read(REVISION, 0) & 0xff;
+	printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
+				revision >> 4, revision & 0xf);
+	return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+	/*
+	 * Errata applicable for OMAP2430ES1.0 and all omap2420
+	 *
+	 * I.
+	 * Erratum ID: Not Available
+	 * Inter Frame DMA buffering issue DMA will wrongly
+	 * buffer elements if packing and bursting is enabled. This might
+	 * result in data gets stalled in FIFO at the end of the block.
+	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+	 * guarantee no data will stay in the DMA FIFO in case inter frame
+	 * buffering occurs
+	 *
+	 * II.
+	 * Erratum ID: Not Available
+	 * DMA may hang when several channels are used in parallel
+	 * In the following configuration, DMA channel hanging can occur:
+	 * a. Channel i, hardware synchronized, is enabled
+	 * b. Another channel (Channel x), software synchronized, is enabled.
+	 * c. Channel i is disabled before end of transfer
+	 * d. Channel i is reenabled.
+	 * e. Steps 1 to 4 are repeated a certain number of times.
+	 * f. A third channel (Channel y), software synchronized, is enabled.
+	 * Channel x and Channel y may hang immediately after step 'f'.
+	 * Workaround:
+	 * For any channel used - make sure NextLCH_ID is set to the value j.
+	 */
+	if (cpu_is_omap2420() || (cpu_is_omap2430() &&
+				(omap_type() == OMAP2430_REV_ES1_0))) {
+
+		SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
+		SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
+	}
+
+	/*
+	 * Erratum ID: i378: OMAP2+: sDMA Channel is not disabled
+	 * after a transaction error.
+	 * Workaround: SW should explicitely disable the channel.
+	 */
+	if (cpu_class_is_omap2())
+		SET_DMA_ERRATA(DMA_ERRATA_i378);
+
+	/*
+	 * Erratum ID: i541: sDMA FIFO draining does not finish
+	 * If sDMA channel is disabled on the fly, sDMA enters standby even
+	 * through FIFO Drain is still in progress
+	 * Workaround: Put sDMA in NoStandby more before a logical channel is
+	 * disabled, then put it back to SmartStandby right after the channel
+	 * finishes FIFO draining.
+	 */
+	if (cpu_is_omap34xx())
+		SET_DMA_ERRATA(DMA_ERRATA_i541);
+
+	/*
+	 * Erratum ID: i88 : Special programming model needed to disable DMA
+	 * before end of block.
+	 * Workaround: software must ensure that the DMA is configured in No
+	 * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
+	 */
+	if (omap_type() == OMAP3430_REV_ES1_0)
+		SET_DMA_ERRATA(DMA_ERRATA_i88);
+
+	/*
+	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+	 * read before the DMA controller finished disabling the channel.
+	 */
+	SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+	/*
+	 * Erratum ID: Not Available
+	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
+	 * after secure sram context save and restore.
+	 * Work around: Hence we need to manually clear those IRQs to avoid
+	 * spurious interrupts. This affects only secure devices.
+	 */
+	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
+		SET_DMA_ERRATA(DMA_ROMCODE_BUG);
+
+	return errata;
+}
+
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
 	struct omap_device			*od;
 	struct omap_system_dma_plat_info	*p;
+	struct resource				*mem;
 	char					*name = "omap_dma_system";
 
+	dma_stride		= OMAP2_DMA_STRIDE;
+	dma_common_ch_start	= CSDP;
+	if (cpu_is_omap3630() || cpu_is_omap4430())
+		dma_common_ch_end = CCDN;
+	else
+		dma_common_ch_end = CCFN;
+
 	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
 	if (!p) {
 		pr_err("%s: Unable to allocate pdata for %s:%s\n",
@@ -54,6 +247,17 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 		return -ENOMEM;
 	}
 
+	p->dma_attr		= (struct omap_dma_dev_attr *)oh->dev_attr;
+	p->disable_irq_lch	= omap2_disable_irq_lch;
+	p->show_dma_caps	= omap2_show_dma_caps;
+	p->clear_dma		= omap2_clear_dma;
+	p->dma_write		= dma_write;
+	p->dma_read		= dma_read;
+
+	p->clear_lch_regs	= NULL;
+
+	p->errata		= configure_dma_errata();
+
 	od = omap_device_build(name, 0, oh, p, sizeof(*p),
 			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
 	kfree(p);
@@ -63,6 +267,25 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 		return IS_ERR(od);
 	}
 
+	mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__);
+		return -EINVAL;
+	}
+	dma_base = ioremap(mem->start, resource_size(mem));
+	if (!dma_base) {
+		dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__);
+		return -ENOMEM;
+	}
+
+	d = oh->dev_attr;
+	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->lch_count), GFP_KERNEL);
+
+	if (!d->chan) {
+		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+		return -ENOMEM;
+	}
 	return 0;
 }
 
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index f73b302..3770cc6 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -15,6 +15,10 @@
  *
  * Support functions for the OMAP internal DMA channels.
  *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into DMA platform driver.
+ *	- G, Manjunath Kondaiah <manjugk@ti.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -40,96 +44,6 @@
 
 #undef DEBUG
 
-static u16 reg_map_omap1[] = {
-	[GCR]		= 0x400,
-	[GSCR]		= 0x404,
-	[GRST1]		= 0x408,
-	[HW_ID]		= 0x442,
-	[PCH2_ID]	= 0x444,
-	[PCH0_ID]	= 0x446,
-	[PCH1_ID]	= 0x448,
-	[PCHG_ID]	= 0x44a,
-	[PCHD_ID]	= 0x44c,
-	[CAPS_0]	= 0x44e,
-	[CAPS_1]	= 0x452,
-	[CAPS_2]	= 0x456,
-	[CAPS_3]	= 0x458,
-	[CAPS_4]	= 0x45a,
-	[PCH2_SR]	= 0x460,
-	[PCH0_SR]	= 0x480,
-	[PCH1_SR]	= 0x482,
-	[PCHD_SR]	= 0x4c0,
-
-	/* Common Registers */
-	[CSDP]		= 0x00,
-	[CCR]		= 0x02,
-	[CICR]		= 0x04,
-	[CSR]		= 0x06,
-	[CEN]		= 0x10,
-	[CFN]		= 0x12,
-	[CSFI]		= 0x14,
-	[CSEI]		= 0x16,
-	[CPC]		= 0x18,	/* 15xx only */
-	[CSAC]		= 0x18,
-	[CDAC]		= 0x1a,
-	[CDEI]		= 0x1c,
-	[CDFI]		= 0x1e,
-	[CLNK_CTRL]	= 0x28,
-
-	/* Channel specific register offsets */
-	[CSSA]		= 0x08,
-	[CDSA]		= 0x0c,
-	[COLOR]		= 0x20,
-	[CCR2]		= 0x24,
-	[LCH_CTRL]	= 0x2a,
-};
-
-static u16 reg_map_omap2[] = {
-	[REVISION]		= 0x00,
-	[GCR]			= 0x78,
-	[IRQSTATUS_L0]		= 0x08,
-	[IRQSTATUS_L1]		= 0x0c,
-	[IRQSTATUS_L2]		= 0x10,
-	[IRQSTATUS_L3]		= 0x14,
-	[IRQENABLE_L0]		= 0x18,
-	[IRQENABLE_L1]		= 0x1c,
-	[IRQENABLE_L2]		= 0x20,
-	[IRQENABLE_L3]		= 0x24,
-	[SYSSTATUS]		= 0x28,
-	[OCP_SYSCONFIG]		= 0x2c,
-	[CAPS_0]		= 0x64,
-	[CAPS_2]		= 0x6c,
-	[CAPS_3]		= 0x70,
-	[CAPS_4]		= 0x74,
-
-	/* Common register offsets */
-	[CCR]			= 0x80,
-	[CLNK_CTRL]		= 0x84,
-	[CICR]			= 0x88,
-	[CSR]			= 0x8c,
-	[CSDP]			= 0x90,
-	[CEN]			= 0x94,
-	[CFN]			= 0x98,
-	[CSEI]			= 0xa4,
-	[CSFI]			= 0xa8,
-	[CDEI]			= 0xac,
-	[CDFI]			= 0xb0,
-	[CSAC]			= 0xb4,
-	[CDAC]			= 0xb8,
-
-	/* Channel specific register offsets */
-	[CSSA]			= 0x9c,
-	[CDSA]			= 0xa0,
-	[CCEN]			= 0xbc,
-	[CCFN]			= 0xc0,
-	[COLOR]			= 0xc4,
-
-	/* OMAP4 specific registers */
-	[CDP]			= 0xd0,
-	[CNDP]			= 0xd4,
-	[CCDN]			= 0xd8,
-};
-
 #ifndef CONFIG_ARCH_OMAP1
 enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
 	DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
@@ -143,6 +57,9 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 
 #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
 
+static struct omap_system_dma_plat_info *p;
+static struct omap_dma_dev_attr *d;
+
 static int enable_1510_mode;
 static u32 errata;
 
@@ -152,27 +69,6 @@ static struct omap_dma_global_context_registers {
 	u32 dma_gcr;
 } omap_dma_global_context;
 
-struct omap_dma_lch {
-	int next_lch;
-	int dev_id;
-	u16 saved_csr;
-	u16 enabled_irqs;
-	const char *dev_name;
-	void (*callback)(int lch, u16 ch_status, void *data);
-	void *data;
-
-#ifndef CONFIG_ARCH_OMAP1
-	/* required for Dynamic chaining */
-	int prev_linked_ch;
-	int next_linked_ch;
-	int state;
-	int chain_id;
-
-	int status;
-#endif
-	long flags;
-};
-
 struct dma_link_info {
 	int *linked_dmach_q;
 	int no_of_lchs_linked;
@@ -228,18 +124,6 @@ static int omap_dma_reserve_channels;
 
 static spinlock_t dma_chan_lock;
 static struct omap_dma_lch *dma_chan;
-static void __iomem *omap_dma_base;
-static u16 *reg_map;
-static u8 dma_stride;
-static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
-
-static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = {
-	INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
-	INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
-	INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10,
-	INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13,
-	INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD
-};
 
 static inline void disable_lnk(int lch);
 static void omap_disable_channel_irq(int lch);
@@ -248,49 +132,6 @@ static inline void omap_enable_channel_irq(int lch);
 #define REVISIT_24XX()		printk(KERN_ERR "FIXME: no %s on 24xx\n", \
 						__func__);
 
-static inline void dma_write(u32 val, int reg, int lch)
-{
-	u8  stride;
-	u32 offset;
-
-	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
-	offset = reg_map[reg] + (stride * lch);
-
-	if (dma_stride  == 0x40) {
-		__raw_writew(val, omap_dma_base + offset);
-		if ((reg > CLNK_CTRL && reg < CCEN) ||
-				(reg > PCHD_ID && reg < CAPS_2)) {
-			u32 offset2 = reg_map[reg] + 2 + (stride * lch);
-			__raw_writew(val >> 16, omap_dma_base + offset2);
-		}
-	} else {
-		__raw_writel(val, omap_dma_base + offset);
-	}
-}
-
-static inline u32 dma_read(int reg, int lch)
-{
-	u8 stride;
-	u32 offset, val;
-
-	stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
-	offset = reg_map[reg] + (stride * lch);
-
-	if (dma_stride  == 0x40) {
-		val = __raw_readw(omap_dma_base + offset);
-		if ((reg > CLNK_CTRL && reg < CCEN) ||
-				(reg > PCHD_ID && reg < CAPS_2)) {
-			u16 upper;
-			u32 offset2 = reg_map[reg] + 2 + (stride * lch);
-			upper = __raw_readw(omap_dma_base + offset2);
-			val |= (upper << 16);
-		}
-	} else {
-		val = __raw_readl(omap_dma_base + offset);
-	}
-	return val;
-}
-
 #ifdef CONFIG_ARCH_OMAP15XX
 /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
 int omap_dma_in_1510_mode(void)
@@ -325,15 +166,6 @@ static inline void set_gdma_dev(int req, int dev)
 #define set_gdma_dev(req, dev)	do {} while (0)
 #endif
 
-/* Omap1 only */
-static void clear_lch_regs(int lch)
-{
-	int i = dma_common_ch_start;
-
-	for (; i <= dma_common_ch_end; i += 1)
-		dma_write(0, i, lch);
-}
-
 void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
 	unsigned long reg;
@@ -366,12 +198,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
 	if (cpu_class_is_omap2()) {
 		u32 ccr;
 
-		ccr = dma_read(CCR, lch);
+		ccr = p->dma_read(CCR, lch);
 		if (priority)
 			ccr |= (1 << 6);
 		else
 			ccr &= ~(1 << 6);
-		dma_write(ccr, CCR, lch);
+		p->dma_write(ccr, CCR, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_priority);
@@ -382,31 +214,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 {
 	u32 l;
 
-	l = dma_read(CSDP, lch);
+	l = p->dma_read(CSDP, lch);
 	l &= ~0x03;
 	l |= data_type;
-	dma_write(l, CSDP, lch);
+	p->dma_write(l, CSDP, lch);
 
 	if (cpu_class_is_omap1()) {
 		u16 ccr;
 
-		ccr = dma_read(CCR, lch);
+		ccr = p->dma_read(CCR, lch);
 		ccr &= ~(1 << 5);
 		if (sync_mode == OMAP_DMA_SYNC_FRAME)
 			ccr |= 1 << 5;
-		dma_write(ccr, CCR, lch);
+		p->dma_write(ccr, CCR, lch);
 
-		ccr = dma_read(CCR2, lch);
+		ccr = p->dma_read(CCR2, lch);
 		ccr &= ~(1 << 2);
 		if (sync_mode == OMAP_DMA_SYNC_BLOCK)
 			ccr |= 1 << 2;
-		dma_write(ccr, CCR2, lch);
+		p->dma_write(ccr, CCR2, lch);
 	}
 
 	if (cpu_class_is_omap2() && dma_trigger) {
 		u32 val;
 
-		val = dma_read(CCR, lch);
+		val = p->dma_read(CCR, lch);
 
 		/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
 		val &= ~((1 << 23) | (3 << 19) | 0x1f);
@@ -431,11 +263,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 		} else {
 			val &= ~(1 << 24);	/* dest synch */
 		}
-		dma_write(val, CCR, lch);
+		p->dma_write(val, CCR, lch);
 	}
 
-	dma_write(elem_count, CEN, lch);
-	dma_write(frame_count, CFN, lch);
+	p->dma_write(elem_count, CEN, lch);
+	p->dma_write(frame_count, CFN, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 
@@ -446,7 +278,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 	if (cpu_class_is_omap1()) {
 		u16 w;
 
-		w = dma_read(CCR2, lch);
+		w = p->dma_read(CCR2, lch);
 		w &= ~0x03;
 
 		switch (mode) {
@@ -461,22 +293,22 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 		default:
 			BUG();
 		}
-		dma_write(w, CCR2, lch);
+		p->dma_write(w, CCR2, lch);
 
-		w = dma_read(LCH_CTRL, lch);
+		w = p->dma_read(LCH_CTRL, lch);
 		w &= ~0x0f;
 		/* Default is channel type 2D */
 		if (mode) {
-			dma_write(color, COLOR, lch);
+			p->dma_write(color, COLOR, lch);
 			w |= 1;		/* Channel type G */
 		}
-		dma_write(w, LCH_CTRL, lch);
+		p->dma_write(w, LCH_CTRL, lch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		u32 val;
 
-		val = dma_read(CCR, lch);
+		val = p->dma_read(CCR, lch);
 		val &= ~((1 << 17) | (1 << 16));
 
 		switch (mode) {
@@ -491,10 +323,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 		default:
 			BUG();
 		}
-		dma_write(val, CCR, lch);
+		p->dma_write(val, CCR, lch);
 
 		color &= 0xffffff;
-		dma_write(color, COLOR, lch);
+		p->dma_write(color, COLOR, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_color_mode);
@@ -504,10 +336,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
 	if (cpu_class_is_omap2()) {
 		u32 csdp;
 
-		csdp = dma_read(CSDP, lch);
+		csdp = p->dma_read(CSDP, lch);
 		csdp &= ~(0x3 << 16);
 		csdp |= (mode << 16);
-		dma_write(csdp, CSDP, lch);
+		p->dma_write(csdp, CSDP, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_write_mode);
@@ -517,10 +349,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
 	if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
 		u32 l;
 
-		l = dma_read(LCH_CTRL, lch);
+		l = p->dma_read(LCH_CTRL, lch);
 		l &= ~0x7;
 		l |= mode;
-		dma_write(l, LCH_CTRL, lch);
+		p->dma_write(l, LCH_CTRL, lch);
 	}
 }
 EXPORT_SYMBOL(omap_set_dma_channel_mode);
@@ -535,21 +367,21 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 	if (cpu_class_is_omap1()) {
 		u16 w;
 
-		w = dma_read(CSDP, lch);
+		w = p->dma_read(CSDP, lch);
 		w &= ~(0x1f << 2);
 		w |= src_port << 2;
-		dma_write(w, CSDP, lch);
+		p->dma_write(w, CSDP, lch);
 	}
 
-	l = dma_read(CCR, lch);
+	l = p->dma_read(CCR, lch);
 	l &= ~(0x03 << 12);
 	l |= src_amode << 12;
-	dma_write(l, CCR, lch);
+	p->dma_write(l, CCR, lch);
 
-	dma_write(src_start, CSSA, lch);
+	p->dma_write(src_start, CSSA, lch);
 
-	dma_write(src_ei, CSEI, lch);
-	dma_write(src_fi, CSFI, lch);
+	p->dma_write(src_ei, CSEI, lch);
+	p->dma_write(src_fi, CSFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_params);
 
@@ -577,8 +409,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx)
 	if (cpu_class_is_omap2())
 		return;
 
-	dma_write(eidx, CSEI, lch);
-	dma_write(fidx, CSFI, lch);
+	p->dma_write(eidx, CSEI, lch);
+	p->dma_write(fidx, CSFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_index);
 
@@ -586,11 +418,11 @@ void omap_set_dma_src_data_pack(int lch, int enable)
 {
 	u32 l;
 
-	l = dma_read(CSDP, lch);
+	l = p->dma_read(CSDP, lch);
 	l &= ~(1 << 6);
 	if (enable)
 		l |= (1 << 6);
-	dma_write(l, CSDP, lch);
+	p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_data_pack);
 
@@ -599,7 +431,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	unsigned int burst = 0;
 	u32 l;
 
-	l = dma_read(CSDP, lch);
+	l = p->dma_read(CSDP, lch);
 	l &= ~(0x03 << 7);
 
 	switch (burst_mode) {
@@ -635,7 +467,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	}
 
 	l |= (burst << 7);
-	dma_write(l, CSDP, lch);
+	p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
 
@@ -647,21 +479,21 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
 	u32 l;
 
 	if (cpu_class_is_omap1()) {
-		l = dma_read(CSDP, lch);
+		l = p->dma_read(CSDP, lch);
 		l &= ~(0x1f << 9);
 		l |= dest_port << 9;
-		dma_write(l, CSDP, lch);
+		p->dma_write(l, CSDP, lch);
 	}
 
-	l = dma_read(CCR, lch);
+	l = p->dma_read(CCR, lch);
 	l &= ~(0x03 << 14);
 	l |= dest_amode << 14;
-	dma_write(l, CCR, lch);
+	p->dma_write(l, CCR, lch);
 
-	dma_write(dest_start, CDSA, lch);
+	p->dma_write(dest_start, CDSA, lch);
 
-	dma_write(dst_ei, CDEI, lch);
-	dma_write(dst_fi, CDFI, lch);
+	p->dma_write(dst_ei, CDEI, lch);
+	p->dma_write(dst_fi, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_params);
 
@@ -670,8 +502,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx)
 	if (cpu_class_is_omap2())
 		return;
 
-	dma_write(eidx, CDEI, lch);
-	dma_write(fidx, CDFI, lch);
+	p->dma_write(eidx, CDEI, lch);
+	p->dma_write(fidx, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_index);
 
@@ -679,11 +511,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable)
 {
 	u32 l;
 
-	l = dma_read(CSDP, lch);
+	l = p->dma_read(CSDP, lch);
 	l &= ~(1 << 13);
 	if (enable)
 		l |= 1 << 13;
-	dma_write(l, CSDP, lch);
+	p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
 
@@ -692,7 +524,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	unsigned int burst = 0;
 	u32 l;
 
-	l = dma_read(CSDP, lch);
+	l = p->dma_read(CSDP, lch);
 	l &= ~(0x03 << 14);
 
 	switch (burst_mode) {
@@ -725,7 +557,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 		return;
 	}
 	l |= (burst << 14);
-	dma_write(l, CSDP, lch);
+	p->dma_write(l, CSDP, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
 
@@ -735,18 +567,18 @@ static inline void omap_enable_channel_irq(int lch)
 
 	/* Clear CSR */
 	if (cpu_class_is_omap1())
-		status = dma_read(CSR, lch);
+		status = p->dma_read(CSR, lch);
 	else if (cpu_class_is_omap2())
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
 
 	/* Enable some nice interrupts. */
-	dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
+	p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
 }
 
 static void omap_disable_channel_irq(int lch)
 {
 	if (cpu_class_is_omap2())
-		dma_write(0, CICR, lch);
+		p->dma_write(0, CICR, lch);
 }
 
 void omap_enable_dma_irq(int lch, u16 bits)
@@ -765,7 +597,7 @@ static inline void enable_lnk(int lch)
 {
 	u32 l;
 
-	l = dma_read(CLNK_CTRL, lch);
+	l = p->dma_read(CLNK_CTRL, lch);
 
 	if (cpu_class_is_omap1())
 		l &= ~(1 << 14);
@@ -780,18 +612,18 @@ static inline void enable_lnk(int lch)
 			l = dma_chan[lch].next_linked_ch | (1 << 15);
 #endif
 
-	dma_write(l, CLNK_CTRL, lch);
+	p->dma_write(l, CLNK_CTRL, lch);
 }
 
 static inline void disable_lnk(int lch)
 {
 	u32 l;
 
-	l = dma_read(CLNK_CTRL, lch);
+	l = p->dma_read(CLNK_CTRL, lch);
 
 	/* Disable interrupts */
 	if (cpu_class_is_omap1()) {
-		dma_write(0, CICR, lch);
+		p->dma_write(0, CICR, lch);
 		/* Set the STOP_LNK bit */
 		l |= 1 << 14;
 	}
@@ -802,7 +634,7 @@ static inline void disable_lnk(int lch)
 		l &= ~(1 << 15);
 	}
 
-	dma_write(l, CLNK_CTRL, lch);
+	p->dma_write(l, CLNK_CTRL, lch);
 	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
@@ -815,9 +647,9 @@ static inline void omap2_enable_irq_lch(int lch)
 		return;
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
-	val = dma_read(IRQENABLE_L0, lch);
+	val = p->dma_read(IRQENABLE_L0, lch);
 	val |= 1 << lch;
-	dma_write(val, IRQENABLE_L0, lch);
+	p->dma_write(val, IRQENABLE_L0, lch);
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -830,9 +662,9 @@ static inline void omap2_disable_irq_lch(int lch)
 		return;
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
-	val = dma_read(IRQENABLE_L0, lch);
+	val = p->dma_read(IRQENABLE_L0, lch);
 	val &= ~(1 << lch);
-	dma_write(val, IRQENABLE_L0, lch);
+	p->dma_write(val, IRQENABLE_L0, lch);
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -859,8 +691,8 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	chan = dma_chan + free_ch;
 	chan->dev_id = dev_id;
 
-	if (cpu_class_is_omap1())
-		clear_lch_regs(free_ch);
+	if (p->clear_lch_regs)
+		p->clear_lch_regs(free_ch);
 
 	if (cpu_class_is_omap2())
 		omap_clear_dma(free_ch);
@@ -897,17 +729,17 @@ int omap_request_dma(int dev_id, const char *dev_name,
 		 * Disable the 1510 compatibility mode and set the sync device
 		 * id.
 		 */
-		dma_write(dev_id | (1 << 10), CCR, free_ch);
+		p->dma_write(dev_id | (1 << 10), CCR, free_ch);
 	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
-		dma_write(dev_id, CCR, free_ch);
+		p->dma_write(dev_id, CCR, free_ch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		omap2_enable_irq_lch(free_ch);
 		omap_enable_channel_irq(free_ch);
 		/* Clear the CSR register and IRQ status register */
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch);
-		dma_write(1 << free_ch, IRQSTATUS_L0, 0);
+		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch);
+		p->dma_write(1 << free_ch, IRQSTATUS_L0, 0);
 	}
 
 	*dma_ch_out = free_ch;
@@ -928,23 +760,23 @@ void omap_free_dma(int lch)
 
 	if (cpu_class_is_omap1()) {
 		/* Disable all DMA interrupts for the channel. */
-		dma_write(0, CICR, lch);
+		p->dma_write(0, CICR, lch);
 		/* Make sure the DMA transfer is stopped. */
-		dma_write(0, CCR, lch);
+		p->dma_write(0, CCR, lch);
 	}
 
 	if (cpu_class_is_omap2()) {
 		omap2_disable_irq_lch(lch);
 
 		/* Clear the CSR register and IRQ status register */
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
-		dma_write(1 << lch, IRQSTATUS_L0, lch);
+		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+		p->dma_write(1 << lch, IRQSTATUS_L0, lch);
 
 		/* Disable all DMA interrupts for the channel. */
-		dma_write(0, CICR, lch);
+		p->dma_write(0, CICR, lch);
 
 		/* Make sure the DMA transfer is stopped. */
-		dma_write(0, CCR, lch);
+		p->dma_write(0, CCR, lch);
 		omap_clear_dma(lch);
 	}
 
@@ -985,7 +817,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
 	reg |= (0x3 & tparams) << 12;
 	reg |= (arb_rate & 0xff) << 16;
 
-	dma_write(reg, GCR, 0);
+	p->dma_write(reg, GCR, 0);
 }
 EXPORT_SYMBOL(omap_dma_set_global_params);
 
@@ -1008,14 +840,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
 		printk(KERN_ERR "Invalid channel id\n");
 		return -EINVAL;
 	}
-	l = dma_read(CCR, lch);
+	l = p->dma_read(CCR, lch);
 	l &= ~((1 << 6) | (1 << 26));
 	if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
 		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
 	else
 		l |= ((read_prio & 0x1) << 6);
 
-	dma_write(l, CCR, lch);
+	p->dma_write(l, CCR, lch);
 
 	return 0;
 }
@@ -1030,24 +862,7 @@ void omap_clear_dma(int lch)
 	unsigned long flags;
 
 	local_irq_save(flags);
-
-	if (cpu_class_is_omap1()) {
-		u32 l;
-
-		l = dma_read(CCR, lch);
-		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR, lch);
-
-		/* Clear pending interrupts */
-		l = dma_read(CSR, lch);
-	}
-
-	if (cpu_class_is_omap2()) {
-		int i = dma_common_ch_start;
-		for (; i <= dma_common_ch_end; i += 1)
-			dma_write(0, i, lch);
-	}
-
+	p->clear_dma(lch);
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL(omap_clear_dma);
@@ -1061,13 +876,13 @@ void omap_start_dma(int lch)
 	 * before starting dma transfer.
 	 */
 	if (cpu_is_omap15xx())
-		dma_write(0, CPC, lch);
+		p->dma_write(0, CPC, lch);
 	else
-		dma_write(0, CDAC, lch);
+		p->dma_write(0, CDAC, lch);
 
 	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
 		int next_lch, cur_lch;
-		char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT];
+		char dma_chan_link_map[dma_lch_count];
 
 		dma_chan_link_map[lch] = 1;
 		/* Set the link register of the first channel */
@@ -1090,17 +905,17 @@ void omap_start_dma(int lch)
 			cur_lch = next_lch;
 		} while (next_lch != -1);
 	} else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
-		dma_write(lch, CLNK_CTRL, lch);
+		p->dma_write(lch, CLNK_CTRL, lch);
 
 	omap_enable_channel_irq(lch);
 
-	l = dma_read(CCR, lch);
+	l = p->dma_read(CCR, lch);
 
 	if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
 			l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
 	l |= OMAP_DMA_CCR_EN;
 
-	dma_write(l, CCR, lch);
+	p->dma_write(l, CCR, lch);
 
 	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 }
@@ -1112,46 +927,46 @@ void omap_stop_dma(int lch)
 
 	/* Disable all interrupts on the channel */
 	if (cpu_class_is_omap1())
-		dma_write(0, CICR, lch);
+		p->dma_write(0, CICR, lch);
 
-	l = dma_read(CCR, lch);
+	l = p->dma_read(CCR, lch);
 	if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
 			(l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
 		int i = 0;
 		u32 sys_cf;
 
 		/* Configure No-Standby */
-		l = dma_read(OCP_SYSCONFIG, lch);
+		l = p->dma_read(OCP_SYSCONFIG, lch);
 		sys_cf = l;
 		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
 		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
-		dma_write(l , OCP_SYSCONFIG, 0);
+		p->dma_write(l , OCP_SYSCONFIG, 0);
 
-		l = dma_read(CCR, lch);
+		l = p->dma_read(CCR, lch);
 		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR, lch);
+		p->dma_write(l, CCR, lch);
 
 		/* Wait for sDMA FIFO drain */
-		l = dma_read(CCR, lch);
+		l = p->dma_read(CCR, lch);
 		while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
 					OMAP_DMA_CCR_WR_ACTIVE))) {
 			udelay(5);
 			i++;
-			l = dma_read(CCR, lch);
+			l = p->dma_read(CCR, lch);
 		}
 		if (i >= 100)
 			printk(KERN_ERR "DMA drain did not complete on "
 					"lch %d\n", lch);
 		/* Restore OCP_SYSCONFIG */
-		dma_write(sys_cf, OCP_SYSCONFIG, lch);
+		p->dma_write(sys_cf, OCP_SYSCONFIG, lch);
 	} else {
 		l &= ~OMAP_DMA_CCR_EN;
-		dma_write(l, CCR, lch);
+		p->dma_write(l, CCR, lch);
 	}
 
 	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
 		int next_lch, cur_lch = lch;
-		char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT];
+		char dma_chan_link_map[dma_lch_count];
 
 		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
 		do {
@@ -1212,15 +1027,15 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 	dma_addr_t offset = 0;
 
 	if (cpu_is_omap15xx())
-		offset = dma_read(CPC, lch);
+		offset = p->dma_read(CPC, lch);
 	else
-		offset = dma_read(CSAC, lch);
+		offset = p->dma_read(CSAC, lch);
 
 	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
-		offset = dma_read(CSAC, lch);
+		offset = p->dma_read(CSAC, lch);
 
 	if (cpu_class_is_omap1())
-		offset |= (dma_read(CSSA, lch) & 0xFFFF0000);
+		offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000);
 
 	return offset;
 }
@@ -1239,19 +1054,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
 	dma_addr_t offset = 0;
 
 	if (cpu_is_omap15xx())
-		offset = dma_read(CPC, lch);
+		offset = p->dma_read(CPC, lch);
 	else
-		offset = dma_read(CDAC, lch);
+		offset = p->dma_read(CDAC, lch);
 
 	/*
 	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
 	 * read before the DMA controller finished disabling the channel.
 	 */
 	if (!cpu_is_omap15xx() && offset == 0)
-		offset = dma_read(CDAC, lch);
+		offset = p->dma_read(CDAC, lch);
 
 	if (cpu_class_is_omap1())
-		offset |= (dma_read(CDSA, lch) & 0xFFFF0000);
+		offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000);
 
 	return offset;
 }
@@ -1259,7 +1074,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos);
 
 int omap_get_dma_active_status(int lch)
 {
-	return (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;
+	return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;
 }
 EXPORT_SYMBOL(omap_get_dma_active_status);
 
@@ -1272,7 +1087,7 @@ int omap_dma_running(void)
 			return 1;
 
 	for (lch = 0; lch < dma_chan_count; lch++)
-		if (dma_read(CCR, lch) & OMAP_DMA_CCR_EN)
+		if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN)
 			return 1;
 
 	return 0;
@@ -1287,7 +1102,7 @@ void omap_dma_link_lch(int lch_head, int lch_queue)
 {
 	if (omap_dma_in_1510_mode()) {
 		if (lch_head == lch_queue) {
-			dma_write(dma_read(CCR, lch_head) | (3 << 8),
+			p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8),
 								CCR, lch_head);
 			return;
 		}
@@ -1314,7 +1129,7 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
 {
 	if (omap_dma_in_1510_mode()) {
 		if (lch_head == lch_queue) {
-			dma_write(dma_read(CCR, lch_head) & ~(3 << 8),
+			p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8),
 								CCR, lch_head);
 			return;
 		}
@@ -1341,8 +1156,6 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
 }
 EXPORT_SYMBOL(omap_dma_unlink_lch);
 
-/*----------------------------------------------------------------------------*/
-
 #ifndef CONFIG_ARCH_OMAP1
 /* Create chain of DMA channesls */
 static void create_dma_lch_chain(int lch_head, int lch_queue)
@@ -1367,15 +1180,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue)
 					lch_queue;
 	}
 
-	l = dma_read(CLNK_CTRL, lch_head);
+	l = p->dma_read(CLNK_CTRL, lch_head);
 	l &= ~(0x1f);
 	l |= lch_queue;
-	dma_write(l, CLNK_CTRL, lch_head);
+	p->dma_write(l, CLNK_CTRL, lch_head);
 
-	l = dma_read(CLNK_CTRL, lch_queue);
+	l = p->dma_read(CLNK_CTRL, lch_queue);
 	l &= ~(0x1f);
 	l |= (dma_chan[lch_queue].next_linked_ch);
-	dma_write(l, CLNK_CTRL, lch_queue);
+	p->dma_write(l, CLNK_CTRL, lch_queue);
 }
 
 /**
@@ -1651,13 +1464,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 
 	/* Set the params to the free channel */
 	if (src_start != 0)
-		dma_write(src_start, CSSA, lch);
+		p->dma_write(src_start, CSSA, lch);
 	if (dest_start != 0)
-		dma_write(dest_start, CDSA, lch);
+		p->dma_write(dest_start, CDSA, lch);
 
 	/* Write the buffer size */
-	dma_write(elem_count, CEN, lch);
-	dma_write(frame_count, CFN, lch);
+	p->dma_write(elem_count, CEN, lch);
+	p->dma_write(frame_count, CFN, lch);
 
 	/*
 	 * If the chain is dynamically linked,
@@ -1690,7 +1503,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 				enable_lnk(dma_chan[lch].prev_linked_ch);
 				dma_chan[lch].state = DMA_CH_QUEUED;
 				start_dma = 0;
-				if (0 == ((1 << 7) & dma_read(
+				if (0 == ((1 << 7) & p->dma_read(
 					CCR, dma_chan[lch].prev_linked_ch))) {
 					disable_lnk(dma_chan[lch].
 						    prev_linked_ch);
@@ -1707,7 +1520,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 			}
 			omap_enable_channel_irq(lch);
 
-			l = dma_read(CCR, lch);
+			l = p->dma_read(CCR, lch);
 
 			if ((0 == (l & (1 << 24))))
 				l &= ~(1 << 25);
@@ -1718,12 +1531,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
 					l |= (1 << 7);
 					dma_chan[lch].state = DMA_CH_STARTED;
 					pr_debug("starting %d\n", lch);
-					dma_write(l, CCR, lch);
+					p->dma_write(l, CCR, lch);
 				} else
 					start_dma = 0;
 			} else {
 				if (0 == (l & (1 << 7)))
-					dma_write(l, CCR, lch);
+					p->dma_write(l, CCR, lch);
 			}
 			dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 		}
@@ -1768,7 +1581,7 @@ int omap_start_dma_chain_transfers(int chain_id)
 		omap_enable_channel_irq(channels[0]);
 	}
 
-	l = dma_read(CCR, channels[0]);
+	l = p->dma_read(CCR, channels[0]);
 	l |= (1 << 7);
 	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
 	dma_chan[channels[0]].state = DMA_CH_STARTED;
@@ -1777,7 +1590,7 @@ int omap_start_dma_chain_transfers(int chain_id)
 		l &= ~(1 << 25);
 	else
 		l |= (1 << 25);
-	dma_write(l, CCR, channels[0]);
+	p->dma_write(l, CCR, channels[0]);
 
 	dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
 
@@ -1813,19 +1626,19 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	channels = dma_linked_lch[chain_id].linked_dmach_q;
 
 	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
-		sys_cf = dma_read(OCP_SYSCONFIG, 0);
+		sys_cf = p->dma_read(OCP_SYSCONFIG, 0);
 		l = sys_cf;
 		/* Middle mode reg set no Standby */
 		l &= ~((1 << 12)|(1 << 13));
-		dma_write(l, OCP_SYSCONFIG, 0);
+		p->dma_write(l, OCP_SYSCONFIG, 0);
 	}
 
 	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
 
 		/* Stop the Channel transmission */
-		l = dma_read(CCR, channels[i]);
+		l = p->dma_read(CCR, channels[i]);
 		l &= ~(1 << 7);
-		dma_write(l, CCR, channels[i]);
+		p->dma_write(l, CCR, channels[i]);
 
 		/* Disable the link in all the channels */
 		disable_lnk(channels[i]);
@@ -1838,7 +1651,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	OMAP_DMA_CHAIN_QINIT(chain_id);
 
 	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
-		dma_write(sys_cf, OCP_SYSCONFIG, 0);
+		p->dma_write(sys_cf, OCP_SYSCONFIG, 0);
 
 	return 0;
 }
@@ -1880,8 +1693,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	*ei = dma_read(CCEN, lch);
-	*fi = dma_read(CCFN, lch);
+	*ei = p->dma_read(CCEN, lch);
+	*fi = p->dma_read(CCFN, lch);
 
 	return 0;
 }
@@ -1918,7 +1731,7 @@ int omap_get_dma_chain_dst_pos(int chain_id)
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	return dma_read(CDAC, lch);
+	return p->dma_read(CDAC, lch);
 }
 EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
 
@@ -1952,7 +1765,7 @@ int omap_get_dma_chain_src_pos(int chain_id)
 	/* Get the current channel */
 	lch = channels[dma_linked_lch[chain_id].q_head];
 
-	return dma_read(CSAC, lch);
+	return p->dma_read(CSAC, lch);
 }
 EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
 #endif	/* ifndef CONFIG_ARCH_OMAP1 */
@@ -1969,7 +1782,7 @@ static int omap1_dma_handle_ch(int ch)
 		csr = dma_chan[ch].saved_csr;
 		dma_chan[ch].saved_csr = 0;
 	} else
-		csr = dma_read(CSR, ch);
+		csr = p->dma_read(CSR, ch);
 	if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
 		dma_chan[ch + 6].saved_csr = csr >> 7;
 		csr &= 0x7f;
@@ -2022,13 +1835,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
 
 static int omap2_dma_handle_ch(int ch)
 {
-	u32 status = dma_read(CSR, ch);
+	u32 status = p->dma_read(CSR, ch);
 
 	if (!status) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
 				ch);
-		dma_write(1 << ch, IRQSTATUS_L0, ch);
+		p->dma_write(1 << ch, IRQSTATUS_L0, ch);
 		return 0;
 	}
 	if (unlikely(dma_chan[ch].dev_id == -1)) {
@@ -2047,9 +1860,9 @@ static int omap2_dma_handle_ch(int ch)
 		if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
 			u32 ccr;
 
-			ccr = dma_read(CCR, ch);
+			ccr = p->dma_read(CCR, ch);
 			ccr &= ~OMAP_DMA_CCR_EN;
-			dma_write(ccr, CCR, ch);
+			p->dma_write(ccr, CCR, ch);
 			dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
 		}
 	}
@@ -2060,16 +1873,16 @@ static int omap2_dma_handle_ch(int ch)
 		printk(KERN_INFO "DMA misaligned error with device %d\n",
 		       dma_chan[ch].dev_id);
 
-	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
-	dma_write(1 << ch, IRQSTATUS_L0, ch);
+	p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
+	p->dma_write(1 << ch, IRQSTATUS_L0, ch);
 	/* read back the register to flush the write */
-	dma_read(IRQSTATUS_L0, ch);
+	p->dma_read(IRQSTATUS_L0, ch);
 
 	/* If the ch is not chained then chain_id will be -1 */
 	if (dma_chan[ch].chain_id != -1) {
 		int chain_id = dma_chan[ch].chain_id;
 		dma_chan[ch].state = DMA_CH_NOTSTARTED;
-		if (dma_read(CLNK_CTRL, ch) & (1 << 15))
+		if (p->dma_read(CLNK_CTRL, ch) & (1 << 15))
 			dma_chan[dma_chan[ch].next_linked_ch].state =
 							DMA_CH_STARTED;
 		if (dma_linked_lch[chain_id].chain_mode ==
@@ -2079,10 +1892,10 @@ static int omap2_dma_handle_ch(int ch)
 		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
 			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 
-		status = dma_read(CSR, ch);
+		status = p->dma_read(CSR, ch);
 	}
 
-	dma_write(status, CSR, ch);
+	p->dma_write(status, CSR, ch);
 
 	if (likely(dma_chan[ch].callback != NULL))
 		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
@@ -2096,13 +1909,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
 	u32 val, enable_reg;
 	int i;
 
-	val = dma_read(IRQSTATUS_L0, 0);
+	val = p->dma_read(IRQSTATUS_L0, 0);
 	if (val == 0) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "Spurious DMA IRQ\n");
 		return IRQ_HANDLED;
 	}
-	enable_reg = dma_read(IRQENABLE_L0, 0);
+	enable_reg = p->dma_read(IRQENABLE_L0, 0);
 	val &= enable_reg; /* Dispatch only relevant interrupts */
 	for (i = 0; i < dma_lch_count && val != 0; i++) {
 		if (val & 1)
@@ -2128,206 +1941,65 @@ static struct irqaction omap24xx_dma_irq;
 void omap_dma_global_context_save(void)
 {
 	omap_dma_global_context.dma_irqenable_l0 =
-		dma_read(IRQENABLE_L0, 0);
+		p->dma_read(IRQENABLE_L0, 0);
 	omap_dma_global_context.dma_ocp_sysconfig =
-		dma_read(OCP_SYSCONFIG, 0);
-	omap_dma_global_context.dma_gcr = dma_read(GCR, 0);
+		p->dma_read(OCP_SYSCONFIG, 0);
+	omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0);
 }
 
 void omap_dma_global_context_restore(void)
 {
 	int ch;
 
-	dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
-	dma_write(omap_dma_global_context.dma_ocp_sysconfig,
+	p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
+	p->dma_write(omap_dma_global_context.dma_ocp_sysconfig,
 		OCP_SYSCONFIG, 0);
-	dma_write(omap_dma_global_context.dma_irqenable_l0,
+	p->dma_write(omap_dma_global_context.dma_irqenable_l0,
 		IRQENABLE_L0, 0);
 
 	if (IS_DMA_ERRATA(DMA_ROMCODE_BUG))
-		dma_write(0x3 , IRQSTATUS_L0, 0);
+		p->dma_write(0x3 , IRQSTATUS_L0, 0);
 
 	for (ch = 0; ch < dma_chan_count; ch++)
 		if (dma_chan[ch].dev_id != -1)
 			omap_clear_dma(ch);
 }
 
-static void configure_dma_errata(void)
+static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 {
-
-	/*
-	 * Errata applicable for OMAP2430ES1.0 and all omap2420
-	 *
-	 * I.
-	 * Erratum ID: Not Available
-	 * Inter Frame DMA buffering issue DMA will wrongly
-	 * buffer elements if packing and bursting is enabled. This might
-	 * result in data gets stalled in FIFO at the end of the block.
-	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
-	 * guarantee no data will stay in the DMA FIFO in case inter frame
-	 * buffering occurs
-	 *
-	 * II.
-	 * Erratum ID: Not Available
-	 * DMA may hang when several channels are used in parallel
-	 * In the following configuration, DMA channel hanging can occur:
-	 * a. Channel i, hardware synchronized, is enabled
-	 * b. Another channel (Channel x), software synchronized, is enabled.
-	 * c. Channel i is disabled before end of transfer
-	 * d. Channel i is reenabled.
-	 * e. Steps 1 to 4 are repeated a certain number of times.
-	 * f. A third channel (Channel y), software synchronized, is enabled.
-	 * Channel x and Channel y may hang immediately after step 'f'.
-	 * Workaround:
-	 * For any channel used - make sure NextLCH_ID is set to the value j.
-	 */
-	if (cpu_is_omap2420() || (cpu_is_omap2430() &&
-				(omap_type() == OMAP2430_REV_ES1_0))) {
-		SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
-		SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
-	}
-
-	/*
-	 * Erratum ID: i378: OMAP2plus: sDMA Channel is not disabled
-	 * after a transaction error.
-	 * Workaround: SW should explicitely disable the channel.
-	 */
-	if (cpu_class_is_omap2())
-		SET_DMA_ERRATA(DMA_ERRATA_i378);
-
-	/*
-	 * Erratum ID: i541: sDMA FIFO draining does not finish
-	 * If sDMA channel is disabled on the fly, sDMA enters standby even
-	 * through FIFO Drain is still in progress
-	 * Workaround: Put sDMA in NoStandby more before a logical channel is
-	 * disabled, then put it back to SmartStandby right after the channel
-	 * finishes FIFO draining.
-	 */
-	if (cpu_is_omap34xx())
-		SET_DMA_ERRATA(DMA_ERRATA_i541);
-
-	/*
-	 * Erratum ID: i88 : Special programming model needed to disable DMA
-	 * before end of block.
-	 * Workaround: software must ensure that the DMA is configured in No
-	 * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
-	 */
-	if (omap_type() == OMAP3430_REV_ES1_0)
-		SET_DMA_ERRATA(DMA_ERRATA_i88);
-
-	/*
-	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
-	 * read before the DMA controller finished disabling the channel.
-	 */
-	if (!cpu_is_omap15xx())
-		SET_DMA_ERRATA(DMA_ERRATA_3_3);
-
-	/*
-	 * Erratum ID: Not Available
-	 * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
-	 * after secure sram context save and restore.
-	 * Work around: Hence we need to manually clear those IRQs to avoid
-	 * spurious interrupts. This affects only secure devices.
-	 */
-	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
-		SET_DMA_ERRATA(DMA_ROMCODE_BUG);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int __init omap_init_dma(void)
-{
-	unsigned long base;
-	int ch, r;
-
-	if (cpu_class_is_omap1()) {
-		base = OMAP1_DMA_BASE;
-		dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
-	} else if (cpu_is_omap24xx()) {
-		base = OMAP24XX_DMA4_BASE;
-		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-	} else if (cpu_is_omap34xx()) {
-		base = OMAP34XX_DMA4_BASE;
-		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-	} else if (cpu_is_omap44xx()) {
-		base = OMAP44XX_DMA4_BASE;
-		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
-	} else {
-		pr_err("DMA init failed for unsupported omap\n");
-		return -ENODEV;
+	int ch, ret = 0;
+	int dma_irq;
+	char irq_name[4];
+
+	p = pdev->dev.platform_data;
+	if (!p) {
+		dev_err(&pdev->dev, "%s: System DMA initialized without"
+			"platform data\n", __func__);
+		return -EINVAL;
 	}
 
-	omap_dma_base = ioremap(base, SZ_4K);
-	BUG_ON(!omap_dma_base);
-
-	if (cpu_class_is_omap1()) {
-		dma_stride		= 0x40;
-		reg_map			= reg_map_omap1;
-		dma_common_ch_start	= CPC;
-		dma_common_ch_end	= COLOR;
-	} else {
-		dma_stride		= 0x60;
-		reg_map			= reg_map_omap2;
-		dma_common_ch_start	= CSDP;
-		if (cpu_is_omap3630() || cpu_is_omap4430())
-			dma_common_ch_end = CCDN;
-		else
-			dma_common_ch_end = CCFN;
-	}
+	d			= p->dma_attr;
+	errata			= p->errata;
 
-	if (cpu_class_is_omap2() && omap_dma_reserve_channels
+	if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels
 			&& (omap_dma_reserve_channels <= dma_lch_count))
-		dma_lch_count = omap_dma_reserve_channels;
+		d->lch_count	= omap_dma_reserve_channels;
 
-	dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count,
-				GFP_KERNEL);
-	if (!dma_chan) {
-		r = -ENOMEM;
-		goto out_unmap;
-	}
+	dma_lch_count		= d->lch_count;
+	dma_chan_count		= dma_lch_count;
+	dma_chan		= d->chan;
+	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;
 
 	if (cpu_class_is_omap2()) {
 		dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
 						dma_lch_count, GFP_KERNEL);
 		if (!dma_linked_lch) {
-			r = -ENOMEM;
-			goto out_free;
+			ret = -ENOMEM;
+			goto exit_dma_chan;
 		}
 	}
 
-	if (cpu_is_omap15xx()) {
-		printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
-		dma_chan_count = 9;
-		enable_1510_mode = 1;
-	} else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
-		printk(KERN_INFO "OMAP DMA hardware version %d\n",
-		       dma_read(HW_ID, 0));
-		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
-		       dma_read(CAPS_0, 0), dma_read(CAPS_1, 0),
-		       dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
-		       dma_read(CAPS_4, 0));
-		if (!enable_1510_mode) {
-			u16 w;
-
-			/* Disable OMAP 3.0/3.1 compatibility mode. */
-			w = dma_read(GSCR, 0);
-			w |= 1 << 3;
-			dma_write(w, GSCR, 0);
-			dma_chan_count = 16;
-		} else
-			dma_chan_count = 9;
-	} else if (cpu_class_is_omap2()) {
-		u8 revision = dma_read(REVISION, 0) & 0xff;
-		printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
-		       revision >> 4, revision & 0xf);
-		dma_chan_count = dma_lch_count;
-	} else {
-		dma_chan_count = 0;
-		return 0;
-	}
-
 	spin_lock_init(&dma_chan_lock);
-
 	for (ch = 0; ch < dma_chan_count; ch++) {
 		omap_clear_dma(ch);
 		if (cpu_class_is_omap2())
@@ -2344,19 +2016,30 @@ static int __init omap_init_dma(void)
 			 * request_irq() doesn't like dev_id (ie. ch) being
 			 * zero, so we have to kludge around this.
 			 */
-			r = request_irq(omap1_dma_irq[ch],
+			sprintf(&irq_name[0], "%d", ch);
+			dma_irq = platform_get_irq_byname(pdev, irq_name);
+
+			if (dma_irq < 0) {
+				dev_err(&pdev->dev, "%s:unable to get irq\n",
+								__func__);
+				ret = dma_irq;
+				goto exit_dma_chan;
+			}
+			ret = request_irq(dma_irq,
 					omap1_dma_irq_handler, 0, "DMA",
 					(void *) (ch + 1));
-			if (r != 0) {
-				int i;
-
-				printk(KERN_ERR "unable to request IRQ %d "
-				       "for DMA (error %d)\n",
-				       omap1_dma_irq[ch], r);
-				for (i = 0; i < ch; i++)
-					free_irq(omap1_dma_irq[i],
-						 (void *) (i + 1));
-				goto out_free;
+			if (ret != 0) {
+				int irq_rel;
+				dev_err(&pdev->dev, "unable to request IRQ %d"
+					"for DMA (error %d)\n", dma_irq, ret);
+				for (irq_rel = 0; irq_rel < ch;
+								irq_rel++) {
+					dma_irq = platform_get_irq(pdev,
+								irq_rel);
+					free_irq(dma_irq, (void *)
+							(irq_rel + 1));
+					goto exit_dma_chan;
+				}
 			}
 		}
 	}
@@ -2366,47 +2049,58 @@ static int __init omap_init_dma(void)
 				DMA_DEFAULT_FIFO_DEPTH, 0);
 
 	if (cpu_class_is_omap2()) {
-		int irq;
-		if (cpu_is_omap44xx())
-			irq = OMAP44XX_IRQ_SDMA_0;
-		else
-			irq = INT_24XX_SDMA_IRQ0;
-		setup_irq(irq, &omap24xx_dma_irq);
-	}
-
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		/* Enable smartidle idlemodes and autoidle */
-		u32 v = dma_read(OCP_SYSCONFIG, 0);
-		v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
-				DMA_SYSCONFIG_SIDLEMODE_MASK |
-				DMA_SYSCONFIG_AUTOIDLE);
-		v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
-			DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
-			DMA_SYSCONFIG_AUTOIDLE);
-		dma_write(v , OCP_SYSCONFIG, 0);
-		/* reserve dma channels 0 and 1 in high security devices */
-		if (cpu_is_omap34xx() &&
-			(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
-			printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
-					"HS ROM code\n");
-			dma_chan[0].dev_id = 0;
-			dma_chan[1].dev_id = 1;
-		}
+		strcpy(irq_name, "0");
+		dma_irq = platform_get_irq_byname(pdev, irq_name);
+		setup_irq(dma_irq, &omap24xx_dma_irq);
 	}
-	configure_dma_errata();
 
+	/* reserve dma channels 0 and 1 in high security devices */
+	if (cpu_is_omap34xx() &&
+		(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
+		printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
+				"HS ROM code\n");
+		dma_chan[0].dev_id = 0;
+		dma_chan[1].dev_id = 1;
+	}
+	p->show_dma_caps();
 	return 0;
 
-out_free:
+exit_dma_chan:
+	kfree(dma_chan);
+	kfree(p);
+	return ret;
+}
+
+static int __devexit omap_system_dma_remove(struct platform_device *pdev)
+{
 	kfree(dma_chan);
+	kfree(p);
+	return 0;
+}
+
+static struct platform_driver omap_system_dma_driver = {
+	.probe		= omap_system_dma_probe,
+	.remove		= omap_system_dma_remove,
+	.driver		= {
+		.name	= "omap_dma_system"
+	},
+};
 
-out_unmap:
-	iounmap(omap_dma_base);
+static int __init omap_system_dma_init(void)
+{
+	return platform_driver_register(&omap_system_dma_driver);
+}
+arch_initcall(omap_system_dma_init);
 
-	return r;
+static void __exit omap_system_dma_exit(void)
+{
+	platform_driver_unregister(&omap_system_dma_driver);
 }
 
-arch_initcall(omap_init_dma);
+MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
 
 /*
  * Reserve the omap SDMA channels using cmdline bootarg
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 4b51d2b..d1c916f 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -21,19 +21,15 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-/* Move omap4 specific defines to dma-44xx.h */
-#include "dma-44xx.h"
-
-/* Hardware registers for omap1 */
-#define OMAP1_DMA_BASE			(0xfffed800)
+#include <linux/platform_device.h>
 
-/* Hardware registers for omap2 and omap3 */
-#define OMAP24XX_DMA4_BASE		(L4_24XX_BASE + 0x56000)
-#define OMAP34XX_DMA4_BASE		(L4_34XX_BASE + 0x56000)
-#define OMAP44XX_DMA4_BASE		(L4_44XX_BASE + 0x56000)
+/*
+ * TODO: These dma channel defines should go away once all
+ * the omap drivers hwmod adapted.
+ */
 
-#define OMAP1_LOGICAL_DMA_CH_COUNT	17
-#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT	32	/* REVISIT: Is this 32 + 2? */
+/* Move omap4 specific defines to dma-44xx.h */
+#include "dma-44xx.h"
 
 /* DMA channels for omap1 */
 #define OMAP_DMA_NO_DEVICE		0
@@ -302,6 +298,14 @@
 #define IS_CSSA_32			BIT(0x3)
 #define IS_CDSA_32			BIT(0x4)
 #define IS_RW_PRIORITY			BIT(0x5)
+#define ENABLE_1510_MODE		BIT(0x6)
+#define SRC_PORT			BIT(0x7)
+#define DST_PORT			BIT(0x8)
+#define SRC_INDEX			BIT(0x9)
+#define DST_INDEX			BIT(0xA)
+#define IS_BURST_ONLY4			BIT(0xB)
+#define CLEAR_CSR_ON_READ		BIT(0xC)
+#define IS_WORD_16			BIT(0xD)
 
 enum omap_reg_offsets {
 
@@ -397,9 +401,40 @@ struct omap_dma_channel_params {
 #endif
 };
 
+struct omap_dma_lch {
+	int next_lch;
+	int dev_id;
+	u16 saved_csr;
+	u16 enabled_irqs;
+	const char *dev_name;
+	void (*callback)(int lch, u16 ch_status, void *data);
+	void *data;
+	long flags;
+	/* required for Dynamic chaining */
+	int prev_linked_ch;
+	int next_linked_ch;
+	int state;
+	int chain_id;
+	int status;
+};
+
 struct omap_dma_dev_attr {
 	u32 dev_caps;
 	u16 lch_count;
+	u16 chan_count;
+	struct omap_dma_lch *chan;
+};
+
+/* System DMA platform data structure */
+struct omap_system_dma_plat_info {
+	struct omap_dma_dev_attr *dma_attr;
+	u32 errata;
+	void (*disable_irq_lch)(int lch);
+	void (*show_dma_caps)(void);
+	void (*clear_lch_regs)(int lch);
+	void (*clear_dma)(int lch);
+	void (*dma_write)(u32 val, int reg, int lch);
+	u32 (*dma_read)(int reg, int lch);
 };
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (8 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-12-02 17:07     ` Tony Lindgren
  2010-11-24 12:51 ` [PATCH v5 11/14] OMAP2+: DMA: descriptor autoloading feature G, Manjunath Kondaiah
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Existing DMA API's are using cpu_*is_* checks for differentiating
omap1 and omap2+ code and handle cpu_*is_* checks with DMA device
attributes.

Also, move OMAP1 and OMAP2+ specific API's into respective mach-omap
dma driver files.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap1/dma.c              |  320 +++++++-
 arch/arm/mach-omap2/dma.c              | 1047 +++++++++++++++++++++++
 arch/arm/mach-omap2/include/mach/dma.h |   56 ++
 arch/arm/plat-omap/dma.c               | 1465 ++------------------------------
 arch/arm/plat-omap/include/plat/dma.h  |   62 +-
 5 files changed, 1533 insertions(+), 1417 deletions(-)
 create mode 100644 arch/arm/mach-omap2/include/mach/dma.h

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 06af97a..80c3380 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -24,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <plat/dma.h>
 #include <plat/tc.h>
@@ -32,12 +34,16 @@
 #define OMAP1_DMA_BASE			(0xfffed800)
 #define OMAP1_LOGICAL_DMA_CH_COUNT	17
 #define OMAP1_DMA_STRIDE		0x40
+#define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
 
 static u32 errata;
 static u32 enable_1510_mode;
 static u8 dma_stride;
 static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
 
+static struct omap_dma_lch *dma_chan;
+static struct omap_dma_dev_attr *d;
+
 static u16 reg_map[] = {
 	[GCR]		= 0x400,
 	[GSCR]		= 0x404,
@@ -212,6 +218,184 @@ static inline u32 dma_read(int reg, int lch)
 	return val;
 }
 
+static void
+set_src_params(int lch, unsigned long src_start, int src_ei, int src_fi)
+{
+	dma_write(src_start, CSSA, lch);
+
+	dma_write(src_ei, CSEI, lch);
+	dma_write(src_fi, CSFI, lch);
+}
+
+static void set_dest_params(int lch, unsigned long dest_start, int dst_ei,
+								int dst_fi)
+{
+	dma_write(dest_start, CDSA, lch);
+
+	dma_write(dst_ei, CDEI, lch);
+	dma_write(dst_fi, CDFI, lch);
+}
+
+static inline void omap1_enable_channel_irq(int lch)
+{
+	u32 status;
+
+	/* Clear CSR */
+	status = dma_read(CSR, lch);
+	dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
+}
+
+static void omap1_disable_channel_irq(int lch)
+{
+	dma_write(0, CICR, lch);
+}
+
+static inline void omap1_enable_lnk(int lch)
+{
+	u32 l;
+
+	l = dma_read(CLNK_CTRL, lch);
+	l &= ~(1 << 14);
+
+	/* Set the ENABLE_LNK bits */
+	if (dma_chan[lch].next_lch != -1)
+		l = dma_chan[lch].next_lch | (1 << 15);
+
+	dma_write(l, CLNK_CTRL, lch);
+}
+
+static inline void omap1_disable_lnk(int lch)
+{
+	u32 l;
+
+	/* Disable interrupts */
+	l = dma_read(CLNK_CTRL, lch);
+	dma_write(0, CICR, lch);
+	/* Set the STOP_LNK bit */
+	l |= 1 << 14;
+	dma_write(l, CLNK_CTRL, lch);
+
+	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+}
+
+static dma_addr_t get_src_pos(int lch)
+{
+	dma_addr_t offset = 0;
+
+	if (enable_1510_mode)
+		offset = dma_read(CPC, lch);
+	else
+		offset = dma_read(CSAC, lch);
+
+	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
+		offset = dma_read(CSAC, lch);
+
+	offset |= dma_read(CSSA, lch) & 0xFFFF0000;
+
+	return offset;
+}
+
+static dma_addr_t get_dst_pos(int lch)
+{
+	dma_addr_t offset = 0;
+
+	if (enable_1510_mode)
+		offset = dma_read(CPC, lch);
+	else
+		offset = dma_read(CDAC, lch);
+
+	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
+		offset = dma_read(CDAC, lch);
+
+	offset |= dma_read(CDSA, lch) & 0xFFFF0000;
+
+	return offset;
+}
+
+static void
+set_transfer_params(int lch, int data_type, int sync_mode, int dma_trigger,
+							int src_or_dst_synch)
+{
+	u16 ccr;
+	u32 l;
+
+	l = dma_read(CSDP, lch);
+	l &= ~0x03;
+	l |= data_type;
+	dma_write(l, CSDP, lch);
+
+	ccr = dma_read(CCR, lch);
+	ccr &= ~(1 << 5);
+	if (sync_mode == OMAP_DMA_SYNC_FRAME)
+		ccr |= 1 << 5;
+	dma_write(ccr, CCR, lch);
+
+	ccr = dma_read(CCR2, lch);
+	ccr &= ~(1 << 2);
+	if (sync_mode == OMAP_DMA_SYNC_BLOCK)
+		ccr |= 1 << 2;
+	dma_write(ccr, CCR2, lch);
+}
+
+static void cpc_cdac_init(int lch)
+{
+	if (enable_1510_mode)
+		dma_write(0, CPC, lch);
+	else
+		dma_write(0, CDAC, lch);
+}
+
+static inline int omap1_get_gdma_dev(int req)
+{
+	u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
+	int shift = ((req - 1) % 5) * 6;
+
+	return ((omap_readl(reg) >> shift) & 0x3f) + 1;
+}
+
+static inline void omap1_set_gdma_dev(int req, int dev)
+{
+	u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
+	int shift = ((req - 1) % 5) * 6;
+	u32 l;
+
+	l = omap_readl(reg);
+	l &= ~(0x3f << shift);
+	l |= (dev - 1) << shift;
+	omap_writel(l, reg);
+}
+
+static void set_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
+{
+	u16 w;
+
+	w = dma_read(CCR2, lch);
+	w &= ~0x03;
+
+	switch (mode) {
+	case OMAP_DMA_CONSTANT_FILL:
+		w |= 0x01;
+		break;
+	case OMAP_DMA_TRANSPARENT_COPY:
+		w |= 0x02;
+		break;
+	case OMAP_DMA_COLOR_DIS:
+		break;
+	default:
+		BUG();
+	}
+	dma_write(w, CCR2, lch);
+
+	w = dma_read(LCH_CTRL, lch);
+	w &= ~0x0f;
+	/* Default is channel type 2D */
+	if (mode) {
+		dma_write(color, COLOR, lch);
+		w |= 1;		/* Channel type G */
+	}
+	dma_write(w, LCH_CTRL, lch);
+}
+
 static void omap1_clear_lch_regs(int lch)
 {
 	int i = dma_common_ch_start;
@@ -266,12 +450,93 @@ static u32 configure_dma_errata(void)
 	return errata;
 }
 
+static int omap1_dma_handle_ch(int ch)
+{
+	u32 csr;
+
+	if (enable_1510_mode && ch >= 6) {
+		csr = dma_chan[ch].saved_csr;
+		dma_chan[ch].saved_csr = 0;
+	} else
+		csr = dma_read(CSR, ch);
+	if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
+		dma_chan[ch + 6].saved_csr = csr >> 7;
+		csr &= 0x7f;
+	}
+	if ((csr & 0x3f) == 0)
+		return 0;
+	if (unlikely(dma_chan[ch].dev_id == -1)) {
+		printk(KERN_WARNING "Spurious interrupt from DMA channel "
+		       "%d (CSR %04x)\n", ch, csr);
+		return 0;
+	}
+	if (unlikely(csr & OMAP1_DMA_TOUT_IRQ))
+		printk(KERN_WARNING "DMA timeout with device %d\n",
+		       dma_chan[ch].dev_id);
+	if (unlikely(csr & OMAP_DMA_DROP_IRQ))
+		printk(KERN_WARNING "DMA synchronization event drop occurred "
+		       "with device %d\n", dma_chan[ch].dev_id);
+	if (likely(csr & OMAP_DMA_BLOCK_IRQ))
+		dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
+	if (likely(dma_chan[ch].callback != NULL))
+		dma_chan[ch].callback(ch, csr, dma_chan[ch].data);
+
+	return 1;
+}
+
+static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
+{
+	int ch = ((int) dev_id) - 1;
+	int handled = 0;
+
+	for (;;) {
+		int handled_now = 0;
+
+		handled_now += omap1_dma_handle_ch(ch);
+		if (enable_1510_mode && dma_chan[ch + 6].saved_csr)
+			handled_now += omap1_dma_handle_ch(ch + 6);
+		if (!handled_now)
+			break;
+		handled += handled_now;
+	}
+
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
+{
+	if (!(d->dev_caps & ENABLE_1510_MODE)) {
+		u32 l;
+
+		l = dma_read(LCH_CTRL, lch);
+		l &= ~0x7;
+		l |= mode;
+		dma_write(l, LCH_CTRL, lch);
+	}
+}
+EXPORT_SYMBOL(omap_set_dma_channel_mode);
+
+void omap_set_dma_src_index(int lch, int eidx, int fidx)
+{
+	dma_write(eidx, CSEI, lch);
+	dma_write(fidx, CSFI, lch);
+}
+EXPORT_SYMBOL(omap_set_dma_src_index);
+
+void omap_set_dma_dest_index(int lch, int eidx, int fidx)
+{
+	dma_write(eidx, CDEI, lch);
+	dma_write(fidx, CDFI, lch);
+}
+EXPORT_SYMBOL(omap_set_dma_dest_index);
+
 static int __init omap1_system_dma_init(void)
 {
 	struct omap_system_dma_plat_info	*p;
-	struct omap_dma_dev_attr		*d;
 	struct platform_device			*pdev;
-	int ret;
+	int ret, ch, irq_rel;
+	char irq_name[4];
+	int dma_irq = 0;
 
 	pdev = platform_device_alloc("omap_dma_system", 0);
 	if (!pdev) {
@@ -328,6 +593,25 @@ static int __init omap1_system_dma_init(void)
 			d->chan_count = 9;
 	}
 
+	for (ch = 0; ch < d->chan_count; ch++) {
+		if (ch >= 6 && enable_1510_mode)
+			continue;
+
+		sprintf(&irq_name[0], "%d", ch);
+		dma_irq = platform_get_irq_byname(pdev, irq_name);
+		if (dma_irq < 0) {
+			dev_err(&pdev->dev, "%s:unable to get irq\n",
+								__func__);
+			ret = dma_irq;
+			goto exit_release_irq;
+		}
+
+		ret = request_irq(dma_irq, omap1_dma_irq_handler, 0, "DMA",
+							(void *) (ch + 1));
+		if (ret != 0)
+			goto exit_release_irq;
+	}
+
 	dma_base		= (void __iomem *)res[0].start;
 
 	p->show_dma_caps	= omap1_show_dma_caps;
@@ -335,6 +619,28 @@ static int __init omap1_system_dma_init(void)
 	p->clear_dma		= omap1_clear_dma;
 	p->dma_write		= dma_write;
 	p->dma_read		= dma_read;
+	p->enable_channel_irq	= omap1_enable_channel_irq;
+	p->disable_channel_irq	= omap1_disable_channel_irq;
+	p->enable_lnk		= omap1_enable_lnk;
+	p->disable_lnk		= omap1_disable_lnk;
+	p->clear_lch_regs	= omap1_clear_lch_regs;
+	p->set_transfer_params	= set_transfer_params;
+	p->set_color_mode	= set_color_mode;
+	p->set_src_params	= set_src_params;
+	p->set_dest_params	= set_dest_params;
+	p->get_src_pos		= get_src_pos;
+	p->get_dst_pos		= get_dst_pos;
+	p->cpc_cdac_init	= cpc_cdac_init;
+
+	if (cpu_is_omap16xx()) {
+		p->get_gdma_dev = omap1_get_gdma_dev;
+		p->set_gdma_dev = omap1_set_gdma_dev;
+	}
+
+	p->enable_irq_lch	= NULL;
+	p->disable_irq_lch	= NULL;
+	p->clear_channel_int	= NULL;
+	p->set_global_params	= NULL;
 	p->disable_irq_lch	= NULL;
 
 	p->errata = configure_dma_errata();
@@ -353,6 +659,7 @@ static int __init omap1_system_dma_init(void)
 		goto exit_release_chan;
 	}
 
+	dma_chan		= d->chan;
 	dma_stride		= OMAP1_DMA_STRIDE;
 	dma_common_ch_start	= CPC;
 	dma_common_ch_end	= COLOR;
@@ -361,6 +668,15 @@ static int __init omap1_system_dma_init(void)
 
 exit_release_chan:
 	kfree(d->chan);
+exit_release_irq:
+	dev_err(&pdev->dev, "unable to request IRQ %d"
+				"for DMA (error %d)\n", dma_irq, ret);
+	if (enable_1510_mode)
+		ch = 6;
+	for (irq_rel = 0; irq_rel < ch; irq_rel++) {
+		dma_irq = platform_get_irq(pdev, irq_rel);
+		free_irq(dma_irq, (void *)(irq_rel + 1));
+	}
 exit_release_p:
 	kfree(p);
 exit_device_put:
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 4a9a56a..2ce1969 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -27,6 +27,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
@@ -36,11 +38,70 @@
 
 static u32 errata;
 static u8 dma_stride;
+static int dma_chan_count;
 
 static struct omap_dma_dev_attr *d;
+static struct dma_link_info *dma_linked_lch;
+static struct omap_dma_lch *dma_chan;
+static struct platform_device *pd;
 
 static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
 
+/* Chain handling macros */
+#define OMAP_DMA_CHAIN_QINIT(chain_id)					\
+	do {								\
+		dma_linked_lch[chain_id].q_head =			\
+		dma_linked_lch[chain_id].q_tail =			\
+		dma_linked_lch[chain_id].q_count = 0;			\
+	} while (0)
+#define OMAP_DMA_CHAIN_QFULL(chain_id)					\
+		(dma_linked_lch[chain_id].no_of_lchs_linked ==		\
+		dma_linked_lch[chain_id].q_count)
+#define OMAP_DMA_CHAIN_QLAST(chain_id)					\
+	do {								\
+		((dma_linked_lch[chain_id].no_of_lchs_linked-1) ==	\
+		dma_linked_lch[chain_id].q_count)			\
+	} while (0)
+#define OMAP_DMA_CHAIN_QEMPTY(chain_id)					\
+		(0 == dma_linked_lch[chain_id].q_count)
+#define __OMAP_DMA_CHAIN_INCQ(end)					\
+	((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked)
+#define OMAP_DMA_CHAIN_INCQHEAD(chain_id)				\
+	do {								\
+		__OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head);	\
+		dma_linked_lch[chain_id].q_count--;			\
+	} while (0)
+
+#define OMAP_DMA_CHAIN_INCQTAIL(chain_id)				\
+	do {								\
+		__OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_tail);	\
+		dma_linked_lch[chain_id].q_count++; \
+	} while (0)
+
+enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
+	DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
+};
+
+enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
+
+struct dma_link_info {
+	int *linked_dmach_q;
+	int no_of_lchs_linked;
+
+	int q_count;
+	int q_tail;
+	int q_head;
+
+	int chain_state;
+	int chain_mode;
+
+};
+
+static struct omap_dma_global_context_registers {
+	u32 dma_irqenable_l0;
+	u32 dma_gcr;
+} omap_dma_global_context;
+
 static u16 reg_map[] = {
 	[REVISION]		= 0x00,
 	[GCR]			= 0x78,
@@ -126,6 +187,15 @@ static inline void omap2_disable_irq_lch(int lch)
 	dma_write(val, IRQENABLE_L0, lch);
 }
 
+static inline void omap2_enable_irq_lch(int lch)
+{
+	u32 val;
+
+	val = dma_read(IRQENABLE_L0, lch);
+	val |= 1 << lch;
+	dma_write(val, IRQENABLE_L0, lch);
+}
+
 static void omap2_clear_dma(int lch)
 {
 	int i = dma_common_ch_start;
@@ -134,6 +204,332 @@ static void omap2_clear_dma(int lch)
 		dma_write(0, i, lch);
 }
 
+static inline void omap2_clear_channel_interrupt(int lch)
+{
+	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+	dma_write(1 << lch, IRQSTATUS_L0, lch);
+}
+
+static inline void omap2_enable_channel_irq(int lch)
+{
+	/* Clear CSR */
+	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+
+	dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
+}
+
+static void omap2_disable_channel_irq(int lch)
+{
+	dma_write(0, CICR, lch);
+}
+
+static inline void omap2_enable_lnk(int lch)
+{
+	u32 l;
+
+	l = dma_read(CLNK_CTRL, lch);
+
+	/* Set the ENABLE_LNK bits */
+	if (dma_chan[lch].next_lch != -1)
+		l = dma_chan[lch].next_lch | (1 << 15);
+
+	if (dma_chan[lch].next_linked_ch != -1)
+		l = dma_chan[lch].next_linked_ch | (1 << 15);
+
+	dma_write(l, CLNK_CTRL, lch);
+}
+
+static inline void omap2_disable_lnk(int lch)
+{
+	u32 l;
+
+	l = dma_read(CLNK_CTRL, lch);
+
+	omap2_disable_channel_irq(lch);
+	/* Clear the ENABLE_LNK bit */
+	l &= ~(1 << 15);
+
+	dma_write(l, CLNK_CTRL, lch);
+	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+}
+
+static void
+omap2_set_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
+{
+	u32 val;
+
+	val = dma_read(CCR, lch);
+	val &= ~((1 << 17) | (1 << 16));
+
+	switch (mode) {
+	case OMAP_DMA_CONSTANT_FILL:
+		val |= 1 << 16;
+		break;
+	case OMAP_DMA_TRANSPARENT_COPY:
+		val |= 1 << 17;
+		break;
+	case OMAP_DMA_COLOR_DIS:
+		break;
+	default:
+		BUG();
+	}
+	dma_write(val, CCR, lch);
+
+	color &= 0xffffff;
+	dma_write(color, COLOR, lch);
+}
+
+void omap_dma_global_context_save(void)
+{
+	omap_dma_global_context.dma_irqenable_l0 =
+		dma_read(IRQENABLE_L0, 0);
+
+	omap_dma_global_context.dma_gcr = dma_read(GCR, 0);
+}
+
+void omap_dma_global_context_restore(void)
+{
+	int ch;
+
+	dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
+
+	dma_write(omap_dma_global_context.dma_irqenable_l0,
+		IRQENABLE_L0, 0);
+
+	if (IS_DMA_ERRATA(DMA_ROMCODE_BUG))
+		dma_write(0x3 , IRQSTATUS_L0, 0);
+
+	for (ch = 0; ch < dma_chan_count; ch++)
+		if (dma_chan[ch].dev_id != -1)
+			omap_clear_dma(ch);
+}
+
+void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
+{
+	u32 csdp;
+
+	csdp = dma_read(CSDP, lch);
+	csdp &= ~(0x3 << 16);
+	csdp |= (mode << 16);
+	dma_write(csdp, CSDP, lch);
+}
+EXPORT_SYMBOL(omap_set_dma_write_mode);
+
+/**
+ * @brief omap_dma_set_global_params : Set global priority settings for dma
+ *
+ * @param arb_rate
+ * @param max_fifo_depth
+ * @param tparams - Number of threads to reserve:
+ * DMA_THREAD_RESERVE_NORM
+ * DMA_THREAD_RESERVE_ONET
+ * DMA_THREAD_RESERVE_TWOT
+ * DMA_THREAD_RESERVE_THREET
+ */
+void
+omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
+{
+	u32 reg;
+
+	if (max_fifo_depth == 0)
+		max_fifo_depth = 1;
+	if (arb_rate == 0)
+		arb_rate = 1;
+
+	reg = 0xff & max_fifo_depth;
+	reg |= (0x3 & tparams) << 12;
+	reg |= (arb_rate & 0xff) << 16;
+
+	dma_write(reg, GCR, 0);
+}
+EXPORT_SYMBOL(omap_dma_set_global_params);
+
+static int omap2_dma_handle_ch(int ch)
+{
+	u32 status = dma_read(CSR, ch);
+
+	if (!status) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
+				ch);
+		dma_write(1 << ch, IRQSTATUS_L0, ch);
+		return 0;
+	}
+	if (unlikely(dma_chan[ch].dev_id == -1)) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING "IRQ %04x for non-allocated DMA"
+					"channel %d\n", status, ch);
+		return 0;
+	}
+	if (unlikely(status & OMAP_DMA_DROP_IRQ))
+		printk(KERN_INFO
+		       "DMA synchronization event drop occurred with device "
+		       "%d\n", dma_chan[ch].dev_id);
+	if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
+		printk(KERN_INFO "DMA transaction error with device %d\n",
+		       dma_chan[ch].dev_id);
+		if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
+			u32 ccr;
+
+			ccr = dma_read(CCR, ch);
+			ccr &= ~OMAP_DMA_CCR_EN;
+			dma_write(ccr, CCR, ch);
+			dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
+		}
+	}
+	if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ))
+		printk(KERN_INFO "DMA secure error with device %d\n",
+		       dma_chan[ch].dev_id);
+	if (unlikely(status & OMAP2_DMA_MISALIGNED_ERR_IRQ))
+		printk(KERN_INFO "DMA misaligned error with device %d\n",
+		       dma_chan[ch].dev_id);
+
+	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
+	dma_write(1 << ch, IRQSTATUS_L0, ch);
+	/* read back the register to flush the write */
+	dma_read(IRQSTATUS_L0, ch);
+
+	/* If the ch is not chained then chain_id will be -1 */
+	if (dma_chan[ch].chain_id != -1) {
+		int chain_id = dma_chan[ch].chain_id;
+		dma_chan[ch].state = DMA_CH_NOTSTARTED;
+		if (dma_read(CLNK_CTRL, ch) & (1 << 15))
+			dma_chan[dma_chan[ch].next_linked_ch].state =
+							DMA_CH_STARTED;
+		if (dma_linked_lch[chain_id].chain_mode ==
+						OMAP_DMA_DYNAMIC_CHAIN)
+			omap2_disable_lnk(ch);
+
+		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
+			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
+
+		status = dma_read(CSR, ch);
+	}
+
+	dma_write(status, CSR, ch);
+
+	if (likely(dma_chan[ch].callback != NULL))
+		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
+
+	return 0;
+}
+
+/* STATUS register count is from 1-32 while our is 0-31 */
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+	u32 val, enable_reg;
+	int i;
+
+	val = dma_read(IRQSTATUS_L0, 0);
+	if (val == 0) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING "Spurious DMA IRQ\n");
+		return IRQ_HANDLED;
+	}
+	enable_reg = dma_read(IRQENABLE_L0, 0);
+	val &= enable_reg; /* Dispatch only relevant interrupts */
+	for (i = 0; i < dma_chan_count && val != 0; i++) {
+		if (val & 1)
+			omap2_dma_handle_ch(i);
+		val >>= 1;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction omap24xx_dma_irq = {
+	.name = "DMA",
+	.handler = irq_handler,
+	.flags = IRQF_DISABLED
+};
+
+static void omap2_set_transfer_params(int lch, int data_type, int sync_mode,
+				int dma_trigger, int src_or_dst_synch)
+{
+	u32 val, l;
+
+	l = dma_read(CSDP, lch);
+	l &= ~0x03;
+	l |= data_type;
+	dma_write(l, CSDP, lch);
+
+	if (dma_trigger) {
+		val = dma_read(CCR, lch);
+
+		/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
+		val &= ~((1 << 23) | (3 << 19) | 0x1f);
+		val |= (dma_trigger & ~0x1f) << 14;
+		val |= dma_trigger & 0x1f;
+
+		if (sync_mode & OMAP_DMA_SYNC_FRAME)
+			val |= 1 << 5;
+		else
+			val &= ~(1 << 5);
+
+		if (sync_mode & OMAP_DMA_SYNC_BLOCK)
+			val |= 1 << 18;
+		else
+			val &= ~(1 << 18);
+
+		if (src_or_dst_synch == OMAP_DMA_DST_SYNC_PREFETCH) {
+			val &= ~(1 << 24);	/* dest synch */
+			val |= (1 << 23);	/* Prefetch */
+		} else if (src_or_dst_synch) {
+			val |= 1 << 24;		/* source synch */
+		} else {
+			val &= ~(1 << 24);	/* dest synch */
+		}
+		dma_write(val, CCR, lch);
+	}
+}
+
+static void omap2_set_src_params(int lch, unsigned long src_start, int src_ei,
+								int src_fi)
+{
+	dma_write(src_start, CSSA, lch);
+
+	dma_write(src_ei, CSEI, lch);
+	dma_write(src_fi, CSFI, lch);
+}
+
+static void omap2_set_dest_params(int lch, unsigned long dest_start, int dst_ei,
+								int dst_fi)
+{
+	dma_write(dest_start, CDSA, lch);
+
+	dma_write(dst_ei, CDEI, lch);
+	dma_write(dst_fi, CDFI, lch);
+}
+
+static dma_addr_t omap2_set_src_pos(int lch)
+{
+	dma_addr_t offset = 0;
+
+	offset = dma_read(CSAC, lch);
+
+	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
+		offset = dma_read(CSAC, lch);
+
+	return offset;
+}
+
+static dma_addr_t omap2_get_dst_pos(int lch)
+{
+	dma_addr_t offset = 0;
+
+	offset = dma_read(CDAC, lch);
+
+	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && (offset == 0))
+		offset = dma_read(CDAC, lch);
+
+	return offset;
+}
+
+static void omap2_cpc_cdac_init(int lch)
+{
+	dma_write(0, CDAC, lch);
+}
+
 static void omap2_show_dma_caps(void)
 {
 	u8 revision = dma_read(REVISION, 0) & 0xff;
@@ -225,12 +621,624 @@ static u32 configure_dma_errata(void)
 	return errata;
 }
 
+/* Create chain of DMA channesls */
+static void create_dma_lch_chain(int lch_head, int lch_queue)
+{
+	u32 l;
+
+	/* Check if this is the first link in chain */
+	if (dma_chan[lch_head].next_linked_ch == -1) {
+		dma_chan[lch_head].next_linked_ch = lch_queue;
+		dma_chan[lch_head].prev_linked_ch = lch_queue;
+		dma_chan[lch_queue].next_linked_ch = lch_head;
+		dma_chan[lch_queue].prev_linked_ch = lch_head;
+	}
+
+	/* a link exists, link the new channel in circular chain */
+	else {
+		dma_chan[lch_queue].next_linked_ch =
+					dma_chan[lch_head].next_linked_ch;
+		dma_chan[lch_queue].prev_linked_ch = lch_head;
+		dma_chan[lch_head].next_linked_ch = lch_queue;
+		dma_chan[dma_chan[lch_queue].next_linked_ch].prev_linked_ch =
+					lch_queue;
+	}
+
+	l = dma_read(CLNK_CTRL, lch_head);
+	l &= ~(0x1f);
+	l |= lch_queue;
+	dma_write(l, CLNK_CTRL, lch_head);
+
+	l = dma_read(CLNK_CTRL, lch_queue);
+	l &= ~(0x1f);
+	l |= (dma_chan[lch_queue].next_linked_ch);
+	dma_write(l, CLNK_CTRL, lch_queue);
+}
+
+/**
+ * @brief omap_request_dma_chain : Request a chain of DMA channels
+ *
+ * @param dev_id - Device id using the dma channel
+ * @param dev_name - Device name
+ * @param callback - Call back function
+ * @chain_id -
+ * @no_of_chans - Number of channels requested
+ * @chain_mode - Dynamic or static chaining : OMAP_DMA_STATIC_CHAIN
+ * OMAP_DMA_DYNAMIC_CHAIN
+ * @params - Channel parameters
+ *
+ * @return - Success : 0
+ *           Failure: -EINVAL/-ENOMEM
+ */
+int omap_request_dma_chain(int dev_id, const char *dev_name,
+			   void (*callback) (int lch, u16 ch_status,
+					     void *data),
+			   int *chain_id, int no_of_chans, int chain_mode,
+			   struct omap_dma_channel_params params)
+{
+	int *channels;
+	int i, err;
+
+	/* Is the chain mode valid ? */
+	if (chain_mode != OMAP_DMA_STATIC_CHAIN
+			&& chain_mode != OMAP_DMA_DYNAMIC_CHAIN) {
+		printk(KERN_ERR "Invalid chain mode requested\n");
+		return -EINVAL;
+	}
+
+	if (unlikely((no_of_chans < 1
+			|| no_of_chans > dma_chan_count))) {
+		printk(KERN_ERR "Invalid Number of channels requested\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Allocate a queue to maintain the status of the channels
+	 * in the chain
+	 */
+	channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL);
+	if (channels == NULL) {
+		printk(KERN_ERR "omap_dma: No memory for channel queue\n");
+		return -ENOMEM;
+	}
+
+	/* request and reserve DMA channels for the chain */
+	for (i = 0; i < no_of_chans; i++) {
+		err = omap_request_dma(dev_id, dev_name,
+					callback, NULL, &channels[i]);
+		if (err < 0) {
+			int j;
+			for (j = 0; j < i; j++)
+				omap_free_dma(channels[j]);
+			kfree(channels);
+			printk(KERN_ERR "omap_dma: Request failed %d\n", err);
+			return err;
+		}
+		dma_chan[channels[i]].prev_linked_ch = -1;
+		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+
+		/*
+		 * Allowing client drivers to set common parameters now,
+		 * so that later only relevant (src_start, dest_start
+		 * and element count) can be set
+		 */
+		omap_set_dma_params(channels[i], &params);
+	}
+
+	*chain_id = channels[0];
+	dma_linked_lch[*chain_id].linked_dmach_q = channels;
+	dma_linked_lch[*chain_id].chain_mode = chain_mode;
+	dma_linked_lch[*chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
+	dma_linked_lch[*chain_id].no_of_lchs_linked = no_of_chans;
+
+	for (i = 0; i < no_of_chans; i++)
+		dma_chan[channels[i]].chain_id = *chain_id;
+
+	/* Reset the Queue pointers */
+	OMAP_DMA_CHAIN_QINIT(*chain_id);
+
+	/* Set up the chain */
+	if (no_of_chans == 1)
+		create_dma_lch_chain(channels[0], channels[0]);
+	else {
+		for (i = 0; i < (no_of_chans - 1); i++)
+			create_dma_lch_chain(channels[i], channels[i + 1]);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_request_dma_chain);
+
+/**
+ * @brief omap_modify_dma_chain_param : Modify the chain's params - Modify the
+ * params after setting it. Dont do this while dma is running!!
+ *
+ * @param chain_id - Chained logical channel id.
+ * @param params
+ *
+ * @return - Success : 0
+ *           Failure : -EINVAL
+ */
+int omap_modify_dma_chain_params(int chain_id,
+				struct omap_dma_channel_params params)
+{
+	int *channels;
+	u32 i;
+
+	/* Check for input params */
+	if (unlikely((chain_id < 0
+			|| chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	/* Check if the chain exists */
+	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+		printk(KERN_ERR "Chain doesn't exists\n");
+		return -EINVAL;
+	}
+	channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
+		/*
+		 * Allowing client drivers to set common parameters now,
+		 * so that later only relevant (src_start, dest_start
+		 * and element count) can be set
+		 */
+		omap_set_dma_params(channels[i], &params);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_modify_dma_chain_params);
+
+/**
+ * @brief omap_free_dma_chain - Free all the logical channels in a chain.
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ *           Failure : -EINVAL
+ */
+int omap_free_dma_chain(int chain_id)
+{
+	int *channels;
+	u32 i;
+
+	/* Check for input params */
+	if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	/* Check if the chain exists */
+	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+		printk(KERN_ERR "Chain doesn't exists\n");
+		return -EINVAL;
+	}
+
+	channels = dma_linked_lch[chain_id].linked_dmach_q;
+	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
+		dma_chan[channels[i]].next_linked_ch = -1;
+		dma_chan[channels[i]].prev_linked_ch = -1;
+		dma_chan[channels[i]].chain_id = -1;
+		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+		omap_free_dma(channels[i]);
+	}
+
+	kfree(channels);
+
+	dma_linked_lch[chain_id].linked_dmach_q = NULL;
+	dma_linked_lch[chain_id].chain_mode = -1;
+	dma_linked_lch[chain_id].chain_state = -1;
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_free_dma_chain);
+
+/**
+ * @brief omap_dma_chain_status - Check if the chain is in
+ * active / inactive state.
+ * @param chain_id
+ *
+ * @return - Success : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ *           Failure : -EINVAL
+ */
+int omap_dma_chain_status(int chain_id)
+{
+	/* Check for input params */
+	if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	/* Check if the chain exists */
+	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+		printk(KERN_ERR "Chain doesn't exists\n");
+		return -EINVAL;
+	}
+	pr_debug("CHAINID=%d, qcnt=%d\n", chain_id,
+			dma_linked_lch[chain_id].q_count);
+
+	if (OMAP_DMA_CHAIN_QEMPTY(chain_id))
+		return OMAP_DMA_CHAIN_INACTIVE;
+
+	return OMAP_DMA_CHAIN_ACTIVE;
+}
+EXPORT_SYMBOL(omap_dma_chain_status);
+
+/**
+ * @brief omap_dma_chain_a_transfer - Get a free channel from a chain,
+ * set the params and start the transfer.
+ *
+ * @param chain_id
+ * @param src_start - buffer start address
+ * @param dest_start - Dest address
+ * @param elem_count
+ * @param frame_count
+ * @param callbk_data - channel callback parameter data.
+ *
+ * @return  - Success : 0
+ *            Failure: -EINVAL/-EBUSY
+ */
+int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
+			int elem_count, int frame_count, void *callbk_data)
+{
+	int *channels;
+	u32 l, lch;
+	int start_dma = 0;
+
+	/*
+	 * if buffer size is less than 1 then there is
+	 * no use of starting the chain
+	 */
+	if (elem_count < 1) {
+		printk(KERN_ERR "Invalid buffer size\n");
+		return -EINVAL;
+	}
+
+	/* Check for input params */
+	if (unlikely((chain_id < 0
+			|| chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	/* Check if the chain exists */
+	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+		printk(KERN_ERR "Chain doesn't exist\n");
+		return -EINVAL;
+	}
+
+	/* Check if all the channels in chain are in use */
+	if (OMAP_DMA_CHAIN_QFULL(chain_id))
+		return -EBUSY;
+
+	/* Frame count may be negative in case of indexed transfers */
+	channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+	/* Get a free channel */
+	lch = channels[dma_linked_lch[chain_id].q_tail];
+
+	/* Store the callback data */
+	dma_chan[lch].data = callbk_data;
+
+	/* Increment the q_tail */
+	OMAP_DMA_CHAIN_INCQTAIL(chain_id);
+
+	/* Set the params to the free channel */
+	if (src_start != 0)
+		dma_write(src_start, CSSA, lch);
+	if (dest_start != 0)
+		dma_write(dest_start, CDSA, lch);
+
+	/* Write the buffer size */
+	dma_write(elem_count, CEN, lch);
+	dma_write(frame_count, CFN, lch);
+
+	/*
+	 * If the chain is dynamically linked,
+	 * then we may have to start the chain if its not active
+	 */
+	if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) {
+
+		/*
+		 * In Dynamic chain, if the chain is not started,
+		 * queue the channel
+		 */
+		if (dma_linked_lch[chain_id].chain_state ==
+						DMA_CHAIN_NOTSTARTED) {
+			/* Enable the link in previous channel */
+			if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
+								DMA_CH_QUEUED)
+				omap2_enable_lnk(dma_chan[lch].prev_linked_ch);
+			dma_chan[lch].state = DMA_CH_QUEUED;
+		}
+
+		/*
+		 * Chain is already started, make sure its active,
+		 * if not then start the chain
+		 */
+		else {
+			start_dma = 1;
+
+			if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
+							DMA_CH_STARTED) {
+				omap2_enable_lnk(dma_chan[lch].prev_linked_ch);
+				dma_chan[lch].state = DMA_CH_QUEUED;
+				start_dma = 0;
+				if (0 == ((1 << 7) & dma_read(
+					CCR, dma_chan[lch].prev_linked_ch))) {
+					omap2_disable_lnk(dma_chan[lch].
+						    prev_linked_ch);
+					pr_debug("\n prev ch is stopped\n");
+					start_dma = 1;
+				}
+			}
+
+			else if (dma_chan[dma_chan[lch].prev_linked_ch].state
+							== DMA_CH_QUEUED) {
+				omap2_enable_lnk(dma_chan[lch].prev_linked_ch);
+				dma_chan[lch].state = DMA_CH_QUEUED;
+				start_dma = 0;
+			}
+			omap2_enable_channel_irq(lch);
+
+			l = dma_read(CCR, lch);
+
+			if ((0 == (l & (1 << 24))))
+				l &= ~(1 << 25);
+			else
+				l |= (1 << 25);
+			if (start_dma == 1) {
+				if (0 == (l & (1 << 7))) {
+					l |= (1 << 7);
+					dma_chan[lch].state = DMA_CH_STARTED;
+					pr_debug("starting %d\n", lch);
+					dma_write(l, CCR, lch);
+				} else
+					start_dma = 0;
+			} else {
+				if (0 == (l & (1 << 7)))
+					dma_write(l, CCR, lch);
+			}
+			dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_dma_chain_a_transfer);
+
+/**
+ * @brief omap_start_dma_chain_transfers - Start the chain
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ *           Failure : -EINVAL/-EBUSY
+ */
+int omap_start_dma_chain_transfers(int chain_id)
+{
+	int *channels;
+	u32 l, i;
+
+	if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+	if (dma_linked_lch[channels[0]].chain_state == DMA_CHAIN_STARTED) {
+		printk(KERN_ERR "Chain is already started\n");
+		return -EBUSY;
+	}
+
+	if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_STATIC_CHAIN) {
+		for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked;
+									i++) {
+			omap2_enable_lnk(channels[i]);
+			omap2_enable_channel_irq(channels[i]);
+		}
+	} else {
+		omap2_enable_channel_irq(channels[0]);
+	}
+
+	l = dma_read(CCR, channels[0]);
+	l |= (1 << 7);
+	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
+	dma_chan[channels[0]].state = DMA_CH_STARTED;
+
+	if ((0 == (l & (1 << 24))))
+		l &= ~(1 << 25);
+	else
+		l |= (1 << 25);
+	dma_write(l, CCR, channels[0]);
+
+	dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_start_dma_chain_transfers);
+
+/**
+ * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain.
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ *           Failure : EINVAL
+ */
+int omap_stop_dma_chain_transfers(int chain_id)
+{
+	int *channels;
+	u32 l, i;
+	u32 sys_cf = 0;
+
+	/* Check for input params */
+	if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	/* Check if the chain exists */
+	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+		printk(KERN_ERR "Chain doesn't exists\n");
+		return -EINVAL;
+	}
+	channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
+		sys_cf = dma_read(OCP_SYSCONFIG, 0);
+		l = sys_cf;
+		/* Middle mode reg set no Standby */
+		l &= ~((1 << 12)|(1 << 13));
+		dma_write(l, OCP_SYSCONFIG, 0);
+	}
+	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
+
+		/* Stop the Channel transmission */
+		l = dma_read(CCR, channels[i]);
+		l &= ~(1 << 7);
+		dma_write(l, CCR, channels[i]);
+
+		/* Disable the link in all the channels */
+		omap2_disable_lnk(channels[i]);
+		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+
+	}
+	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
+
+	/* Reset the Queue pointers */
+	OMAP_DMA_CHAIN_QINIT(chain_id);
+
+	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+		dma_write(sys_cf, OCP_SYSCONFIG, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_stop_dma_chain_transfers);
+
+/* Get the index of the ongoing DMA in chain */
+/**
+ * @brief omap_get_dma_chain_index - Get the element and frame index
+ * of the ongoing DMA in chain
+ *
+ * @param chain_id
+ * @param ei - Element index
+ * @param fi - Frame index
+ *
+ * @return - Success : 0
+ *           Failure : -EINVAL
+ */
+int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
+{
+	int lch;
+	int *channels;
+
+	/* Check for input params */
+	if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	/* Check if the chain exists */
+	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+		printk(KERN_ERR "Chain doesn't exists\n");
+		return -EINVAL;
+	}
+	if ((!ei) || (!fi))
+		return -EINVAL;
+
+	channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+	/* Get the current channel */
+	lch = channels[dma_linked_lch[chain_id].q_head];
+
+	*ei = dma_read(CCEN, lch);
+	*fi = dma_read(CCFN, lch);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_get_dma_chain_index);
+
+/**
+ * @brief omap_get_dma_chain_dst_pos - Get the destination position of the
+ * ongoing DMA in chain
+ *
+ * @param chain_id
+ *
+ * @return - Success : Destination position
+ *           Failure : -EINVAL
+ */
+int omap_get_dma_chain_dst_pos(int chain_id)
+{
+	int lch;
+	int *channels;
+
+	/* Check for input params */
+	if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	/* Check if the chain exists */
+	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+		printk(KERN_ERR "Chain doesn't exists\n");
+		return -EINVAL;
+	}
+
+	channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+	/* Get the current channel */
+	lch = channels[dma_linked_lch[chain_id].q_head];
+
+	return dma_read(CDAC, lch);
+}
+EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
+
+/**
+ * @brief omap_get_dma_chain_src_pos - Get the source position
+ * of the ongoing DMA in chain
+ * @param chain_id
+ *
+ * @return - Success : Destination position
+ *           Failure : -EINVAL
+ */
+int omap_get_dma_chain_src_pos(int chain_id)
+{
+	int lch;
+	int *channels;
+
+	/* Check for input params */
+	if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+		printk(KERN_ERR "Invalid chain id\n");
+		return -EINVAL;
+	}
+
+	/* Check if the chain exists */
+	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+		printk(KERN_ERR "Chain doesn't exists\n");
+		return -EINVAL;
+	}
+
+	channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+	/* Get the current channel */
+	lch = channels[dma_linked_lch[chain_id].q_head];
+
+	return dma_read(CSAC, lch);
+}
+EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
+
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
 	struct omap_device			*od;
 	struct omap_system_dma_plat_info	*p;
 	struct resource				*mem;
+	int dma_irq, ret;
 	char					*name = "omap_dma_system";
 
 	dma_stride		= OMAP2_DMA_STRIDE;
@@ -249,12 +1257,27 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 
 	p->dma_attr		= (struct omap_dma_dev_attr *)oh->dev_attr;
 	p->disable_irq_lch	= omap2_disable_irq_lch;
+	p->enable_irq_lch	= omap2_enable_irq_lch;
+	p->cpc_cdac_init	= omap2_cpc_cdac_init;
+	p->set_transfer_params	= omap2_set_transfer_params;
+	p->set_color_mode	= omap2_set_color_mode;
+	p->set_src_params	= omap2_set_src_params;
+	p->set_dest_params	= omap2_set_dest_params;
+	p->get_src_pos		= omap2_set_src_pos;
+	p->get_dst_pos		= omap2_get_dst_pos;
+	p->clear_channel_int	= omap2_clear_channel_interrupt;
+	p->enable_channel_irq	= omap2_enable_channel_irq;
+	p->disable_channel_irq	= omap2_disable_channel_irq;
+	p->enable_lnk		= omap2_enable_lnk;
+	p->disable_lnk		= omap2_disable_lnk;
 	p->show_dma_caps	= omap2_show_dma_caps;
 	p->clear_dma		= omap2_clear_dma;
 	p->dma_write		= dma_write;
 	p->dma_read		= dma_read;
 
 	p->clear_lch_regs	= NULL;
+	p->get_gdma_dev		= NULL;
+	p->set_gdma_dev		= NULL;
 
 	p->errata		= configure_dma_errata();
 
@@ -266,6 +1289,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 			__func__, name, oh->name);
 		return IS_ERR(od);
 	}
+	pd = &od->pdev;
 
 	mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -279,6 +1303,20 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 	}
 
 	d = oh->dev_attr;
+	dma_irq = platform_get_irq_byname(&od->pdev, "0");
+	ret = setup_irq(dma_irq, &omap24xx_dma_irq);
+	if (ret) {
+		dev_err(&od->pdev.dev, "%s:irq handler setup fail\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Get DMA device attributes from hwmod data base */
+	d = (struct omap_dma_dev_attr *)oh->dev_attr;
+
+	/* OMAP2 Plus: physical and logical channel count is same */
+	d->chan_count  = d->lch_count;
+	dma_chan_count = d->chan_count;
+
 	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
 					(d->lch_count), GFP_KERNEL);
 
@@ -286,6 +1324,15 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
 		return -ENOMEM;
 	}
+
+	dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
+						dma_chan_count, GFP_KERNEL);
+	if (!dma_linked_lch) {
+		kfree(d->chan);
+		return -ENOMEM;
+	}
+	dma_chan = d->chan;
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/include/mach/dma.h b/arch/arm/mach-omap2/include/mach/dma.h
new file mode 100644
index 0000000..c6f1a20
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -0,0 +1,56 @@
+/*
+ *  OMAP2+ DMA driver API declarations
+ *
+ *  Copyright (C) 2003 Nokia Corporation
+ *  Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ *  Copyright (C) 2009 Texas Instruments
+ *  Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ *  Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *  Converted DMA library into platform driver
+ *          - G, Manjunath Kondaiah <manjugk@ti.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; 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_OMAP2_DMA_H
+#define __ASM_ARCH_OMAP2_DMA_H
+
+/* Chaining modes*/
+#define OMAP_DMA_STATIC_CHAIN		0x1
+#define OMAP_DMA_DYNAMIC_CHAIN		0x2
+#define OMAP_DMA_CHAIN_ACTIVE		0x1
+#define OMAP_DMA_CHAIN_INACTIVE		0x0
+
+/* Chaining APIs */
+extern int omap_request_dma_chain(int dev_id, const char *dev_name,
+				  void (*callback) (int lch, u16 ch_status,
+						    void *data),
+				  int *chain_id, int no_of_chans,
+				  int chain_mode,
+				  struct omap_dma_channel_params params);
+extern int omap_free_dma_chain(int chain_id);
+extern int omap_dma_chain_a_transfer(int chain_id, int src_start,
+				     int dest_start, int elem_count,
+				     int frame_count, void *callbk_data);
+extern int omap_start_dma_chain_transfers(int chain_id);
+extern int omap_stop_dma_chain_transfers(int chain_id);
+extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
+extern int omap_get_dma_chain_dst_pos(int chain_id);
+extern int omap_get_dma_chain_src_pos(int chain_id);
+
+extern int omap_modify_dma_chain_params(int chain_id,
+					struct omap_dma_channel_params params);
+extern int omap_dma_chain_status(int chain_id);
+
+#endif /* __ASM_ARCH_OMAP2_DMA_H */
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 3770cc6..c33c630 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -27,151 +27,33 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
-#include <mach/hardware.h>
 #include <plat/dma.h>
-
 #include <plat/tc.h>
 
-#undef DEBUG
-
-#ifndef CONFIG_ARCH_OMAP1
-enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
-	DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
-};
-
-enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
-#endif
-
-#define OMAP_DMA_ACTIVE			0x01
-#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
-
-#define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
-
 static struct omap_system_dma_plat_info *p;
 static struct omap_dma_dev_attr *d;
+static struct omap_dma_lch		*dma_chan;
 
 static int enable_1510_mode;
-static u32 errata;
-
-static struct omap_dma_global_context_registers {
-	u32 dma_irqenable_l0;
-	u32 dma_ocp_sysconfig;
-	u32 dma_gcr;
-} omap_dma_global_context;
-
-struct dma_link_info {
-	int *linked_dmach_q;
-	int no_of_lchs_linked;
-
-	int q_count;
-	int q_tail;
-	int q_head;
-
-	int chain_state;
-	int chain_mode;
-
-};
-
-static struct dma_link_info *dma_linked_lch;
-
-#ifndef CONFIG_ARCH_OMAP1
-
-/* Chain handling macros */
-#define OMAP_DMA_CHAIN_QINIT(chain_id)					\
-	do {								\
-		dma_linked_lch[chain_id].q_head =			\
-		dma_linked_lch[chain_id].q_tail =			\
-		dma_linked_lch[chain_id].q_count = 0;			\
-	} while (0)
-#define OMAP_DMA_CHAIN_QFULL(chain_id)					\
-		(dma_linked_lch[chain_id].no_of_lchs_linked ==		\
-		dma_linked_lch[chain_id].q_count)
-#define OMAP_DMA_CHAIN_QLAST(chain_id)					\
-	do {								\
-		((dma_linked_lch[chain_id].no_of_lchs_linked-1) ==	\
-		dma_linked_lch[chain_id].q_count)			\
-	} while (0)
-#define OMAP_DMA_CHAIN_QEMPTY(chain_id)					\
-		(0 == dma_linked_lch[chain_id].q_count)
-#define __OMAP_DMA_CHAIN_INCQ(end)					\
-	((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked)
-#define OMAP_DMA_CHAIN_INCQHEAD(chain_id)				\
-	do {								\
-		__OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head);	\
-		dma_linked_lch[chain_id].q_count--;			\
-	} while (0)
-
-#define OMAP_DMA_CHAIN_INCQTAIL(chain_id)				\
-	do {								\
-		__OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_tail);	\
-		dma_linked_lch[chain_id].q_count++; \
-	} while (0)
-#endif
-
 static int dma_lch_count;
 static int dma_chan_count;
 static int omap_dma_reserve_channels;
+static u32 errata;
 
 static spinlock_t dma_chan_lock;
-static struct omap_dma_lch *dma_chan;
-
-static inline void disable_lnk(int lch);
-static void omap_disable_channel_irq(int lch);
-static inline void omap_enable_channel_irq(int lch);
-
-#define REVISIT_24XX()		printk(KERN_ERR "FIXME: no %s on 24xx\n", \
-						__func__);
-
-#ifdef CONFIG_ARCH_OMAP15XX
-/* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
-int omap_dma_in_1510_mode(void)
-{
-	return enable_1510_mode;
-}
-#else
-#define omap_dma_in_1510_mode()		0
-#endif
-
-#ifdef CONFIG_ARCH_OMAP1
-static inline int get_gdma_dev(int req)
-{
-	u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
-	int shift = ((req - 1) % 5) * 6;
-
-	return ((omap_readl(reg) >> shift) & 0x3f) + 1;
-}
-
-static inline void set_gdma_dev(int req, int dev)
-{
-	u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
-	int shift = ((req - 1) % 5) * 6;
-	u32 l;
-
-	l = omap_readl(reg);
-	l &= ~(0x3f << shift);
-	l |= (dev - 1) << shift;
-	omap_writel(l, reg);
-}
-#else
-#define set_gdma_dev(req, dev)	do {} while (0)
-#endif
 
 void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
 	unsigned long reg;
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (d->dev_caps & IS_WORD_16) {
 		switch (dst_port) {
 		case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
 			reg = OMAP_TC_OCPT1_PRIOR;
@@ -193,9 +75,7 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
 		l &= ~(0xf << 8);
 		l |= (priority & 0xf) << 8;
 		omap_writel(l, reg);
-	}
-
-	if (cpu_class_is_omap2()) {
+	} else {
 		u32 ccr;
 
 		ccr = p->dma_read(CCR, lch);
@@ -212,151 +92,21 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 				  int frame_count, int sync_mode,
 				  int dma_trigger, int src_or_dst_synch)
 {
-	u32 l;
-
-	l = p->dma_read(CSDP, lch);
-	l &= ~0x03;
-	l |= data_type;
-	p->dma_write(l, CSDP, lch);
-
-	if (cpu_class_is_omap1()) {
-		u16 ccr;
-
-		ccr = p->dma_read(CCR, lch);
-		ccr &= ~(1 << 5);
-		if (sync_mode == OMAP_DMA_SYNC_FRAME)
-			ccr |= 1 << 5;
-		p->dma_write(ccr, CCR, lch);
-
-		ccr = p->dma_read(CCR2, lch);
-		ccr &= ~(1 << 2);
-		if (sync_mode == OMAP_DMA_SYNC_BLOCK)
-			ccr |= 1 << 2;
-		p->dma_write(ccr, CCR2, lch);
-	}
-
-	if (cpu_class_is_omap2() && dma_trigger) {
-		u32 val;
-
-		val = p->dma_read(CCR, lch);
-
-		/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
-		val &= ~((1 << 23) | (3 << 19) | 0x1f);
-		val |= (dma_trigger & ~0x1f) << 14;
-		val |= dma_trigger & 0x1f;
-
-		if (sync_mode & OMAP_DMA_SYNC_FRAME)
-			val |= 1 << 5;
-		else
-			val &= ~(1 << 5);
-
-		if (sync_mode & OMAP_DMA_SYNC_BLOCK)
-			val |= 1 << 18;
-		else
-			val &= ~(1 << 18);
-
-		if (src_or_dst_synch == OMAP_DMA_DST_SYNC_PREFETCH) {
-			val &= ~(1 << 24);	/* dest synch */
-			val |= (1 << 23);	/* Prefetch */
-		} else if (src_or_dst_synch) {
-			val |= 1 << 24;		/* source synch */
-		} else {
-			val &= ~(1 << 24);	/* dest synch */
-		}
-		p->dma_write(val, CCR, lch);
-	}
-
 	p->dma_write(elem_count, CEN, lch);
 	p->dma_write(frame_count, CFN, lch);
+
+	p->set_transfer_params(lch, data_type, sync_mode, dma_trigger,
+							src_or_dst_synch);
 }
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 
 void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 {
-	BUG_ON(omap_dma_in_1510_mode());
-
-	if (cpu_class_is_omap1()) {
-		u16 w;
-
-		w = p->dma_read(CCR2, lch);
-		w &= ~0x03;
-
-		switch (mode) {
-		case OMAP_DMA_CONSTANT_FILL:
-			w |= 0x01;
-			break;
-		case OMAP_DMA_TRANSPARENT_COPY:
-			w |= 0x02;
-			break;
-		case OMAP_DMA_COLOR_DIS:
-			break;
-		default:
-			BUG();
-		}
-		p->dma_write(w, CCR2, lch);
-
-		w = p->dma_read(LCH_CTRL, lch);
-		w &= ~0x0f;
-		/* Default is channel type 2D */
-		if (mode) {
-			p->dma_write(color, COLOR, lch);
-			w |= 1;		/* Channel type G */
-		}
-		p->dma_write(w, LCH_CTRL, lch);
-	}
-
-	if (cpu_class_is_omap2()) {
-		u32 val;
-
-		val = p->dma_read(CCR, lch);
-		val &= ~((1 << 17) | (1 << 16));
-
-		switch (mode) {
-		case OMAP_DMA_CONSTANT_FILL:
-			val |= 1 << 16;
-			break;
-		case OMAP_DMA_TRANSPARENT_COPY:
-			val |= 1 << 17;
-			break;
-		case OMAP_DMA_COLOR_DIS:
-			break;
-		default:
-			BUG();
-		}
-		p->dma_write(val, CCR, lch);
-
-		color &= 0xffffff;
-		p->dma_write(color, COLOR, lch);
-	}
+	BUG_ON(enable_1510_mode);
+	p->set_color_mode(lch, mode, color);
 }
 EXPORT_SYMBOL(omap_set_dma_color_mode);
 
-void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
-{
-	if (cpu_class_is_omap2()) {
-		u32 csdp;
-
-		csdp = p->dma_read(CSDP, lch);
-		csdp &= ~(0x3 << 16);
-		csdp |= (mode << 16);
-		p->dma_write(csdp, CSDP, lch);
-	}
-}
-EXPORT_SYMBOL(omap_set_dma_write_mode);
-
-void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
-{
-	if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
-		u32 l;
-
-		l = p->dma_read(LCH_CTRL, lch);
-		l &= ~0x7;
-		l |= mode;
-		p->dma_write(l, LCH_CTRL, lch);
-	}
-}
-EXPORT_SYMBOL(omap_set_dma_channel_mode);
-
 /* Note that src_port is only for omap1 */
 void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 			     unsigned long src_start,
@@ -364,7 +114,7 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 {
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (d->dev_caps & IS_WORD_16) {
 		u16 w;
 
 		w = p->dma_read(CSDP, lch);
@@ -378,10 +128,7 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 	l |= src_amode << 12;
 	p->dma_write(l, CCR, lch);
 
-	p->dma_write(src_start, CSSA, lch);
-
-	p->dma_write(src_ei, CSEI, lch);
-	p->dma_write(src_fi, CSFI, lch);
+	p->set_src_params(lch, src_start, src_ei, src_fi);
 }
 EXPORT_SYMBOL(omap_set_dma_src_params);
 
@@ -404,16 +151,6 @@ void omap_set_dma_params(int lch, struct omap_dma_channel_params *params)
 }
 EXPORT_SYMBOL(omap_set_dma_params);
 
-void omap_set_dma_src_index(int lch, int eidx, int fidx)
-{
-	if (cpu_class_is_omap2())
-		return;
-
-	p->dma_write(eidx, CSEI, lch);
-	p->dma_write(fidx, CSFI, lch);
-}
-EXPORT_SYMBOL(omap_set_dma_src_index);
-
 void omap_set_dma_src_data_pack(int lch, int enable)
 {
 	u32 l;
@@ -438,26 +175,24 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	case OMAP_DMA_DATA_BURST_DIS:
 		break;
 	case OMAP_DMA_DATA_BURST_4:
-		if (cpu_class_is_omap2())
+		if (!(d->dev_caps & IS_BURST_ONLY4))
 			burst = 0x1;
 		else
 			burst = 0x2;
 		break;
 	case OMAP_DMA_DATA_BURST_8:
-		if (cpu_class_is_omap2()) {
+		if (!(d->dev_caps & IS_BURST_ONLY4))
 			burst = 0x2;
-			break;
-		}
+		break;
 		/*
 		 * not supported by current hardware on OMAP1
 		 * w |= (0x03 << 7);
 		 * fall through
 		 */
 	case OMAP_DMA_DATA_BURST_16:
-		if (cpu_class_is_omap2()) {
+		if (!(d->dev_caps & IS_BURST_ONLY4))
 			burst = 0x3;
-			break;
-		}
+		break;
 		/*
 		 * OMAP1 don't support burst 16
 		 * fall through
@@ -473,40 +208,26 @@ EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
 
 /* Note that dest_port is only for OMAP1 */
 void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
-			      unsigned long dest_start,
-			      int dst_ei, int dst_fi)
+		      unsigned long dest_start, int dst_ei, int dst_fi)
 {
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (d->dev_caps & IS_WORD_16) {
 		l = p->dma_read(CSDP, lch);
 		l &= ~(0x1f << 9);
 		l |= dest_port << 9;
 		p->dma_write(l, CSDP, lch);
 	}
-
 	l = p->dma_read(CCR, lch);
 	l &= ~(0x03 << 14);
 	l |= dest_amode << 14;
 	p->dma_write(l, CCR, lch);
 
-	p->dma_write(dest_start, CDSA, lch);
+	p->set_dest_params(lch, dest_start, dst_ei, dst_fi);
 
-	p->dma_write(dst_ei, CDEI, lch);
-	p->dma_write(dst_fi, CDFI, lch);
 }
 EXPORT_SYMBOL(omap_set_dma_dest_params);
 
-void omap_set_dma_dest_index(int lch, int eidx, int fidx)
-{
-	if (cpu_class_is_omap2())
-		return;
-
-	p->dma_write(eidx, CDEI, lch);
-	p->dma_write(fidx, CDFI, lch);
-}
-EXPORT_SYMBOL(omap_set_dma_dest_index);
-
 void omap_set_dma_dest_data_pack(int lch, int enable)
 {
 	u32 l;
@@ -531,22 +252,21 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	case OMAP_DMA_DATA_BURST_DIS:
 		break;
 	case OMAP_DMA_DATA_BURST_4:
-		if (cpu_class_is_omap2())
+		if (!(d->dev_caps & IS_BURST_ONLY4))
 			burst = 0x1;
 		else
 			burst = 0x2;
 		break;
 	case OMAP_DMA_DATA_BURST_8:
-		if (cpu_class_is_omap2())
+		if (!(d->dev_caps & IS_BURST_ONLY4))
 			burst = 0x2;
 		else
 			burst = 0x3;
 		break;
 	case OMAP_DMA_DATA_BURST_16:
-		if (cpu_class_is_omap2()) {
+		if (!(d->dev_caps & IS_BURST_ONLY4))
 			burst = 0x3;
-			break;
-		}
+		break;
 		/*
 		 * OMAP1 don't support burst 16
 		 * fall through
@@ -561,26 +281,6 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 }
 EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
 
-static inline void omap_enable_channel_irq(int lch)
-{
-	u32 status;
-
-	/* Clear CSR */
-	if (cpu_class_is_omap1())
-		status = p->dma_read(CSR, lch);
-	else if (cpu_class_is_omap2())
-		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
-
-	/* Enable some nice interrupts. */
-	p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
-}
-
-static void omap_disable_channel_irq(int lch)
-{
-	if (cpu_class_is_omap2())
-		p->dma_write(0, CICR, lch);
-}
-
 void omap_enable_dma_irq(int lch, u16 bits)
 {
 	dma_chan[lch].enabled_irqs |= bits;
@@ -593,81 +293,6 @@ void omap_disable_dma_irq(int lch, u16 bits)
 }
 EXPORT_SYMBOL(omap_disable_dma_irq);
 
-static inline void enable_lnk(int lch)
-{
-	u32 l;
-
-	l = p->dma_read(CLNK_CTRL, lch);
-
-	if (cpu_class_is_omap1())
-		l &= ~(1 << 14);
-
-	/* Set the ENABLE_LNK bits */
-	if (dma_chan[lch].next_lch != -1)
-		l = dma_chan[lch].next_lch | (1 << 15);
-
-#ifndef CONFIG_ARCH_OMAP1
-	if (cpu_class_is_omap2())
-		if (dma_chan[lch].next_linked_ch != -1)
-			l = dma_chan[lch].next_linked_ch | (1 << 15);
-#endif
-
-	p->dma_write(l, CLNK_CTRL, lch);
-}
-
-static inline void disable_lnk(int lch)
-{
-	u32 l;
-
-	l = p->dma_read(CLNK_CTRL, lch);
-
-	/* Disable interrupts */
-	if (cpu_class_is_omap1()) {
-		p->dma_write(0, CICR, lch);
-		/* Set the STOP_LNK bit */
-		l |= 1 << 14;
-	}
-
-	if (cpu_class_is_omap2()) {
-		omap_disable_channel_irq(lch);
-		/* Clear the ENABLE_LNK bit */
-		l &= ~(1 << 15);
-	}
-
-	p->dma_write(l, CLNK_CTRL, lch);
-	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
-}
-
-static inline void omap2_enable_irq_lch(int lch)
-{
-	u32 val;
-	unsigned long flags;
-
-	if (!cpu_class_is_omap2())
-		return;
-
-	spin_lock_irqsave(&dma_chan_lock, flags);
-	val = p->dma_read(IRQENABLE_L0, lch);
-	val |= 1 << lch;
-	p->dma_write(val, IRQENABLE_L0, lch);
-	spin_unlock_irqrestore(&dma_chan_lock, flags);
-}
-
-static inline void omap2_disable_irq_lch(int lch)
-{
-	u32 val;
-	unsigned long flags;
-
-	if (!cpu_class_is_omap2())
-		return;
-
-	spin_lock_irqsave(&dma_chan_lock, flags);
-	val = p->dma_read(IRQENABLE_L0, lch);
-	val &= ~(1 << lch);
-	p->dma_write(val, IRQENABLE_L0, lch);
-	spin_unlock_irqrestore(&dma_chan_lock, flags);
-}
-
 int omap_request_dma(int dev_id, const char *dev_name,
 		     void (*callback)(int lch, u16 ch_status, void *data),
 		     void *data, int *dma_ch_out)
@@ -691,10 +316,9 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	chan = dma_chan + free_ch;
 	chan->dev_id = dev_id;
 
-	if (p->clear_lch_regs)
+	if (d->dev_caps & IS_WORD_16)
 		p->clear_lch_regs(free_ch);
-
-	if (cpu_class_is_omap2())
+	else
 		omap_clear_dma(free_ch);
 
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
@@ -704,25 +328,23 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	chan->data = data;
 	chan->flags = 0;
 
-#ifndef CONFIG_ARCH_OMAP1
-	if (cpu_class_is_omap2()) {
+	if (d->dev_caps & DMA_LINKED_LCH) {
 		chan->chain_id = -1;
 		chan->next_linked_ch = -1;
 	}
-#endif
 
 	chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
 
-	if (cpu_class_is_omap1())
+	if (d->dev_caps & IS_WORD_16)
 		chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
-	else if (cpu_class_is_omap2())
+	else
 		chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
 			OMAP2_DMA_TRANS_ERR_IRQ;
 
-	if (cpu_is_omap16xx()) {
+	if (p->set_gdma_dev) {
 		/* If the sync device is set, configure it dynamically. */
 		if (dev_id != 0) {
-			set_gdma_dev(free_ch + 1, dev_id);
+			p->set_gdma_dev(free_ch + 1, dev_id);
 			dev_id = free_ch + 1;
 		}
 		/*
@@ -730,18 +352,17 @@ int omap_request_dma(int dev_id, const char *dev_name,
 		 * id.
 		 */
 		p->dma_write(dev_id | (1 << 10), CCR, free_ch);
-	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
+	} else if (d->dev_caps & IS_WORD_16)
 		p->dma_write(dev_id, CCR, free_ch);
-	}
 
-	if (cpu_class_is_omap2()) {
-		omap2_enable_irq_lch(free_ch);
-		omap_enable_channel_irq(free_ch);
+	if (p->enable_irq_lch) {
+		spin_lock_irqsave(&dma_chan_lock, flags);
+		p->enable_irq_lch(free_ch);
+		spin_unlock_irqrestore(&dma_chan_lock, flags);
+		p->enable_channel_irq(free_ch);
 		/* Clear the CSR register and IRQ status register */
-		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch);
-		p->dma_write(1 << free_ch, IRQSTATUS_L0, 0);
+		p->clear_channel_int(free_ch);
 	}
-
 	*dma_ch_out = free_ch;
 
 	return 0;
@@ -758,19 +379,20 @@ void omap_free_dma(int lch)
 		return;
 	}
 
-	if (cpu_class_is_omap1()) {
+	if (d->dev_caps & IS_WORD_16) {
 		/* Disable all DMA interrupts for the channel. */
 		p->dma_write(0, CICR, lch);
 		/* Make sure the DMA transfer is stopped. */
 		p->dma_write(0, CCR, lch);
 	}
 
-	if (cpu_class_is_omap2()) {
-		omap2_disable_irq_lch(lch);
+	if (p->disable_irq_lch) {
+		spin_lock_irqsave(&dma_chan_lock, flags);
+		p->disable_irq_lch(lch);
+		spin_unlock_irqrestore(&dma_chan_lock, flags);
 
 		/* Clear the CSR register and IRQ status register */
-		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
-		p->dma_write(1 << lch, IRQSTATUS_L0, lch);
+		p->clear_channel_int(lch);
 
 		/* Disable all DMA interrupts for the channel. */
 		p->dma_write(0, CICR, lch);
@@ -789,39 +411,6 @@ void omap_free_dma(int lch)
 EXPORT_SYMBOL(omap_free_dma);
 
 /**
- * @brief omap_dma_set_global_params : Set global priority settings for dma
- *
- * @param arb_rate
- * @param max_fifo_depth
- * @param tparams - Number of threads to reserve : DMA_THREAD_RESERVE_NORM
- * 						   DMA_THREAD_RESERVE_ONET
- * 						   DMA_THREAD_RESERVE_TWOT
- * 						   DMA_THREAD_RESERVE_THREET
- */
-void
-omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
-{
-	u32 reg;
-
-	if (!cpu_class_is_omap2()) {
-		printk(KERN_ERR "FIXME: no %s on 15xx/16xx\n", __func__);
-		return;
-	}
-
-	if (max_fifo_depth == 0)
-		max_fifo_depth = 1;
-	if (arb_rate == 0)
-		arb_rate = 1;
-
-	reg = 0xff & max_fifo_depth;
-	reg |= (0x3 & tparams) << 12;
-	reg |= (arb_rate & 0xff) << 16;
-
-	p->dma_write(reg, GCR, 0);
-}
-EXPORT_SYMBOL(omap_dma_set_global_params);
-
-/**
  * @brief omap_dma_set_prio_lch : Set channel wise priority settings
  *
  * @param lch
@@ -841,12 +430,13 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
 		return -EINVAL;
 	}
 	l = p->dma_read(CCR, lch);
-	l &= ~((1 << 6) | (1 << 26));
-	if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
+	if (d->dev_caps & IS_RW_PRIORITY) {
+		l &= ~((1 << 6) | (1 << 26));
 		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
-	else
+	} else {
+		l &= ~(1 << 6);
 		l |= ((read_prio & 0x1) << 6);
-
+	}
 	p->dma_write(l, CCR, lch);
 
 	return 0;
@@ -875,18 +465,16 @@ void omap_start_dma(int lch)
 	 * The CPC/CDAC register needs to be initialized to zero
 	 * before starting dma transfer.
 	 */
-	if (cpu_is_omap15xx())
-		p->dma_write(0, CPC, lch);
-	else
-		p->dma_write(0, CDAC, lch);
+	p->cpc_cdac_init(lch);
 
-	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+
+	if (!enable_1510_mode && dma_chan[lch].next_lch != -1) {
 		int next_lch, cur_lch;
-		char dma_chan_link_map[dma_lch_count];
+		char dma_chan_link_map[dma_chan_count];
 
 		dma_chan_link_map[lch] = 1;
 		/* Set the link register of the first channel */
-		enable_lnk(lch);
+		p->enable_lnk(lch);
 
 		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
 		cur_lch = dma_chan[lch].next_lch;
@@ -899,22 +487,24 @@ void omap_start_dma(int lch)
 			/* Mark the current channel */
 			dma_chan_link_map[cur_lch] = 1;
 
-			enable_lnk(cur_lch);
-			omap_enable_channel_irq(cur_lch);
+			p->enable_lnk(cur_lch);
+			p->enable_channel_irq(cur_lch);
 
 			cur_lch = next_lch;
 		} while (next_lch != -1);
 	} else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
 		p->dma_write(lch, CLNK_CTRL, lch);
 
-	omap_enable_channel_irq(lch);
+	p->enable_channel_irq(lch);
 
 	l = p->dma_read(CCR, lch);
-
-	if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
+	if (d->dev_caps & IS_WORD_16)
+		l |= OMAP_DMA_CCR_EN;
+	else {
+		if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
 			l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
-	l |= OMAP_DMA_CCR_EN;
-
+		l |= OMAP_DMA_CCR_EN;
+	}
 	p->dma_write(l, CCR, lch);
 
 	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
@@ -923,10 +513,10 @@ EXPORT_SYMBOL(omap_start_dma);
 
 void omap_stop_dma(int lch)
 {
-	u32 l;
+	u32 l = 0;
 
 	/* Disable all interrupts on the channel */
-	if (cpu_class_is_omap1())
+	if (d->dev_caps & IS_WORD_16)
 		p->dma_write(0, CICR, lch);
 
 	l = p->dma_read(CCR, lch);
@@ -964,7 +554,7 @@ void omap_stop_dma(int lch)
 		p->dma_write(l, CCR, lch);
 	}
 
-	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+	if (!enable_1510_mode && dma_chan[lch].next_lch != -1) {
 		int next_lch, cur_lch = lch;
 		char dma_chan_link_map[dma_lch_count];
 
@@ -976,7 +566,7 @@ void omap_stop_dma(int lch)
 			/* Mark the current channel */
 			dma_chan_link_map[cur_lch] = 1;
 
-			disable_lnk(cur_lch);
+			p->disable_lnk(cur_lch);
 
 			next_lch = dma_chan[cur_lch].next_lch;
 			cur_lch = next_lch;
@@ -1024,20 +614,7 @@ EXPORT_SYMBOL(omap_set_dma_callback);
  */
 dma_addr_t omap_get_dma_src_pos(int lch)
 {
-	dma_addr_t offset = 0;
-
-	if (cpu_is_omap15xx())
-		offset = p->dma_read(CPC, lch);
-	else
-		offset = p->dma_read(CSAC, lch);
-
-	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
-		offset = p->dma_read(CSAC, lch);
-
-	if (cpu_class_is_omap1())
-		offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000);
-
-	return offset;
+	return p->get_src_pos(lch);
 }
 EXPORT_SYMBOL(omap_get_dma_src_pos);
 
@@ -1051,24 +628,7 @@ EXPORT_SYMBOL(omap_get_dma_src_pos);
  */
 dma_addr_t omap_get_dma_dst_pos(int lch)
 {
-	dma_addr_t offset = 0;
-
-	if (cpu_is_omap15xx())
-		offset = p->dma_read(CPC, lch);
-	else
-		offset = p->dma_read(CDAC, lch);
-
-	/*
-	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
-	 * read before the DMA controller finished disabling the channel.
-	 */
-	if (!cpu_is_omap15xx() && offset == 0)
-		offset = p->dma_read(CDAC, lch);
-
-	if (cpu_class_is_omap1())
-		offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000);
-
-	return offset;
+	return p->get_dst_pos(lch);
 }
 EXPORT_SYMBOL(omap_get_dma_dst_pos);
 
@@ -1082,7 +642,7 @@ int omap_dma_running(void)
 {
 	int lch;
 
-	if (cpu_class_is_omap1())
+	if (d->dev_caps & IS_WORD_16)
 		if (omap_lcd_dma_running())
 			return 1;
 
@@ -1100,7 +660,7 @@ int omap_dma_running(void)
  */
 void omap_dma_link_lch(int lch_head, int lch_queue)
 {
-	if (omap_dma_in_1510_mode()) {
+	if (enable_1510_mode) {
 		if (lch_head == lch_queue) {
 			p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8),
 								CCR, lch_head);
@@ -1127,7 +687,7 @@ EXPORT_SYMBOL(omap_dma_link_lch);
  */
 void omap_dma_unlink_lch(int lch_head, int lch_queue)
 {
-	if (omap_dma_in_1510_mode()) {
+	if (enable_1510_mode) {
 		if (lch_head == lch_queue) {
 			p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8),
 								CCR, lch_head);
@@ -1156,820 +716,9 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
 }
 EXPORT_SYMBOL(omap_dma_unlink_lch);
 
-#ifndef CONFIG_ARCH_OMAP1
-/* Create chain of DMA channesls */
-static void create_dma_lch_chain(int lch_head, int lch_queue)
-{
-	u32 l;
-
-	/* Check if this is the first link in chain */
-	if (dma_chan[lch_head].next_linked_ch == -1) {
-		dma_chan[lch_head].next_linked_ch = lch_queue;
-		dma_chan[lch_head].prev_linked_ch = lch_queue;
-		dma_chan[lch_queue].next_linked_ch = lch_head;
-		dma_chan[lch_queue].prev_linked_ch = lch_head;
-	}
-
-	/* a link exists, link the new channel in circular chain */
-	else {
-		dma_chan[lch_queue].next_linked_ch =
-					dma_chan[lch_head].next_linked_ch;
-		dma_chan[lch_queue].prev_linked_ch = lch_head;
-		dma_chan[lch_head].next_linked_ch = lch_queue;
-		dma_chan[dma_chan[lch_queue].next_linked_ch].prev_linked_ch =
-					lch_queue;
-	}
-
-	l = p->dma_read(CLNK_CTRL, lch_head);
-	l &= ~(0x1f);
-	l |= lch_queue;
-	p->dma_write(l, CLNK_CTRL, lch_head);
-
-	l = p->dma_read(CLNK_CTRL, lch_queue);
-	l &= ~(0x1f);
-	l |= (dma_chan[lch_queue].next_linked_ch);
-	p->dma_write(l, CLNK_CTRL, lch_queue);
-}
-
-/**
- * @brief omap_request_dma_chain : Request a chain of DMA channels
- *
- * @param dev_id - Device id using the dma channel
- * @param dev_name - Device name
- * @param callback - Call back function
- * @chain_id -
- * @no_of_chans - Number of channels requested
- * @chain_mode - Dynamic or static chaining : OMAP_DMA_STATIC_CHAIN
- * 					      OMAP_DMA_DYNAMIC_CHAIN
- * @params - Channel parameters
- *
- * @return - Success : 0
- * 	     Failure: -EINVAL/-ENOMEM
- */
-int omap_request_dma_chain(int dev_id, const char *dev_name,
-			   void (*callback) (int lch, u16 ch_status,
-					     void *data),
-			   int *chain_id, int no_of_chans, int chain_mode,
-			   struct omap_dma_channel_params params)
-{
-	int *channels;
-	int i, err;
-
-	/* Is the chain mode valid ? */
-	if (chain_mode != OMAP_DMA_STATIC_CHAIN
-			&& chain_mode != OMAP_DMA_DYNAMIC_CHAIN) {
-		printk(KERN_ERR "Invalid chain mode requested\n");
-		return -EINVAL;
-	}
-
-	if (unlikely((no_of_chans < 1
-			|| no_of_chans > dma_lch_count))) {
-		printk(KERN_ERR "Invalid Number of channels requested\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Allocate a queue to maintain the status of the channels
-	 * in the chain
-	 */
-	channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL);
-	if (channels == NULL) {
-		printk(KERN_ERR "omap_dma: No memory for channel queue\n");
-		return -ENOMEM;
-	}
-
-	/* request and reserve DMA channels for the chain */
-	for (i = 0; i < no_of_chans; i++) {
-		err = omap_request_dma(dev_id, dev_name,
-					callback, NULL, &channels[i]);
-		if (err < 0) {
-			int j;
-			for (j = 0; j < i; j++)
-				omap_free_dma(channels[j]);
-			kfree(channels);
-			printk(KERN_ERR "omap_dma: Request failed %d\n", err);
-			return err;
-		}
-		dma_chan[channels[i]].prev_linked_ch = -1;
-		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
-
-		/*
-		 * Allowing client drivers to set common parameters now,
-		 * so that later only relevant (src_start, dest_start
-		 * and element count) can be set
-		 */
-		omap_set_dma_params(channels[i], &params);
-	}
-
-	*chain_id = channels[0];
-	dma_linked_lch[*chain_id].linked_dmach_q = channels;
-	dma_linked_lch[*chain_id].chain_mode = chain_mode;
-	dma_linked_lch[*chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
-	dma_linked_lch[*chain_id].no_of_lchs_linked = no_of_chans;
-
-	for (i = 0; i < no_of_chans; i++)
-		dma_chan[channels[i]].chain_id = *chain_id;
-
-	/* Reset the Queue pointers */
-	OMAP_DMA_CHAIN_QINIT(*chain_id);
-
-	/* Set up the chain */
-	if (no_of_chans == 1)
-		create_dma_lch_chain(channels[0], channels[0]);
-	else {
-		for (i = 0; i < (no_of_chans - 1); i++)
-			create_dma_lch_chain(channels[i], channels[i + 1]);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_request_dma_chain);
-
-/**
- * @brief omap_modify_dma_chain_param : Modify the chain's params - Modify the
- * params after setting it. Dont do this while dma is running!!
- *
- * @param chain_id - Chained logical channel id.
- * @param params
- *
- * @return - Success : 0
- * 	     Failure : -EINVAL
- */
-int omap_modify_dma_chain_params(int chain_id,
-				struct omap_dma_channel_params params)
-{
-	int *channels;
-	u32 i;
-
-	/* Check for input params */
-	if (unlikely((chain_id < 0
-			|| chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	/* Check if the chain exists */
-	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
-		printk(KERN_ERR "Chain doesn't exists\n");
-		return -EINVAL;
-	}
-	channels = dma_linked_lch[chain_id].linked_dmach_q;
-
-	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
-		/*
-		 * Allowing client drivers to set common parameters now,
-		 * so that later only relevant (src_start, dest_start
-		 * and element count) can be set
-		 */
-		omap_set_dma_params(channels[i], &params);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_modify_dma_chain_params);
-
-/**
- * @brief omap_free_dma_chain - Free all the logical channels in a chain.
- *
- * @param chain_id
- *
- * @return - Success : 0
- * 	     Failure : -EINVAL
- */
-int omap_free_dma_chain(int chain_id)
-{
-	int *channels;
-	u32 i;
-
-	/* Check for input params */
-	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	/* Check if the chain exists */
-	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
-		printk(KERN_ERR "Chain doesn't exists\n");
-		return -EINVAL;
-	}
-
-	channels = dma_linked_lch[chain_id].linked_dmach_q;
-	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
-		dma_chan[channels[i]].next_linked_ch = -1;
-		dma_chan[channels[i]].prev_linked_ch = -1;
-		dma_chan[channels[i]].chain_id = -1;
-		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
-		omap_free_dma(channels[i]);
-	}
-
-	kfree(channels);
-
-	dma_linked_lch[chain_id].linked_dmach_q = NULL;
-	dma_linked_lch[chain_id].chain_mode = -1;
-	dma_linked_lch[chain_id].chain_state = -1;
-
-	return (0);
-}
-EXPORT_SYMBOL(omap_free_dma_chain);
-
-/**
- * @brief omap_dma_chain_status - Check if the chain is in
- * active / inactive state.
- * @param chain_id
- *
- * @return - Success : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
- * 	     Failure : -EINVAL
- */
-int omap_dma_chain_status(int chain_id)
-{
-	/* Check for input params */
-	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	/* Check if the chain exists */
-	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
-		printk(KERN_ERR "Chain doesn't exists\n");
-		return -EINVAL;
-	}
-	pr_debug("CHAINID=%d, qcnt=%d\n", chain_id,
-			dma_linked_lch[chain_id].q_count);
-
-	if (OMAP_DMA_CHAIN_QEMPTY(chain_id))
-		return OMAP_DMA_CHAIN_INACTIVE;
-
-	return OMAP_DMA_CHAIN_ACTIVE;
-}
-EXPORT_SYMBOL(omap_dma_chain_status);
-
-/**
- * @brief omap_dma_chain_a_transfer - Get a free channel from a chain,
- * set the params and start the transfer.
- *
- * @param chain_id
- * @param src_start - buffer start address
- * @param dest_start - Dest address
- * @param elem_count
- * @param frame_count
- * @param callbk_data - channel callback parameter data.
- *
- * @return  - Success : 0
- * 	      Failure: -EINVAL/-EBUSY
- */
-int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
-			int elem_count, int frame_count, void *callbk_data)
-{
-	int *channels;
-	u32 l, lch;
-	int start_dma = 0;
-
-	/*
-	 * if buffer size is less than 1 then there is
-	 * no use of starting the chain
-	 */
-	if (elem_count < 1) {
-		printk(KERN_ERR "Invalid buffer size\n");
-		return -EINVAL;
-	}
-
-	/* Check for input params */
-	if (unlikely((chain_id < 0
-			|| chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	/* Check if the chain exists */
-	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
-		printk(KERN_ERR "Chain doesn't exist\n");
-		return -EINVAL;
-	}
-
-	/* Check if all the channels in chain are in use */
-	if (OMAP_DMA_CHAIN_QFULL(chain_id))
-		return -EBUSY;
-
-	/* Frame count may be negative in case of indexed transfers */
-	channels = dma_linked_lch[chain_id].linked_dmach_q;
-
-	/* Get a free channel */
-	lch = channels[dma_linked_lch[chain_id].q_tail];
-
-	/* Store the callback data */
-	dma_chan[lch].data = callbk_data;
-
-	/* Increment the q_tail */
-	OMAP_DMA_CHAIN_INCQTAIL(chain_id);
-
-	/* Set the params to the free channel */
-	if (src_start != 0)
-		p->dma_write(src_start, CSSA, lch);
-	if (dest_start != 0)
-		p->dma_write(dest_start, CDSA, lch);
-
-	/* Write the buffer size */
-	p->dma_write(elem_count, CEN, lch);
-	p->dma_write(frame_count, CFN, lch);
-
-	/*
-	 * If the chain is dynamically linked,
-	 * then we may have to start the chain if its not active
-	 */
-	if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) {
-
-		/*
-		 * In Dynamic chain, if the chain is not started,
-		 * queue the channel
-		 */
-		if (dma_linked_lch[chain_id].chain_state ==
-						DMA_CHAIN_NOTSTARTED) {
-			/* Enable the link in previous channel */
-			if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
-								DMA_CH_QUEUED)
-				enable_lnk(dma_chan[lch].prev_linked_ch);
-			dma_chan[lch].state = DMA_CH_QUEUED;
-		}
-
-		/*
-		 * Chain is already started, make sure its active,
-		 * if not then start the chain
-		 */
-		else {
-			start_dma = 1;
-
-			if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
-							DMA_CH_STARTED) {
-				enable_lnk(dma_chan[lch].prev_linked_ch);
-				dma_chan[lch].state = DMA_CH_QUEUED;
-				start_dma = 0;
-				if (0 == ((1 << 7) & p->dma_read(
-					CCR, dma_chan[lch].prev_linked_ch))) {
-					disable_lnk(dma_chan[lch].
-						    prev_linked_ch);
-					pr_debug("\n prev ch is stopped\n");
-					start_dma = 1;
-				}
-			}
-
-			else if (dma_chan[dma_chan[lch].prev_linked_ch].state
-							== DMA_CH_QUEUED) {
-				enable_lnk(dma_chan[lch].prev_linked_ch);
-				dma_chan[lch].state = DMA_CH_QUEUED;
-				start_dma = 0;
-			}
-			omap_enable_channel_irq(lch);
-
-			l = p->dma_read(CCR, lch);
-
-			if ((0 == (l & (1 << 24))))
-				l &= ~(1 << 25);
-			else
-				l |= (1 << 25);
-			if (start_dma == 1) {
-				if (0 == (l & (1 << 7))) {
-					l |= (1 << 7);
-					dma_chan[lch].state = DMA_CH_STARTED;
-					pr_debug("starting %d\n", lch);
-					p->dma_write(l, CCR, lch);
-				} else
-					start_dma = 0;
-			} else {
-				if (0 == (l & (1 << 7)))
-					p->dma_write(l, CCR, lch);
-			}
-			dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
-		}
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_dma_chain_a_transfer);
-
-/**
- * @brief omap_start_dma_chain_transfers - Start the chain
- *
- * @param chain_id
- *
- * @return - Success : 0
- * 	     Failure : -EINVAL/-EBUSY
- */
-int omap_start_dma_chain_transfers(int chain_id)
-{
-	int *channels;
-	u32 l, i;
-
-	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	channels = dma_linked_lch[chain_id].linked_dmach_q;
-
-	if (dma_linked_lch[channels[0]].chain_state == DMA_CHAIN_STARTED) {
-		printk(KERN_ERR "Chain is already started\n");
-		return -EBUSY;
-	}
-
-	if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_STATIC_CHAIN) {
-		for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked;
-									i++) {
-			enable_lnk(channels[i]);
-			omap_enable_channel_irq(channels[i]);
-		}
-	} else {
-		omap_enable_channel_irq(channels[0]);
-	}
-
-	l = p->dma_read(CCR, channels[0]);
-	l |= (1 << 7);
-	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
-	dma_chan[channels[0]].state = DMA_CH_STARTED;
-
-	if ((0 == (l & (1 << 24))))
-		l &= ~(1 << 25);
-	else
-		l |= (1 << 25);
-	p->dma_write(l, CCR, channels[0]);
-
-	dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_start_dma_chain_transfers);
-
-/**
- * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain.
- *
- * @param chain_id
- *
- * @return - Success : 0
- * 	     Failure : EINVAL
- */
-int omap_stop_dma_chain_transfers(int chain_id)
-{
-	int *channels;
-	u32 l, i;
-	u32 sys_cf = 0;
-
-	/* Check for input params */
-	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	/* Check if the chain exists */
-	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
-		printk(KERN_ERR "Chain doesn't exists\n");
-		return -EINVAL;
-	}
-	channels = dma_linked_lch[chain_id].linked_dmach_q;
-
-	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
-		sys_cf = p->dma_read(OCP_SYSCONFIG, 0);
-		l = sys_cf;
-		/* Middle mode reg set no Standby */
-		l &= ~((1 << 12)|(1 << 13));
-		p->dma_write(l, OCP_SYSCONFIG, 0);
-	}
-
-	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
-
-		/* Stop the Channel transmission */
-		l = p->dma_read(CCR, channels[i]);
-		l &= ~(1 << 7);
-		p->dma_write(l, CCR, channels[i]);
-
-		/* Disable the link in all the channels */
-		disable_lnk(channels[i]);
-		dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
-
-	}
-	dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
-
-	/* Reset the Queue pointers */
-	OMAP_DMA_CHAIN_QINIT(chain_id);
-
-	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
-		p->dma_write(sys_cf, OCP_SYSCONFIG, 0);
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_stop_dma_chain_transfers);
-
-/* Get the index of the ongoing DMA in chain */
-/**
- * @brief omap_get_dma_chain_index - Get the element and frame index
- * of the ongoing DMA in chain
- *
- * @param chain_id
- * @param ei - Element index
- * @param fi - Frame index
- *
- * @return - Success : 0
- * 	     Failure : -EINVAL
- */
-int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
-{
-	int lch;
-	int *channels;
-
-	/* Check for input params */
-	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	/* Check if the chain exists */
-	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
-		printk(KERN_ERR "Chain doesn't exists\n");
-		return -EINVAL;
-	}
-	if ((!ei) || (!fi))
-		return -EINVAL;
-
-	channels = dma_linked_lch[chain_id].linked_dmach_q;
-
-	/* Get the current channel */
-	lch = channels[dma_linked_lch[chain_id].q_head];
-
-	*ei = p->dma_read(CCEN, lch);
-	*fi = p->dma_read(CCFN, lch);
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_get_dma_chain_index);
-
-/**
- * @brief omap_get_dma_chain_dst_pos - Get the destination position of the
- * ongoing DMA in chain
- *
- * @param chain_id
- *
- * @return - Success : Destination position
- * 	     Failure : -EINVAL
- */
-int omap_get_dma_chain_dst_pos(int chain_id)
-{
-	int lch;
-	int *channels;
-
-	/* Check for input params */
-	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	/* Check if the chain exists */
-	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
-		printk(KERN_ERR "Chain doesn't exists\n");
-		return -EINVAL;
-	}
-
-	channels = dma_linked_lch[chain_id].linked_dmach_q;
-
-	/* Get the current channel */
-	lch = channels[dma_linked_lch[chain_id].q_head];
-
-	return p->dma_read(CDAC, lch);
-}
-EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
-
-/**
- * @brief omap_get_dma_chain_src_pos - Get the source position
- * of the ongoing DMA in chain
- * @param chain_id
- *
- * @return - Success : Destination position
- * 	     Failure : -EINVAL
- */
-int omap_get_dma_chain_src_pos(int chain_id)
-{
-	int lch;
-	int *channels;
-
-	/* Check for input params */
-	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
-		printk(KERN_ERR "Invalid chain id\n");
-		return -EINVAL;
-	}
-
-	/* Check if the chain exists */
-	if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
-		printk(KERN_ERR "Chain doesn't exists\n");
-		return -EINVAL;
-	}
-
-	channels = dma_linked_lch[chain_id].linked_dmach_q;
-
-	/* Get the current channel */
-	lch = channels[dma_linked_lch[chain_id].q_head];
-
-	return p->dma_read(CSAC, lch);
-}
-EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
-#endif	/* ifndef CONFIG_ARCH_OMAP1 */
-
-/*----------------------------------------------------------------------------*/
-
-#ifdef CONFIG_ARCH_OMAP1
-
-static int omap1_dma_handle_ch(int ch)
-{
-	u32 csr;
-
-	if (enable_1510_mode && ch >= 6) {
-		csr = dma_chan[ch].saved_csr;
-		dma_chan[ch].saved_csr = 0;
-	} else
-		csr = p->dma_read(CSR, ch);
-	if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
-		dma_chan[ch + 6].saved_csr = csr >> 7;
-		csr &= 0x7f;
-	}
-	if ((csr & 0x3f) == 0)
-		return 0;
-	if (unlikely(dma_chan[ch].dev_id == -1)) {
-		printk(KERN_WARNING "Spurious interrupt from DMA channel "
-		       "%d (CSR %04x)\n", ch, csr);
-		return 0;
-	}
-	if (unlikely(csr & OMAP1_DMA_TOUT_IRQ))
-		printk(KERN_WARNING "DMA timeout with device %d\n",
-		       dma_chan[ch].dev_id);
-	if (unlikely(csr & OMAP_DMA_DROP_IRQ))
-		printk(KERN_WARNING "DMA synchronization event drop occurred "
-		       "with device %d\n", dma_chan[ch].dev_id);
-	if (likely(csr & OMAP_DMA_BLOCK_IRQ))
-		dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
-	if (likely(dma_chan[ch].callback != NULL))
-		dma_chan[ch].callback(ch, csr, dma_chan[ch].data);
-
-	return 1;
-}
-
-static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
-{
-	int ch = ((int) dev_id) - 1;
-	int handled = 0;
-
-	for (;;) {
-		int handled_now = 0;
-
-		handled_now += omap1_dma_handle_ch(ch);
-		if (enable_1510_mode && dma_chan[ch + 6].saved_csr)
-			handled_now += omap1_dma_handle_ch(ch + 6);
-		if (!handled_now)
-			break;
-		handled += handled_now;
-	}
-
-	return handled ? IRQ_HANDLED : IRQ_NONE;
-}
-
-#else
-#define omap1_dma_irq_handler	NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-
-static int omap2_dma_handle_ch(int ch)
-{
-	u32 status = p->dma_read(CSR, ch);
-
-	if (!status) {
-		if (printk_ratelimit())
-			printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
-				ch);
-		p->dma_write(1 << ch, IRQSTATUS_L0, ch);
-		return 0;
-	}
-	if (unlikely(dma_chan[ch].dev_id == -1)) {
-		if (printk_ratelimit())
-			printk(KERN_WARNING "IRQ %04x for non-allocated DMA"
-					"channel %d\n", status, ch);
-		return 0;
-	}
-	if (unlikely(status & OMAP_DMA_DROP_IRQ))
-		printk(KERN_INFO
-		       "DMA synchronization event drop occurred with device "
-		       "%d\n", dma_chan[ch].dev_id);
-	if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
-		printk(KERN_INFO "DMA transaction error with device %d\n",
-		       dma_chan[ch].dev_id);
-		if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
-			u32 ccr;
-
-			ccr = p->dma_read(CCR, ch);
-			ccr &= ~OMAP_DMA_CCR_EN;
-			p->dma_write(ccr, CCR, ch);
-			dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
-		}
-	}
-	if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ))
-		printk(KERN_INFO "DMA secure error with device %d\n",
-		       dma_chan[ch].dev_id);
-	if (unlikely(status & OMAP2_DMA_MISALIGNED_ERR_IRQ))
-		printk(KERN_INFO "DMA misaligned error with device %d\n",
-		       dma_chan[ch].dev_id);
-
-	p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
-	p->dma_write(1 << ch, IRQSTATUS_L0, ch);
-	/* read back the register to flush the write */
-	p->dma_read(IRQSTATUS_L0, ch);
-
-	/* If the ch is not chained then chain_id will be -1 */
-	if (dma_chan[ch].chain_id != -1) {
-		int chain_id = dma_chan[ch].chain_id;
-		dma_chan[ch].state = DMA_CH_NOTSTARTED;
-		if (p->dma_read(CLNK_CTRL, ch) & (1 << 15))
-			dma_chan[dma_chan[ch].next_linked_ch].state =
-							DMA_CH_STARTED;
-		if (dma_linked_lch[chain_id].chain_mode ==
-						OMAP_DMA_DYNAMIC_CHAIN)
-			disable_lnk(ch);
-
-		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
-			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
-
-		status = p->dma_read(CSR, ch);
-	}
-
-	p->dma_write(status, CSR, ch);
-
-	if (likely(dma_chan[ch].callback != NULL))
-		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
-
-	return 0;
-}
-
-/* STATUS register count is from 1-32 while our is 0-31 */
-static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
-{
-	u32 val, enable_reg;
-	int i;
-
-	val = p->dma_read(IRQSTATUS_L0, 0);
-	if (val == 0) {
-		if (printk_ratelimit())
-			printk(KERN_WARNING "Spurious DMA IRQ\n");
-		return IRQ_HANDLED;
-	}
-	enable_reg = p->dma_read(IRQENABLE_L0, 0);
-	val &= enable_reg; /* Dispatch only relevant interrupts */
-	for (i = 0; i < dma_lch_count && val != 0; i++) {
-		if (val & 1)
-			omap2_dma_handle_ch(i);
-		val >>= 1;
-	}
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction omap24xx_dma_irq = {
-	.name = "DMA",
-	.handler = omap2_dma_irq_handler,
-	.flags = IRQF_DISABLED
-};
-
-#else
-static struct irqaction omap24xx_dma_irq;
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-void omap_dma_global_context_save(void)
-{
-	omap_dma_global_context.dma_irqenable_l0 =
-		p->dma_read(IRQENABLE_L0, 0);
-	omap_dma_global_context.dma_ocp_sysconfig =
-		p->dma_read(OCP_SYSCONFIG, 0);
-	omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0);
-}
-
-void omap_dma_global_context_restore(void)
-{
-	int ch;
-
-	p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
-	p->dma_write(omap_dma_global_context.dma_ocp_sysconfig,
-		OCP_SYSCONFIG, 0);
-	p->dma_write(omap_dma_global_context.dma_irqenable_l0,
-		IRQENABLE_L0, 0);
-
-	if (IS_DMA_ERRATA(DMA_ROMCODE_BUG))
-		p->dma_write(0x3 , IRQSTATUS_L0, 0);
-
-	for (ch = 0; ch < dma_chan_count; ch++)
-		if (dma_chan[ch].dev_id != -1)
-			omap_clear_dma(ch);
-}
-
 static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 {
-	int ch, ret = 0;
-	int dma_irq;
-	char irq_name[4];
+	int ch;
 
 	p = pdev->dev.platform_data;
 	if (!p) {
@@ -1990,73 +739,26 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	dma_chan		= d->chan;
 	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;
 
-	if (cpu_class_is_omap2()) {
-		dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
-						dma_lch_count, GFP_KERNEL);
-		if (!dma_linked_lch) {
-			ret = -ENOMEM;
-			goto exit_dma_chan;
-		}
-	}
-
 	spin_lock_init(&dma_chan_lock);
 	for (ch = 0; ch < dma_chan_count; ch++) {
+		unsigned long flags;
 		omap_clear_dma(ch);
-		if (cpu_class_is_omap2())
-			omap2_disable_irq_lch(ch);
+		if (p->disable_irq_lch) {
+			spin_lock_irqsave(&dma_chan_lock, flags);
+			p->disable_irq_lch(ch);
+			spin_unlock_irqrestore(&dma_chan_lock, flags);
+		}
 
 		dma_chan[ch].dev_id = -1;
 		dma_chan[ch].next_lch = -1;
-
-		if (ch >= 6 && enable_1510_mode)
-			continue;
-
-		if (cpu_class_is_omap1()) {
-			/*
-			 * request_irq() doesn't like dev_id (ie. ch) being
-			 * zero, so we have to kludge around this.
-			 */
-			sprintf(&irq_name[0], "%d", ch);
-			dma_irq = platform_get_irq_byname(pdev, irq_name);
-
-			if (dma_irq < 0) {
-				dev_err(&pdev->dev, "%s:unable to get irq\n",
-								__func__);
-				ret = dma_irq;
-				goto exit_dma_chan;
-			}
-			ret = request_irq(dma_irq,
-					omap1_dma_irq_handler, 0, "DMA",
-					(void *) (ch + 1));
-			if (ret != 0) {
-				int irq_rel;
-				dev_err(&pdev->dev, "unable to request IRQ %d"
-					"for DMA (error %d)\n", dma_irq, ret);
-				for (irq_rel = 0; irq_rel < ch;
-								irq_rel++) {
-					dma_irq = platform_get_irq(pdev,
-								irq_rel);
-					free_irq(dma_irq, (void *)
-							(irq_rel + 1));
-					goto exit_dma_chan;
-				}
-			}
-		}
 	}
 
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx())
-		omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
+	if ((d->dev_caps & GLOBAL_PRIORITY) && (p->set_global_params))
+		p->set_global_params(DMA_DEFAULT_ARB_RATE,
 				DMA_DEFAULT_FIFO_DEPTH, 0);
 
-	if (cpu_class_is_omap2()) {
-		strcpy(irq_name, "0");
-		dma_irq = platform_get_irq_byname(pdev, irq_name);
-		setup_irq(dma_irq, &omap24xx_dma_irq);
-	}
-
 	/* reserve dma channels 0 and 1 in high security devices */
-	if (cpu_is_omap34xx() &&
-		(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
+	if (d->dev_caps & RESERVE_CHANNEL) {
 		printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
 				"HS ROM code\n");
 		dma_chan[0].dev_id = 0;
@@ -2064,11 +766,6 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	}
 	p->show_dma_caps();
 	return 0;
-
-exit_dma_chan:
-	kfree(dma_chan);
-	kfree(p);
-	return ret;
 }
 
 static int __devexit omap_system_dma_remove(struct platform_device *pdev)
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index d1c916f..cea7e12 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -268,17 +268,12 @@
 #define DMA_IDLEMODE_NO_IDLE			0x1
 #define DMA_IDLEMODE_FORCE_IDLE			0x0
 
-/* Chaining modes*/
-#ifndef CONFIG_ARCH_OMAP1
-#define OMAP_DMA_STATIC_CHAIN		0x1
-#define OMAP_DMA_DYNAMIC_CHAIN		0x2
-#define OMAP_DMA_CHAIN_ACTIVE		0x1
-#define OMAP_DMA_CHAIN_INACTIVE		0x0
-#endif
-
 #define DMA_CH_PRIO_HIGH		0x1
 #define DMA_CH_PRIO_LOW			0x0 /* Def */
 
+#define OMAP_DMA_ACTIVE			0x01
+#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
+
 /* Errata handling */
 #define IS_DMA_ERRATA(id)		(errata & (id))
 #define SET_DMA_ERRATA(id)		(errata |= (id))
@@ -401,6 +396,10 @@ struct omap_dma_channel_params {
 #endif
 };
 
+#ifdef CONFIG_ARCH_OMAP2PLUS
+#include <mach/dma.h>
+#endif
+
 struct omap_dma_lch {
 	int next_lch;
 	int dev_id;
@@ -432,6 +431,30 @@ struct omap_system_dma_plat_info {
 	void (*disable_irq_lch)(int lch);
 	void (*show_dma_caps)(void);
 	void (*clear_lch_regs)(int lch);
+	void (*cpc_cdac_init)(int lch);
+	int (*get_gdma_dev)(int req);
+	void (*set_gdma_dev)(int req, int dev);
+	void (*set_transfer_params)(int lch, int data_type, int sync_mode,
+				int dma_trigger, int src_or_dst_synch);
+	void (*set_color_mode)(int lch, enum omap_dma_color_mode mode,
+								u32 color);
+	void (*set_src_params)(int lch, unsigned long src_start, int src_ei,
+								int src_fi);
+	void (*set_dest_params)(int lch, unsigned long dest_start, int dst_ei,
+								int dst_fi);
+	dma_addr_t (*get_src_pos)(int lch);
+	dma_addr_t (*get_dst_pos)(int lch);
+
+	void (*enable_irq_lch)(int lch);
+	void (*enable_channel_irq)(int lch);
+	void (*disable_channel_irq)(int lch);
+	void (*enable_lnk)(int lch);
+	void (*disable_lnk)(int lch);
+
+	void (*clear_channel_int)(int lch);
+
+	void (*set_global_params)(int arb_rate,
+			int max_fifo_depth, int tparams);
 	void (*clear_dma)(int lch);
 	void (*dma_write)(u32 val, int reg, int lch);
 	u32 (*dma_read)(int reg, int lch);
@@ -498,29 +521,6 @@ void omap_dma_global_context_restore(void);
 
 extern void omap_dma_disable_irq(int lch);
 
-/* Chaining APIs */
-#ifndef CONFIG_ARCH_OMAP1
-extern int omap_request_dma_chain(int dev_id, const char *dev_name,
-				  void (*callback) (int lch, u16 ch_status,
-						    void *data),
-				  int *chain_id, int no_of_chans,
-				  int chain_mode,
-				  struct omap_dma_channel_params params);
-extern int omap_free_dma_chain(int chain_id);
-extern int omap_dma_chain_a_transfer(int chain_id, int src_start,
-				     int dest_start, int elem_count,
-				     int frame_count, void *callbk_data);
-extern int omap_start_dma_chain_transfers(int chain_id);
-extern int omap_stop_dma_chain_transfers(int chain_id);
-extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
-extern int omap_get_dma_chain_dst_pos(int chain_id);
-extern int omap_get_dma_chain_src_pos(int chain_id);
-
-extern int omap_modify_dma_chain_params(int chain_id,
-					struct omap_dma_channel_params params);
-extern int omap_dma_chain_status(int chain_id);
-#endif
-
 #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
 #include <mach/lcd_dma.h>
 #else
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 11/14] OMAP2+: DMA: descriptor autoloading feature
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (9 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 12/14] OMAP3630: DMA: Add work around for erratum i557 G, Manjunath Kondaiah
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: Venkatraman S, G, Manjunath Kondaiah, linux-arm-kernel,
	Kevin Hilman, Tony Lindgren, Santosh Shilimkar, Benoit Cousson

From: Venkatraman S <svenkatr@ti.com>

Add sDMA driver support for descriptor autoloading feature.
Descriptor autoloading is OMAP sDMA v5 hardware capability that can be
exploited for scatter gather scenarios, currently available in OMAP3630
and OMAP4430.

The feature works as described below.
1. A sDMA channel is programmed to be in 'linked list' mode.
2) The client (sDMA user) provides a list of descriptors in a linked
list format
3) Each of the 'descriptor' (element in the linked list) contains an
updated set of DMA configuration register values.
4) Client starts DMA transfer.
5) sDMA controller loads the first element to its register configuration
memory and executes the transfer.
6) After completion, loads the next element (in linked list) to
configuration memory and executes the transfer, without MCU
intervention.
7) Interrupt is generated after all transfers are completed; this can be
configured to be done differently.

Configurations and additional features
1) Fast mode & non-fast mode
Fast mode/non-fast decides on how the first transfer begins. In non-fast
mode, the first element in the linked list is loaded only after
completing the
transfer according to the configurations already in the sDMA channel
registers.
In fast mode, the loading of the first element precedes the transfer.

2) Pause / resume of transfers
A transfer can be paused after a descriptor set has been loaded,
provided the pause bit' is set in the linked list element.
An ongoing transfer cannot be paused. If the 'pause bit' is set,
transfer is not started after loading the register set from memory.
Such a transfer can be resumed later.

3) Descriptor types
Three possible configurations of descriptors (initialized as linked list
elements) are possible.
Type 1 provides the maximum flexibility, which contains most register
definitions of a DMA logical channel.
Fewer options are present in type 2.
Type 3 can just modify source/destinations address of transfers. In all
transfers, unmodified registers settings are maintained for the next
transfer.

Patch provides options / API for
1) Setting up a descriptor loading for DMA channel for sg type transfers
2) configuration with linked list elements
3) Starting / pause and resume of the said transfers, query state
4) Clearing the sglist mode

Signed-off-by: Venkatraman S <svenkatr@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap2/dma.c              |  249 ++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/include/mach/dma.h |   87 +++++++++++
 arch/arm/plat-omap/dma.c               |    2 +-
 arch/arm/plat-omap/include/plat/dma.h  |  108 ++++++++++++++
 4 files changed, 445 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 2ce1969..290b40c 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -39,6 +39,7 @@
 static u32 errata;
 static u8 dma_stride;
 static int dma_chan_count;
+static int dma_caps0_status;
 
 static struct omap_dma_dev_attr *d;
 static struct dma_link_info *dma_linked_lch;
@@ -253,6 +254,76 @@ static inline void omap2_disable_lnk(int lch)
 	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
+static inline void omap_dma_list_set_ntype(struct omap_dma_sglist_node *node,
+					   int value)
+{
+	node->num_of_elem |= ((value) << 29);
+}
+
+static void omap_set_dma_sglist_pausebit(
+		struct omap_dma_list_config_params *lcfg, int nelem, int set)
+{
+	struct omap_dma_sglist_node *sgn = lcfg->sghead;
+
+	if (nelem > 0 && nelem < lcfg->num_elem) {
+		lcfg->pausenode = nelem;
+		sgn += nelem;
+
+		if (set)
+			sgn->next_desc_add_ptr |= DMA_LIST_DESC_PAUSE;
+		else
+			sgn->next_desc_add_ptr &= ~(DMA_LIST_DESC_PAUSE);
+	}
+}
+
+static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
+		dma_addr_t phyaddr, int nelem)
+{
+	struct omap_dma_sglist_node *sgcurr, *sgprev;
+	dma_addr_t elem_paddr = phyaddr;
+
+	for (sgprev = sghead;
+		sgprev < sghead + nelem;
+		sgprev++) {
+
+		sgcurr = sgprev + 1;
+		sgprev->next = sgcurr;
+		elem_paddr += (int)sizeof(*sgcurr);
+		sgprev->next_desc_add_ptr = elem_paddr;
+
+		switch (sgcurr->desc_type) {
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
+			omap_dma_list_set_ntype(sgprev, 1);
+			break;
+
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
+		/* intentional no break */
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
+			omap_dma_list_set_ntype(sgprev, 2);
+			break;
+
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
+			/* intentional no break */
+		case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
+			omap_dma_list_set_ntype(sgprev, 3);
+			break;
+
+		default:
+			return -EINVAL;
+
+		}
+		if (sgcurr->flags & OMAP_DMA_LIST_SRC_VALID)
+			sgprev->num_of_elem |= DMA_LIST_DESC_SRC_VALID;
+		if (sgcurr->flags & OMAP_DMA_LIST_DST_VALID)
+			sgprev->num_of_elem |= DMA_LIST_DESC_DST_VALID;
+		if (sgcurr->flags & OMAP_DMA_LIST_NOTIFY_BLOCK_END)
+			sgprev->num_of_elem |= DMA_LIST_DESC_BLK_END;
+	}
+	sgprev--;
+	sgprev->next_desc_add_ptr = OMAP_DMA_INVALID_DESCRIPTOR_POINTER;
+	return 0;
+}
+
 static void
 omap2_set_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 {
@@ -1232,6 +1303,182 @@ int omap_get_dma_chain_src_pos(int chain_id)
 }
 EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
 
+int omap_set_dma_sglist_mode(int lch, struct omap_dma_sglist_node *sgparams,
+	dma_addr_t padd, int nelem, struct omap_dma_channel_params *ch_params)
+{
+	struct omap_dma_list_config_params *lcfg;
+	int l = DMA_LIST_CDP_LISTMODE; /* Enable Linked list mode in CDP */
+
+	if ((dma_caps0_status & DMA_CAPS_SGLIST_SUPPORT) == 0) {
+		printk(KERN_ERR "omap DMA: sglist feature not supported\n");
+		return -EPERM;
+	}
+	if (dma_chan[lch].flags & OMAP_DMA_ACTIVE) {
+		printk(KERN_ERR "omap DMA: configuring active DMA channel\n");
+		return -EPERM;
+	}
+
+	if (padd == 0) {
+		printk(KERN_ERR "omap DMA: sglist invalid dma_addr\n");
+		return -EINVAL;
+	}
+	lcfg = &dma_chan[lch].list_config;
+
+	lcfg->sghead = sgparams;
+	lcfg->num_elem = nelem;
+	lcfg->sgheadphy = padd;
+	lcfg->pausenode = -1;
+
+	if (NULL == ch_params)
+		l |= DMA_LIST_CDP_FASTMODE;
+	else
+		omap_set_dma_params(lch, ch_params);
+
+	dma_write(l, CDP, lch);
+	dma_write(0, CCDN, lch); /* Reset List index numbering */
+	/* Initialize frame and element counters to invalid values */
+	dma_write(OMAP_DMA_INVALID_FRAME_COUNT, CCFN, lch);
+	dma_write(OMAP_DMA_INVALID_ELEM_COUNT, CCEN, lch);
+
+	return dma_sglist_set_phy_params(sgparams, lcfg->sgheadphy, nelem);
+
+}
+EXPORT_SYMBOL(omap_set_dma_sglist_mode);
+
+void omap2_clear_dma_sglist_mode(int lch)
+{
+	/* Clear entire CDP which is related to sglist handling */
+	dma_write(0, CDP, lch);
+	dma_write(0, CCDN, lch);
+	/*
+	 * Put back the original enabled irqs, which
+	 * could have been overwritten by type 1 or type 2
+	 * descriptors
+	 */
+	dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
+	return;
+}
+EXPORT_SYMBOL(omap2_clear_dma_sglist_mode);
+
+int omap_start_dma_sglist_transfers(int lch, int pauseafter)
+{
+	struct omap_dma_list_config_params *lcfg;
+	struct omap_dma_sglist_node *sgn;
+	unsigned int l, type_id;
+
+	lcfg = &dma_chan[lch].list_config;
+	sgn = lcfg->sghead;
+
+	lcfg->pausenode = 0;
+	omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
+
+	/* Program the head descriptor's properties into CDP */
+	switch (lcfg->sghead->desc_type) {
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
+		type_id = DMA_LIST_CDP_TYPE1;
+		break;
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
+		type_id = DMA_LIST_CDP_TYPE2;
+		break;
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
+	case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
+		type_id = DMA_LIST_CDP_TYPE3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	l = dma_read(CDP, lch);
+	l |= type_id;
+	if (lcfg->sghead->flags & OMAP_DMA_LIST_SRC_VALID)
+		l |= DMA_LIST_CDP_SRC_VALID;
+	if (lcfg->sghead->flags & OMAP_DMA_LIST_DST_VALID)
+		l |= DMA_LIST_CDP_DST_VALID;
+
+	dma_write(l, CDP, lch);
+	dma_write((lcfg->sgheadphy), CNDP, lch);
+
+	/*
+	 * Memory barrier is needed because data may still be
+	 * in the write buffer. The barrier drains write buffers and
+	 * ensures that DMA sees correct descriptors
+	 */
+	wmb();
+	omap_start_dma(lch);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_start_dma_sglist_transfers);
+
+int omap_resume_dma_sglist_transfers(int lch, int pauseafter)
+{
+	struct omap_dma_list_config_params *lcfg;
+	struct omap_dma_sglist_node *sgn;
+	int l;
+
+	lcfg = &dma_chan[lch].list_config;
+	sgn = lcfg->sghead;
+
+	/* Maintain the pause state in descriptor */
+	omap_set_dma_sglist_pausebit(lcfg, lcfg->pausenode, 0);
+	omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1);
+
+	/*
+	 * Memory barrier is needed because data may still be
+	 * in the write buffer. The barrier drains write buffers and
+	 * ensures that DMA sees correct descriptors
+	 */
+	wmb();
+
+	/* Clear pause bit in CDP */
+	l = dma_read(CDP, lch);
+	l &= ~(DMA_LIST_CDP_PAUSEMODE);
+	dma_write(l, CDP, lch);
+
+	omap_start_dma(lch);
+	return 0;
+}
+EXPORT_SYMBOL(omap_resume_dma_sglist_transfers);
+
+void omap_release_dma_sglist(int lch)
+{
+	omap2_clear_dma_sglist_mode(lch);
+	omap_free_dma(lch);
+
+	return;
+}
+EXPORT_SYMBOL(omap_release_dma_sglist);
+
+int omap_get_completed_sglist_nodes(int lch)
+{
+	int list_count;
+
+	list_count = dma_read(CCDN, lch);
+	return list_count & 0xffff; /* only 16 LSB bits are valid */
+}
+EXPORT_SYMBOL(omap_get_completed_sglist_nodes);
+
+int omap_dma_sglist_is_paused(int lch)
+{
+	int list_state;
+	list_state = dma_read(CDP, lch);
+	return (list_state & DMA_LIST_CDP_PAUSEMODE) ? 1 : 0;
+}
+EXPORT_SYMBOL(omap_dma_sglist_is_paused);
+
+void omap_dma_set_sglist_fastmode(int lch, int fastmode)
+{
+	int l = dma_read(CDP, lch);
+
+	if (fastmode)
+		l |= DMA_LIST_CDP_FASTMODE;
+	else
+		l &= ~(DMA_LIST_CDP_FASTMODE);
+	dma_write(l, CDP, lch);
+}
+EXPORT_SYMBOL(omap_dma_set_sglist_fastmode);
+
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
@@ -1274,6 +1521,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 	p->clear_dma		= omap2_clear_dma;
 	p->dma_write		= dma_write;
 	p->dma_read		= dma_read;
+	p->clear_sglist_mode	= omap2_clear_dma_sglist_mode;
 
 	p->clear_lch_regs	= NULL;
 	p->get_gdma_dev		= NULL;
@@ -1332,6 +1580,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 		return -ENOMEM;
 	}
 	dma_chan = d->chan;
+	dma_caps0_status = dma_read(CAPS_0, 0);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/include/mach/dma.h b/arch/arm/mach-omap2/include/mach/dma.h
index c6f1a20..d26b647 100644
--- a/arch/arm/mach-omap2/include/mach/dma.h
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -53,4 +53,91 @@ extern int omap_modify_dma_chain_params(int chain_id,
 					struct omap_dma_channel_params params);
 extern int omap_dma_chain_status(int chain_id);
 
+/**
+ * omap_set_dma_sglist_mode()	Switch channel to scatter gather mode
+ * @lch:	Logical channel to switch to sglist mode
+ * @sghead:	Contains the descriptor elements to be executed
+ *		Should be allocated using dma_alloc_coherent
+ * @padd:	The dma address of sghead, as returned by dma_alloc_coherent
+ * @nelem:	Number of elements in sghead
+ * @chparams:	DMA channel transfer parameters. Can be NULL
+ */
+extern int omap_set_dma_sglist_mode(int lch,
+	struct omap_dma_sglist_node *sghead, dma_addr_t padd,
+	int nelem, struct omap_dma_channel_params *chparams);
+
+/**
+ * omap_clear_dma_sglist_mode()	Switch from scatter gather mode
+ *				to normal mode
+ * @lch:	The logical channel to be switched to normal mode
+ *
+ * Switches the requested logical channel to normal mode
+ * from scatter gather mode
+ */
+extern void omap_clear_dma_sglist_mode(int lch);
+
+/**
+ * omap_start_dma_sglist_transfers()	Starts the sglist transfer
+ * @lch:	logical channel on which sglist transfer to be started
+ * @pauseafter:	index of the element on which to pause the transfer
+ *		set to -1 if no pause is needed till end of transfer
+ *
+ * Start the dma transfer in list mode
+ * The index (in pauseafter) is absolute (from the head of the list)
+ * User should have previously called omap_set_dma_sglist_mode()
+ */
+extern int omap_start_dma_sglist_transfers(int lch, int pauseafter);
+
+/**
+ * omap_resume_dma_sglist_transfers()	Resumes a previously paused
+ *					sglist transfer
+ * @lch:	The logical channel to be resumed
+ * @pauseafter:	The index of sglist to be paused again
+ *		set to -1 if no pause is needed till end of transfer
+ *
+ * Resume the previously paused transfer
+ * The index (in pauseafter) is absolute (from the head of the list)
+ */
+extern int omap_resume_dma_sglist_transfers(int lch, int pauseafter);
+
+/**
+ * omap_release_dma_sglist()	Releases a previously requested
+ *				DMA channel which is in sglist mode
+ * @lch:	The logical channel to be released
+ */
+extern void omap_release_dma_sglist(int lch);
+
+/**
+ * omap_get_completed_sglist_nodes()	Returns a list of completed
+ *					sglist nodes
+ * @lch:	The logical on which the query is to be made
+ *
+ * Returns the number of completed elements in the linked list
+ * The value is transient if the API is invoked for an ongoing transfer
+ */
+int omap_get_completed_sglist_nodes(int lch);
+
+/**
+ * omap_dma_sglist_is_paused()	Query is the logical channel in
+ *				sglist mode is paused or note
+ * @lch:	The logical on which the query is to be made
+ *
+ * Returns non zero if the linked list is currently in pause state
+ */
+int omap_dma_sglist_is_paused(int lch);
+
+/**
+ * omap_dma_set_sglist_fastmode() Set the sglist transfer to fastmode
+ * @lch:	The logical channel which is to be changed to fastmode
+ * @fastmode:	Set or clear the fastmode status
+ *		1 = set fastmode
+ *		0 = clear fastmode
+ *
+ * In fastmode, DMA register settings are updated from the first element
+ * of the linked list, before initiating the tranfer.
+ * In non-fastmode, the first element is used only after completing the
+ * transfer as already configured in the registers
+ */
+void omap_dma_set_sglist_fastmode(int lch, int fastmode);
+
 #endif /* __ASM_ARCH_OMAP2_DMA_H */
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index c33c630..8563370 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -400,8 +400,8 @@ void omap_free_dma(int lch)
 		/* Make sure the DMA transfer is stopped. */
 		p->dma_write(0, CCR, lch);
 		omap_clear_dma(lch);
+		p->clear_sglist_mode(lch);
 	}
-
 	spin_lock_irqsave(&dma_chan_lock, flags);
 	dma_chan[lch].dev_id = -1;
 	dma_chan[lch].next_lch = -1;
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index cea7e12..fd378f6 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -396,6 +396,112 @@ struct omap_dma_channel_params {
 #endif
 };
 
+/* CDP Register bitmaps */
+#define DMA_LIST_CDP_DST_VALID			BIT(0)
+#define DMA_LIST_CDP_SRC_VALID			BIT(2)
+#define DMA_LIST_CDP_TYPE1			BIT(4)
+#define DMA_LIST_CDP_TYPE2			BIT(5)
+#define DMA_LIST_CDP_TYPE3			(BIT(4) | BIT(5))
+#define DMA_LIST_CDP_PAUSEMODE			BIT(7)
+#define DMA_LIST_CDP_LISTMODE			BIT(8)
+#define DMA_LIST_CDP_FASTMODE			BIT(10)
+/* CAPS register bitmaps */
+#define DMA_CAPS_SGLIST_SUPPORT			BIT(20)
+
+#define DMA_LIST_DESC_PAUSE			BIT(0)
+#define DMA_LIST_DESC_SRC_VALID			BIT(24)
+#define DMA_LIST_DESC_DST_VALID			BIT(26)
+#define DMA_LIST_DESC_BLK_END			BIT(28)
+
+#define OMAP_DMA_INVALID_FRAME_COUNT		0xffff
+#define OMAP_DMA_INVALID_ELEM_COUNT		0xffffff
+#define OMAP_DMA_INVALID_DESCRIPTOR_POINTER	0xfffffffc
+
+struct omap_dma_list_config_params {
+	unsigned int num_elem;
+	struct omap_dma_sglist_node *sghead;
+	dma_addr_t sgheadphy;
+	unsigned int pausenode;
+};
+
+struct omap_dma_sglist_type1_params {
+	u32 src_addr;
+	u32 dst_addr;
+	u16 cfn_fn;
+	u16 cicr;
+	u16 dst_elem_idx;
+	u16 src_elem_idx;
+	u32 dst_frame_idx_or_pkt_size;
+	u32 src_frame_idx_or_pkt_size;
+	u32 color;
+	u32 csdp;
+	u32 clnk_ctrl;
+	u32 ccr;
+};
+
+struct omap_dma_sglist_type2a_params {
+	u32 src_addr;
+	u32 dst_addr;
+	u16 cfn_fn;
+	u16 cicr;
+	u16 dst_elem_idx;
+	u16 src_elem_idx;
+	u32 dst_frame_idx_or_pkt_size;
+	u32 src_frame_idx_or_pkt_size;
+};
+
+struct omap_dma_sglist_type2b_params {
+	u32 src_or_dest_addr;
+	u16 cfn_fn;
+	u16 cicr;
+	u16 dst_elem_idx;
+	u16 src_elem_idx;
+	u32 dst_frame_idx_or_pkt_size;
+	u32 src_frame_idx_or_pkt_size;
+};
+
+struct omap_dma_sglist_type3a_params {
+	u32 src_addr;
+	u32 dst_addr;
+};
+
+struct omap_dma_sglist_type3b_params {
+	u32 src_or_dest_addr;
+};
+
+enum omap_dma_sglist_descriptor_select {
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1,
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a,
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b,
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a,
+	OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b,
+};
+
+union omap_dma_sglist_node_type {
+	struct omap_dma_sglist_type1_params t1;
+	struct omap_dma_sglist_type2a_params t2a;
+	struct omap_dma_sglist_type2b_params t2b;
+	struct omap_dma_sglist_type3a_params t3a;
+	struct omap_dma_sglist_type3b_params t3b;
+};
+
+struct omap_dma_sglist_node {
+
+	/* Common elements for all descriptors */
+	dma_addr_t next_desc_add_ptr;
+	u32 num_of_elem;
+	/* Type specific elements */
+	union omap_dma_sglist_node_type sg_node;
+	/* Control fields */
+	unsigned short flags;
+	/* Fields that can be set in flags variable */
+	#define OMAP_DMA_LIST_SRC_VALID		BIT(0)
+	#define OMAP_DMA_LIST_DST_VALID		BIT(1)
+	#define OMAP_DMA_LIST_NOTIFY_BLOCK_END	BIT(2)
+	enum omap_dma_sglist_descriptor_select desc_type;
+	struct omap_dma_sglist_node *next;
+};
+
 #ifdef CONFIG_ARCH_OMAP2PLUS
 #include <mach/dma.h>
 #endif
@@ -415,6 +521,7 @@ struct omap_dma_lch {
 	int state;
 	int chain_id;
 	int status;
+	struct omap_dma_list_config_params list_config;
 };
 
 struct omap_dma_dev_attr {
@@ -458,6 +565,7 @@ struct omap_system_dma_plat_info {
 	void (*clear_dma)(int lch);
 	void (*dma_write)(u32 val, int reg, int lch);
 	u32 (*dma_read)(int reg, int lch);
+	void (*clear_sglist_mode)(int lch);
 };
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 12/14] OMAP3630: DMA: Add work around for erratum i557
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (10 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 11/14] OMAP2+: DMA: descriptor autoloading feature G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 13/14] OMAP2+: DMA: Replace sysconfig register access with API's G, Manjunath Kondaiah
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

DMA4 channel fails to continue with descriptor load when
pause bit is cleared through config port access while in
mstandby.

Work around: Software should configure DMA in no standby mode
or force standby before clearing the pause bit(CDPi[7]) using
mstandby mode control API's.

Applicable for all versions of OMAP3630 silicons.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap2/dma.c             |   18 ++++++++++++++++++
 arch/arm/plat-omap/include/plat/dma.h |    1 +
 2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 290b40c..86c8d20 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -689,6 +689,17 @@ static u32 configure_dma_errata(void)
 	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
 		SET_DMA_ERRATA(DMA_ROMCODE_BUG);
 
+	/*
+	 * Erratum i557 - DMA4 channel fails to continue with descriptor load
+	 * when pause bit is cleared through config port access while in
+	 * standby.
+	 * Work around: Software should configure DMA in no standby mode or
+	 * Force standby before clearing the pause bit(CDPi[7]).
+	 * Applicable for all versions of OMAP3630 silicons.
+	 */
+	if (cpu_is_omap3630())
+		SET_DMA_ERRATA(DMA_ERRATA_i557);
+
 	return errata;
 }
 
@@ -1431,12 +1442,19 @@ int omap_resume_dma_sglist_transfers(int lch, int pauseafter)
 	 */
 	wmb();
 
+	if (IS_DMA_ERRATA(DMA_ERRATA_i557))
+		omap_device_require_no_mstandby(pd);
+
 	/* Clear pause bit in CDP */
 	l = dma_read(CDP, lch);
 	l &= ~(DMA_LIST_CDP_PAUSEMODE);
 	dma_write(l, CDP, lch);
 
 	omap_start_dma(lch);
+
+	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+		omap_device_release_no_mstandby(pd);
+
 	return 0;
 }
 EXPORT_SYMBOL(omap_resume_dma_sglist_transfers);
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index fd378f6..e18603d 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -285,6 +285,7 @@
 #define DMA_ERRATA_i88			BIT(0x4)
 #define DMA_ERRATA_3_3			BIT(0x5)
 #define DMA_ROMCODE_BUG			BIT(0x6)
+#define DMA_ERRATA_i557			BIT(0x7)
 
 /* Attributes for OMAP DMA Contrller */
 #define DMA_LINKED_LCH			BIT(0x0)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 13/14] OMAP2+: DMA: Replace sysconfig register access with API's
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (11 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 12/14] OMAP3630: DMA: Add work around for erratum i557 G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
  2010-11-24 12:51 ` [PATCH v5 14/14] OMAP: PM: DMA: Enable runtime pm G, Manjunath Kondaiah
       [not found] ` <20101125112811.GA27574@GLPP-machine>
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Few errata in OMAP2+ DMA driver require forcing DMA controller
mstandby mode to 'no standby' mode. Current implementation
directly access sysconfig registers for this operation.

Since there are API's for controlling mstandby mode, cleanup
sysconfig register access and replace the same with API's.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap1/dma.c             |    2 ++
 arch/arm/mach-omap2/dma.c             |   15 ++++++---------
 arch/arm/plat-omap/dma.c              |   13 ++++---------
 arch/arm/plat-omap/include/plat/dma.h |   17 ++---------------
 4 files changed, 14 insertions(+), 33 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 80c3380..57f5415 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -642,6 +642,8 @@ static int __init omap1_system_dma_init(void)
 	p->clear_channel_int	= NULL;
 	p->set_global_params	= NULL;
 	p->disable_irq_lch	= NULL;
+	p->require_no_mstandby	= NULL;
+	p->release_no_mstandby	= NULL;
 
 	p->errata = configure_dma_errata();
 
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 86c8d20..b50ecee 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -1156,7 +1156,6 @@ int omap_stop_dma_chain_transfers(int chain_id)
 {
 	int *channels;
 	u32 l, i;
-	u32 sys_cf = 0;
 
 	/* Check for input params */
 	if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
@@ -1171,13 +1170,9 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	}
 	channels = dma_linked_lch[chain_id].linked_dmach_q;
 
-	if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
-		sys_cf = dma_read(OCP_SYSCONFIG, 0);
-		l = sys_cf;
-		/* Middle mode reg set no Standby */
-		l &= ~((1 << 12)|(1 << 13));
-		dma_write(l, OCP_SYSCONFIG, 0);
-	}
+	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+		omap_device_require_no_mstandby(pd);
+
 	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
 
 		/* Stop the Channel transmission */
@@ -1196,7 +1191,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	OMAP_DMA_CHAIN_QINIT(chain_id);
 
 	if (IS_DMA_ERRATA(DMA_ERRATA_i88))
-		dma_write(sys_cf, OCP_SYSCONFIG, 0);
+		omap_device_release_no_mstandby(pd);
 
 	return 0;
 }
@@ -1540,6 +1535,8 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 	p->dma_write		= dma_write;
 	p->dma_read		= dma_read;
 	p->clear_sglist_mode	= omap2_clear_dma_sglist_mode;
+	p->require_no_mstandby	= omap_device_require_no_mstandby;
+	p->release_no_mstandby	= omap_device_release_no_mstandby;
 
 	p->clear_lch_regs	= NULL;
 	p->get_gdma_dev		= NULL;
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 8563370..a859c70 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -39,6 +39,7 @@
 static struct omap_system_dma_plat_info *p;
 static struct omap_dma_dev_attr *d;
 static struct omap_dma_lch		*dma_chan;
+static struct platform_device		*pd;
 
 static int enable_1510_mode;
 static int dma_lch_count;
@@ -523,14 +524,8 @@ void omap_stop_dma(int lch)
 	if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
 			(l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
 		int i = 0;
-		u32 sys_cf;
 
-		/* Configure No-Standby */
-		l = p->dma_read(OCP_SYSCONFIG, lch);
-		sys_cf = l;
-		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
-		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
-		p->dma_write(l , OCP_SYSCONFIG, 0);
+		p->require_no_mstandby(pd);
 
 		l = p->dma_read(CCR, lch);
 		l &= ~OMAP_DMA_CCR_EN;
@@ -547,8 +542,7 @@ void omap_stop_dma(int lch)
 		if (i >= 100)
 			printk(KERN_ERR "DMA drain did not complete on "
 					"lch %d\n", lch);
-		/* Restore OCP_SYSCONFIG */
-		p->dma_write(sys_cf, OCP_SYSCONFIG, lch);
+		p->release_no_mstandby(pd);
 	} else {
 		l &= ~OMAP_DMA_CCR_EN;
 		p->dma_write(l, CCR, lch);
@@ -727,6 +721,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	pd			= pdev;
 	d			= p->dma_attr;
 	errata			= p->errata;
 
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index e18603d..9cb9fbd 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -253,21 +253,6 @@
 #define DMA_THREAD_FIFO_25		(0x02 << 14)
 #define DMA_THREAD_FIFO_50		(0x03 << 14)
 
-/* DMA4_OCP_SYSCONFIG bits */
-#define DMA_SYSCONFIG_MIDLEMODE_MASK		(3 << 12)
-#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK	(3 << 8)
-#define DMA_SYSCONFIG_EMUFREE			(1 << 5)
-#define DMA_SYSCONFIG_SIDLEMODE_MASK		(3 << 3)
-#define DMA_SYSCONFIG_SOFTRESET			(1 << 2)
-#define DMA_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define DMA_SYSCONFIG_MIDLEMODE(n)		((n) << 12)
-#define DMA_SYSCONFIG_SIDLEMODE(n)		((n) << 3)
-
-#define DMA_IDLEMODE_SMARTIDLE			0x2
-#define DMA_IDLEMODE_NO_IDLE			0x1
-#define DMA_IDLEMODE_FORCE_IDLE			0x0
-
 #define DMA_CH_PRIO_HIGH		0x1
 #define DMA_CH_PRIO_LOW			0x0 /* Def */
 
@@ -567,6 +552,8 @@ struct omap_system_dma_plat_info {
 	void (*dma_write)(u32 val, int reg, int lch);
 	u32 (*dma_read)(int reg, int lch);
 	void (*clear_sglist_mode)(int lch);
+	int (*require_no_mstandby)(struct platform_device *pdev);
+	int (*release_no_mstandby)(struct platform_device *pdev);
 };
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v5 14/14] OMAP: PM: DMA: Enable runtime pm
  2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
                   ` (12 preceding siblings ...)
  2010-11-24 12:51 ` [PATCH v5 13/14] OMAP2+: DMA: Replace sysconfig register access with API's G, Manjunath Kondaiah
@ 2010-11-24 12:51 ` G, Manjunath Kondaiah
       [not found] ` <20101125112811.GA27574@GLPP-machine>
  14 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-24 12:51 UTC (permalink / raw)
  To: linux-omap
  Cc: G, Manjunath Kondaiah, linux-arm-kernel, Kevin Hilman,
	Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Enable runtime pm and use pm_runtime_get_sync and pm_runtime_put
for OMAP DMA driver.

Since DMA driver callback will happen from interrupt context and
DMA client driver will release all DMA resources from interrupt
context itself, pm_runtime_put_sync() cannot be used in DMA driver.
Instead, pm_runtime_put() is used which is asynchronous call and
gets executed in work queue.

Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/plat-omap/dma.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index a859c70..527ebfc 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -32,6 +32,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/dma.h>
 #include <plat/tc.h>
@@ -302,6 +303,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	unsigned long flags;
 	struct omap_dma_lch *chan;
 
+	pm_runtime_get_sync(&pd->dev);
 	spin_lock_irqsave(&dma_chan_lock, flags);
 	for (ch = 0; ch < dma_chan_count; ch++) {
 		if (free_ch == -1 && dma_chan[ch].dev_id == -1) {
@@ -312,6 +314,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	}
 	if (free_ch == -1) {
 		spin_unlock_irqrestore(&dma_chan_lock, flags);
+		pm_runtime_put(&pd->dev);
 		return -EBUSY;
 	}
 	chan = dma_chan + free_ch;
@@ -403,6 +406,7 @@ void omap_free_dma(int lch)
 		omap_clear_dma(lch);
 		p->clear_sglist_mode(lch);
 	}
+	pm_runtime_put(&pd->dev);
 	spin_lock_irqsave(&dma_chan_lock, flags);
 	dma_chan[lch].dev_id = -1;
 	dma_chan[lch].next_lch = -1;
@@ -734,6 +738,9 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	dma_chan		= d->chan;
 	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;
 
+	pm_runtime_enable(&pd->dev);
+	pm_runtime_get_sync(&pd->dev);
+
 	spin_lock_init(&dma_chan_lock);
 	for (ch = 0; ch < dma_chan_count; ch++) {
 		unsigned long flags;
@@ -760,6 +767,14 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 		dma_chan[1].dev_id = 1;
 	}
 	p->show_dma_caps();
+
+	/*
+	 * Note: If dma channels are reserved through boot paramters,
+	 * then dma device is always enabled.
+	 */
+	if (!omap_dma_reserve_channels)
+		pm_runtime_put(&pd->dev);
+
 	return 0;
 }
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device
       [not found] ` <20101125112811.GA27574@GLPP-machine>
@ 2010-12-01 19:04     ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-12-01 19:04 UTC (permalink / raw)
  To: linux-omap, Kevin Hilman
  Cc: linux-arm-kernel, Tony Lindgren, Santosh Shilimkar, Benoit Cousson

Hi Tony/Kevin,

* G, Manjunath Kondaiah <manjugk@ti.com> [2010-11-25 16:58:11 +0530]:

> Kevin,
> 
> * G, Manjunath Kondaiah <manjugk@ti.com> [2010-11-24 18:21:36 +0530]:
> 
> > Patch series to convert DMA library into platform driver using platform
> > device model and adapting hwmod for omap2+.
> > 	
> [...]
> > 
> > Patch series applies on top of latest linux omap master branch:
> > *************************************************************************
> > git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> > Branch: master
> > commit 25f7615faa843731af4eda7d05077f1c5132e1a9
> > Merge: 784bee8 8973a21
> > Author: Tony Lindgren <tony@atomide.com>
> > 
> >     Linux-omap rebuilt: Updated to -rc3
> > *************************************************************************
> 
> It also applies cleanly on top of:
> 
> *************************************************************************
> git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git
> Branch: pm-core
> commit 8bcd9727ee126dc50093e84f19dd6c118842202f
> Merge: 632dd87 25f7a1d
> Author: Kevin Hilman <khilman@deeprootsystems.com>
> 
>     Merge branch 'pm-hacks' into pm-reset
>   
> *************************************************************************
Do you have any further comments for this series?

-Manjunath
[...]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device
@ 2010-12-01 19:04     ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-12-01 19:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tony/Kevin,

* G, Manjunath Kondaiah <manjugk@ti.com> [2010-11-25 16:58:11 +0530]:

> Kevin,
> 
> * G, Manjunath Kondaiah <manjugk@ti.com> [2010-11-24 18:21:36 +0530]:
> 
> > Patch series to convert DMA library into platform driver using platform
> > device model and adapting hwmod for omap2+.
> > 	
> [...]
> > 
> > Patch series applies on top of latest linux omap master branch:
> > *************************************************************************
> > git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> > Branch: master
> > commit 25f7615faa843731af4eda7d05077f1c5132e1a9
> > Merge: 784bee8 8973a21
> > Author: Tony Lindgren <tony@atomide.com>
> > 
> >     Linux-omap rebuilt: Updated to -rc3
> > *************************************************************************
> 
> It also applies cleanly on top of:
> 
> *************************************************************************
> git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git
> Branch: pm-core
> commit 8bcd9727ee126dc50093e84f19dd6c118842202f
> Merge: 632dd87 25f7a1d
> Author: Kevin Hilman <khilman@deeprootsystems.com>
> 
>     Merge branch 'pm-hacks' into pm-reset
>   
> *************************************************************************
Do you have any further comments for this series?

-Manjunath
[...]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device
  2010-12-01 19:04     ` G, Manjunath Kondaiah
@ 2010-12-02  2:37       ` Tony Lindgren
  -1 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02  2:37 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, Kevin Hilman, linux-arm-kernel, Santosh Shilimkar,
	Benoit Cousson

Hi,

* G, Manjunath Kondaiah <manjugk@ti.com> [101201 10:53]:
>
> Do you have any further comments for this series?

I'll be looking at it on Thursday.

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device
@ 2010-12-02  2:37       ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02  2:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

* G, Manjunath Kondaiah <manjugk@ti.com> [101201 10:53]:
>
> Do you have any further comments for this series?

I'll be looking at it on Thursday.

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes
  2010-11-24 12:51 ` [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes G, Manjunath Kondaiah
@ 2010-12-02 17:07     ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 17:07 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

* G, Manjunath Kondaiah <manjugk@ti.com> [101124 04:43]:
> Existing DMA API's are using cpu_*is_* checks for differentiating
> omap1 and omap2+ code and handle cpu_*is_* checks with DMA device
> attributes.
> 
> Also, move OMAP1 and OMAP2+ specific API's into respective mach-omap
> dma driver files.

This patch is unreadable and needs to be split.

Also, why are you making duplicate copies of the same generic
functions?

Now you've copied these into mach-omap1/dma.c: 

> +set_src_params(int lch, unsigned long src_start, int src_ei, int src_fi)
> +{
> +	dma_write(src_start, CSSA, lch);
> +
> +	dma_write(src_ei, CSEI, lch);
> +	dma_write(src_fi, CSFI, lch);
> +}
> +
> +static void set_dest_params(int lch, unsigned long dest_start, int dst_ei,
> +								int dst_fi)
> +{
> +	dma_write(dest_start, CDSA, lch);
> +
> +	dma_write(dst_ei, CDEI, lch);
> +	dma_write(dst_fi, CDFI, lch);
> +}
...

And then again the same functions in mach-omap2/dma.c:

> +static void omap2_set_src_params(int lch, unsigned long src_start, int src_ei,
> +								int src_fi)
> +{
> +	dma_write(src_start, CSSA, lch);
> +
> +	dma_write(src_ei, CSEI, lch);
> +	dma_write(src_fi, CSFI, lch);
> +}
> +
> +static void omap2_set_dest_params(int lch, unsigned long dest_start, int dst_ei,
> +								int dst_fi)
> +{
> +	dma_write(dest_start, CDSA, lch);
> +
> +	dma_write(dst_ei, CDEI, lch);
> +	dma_write(dst_fi, CDFI, lch);
> +}
...

All the common functions should stay in plat-omap/dma.c.

Rgards,

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes
@ 2010-12-02 17:07     ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 17:07 UTC (permalink / raw)
  To: linux-arm-kernel

* G, Manjunath Kondaiah <manjugk@ti.com> [101124 04:43]:
> Existing DMA API's are using cpu_*is_* checks for differentiating
> omap1 and omap2+ code and handle cpu_*is_* checks with DMA device
> attributes.
> 
> Also, move OMAP1 and OMAP2+ specific API's into respective mach-omap
> dma driver files.

This patch is unreadable and needs to be split.

Also, why are you making duplicate copies of the same generic
functions?

Now you've copied these into mach-omap1/dma.c: 

> +set_src_params(int lch, unsigned long src_start, int src_ei, int src_fi)
> +{
> +	dma_write(src_start, CSSA, lch);
> +
> +	dma_write(src_ei, CSEI, lch);
> +	dma_write(src_fi, CSFI, lch);
> +}
> +
> +static void set_dest_params(int lch, unsigned long dest_start, int dst_ei,
> +								int dst_fi)
> +{
> +	dma_write(dest_start, CDSA, lch);
> +
> +	dma_write(dst_ei, CDEI, lch);
> +	dma_write(dst_fi, CDFI, lch);
> +}
...

And then again the same functions in mach-omap2/dma.c:

> +static void omap2_set_src_params(int lch, unsigned long src_start, int src_ei,
> +								int src_fi)
> +{
> +	dma_write(src_start, CSSA, lch);
> +
> +	dma_write(src_ei, CSEI, lch);
> +	dma_write(src_fi, CSFI, lch);
> +}
> +
> +static void omap2_set_dest_params(int lch, unsigned long dest_start, int dst_ei,
> +								int dst_fi)
> +{
> +	dma_write(dest_start, CDSA, lch);
> +
> +	dma_write(dst_ei, CDEI, lch);
> +	dma_write(dst_fi, CDFI, lch);
> +}
...

All the common functions should stay in plat-omap/dma.c.

Rgards,

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes
  2010-12-02 17:07     ` Tony Lindgren
@ 2010-12-02 17:32       ` G, Manjunath Kondaiah
  -1 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-12-02 17:32 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

On Thu, Dec 02, 2010 at 09:07:25AM -0800, Tony Lindgren wrote:
> * G, Manjunath Kondaiah <manjugk@ti.com> [101124 04:43]:
> > Existing DMA API's are using cpu_*is_* checks for differentiating
> > omap1 and omap2+ code and handle cpu_*is_* checks with DMA device
> > attributes.
> > 
> > Also, move OMAP1 and OMAP2+ specific API's into respective mach-omap
> > dma driver files.
> 
> This patch is unreadable and needs to be split.

I can split this patch as:
1. all chaining related API movement in one patch.
2. Rest of the changes in second patch.

> 
> Also, why are you making duplicate copies of the same generic
> functions?
> 
> Now you've copied these into mach-omap1/dma.c: 
> 
> > +set_src_params(int lch, unsigned long src_start, int src_ei, int src_fi)
> > +{
> > +	dma_write(src_start, CSSA, lch);
> > +
> > +	dma_write(src_ei, CSEI, lch);
> > +	dma_write(src_fi, CSFI, lch);
> > +}
> > +
> > +static void set_dest_params(int lch, unsigned long dest_start, int dst_ei,
> > +								int dst_fi)
> > +{
> > +	dma_write(dest_start, CDSA, lch);
> > +
> > +	dma_write(dst_ei, CDEI, lch);
> > +	dma_write(dst_fi, CDFI, lch);
> > +}
> ...
> 
> And then again the same functions in mach-omap2/dma.c:

Earlier, handling of CSSA and CDSA was different because 16 bit
registers vs 32 bit registers. Now, with latest patch series, all the
registers are handled inside functions, these API's can be retained in
plat-omap.

> 
> > +static void omap2_set_src_params(int lch, unsigned long src_start, int src_ei,
> > +								int src_fi)
> > +{
> > +	dma_write(src_start, CSSA, lch);
> > +
> > +	dma_write(src_ei, CSEI, lch);
> > +	dma_write(src_fi, CSFI, lch);
> > +}
> > +
> > +static void omap2_set_dest_params(int lch, unsigned long dest_start, int dst_ei,
> > +								int dst_fi)
> > +{
> > +	dma_write(dest_start, CDSA, lch);
> > +
> > +	dma_write(dst_ei, CDEI, lch);
> > +	dma_write(dst_fi, CDFI, lch);
> > +}
> ...
> 
> All the common functions should stay in plat-omap/dma.c.
I agree.

-Manjunath


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes
@ 2010-12-02 17:32       ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-12-02 17:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Dec 02, 2010 at 09:07:25AM -0800, Tony Lindgren wrote:
> * G, Manjunath Kondaiah <manjugk@ti.com> [101124 04:43]:
> > Existing DMA API's are using cpu_*is_* checks for differentiating
> > omap1 and omap2+ code and handle cpu_*is_* checks with DMA device
> > attributes.
> > 
> > Also, move OMAP1 and OMAP2+ specific API's into respective mach-omap
> > dma driver files.
> 
> This patch is unreadable and needs to be split.

I can split this patch as:
1. all chaining related API movement in one patch.
2. Rest of the changes in second patch.

> 
> Also, why are you making duplicate copies of the same generic
> functions?
> 
> Now you've copied these into mach-omap1/dma.c: 
> 
> > +set_src_params(int lch, unsigned long src_start, int src_ei, int src_fi)
> > +{
> > +	dma_write(src_start, CSSA, lch);
> > +
> > +	dma_write(src_ei, CSEI, lch);
> > +	dma_write(src_fi, CSFI, lch);
> > +}
> > +
> > +static void set_dest_params(int lch, unsigned long dest_start, int dst_ei,
> > +								int dst_fi)
> > +{
> > +	dma_write(dest_start, CDSA, lch);
> > +
> > +	dma_write(dst_ei, CDEI, lch);
> > +	dma_write(dst_fi, CDFI, lch);
> > +}
> ...
> 
> And then again the same functions in mach-omap2/dma.c:

Earlier, handling of CSSA and CDSA was different because 16 bit
registers vs 32 bit registers. Now, with latest patch series, all the
registers are handled inside functions, these API's can be retained in
plat-omap.

> 
> > +static void omap2_set_src_params(int lch, unsigned long src_start, int src_ei,
> > +								int src_fi)
> > +{
> > +	dma_write(src_start, CSSA, lch);
> > +
> > +	dma_write(src_ei, CSEI, lch);
> > +	dma_write(src_fi, CSFI, lch);
> > +}
> > +
> > +static void omap2_set_dest_params(int lch, unsigned long dest_start, int dst_ei,
> > +								int dst_fi)
> > +{
> > +	dma_write(dest_start, CDSA, lch);
> > +
> > +	dma_write(dst_ei, CDEI, lch);
> > +	dma_write(dst_fi, CDFI, lch);
> > +}
> ...
> 
> All the common functions should stay in plat-omap/dma.c.
I agree.

-Manjunath

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-11-24 12:51 ` [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver G, Manjunath Kondaiah
@ 2010-12-02 18:44     ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 18:44 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

* G, Manjunath Kondaiah <manjugk@ti.com> [101124 04:42]:
> Convert DMA library into DMA platform driver and make use of
> platform data provided by hwmod data base for OMAP2+ onwards.
> 
> For OMAP1 processors, the DMA driver in mach-omap uses resource
> structures for getting platform data.

And has never been tested..

<snip>

>  static int __init omap1_system_dma_init(void)
>  {
>  	struct omap_system_dma_plat_info	*p;
> +	struct omap_dma_dev_attr		*d;
>  	struct platform_device			*pdev;
>  	int ret;
>  
> @@ -153,22 +295,74 @@ static int __init omap1_system_dma_init(void)
>  		goto exit_device_put;
>  	}
>  
> +	d = p->dma_attr;

This fails on omap1 as d is not allocated. Please merge the
following fix.

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Thu, 2 Dec 2010 10:02:08 -0800
Subject: [PATCH] Fix dma init for omap1

Fix dma init for omap1

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -295,13 +295,20 @@ static int __init omap1_system_dma_init(void)
 		goto exit_device_put;
 	}
 
-	d = p->dma_attr;
+	d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
+	if (!d) {
+		dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
+			__func__, pdev->name);
+		ret = -ENOMEM;
+		goto exit_release_p;
+	}
+
 	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
 					(d->lch_count), GFP_KERNEL);
 	if (!d->chan) {
 		dev_err(&pdev->dev, "%s: Memory allocation failed"
 					"for d->chan!!!\n", __func__);
-		goto exit_release_p;
+		goto exit_release_d;
 	}
 
 	/* Valid attributes for omap1 plus processors */
@@ -328,6 +335,8 @@ static int __init omap1_system_dma_init(void)
 			d->chan_count = 9;
 	}
 
+	p->dma_attr = d;
+
 	dma_base		= (void __iomem *)res[0].start;
 
 	p->show_dma_caps	= omap1_show_dma_caps;
@@ -361,6 +370,8 @@ static int __init omap1_system_dma_init(void)
 
 exit_release_chan:
 	kfree(d->chan);
+exit_release_d:
+	kfree(d);
 exit_release_p:
 	kfree(p);
 exit_device_put:

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2010-12-02 18:44     ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 18:44 UTC (permalink / raw)
  To: linux-arm-kernel

* G, Manjunath Kondaiah <manjugk@ti.com> [101124 04:42]:
> Convert DMA library into DMA platform driver and make use of
> platform data provided by hwmod data base for OMAP2+ onwards.
> 
> For OMAP1 processors, the DMA driver in mach-omap uses resource
> structures for getting platform data.

And has never been tested..

<snip>

>  static int __init omap1_system_dma_init(void)
>  {
>  	struct omap_system_dma_plat_info	*p;
> +	struct omap_dma_dev_attr		*d;
>  	struct platform_device			*pdev;
>  	int ret;
>  
> @@ -153,22 +295,74 @@ static int __init omap1_system_dma_init(void)
>  		goto exit_device_put;
>  	}
>  
> +	d = p->dma_attr;

This fails on omap1 as d is not allocated. Please merge the
following fix.

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Thu, 2 Dec 2010 10:02:08 -0800
Subject: [PATCH] Fix dma init for omap1

Fix dma init for omap1

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -295,13 +295,20 @@ static int __init omap1_system_dma_init(void)
 		goto exit_device_put;
 	}
 
-	d = p->dma_attr;
+	d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
+	if (!d) {
+		dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
+			__func__, pdev->name);
+		ret = -ENOMEM;
+		goto exit_release_p;
+	}
+
 	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
 					(d->lch_count), GFP_KERNEL);
 	if (!d->chan) {
 		dev_err(&pdev->dev, "%s: Memory allocation failed"
 					"for d->chan!!!\n", __func__);
-		goto exit_release_p;
+		goto exit_release_d;
 	}
 
 	/* Valid attributes for omap1 plus processors */
@@ -328,6 +335,8 @@ static int __init omap1_system_dma_init(void)
 			d->chan_count = 9;
 	}
 
+	p->dma_attr = d;
+
 	dma_base		= (void __iomem *)res[0].start;
 
 	p->show_dma_caps	= omap1_show_dma_caps;
@@ -361,6 +370,8 @@ static int __init omap1_system_dma_init(void)
 
 exit_release_chan:
 	kfree(d->chan);
+exit_release_d:
+	kfree(d);
 exit_release_p:
 	kfree(p);
 exit_device_put:

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-12-02 18:44     ` Tony Lindgren
@ 2010-12-02 18:46       ` Tony Lindgren
  -1 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 18:46 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

* Tony Lindgren <tony@atomide.com> [101202 10:34]:
> 
> This fails on omap1 as d is not allocated. Please merge the
> following fix.

And another fix here:

From: Tony Lindgren <tony@atomide.com>
Date: Thu, 2 Dec 2010 10:19:15 -0800
Subject: [PATCH] Fix omap1_system_dma_init to use ioremap

Fix omap1_system_dma_init to use ioremap

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -280,6 +280,12 @@ static int __init omap1_system_dma_init(void)
 		return -ENOMEM;
 	}
 
+	dma_base = ioremap(res[0].start, resource_size(&res[0]));
+	if (!dma_base) {
+		pr_err("%s: Unable to ioremap\n", __func__);
+		return -ENODEV;
+	}
+
 	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
@@ -337,8 +343,6 @@ static int __init omap1_system_dma_init(void)
 
 	p->dma_attr = d;
 
-	dma_base		= (void __iomem *)res[0].start;
-
 	p->show_dma_caps	= omap1_show_dma_caps;
 	p->clear_lch_regs	= omap1_clear_lch_regs;
 	p->clear_dma		= omap1_clear_dma;

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2010-12-02 18:46       ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 18:46 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [101202 10:34]:
> 
> This fails on omap1 as d is not allocated. Please merge the
> following fix.

And another fix here:

From: Tony Lindgren <tony@atomide.com>
Date: Thu, 2 Dec 2010 10:19:15 -0800
Subject: [PATCH] Fix omap1_system_dma_init to use ioremap

Fix omap1_system_dma_init to use ioremap

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -280,6 +280,12 @@ static int __init omap1_system_dma_init(void)
 		return -ENOMEM;
 	}
 
+	dma_base = ioremap(res[0].start, resource_size(&res[0]));
+	if (!dma_base) {
+		pr_err("%s: Unable to ioremap\n", __func__);
+		return -ENODEV;
+	}
+
 	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
@@ -337,8 +343,6 @@ static int __init omap1_system_dma_init(void)
 
 	p->dma_attr = d;
 
-	dma_base		= (void __iomem *)res[0].start;
-
 	p->show_dma_caps	= omap1_show_dma_caps;
 	p->clear_lch_regs	= omap1_clear_lch_regs;
 	p->clear_dma		= omap1_clear_dma;

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-12-02 18:46       ` Tony Lindgren
@ 2010-12-02 18:49         ` Tony Lindgren
  -1 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 18:49 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

* Tony Lindgren <tony@atomide.com> [101202 10:36]:
> * Tony Lindgren <tony@atomide.com> [101202 10:34]:
> > 
> > This fails on omap1 as d is not allocated. Please merge the
> > following fix.
> 
> And another fix here:

One more fix below.

Note that even with these three fixes, 5912OSK still fails to
boot to init. Maybe something wrong with the framebuffer DMA?

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Thu, 2 Dec 2010 10:34:18 -0800
Subject: [PATCH] Fix omap1_system_dma_init to initialize d->lch_count earlier

Otherwise the kzalloc will allocate wrong amount of memory.

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -309,13 +309,7 @@ static int __init omap1_system_dma_init(void)
 		goto exit_release_p;
 	}
 
-	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
-					(d->lch_count), GFP_KERNEL);
-	if (!d->chan) {
-		dev_err(&pdev->dev, "%s: Memory allocation failed"
-					"for d->chan!!!\n", __func__);
-		goto exit_release_d;
-	}
+	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
 
 	/* Valid attributes for omap1 plus processors */
 	if (cpu_is_omap15xx())
@@ -330,7 +324,14 @@ static int __init omap1_system_dma_init(void)
 	d->dev_caps		|= CLEAR_CSR_ON_READ;
 	d->dev_caps		|= IS_WORD_16;
 
-	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
+
+	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->lch_count), GFP_KERNEL);
+	if (!d->chan) {
+		dev_err(&pdev->dev, "%s: Memory allocation failed"
+					"for d->chan!!!\n", __func__);
+		goto exit_release_d;
+	}
 
 	if (cpu_is_omap15xx())
 		d->chan_count = 9;

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2010-12-02 18:49         ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 18:49 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [101202 10:36]:
> * Tony Lindgren <tony@atomide.com> [101202 10:34]:
> > 
> > This fails on omap1 as d is not allocated. Please merge the
> > following fix.
> 
> And another fix here:

One more fix below.

Note that even with these three fixes, 5912OSK still fails to
boot to init. Maybe something wrong with the framebuffer DMA?

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Thu, 2 Dec 2010 10:34:18 -0800
Subject: [PATCH] Fix omap1_system_dma_init to initialize d->lch_count earlier

Otherwise the kzalloc will allocate wrong amount of memory.

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -309,13 +309,7 @@ static int __init omap1_system_dma_init(void)
 		goto exit_release_p;
 	}
 
-	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
-					(d->lch_count), GFP_KERNEL);
-	if (!d->chan) {
-		dev_err(&pdev->dev, "%s: Memory allocation failed"
-					"for d->chan!!!\n", __func__);
-		goto exit_release_d;
-	}
+	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
 
 	/* Valid attributes for omap1 plus processors */
 	if (cpu_is_omap15xx())
@@ -330,7 +324,14 @@ static int __init omap1_system_dma_init(void)
 	d->dev_caps		|= CLEAR_CSR_ON_READ;
 	d->dev_caps		|= IS_WORD_16;
 
-	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
+
+	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->lch_count), GFP_KERNEL);
+	if (!d->chan) {
+		dev_err(&pdev->dev, "%s: Memory allocation failed"
+					"for d->chan!!!\n", __func__);
+		goto exit_release_d;
+	}
 
 	if (cpu_is_omap15xx())
 		d->chan_count = 9;

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-12-02 18:49         ` Tony Lindgren
@ 2010-12-02 20:04           ` G, Manjunath Kondaiah
  -1 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-12-02 20:04 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

On Thu, Dec 02, 2010 at 10:49:25AM -0800, Tony Lindgren wrote:
> * Tony Lindgren <tony@atomide.com> [101202 10:36]:
> > * Tony Lindgren <tony@atomide.com> [101202 10:34]:
> > > 
> > > This fails on omap1 as d is not allocated. Please merge the
> > > following fix.
> > 
> > And another fix here:
> 
> One more fix below.

Thanks. I will merge these fixes.

> 
> Note that even with these three fixes, 5912OSK still fails to
> boot to init. Maybe something wrong with the framebuffer DMA?

Not sure. I don't have omap1 board for testing. Patch series is only 
build tested for omap1.

Can you pls confirm if OSK5912 boots successfully without this patch
series?

If yes, I will cross verify omap1 changes again.

-Manjunath


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2010-12-02 20:04           ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-12-02 20:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Dec 02, 2010 at 10:49:25AM -0800, Tony Lindgren wrote:
> * Tony Lindgren <tony@atomide.com> [101202 10:36]:
> > * Tony Lindgren <tony@atomide.com> [101202 10:34]:
> > > 
> > > This fails on omap1 as d is not allocated. Please merge the
> > > following fix.
> > 
> > And another fix here:
> 
> One more fix below.

Thanks. I will merge these fixes.

> 
> Note that even with these three fixes, 5912OSK still fails to
> boot to init. Maybe something wrong with the framebuffer DMA?

Not sure. I don't have omap1 board for testing. Patch series is only 
build tested for omap1.

Can you pls confirm if OSK5912 boots successfully without this patch
series?

If yes, I will cross verify omap1 changes again.

-Manjunath

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-12-02 20:04           ` G, Manjunath Kondaiah
@ 2010-12-02 20:52             ` Tony Lindgren
  -1 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 20:52 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

* G, Manjunath Kondaiah <manjugk@ti.com> [101202 11:55]:
> 
> > 
> > Note that even with these three fixes, 5912OSK still fails to
> > boot to init. Maybe something wrong with the framebuffer DMA?
> 
> Not sure. I don't have omap1 board for testing. Patch series is only 
> build tested for omap1.
> 
> Can you pls confirm if OSK5912 boots successfully without this patch
> series?

Yeah boots just fine without these as always.

Anybody care to donate a OSK5912 or similar for the TI guys
for doing quick omap1 boot testing on?
 
> If yes, I will cross verify omap1 changes again.

Found the problem. INT_DMA_LCD is handled in mach-omap1/lcd_dma.c.
In your omap_system_dma_probe we now exit everything if request_irq
fails for one channel. So let's skip INT_DMA_LCD.

Also, you should check the logic in omap_system_dma_probe as it's
not very good handling right now. Note how platform_get_irq_byname
does not free other dma_irqs like after request_irq we do.

With your patches applied up to patch "Convert DMA library into
platform driver" + my three earlie fixes + the following fix
I can now boot OSK5912 and see the penguin on the LCD too.

I suggest you break your series into two where the last patch
in the first series is "Convert DMA library into platform driver".
That way the init related changes are done, and we can merge
those in for testing while you update the rest of the series.

Also, eventually within next few merge cycles we should have:

arch/arm/mach-omap1/dma.c	omap1 specific platform init
arch/arm/mach-omap2/dma.c	omap2+ specific platform init
drivers/dma/omap-dma.c		driver using dmaengine.c

So before continuing beyond "Convert DMA library into platform
driver" in the series, maybe take a quick look at dmaengine
in drivers/dma/ so we don't have to redo tons of things again
later on.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Thu, 2 Dec 2010 12:35:02 -0800
Subject: [PATCH] Fix omap_system_dma_probe for omap1 INT_DMA_LCD

We don't want to request it as it's handled by mach-omap1/lcd_dma.c.

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -118,6 +118,7 @@ static struct resource res[] __initdata = {
 		.start  = INT_DMA_CH5,
 		.flags  = IORESOURCE_IRQ,
 	},
+	/* Handled in lcd_dma.c */
 	[7] = {
 		.name   = "6",
 		.start  = INT_DMA_LCD,
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -2025,6 +2025,11 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 				ret = dma_irq;
 				goto exit_dma_chan;
 			}
+
+			/* INT_DMA_LCD is handled in lcd_dma.c */
+			if (dma_irq == INT_DMA_LCD)
+				continue;
+
 			ret = request_irq(dma_irq,
 					omap1_dma_irq_handler, 0, "DMA",
 					(void *) (ch + 1));

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2010-12-02 20:52             ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-02 20:52 UTC (permalink / raw)
  To: linux-arm-kernel

* G, Manjunath Kondaiah <manjugk@ti.com> [101202 11:55]:
> 
> > 
> > Note that even with these three fixes, 5912OSK still fails to
> > boot to init. Maybe something wrong with the framebuffer DMA?
> 
> Not sure. I don't have omap1 board for testing. Patch series is only 
> build tested for omap1.
> 
> Can you pls confirm if OSK5912 boots successfully without this patch
> series?

Yeah boots just fine without these as always.

Anybody care to donate a OSK5912 or similar for the TI guys
for doing quick omap1 boot testing on?
 
> If yes, I will cross verify omap1 changes again.

Found the problem. INT_DMA_LCD is handled in mach-omap1/lcd_dma.c.
In your omap_system_dma_probe we now exit everything if request_irq
fails for one channel. So let's skip INT_DMA_LCD.

Also, you should check the logic in omap_system_dma_probe as it's
not very good handling right now. Note how platform_get_irq_byname
does not free other dma_irqs like after request_irq we do.

With your patches applied up to patch "Convert DMA library into
platform driver" + my three earlie fixes + the following fix
I can now boot OSK5912 and see the penguin on the LCD too.

I suggest you break your series into two where the last patch
in the first series is "Convert DMA library into platform driver".
That way the init related changes are done, and we can merge
those in for testing while you update the rest of the series.

Also, eventually within next few merge cycles we should have:

arch/arm/mach-omap1/dma.c	omap1 specific platform init
arch/arm/mach-omap2/dma.c	omap2+ specific platform init
drivers/dma/omap-dma.c		driver using dmaengine.c

So before continuing beyond "Convert DMA library into platform
driver" in the series, maybe take a quick look at dmaengine
in drivers/dma/ so we don't have to redo tons of things again
later on.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Thu, 2 Dec 2010 12:35:02 -0800
Subject: [PATCH] Fix omap_system_dma_probe for omap1 INT_DMA_LCD

We don't want to request it as it's handled by mach-omap1/lcd_dma.c.

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -118,6 +118,7 @@ static struct resource res[] __initdata = {
 		.start  = INT_DMA_CH5,
 		.flags  = IORESOURCE_IRQ,
 	},
+	/* Handled in lcd_dma.c */
 	[7] = {
 		.name   = "6",
 		.start  = INT_DMA_LCD,
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -2025,6 +2025,11 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 				ret = dma_irq;
 				goto exit_dma_chan;
 			}
+
+			/* INT_DMA_LCD is handled in lcd_dma.c */
+			if (dma_irq == INT_DMA_LCD)
+				continue;
+
 			ret = request_irq(dma_irq,
 					omap1_dma_irq_handler, 0, "DMA",
 					(void *) (ch + 1));

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-12-02 20:52             ` Tony Lindgren
@ 2010-12-03 16:43               ` G, Manjunath Kondaiah
  -1 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-12-03 16:43 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

Hi Tony,

* Tony Lindgren <tony@atomide.com> [2010-12-02 12:52:19 -0800]:

> * G, Manjunath Kondaiah <manjugk@ti.com> [101202 11:55]:
> > 
> > > 
> > > Note that even with these three fixes, 5912OSK still fails to
> > > boot to init. Maybe something wrong with the framebuffer DMA?
> > 
> > Not sure. I don't have omap1 board for testing. Patch series is only 
> > build tested for omap1.
> > 
> > Can you pls confirm if OSK5912 boots successfully without this patch
> > series?
> 
> Yeah boots just fine without these as always.
> 
> Anybody care to donate a OSK5912 or similar for the TI guys
> for doing quick omap1 boot testing on?
>  
> > If yes, I will cross verify omap1 changes again.
> 
> Found the problem. INT_DMA_LCD is handled in mach-omap1/lcd_dma.c.
> In your omap_system_dma_probe we now exit everything if request_irq
> fails for one channel. So let's skip INT_DMA_LCD.
> 
> Also, you should check the logic in omap_system_dma_probe as it's
> not very good handling right now. Note how platform_get_irq_byname
> does not free other dma_irqs like after request_irq we do.

Fixed error handling cases.

> 
> With your patches applied up to patch "Convert DMA library into
> platform driver" + my three earlie fixes + the following fix
> I can now boot OSK5912 and see the penguin on the LCD too.

Thanks a lot. I pulled in all these fixes into the patch series.

> 
> I suggest you break your series into two where the last patch
> in the first series is "Convert DMA library into platform driver".

I am ok with this approach.

> That way the init related changes are done, and we can merge
> those in for testing while you update the rest of the series.

cool.

I have done required changes to patch series and tested the same on
omap2+ boards. Can you pls test OSK5912 board boot from the below
git repo? If OSK5912 boots up(with LCD), I will post the 1st series to
LO ML.

git://dev.omapzoom.org/pub/scm/manju/kernel-omap3-dev.git
Branch: dma_testing
commit 3047de5b11cc3fef9ea18a7e8d64fec7a9ea7a89
Author: G, Manjunath Kondaiah <manjugk@ti.com>
Date:   Fri Dec 3 20:03:23 2010 +0530

    OMAP: DMA: Convert DMA library into platform driver
    
    Convert DMA library into DMA platform driver and make use of
    platform data provided by hwmod data base for OMAP2+ onwards.
    
    For OMAP1 processors, the DMA driver in mach-omap uses resource
    structures for getting platform data.
    
    Thanks to Tony Lindgren <tony@atomide.com> for fixing various
    omap1 issues and testing the same on OSK5912 board.
    
    Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
    Signed-off-by: Tony Lindgren <tony@atomide.com>
    Cc: Benoit Cousson <b-cousson@ti.com>
    Cc: Kevin Hilman <khilman@deeprootsystems.com>
    Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>

> 
> Also, eventually within next few merge cycles we should have:
> 
> arch/arm/mach-omap1/dma.c	omap1 specific platform init
> arch/arm/mach-omap2/dma.c	omap2+ specific platform init

This seems to be ok.

> drivers/dma/omap-dma.c		driver using dmaengine.c

This might require more time.

-Manjunath


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2010-12-03 16:43               ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2010-12-03 16:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tony,

* Tony Lindgren <tony@atomide.com> [2010-12-02 12:52:19 -0800]:

> * G, Manjunath Kondaiah <manjugk@ti.com> [101202 11:55]:
> > 
> > > 
> > > Note that even with these three fixes, 5912OSK still fails to
> > > boot to init. Maybe something wrong with the framebuffer DMA?
> > 
> > Not sure. I don't have omap1 board for testing. Patch series is only 
> > build tested for omap1.
> > 
> > Can you pls confirm if OSK5912 boots successfully without this patch
> > series?
> 
> Yeah boots just fine without these as always.
> 
> Anybody care to donate a OSK5912 or similar for the TI guys
> for doing quick omap1 boot testing on?
>  
> > If yes, I will cross verify omap1 changes again.
> 
> Found the problem. INT_DMA_LCD is handled in mach-omap1/lcd_dma.c.
> In your omap_system_dma_probe we now exit everything if request_irq
> fails for one channel. So let's skip INT_DMA_LCD.
> 
> Also, you should check the logic in omap_system_dma_probe as it's
> not very good handling right now. Note how platform_get_irq_byname
> does not free other dma_irqs like after request_irq we do.

Fixed error handling cases.

> 
> With your patches applied up to patch "Convert DMA library into
> platform driver" + my three earlie fixes + the following fix
> I can now boot OSK5912 and see the penguin on the LCD too.

Thanks a lot. I pulled in all these fixes into the patch series.

> 
> I suggest you break your series into two where the last patch
> in the first series is "Convert DMA library into platform driver".

I am ok with this approach.

> That way the init related changes are done, and we can merge
> those in for testing while you update the rest of the series.

cool.

I have done required changes to patch series and tested the same on
omap2+ boards. Can you pls test OSK5912 board boot from the below
git repo? If OSK5912 boots up(with LCD), I will post the 1st series to
LO ML.

git://dev.omapzoom.org/pub/scm/manju/kernel-omap3-dev.git
Branch: dma_testing
commit 3047de5b11cc3fef9ea18a7e8d64fec7a9ea7a89
Author: G, Manjunath Kondaiah <manjugk@ti.com>
Date:   Fri Dec 3 20:03:23 2010 +0530

    OMAP: DMA: Convert DMA library into platform driver
    
    Convert DMA library into DMA platform driver and make use of
    platform data provided by hwmod data base for OMAP2+ onwards.
    
    For OMAP1 processors, the DMA driver in mach-omap uses resource
    structures for getting platform data.
    
    Thanks to Tony Lindgren <tony@atomide.com> for fixing various
    omap1 issues and testing the same on OSK5912 board.
    
    Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
    Signed-off-by: Tony Lindgren <tony@atomide.com>
    Cc: Benoit Cousson <b-cousson@ti.com>
    Cc: Kevin Hilman <khilman@deeprootsystems.com>
    Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>

> 
> Also, eventually within next few merge cycles we should have:
> 
> arch/arm/mach-omap1/dma.c	omap1 specific platform init
> arch/arm/mach-omap2/dma.c	omap2+ specific platform init

This seems to be ok.

> drivers/dma/omap-dma.c		driver using dmaengine.c

This might require more time.

-Manjunath

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-12-03 16:43               ` G, Manjunath Kondaiah
@ 2010-12-03 23:24                 ` Tony Lindgren
  -1 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-03 23:24 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, linux-arm-kernel, Kevin Hilman, Santosh Shilimkar,
	Benoit Cousson

* G, Manjunath Kondaiah <manjugk@ti.com> [101203 08:32]:
> 
> I have done required changes to patch series and tested the same on
> omap2+ boards. Can you pls test OSK5912 board boot from the below
> git repo? If OSK5912 boots up(with LCD), I will post the 1st series to
> LO ML.

Yeah seems to boot OK now with tux showing up too.

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2010-12-03 23:24                 ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2010-12-03 23:24 UTC (permalink / raw)
  To: linux-arm-kernel

* G, Manjunath Kondaiah <manjugk@ti.com> [101203 08:32]:
> 
> I have done required changes to patch series and tested the same on
> omap2+ boards. Can you pls test OSK5912 board boot from the below
> git repo? If OSK5912 boots up(with LCD), I will post the 1st series to
> LO ML.

Yeah seems to boot OK now with tux showing up too.

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2010-12-03 16:43               ` G, Manjunath Kondaiah
@ 2011-01-13 11:20                 ` G, Manjunath Kondaiah
  -1 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2011-01-13 11:20 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap, linux-arm-kernel, Kevin Hilman

Hi Tony,

On Fri, Dec 3, 2010 at 10:13 PM, G, Manjunath Kondaiah <manjugk@ti.com> wrote:
> Hi Tony,
>
> * Tony Lindgren <tony@atomide.com> [2010-12-02 12:52:19 -0800]:
>
>> * G, Manjunath Kondaiah <manjugk@ti.com> [101202 11:55]:
>> >
>> > >
>> > > Note that even with these three fixes, 5912OSK still fails to
>> > > boot to init. Maybe something wrong with the framebuffer DMA?
>> >
>> > Not sure. I don't have omap1 board for testing. Patch series is only
>> > build tested for omap1.
>> >
>> > Can you pls confirm if OSK5912 boots successfully without this patch
>> > series?
>>
>> Yeah boots just fine without these as always.
>>
>> Anybody care to donate a OSK5912 or similar for the TI guys
>> for doing quick omap1 boot testing on?
>>
>> > If yes, I will cross verify omap1 changes again.
>>
>> Found the problem. INT_DMA_LCD is handled in mach-omap1/lcd_dma.c.
>> In your omap_system_dma_probe we now exit everything if request_irq
>> fails for one channel. So let's skip INT_DMA_LCD.
>>
>> Also, you should check the logic in omap_system_dma_probe as it's
>> not very good handling right now. Note how platform_get_irq_byname
>> does not free other dma_irqs like after request_irq we do.
>
> Fixed error handling cases.
>
>>
>> With your patches applied up to patch "Convert DMA library into
>> platform driver" + my three earlie fixes + the following fix
>> I can now boot OSK5912 and see the penguin on the LCD too.
>
> Thanks a lot. I pulled in all these fixes into the patch series.
>
>>
>> I suggest you break your series into two where the last patch
>> in the first series is "Convert DMA library into platform driver".
>
> I am ok with this approach.
>
>> That way the init related changes are done, and we can merge
>> those in for testing while you update the rest of the series.
>
> cool.
>
> I have done required changes to patch series and tested the same on
> omap2+ boards. Can you pls test OSK5912 board boot from the below
> git repo? If OSK5912 boots up(with LCD), I will post the 1st series to
> LO ML.
>
> git://dev.omapzoom.org/pub/scm/manju/kernel-omap3-dev.git
> Branch: dma_testing
> commit 3047de5b11cc3fef9ea18a7e8d64fec7a9ea7a89
> Author: G, Manjunath Kondaiah <manjugk@ti.com>
> Date:   Fri Dec 3 20:03:23 2010 +0530
>
>    OMAP: DMA: Convert DMA library into platform driver
>
>    Convert DMA library into DMA platform driver and make use of
>    platform data provided by hwmod data base for OMAP2+ onwards.
>
>    For OMAP1 processors, the DMA driver in mach-omap uses resource
>    structures for getting platform data.
>
>    Thanks to Tony Lindgren <tony@atomide.com> for fixing various
>    omap1 issues and testing the same on OSK5912 board.
>
>    Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
>    Signed-off-by: Tony Lindgren <tony@atomide.com>
>    Cc: Benoit Cousson <b-cousson@ti.com>
>    Cc: Kevin Hilman <khilman@deeprootsystems.com>
>    Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>
>>
>> Also, eventually within next few merge cycles we should have:
>>
>> arch/arm/mach-omap1/dma.c     omap1 specific platform init
>> arch/arm/mach-omap2/dma.c     omap2+ specific platform init
>
> This seems to be ok.
>
>> drivers/dma/omap-dma.c                driver using dmaengine.c
>
> This might require more time.

Since this will take more time, can we have run time pm changes on top
of existing dma hwmod changes?
If so, I can pull out run time pm patch from the dma hwmod series and
resend it again.

-Manjunath
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2011-01-13 11:20                 ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 41+ messages in thread
From: G, Manjunath Kondaiah @ 2011-01-13 11:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tony,

On Fri, Dec 3, 2010 at 10:13 PM, G, Manjunath Kondaiah <manjugk@ti.com> wrote:
> Hi Tony,
>
> * Tony Lindgren <tony@atomide.com> [2010-12-02 12:52:19 -0800]:
>
>> * G, Manjunath Kondaiah <manjugk@ti.com> [101202 11:55]:
>> >
>> > >
>> > > Note that even with these three fixes, 5912OSK still fails to
>> > > boot to init. Maybe something wrong with the framebuffer DMA?
>> >
>> > Not sure. I don't have omap1 board for testing. Patch series is only
>> > build tested for omap1.
>> >
>> > Can you pls confirm if OSK5912 boots successfully without this patch
>> > series?
>>
>> Yeah boots just fine without these as always.
>>
>> Anybody care to donate a OSK5912 or similar for the TI guys
>> for doing quick omap1 boot testing on?
>>
>> > If yes, I will cross verify omap1 changes again.
>>
>> Found the problem. INT_DMA_LCD is handled in mach-omap1/lcd_dma.c.
>> In your omap_system_dma_probe we now exit everything if request_irq
>> fails for one channel. So let's skip INT_DMA_LCD.
>>
>> Also, you should check the logic in omap_system_dma_probe as it's
>> not very good handling right now. Note how platform_get_irq_byname
>> does not free other dma_irqs like after request_irq we do.
>
> Fixed error handling cases.
>
>>
>> With your patches applied up to patch "Convert DMA library into
>> platform driver" + my three earlie fixes + the following fix
>> I can now boot OSK5912 and see the penguin on the LCD too.
>
> Thanks a lot. I pulled in all these fixes into the patch series.
>
>>
>> I suggest you break your series into two where the last patch
>> in the first series is "Convert DMA library into platform driver".
>
> I am ok with this approach.
>
>> That way the init related changes are done, and we can merge
>> those in for testing while you update the rest of the series.
>
> cool.
>
> I have done required changes to patch series and tested the same on
> omap2+ boards. Can you pls test OSK5912 board boot from the below
> git repo? If OSK5912 boots up(with LCD), I will post the 1st series to
> LO ML.
>
> git://dev.omapzoom.org/pub/scm/manju/kernel-omap3-dev.git
> Branch: dma_testing
> commit 3047de5b11cc3fef9ea18a7e8d64fec7a9ea7a89
> Author: G, Manjunath Kondaiah <manjugk@ti.com>
> Date: ? Fri Dec 3 20:03:23 2010 +0530
>
> ? ?OMAP: DMA: Convert DMA library into platform driver
>
> ? ?Convert DMA library into DMA platform driver and make use of
> ? ?platform data provided by hwmod data base for OMAP2+ onwards.
>
> ? ?For OMAP1 processors, the DMA driver in mach-omap uses resource
> ? ?structures for getting platform data.
>
> ? ?Thanks to Tony Lindgren <tony@atomide.com> for fixing various
> ? ?omap1 issues and testing the same on OSK5912 board.
>
> ? ?Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> ? ?Signed-off-by: Tony Lindgren <tony@atomide.com>
> ? ?Cc: Benoit Cousson <b-cousson@ti.com>
> ? ?Cc: Kevin Hilman <khilman@deeprootsystems.com>
> ? ?Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>
>>
>> Also, eventually within next few merge cycles we should have:
>>
>> arch/arm/mach-omap1/dma.c ? ? omap1 specific platform init
>> arch/arm/mach-omap2/dma.c ? ? omap2+ specific platform init
>
> This seems to be ok.
>
>> drivers/dma/omap-dma.c ? ? ? ? ? ? ? ?driver using dmaengine.c
>
> This might require more time.

Since this will take more time, can we have run time pm changes on top
of existing dma hwmod changes?
If so, I can pull out run time pm patch from the dma hwmod series and
resend it again.

-Manjunath

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
  2011-01-13 11:20                 ` G, Manjunath Kondaiah
@ 2011-01-19 19:04                   ` Tony Lindgren
  -1 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2011-01-19 19:04 UTC (permalink / raw)
  To: G, Manjunath Kondaiah; +Cc: linux-omap, linux-arm-kernel, Kevin Hilman

* G, Manjunath Kondaiah <manjugk@ti.com> [110113 03:19]:
> >
> >>
> >> Also, eventually within next few merge cycles we should have:
> >>
> >> arch/arm/mach-omap1/dma.c     omap1 specific platform init
> >> arch/arm/mach-omap2/dma.c     omap2+ specific platform init
> >
> > This seems to be ok.
> >
> >> drivers/dma/omap-dma.c                driver using dmaengine.c
> >
> > This might require more time.
> 
> Since this will take more time, can we have run time pm changes on top
> of existing dma hwmod changes?
> If so, I can pull out run time pm patch from the dma hwmod series and
> resend it again.

Sure. That will make it easier to convert it to use dmaengine
eventually.

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver
@ 2011-01-19 19:04                   ` Tony Lindgren
  0 siblings, 0 replies; 41+ messages in thread
From: Tony Lindgren @ 2011-01-19 19:04 UTC (permalink / raw)
  To: linux-arm-kernel

* G, Manjunath Kondaiah <manjugk@ti.com> [110113 03:19]:
> >
> >>
> >> Also, eventually within next few merge cycles we should have:
> >>
> >> arch/arm/mach-omap1/dma.c ? ? omap1 specific platform init
> >> arch/arm/mach-omap2/dma.c ? ? omap2+ specific platform init
> >
> > This seems to be ok.
> >
> >> drivers/dma/omap-dma.c ? ? ? ? ? ? ? ?driver using dmaengine.c
> >
> > This might require more time.
> 
> Since this will take more time, can we have run time pm changes on top
> of existing dma hwmod changes?
> If so, I can pull out run time pm patch from the dma hwmod series and
> resend it again.

Sure. That will make it easier to convert it to use dmaengine
eventually.

Tony

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2011-01-19 19:04 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-24 12:51 [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 01/14] OMAP: DMA: Replace read/write macros with functions G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 02/14] OMAP: DMA: Introduce errata handling feature G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 03/14] OMAP2420: hwmod data: add system DMA G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 04/14] OMAP2430: " G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 05/14] OMAP3: " G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 06/14] OMAP4: " G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 07/14] OMAP1: DMA: Implement in platform device model G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 08/14] OMAP2+: DMA: hwmod: Device registration G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 09/14] OMAP: DMA: Convert DMA library into platform driver G, Manjunath Kondaiah
2010-12-02 18:44   ` Tony Lindgren
2010-12-02 18:44     ` Tony Lindgren
2010-12-02 18:46     ` Tony Lindgren
2010-12-02 18:46       ` Tony Lindgren
2010-12-02 18:49       ` Tony Lindgren
2010-12-02 18:49         ` Tony Lindgren
2010-12-02 20:04         ` G, Manjunath Kondaiah
2010-12-02 20:04           ` G, Manjunath Kondaiah
2010-12-02 20:52           ` Tony Lindgren
2010-12-02 20:52             ` Tony Lindgren
2010-12-03 16:43             ` G, Manjunath Kondaiah
2010-12-03 16:43               ` G, Manjunath Kondaiah
2010-12-03 23:24               ` Tony Lindgren
2010-12-03 23:24                 ` Tony Lindgren
2011-01-13 11:20               ` G, Manjunath Kondaiah
2011-01-13 11:20                 ` G, Manjunath Kondaiah
2011-01-19 19:04                 ` Tony Lindgren
2011-01-19 19:04                   ` Tony Lindgren
2010-11-24 12:51 ` [PATCH v5 10/14] OMAP: DMA: Use DMA device attributes G, Manjunath Kondaiah
2010-12-02 17:07   ` Tony Lindgren
2010-12-02 17:07     ` Tony Lindgren
2010-12-02 17:32     ` G, Manjunath Kondaiah
2010-12-02 17:32       ` G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 11/14] OMAP2+: DMA: descriptor autoloading feature G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 12/14] OMAP3630: DMA: Add work around for erratum i557 G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 13/14] OMAP2+: DMA: Replace sysconfig register access with API's G, Manjunath Kondaiah
2010-11-24 12:51 ` [PATCH v5 14/14] OMAP: PM: DMA: Enable runtime pm G, Manjunath Kondaiah
     [not found] ` <20101125112811.GA27574@GLPP-machine>
2010-12-01 19:04   ` [PATCH v5 00/14] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
2010-12-01 19:04     ` G, Manjunath Kondaiah
2010-12-02  2:37     ` Tony Lindgren
2010-12-02  2:37       ` Tony Lindgren

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.