All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver
@ 2010-07-29  9:58 Manjunatha GK
  2010-07-29  9:58 ` [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
                   ` (11 more replies)
  0 siblings, 12 replies; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patch series is refined version of earlier patches posted at:
http://www.spinics.net/lists/linux-omap/index.html#33393

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)

This patch series applies on top of:
git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git
Branch: pm-wip/hwmods-omap4
commit f1c79ab452ed9cf7b5ff6488335c1ddf15d5c92a
Author: Benoit Cousson <b-cousson@ti.com>
Date:   Wed May 12 17:54:37 2010 +0200

    OMAP4: hwmod: Enable omap_hwmod build for OMAP4

Patch series summary:
=====================
Manjunatha GK (10):
  OMAP: DMA: Introduce DMA device attributes
  OMAP2420: DMA: HWMOD: Add hwmod data structures
  OMAP2430: DMA: HWMOD: Add hwmod data structures
  OMAP3: DMA: HWMOD: Add hwmod data structures
  OMAP4: DMA: HWMOD: update OMAP4 data base
  OMAP1: DMA: Introduce DMA driver as platform driver
  OMAP2/3/4: DMA: HWMOD: Device registration
  OMAP: DMA: Convert DMA library into DMA platform Driver
  OMAP: DMA: Implement generic errata handling
  OMAP: DMA: Use DMA device attributes

Venkatraman S (1):
  sDMA: descriptor autoloading feature

 arch/arm/mach-omap1/Makefile               |    2 +-
 arch/arm/mach-omap1/dma.c                  |  446 ++++++++
 arch/arm/mach-omap1/include/mach/dma.h     |  148 +++
 arch/arm/mach-omap2/Makefile               |    2 +-
 arch/arm/mach-omap2/dma.c                  | 1380 +++++++++++++++++++++++++
 arch/arm/mach-omap2/include/mach/dma.h     |  378 +++++++
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   89 ++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   89 ++
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   89 ++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   19 +-
 arch/arm/plat-omap/dma.c                   | 1515 +++-------------------------
 arch/arm/plat-omap/include/plat/dma.h      |  222 +----
 12 files changed, 2850 insertions(+), 1529 deletions(-)
 create mode 100644 arch/arm/mach-omap1/dma.c
 create mode 100644 arch/arm/mach-omap1/include/mach/dma.h
 create mode 100644 arch/arm/mach-omap2/dma.c
 create mode 100644 arch/arm/mach-omap2/include/mach/dma.h


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

* [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
@ 2010-07-29  9:58 ` Manjunatha GK
  2010-07-29 12:35   ` Cousson, Benoit
  2010-07-29  9:58 ` [PATCH 02/11] OMAP2420: DMA: HWMOD: Add hwmod data structures Manjunatha GK
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patches introduces OMAP DMA device attributes for using the same in
DMA platform driver for all OMAP's and HWMOD database(OMAP2PLUS onwards)

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/plat-omap/include/plat/dma.h |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 02232ca..ff60f11 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -398,6 +398,22 @@
 #define DMA_CH_PRIO_HIGH		0x1
 #define DMA_CH_PRIO_LOW			0x0 /* Def */
 
+/* Attributes for OMAP DMA Contrllers */
+#define ENABLE_1510_MODE		(1 << 0)
+#define DMA_LINKED_LCH			(1 << 1)
+#define GLOBAL_PRIORITY			(1 << 2)
+#define RESERVE_CHANNEL			(1 << 3)
+#define SRC_PORT			(2 << 3)
+#define DST_PORT			(2 << 4)
+#define IS_CSSA_32			(2 << 5)
+#define IS_CDSA_32			(2 << 6)
+#define SRC_INDEX			(4 << 6)
+#define DST_INDEX			(4 << 7)
+#define IS_BURST_ONLY4			(4 << 8)
+#define CLEAR_CSR_ON_READ		(4 << 9)
+#define IS_WORD_16			(8 << 9)
+#define IS_RW_PRIORIY			(8 << 0xA)
+
 enum omap_dma_burst_mode {
 	OMAP_DMA_DATA_BURST_DIS = 0,
 	OMAP_DMA_DATA_BURST_4,
@@ -463,6 +479,12 @@ struct omap_dma_channel_params {
 #endif
 };
 
+struct omap_dma_dev_attr {
+	u32 dma_dev_attr;
+	u16 dma_lch_count;
+	u16 dma_chan_count;
+	struct omap_dma_lch *dma_chan;
+};
 
 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.0.4


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

* [PATCH 02/11] OMAP2420: DMA: HWMOD: Add hwmod data structures
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
  2010-07-29  9:58 ` [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
@ 2010-07-29  9:58 ` Manjunatha GK
  2010-07-29  9:58 ` [PATCH 03/11] OMAP2430: " Manjunatha GK
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patch adds OMAP2420 DMA hwmod structures.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   89 ++++++++++++++++++++++++++++
 1 files changed, 89 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 8c90b27..83370e2 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -32,6 +32,7 @@
 static struct omap_hwmod omap2420_mpu_hwmod;
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
+static struct omap_hwmod omap2420_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -136,11 +137,99 @@ static struct omap_hwmod omap2420_mpu_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
+/* 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 = {
+	.dma_dev_attr = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32,
+	.dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT,
+};
+
+static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
+	{ .name = "dma_0", .irq = INT_24XX_SDMA_IRQ0 },
+	{ .name = "dma_1", .irq = INT_24XX_SDMA_IRQ1 },
+	{ .name = "dma_2", .irq = INT_24XX_SDMA_IRQ2 },
+	{ .name = "dma_3", .irq = 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",
+	.prcm = {
+		.omap2 = {
+			/* .clkctrl_reg = NULL, */
+		},
+	},
+	.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),
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 	&omap2420_l3_main_hwmod,
 	&omap2420_l4_core_hwmod,
 	&omap2420_l4_wkup_hwmod,
 	&omap2420_mpu_hwmod,
+	&omap2420_dma_system_hwmod,
 	NULL,
 };
 
-- 
1.7.0.4


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

* [PATCH 03/11] OMAP2430: DMA: HWMOD: Add hwmod data structures
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
  2010-07-29  9:58 ` [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
  2010-07-29  9:58 ` [PATCH 02/11] OMAP2420: DMA: HWMOD: Add hwmod data structures Manjunatha GK
@ 2010-07-29  9:58 ` Manjunatha GK
  2010-07-29  9:58 ` [PATCH 04/11] OMAP3: " Manjunatha GK
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patch adds OMAP2430 DMA hwmod structures.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   89 ++++++++++++++++++++++++++++
 1 files changed, 89 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 c0f3311..5463199 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -32,6 +32,7 @@
 static struct omap_hwmod omap2430_mpu_hwmod;
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
+static struct omap_hwmod omap2430_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -138,11 +139,99 @@ static struct omap_hwmod omap2430_mpu_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 = {
+	.dma_dev_attr = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
+	.dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT,
+};
+
+static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
+	{ .name = "dma_0", .irq = INT_24XX_SDMA_IRQ0 },
+	{ .name = "dma_1", .irq = INT_24XX_SDMA_IRQ1 },
+	{ .name = "dma_2", .irq = INT_24XX_SDMA_IRQ2 },
+	{ .name = "dma_3", .irq = 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",
+	.prcm = {
+		.omap2 = {
+			/*.clkctrl_reg = NULL, */
+		},
+	},
+	.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),
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 	&omap2430_l3_main_hwmod,
 	&omap2430_l4_core_hwmod,
 	&omap2430_l4_wkup_hwmod,
 	&omap2430_mpu_hwmod,
+	&omap2430_dma_system_hwmod,
 	NULL,
 };
 
-- 
1.7.0.4


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

* [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (2 preceding siblings ...)
  2010-07-29  9:58 ` [PATCH 03/11] OMAP2430: " Manjunatha GK
@ 2010-07-29  9:58 ` Manjunatha GK
  2010-08-03 21:56   ` Kevin Hilman
  2010-07-29  9:58 ` [PATCH 05/11] OMAP4: DMA: HWMOD: update OMAP4 data base Manjunatha GK
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patch adds OMAP3 DMA hwmod structures.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   89 ++++++++++++++++++++++++++++
 1 files changed, 89 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 d3bf85b..07f2794 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -36,6 +36,7 @@ static struct omap_hwmod omap3xxx_iva_hwmod;
 static struct omap_hwmod omap3xxx_l3_main_hwmod;
 static struct omap_hwmod omap3xxx_l4_core_hwmod;
 static struct omap_hwmod omap3xxx_l4_per_hwmod;
+static struct omap_hwmod omap3xxx_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -197,6 +198,93 @@ static struct omap_hwmod omap3xxx_iva_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		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dma_dev_attr = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
+	.dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT,
+};;
+
+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 = "dma_0", .irq = INT_24XX_SDMA_IRQ0 },
+	{ .name = "dma_1", .irq = INT_24XX_SDMA_IRQ1 },
+	{ .name = "dma_2", .irq = INT_24XX_SDMA_IRQ2 },
+	{ .name = "dma_3", .irq = 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		= "l4_div_ck",
+	.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	= "l3_div_ck",
+	.prcm = {
+		.omap2 = {
+			/* .clkctrl_reg = NULL, */
+		},
+	},
+	.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),
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l3_main_hwmod,
 	&omap3xxx_l4_core_hwmod,
@@ -204,6 +292,7 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l4_wkup_hwmod,
 	&omap3xxx_mpu_hwmod,
 	&omap3xxx_iva_hwmod,
+	&omap3xxx_dma_system_hwmod,
 	NULL,
 };
 
-- 
1.7.0.4


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

* [PATCH 05/11] OMAP4: DMA: HWMOD: update OMAP4 data base
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (3 preceding siblings ...)
  2010-07-29  9:58 ` [PATCH 04/11] OMAP3: " Manjunatha GK
@ 2010-07-29  9:58 ` Manjunatha GK
  2010-07-29 12:48   ` Cousson, Benoit
  2010-07-29  9:59 ` [PATCH 06/11] OMAP1: DMA: Introduce DMA driver as platform driver Manjunatha GK
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:58 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

The OMAP4 hwmod data base is updated with DMA controller attributes.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 20f5f8c..ee589c5 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"
 
@@ -750,12 +751,19 @@ static struct omap_hwmod_class omap44xx_dma_hwmod_class = {
 	.sysc = &omap44xx_dma_sysc,
 };
 
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dma_dev_attr = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
+	.dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT,
+};
+
 /* 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 },
+	{ .name = "dma_0", .irq = 12 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "dma_1", .irq = 13 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "dma_2", .irq = 14 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "dma_3", .irq = 15 + OMAP44XX_IRQ_GIC_START },
 };
 
 static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
@@ -801,6 +809,7 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = {
 	.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),
 };
 
@@ -4789,7 +4798,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	/* counter class */
 	&omap44xx_counter_32k_hwmod,
 	/* dma class */
-/*	&omap44xx_dma_system_hwmod, */
+	&omap44xx_dma_system_hwmod,
 	/* dmic class */
 /*	&omap44xx_dmic_hwmod, */
 	/* dsp class */
-- 
1.7.0.4


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

* [PATCH 06/11] OMAP1: DMA: Introduce DMA driver as platform driver
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (4 preceding siblings ...)
  2010-07-29  9:58 ` [PATCH 05/11] OMAP4: DMA: HWMOD: update OMAP4 data base Manjunatha GK
@ 2010-07-29  9:59 ` Manjunatha GK
  2010-07-29  9:59 ` [PATCH 07/11] OMAP2/3/4: DMA: HWMOD: Device registration Manjunatha GK
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:59 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patch introduces OMAP1 DMA driver as platform device
and adds support for registering through platform device
layer.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap1/dma.c              |  234 ++++++++++++++++++++++++++++++++
 arch/arm/mach-omap1/include/mach/dma.h |   80 +++++++++++
 2 files changed, 314 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap1/dma.c
 create mode 100644 arch/arm/mach-omap1/include/mach/dma.h

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
new file mode 100644
index 0000000..0df2b82
--- /dev/null
+++ b/arch/arm/mach-omap1/dma.c
@@ -0,0 +1,234 @@
+/*
+ * dma.c - OMAP1/OMAP7xx-specific DMA code
+ *
+ * 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, Inc.
+ * Converted DMA library into platform driver by Manjunatha GK <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/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/io.h>
+#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/device.h>
+
+#include <plat/dma.h>
+#include <plat/tc.h>
+
+#define dma_read(reg)							\
+({									\
+	u32 __val;							\
+	__val = __raw_readw(dma_base + OMAP1_DMA_##reg);		\
+	__val;								\
+})
+
+#define dma_write(val, reg)						\
+({									\
+	__raw_writew((val), dma_base + OMAP1_DMA_##reg);		\
+})
+
+static struct resource res[] __initdata = {
+	[0] = {
+		.start	= OMAP1_DMA_BASE,
+		.end	= OMAP1_DMA_BASE + SZ_2K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name   = "system_dma_0",
+		.start  = INT_DMA_CH0_6,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.name   = "system_dma_1",
+		.start  = INT_DMA_CH1_7,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.name   = "system_dma_2",
+		.start  = INT_DMA_CH2_8,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[4] = {
+		.name   = "system_dma_3",
+		.start  = INT_DMA_CH3,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[5] = {
+		.name   = "system_dma_4",
+		.start  = INT_DMA_CH4,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[6] = {
+		.name   = "system_dma_5",
+		.start  = INT_DMA_CH5,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[7] = {
+		.name   = "system_dma_6",
+		.start  = INT_DMA_LCD,
+		.flags  = IORESOURCE_IRQ,
+	},
+	/* irq's for omap16xx and omap7xx */
+	[8] = {
+		.name   = "system_dma_7",
+		.start  = 53 + IH2_BASE,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[9] = {
+		.name   = "system_dma_8",
+		.start  = 54 + IH2_BASE,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[10] = {
+		.name  = "system_dma_9",
+		.start = 55 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[11] = {
+		.name  = "system_dma_10",
+		.start = 56 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[12] = {
+		.name  = "system_dma_11",
+		.start = 57 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[13] = {
+		.name  = "system_dma_12",
+		.start = 58 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[14] = {
+		.name  = "system_dma_13",
+		.start = 59 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[15] = {
+		.name  = "system_dma_14",
+		.start = 60 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[16] = {
+		.name  = "system_dma_15",
+		.start = 61 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[17] = {
+		.name  = "system_dma_16",
+		.start = 62 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static void __iomem *dma_base;
+
+static int __init omap1_system_dma_init(void)
+{
+	struct platform_device *pdev;
+	struct omap_system_dma_plat_info *pdata;
+	struct omap_dma_dev_attr *d;
+	int ret;
+
+	pdev = platform_device_alloc("system_dma", 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) {
+		pr_err("%s: Unable to add resources for %s%d\n",
+			__func__, pdev->name, pdev->id);
+		goto exit_device_put;
+	}
+
+	pdata = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: Unable to allocate pdata for %s\n",
+			__func__, pdev->name);
+		ret = -ENOMEM;
+		goto exit_device_put;
+	}
+
+	d = pdata->dma_attr;
+
+	/* Valid attributes for omap1 plus processors */
+	d->dma_dev_attr = 0;
+
+	if (cpu_is_omap15xx())
+		d->dma_dev_attr = ENABLE_1510_MODE;
+
+	d->dma_dev_attr			|= SRC_PORT;
+	d->dma_dev_attr			|= DST_PORT;
+	d->dma_dev_attr			|= SRC_INDEX;
+	d->dma_dev_attr			|= DST_INDEX;
+	d->dma_dev_attr			|= IS_BURST_ONLY4;
+	d->dma_dev_attr			|= CLEAR_CSR_ON_READ;
+	d->dma_dev_attr			|= IS_WORD_16;
+
+	d->dma_lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
+
+	if (cpu_is_omap15xx())
+		d->dma_chan_count = 9;
+	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+		if (!(d->dma_dev_attr & ENABLE_1510_MODE))
+			d->dma_chan_count = 16;
+		else
+			d->dma_chan_count = 9;
+	}
+
+	pdata->omap_dma_base		= (void __iomem *)res[0].start;
+	dma_base			= pdata->omap_dma_base;
+
+	d->dma_chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->dma_lch_count), GFP_KERNEL);
+
+	if (!d->dma_chan) {
+		dev_err(&pdev->dev, "%s: Memory allcation failed"
+					"for dma_chan!!!\n", __func__);
+		goto exit_release_pdata;
+	}
+
+	ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+			__func__, pdev->name, pdev->id);
+		goto exit_release_dma_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_release_dma_chan;
+	}
+
+exit_release_dma_chan:
+	kfree(d->dma_chan);
+exit_release_pdata:
+	kfree(pdata);
+exit_device_put:
+	platform_device_put(pdev);
+
+	return ret;
+}
+arch_initcall(omap1_system_dma_init);
diff --git a/arch/arm/mach-omap1/include/mach/dma.h b/arch/arm/mach-omap1/include/mach/dma.h
new file mode 100644
index 0000000..d446cdd
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/dma.h
@@ -0,0 +1,80 @@
+/*
+ *  OMAP DMA controller register offsets.
+ *
+ *  Copyright (C) 2003 Nokia Corporation
+ *  Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ *  Copyright (C) 2010 Texas Instruments
+ *  Converted DMA library into platform driver by Manjunatha GK <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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARCH_OMAP1_DMA_H
+#define __ASM_ARCH_OMAP1_DMA_H
+/* 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
+
+#define OMAP1_LOGICAL_DMA_CH_COUNT	17
+
+/* 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)
+
+/* 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)
+
+#endif /* __ASM_ARCH_OMAP1_DMA_H */
-- 
1.7.0.4

--
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] 29+ messages in thread

* [PATCH 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (5 preceding siblings ...)
  2010-07-29  9:59 ` [PATCH 06/11] OMAP1: DMA: Introduce DMA driver as platform driver Manjunatha GK
@ 2010-07-29  9:59 ` Manjunatha GK
  2010-07-29  9:59 ` [PATCH 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver Manjunatha GK
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:59 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patch converts omap2/3/4 dma driver into platform
devices through using omap hwmod, omap device and runtime pm
frameworks.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap2/dma.c              |  134 ++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/include/mach/dma.h |   80 +++++++++++++++++++
 2 files changed, 214 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/dma.c
 create mode 100644 arch/arm/mach-omap2/include/mach/dma.h

diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
new file mode 100644
index 0000000..da76c34
--- /dev/null
+++ b/arch/arm/mach-omap2/dma.c
@@ -0,0 +1,134 @@
+/*
+ * dma.c - OMAP2 specific DMA code
+ *
+ * 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, Inc.
+ * Converted DMA library into platform driver by Manjunatha GK <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/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/io.h>
+#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/device.h>
+
+#include <plat/irqs.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/dma.h>
+
+#define dma_read(reg)							\
+({									\
+	u32 __val;							\
+	__val = __raw_readl(dma_base + OMAP_DMA4_##reg);		\
+	__val;								\
+})
+
+#define dma_write(val, reg)						\
+({									\
+	__raw_writel((val), dma_base + OMAP_DMA4_##reg);		\
+})
+
+static struct omap_dma_dev_attr *d;
+static void __iomem *dma_base;
+static struct omap_system_dma_plat_info *omap2_pdata;
+static int dma_caps0_status;
+
+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 *user)
+{
+	struct omap_device *od;
+	struct omap_system_dma_plat_info *pdata;
+	struct resource *mem;
+	char *name = "dma";
+
+	pdata = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: Unable to allocate pdata for %s:%s\n",
+			__func__, name, oh->name);
+		return -ENOMEM;
+	}
+
+	pdata->dma_attr		= (struct omap_dma_dev_attr *)oh->dev_attr;
+
+	od = omap_device_build(name, 0, oh, pdata, sizeof(*pdata),
+			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+
+	if (IS_ERR(od)) {
+		pr_err("%s: Cant build omap_device for %s:%s.\n",
+			__func__, name, oh->name);
+		kfree(pdata);
+		return 0;
+	}
+
+	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;
+	}
+
+	/* 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->dma_chan_count = d->dma_lch_count;
+
+	d->dma_chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->dma_lch_count), GFP_KERNEL);
+
+	if (!d->dma_chan) {
+		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+		return -ENOMEM;
+	}
+
+	omap2_pdata		= pdata;
+	dma_caps0_status	= dma_read(CAPS_0);
+
+	return 0;
+}
+
+static int __init omap2_system_dma_init(void)
+{
+	int ret;
+
+	ret = omap_hwmod_for_each_by_class("dma",
+			omap2_system_dma_init_dev, NULL);
+
+	return ret;
+}
+arch_initcall(omap2_system_dma_init);
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..3eca7d8
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -0,0 +1,80 @@
+/*
+ *  OMAP DMA controller register offsets.
+ *
+ *  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
+ *  Converted DMA library into platform driver by Manjunatha GK <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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARCH_OMAP2_DMA_H
+#define __ASM_ARCH_OMAP2_DMA_H
+
+/* OMAP2 Plus register offset's */
+#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
+
+/* Should be part of hwmod data base ? */
+#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT	32	/* REVISIT: Is this 32 + 2? */
+
+/* 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 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)
+
+#endif /* __ASM_ARCH_OMAP2_DMA_H */
-- 
1.7.0.4

--
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] 29+ messages in thread

* [PATCH 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (6 preceding siblings ...)
  2010-07-29  9:59 ` [PATCH 07/11] OMAP2/3/4: DMA: HWMOD: Device registration Manjunatha GK
@ 2010-07-29  9:59 ` Manjunatha GK
  2010-07-29  9:59 ` [PATCH 09/11] OMAP: DMA: Implement generic errata handling Manjunatha GK
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:59 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patch converts DMA library into DMA platform driver and make use
of platform data provided by HWMOD data base for OMAP2PLUS onwards.
For OMAP1 processors, the DMA driver in mach-omap uses resource structures
for getting platform data.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap1/Makefile           |    2 +-
 arch/arm/mach-omap1/include/mach/dma.h |   66 ++++++++++
 arch/arm/mach-omap2/Makefile           |    2 +-
 arch/arm/mach-omap2/include/mach/dma.h |   83 ++++++++++++
 arch/arm/plat-omap/dma.c               |  224 ++++++++++++++++----------------
 arch/arm/plat-omap/include/plat/dma.h  |  157 ++---------------------
 6 files changed, 271 insertions(+), 263 deletions(-)

diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index fd4df71..a159af4 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/include/mach/dma.h b/arch/arm/mach-omap1/include/mach/dma.h
index d446cdd..1eb0d31 100644
--- a/arch/arm/mach-omap1/include/mach/dma.h
+++ b/arch/arm/mach-omap1/include/mach/dma.h
@@ -77,4 +77,70 @@
 #define OMAP1_DMA_CCR2(n)		(0x40 * (n) + 0x24)
 #define OMAP1_DMA_LCH_CTRL(n)		(0x40 * (n) + 0x2a)
 
+/* Dummy defines to support multi omap code */
+/* Channel specific registers */
+#define OMAP_DMA4_CCR(n)		0
+#define OMAP_DMA4_CSDP(n)		0
+#define OMAP_DMA4_CEN(n)		0
+#define OMAP_DMA4_CFN(n)		0
+#define OMAP_DMA4_COLOR(n)		0
+#define OMAP_DMA4_CSSA(n)		0
+#define OMAP_DMA4_CSEI(n)		0
+#define OMAP_DMA4_CSFI(n)		0
+#define OMAP_DMA4_CDSA(n)		0
+#define OMAP_DMA4_CDEI(n)		0
+#define OMAP_DMA4_CDFI(n)		0
+#define OMAP_DMA4_CSR(n)		0
+#define OMAP_DMA4_CICR(n)		0
+#define OMAP_DMA4_CLNK_CTRL(n)		0
+#define OMAP_DMA4_CH_BASE(n)		0
+#define OMAP_DMA4_CDAC(n)		0
+#define OMAP_DMA4_CSAC(n)		0
+
+/* Common registers */
+#define OMAP_DMA4_IRQENABLE_L0		0
+#define OMAP_DMA4_OCP_SYSCONFIG		0
+#define OMAP_DMA4_GCR			0
+#define OMAP_DMA4_IRQSTATUS_L0		0
+#define OMAP_DMA4_CAPS_2		0
+#define OMAP_DMA4_CAPS_3		0
+#define OMAP_DMA4_CAPS_4		0
+#define OMAP_DMA4_REVISION		0
+
+#define OMAP_DMA4_CCR2(n)		0
+#define OMAP_DMA4_LCH_CTRL(n)		0
+#define OMAP_DMA4_COLOR_L(n)		0
+#define OMAP_DMA4_COLOR_U(n)		0
+#define OMAP1_DMA_COLOR(n)		0
+#define OMAP_DMA4_CSSA_U(n)		0
+#define OMAP_DMA4_CSSA_L(n)		0
+#define OMAP1_DMA_CSSA(n)		0
+#define OMAP_DMA4_CDSA_U(n)		0
+#define OMAP_DMA4_CDSA_L(n)		0
+#define OMAP1_DMA_CDSA(n)		0
+#define OMAP_DMA4_CPC(n)		0
+
+#define OMAP1_DMA_IRQENABLE_L0		0
+#define OMAP1_DMA_IRQENABLE_L0		0
+#define OMAP1_DMA_IRQSTATUS_L0		0
+#define OMAP1_DMA_OCP_SYSCONFIG		0
+#define OMAP_DMA4_HW_ID			0
+#define OMAP_DMA4_CAPS_0_U		0
+#define OMAP_DMA4_CAPS_0_L		0
+#define OMAP_DMA4_CAPS_1_U		0
+#define OMAP_DMA4_CAPS_1_L		0
+#define OMAP_DMA4_GSCR			0
+#define OMAP1_DMA_REVISION		0
+
+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;
+};
+
 #endif /* __ASM_ARCH_OMAP1_DMA_H */
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index ae5f36f..3c5557a 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o dma.o
 
 omap-2-3-common				= irq.o sdrc.o
 hwmod-common				= omap_hwmod.o \
diff --git a/arch/arm/mach-omap2/include/mach/dma.h b/arch/arm/mach-omap2/include/mach/dma.h
index 3eca7d8..22f4b41 100644
--- a/arch/arm/mach-omap2/include/mach/dma.h
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -77,4 +77,87 @@
 #define OMAP_DMA4_CNDP(n)		(0x60 * (n) + 0xd4)
 #define OMAP_DMA4_CCDN(n)		(0x60 * (n) + 0xd8)
 
+
+/* Dummy defines for support multi omap code */
+/* Common registers */
+#define OMAP1_DMA_GCR				0
+#define OMAP1_DMA_HW_ID				0
+#define OMAP1_DMA_CAPS_0_U			0
+#define OMAP1_DMA_CAPS_0_L			0
+#define OMAP1_DMA_CAPS_1_U			0
+#define OMAP1_DMA_CAPS_1_L			0
+#define OMAP1_DMA_CAPS_2			0
+#define OMAP1_DMA_CAPS_3			0
+#define OMAP1_DMA_CAPS_4			0
+#define OMAP1_DMA_GSCR				0
+
+/* Channel specific registers */
+#define OMAP1_DMA_CH_BASE(n)			0
+#define OMAP1_DMA_CCR(n)			0
+#define OMAP1_DMA_CSDP(n)			0
+#define OMAP1_DMA_CCR2(n)			0
+#define OMAP1_DMA_CEN(n)			0
+#define OMAP1_DMA_CFN(n)			0
+#define OMAP1_DMA_LCH_CTRL(n)			0
+#define OMAP1_DMA_COLOR_L(n)			0
+#define OMAP1_DMA_COLOR_U(n)			0
+#define OMAP1_DMA_CSSA_U(n)			0
+#define OMAP1_DMA_CSSA_L(n)			0
+#define OMAP1_DMA_CSEI(n)			0
+#define OMAP1_DMA_CSFI(n)			0
+#define OMAP1_DMA_CDSA_U(n)			0
+#define OMAP1_DMA_CDSA_L(n)			0
+#define OMAP1_DMA_CDEI(n)			0
+#define OMAP1_DMA_CDFI(n)			0
+#define OMAP1_DMA_CSR(n)			0
+#define OMAP1_DMA_CICR(n)			0
+#define OMAP1_DMA_CLNK_CTRL(n)			0
+#define OMAP1_DMA_CPC(n)			0
+#define OMAP1_DMA_CDAC(n)			0
+#define OMAP1_DMA_CSAC(n)			0
+#define OMAP1_DMA_CCEN(n)			0
+#define OMAP1_DMA_CCFN(n)			0
+
+#define OMAP_DMA4_CCR2(n)			0
+#define OMAP_DMA4_LCH_CTRL(n)			0
+#define OMAP_DMA4_COLOR_L(n)			0
+#define OMAP_DMA4_COLOR_U(n)			0
+#define OMAP1_DMA_COLOR(n)			0
+#define OMAP_DMA4_CSSA_U(n)			0
+#define OMAP_DMA4_CSSA_L(n)			0
+#define OMAP1_DMA_CSSA(n)			0
+#define OMAP_DMA4_CDSA_U(n)			0
+#define OMAP_DMA4_CDSA_L(n)			0
+#define OMAP1_DMA_CDSA(n)			0
+#define OMAP_DMA4_CPC(n)			0
+
+#define OMAP1_DMA_IRQENABLE_L0			0
+#define OMAP1_DMA_IRQSTATUS_L0			0
+#define OMAP1_DMA_OCP_SYSCONFIG			0
+#define OMAP1_DMA_OCP_SYSCONFIG			0
+#define OMAP_DMA4_HW_ID				0
+#define OMAP_DMA4_CAPS_0_U			0
+#define OMAP_DMA4_CAPS_0_L			0
+#define OMAP_DMA4_CAPS_1_U			0
+#define OMAP_DMA4_CAPS_1_L			0
+#define OMAP_DMA4_GSCR				0
+#define OMAP1_DMA_REVISION			0
+
+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;
+};
+
 #endif /* __ASM_ARCH_OMAP2_DMA_H */
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index f7f571e..4627e84 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -15,6 +15,9 @@
  *
  * Support functions for the OMAP internal DMA channels.
  *
+ * Copyright (C) 2010 Texas Instruments
+ * Converted DMA library into DMA platform driver.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -60,27 +63,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;
@@ -136,15 +118,10 @@ 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 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 void __iomem *omap_dma_base;
+static struct omap_system_dma_plat_info *p;
+static struct omap_dma_dev_attr *d;
 
 static inline void disable_lnk(int lch);
 static void omap_disable_channel_irq(int lch);
@@ -959,7 +936,7 @@ void omap_start_dma(int 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_chan_count];
 
 		dma_chan_link_map[lch] = 1;
 		/* Set the link register of the first channel */
@@ -1020,7 +997,7 @@ void omap_stop_dma(int 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_chan_count];
 
 		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
 		do {
@@ -2036,57 +2013,56 @@ void omap_dma_global_context_restore(void)
 			omap_clear_dma(ch);
 }
 
-/*----------------------------------------------------------------------------*/
-
-static int __init omap_init_dma(void)
+static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 {
-	unsigned long base;
-	int ch, r;
+	struct omap_system_dma_plat_info *pdata = pdev->dev.platform_data;
+	struct resource *mem;
+	int ch, ret = 0;
+	int dma_irq;
+	char irq_name[14];
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: System DMA initialized without"
+			"platform data\n", __func__);
+		return -EINVAL;
+	}
 
-	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;
+	p = pdata;
+	d = p->dma_attr;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+		return -EINVAL;
 	}
 
-	omap_dma_base = ioremap(base, SZ_4K);
-	BUG_ON(!omap_dma_base);
+	omap_dma_base = ioremap(mem->start, resource_size(mem));
+	if (!omap_dma_base) {
+		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
+		ret = -ENOMEM;
+		goto exit_release_region;
+	}
 
 	if (cpu_class_is_omap2() && omap_dma_reserve_channels
 			&& (omap_dma_reserve_channels <= dma_lch_count))
-		dma_lch_count = omap_dma_reserve_channels;
+		d->dma_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->dma_lch_count;
+	dma_chan_count		= d->dma_chan_count;
+	dma_chan		= d->dma_chan;
 
 	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;
 		}
 	}
+	enable_1510_mode = d->dma_dev_attr & ENABLE_1510_MODE;
 
 	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));
@@ -2104,21 +2080,14 @@ static int __init omap_init_dma(void)
 			w = dma_read(GSCR);
 			w |= 1 << 3;
 			dma_write(w, GSCR);
-			dma_chan_count = 16;
-		} else
-			dma_chan_count = 9;
+		}
 	} else if (cpu_class_is_omap2()) {
 		u8 revision = dma_read(REVISION) & 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())
@@ -2135,19 +2104,29 @@ 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],
+			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_unmap;
+			}
+			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;
+				printk(KERN_ERR "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;
+				}
 			}
 		}
 	}
@@ -2157,46 +2136,65 @@ 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);
-		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);
-		/* 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, "dma_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)) {
+		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;
+	}
+
+	dev_info(&pdev->dev, "System DMA registered\n");
 	return 0;
 
-out_free:
+exit_dma_chan:
 	kfree(dma_chan);
+exit_unmap:
+	iounmap(omap_dma_base);
+exit_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+	return ret;
+}
 
-out_unmap:
+static int __devexit omap_system_dma_remove(struct platform_device *pdev)
+{
+	struct resource *mem;
 	iounmap(omap_dma_base);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	return 0;
+}
+
+static struct platform_driver omap_system_dma_driver = {
+	.probe		= omap_system_dma_probe,
+	.remove		= omap_system_dma_remove,
+	.driver		= {
+		.name	= "dma"
+	},
+};
 
-	return r;
+static int __init omap_system_dma_init(void)
+{
+	return platform_driver_register(&omap_system_dma_driver);
+}
+
+arch_initcall(omap_system_dma_init);
+
+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 ff60f11..92c348f 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -21,142 +21,11 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
+#include <linux/platform_device.h>
+
 /* Move omap4 specific defines to dma-44xx.h */
 #include "dma-44xx.h"
 
-/* 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
@@ -372,21 +241,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
-
 /* Chaining modes*/
 #ifndef CONFIG_ARCH_OMAP1
 #define OMAP_DMA_STATIC_CHAIN		0x1
@@ -479,6 +333,7 @@ struct omap_dma_channel_params {
 #endif
 };
 
+#include <mach/dma.h>
 struct omap_dma_dev_attr {
 	u32 dma_dev_attr;
 	u16 dma_lch_count;
@@ -486,6 +341,12 @@ struct omap_dma_dev_attr {
 	struct omap_dma_lch *dma_chan;
 };
 
+/* System DMA platform data structure */
+struct omap_system_dma_plat_info {
+	struct omap_dma_dev_attr *dma_attr;
+	void __iomem *omap_dma_base;
+};
+
 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,
 			void (*callback)(int lch, u16 ch_status, void *data),
-- 
1.7.0.4


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

* [PATCH 09/11] OMAP: DMA: Implement generic errata handling
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (7 preceding siblings ...)
  2010-07-29  9:59 ` [PATCH 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver Manjunatha GK
@ 2010-07-29  9:59 ` Manjunatha GK
  2010-07-29  9:59 ` [PATCH 10/11] OMAP: DMA: Use DMA device attributes Manjunatha GK
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:59 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

This patch introduces generic way of handling all OMAP DMA
errata's which are applicable for OMAP1 and OMAP2PLUS processors.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap1/dma.c             |    6 ++++
 arch/arm/mach-omap2/dma.c             |   34 +++++++++++++++++++++++
 arch/arm/plat-omap/dma.c              |   48 ++++++++++++++++++--------------
 arch/arm/plat-omap/include/plat/dma.h |    9 ++++++
 4 files changed, 76 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 0df2b82..00ef40f 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -170,6 +170,12 @@ static int __init omap1_system_dma_init(void)
 		goto exit_device_put;
 	}
 
+	/* Errata handling for all omap1 plus processors */
+	pdata->errata			= 0;
+
+	if (cpu_class_is_omap1() && !cpu_is_omap15xx())
+		pdata->errata		|= OMAP3_3_ERRATUM;
+
 	d = pdata->dma_attr;
 
 	/* Valid attributes for omap1 plus processors */
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index da76c34..72abfec 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -80,6 +80,40 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *user)
 
 	pdata->dma_attr		= (struct omap_dma_dev_attr *)oh->dev_attr;
 
+	/* Handling Errata's for all OMAP2PLUS processors */
+	pdata->errata			= 0;
+
+	if (cpu_is_omap242x() ||
+		(cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0))
+		pdata->errata		= DMA_CHAINING_ERRATA;
+
+	/*
+	 * Errata: On ES2.0 BUFFERING disable must be set.
+	 * This will always fail on ES1.0
+	 */
+	if (cpu_is_omap24xx())
+		pdata->errata		|= DMA_BUFF_DISABLE_ERRATA;
+
+	/*
+	 * Errata: OMAP2: sDMA Channel is not disabled
+	 * after a transaction error. So we explicitely
+	 * disable the channel
+	 */
+	if (cpu_class_is_omap2())
+		pdata->errata		|= DMA_CH_DISABLE_ERRATA;
+
+	/* Errata: OMAP3 :
+	 * 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))
+		pdata->errata		|= DMA_IRQ_STATUS_ERRATA;
+
+	/* Errata3.3: Applicable for all omap2 plus */
+	pdata->errata			|= OMAP3_3_ERRATUM;
+
 	od = omap_device_build(name, 0, oh, pdata, sizeof(*pdata),
 			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
 
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 4627e84..b31c88f 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -182,6 +182,25 @@ static inline void set_gdma_dev(int req, int dev)
 #define set_gdma_dev(req, dev)	do {} while (0)
 #endif
 
+static void dma_ocpsysconfig_errata(u32 *sys_cf, bool flag)
+{
+	u32 l;
+
+	/*
+	 * DMA Errata:
+	 * Special programming model needed to disable DMA before end of block
+	 */
+	if (!flag) {
+		*sys_cf = dma_read(OCP_SYSCONFIG);
+		l = *sys_cf;
+		/* Middle mode reg set no Standby */
+		l &= ~((1 << 12)|(1 << 13));
+		dma_write(l, OCP_SYSCONFIG);
+	} else
+		/* put back old value */
+		dma_write(*sys_cf, OCP_SYSCONFIG);
+}
+
 /* Omap1 only */
 static void clear_lch_regs(int lch)
 {
@@ -958,22 +977,16 @@ 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 */
+	if (p->errata & DMA_CHAINING_ERRATA)
 		dma_write(lch, CLNK_CTRL(lch));
-	}
 
 	omap_enable_channel_irq(lch);
 
 	l = dma_read(CCR(lch));
 
-	/*
-	 * Errata: On ES2.0 BUFFERING disable must be set.
-	 * This will always fail on ES1.0
-	 */
-	if (cpu_is_omap24xx())
+	if (p->errata & DMA_BUFF_DISABLE_ERRATA)
 		l |= OMAP_DMA_CCR_EN;
 
 	l |= OMAP_DMA_CCR_EN;
@@ -1647,7 +1660,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
 {
 	int *channels;
 	u32 l, i;
-	u32 sys_cf;
+	u32 get_sysconfig;
 
 	/* Check for input params */
 	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
@@ -1662,15 +1675,8 @@ 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);
-	l = sys_cf;
-	/* Middle mode reg set no Standby */
-	l &= ~((1 << 12)|(1 << 13));
-	dma_write(l, OCP_SYSCONFIG);
+	if (p->errata & DMA_SYSCONFIG_ERRATA)
+		dma_ocpsysconfig_errata(&get_sysconfig, false);
 
 	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
 
@@ -1689,8 +1695,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);
+	if (p->errata & DMA_SYSCONFIG_ERRATA)
+		dma_ocpsysconfig_errata(&get_sysconfig, true);
 
 	return 0;
 }
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 92c348f..6d1fee0 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -268,6 +268,14 @@
 #define IS_WORD_16			(8 << 9)
 #define IS_RW_PRIORIY			(8 << 0xA)
 
+/* Errata Definitions */
+#define	DMA_CHAINING_ERRATA		(1 << 0)
+#define	DMA_BUFF_DISABLE_ERRATA		(1 << 1)
+#define	OMAP3_3_ERRATUM			(1 << 2)
+#define	DMA_SYSCONFIG_ERRATA		(1 << 3)
+#define	DMA_CH_DISABLE_ERRATA		(1 << 4)
+#define	DMA_IRQ_STATUS_ERRATA		(1 << 5)
+
 enum omap_dma_burst_mode {
 	OMAP_DMA_DATA_BURST_DIS = 0,
 	OMAP_DMA_DATA_BURST_4,
@@ -345,6 +353,7 @@ struct omap_dma_dev_attr {
 struct omap_system_dma_plat_info {
 	struct omap_dma_dev_attr *dma_attr;
 	void __iomem *omap_dma_base;
+	u32 errata;
 };
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
-- 
1.7.0.4


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

* [PATCH 10/11] OMAP: DMA: Use DMA device attributes
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (8 preceding siblings ...)
  2010-07-29  9:59 ` [PATCH 09/11] OMAP: DMA: Implement generic errata handling Manjunatha GK
@ 2010-07-29  9:59 ` Manjunatha GK
  2010-07-29  9:59 ` [PATCH 11/11] sDMA: descriptor autoloading feature Manjunatha GK
  2010-08-11  7:43 ` [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah
  11 siblings, 0 replies; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:59 UTC (permalink / raw)
  To: linux-omap
  Cc: Benoit Cousson, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

Existing DMA API's are using cpu_is_xxxx checks for differenciating
omap1 and omap2plus code.

This patch replaces cpu_is_xxxx checks with DMA device attributes and
also moves API's which are OMAP1 and OMAP2plus specific into respective
mach-omap dma driver files.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap1/dma.c              |  227 +++++-
 arch/arm/mach-omap2/dma.c              |  966 ++++++++++++++++++++++-
 arch/arm/mach-omap2/include/mach/dma.h |   21 +
 arch/arm/plat-omap/dma.c               | 1384 +++-----------------------------
 arch/arm/plat-omap/include/plat/dma.h  |   36 +-
 5 files changed, 1305 insertions(+), 1329 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 00ef40f..eadc160 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -140,13 +140,177 @@ static struct resource res[] __initdata = {
 };
 
 static void __iomem *dma_base;
+static struct omap_dma_lch *dma_chan;
+struct omap_dma_dev_attr *d;
+
+u32 enable_1510_mode;
+
+#define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
+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 omap1_clear_lch_regs(int lch)
+{
+	int i;
+	void __iomem *lch_base = dma_base + OMAP1_DMA_CH_BASE(lch);
+
+	for (i = 0; i < 0x2c; i += 2)
+		__raw_writew(0, lch_base + i);
+}
+
+static inline void omap1_enable_channel_irq(int lch)
+{
+	u32 status;
+
+	status = dma_read(CSR(lch));
+	dma_write(dma_chan[lch].enabled_irqs, CICR(lch));
+}
+
+static void omap1_disable_channel_irq(int lch)
+{
+	return;
+}
+
+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;
+
+	l = dma_read(CLNK_CTRL(lch));
+
+	/* Disable interrupts */
+	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 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 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->dma_dev_attr & 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);
+
+void omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
+{
+	return;
+}
+EXPORT_SYMBOL(omap_dma_set_global_params);
 
 static int __init omap1_system_dma_init(void)
 {
 	struct platform_device *pdev;
 	struct omap_system_dma_plat_info *pdata;
-	struct omap_dma_dev_attr *d;
-	int ret;
+	int dma_irq, ret, ch;
+	char irq_name[14];
+	int irq_rel;
 
 	pdev = platform_device_alloc("system_dma", 0);
 	if (!pdev) {
@@ -155,11 +319,19 @@ static int __init omap1_system_dma_init(void)
 		return -ENOMEM;
 	}
 
+	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_pdev;
+	}
+
 	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
 	if (ret) {
 		pr_err("%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
-		goto exit_device_put;
+		goto exit_pdev;
 	}
 
 	pdata = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
@@ -167,7 +339,7 @@ static int __init omap1_system_dma_init(void)
 		dev_err(&pdev->dev, "%s: Unable to allocate pdata for %s\n",
 			__func__, pdev->name);
 		ret = -ENOMEM;
-		goto exit_device_put;
+		goto exit_pdev;
 	}
 
 	/* Errata handling for all omap1 plus processors */
@@ -183,6 +355,7 @@ static int __init omap1_system_dma_init(void)
 
 	if (cpu_is_omap15xx())
 		d->dma_dev_attr = ENABLE_1510_MODE;
+	enable_1510_mode		= d->dma_dev_attr & ENABLE_1510_MODE;
 
 	d->dma_dev_attr			|= SRC_PORT;
 	d->dma_dev_attr			|= DST_PORT;
@@ -194,6 +367,19 @@ static int __init omap1_system_dma_init(void)
 
 	d->dma_lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
 
+	pdata->enable_channel_irq		= omap1_enable_channel_irq;
+	pdata->disable_channel_irq		= omap1_disable_channel_irq;
+	pdata->enable_lnk			= omap1_enable_lnk;
+	pdata->disable_lnk			= omap1_disable_lnk;
+	pdata->clear_lch_regs		= omap1_clear_lch_regs;
+	if (cpu_is_omap16xx()) {
+		pdata->get_gdma_dev		= omap1_get_gdma_dev;
+		pdata->set_gdma_dev		= omap1_set_gdma_dev;
+	}
+	pdata->enable_irq_lch		= NULL;
+	pdata->disable_irq_lch		= NULL;
+	pdata->set_dma_chain_ch		= NULL;
+
 	if (cpu_is_omap15xx())
 		d->dma_chan_count = 9;
 	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
@@ -203,38 +389,53 @@ static int __init omap1_system_dma_init(void)
 			d->dma_chan_count = 9;
 	}
 
+	for (ch = 0; ch < d->dma_chan_count; ch++) {
+		if (ch >= 6 && enable_1510_mode)
+			continue;
+		ret = request_irq(dma_irq, irq_handler, 0, "DMA",
+							(void *) (ch + 1));
+		if (ret != 0)
+			goto exit_pdata;
+	}
+
 	pdata->omap_dma_base		= (void __iomem *)res[0].start;
 	dma_base			= pdata->omap_dma_base;
-
 	d->dma_chan = kzalloc(sizeof(struct omap_dma_lch) *
 					(d->dma_lch_count), GFP_KERNEL);
-
 	if (!d->dma_chan) {
 		dev_err(&pdev->dev, "%s: Memory allcation failed"
 					"for dma_chan!!!\n", __func__);
-		goto exit_release_pdata;
+		goto exit_pdata;
 	}
+	dma_chan = d->dma_chan;
 
 	ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
-		goto exit_release_dma_chan;
+		goto exit_pdata;
 	}
 	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_release_dma_chan;
+		goto exit_dma_chan;
 	}
 
-exit_release_dma_chan:
+exit_dma_chan:
 	kfree(d->dma_chan);
-exit_release_pdata:
+exit_pdata:
+	printk(KERN_ERR "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));
+	}
 	kfree(pdata);
-exit_device_put:
+exit_pdev:
 	platform_device_put(pdev);
-
 	return ret;
 }
 arch_initcall(omap1_system_dma_init);
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 72abfec..390c428 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -50,9 +50,70 @@
 	__raw_writel((val), dma_base + OMAP_DMA4_##reg);		\
 })
 
+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;
+static struct omap_dma_lch *dma_chan;
+
+static int dma_chan_count;
+
+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 };
+
+/* 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)
+
 static struct omap_dma_dev_attr *d;
 static void __iomem *dma_base;
-static struct omap_system_dma_plat_info *omap2_pdata;
+static struct omap_system_dma_plat_info *p;
 static int dma_caps0_status;
 
 static struct omap_device_pm_latency omap2_dma_latency[] = {
@@ -63,6 +124,874 @@ static struct omap_device_pm_latency omap2_dma_latency[] = {
 	},
 };
 
+static inline void omap2_enable_irq_lch(int lch)
+{
+	u32 val;
+
+	val = dma_read(IRQENABLE_L0);
+	val |= 1 << lch;
+	dma_write(val, IRQENABLE_L0);
+}
+
+static inline void omap2_disable_irq_lch(int lch)
+{
+	u32 val;
+
+	val = dma_read(IRQENABLE_L0);
+	val &= ~(1 << lch);
+	dma_write(val, IRQENABLE_L0);
+}
+
+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 dma_ocpsysconfig_errata(u32 *sys_cf, bool flag)
+{
+	u32 l;
+
+	/*
+	 * DMA Errata:
+	 * Special programming model needed to disable DMA before end of block
+	 */
+	if (!flag) {
+		*sys_cf = dma_read(OCP_SYSCONFIG);
+		l = *sys_cf;
+		/* Middle mode reg set no Standby */
+		l &= ~((1 << 12)|(1 << 13));
+		dma_write(l, OCP_SYSCONFIG);
+	} else
+		/* put back old value */
+		dma_write(*sys_cf, OCP_SYSCONFIG);
+}
+
+void omap_dma_global_context_save(void)
+{
+	omap_dma_global_context.dma_irqenable_l0 =
+		dma_read(IRQENABLE_L0);
+	omap_dma_global_context.dma_ocp_sysconfig =
+		dma_read(OCP_SYSCONFIG);
+	omap_dma_global_context.dma_gcr = dma_read(GCR);
+}
+
+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_ocp_sysconfig,
+		OCP_SYSCONFIG);
+	dma_write(omap_dma_global_context.dma_irqenable_l0,
+		IRQENABLE_L0);
+
+	/*
+	 * 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))
+		dma_write(0x3 , IRQSTATUS_L0);
+
+	for (ch = 0; ch < dma_chan_count; ch++)
+		if (dma_chan[ch].dev_id != -1)
+			omap_clear_dma(ch);
+}
+
+/* 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));
+}
+
+static void set_dma_chain_ch(int free_ch)
+{
+	dma_chan[free_ch].chain_id       = -1;
+	dma_chan[free_ch].next_linked_ch = -1;
+}
+
+/**
+ * @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 : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ *		Failure : -EINVAL
+ */
+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 : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ *		Failure : -EINVAL
+ */
+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 : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ *		Failure : -EINVAL
+ */
+int omap_stop_dma_chain_transfers(int chain_id)
+{
+	int *channels;
+	u32 l, i;
+	u32 get_sysconfig;
+
+	/* 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 (p->errata & DMA_SYSCONFIG_ERRATA)
+		dma_ocpsysconfig_errata(&get_sysconfig, false);
+
+	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 (p->errata & DMA_SYSCONFIG_ERRATA)
+		dma_ocpsysconfig_errata(&get_sysconfig, true);
+
+	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 : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ *		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 : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ *		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 : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ *		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);
+
+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);
+
+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);
+		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 (cpu_class_is_omap2()) {
+			/*
+			 * Errata: sDMA Channel is not disabled
+			 * after a transaction error. So we explicitely
+			 * disable the channel
+			 */
+			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);
+
+	/* 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);
+	if (val == 0) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING "Spurious DMA IRQ\n");
+		return IRQ_HANDLED;
+	}
+	enable_reg = dma_read(IRQENABLE_L0);
+	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
+};
+
+/**
+ * @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);
+}
+EXPORT_SYMBOL(omap_dma_set_global_params);
+
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *user)
 {
@@ -70,6 +999,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *user)
 	struct omap_system_dma_plat_info *pdata;
 	struct resource *mem;
 	char *name = "dma";
+	int dma_irq, ret;
 
 	pdata = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
 	if (!pdata) {
@@ -114,6 +1044,18 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *user)
 	/* Errata3.3: Applicable for all omap2 plus */
 	pdata->errata			|= OMAP3_3_ERRATUM;
 
+	p			= pdata;
+	p->enable_irq_lch	= omap2_enable_irq_lch;
+	p->disable_irq_lch	= omap2_disable_irq_lch;
+	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->set_dma_chain_ch	= set_dma_chain_ch;
+	p->clear_lch_regs	= NULL;
+	p->get_gdma_dev		= NULL;
+	p->set_gdma_dev		= NULL;
+
 	od = omap_device_build(name, 0, oh, pdata, sizeof(*pdata),
 			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
 
@@ -136,21 +1078,37 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *user)
 		return -ENOMEM;
 	}
 
+	dma_irq = platform_get_irq_byname(&od->pdev, "dma_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->dma_chan_count = d->dma_lch_count;
+	d->dma_chan_count	= d->dma_lch_count;
+	dma_chan_count		= d->dma_chan_count;
 
 	d->dma_chan = kzalloc(sizeof(struct omap_dma_lch) *
-					(d->dma_lch_count), GFP_KERNEL);
+					(dma_chan_count), GFP_KERNEL);
 
 	if (!d->dma_chan) {
 		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
 		return -ENOMEM;
 	}
 
-	omap2_pdata		= pdata;
+	dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
+						dma_chan_count, GFP_KERNEL);
+	if (!dma_linked_lch) {
+		kfree(d->dma_chan);
+		return -ENOMEM;
+	}
+
+	dma_chan		= d->dma_chan;
+
 	dma_caps0_status	= dma_read(CAPS_0);
 
 	return 0;
diff --git a/arch/arm/mach-omap2/include/mach/dma.h b/arch/arm/mach-omap2/include/mach/dma.h
index 22f4b41..f3e21d5 100644
--- a/arch/arm/mach-omap2/include/mach/dma.h
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -160,4 +160,25 @@ struct omap_dma_lch {
 	int status;
 };
 
+/* 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 b31c88f..643f538 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -35,101 +35,25 @@
 #include <linux/slab.h>
 
 #include <asm/system.h>
+
 #include <mach/hardware.h>
-#include <plat/dma.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 int enable_1510_mode;
-
-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 spinlock_t dma_chan_lock;
-static struct omap_dma_lch *dma_chan;
 
 static void __iomem *omap_dma_base;
+
+static struct omap_dma_lch *dma_chan;
 static struct omap_system_dma_plat_info *p;
 static struct omap_dma_dev_attr *d;
 
-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__);
-
 #define dma_read(reg)							\
 ({									\
 	u32 __val;							\
@@ -148,75 +72,12 @@ static inline void omap_enable_channel_irq(int lch);
 		__raw_writel((val), omap_dma_base + OMAP_DMA4_##reg);	\
 })
 
-#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
-
-static void dma_ocpsysconfig_errata(u32 *sys_cf, bool flag)
-{
-	u32 l;
-
-	/*
-	 * DMA Errata:
-	 * Special programming model needed to disable DMA before end of block
-	 */
-	if (!flag) {
-		*sys_cf = dma_read(OCP_SYSCONFIG);
-		l = *sys_cf;
-		/* Middle mode reg set no Standby */
-		l &= ~((1 << 12)|(1 << 13));
-		dma_write(l, OCP_SYSCONFIG);
-	} else
-		/* put back old value */
-		dma_write(*sys_cf, OCP_SYSCONFIG);
-}
-
-/* Omap1 only */
-static void clear_lch_regs(int lch)
-{
-	int i;
-	void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch);
-
-	for (i = 0; i < 0x2c; i += 2)
-		__raw_writew(0, lch_base + i);
-}
-
 void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
 	unsigned long reg;
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & IS_WORD_16) {
 		switch (dst_port) {
 		case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
 			reg = OMAP_TC_OCPT1_PRIOR;
@@ -238,9 +99,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 = dma_read(CCR(lch));
@@ -264,7 +123,7 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 	l |= data_type;
 	dma_write(l, CSDP(lch));
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & IS_WORD_16) {
 		u16 ccr;
 
 		ccr = dma_read(CCR(lch));
@@ -278,9 +137,7 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 		if (sync_mode == OMAP_DMA_SYNC_BLOCK)
 			ccr |= 1 << 2;
 		dma_write(ccr, CCR2(lch));
-	}
-
-	if (cpu_class_is_omap2() && dma_trigger) {
+	} else if (dma_trigger) {
 		u32 val;
 
 		val = dma_read(CCR(lch));
@@ -315,9 +172,9 @@ 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());
+	BUG_ON(enable_1510_mode);
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & IS_WORD_16) {
 		u16 w;
 
 		w = dma_read(CCR2(lch));
@@ -346,9 +203,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 			w |= 1;		/* Channel type G */
 		}
 		dma_write(w, LCH_CTRL(lch));
-	}
-
-	if (cpu_class_is_omap2()) {
+	} else {
 		u32 val;
 
 		val = dma_read(CCR(lch));
@@ -374,32 +229,6 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 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 = dma_read(CSDP(lch));
-		csdp &= ~(0x3 << 16);
-		csdp |= (mode << 16);
-		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 = dma_read(LCH_CTRL(lch));
-		l &= ~0x7;
-		l |= mode;
-		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,
@@ -407,7 +236,7 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 {
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & SRC_PORT) {
 		u16 w;
 
 		w = dma_read(CSDP(lch));
@@ -421,12 +250,10 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 	l |= src_amode << 12;
 	dma_write(l, CCR(lch));
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & IS_WORD_16) {
 		dma_write(src_start >> 16, CSSA_U(lch));
 		dma_write((u16)src_start, CSSA_L(lch));
-	}
-
-	if (cpu_class_is_omap2())
+	} else
 		dma_write(src_start, CSSA(lch));
 
 	dma_write(src_ei, CSEI(lch));
@@ -453,16 +280,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;
-
-	dma_write(eidx, CSEI(lch));
-	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;
@@ -487,13 +304,13 @@ 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())
-			burst = 0x1;
-		else
+		if (d->dma_dev_attr & IS_BURST_ONLY4)
 			burst = 0x2;
+		else
+			burst = 0x1;
 		break;
 	case OMAP_DMA_DATA_BURST_8:
-		if (cpu_class_is_omap2()) {
+		if (!(d->dma_dev_attr & IS_BURST_ONLY4)) {
 			burst = 0x2;
 			break;
 		}
@@ -503,7 +320,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 		 * fall through
 		 */
 	case OMAP_DMA_DATA_BURST_16:
-		if (cpu_class_is_omap2()) {
+		if (!(d->dma_dev_attr & IS_BURST_ONLY4)) {
 			burst = 0x3;
 			break;
 		}
@@ -527,7 +344,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
 {
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & DST_PORT) {
 		l = dma_read(CSDP(lch));
 		l &= ~(0x1f << 9);
 		l |= dest_port << 9;
@@ -539,12 +356,10 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
 	l |= dest_amode << 14;
 	dma_write(l, CCR(lch));
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & IS_WORD_16) {
 		dma_write(dest_start >> 16, CDSA_U(lch));
 		dma_write(dest_start, CDSA_L(lch));
-	}
-
-	if (cpu_class_is_omap2())
+	} else
 		dma_write(dest_start, CDSA(lch));
 
 	dma_write(dst_ei, CDEI(lch));
@@ -552,16 +367,6 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
 }
 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;
-
-	dma_write(eidx, CDEI(lch));
-	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;
@@ -586,19 +391,19 @@ 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())
-			burst = 0x1;
-		else
+		if (d->dma_dev_attr & IS_BURST_ONLY4)
 			burst = 0x2;
+		else
+			burst = 0x1;
 		break;
 	case OMAP_DMA_DATA_BURST_8:
-		if (cpu_class_is_omap2())
-			burst = 0x2;
-		else
+		if (d->dma_dev_attr & IS_BURST_ONLY4)
 			burst = 0x3;
+		else
+			burst = 0x2;
 		break;
 	case OMAP_DMA_DATA_BURST_16:
-		if (cpu_class_is_omap2()) {
+		if (!(d->dma_dev_attr & IS_BURST_ONLY4)) {
 			burst = 0x3;
 			break;
 		}
@@ -616,26 +421,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 = dma_read(CSR(lch));
-	else if (cpu_class_is_omap2())
-		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
-
-	/* Enable some nice interrupts. */
-	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));
-}
-
 void omap_enable_dma_irq(int lch, u16 bits)
 {
 	dma_chan[lch].enabled_irqs |= bits;
@@ -648,81 +433,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 = 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
-
-	dma_write(l, CLNK_CTRL(lch));
-}
-
-static inline void disable_lnk(int lch)
-{
-	u32 l;
-
-	l = dma_read(CLNK_CTRL(lch));
-
-	/* Disable interrupts */
-	if (cpu_class_is_omap1()) {
-		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);
-	}
-
-	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 = dma_read(IRQENABLE_L0);
-	val |= 1 << lch;
-	dma_write(val, IRQENABLE_L0);
-	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 = dma_read(IRQENABLE_L0);
-	val &= ~(1 << lch);
-	dma_write(val, IRQENABLE_L0);
-	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)
@@ -746,10 +456,9 @@ 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 (cpu_class_is_omap2())
+	if (p->clear_lch_regs)
+		p->clear_lch_regs(free_ch);
+	else
 		omap_clear_dma(free_ch);
 
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
@@ -759,25 +468,21 @@ 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()) {
-		chan->chain_id = -1;
-		chan->next_linked_ch = -1;
-	}
-#endif
+	if (p->set_dma_chain_ch)
+		p->set_dma_chain_ch(free_ch);
 
 	chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
 
-	if (cpu_class_is_omap1())
+	if (d->dma_dev_attr & 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;
+						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;
 		}
 		/*
@@ -785,13 +490,15 @@ int omap_request_dma(int dev_id, const char *dev_name,
 		 * id.
 		 */
 		dma_write(dev_id | (1 << 10), CCR(free_ch));
-	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
+	} else if (d->dma_dev_attr & IS_WORD_16)
 		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);
+		if (p->enable_channel_irq)
+			p->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);
@@ -813,15 +520,18 @@ void omap_free_dma(int lch)
 		return;
 	}
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & IS_WORD_16) {
 		/* Disable all DMA interrupts for the channel. */
 		dma_write(0, CICR(lch));
 		/* Make sure the DMA transfer is stopped. */
 		dma_write(0, CCR(lch));
 	}
 
-	if (cpu_class_is_omap2()) {
-		omap2_disable_irq_lch(lch);
+	if (p->disable_irq_lch) {
+		unsigned long flags;
+		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 */
 		dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
@@ -844,39 +554,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;
-
-	dma_write(reg, GCR);
-}
-EXPORT_SYMBOL(omap_dma_set_global_params);
-
-/**
  * @brief omap_dma_set_prio_lch : Set channel wise priority settings
  *
  * @param lch
@@ -897,7 +574,7 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
 	}
 	l = dma_read(CCR(lch));
 	l &= ~((1 << 6) | (1 << 26));
-	if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
+	if (d->dma_dev_attr & IS_RW_PRIORIY)
 		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
 	else
 		l |= ((read_prio & 0x1) << 6);
@@ -918,7 +595,7 @@ void omap_clear_dma(int lch)
 
 	local_irq_save(flags);
 
-	if (cpu_class_is_omap1()) {
+	if (d->dma_dev_attr & IS_WORD_16) {
 		u32 l;
 
 		l = dma_read(CCR(lch));
@@ -927,9 +604,7 @@ void omap_clear_dma(int lch)
 
 		/* Clear pending interrupts */
 		l = dma_read(CSR(lch));
-	}
-
-	if (cpu_class_is_omap2()) {
+	} else {
 		int i;
 		void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch);
 		for (i = 0; i < 0x44; i += 4)
@@ -948,18 +623,19 @@ void omap_start_dma(int lch)
 	 * The CPC/CDAC register needs to be initialized to zero
 	 * before starting dma transfer.
 	 */
-	if (cpu_is_omap15xx())
+	if (d->dma_dev_attr & IS_WORD_16)
 		dma_write(0, CPC(lch));
 	else
 		dma_write(0, CDAC(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_chan_count];
 
 		dma_chan_link_map[lch] = 1;
 		/* Set the link register of the first channel */
-		enable_lnk(lch);
+		if (p->enable_lnk)
+			p->enable_lnk(lch);
 
 		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
 		cur_lch = dma_chan[lch].next_lch;
@@ -972,8 +648,10 @@ 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);
+			if (p->enable_lnk)
+				p->enable_lnk(cur_lch);
+			if (p->enable_channel_irq)
+				p->enable_channel_irq(cur_lch);
 
 			cur_lch = next_lch;
 		} while (next_lch != -1);
@@ -982,7 +660,8 @@ void omap_start_dma(int lch)
 	if (p->errata & DMA_CHAINING_ERRATA)
 		dma_write(lch, CLNK_CTRL(lch));
 
-	omap_enable_channel_irq(lch);
+	if (p->enable_channel_irq)
+		p->enable_channel_irq(lch);
 
 	l = dma_read(CCR(lch));
 
@@ -1001,14 +680,14 @@ void omap_stop_dma(int lch)
 	u32 l;
 
 	/* Disable all interrupts on the channel */
-	if (cpu_class_is_omap1())
+	if (d->dma_dev_attr & IS_WORD_16)
 		dma_write(0, CICR(lch));
 
 	l = dma_read(CCR(lch));
 	l &= ~OMAP_DMA_CCR_EN;
 	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_chan_count];
 
@@ -1020,7 +699,8 @@ void omap_stop_dma(int lch)
 			/* Mark the current channel */
 			dma_chan_link_map[cur_lch] = 1;
 
-			disable_lnk(cur_lch);
+			if (p->disable_lnk)
+				p->disable_lnk(cur_lch);
 
 			next_lch = dma_chan[cur_lch].next_lch;
 			cur_lch = next_lch;
@@ -1070,19 +750,16 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 {
 	dma_addr_t offset = 0;
 
-	if (cpu_is_omap15xx())
+	if (d->dma_dev_attr & ENABLE_1510_MODE)
 		offset = dma_read(CPC(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 ((p->errata & OMAP3_3_ERRATUM) && !(enable_1510_mode)
+				&& (offset == 0))
 		offset = dma_read(CSAC(lch));
 
-	if (cpu_class_is_omap1())
+	if (d->dma_dev_attr & IS_WORD_16)
 		offset |= (dma_read(CSSA_U(lch)) << 16);
 
 	return offset;
@@ -1101,19 +778,16 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
 {
 	dma_addr_t offset = 0;
 
-	if (cpu_is_omap15xx())
+	if (d->dma_dev_attr & ENABLE_1510_MODE)
 		offset = dma_read(CPC(lch));
 	else
 		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)
+	if ((p->errata & OMAP3_3_ERRATUM) && !(enable_1510_mode)
+				&& (offset == 0))
 		offset = dma_read(CDAC(lch));
 
-	if (cpu_class_is_omap1())
+	if (d->dma_dev_attr & IS_WORD_16)
 		offset |= (dma_read(CDSA_U(lch)) << 16);
 
 	return offset;
@@ -1130,7 +804,7 @@ int omap_dma_running(void)
 {
 	int lch;
 
-	if (cpu_class_is_omap1())
+	if (d->dma_dev_attr & IS_WORD_16)
 		if (omap_lcd_dma_running())
 			return 1;
 
@@ -1148,7 +822,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) {
 			dma_write(dma_read(CCR(lch_head)) | (3 << 8),
 								CCR(lch_head));
@@ -1175,7 +849,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) {
 			dma_write(dma_read(CCR(lch_head)) & ~(3 << 8),
 								CCR(lch_head));
@@ -1204,828 +878,11 @@ 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 = 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_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)
-		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)
-				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) & 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 = 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_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 = 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 get_sysconfig;
-
-	/* 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 (p->errata & DMA_SYSCONFIG_ERRATA)
-		dma_ocpsysconfig_errata(&get_sysconfig, false);
-
-	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 */
-		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 (p->errata & DMA_SYSCONFIG_ERRATA)
-		dma_ocpsysconfig_errata(&get_sysconfig, true);
-
-	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 = 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_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 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 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 = 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 = 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);
-		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 (cpu_class_is_omap2()) {
-			/*
-			 * Errata: sDMA Channel is not disabled
-			 * after a transaction error. So we explicitely
-			 * disable the channel
-			 */
-			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);
-
-	/* 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)
-			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 omap2_dma_irq_handler(int irq, void *dev_id)
-{
-	u32 val, enable_reg;
-	int i;
-
-	val = dma_read(IRQSTATUS_L0);
-	if (val == 0) {
-		if (printk_ratelimit())
-			printk(KERN_WARNING "Spurious DMA IRQ\n");
-		return IRQ_HANDLED;
-	}
-	enable_reg = dma_read(IRQENABLE_L0);
-	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 =
-		dma_read(IRQENABLE_L0);
-	omap_dma_global_context.dma_ocp_sysconfig =
-		dma_read(OCP_SYSCONFIG);
-	omap_dma_global_context.dma_gcr = dma_read(GCR);
-}
-
-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_ocp_sysconfig,
-		OCP_SYSCONFIG);
-	dma_write(omap_dma_global_context.dma_irqenable_l0,
-		IRQENABLE_L0);
-
-	/*
-	 * 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))
-		dma_write(0x3 , IRQSTATUS_L0);
-
-	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)
 {
 	struct omap_system_dma_plat_info *pdata = pdev->dev.platform_data;
 	struct resource *mem;
 	int ch, ret = 0;
-	int dma_irq;
-	char irq_name[14];
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "%s: System DMA initialized without"
@@ -2046,10 +903,11 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	if (!omap_dma_base) {
 		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
 		ret = -ENOMEM;
-		goto exit_release_region;
+		release_mem_region(mem->start, resource_size(mem));
+		return ret;
 	}
 
-	if (cpu_class_is_omap2() && omap_dma_reserve_channels
+	if (!(d->dma_dev_attr & IS_WORD_16) && omap_dma_reserve_channels
 			&& (omap_dma_reserve_channels <= dma_lch_count))
 		d->dma_lch_count = omap_dma_reserve_channels;
 
@@ -2057,19 +915,12 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	dma_chan_count		= d->dma_chan_count;
 	dma_chan		= d->dma_chan;
 
-	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;
-		}
-	}
+
 	enable_1510_mode = d->dma_dev_attr & ENABLE_1510_MODE;
 
-	if (cpu_is_omap15xx()) {
+	if (enable_1510_mode) {
 		printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
-	} else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+	} else if (d->dma_dev_attr & IS_WORD_16) {
 		printk(KERN_INFO "OMAP DMA hardware version %d\n",
 		       dma_read(HW_ID));
 		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
@@ -2087,7 +938,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 			w |= 1 << 3;
 			dma_write(w, GSCR);
 		}
-	} else if (cpu_class_is_omap2()) {
+	} else {
 		u8 revision = dma_read(REVISION) & 0xff;
 		printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
 		       revision >> 4, revision & 0xf);
@@ -2096,60 +947,23 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	spin_lock_init(&dma_chan_lock);
 	for (ch = 0; ch < dma_chan_count; ch++) {
 		omap_clear_dma(ch);
-		if (cpu_class_is_omap2())
-			omap2_disable_irq_lch(ch);
+		if (p->disable_irq_lch) {
+			unsigned long flags;
+			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.
-			 */
-			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_unmap;
-			}
-			ret = request_irq(dma_irq,
-					omap1_dma_irq_handler, 0, "DMA",
-					(void *) (ch + 1));
-			if (ret != 0) {
-				int irq_rel;
-				printk(KERN_ERR "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())
+	if (d->dma_dev_attr & GLOBAL_PRIORITY)
 		omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
 				DMA_DEFAULT_FIFO_DEPTH, 0);
 
-	if (cpu_class_is_omap2()) {
-		strcpy(irq_name, "dma_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->dma_dev_attr & RESERVE_CHANNEL) {
 		printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
 				"HS ROM code\n");
 		dma_chan[0].dev_id = 0;
@@ -2158,14 +972,6 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "System DMA registered\n");
 	return 0;
-
-exit_dma_chan:
-	kfree(dma_chan);
-exit_unmap:
-	iounmap(omap_dma_base);
-exit_release_region:
-	release_mem_region(mem->start, resource_size(mem));
-	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 6d1fee0..bed582b 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -241,6 +241,9 @@
 #define DMA_THREAD_FIFO_25		(0x02 << 14)
 #define DMA_THREAD_FIFO_50		(0x03 << 14)
 
+#define OMAP_DMA_ACTIVE			0x01
+#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
+
 /* Chaining modes*/
 #ifndef CONFIG_ARCH_OMAP1
 #define OMAP_DMA_STATIC_CHAIN		0x1
@@ -354,6 +357,16 @@ struct omap_system_dma_plat_info {
 	struct omap_dma_dev_attr *dma_attr;
 	void __iomem *omap_dma_base;
 	u32 errata;
+	void (*enable_irq_lch)(int lch);
+	void (*disable_irq_lch)(int lch);
+	void (*enable_lnk)(int lch);
+	void (*disable_lnk)(int lch);
+	void (*clear_lch_regs)(int lch);
+	int (*get_gdma_dev)(int req);
+	void (*set_gdma_dev)(int req, int dev);
+	void (*enable_channel_irq)(int lch);
+	void (*disable_channel_irq)(int lch);
+	void (*set_dma_chain_ch)(int free_ch);
 };
 
 extern void omap_set_dma_priority(int lch, int dst_port, int priority);
@@ -417,29 +430,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.0.4


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

* [PATCH 11/11] sDMA: descriptor autoloading feature
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (9 preceding siblings ...)
  2010-07-29  9:59 ` [PATCH 10/11] OMAP: DMA: Use DMA device attributes Manjunatha GK
@ 2010-07-29  9:59 ` Manjunatha GK
  2010-07-29 10:30   ` G, Manjunath Kondaiah
  2010-08-11  7:43 ` [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah
  11 siblings, 1 reply; 29+ messages in thread
From: Manjunatha GK @ 2010-07-29  9:59 UTC (permalink / raw)
  To: linux-omap
  Cc: Venkatraman S, Benoit Cousson, Kevin Hilman, Paul Walmsley,
	Tony Lindgren, Anand Sawant, Santosh Shilimkar, Rajendra Nayak,
	Basak Partha, Charulatha V

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: Manjunatha GK <manjugk@ti.com>
---
 arch/arm/mach-omap1/dma.c              |    5 +
 arch/arm/mach-omap1/include/mach/dma.h |    2 +
 arch/arm/mach-omap2/dma.c              |  254 ++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/include/mach/dma.h |  194 ++++++++++++++++++++++++
 arch/arm/plat-omap/dma.c               |    1 +
 5 files changed, 456 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index eadc160..1f10f62 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -304,6 +304,11 @@ void omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
 }
 EXPORT_SYMBOL(omap_dma_set_global_params);
 
+void omap_clear_dma_sglist_mode(int lch)
+{
+	return;
+}
+
 static int __init omap1_system_dma_init(void)
 {
 	struct platform_device *pdev;
diff --git a/arch/arm/mach-omap1/include/mach/dma.h b/arch/arm/mach-omap1/include/mach/dma.h
index 1eb0d31..afe486b 100644
--- a/arch/arm/mach-omap1/include/mach/dma.h
+++ b/arch/arm/mach-omap1/include/mach/dma.h
@@ -143,4 +143,6 @@ struct omap_dma_lch {
 	long flags;
 };
 
+/* Dummy function */
+extern void omap_clear_dma_sglist_mode(int lch);
 #endif /* __ASM_ARCH_OMAP1_DMA_H */
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 390c428..c24ed00 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -204,6 +204,77 @@ static void dma_ocpsysconfig_errata(u32 *sys_cf, bool flag)
 		dma_write(*sys_cf, OCP_SYSCONFIG);
 }
 
+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;
+}
+
+
 void omap_dma_global_context_save(void)
 {
 	omap_dma_global_context.dma_irqenable_l0 =
@@ -861,6 +932,189 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
 }
 EXPORT_SYMBOL(omap_set_dma_write_mode);
 
+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 *chparams)
+{
+	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 == chparams)
+		l |= DMA_LIST_CDP_FASTMODE;
+	else
+		omap_set_dma_params(lch, chparams);
+
+	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 omap_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(omap_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));
+	/**
+	 * Barrier needed as writes to the
+	 * descriptor memory needs to be flushed
+	 * before it's used by DMA controller
+	 */
+	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, get_sysconfig;
+
+	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);
+
+	/**
+	 * Barrier needed as writes to the
+	 * descriptor memory needs to be flushed
+	 * before it's used by DMA controller
+	 */
+	wmb();
+
+	if (p->errata & DMA_SYSCONFIG_ERRATA)
+		dma_ocpsysconfig_errata(&get_sysconfig, false)
+
+	/* 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 (p->errata & DMA_SYSCONFIG_ERRATA)
+		dma_ocpsysconfig_errata(&get_sysconfig, true);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap_resume_dma_sglist_transfers);
+
+void omap_release_dma_sglist(int lch)
+{
+	omap_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);
+
 static int omap2_dma_handle_ch(int ch)
 {
 	u32 status = dma_read(CSR(ch));
diff --git a/arch/arm/mach-omap2/include/mach/dma.h b/arch/arm/mach-omap2/include/mach/dma.h
index f3e21d5..e039ea4 100644
--- a/arch/arm/mach-omap2/include/mach/dma.h
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -143,6 +143,112 @@
 #define OMAP_DMA4_GSCR				0
 #define OMAP1_DMA_REVISION			0
 
+/* 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;
+};
+
 struct omap_dma_lch {
 	int next_lch;
 	int dev_id;
@@ -158,8 +264,96 @@ struct omap_dma_lch {
 	int state;
 	int chain_id;
 	int status;
+	struct omap_dma_list_config_params list_config;
 };
 
+/**
+ * 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);
+
 /* Chaining APIs */
 extern int omap_request_dma_chain(int dev_id, const char *dev_name,
 				  void (*callback) (int lch, u16 ch_status,
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 643f538..daac49c 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -543,6 +543,7 @@ void omap_free_dma(int lch)
 		/* Make sure the DMA transfer is stopped. */
 		dma_write(0, CCR(lch));
 		omap_clear_dma(lch);
+		omap_clear_dma_sglist_mode(lch);
 	}
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
-- 
1.7.0.4


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

* RE: [PATCH 11/11] sDMA: descriptor autoloading feature
  2010-07-29  9:59 ` [PATCH 11/11] sDMA: descriptor autoloading feature Manjunatha GK
@ 2010-07-29 10:30   ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 29+ messages in thread
From: G, Manjunath Kondaiah @ 2010-07-29 10:30 UTC (permalink / raw)
  To: linux-omap

 

> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org 
> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, 
> Manjunath Kondaiah
> Sent: Thursday, July 29, 2010 3:29 PM
> To: linux-omap@vger.kernel.org
> Cc: S, Venkatraman; Cousson, Benoit; Kevin Hilman; Paul 
> Walmsley; Tony Lindgren; Sawant, Anand; Shilimkar, Santosh; 
> Nayak, Rajendra; Basak, Partha; Varadarajan, Charulatha
> Subject: [PATCH 11/11] sDMA: descriptor autoloading feature
> 
> 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: Manjunatha GK <manjugk@ti.com>
> ---
>  arch/arm/mach-omap1/dma.c              |    5 +
>  arch/arm/mach-omap1/include/mach/dma.h |    2 +
>  arch/arm/mach-omap2/dma.c              |  254 
> ++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/include/mach/dma.h |  194 
> ++++++++++++++++++++++++
>  arch/arm/plat-omap/dma.c               |    1 +
>  5 files changed, 456 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
> index eadc160..1f10f62 100644
> --- a/arch/arm/mach-omap1/dma.c
> +++ b/arch/arm/mach-omap1/dma.c
> @@ -304,6 +304,11 @@ void omap_dma_set_global_params(int 
> arb_rate, int max_fifo_depth, int tparams)
>  }
>  EXPORT_SYMBOL(omap_dma_set_global_params);
>  
> +void omap_clear_dma_sglist_mode(int lch)
> +{
> +	return;
> +}
> +
>  static int __init omap1_system_dma_init(void)
>  {
>  	struct platform_device *pdev;
> diff --git a/arch/arm/mach-omap1/include/mach/dma.h 
> b/arch/arm/mach-omap1/include/mach/dma.h
> index 1eb0d31..afe486b 100644
> --- a/arch/arm/mach-omap1/include/mach/dma.h
> +++ b/arch/arm/mach-omap1/include/mach/dma.h
> @@ -143,4 +143,6 @@ struct omap_dma_lch {
>  	long flags;
>  };
>  
> +/* Dummy function */
> +extern void omap_clear_dma_sglist_mode(int lch);
>  #endif /* __ASM_ARCH_OMAP1_DMA_H */
> diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
> index 390c428..c24ed00 100644
> --- a/arch/arm/mach-omap2/dma.c
> +++ b/arch/arm/mach-omap2/dma.c
> @@ -204,6 +204,77 @@ static void dma_ocpsysconfig_errata(u32 
> *sys_cf, bool flag)
>  		dma_write(*sys_cf, OCP_SYSCONFIG);
>  }
>  
> +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;
> +}
> +
> +
>  void omap_dma_global_context_save(void)
>  {
>  	omap_dma_global_context.dma_irqenable_l0 =
> @@ -861,6 +932,189 @@ void omap_set_dma_write_mode(int lch, 
> enum omap_dma_write_mode mode)
>  }
>  EXPORT_SYMBOL(omap_set_dma_write_mode);
>  
> +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 *chparams)
> +{
> +	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 == chparams)
> +		l |= DMA_LIST_CDP_FASTMODE;
> +	else
> +		omap_set_dma_params(lch, chparams);
> +
> +	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 omap_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(omap_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));
> +	/**
> +	 * Barrier needed as writes to the
> +	 * descriptor memory needs to be flushed
> +	 * before it's used by DMA controller
> +	 */
> +	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, get_sysconfig;
> +
> +	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);
> +
> +	/**
> +	 * Barrier needed as writes to the
> +	 * descriptor memory needs to be flushed
> +	 * before it's used by DMA controller
> +	 */
> +	wmb();
> +
> +	if (p->errata & DMA_SYSCONFIG_ERRATA)
> +		dma_ocpsysconfig_errata(&get_sysconfig, false)

Sorry. I missed ; here and forgot to commit this in last patch. 

-Manjunath

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

* Re: [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes
  2010-07-29  9:58 ` [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
@ 2010-07-29 12:35   ` Cousson, Benoit
  2010-07-30  3:57     ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 29+ messages in thread
From: Cousson, Benoit @ 2010-07-29 12:35 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, Kevin Hilman, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

Hi Manjunatha,

I just have a couple of minor comments.

On 7/29/2010 11:58 AM, G, Manjunath Kondaiah wrote:
> This patches introduces OMAP DMA device attributes for using the same in
> DMA platform driver for all OMAP's and HWMOD database(OMAP2PLUS onwards)
>
> Signed-off-by: Manjunatha GK<manjugk@ti.com>
> ---
>   arch/arm/plat-omap/include/plat/dma.h |   22 ++++++++++++++++++++++
>   1 files changed, 22 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
> index 02232ca..ff60f11 100644
> --- a/arch/arm/plat-omap/include/plat/dma.h
> +++ b/arch/arm/plat-omap/include/plat/dma.h
> @@ -398,6 +398,22 @@
>   #define DMA_CH_PRIO_HIGH		0x1
>   #define DMA_CH_PRIO_LOW			0x0 /* Def */
>
> +/* Attributes for OMAP DMA Contrllers */
> +#define ENABLE_1510_MODE		(1<<  0)
> +#define DMA_LINKED_LCH			(1<<  1)
> +#define GLOBAL_PRIORITY			(1<<  2)
> +#define RESERVE_CHANNEL			(1<<  3)
> +#define SRC_PORT			(2<<  3)
> +#define DST_PORT			(2<<  4)
> +#define IS_CSSA_32			(2<<  5)
> +#define IS_CDSA_32			(2<<  6)
> +#define SRC_INDEX			(4<<  6)
> +#define DST_INDEX			(4<<  7)
> +#define IS_BURST_ONLY4			(4<<  8)
> +#define CLEAR_CSR_ON_READ		(4<<  9)
> +#define IS_WORD_16			(8<<  9)
> +#define IS_RW_PRIORIY			(8<<  0xA)

It is a minor detail, but why are you shifting both side of the
operator? It is really confusing, cannot you just do 1 << X?
With 0 < X < 13.

> +
>   enum omap_dma_burst_mode {
>   	OMAP_DMA_DATA_BURST_DIS = 0,
>   	OMAP_DMA_DATA_BURST_4,
> @@ -463,6 +479,12 @@ struct omap_dma_channel_params {
>   #endif
>   };
>
> +struct omap_dma_dev_attr {
> +	u32 dma_dev_attr;

That name is not very meaningful, maybe dma_cap for capability or 
something else will be better.


> +	u16 dma_lch_count;
> +	u16 dma_chan_count;
> +	struct omap_dma_lch *dma_chan;

In general, I think that there are too many "dma_" prefix in that 
structure. It is already inside a dma_XXX struct so I don't think that 
adding an extra prefix to every attribute is needed.

Regards,
Benoit


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

* Re: [PATCH 05/11] OMAP4: DMA: HWMOD: update OMAP4 data base
  2010-07-29  9:58 ` [PATCH 05/11] OMAP4: DMA: HWMOD: update OMAP4 data base Manjunatha GK
@ 2010-07-29 12:48   ` Cousson, Benoit
  0 siblings, 0 replies; 29+ messages in thread
From: Cousson, Benoit @ 2010-07-29 12:48 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, Kevin Hilman, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

Some more comments about "dma_" prefix...

On 7/29/2010 11:58 AM, G, Manjunath Kondaiah wrote:
> The OMAP4 hwmod data base is updated with DMA controller attributes.
>
> Signed-off-by: Manjunatha GK<manjugk@ti.com>
> ---
>   arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   19 ++++++++++++++-----
>   1 files changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> index 20f5f8c..ee589c5 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"
>
> @@ -750,12 +751,19 @@ static struct omap_hwmod_class omap44xx_dma_hwmod_class = {
>   	.sysc =&omap44xx_dma_sysc,
>   };
>
> +/* dma attributes */
> +static struct omap_dma_dev_attr dma_dev_attr = {
> +	.dma_dev_attr = DMA_LINKED_LCH | GLOBAL_PRIORITY |
> +				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
> +	.dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT,
> +};
> +
>   /* 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 },
> +	{ .name = "dma_0", .irq = 12 + OMAP44XX_IRQ_GIC_START },
> +	{ .name = "dma_1", .irq = 13 + OMAP44XX_IRQ_GIC_START },
> +	{ .name = "dma_2", .irq = 14 + OMAP44XX_IRQ_GIC_START },
> +	{ .name = "dma_3", .irq = 15 + OMAP44XX_IRQ_GIC_START },

"0", "1", "2", and "3" are maybe not very meaningful name, but what 
information the dma_ prefix will bring us?
That name will only be used inside the dma driver, so there is no 
namespace confusion. The shorter, the better.

Regards,
Benoit

>   };
>
>   static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
> @@ -801,6 +809,7 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = {
>   	.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),
>   };
>
> @@ -4789,7 +4798,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
>   	/* counter class */
>   	&omap44xx_counter_32k_hwmod,
>   	/* dma class */
> -/*	&omap44xx_dma_system_hwmod, */
> +	&omap44xx_dma_system_hwmod,
>   	/* dmic class */
>   /*	&omap44xx_dmic_hwmod, */
>   	/* dsp class */


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

* RE: [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes
  2010-07-29 12:35   ` Cousson, Benoit
@ 2010-07-30  3:57     ` G, Manjunath Kondaiah
  2010-08-04 10:13       ` Cousson, Benoit
  0 siblings, 1 reply; 29+ messages in thread
From: G, Manjunath Kondaiah @ 2010-07-30  3:57 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: linux-omap, Kevin Hilman, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

 

> -----Original Message-----
> From: Cousson, Benoit 
> Sent: Thursday, July 29, 2010 6:06 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Kevin Hilman; Paul Walmsley; 
> Tony Lindgren; Sawant, Anand; Shilimkar, Santosh; Nayak, 
> Rajendra; Basak, Partha; Varadarajan, Charulatha
> Subject: Re: [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes
> 
> Hi Manjunatha,
> 
> I just have a couple of minor comments.
> 
> On 7/29/2010 11:58 AM, G, Manjunath Kondaiah wrote:
> > This patches introduces OMAP DMA device attributes for 
> using the same in
> > DMA platform driver for all OMAP's and HWMOD 
> database(OMAP2PLUS onwards)
> >
> > Signed-off-by: Manjunatha GK<manjugk@ti.com>
> > ---
> >   arch/arm/plat-omap/include/plat/dma.h |   22 
> ++++++++++++++++++++++
> >   1 files changed, 22 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/plat-omap/include/plat/dma.h 
> b/arch/arm/plat-omap/include/plat/dma.h
> > index 02232ca..ff60f11 100644
> > --- a/arch/arm/plat-omap/include/plat/dma.h
> > +++ b/arch/arm/plat-omap/include/plat/dma.h
> > @@ -398,6 +398,22 @@
> >   #define DMA_CH_PRIO_HIGH		0x1
> >   #define DMA_CH_PRIO_LOW			0x0 /* Def */
> >
> > +/* Attributes for OMAP DMA Contrllers */
> > +#define ENABLE_1510_MODE		(1<<  0)
> > +#define DMA_LINKED_LCH			(1<<  1)
> > +#define GLOBAL_PRIORITY			(1<<  2)
> > +#define RESERVE_CHANNEL			(1<<  3)
> > +#define SRC_PORT			(2<<  3)
> > +#define DST_PORT			(2<<  4)
> > +#define IS_CSSA_32			(2<<  5)
> > +#define IS_CDSA_32			(2<<  6)
> > +#define SRC_INDEX			(4<<  6)
> > +#define DST_INDEX			(4<<  7)
> > +#define IS_BURST_ONLY4			(4<<  8)
> > +#define CLEAR_CSR_ON_READ		(4<<  9)
> > +#define IS_WORD_16			(8<<  9)
> > +#define IS_RW_PRIORIY			(8<<  0xA)
> 
> It is a minor detail, but why are you shifting both side of the
> operator? It is really confusing, cannot you just do 1 << X?
> With 0 < X < 13.
I can change this if it is confusing to others.

> 
> > +
> >   enum omap_dma_burst_mode {
> >   	OMAP_DMA_DATA_BURST_DIS = 0,
> >   	OMAP_DMA_DATA_BURST_4,
> > @@ -463,6 +479,12 @@ struct omap_dma_channel_params {
> >   #endif
> >   };
> >
> > +struct omap_dma_dev_attr {
> > +	u32 dma_dev_attr;
> 
> That name is not very meaningful, maybe dma_cap for capability or 
> something else will be better.
Makes sense. I will change this also.

> 
> 
> > +	u16 dma_lch_count;
> > +	u16 dma_chan_count;
> > +	struct omap_dma_lch *dma_chan;
> 
> In general, I think that there are too many "dma_" prefix in that 
> structure. It is already inside a dma_XXX struct so I don't 
> think that 
> adding an extra prefix to every attribute is needed.

These variables are part of legacy code which I used "as is". 
I can remove these prefixes.

-Manjunath


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

* Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-07-29  9:58 ` [PATCH 04/11] OMAP3: " Manjunatha GK
@ 2010-08-03 21:56   ` Kevin Hilman
  2010-08-04  0:35     ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 29+ messages in thread
From: Kevin Hilman @ 2010-08-03 21:56 UTC (permalink / raw)
  To: Manjunatha GK
  Cc: linux-omap, Benoit Cousson, Paul Walmsley, Tony Lindgren,
	Anand Sawant, Santosh Shilimkar, Rajendra Nayak, Basak Partha,
	Charulatha V

Manjunatha GK <manjugk@ti.com> writes:

> This patch adds OMAP3 DMA hwmod structures.
>
> Signed-off-by: Manjunatha GK <manjugk@ti.com>

[...]

> +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	= "l3_div_ck",
> +	.prcm = {
> +		.omap2 = {
> +			/* .clkctrl_reg = NULL, */
> +		},
> +	},

Has this been tested?  Without valid fields here the hwmod will never be
enabled.

Kevin

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

* RE: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-03 21:56   ` Kevin Hilman
@ 2010-08-04  0:35     ` G, Manjunath Kondaiah
  2010-08-04 10:08       ` Cousson, Benoit
  0 siblings, 1 reply; 29+ messages in thread
From: G, Manjunath Kondaiah @ 2010-08-04  0:35 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, Cousson, Benoit, Paul Walmsley, Tony Lindgren,
	Sawant, Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak,
	Partha, Varadarajan, Charulatha

Kevin,

> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Wednesday, August 04, 2010 3:27 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Paul 
> Walmsley; Tony Lindgren; Sawant, Anand; Shilimkar, Santosh; 
> Nayak, Rajendra; Basak, Partha; Varadarajan, Charulatha
> Subject: Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data 
> structures
> 
> Manjunatha GK <manjugk@ti.com> writes:
> 
> > This patch adds OMAP3 DMA hwmod structures.
> >
> > Signed-off-by: Manjunatha GK <manjugk@ti.com>
> 
> [...]
> 
> > +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	= "l3_div_ck",
> > +	.prcm = {
> > +		.omap2 = {
> > +			/* .clkctrl_reg = NULL, */
> > +		},
> > +	},
> 
> Has this been tested?  Without valid fields here the hwmod 
> will never be
> enabled.

This patch series has been tested on both omap3 and omap4. I didn't find
any entries for DMA module in prcm-common.h(for assigning .module_bit etc)
hence I commented this for clarification.

However, all omap3 applicable dma tests used to pass with these changes.

I can include and test it again if these entries are available at some other 
place or I can define if it is applicable for DMA.

-Manjunath


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

* Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-04  0:35     ` G, Manjunath Kondaiah
@ 2010-08-04 10:08       ` Cousson, Benoit
  2010-08-04 10:15         ` Shilimkar, Santosh
  0 siblings, 1 reply; 29+ messages in thread
From: Cousson, Benoit @ 2010-08-04 10:08 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: Kevin Hilman, linux-omap, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

On 8/4/2010 2:35 AM, G, Manjunath Kondaiah wrote:
> Kevin,
>
>> From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>> Sent: Wednesday, August 04, 2010 3:27 AM
>>
>> Manjunatha GK<manjugk@ti.com>  writes:
>>
>>> This patch adds OMAP3 DMA hwmod structures.
>>>
>>> Signed-off-by: Manjunatha GK<manjugk@ti.com>
>>
>> [...]
>>
>>> +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	= "l3_div_ck",
>>> +	.prcm = {
>>> +		.omap2 = {
>>> +			/* .clkctrl_reg = NULL, */
>>> +		},
>>> +	},
>>
>> Has this been tested?  Without valid fields here the hwmod
>> will never be
>> enabled.
>
> This patch series has been tested on both omap3 and omap4. I didn't find
> any entries for DMA module in prcm-common.h(for assigning .module_bit etc)
> hence I commented this for clarification.

There is no explicit PRCM control for the SDMA. You can just access the 
standby status and change the sysconfig idle and standby settings.
It uses the L3 interface clock as functional clock.
You should still use HWMOD_NO_IDLEST status to prevent the enable to crash.

In your case, I think that you are probably never explicitly enabling or 
disabling the dma device due to the library kind of API and the fact 
that the HW is managing is automatically, isn't it?

We had the same kind of discussion for the hwspinlock. Since these IPs 
are using interface clock as a functional clock, there is no need to 
explicitly enable them. But we should, otherwise we have no way to track 
the usage of this IP and potentially to enable the power domain that 
contains these IP.

Each time a dma channel is requested, you should call the 
pm_runtime_get, and pm_runtime_put() when the channel is not needed anymore.

Regards,
Benoit


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

* Re: [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes
  2010-07-30  3:57     ` G, Manjunath Kondaiah
@ 2010-08-04 10:13       ` Cousson, Benoit
  2010-08-04 17:21         ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 29+ messages in thread
From: Cousson, Benoit @ 2010-08-04 10:13 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, Kevin Hilman, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

On 7/30/2010 5:57 AM, G, Manjunath Kondaiah wrote:

<snip>

>>> +/* Attributes for OMAP DMA Contrllers */
>>> +#define ENABLE_1510_MODE		(1<<   0)
>>> +#define DMA_LINKED_LCH			(1<<   1)
>>> +#define GLOBAL_PRIORITY			(1<<   2)
>>> +#define RESERVE_CHANNEL			(1<<   3)
>>> +#define SRC_PORT			(2<<   3)
>>> +#define DST_PORT			(2<<   4)
>>> +#define IS_CSSA_32			(2<<   5)
>>> +#define IS_CDSA_32			(2<<   6)
>>> +#define SRC_INDEX			(4<<   6)
>>> +#define DST_INDEX			(4<<   7)
>>> +#define IS_BURST_ONLY4			(4<<   8)
>>> +#define CLEAR_CSR_ON_READ		(4<<   9)
>>> +#define IS_WORD_16			(8<<   9)
>>> +#define IS_RW_PRIORIY			(8<<   0xA)
>>
>> It is a minor detail, but why are you shifting both side of the
>> operator? It is really confusing, cannot you just do 1<<  X?
>> With 0<  X<  13.
> I can change this if it is confusing to others.

So you are still convince that this is a good way to do it???
What is the rational behind that?
Why adding potential source of confusion when you can avoid that easily?

Regards,
Benoit

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

* RE: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-04 10:08       ` Cousson, Benoit
@ 2010-08-04 10:15         ` Shilimkar, Santosh
  2010-08-04 10:23           ` Cousson, Benoit
  0 siblings, 1 reply; 29+ messages in thread
From: Shilimkar, Santosh @ 2010-08-04 10:15 UTC (permalink / raw)
  To: Cousson, Benoit, G, Manjunath Kondaiah
  Cc: Kevin Hilman, linux-omap, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Nayak, Rajendra, Basak, Partha, Varadarajan, Charulatha

> -----Original Message-----
> From: Cousson, Benoit
> Sent: Wednesday, August 04, 2010 3:38 PM
> To: G, Manjunath Kondaiah
> Cc: Kevin Hilman; linux-omap@vger.kernel.org; Paul Walmsley; Tony
> Lindgren; Sawant, Anand; Shilimkar, Santosh; Nayak, Rajendra; Basak,
> Partha; Varadarajan, Charulatha
> Subject: Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
> 
> On 8/4/2010 2:35 AM, G, Manjunath Kondaiah wrote:
> > Kevin,
> >
> >> From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
> >> Sent: Wednesday, August 04, 2010 3:27 AM
> >>
> >> Manjunatha GK<manjugk@ti.com>  writes:
> >>
> >>> This patch adds OMAP3 DMA hwmod structures.
> >>>
> >>> Signed-off-by: Manjunatha GK<manjugk@ti.com>
> >>
> >> [...]
> >>
> >>> +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	= "l3_div_ck",
> >>> +	.prcm = {
> >>> +		.omap2 = {
> >>> +			/* .clkctrl_reg = NULL, */
> >>> +		},
> >>> +	},
> >>
> >> Has this been tested?  Without valid fields here the hwmod
> >> will never be
> >> enabled.
> >
> > This patch series has been tested on both omap3 and omap4. I didn't find
> > any entries for DMA module in prcm-common.h(for assigning .module_bit
> etc)
> > hence I commented this for clarification.
> 
> There is no explicit PRCM control for the SDMA. You can just access the
> standby status and change the sysconfig idle and standby settings.
> It uses the L3 interface clock as functional clock.
> You should still use HWMOD_NO_IDLEST status to prevent the enable to
> crash.
> 
> In your case, I think that you are probably never explicitly enabling or
> disabling the dma device due to the library kind of API and the fact
> that the HW is managing is automatically, isn't it?
> 
> We had the same kind of discussion for the hwspinlock. Since these IPs
> are using interface clock as a functional clock, there is no need to
> explicitly enable them. But we should, otherwise we have no way to track
> the usage of this IP and potentially to enable the power domain that
> contains these IP.
> 
> Each time a dma channel is requested, you should call the
> pm_runtime_get, and pm_runtime_put() when the channel is not needed
> anymore.
> 
Request call can get called on multiple channels.
So at the time of request a channel, other channels might be already 
in use. So logically " pm_runtime_put" should only be done if
reserved channels are 0

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

* Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-04 10:15         ` Shilimkar, Santosh
@ 2010-08-04 10:23           ` Cousson, Benoit
  2010-08-04 10:27             ` Shilimkar, Santosh
  0 siblings, 1 reply; 29+ messages in thread
From: Cousson, Benoit @ 2010-08-04 10:23 UTC (permalink / raw)
  To: Shilimkar, Santosh
  Cc: G, Manjunath Kondaiah, Kevin Hilman, linux-omap, Paul Walmsley,
	Tony Lindgren, Sawant, Anand, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

On 8/4/2010 12:15 PM, Shilimkar, Santosh wrote:
>> From: Cousson, Benoit
>> Sent: Wednesday, August 04, 2010 3:38 PM
>>
>> On 8/4/2010 2:35 AM, G, Manjunath Kondaiah wrote:
>>> Kevin,
>>>
>>>> From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>> Sent: Wednesday, August 04, 2010 3:27 AM
>>>>
>>>> Manjunatha GK<manjugk@ti.com>   writes:
>>>>
>>>>> This patch adds OMAP3 DMA hwmod structures.
>>>>>
>>>>> Signed-off-by: Manjunatha GK<manjugk@ti.com>
>>>>
>>>> [...]
>>>>
>>>>> +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	= "l3_div_ck",
>>>>> +	.prcm = {
>>>>> +		.omap2 = {
>>>>> +			/* .clkctrl_reg = NULL, */
>>>>> +		},
>>>>> +	},
>>>>
>>>> Has this been tested?  Without valid fields here the hwmod
>>>> will never be
>>>> enabled.
>>>
>>> This patch series has been tested on both omap3 and omap4. I didn't find
>>> any entries for DMA module in prcm-common.h(for assigning .module_bit
>> etc)
>>> hence I commented this for clarification.
>>
>> There is no explicit PRCM control for the SDMA. You can just access the
>> standby status and change the sysconfig idle and standby settings.
>> It uses the L3 interface clock as functional clock.
>> You should still use HWMOD_NO_IDLEST status to prevent the enable to
>> crash.
>>
>> In your case, I think that you are probably never explicitly enabling or
>> disabling the dma device due to the library kind of API and the fact
>> that the HW is managing is automatically, isn't it?
>>
>> We had the same kind of discussion for the hwspinlock. Since these IPs
>> are using interface clock as a functional clock, there is no need to
>> explicitly enable them. But we should, otherwise we have no way to track
>> the usage of this IP and potentially to enable the power domain that
>> contains these IP.
>>
>> Each time a dma channel is requested, you should call the
>> pm_runtime_get, and pm_runtime_put() when the channel is not needed
>> anymore.
>>
> Request call can get called on multiple channels.
> So at the time of request a channel, other channels might be already
> in use. So logically " pm_runtime_put" should only be done if
> reserved channels are 0

The point is to "enable" the device when at least one channel is in use 
and "disable" it when every channel are released. We do have only one 
DMA IP that managed severals channels, since pm_runtime is doing 
reference counting, we can call get for each channel request and put for 
each release.
Did I miss something?


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

* RE: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-04 10:23           ` Cousson, Benoit
@ 2010-08-04 10:27             ` Shilimkar, Santosh
  2010-08-04 10:36               ` Cousson, Benoit
  0 siblings, 1 reply; 29+ messages in thread
From: Shilimkar, Santosh @ 2010-08-04 10:27 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: G, Manjunath Kondaiah, Kevin Hilman, linux-omap, Paul Walmsley,
	Tony Lindgren, Sawant, Anand, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

> -----Original Message-----
> From: Cousson, Benoit
> Sent: Wednesday, August 04, 2010 3:53 PM
> To: Shilimkar, Santosh
> Cc: G, Manjunath Kondaiah; Kevin Hilman; linux-omap@vger.kernel.org; Paul
> Walmsley; Tony Lindgren; Sawant, Anand; Nayak, Rajendra; Basak, Partha;
> Varadarajan, Charulatha
> Subject: Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
> 
> On 8/4/2010 12:15 PM, Shilimkar, Santosh wrote:
> >> From: Cousson, Benoit
> >> Sent: Wednesday, August 04, 2010 3:38 PM
> >>
> >> On 8/4/2010 2:35 AM, G, Manjunath Kondaiah wrote:
> >>> Kevin,
> >>>
> >>>> From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
> >>>> Sent: Wednesday, August 04, 2010 3:27 AM
> >>>>
> >>>> Manjunatha GK<manjugk@ti.com>   writes:
> >>>>
> >>>>> This patch adds OMAP3 DMA hwmod structures.
> >>>>>
> >>>>> Signed-off-by: Manjunatha GK<manjugk@ti.com>
> >>>>
> >>>> [...]
> >>>>
> >>>>> +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	= "l3_div_ck",
> >>>>> +	.prcm = {
> >>>>> +		.omap2 = {
> >>>>> +			/* .clkctrl_reg = NULL, */
> >>>>> +		},
> >>>>> +	},
> >>>>
> >>>> Has this been tested?  Without valid fields here the hwmod
> >>>> will never be
> >>>> enabled.
> >>>
> >>> This patch series has been tested on both omap3 and omap4. I didn't
> find
> >>> any entries for DMA module in prcm-common.h(for assigning .module_bit
> >> etc)
> >>> hence I commented this for clarification.
> >>
> >> There is no explicit PRCM control for the SDMA. You can just access the
> >> standby status and change the sysconfig idle and standby settings.
> >> It uses the L3 interface clock as functional clock.
> >> You should still use HWMOD_NO_IDLEST status to prevent the enable to
> >> crash.
> >>
> >> In your case, I think that you are probably never explicitly enabling
> or
> >> disabling the dma device due to the library kind of API and the fact
> >> that the HW is managing is automatically, isn't it?
> >>
> >> We had the same kind of discussion for the hwspinlock. Since these IPs
> >> are using interface clock as a functional clock, there is no need to
> >> explicitly enable them. But we should, otherwise we have no way to
> track
> >> the usage of this IP and potentially to enable the power domain that
> >> contains these IP.
> >>
> >> Each time a dma channel is requested, you should call the
> >> pm_runtime_get, and pm_runtime_put() when the channel is not needed
> >> anymore.
> >>
> > Request call can get called on multiple channels.
> > So at the time of request a channel, other channels might be already
> > in use. So logically " pm_runtime_put" should only be done if
> > reserved channels are 0
> 
> The point is to "enable" the device when at least one channel is in use
> and "disable" it when every channel are released. We do have only one
> DMA IP that managed severals channels, since pm_runtime is doing
> reference counting, we can call get for each channel request and put for
> each release.
> Did I miss something?
We are saying same thing more or less :) 
Since it's one IP, and say have one clock, then doing per channel runtime
get/put is redundant, No?



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

* Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-04 10:27             ` Shilimkar, Santosh
@ 2010-08-04 10:36               ` Cousson, Benoit
  2010-08-04 10:38                 ` Shilimkar, Santosh
  0 siblings, 1 reply; 29+ messages in thread
From: Cousson, Benoit @ 2010-08-04 10:36 UTC (permalink / raw)
  To: Shilimkar, Santosh
  Cc: G, Manjunath Kondaiah, Kevin Hilman, linux-omap, Paul Walmsley,
	Tony Lindgren, Sawant, Anand, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

On 8/4/2010 12:27 PM, Shilimkar, Santosh wrote:
>> -----Original Message-----
>> From: Cousson, Benoit
>> Sent: Wednesday, August 04, 2010 3:53 PM
>> To: Shilimkar, Santosh
>> Cc: G, Manjunath Kondaiah; Kevin Hilman; linux-omap@vger.kernel.org; Paul
>> Walmsley; Tony Lindgren; Sawant, Anand; Nayak, Rajendra; Basak, Partha;
>> Varadarajan, Charulatha
>> Subject: Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
>>
>> On 8/4/2010 12:15 PM, Shilimkar, Santosh wrote:
>>>> From: Cousson, Benoit
>>>> Sent: Wednesday, August 04, 2010 3:38 PM
>>>>
>>>> On 8/4/2010 2:35 AM, G, Manjunath Kondaiah wrote:
>>>>> Kevin,
>>>>>
>>>>>> From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>>>> Sent: Wednesday, August 04, 2010 3:27 AM
>>>>>>
>>>>>> Manjunatha GK<manjugk@ti.com>    writes:
>>>>>>
>>>>>>> This patch adds OMAP3 DMA hwmod structures.
>>>>>>>
>>>>>>> Signed-off-by: Manjunatha GK<manjugk@ti.com>
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>>> +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	= "l3_div_ck",
>>>>>>> +	.prcm = {
>>>>>>> +		.omap2 = {
>>>>>>> +			/* .clkctrl_reg = NULL, */
>>>>>>> +		},
>>>>>>> +	},
>>>>>>
>>>>>> Has this been tested?  Without valid fields here the hwmod
>>>>>> will never be
>>>>>> enabled.
>>>>>
>>>>> This patch series has been tested on both omap3 and omap4. I didn't
>> find
>>>>> any entries for DMA module in prcm-common.h(for assigning .module_bit
>>>> etc)
>>>>> hence I commented this for clarification.
>>>>
>>>> There is no explicit PRCM control for the SDMA. You can just access the
>>>> standby status and change the sysconfig idle and standby settings.
>>>> It uses the L3 interface clock as functional clock.
>>>> You should still use HWMOD_NO_IDLEST status to prevent the enable to
>>>> crash.
>>>>
>>>> In your case, I think that you are probably never explicitly enabling
>> or
>>>> disabling the dma device due to the library kind of API and the fact
>>>> that the HW is managing is automatically, isn't it?
>>>>
>>>> We had the same kind of discussion for the hwspinlock. Since these IPs
>>>> are using interface clock as a functional clock, there is no need to
>>>> explicitly enable them. But we should, otherwise we have no way to
>> track
>>>> the usage of this IP and potentially to enable the power domain that
>>>> contains these IP.
>>>>
>>>> Each time a dma channel is requested, you should call the
>>>> pm_runtime_get, and pm_runtime_put() when the channel is not needed
>>>> anymore.
>>>>
>>> Request call can get called on multiple channels.
>>> So at the time of request a channel, other channels might be already
>>> in use. So logically " pm_runtime_put" should only be done if
>>> reserved channels are 0
>>
>> The point is to "enable" the device when at least one channel is in use
>> and "disable" it when every channel are released. We do have only one
>> DMA IP that managed several channels, since pm_runtime is doing
>> reference counting, we can call get for each channel request and put for
>> each release.
>> Did I miss something?
> We are saying same thing more or less :)

That was my impression as well, but I was not sure :-)

> Since it's one IP, and say have one clock, then doing per channel runtime
> get/put is redundant, No?

If the DMA driver is already counting the number of channel in use, 
you're right we can avoid that. It is already the case today?

Benoit


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

* RE: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-04 10:36               ` Cousson, Benoit
@ 2010-08-04 10:38                 ` Shilimkar, Santosh
  2010-08-04 17:24                   ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 29+ messages in thread
From: Shilimkar, Santosh @ 2010-08-04 10:38 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: G, Manjunath Kondaiah, Kevin Hilman, linux-omap, Paul Walmsley,
	Tony Lindgren, Sawant, Anand, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha



> -----Original Message-----
> From: Cousson, Benoit
> Sent: Wednesday, August 04, 2010 4:06 PM
> To: Shilimkar, Santosh
> Cc: G, Manjunath Kondaiah; Kevin Hilman; linux-omap@vger.kernel.org; Paul
> Walmsley; Tony Lindgren; Sawant, Anand; Nayak, Rajendra; Basak, Partha;
> Varadarajan, Charulatha
> Subject: Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
> 
<snip>
> >>
> >> The point is to "enable" the device when at least one channel is in use
> >> and "disable" it when every channel are released. We do have only one
> >> DMA IP that managed several channels, since pm_runtime is doing
> >> reference counting, we can call get for each channel request and put
> for
> >> each release.
> >> Did I miss something?
> > We are saying same thing more or less :)
> 
> That was my impression as well, but I was not sure :-)
> 
> > Since it's one IP, and say have one clock, then doing per channel
> runtime
> > get/put is redundant, No?
> 
> If the DMA driver is already counting the number of channel in use,
> you're right we can avoid that. It is already the case today?
> 
Yes. That's the case I was refrering

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

* RE: [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes
  2010-08-04 10:13       ` Cousson, Benoit
@ 2010-08-04 17:21         ` G, Manjunath Kondaiah
  2010-08-04 18:13           ` Gadiyar, Anand
  0 siblings, 1 reply; 29+ messages in thread
From: G, Manjunath Kondaiah @ 2010-08-04 17:21 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: linux-omap, Kevin Hilman, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha



> -----Original Message-----
> From: Cousson, Benoit 
> Sent: Wednesday, August 04, 2010 3:44 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Kevin Hilman; Paul Walmsley; 
> Tony Lindgren; Sawant, Anand; Shilimkar, Santosh; Nayak, 
> Rajendra; Basak, Partha; Varadarajan, Charulatha
> Subject: Re: [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes
> 
> On 7/30/2010 5:57 AM, G, Manjunath Kondaiah wrote:
> 
> <snip>
> 
> >>> +/* Attributes for OMAP DMA Contrllers */
> >>> +#define ENABLE_1510_MODE		(1<<   0)
> >>> +#define DMA_LINKED_LCH			(1<<   1)
> >>> +#define GLOBAL_PRIORITY			(1<<   2)
> >>> +#define RESERVE_CHANNEL			(1<<   3)
> >>> +#define SRC_PORT			(2<<   3)
> >>> +#define DST_PORT			(2<<   4)
> >>> +#define IS_CSSA_32			(2<<   5)
> >>> +#define IS_CDSA_32			(2<<   6)
> >>> +#define SRC_INDEX			(4<<   6)
> >>> +#define DST_INDEX			(4<<   7)
> >>> +#define IS_BURST_ONLY4			(4<<   8)
> >>> +#define CLEAR_CSR_ON_READ		(4<<   9)
> >>> +#define IS_WORD_16			(8<<   9)
> >>> +#define IS_RW_PRIORIY			(8<<   0xA)
> >>
> >> It is a minor detail, but why are you shifting both side of the
> >> operator? It is really confusing, cannot you just do 1<<  X?
> >> With 0<  X<  13.
> > I can change this if it is confusing to others.
> 
> So you are still convince that this is a good way to do it???
> What is the rational behind that?
> Why adding potential source of confusion when you can avoid 
> that easily?

There is no specific reason/rationale. Left side bit keeps incrementing
for every four bits and right side bit keeps incrementing every time except
during left bit increment.
As I mentioned earlier, I can change this to your logic or we can have something like:
0x0001, 0x0002, 0x0004, 0x0008, 0x0010 ...

-Manjunath

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

* RE: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-04 10:38                 ` Shilimkar, Santosh
@ 2010-08-04 17:24                   ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 29+ messages in thread
From: G, Manjunath Kondaiah @ 2010-08-04 17:24 UTC (permalink / raw)
  To: Shilimkar, Santosh, Cousson, Benoit
  Cc: Kevin Hilman, linux-omap, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Nayak, Rajendra, Basak, Partha, Varadarajan, Charulatha





> -----Original Message-----
> From: Shilimkar, Santosh 
> Sent: Wednesday, August 04, 2010 4:08 PM
> To: Cousson, Benoit
> Cc: G, Manjunath Kondaiah; Kevin Hilman; 
> linux-omap@vger.kernel.org; Paul Walmsley; Tony Lindgren; 
> Sawant, Anand; Nayak, Rajendra; Basak, Partha; Varadarajan, Charulatha
> Subject: RE: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod data 
> structures
> 
> 
> 
> > -----Original Message-----
> > From: Cousson, Benoit
> > Sent: Wednesday, August 04, 2010 4:06 PM
> > To: Shilimkar, Santosh
> > Cc: G, Manjunath Kondaiah; Kevin Hilman; 
> linux-omap@vger.kernel.org; Paul
> > Walmsley; Tony Lindgren; Sawant, Anand; Nayak, Rajendra; 
> Basak, Partha;
> > Varadarajan, Charulatha
> > Subject: Re: [PATCH 04/11] OMAP3: DMA: HWMOD: Add hwmod 
> data structures
> > 
> <snip>
> > >>
> > >> The point is to "enable" the device when at least one 
> channel is in use
> > >> and "disable" it when every channel are released. We do 
> have only one
> > >> DMA IP that managed several channels, since pm_runtime is doing
> > >> reference counting, we can call get for each channel 
> request and put
> > for
> > >> each release.
> > >> Did I miss something?
> > > We are saying same thing more or less :)
> > 
> > That was my impression as well, but I was not sure :-)
> > 
> > > Since it's one IP, and say have one clock, then doing per channel
> > runtime
> > > get/put is redundant, No?
> > 
> > If the DMA driver is already counting the number of channel in use,
> > you're right we can avoid that. It is already the case today?
> > 
> Yes. That's the case I was refrering
> 

Agreed. I will incorporate this comment in next version.

-Manjunath

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

* RE: [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes
  2010-08-04 17:21         ` G, Manjunath Kondaiah
@ 2010-08-04 18:13           ` Gadiyar, Anand
  0 siblings, 0 replies; 29+ messages in thread
From: Gadiyar, Anand @ 2010-08-04 18:13 UTC (permalink / raw)
  To: G, Manjunath Kondaiah, Cousson, Benoit
  Cc: linux-omap, Kevin Hilman, Paul Walmsley, Tony Lindgren, Sawant,
	Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak, Partha,
	Varadarajan, Charulatha

G, Manjunath Kondaiah [manjugk@ti.com] wrote:
> > From: Cousson, Benoit
> > On 7/30/2010 5:57 AM, G, Manjunath Kondaiah wrote:
> >
> > <snip>
> >
> > >>> +/* Attributes for OMAP DMA Contrllers */
> > >>> +#define ENABLE_1510_MODE         (1<<   0)
> > >>> +#define DMA_LINKED_LCH                   (1<<   1)
> > >>> +#define GLOBAL_PRIORITY                  (1<<   2)
> > >>> +#define RESERVE_CHANNEL                  (1<<   3)
> > >>> +#define SRC_PORT                 (2<<   3)
> > >>> +#define DST_PORT                 (2<<   4)
> > >>> +#define IS_CSSA_32                       (2<<   5)
> > >>> +#define IS_CDSA_32                       (2<<   6)
> > >>> +#define SRC_INDEX                        (4<<   6)
> > >>> +#define DST_INDEX                        (4<<   7)
> > >>> +#define IS_BURST_ONLY4                   (4<<   8)
> > >>> +#define CLEAR_CSR_ON_READ                (4<<   9)
> > >>> +#define IS_WORD_16                       (8<<   9)
> > >>> +#define IS_RW_PRIORIY                    (8<<   0xA)
> > >>
> > >> It is a minor detail, but why are you shifting both side of the
> > >> operator? It is really confusing, cannot you just do 1<<  X?
> > >> With 0<  X<  13.
> > > I can change this if it is confusing to others.
> >
> > So you are still convince that this is a good way to do it???
> > What is the rational behind that?
> > Why adding potential source of confusion when you can avoid
> > that easily?
> 
> There is no specific reason/rationale. Left side bit keeps incrementing
> for every four bits and right side bit keeps incrementing every time except
> during left bit increment.
> As I mentioned earlier, I can change this to your logic or we can have something like:
> 0x0001, 0x0002, 0x0004, 0x0008, 0x0010 ...
> 
> -Manjunath

Please, just use BIT(i) for things like these.

It's much more clear, when you look up some bitfield in the TRM.

The TRM doesn't group the bits within a register in groups of 4,
and you'll need to do more mental math to figure out what you're
looking at.

- Anand

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

* RE: [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (10 preceding siblings ...)
  2010-07-29  9:59 ` [PATCH 11/11] sDMA: descriptor autoloading feature Manjunatha GK
@ 2010-08-11  7:43 ` G, Manjunath Kondaiah
  11 siblings, 0 replies; 29+ messages in thread
From: G, Manjunath Kondaiah @ 2010-08-11  7:43 UTC (permalink / raw)
  To: G, Manjunath Kondaiah, linux-omap
  Cc: Cousson, Benoit, Kevin Hilman, Paul Walmsley, Tony Lindgren,
	Sawant, Anand, Shilimkar, Santosh, Nayak, Rajendra, Basak,
	Partha, Varadarajan, Charulatha

So far, the following comments are received.

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

If there are no further comments for this patch series, I will
incorporate review comments and post next version.

Regards,
Manjunath 

> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org 
> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, 
> Manjunath Kondaiah
> Sent: Thursday, July 29, 2010 3:29 PM
> To: linux-omap@vger.kernel.org
> Cc: Cousson, Benoit; Kevin Hilman; Paul Walmsley; Tony 
> Lindgren; Sawant, Anand; Shilimkar, Santosh; Nayak, Rajendra; 
> Basak, Partha; Varadarajan, Charulatha
> Subject: [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver
> 
> This patch series is refined version of earlier patches posted at:
> http://www.spinics.net/lists/linux-omap/index.html#33393
> 
> 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)
> 
> This patch series applies on top of:
> git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-om
> ap-pm.git
> Branch: pm-wip/hwmods-omap4
> commit f1c79ab452ed9cf7b5ff6488335c1ddf15d5c92a
> Author: Benoit Cousson <b-cousson@ti.com>
> Date:   Wed May 12 17:54:37 2010 +0200
> 
>     OMAP4: hwmod: Enable omap_hwmod build for OMAP4
> 
> Patch series summary:
> =====================
> Manjunatha GK (10):
>   OMAP: DMA: Introduce DMA device attributes
>   OMAP2420: DMA: HWMOD: Add hwmod data structures
>   OMAP2430: DMA: HWMOD: Add hwmod data structures
>   OMAP3: DMA: HWMOD: Add hwmod data structures
>   OMAP4: DMA: HWMOD: update OMAP4 data base
>   OMAP1: DMA: Introduce DMA driver as platform driver
>   OMAP2/3/4: DMA: HWMOD: Device registration
>   OMAP: DMA: Convert DMA library into DMA platform Driver
>   OMAP: DMA: Implement generic errata handling
>   OMAP: DMA: Use DMA device attributes
> 
> Venkatraman S (1):
>   sDMA: descriptor autoloading feature
> 
>  arch/arm/mach-omap1/Makefile               |    2 +-
>  arch/arm/mach-omap1/dma.c                  |  446 ++++++++
>  arch/arm/mach-omap1/include/mach/dma.h     |  148 +++
>  arch/arm/mach-omap2/Makefile               |    2 +-
>  arch/arm/mach-omap2/dma.c                  | 1380 
> +++++++++++++++++++++++++
>  arch/arm/mach-omap2/include/mach/dma.h     |  378 +++++++
>  arch/arm/mach-omap2/omap_hwmod_2420_data.c |   89 ++
>  arch/arm/mach-omap2/omap_hwmod_2430_data.c |   89 ++
>  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   89 ++
>  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   19 +-
>  arch/arm/plat-omap/dma.c                   | 1515 
> +++-------------------------
>  arch/arm/plat-omap/include/plat/dma.h      |  222 +----
>  12 files changed, 2850 insertions(+), 1529 deletions(-)
>  create mode 100644 arch/arm/mach-omap1/dma.c
>  create mode 100644 arch/arm/mach-omap1/include/mach/dma.h
>  create mode 100644 arch/arm/mach-omap2/dma.c
>  create mode 100644 arch/arm/mach-omap2/include/mach/dma.h
> 
> --
> 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] 29+ messages in thread

end of thread, other threads:[~2010-08-11  7:44 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-29  9:58 [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
2010-07-29  9:58 ` [PATCH 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
2010-07-29 12:35   ` Cousson, Benoit
2010-07-30  3:57     ` G, Manjunath Kondaiah
2010-08-04 10:13       ` Cousson, Benoit
2010-08-04 17:21         ` G, Manjunath Kondaiah
2010-08-04 18:13           ` Gadiyar, Anand
2010-07-29  9:58 ` [PATCH 02/11] OMAP2420: DMA: HWMOD: Add hwmod data structures Manjunatha GK
2010-07-29  9:58 ` [PATCH 03/11] OMAP2430: " Manjunatha GK
2010-07-29  9:58 ` [PATCH 04/11] OMAP3: " Manjunatha GK
2010-08-03 21:56   ` Kevin Hilman
2010-08-04  0:35     ` G, Manjunath Kondaiah
2010-08-04 10:08       ` Cousson, Benoit
2010-08-04 10:15         ` Shilimkar, Santosh
2010-08-04 10:23           ` Cousson, Benoit
2010-08-04 10:27             ` Shilimkar, Santosh
2010-08-04 10:36               ` Cousson, Benoit
2010-08-04 10:38                 ` Shilimkar, Santosh
2010-08-04 17:24                   ` G, Manjunath Kondaiah
2010-07-29  9:58 ` [PATCH 05/11] OMAP4: DMA: HWMOD: update OMAP4 data base Manjunatha GK
2010-07-29 12:48   ` Cousson, Benoit
2010-07-29  9:59 ` [PATCH 06/11] OMAP1: DMA: Introduce DMA driver as platform driver Manjunatha GK
2010-07-29  9:59 ` [PATCH 07/11] OMAP2/3/4: DMA: HWMOD: Device registration Manjunatha GK
2010-07-29  9:59 ` [PATCH 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver Manjunatha GK
2010-07-29  9:59 ` [PATCH 09/11] OMAP: DMA: Implement generic errata handling Manjunatha GK
2010-07-29  9:59 ` [PATCH 10/11] OMAP: DMA: Use DMA device attributes Manjunatha GK
2010-07-29  9:59 ` [PATCH 11/11] sDMA: descriptor autoloading feature Manjunatha GK
2010-07-29 10:30   ` G, Manjunath Kondaiah
2010-08-11  7:43 ` [PATCH 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah

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.