All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
@ 2010-08-24 11:04 Manjunatha GK
  2010-08-24 11:04 ` [PATCH v2 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
                   ` (12 more replies)
  0 siblings, 13 replies; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

This patch series has review comments incorporated which are received
for v1 version.
The review comments can be found at:
http://www.spinics.net/lists/linux-omap/msg34291.html
http://www.spinics.net/lists/linux-omap/msg34292.html
http://www.spinics.net/lists/linux-omap/msg34078.html
http://www.spinics.net/lists/linux-omap/msg34083.html

These changes are tested on following boards:
- Zoom3     (OMAP3630)
- Beagle    (OMAP3530)
- OMAP4 SDP (OMAP4430)
I don't have omap1 and omap2 boards and appreciate if 
some one can test these boards and provides feedback.

Build tested for both omap1 and omap2 plus boards.

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 f6f7f1103b80b4dc0ace8a0314d95d1b1ebca726
Merge: 79d0b02 597e89c
Author: Kevin Hilman <khilman@ti.com>

    Merge branch 'pm-wip/hwmods' into pm-wip/hwmods-omap4-base

The earlier version of the patches can be found at:
RFC patches:
http://www.spinics.net/lists/linux-omap/index.html#33393

v1 patches:
http://www.spinics.net/lists/linux-omap/msg34066.html

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: Add hwmod data structures
  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                  |  451 ++++++++
 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 |   85 ++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   85 ++
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   85 ++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   99 ++
 arch/arm/plat-omap/dma.c                   | 1539 ++++------------------------
 arch/arm/plat-omap/include/plat/dma.h      |  222 +---
 12 files changed, 2945 insertions(+), 1531 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

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>

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

* [PATCH v2 01/11] OMAP: DMA: Introduce DMA device attributes
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-08-24 11:04 ` [PATCH v2 02/11] OMAP2420: DMA: HWMOD: Add hwmod data structures Manjunatha GK
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

This patch 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>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@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 af3a039..67b9489 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -399,6 +399,22 @@
 #define DMA_CH_PRIO_HIGH		0x1
 #define DMA_CH_PRIO_LOW			0x0 /* Def */
 
+/* Attributes for OMAP DMA Contrllers */
+#define ENABLE_1510_MODE		(1 << 0x0)
+#define DMA_LINKED_LCH			(1 << 0x1)
+#define GLOBAL_PRIORITY			(1 << 0x2)
+#define RESERVE_CHANNEL			(1 << 0x3)
+#define SRC_PORT			(1 << 0x4)
+#define DST_PORT			(1 << 0x5)
+#define IS_CSSA_32			(1 << 0x6)
+#define IS_CDSA_32			(1 << 0x7)
+#define SRC_INDEX			(1 << 0x8)
+#define DST_INDEX			(1 << 0x9)
+#define IS_BURST_ONLY4			(1 << 0xA)
+#define CLEAR_CSR_ON_READ		(1 << 0xB)
+#define IS_WORD_16			(1 << 0xC)
+#define IS_RW_PRIORIY			(1 << 0xD)
+
 enum omap_dma_burst_mode {
 	OMAP_DMA_DATA_BURST_DIS = 0,
 	OMAP_DMA_DATA_BURST_4,
@@ -464,6 +480,12 @@ struct omap_dma_channel_params {
 #endif
 };
 
+struct omap_dma_dev_attr {
+	u32 dev_caps;
+	u16 lch_count;
+	u16 chan_count;
+	struct omap_dma_lch *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] 62+ messages in thread

* [PATCH v2 02/11] OMAP2420: DMA: HWMOD: Add hwmod data structures
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
  2010-08-24 11:04 ` [PATCH v2 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-08-24 11:04 ` [PATCH v2 03/11] OMAP2430: " Manjunatha GK
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

This patch adds OMAP2420 DMA hwmod structures.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   85 ++++++++++++++++++++++++++++
 1 files changed, 85 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 3cc768e..1480272 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -33,6 +33,7 @@ static struct omap_hwmod omap2420_mpu_hwmod;
 static struct omap_hwmod omap2420_iva_hwmod;
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
+static struct omap_hwmod omap2420_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -165,12 +166,96 @@ static struct omap_hwmod omap2420_iva_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 = {
+	.dev_caps  = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32,
+	.lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT,
+};
+
+static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
+	{ .name = "0", .irq = INT_24XX_SDMA_IRQ0 },
+	{ .name = "1", .irq = INT_24XX_SDMA_IRQ1 },
+	{ .name = "2", .irq = INT_24XX_SDMA_IRQ2 },
+	{ .name = "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",
+	.slaves		= omap2420_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dma_system_slaves),
+	.masters	= omap2420_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2420_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 	&omap2420_l3_main_hwmod,
 	&omap2420_l4_core_hwmod,
 	&omap2420_l4_wkup_hwmod,
 	&omap2420_mpu_hwmod,
 	&omap2420_iva_hwmod,
+	&omap2420_dma_system_hwmod,
 	NULL,
 };
 
-- 
1.7.0.4


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

* [PATCH v2 03/11] OMAP2430: DMA: HWMOD: Add hwmod data structures
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
  2010-08-24 11:04 ` [PATCH v2 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
  2010-08-24 11:04 ` [PATCH v2 02/11] OMAP2420: DMA: HWMOD: Add hwmod data structures Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-08-24 11:30   ` Mika Westerberg
  2010-08-24 11:04 ` [PATCH v2 04/11] OMAP3: " Manjunatha GK
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

This patch adds OMAP2430 DMA hwmod structures.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   85 ++++++++++++++++++++++++++++
 1 files changed, 85 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 4526628..3d79a52 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -33,6 +33,7 @@ static struct omap_hwmod omap2430_mpu_hwmod;
 static struct omap_hwmod omap2430_iva_hwmod;
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
+static struct omap_hwmod omap2430_dma_system_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -165,12 +166,96 @@ static struct omap_hwmod omap2430_iva_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
+/* dma_system */
+static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap2430_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
+	.lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT,
+};
+
+static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
+	{ .name = "0", .irq = INT_24XX_SDMA_IRQ0 },
+	{ .name = "1", .irq = INT_24XX_SDMA_IRQ1 },
+	{ .name = "2", .irq = INT_24XX_SDMA_IRQ2 },
+	{ .name = "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",
+	.slaves		= omap2430_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dma_system_slaves),
+	.masters	= omap2430_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 	&omap2430_l3_main_hwmod,
 	&omap2430_l4_core_hwmod,
 	&omap2430_l4_wkup_hwmod,
 	&omap2430_mpu_hwmod,
 	&omap2430_iva_hwmod,
+	&omap2430_dma_system_hwmod,
 	NULL,
 };
 
-- 
1.7.0.4


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

* [PATCH v2 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (2 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 03/11] OMAP2430: " Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-09-03 20:51   ` Kevin Hilman
  2010-08-24 11:04 ` [PATCH v2 05/11] OMAP4: " Manjunatha GK
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

This patch adds OMAP3 DMA hwmod structures.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   85 ++++++++++++++++++++++++++++
 1 files changed, 85 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 5d8eb58..0979c51 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,89 @@ 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 = {
+	.dev_caps  = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
+	.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 = "0", .irq = INT_24XX_SDMA_IRQ0 },
+	{ .name = "1", .irq = INT_24XX_SDMA_IRQ1 },
+	{ .name = "2", .irq = INT_24XX_SDMA_IRQ2 },
+	{ .name = "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",
+	.slaves		= omap3xxx_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves),
+	.masters	= omap3xxx_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l3_main_hwmod,
 	&omap3xxx_l4_core_hwmod,
@@ -204,6 +288,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] 62+ messages in thread

* [PATCH v2 05/11] OMAP4: DMA: HWMOD: Add hwmod data structures
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (3 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 04/11] OMAP3: " Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-08-24 11:04 ` [PATCH v2 06/11] OMAP1: DMA: Introduce DMA driver as platform driver Manjunatha GK
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

This patch adds OMAP4430 DMA hwmod structures.

Signed-off-by: Manjunatha GK <manjugk@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   99 ++++++++++++++++++++++++++++
 1 files changed, 99 insertions(+), 0 deletions(-)

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


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

* [PATCH v2 06/11] OMAP1: DMA: Introduce DMA driver as platform driver
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (4 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 05/11] OMAP4: " Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-08-24 11:04 ` [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration Manjunatha GK
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

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>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@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..26ab6e3
--- /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   = "0",
+		.start  = INT_DMA_CH0_6,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.name   = "1",
+		.start  = INT_DMA_CH1_7,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.name   = "2",
+		.start  = INT_DMA_CH2_8,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[4] = {
+		.name   = "3",
+		.start  = INT_DMA_CH3,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[5] = {
+		.name   = "4",
+		.start  = INT_DMA_CH4,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[6] = {
+		.name   = "5",
+		.start  = INT_DMA_CH5,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[7] = {
+		.name   = "6",
+		.start  = INT_DMA_LCD,
+		.flags  = IORESOURCE_IRQ,
+	},
+	/* irq's for omap16xx and omap7xx */
+	[8] = {
+		.name   = "7",
+		.start  = 53 + IH2_BASE,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[9] = {
+		.name   = "8",
+		.start  = 54 + IH2_BASE,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[10] = {
+		.name  = "9",
+		.start = 55 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[11] = {
+		.name  = "10",
+		.start = 56 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[12] = {
+		.name  = "11",
+		.start = 57 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[13] = {
+		.name  = "12",
+		.start = 58 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[14] = {
+		.name  = "13",
+		.start = 59 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[15] = {
+		.name  = "14",
+		.start = 60 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[16] = {
+		.name  = "15",
+		.start = 61 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+	[17] = {
+		.name  = "16",
+		.start = 62 + IH2_BASE,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static 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->dev_caps = 0;
+
+	if (cpu_is_omap15xx())
+		d->dev_caps = ENABLE_1510_MODE;
+
+	d->dev_caps			|= SRC_PORT;
+	d->dev_caps			|= DST_PORT;
+	d->dev_caps			|= SRC_INDEX;
+	d->dev_caps			|= DST_INDEX;
+	d->dev_caps			|= IS_BURST_ONLY4;
+	d->dev_caps			|= CLEAR_CSR_ON_READ;
+	d->dev_caps			|= IS_WORD_16;
+
+	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
+
+	if (cpu_is_omap15xx())
+		d->chan_count = 9;
+	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+		if (!(d->dev_caps & ENABLE_1510_MODE))
+			d->chan_count = 16;
+		else
+			d->chan_count = 9;
+	}
+
+	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->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] 62+ messages in thread

* [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (5 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 06/11] OMAP1: DMA: Introduce DMA driver as platform driver Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-09-03 20:59   ` Kevin Hilman
  2010-08-24 11:04 ` [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver Manjunatha GK
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

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>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@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..f369bee
--- /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->chan_count = d->lch_count;
+
+	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+					(d->lch_count), GFP_KERNEL);
+
+	if (!d->chan) {
+		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+		return -ENOMEM;
+	}
+
+	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] 62+ messages in thread

* [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (6 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-09-03 22:34   ` Kevin Hilman
  2010-08-24 11:04 ` [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling Manjunatha GK
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

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.

Also, it enables and uses run time PM API's

Signed-off-by: Manjunatha GK <manjugk@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@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               |  244 +++++++++++++++++---------------
 arch/arm/plat-omap/include/plat/dma.h  |  157 ++-------------------
 6 files changed, 290 insertions(+), 264 deletions(-)

diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 9a304d8..b7dfc54 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 9b44773..6a8b231 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 pm.o
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.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 ec7eddf..36c3dde 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.
@@ -30,13 +33,17 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/system.h>
+
 #include <mach/hardware.h>
-#include <plat/dma.h>
 
+#include <plat/dma.h>
+#include <plat/omap_device.h>
 #include <plat/tc.h>
 
+
 #undef DEBUG
 
 #ifndef CONFIG_ARCH_OMAP1
@@ -60,27 +67,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;
@@ -95,6 +81,7 @@ struct dma_link_info {
 };
 
 static struct dma_link_info *dma_linked_lch;
+static struct platform_device *ddev;
 
 #ifndef CONFIG_ARCH_OMAP1
 
@@ -136,15 +123,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);
@@ -753,6 +735,8 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	chan = dma_chan + free_ch;
 	chan->dev_id = dev_id;
 
+	pm_runtime_get_sync(&ddev->dev);
+
 	if (cpu_class_is_omap1())
 		clear_lch_regs(free_ch);
 
@@ -846,6 +830,9 @@ void omap_free_dma(int lch)
 	dma_chan[lch].dev_id = -1;
 	dma_chan[lch].next_lch = -1;
 	dma_chan[lch].callback = NULL;
+
+	pm_runtime_put_sync(&ddev->dev);
+
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 EXPORT_SYMBOL(omap_free_dma);
@@ -962,7 +949,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 */
@@ -1023,7 +1010,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 {
@@ -2039,57 +2026,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[4];
+
+	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->lch_count = omap_dma_reserve_channels;
 
-	dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count,
-				GFP_KERNEL);
-	if (!dma_chan) {
-		r = -ENOMEM;
-		goto out_unmap;
-	}
+	dma_lch_count		= d->lch_count;
+	dma_chan_count		= d->chan_count;
+	dma_chan		= d->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->dev_caps & 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));
@@ -2107,21 +2093,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())
@@ -2138,19 +2117,30 @@ static int __init omap_init_dma(void)
 			 * request_irq() doesn't like dev_id (ie. ch) being
 			 * zero, so we have to kludge around this.
 			 */
-			r = request_irq(omap1_dma_irq[ch],
+			sprintf(&irq_name[0], "%d", ch);
+			dma_irq = platform_get_irq_byname(pdev, irq_name);
+
+			if (dma_irq < 0) {
+				dev_err(&pdev->dev, "%s:unable to get irq\n",
+								__func__);
+				ret = dma_irq;
+				goto exit_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;
+				}
 			}
 		}
 	}
@@ -2160,46 +2150,72 @@ 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, "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;
+	}
+
+	/* Enable run timer PM */
+	ddev = pdev;
+	pm_runtime_enable(&ddev->dev);
+
+	if (omap_dma_reserve_channels)
+		pm_runtime_get_sync(&ddev->dev);
+
+	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;
+}
 
-	return r;
+static struct platform_driver omap_system_dma_driver = {
+	.probe		= omap_system_dma_probe,
+	.remove		= omap_system_dma_remove,
+	.driver		= {
+		.name	= "dma"
+	},
+};
+
+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 67b9489..a44b11b 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
@@ -373,21 +242,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
@@ -480,6 +334,7 @@ struct omap_dma_channel_params {
 #endif
 };
 
+#include <mach/dma.h>
 struct omap_dma_dev_attr {
 	u32 dev_caps;
 	u16 lch_count;
@@ -487,6 +342,12 @@ struct omap_dma_dev_attr {
 	struct omap_dma_lch *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] 62+ messages in thread

* [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (7 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-09-03 22:42   ` Kevin Hilman
  2010-09-17 15:45   ` Cousson, Benoit
  2010-08-24 11:04 ` [PATCH v2 10/11] OMAP: DMA: Use DMA device attributes Manjunatha GK
                   ` (3 subsequent siblings)
  12 siblings, 2 replies; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

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>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@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 26ab6e3..615c5f5 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 f369bee..8832bd1 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 36c3dde..409586a 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -187,6 +187,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)
 {
@@ -971,22 +990,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;
@@ -1660,7 +1673,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))) {
@@ -1675,15 +1688,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++) {
 
@@ -1702,8 +1708,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 a44b11b..ca251ac 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -269,6 +269,14 @@
 #define IS_WORD_16			(1 << 0xC)
 #define IS_RW_PRIORIY			(1 << 0xD)
 
+/* 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,
@@ -346,6 +354,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] 62+ messages in thread

* [PATCH v2 10/11] OMAP: DMA: Use DMA device attributes
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (8 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-09-03 20:45   ` Kevin Hilman
  2010-08-24 11:04 ` [PATCH v2 11/11] sDMA: descriptor autoloading feature Manjunatha GK
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Benoit Cousson, Kevin Hilman, Santosh Shilimkar

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>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap1/dma.c              |  234 +++++-
 arch/arm/mach-omap2/dma.c              |  964 ++++++++++++++++++++++-
 arch/arm/mach-omap2/include/mach/dma.h |   21 +
 arch/arm/plat-omap/dma.c               | 1398 +++-----------------------------
 arch/arm/plat-omap/include/plat/dma.h  |   36 +-
 5 files changed, 1313 insertions(+), 1340 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 615c5f5..563e60f 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->dev_caps & ENABLE_1510_MODE)) {
+		u32 l;
+
+		l = dma_read(LCH_CTRL(lch));
+		l &= ~0x7;
+		l |= mode;
+		dma_write(l, LCH_CTRL(lch));
+	}
+}
+EXPORT_SYMBOL(omap_set_dma_channel_mode);
+
+void omap_set_dma_src_index(int lch, int eidx, int fidx)
+{
+	dma_write(eidx, CSEI(lch));
+	dma_write(fidx, CSFI(lch));
+}
+EXPORT_SYMBOL(omap_set_dma_src_index);
+
+void omap_set_dma_dest_index(int lch, int eidx, int fidx)
+{
+	dma_write(eidx, CDEI(lch));
+	dma_write(fidx, CDFI(lch));
+}
+EXPORT_SYMBOL(omap_set_dma_dest_index);
+
+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[4];
+	int irq_rel;
 
 	pdev = platform_device_alloc("system_dma", 0);
 	if (!pdev) {
@@ -159,7 +323,7 @@ static int __init omap1_system_dma_init(void)
 	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 +331,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 */
@@ -184,6 +348,8 @@ static int __init omap1_system_dma_init(void)
 	if (cpu_is_omap15xx())
 		d->dev_caps = ENABLE_1510_MODE;
 
+	enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
+
 	d->dev_caps			|= SRC_PORT;
 	d->dev_caps			|= DST_PORT;
 	d->dev_caps			|= SRC_INDEX;
@@ -194,6 +360,19 @@ static int __init omap1_system_dma_init(void)
 
 	d->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->chan_count = 9;
 	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
@@ -203,36 +382,63 @@ static int __init omap1_system_dma_init(void)
 			d->chan_count = 9;
 	}
 
+	for (ch = 0; ch < d->chan_count; ch++) {
+		if (ch >= 6 && enable_1510_mode)
+			continue;
+
+		sprintf(&irq_name[0], "%d", ch);
+		dma_irq = platform_get_irq_byname(pdev, irq_name);
+		if (dma_irq < 0) {
+			dev_err(&pdev->dev, "%s:unable to get irq\n",
+								__func__);
+			ret = dma_irq;
+			goto exit_pdata;
+		}
+
+		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->chan = kzalloc(sizeof(struct omap_dma_lch) *
 					(d->lch_count), GFP_KERNEL);
 
-	if (!d->dma_chan) {
+	if (!d->chan) {
 		dev_err(&pdev->dev, "%s: Memory allcation failed"
 					"for dma_chan!!!\n", __func__);
-		goto exit_release_pdata;
+		goto exit_pdata;
 	}
+	dma_chan = d->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:
-	kfree(d->dma_chan);
-exit_release_pdata:
+exit_dma_chan:
+	kfree(d->chan);
+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;
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 8832bd1..6a5160d 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,11 +1078,19 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *user)
 		return -ENOMEM;
 	}
 
+	dma_irq = platform_get_irq_byname(&od->pdev, "0");
+	ret = setup_irq(dma_irq, &omap24xx_dma_irq);
+	if (ret) {
+		dev_err(&od->pdev.dev, "%s:irq handler setup fail\n", __func__);
+		return -EINVAL;
+	}
+
 	/* Get DMA device attributes from hwmod data base */
 	d = (struct omap_dma_dev_attr *)oh->dev_attr;
 
 	/* OMAP2 Plus: physical and logical channel count is same */
-	d->chan_count = d->lch_count;
+	d->chan_count  = d->lch_count;
+	dma_chan_count = d->chan_count;
 
 	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
 					(d->lch_count), GFP_KERNEL);
@@ -150,7 +1100,15 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *user)
 		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->chan);
+		return -ENOMEM;
+	}
+
+	dma_chan		= d->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 409586a..3934b98 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -43,98 +43,20 @@
 #include <plat/omap_device.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;
-static struct platform_device *ddev;
-
-#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 platform_device *ddev;
+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;							\
@@ -153,75 +75,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->dev_caps & IS_WORD_16) {
 		switch (dst_port) {
 		case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
 			reg = OMAP_TC_OCPT1_PRIOR;
@@ -243,9 +102,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));
@@ -269,7 +126,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->dev_caps & IS_WORD_16) {
 		u16 ccr;
 
 		ccr = dma_read(CCR(lch));
@@ -283,15 +140,13 @@ 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));
 
 		/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
-		val &= ~((1 << 23) | (3 << 19) | 0x1f);
+		val &= ~((3 << 19) | 0x1f);
 		val |= (dma_trigger & ~0x1f) << 14;
 		val |= dma_trigger & 0x1f;
 
@@ -305,14 +160,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 		else
 			val &= ~(1 << 18);
 
-		if (src_or_dst_synch == OMAP_DMA_DST_SYNC_PREFETCH) {
-			val &= ~(1 << 24);	/* dest synch */
-			val |= (1 << 23);	/* Prefetch */
-		} else if (src_or_dst_synch) {
+		if (src_or_dst_synch)
 			val |= 1 << 24;		/* source synch */
-		} else {
+		else
 			val &= ~(1 << 24);	/* dest synch */
-		}
+
 		dma_write(val, CCR(lch));
 	}
 
@@ -323,9 +175,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->dev_caps & IS_WORD_16) {
 		u16 w;
 
 		w = dma_read(CCR2(lch));
@@ -354,9 +206,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));
@@ -382,32 +232,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,
@@ -415,7 +239,7 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 {
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (d->dev_caps & SRC_PORT) {
 		u16 w;
 
 		w = dma_read(CSDP(lch));
@@ -429,12 +253,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->dev_caps & 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));
@@ -461,16 +283,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;
@@ -495,13 +307,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->dev_caps & IS_BURST_ONLY4)
 			burst = 0x2;
+		else
+			burst = 0x1;
 		break;
 	case OMAP_DMA_DATA_BURST_8:
-		if (cpu_class_is_omap2()) {
+		if (!(d->dev_caps & IS_BURST_ONLY4)) {
 			burst = 0x2;
 			break;
 		}
@@ -511,7 +323,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->dev_caps & IS_BURST_ONLY4)) {
 			burst = 0x3;
 			break;
 		}
@@ -535,7 +347,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
 {
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (d->dev_caps & DST_PORT) {
 		l = dma_read(CSDP(lch));
 		l &= ~(0x1f << 9);
 		l |= dest_port << 9;
@@ -547,12 +359,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->dev_caps & 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));
@@ -560,16 +370,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;
@@ -594,19 +394,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->dev_caps & 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->dev_caps & IS_BURST_ONLY4)
 			burst = 0x3;
+		else
+			burst = 0x2;
 		break;
 	case OMAP_DMA_DATA_BURST_16:
-		if (cpu_class_is_omap2()) {
+		if (!(d->dev_caps & IS_BURST_ONLY4)) {
 			burst = 0x3;
 			break;
 		}
@@ -624,26 +424,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;
@@ -656,81 +436,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)
@@ -754,14 +459,12 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	chan = dma_chan + free_ch;
 	chan->dev_id = dev_id;
 
-	pm_runtime_get_sync(&ddev->dev);
-
-	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);
 
+	pm_runtime_get_sync(&ddev->dev);
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
 
 	chan->dev_name = dev_name;
@@ -769,25 +472,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->dev_caps & IS_WORD_16)
 		chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
-	else if (cpu_class_is_omap2())
+	else
 		chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
-			OMAP2_DMA_TRANS_ERR_IRQ;
+						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;
 		}
 		/*
@@ -795,13 +494,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->dev_caps & 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);
@@ -823,15 +524,18 @@ void omap_free_dma(int lch)
 		return;
 	}
 
-	if (cpu_class_is_omap1()) {
+	if (d->dev_caps & IS_WORD_16) {
 		/* Disable all DMA interrupts for the channel. */
 		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));
@@ -857,39 +561,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
@@ -910,7 +581,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->dev_caps & IS_RW_PRIORIY)
 		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
 	else
 		l |= ((read_prio & 0x1) << 6);
@@ -931,7 +602,7 @@ void omap_clear_dma(int lch)
 
 	local_irq_save(flags);
 
-	if (cpu_class_is_omap1()) {
+	if (d->dev_caps & IS_WORD_16) {
 		u32 l;
 
 		l = dma_read(CCR(lch));
@@ -940,9 +611,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)
@@ -961,18 +630,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->dev_caps & 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;
@@ -985,8 +655,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);
@@ -995,7 +667,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));
 
@@ -1014,14 +687,14 @@ void omap_stop_dma(int lch)
 	u32 l;
 
 	/* Disable all interrupts on the channel */
-	if (cpu_class_is_omap1())
+	if (d->dev_caps & 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];
 
@@ -1033,7 +706,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;
@@ -1083,19 +757,16 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 {
 	dma_addr_t offset = 0;
 
-	if (cpu_is_omap15xx())
+	if (d->dev_caps & 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->dev_caps & IS_WORD_16)
 		offset |= (dma_read(CSSA_U(lch)) << 16);
 
 	return offset;
@@ -1114,19 +785,16 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
 {
 	dma_addr_t offset = 0;
 
-	if (cpu_is_omap15xx())
+	if (d->dev_caps & 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->dev_caps & IS_WORD_16)
 		offset |= (dma_read(CDSA_U(lch)) << 16);
 
 	return offset;
@@ -1143,7 +811,7 @@ int omap_dma_running(void)
 {
 	int lch;
 
-	if (cpu_class_is_omap1())
+	if (d->dev_caps & IS_WORD_16)
 		if (omap_lcd_dma_running())
 			return 1;
 
@@ -1161,7 +829,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));
@@ -1188,7 +856,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));
@@ -1217,828 +885,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[4];
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "%s: System DMA initialized without"
@@ -2059,10 +910,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->dev_caps & IS_WORD_16) && omap_dma_reserve_channels
 			&& (omap_dma_reserve_channels <= dma_lch_count))
 		d->lch_count = omap_dma_reserve_channels;
 
@@ -2070,19 +922,11 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	dma_chan_count		= d->chan_count;
 	dma_chan		= d->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->dev_caps & 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->dev_caps & 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",
@@ -2100,7 +944,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);
@@ -2109,61 +953,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.
-			 */
-			sprintf(&irq_name[0], "%d", ch);
-			dma_irq = platform_get_irq_byname(pdev, irq_name);
-
-			if (dma_irq < 0) {
-				dev_err(&pdev->dev, "%s:unable to get irq\n",
-								__func__);
-				ret = dma_irq;
-				goto exit_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->dev_caps & GLOBAL_PRIORITY)
 		omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
 				DMA_DEFAULT_FIFO_DEPTH, 0);
 
-	if (cpu_class_is_omap2()) {
-		strcpy(irq_name, "0");
-		dma_irq = platform_get_irq_byname(pdev, irq_name);
-		setup_irq(dma_irq, &omap24xx_dma_irq);
-	}
-
 	/* reserve dma channels 0 and 1 in high security devices */
-	if (cpu_is_omap34xx() &&
-		(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
+	if (d->dev_caps & RESERVE_CHANNEL) {
 		printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
 				"HS ROM code\n");
 		dma_chan[0].dev_id = 0;
@@ -2179,14 +985,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 ca251ac..3bf7c19 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -242,6 +242,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
@@ -355,6 +358,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);
@@ -418,29 +431,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] 62+ messages in thread

* [PATCH v2 11/11] sDMA: descriptor autoloading feature
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (9 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 10/11] OMAP: DMA: Use DMA device attributes Manjunatha GK
@ 2010-08-24 11:04 ` Manjunatha GK
  2010-09-03 16:21 ` [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah
  2010-09-03 20:38 ` Kevin Hilman
  12 siblings, 0 replies; 62+ messages in thread
From: Manjunatha GK @ 2010-08-24 11:04 UTC (permalink / raw)
  To: linux-omap; +Cc: Venkatraman S, Benoit Cousson, Kevin Hilman, Santosh Shilimkar

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>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Santosh Shilimkar <santosh.shilimkar@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 563e60f..5ec31e8 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 6a5160d..d5fdc36 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 3934b98..c29f30d 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -547,6 +547,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] 62+ messages in thread

* Re: [PATCH v2 03/11] OMAP2430: DMA: HWMOD: Add hwmod data structures
  2010-08-24 11:04 ` [PATCH v2 03/11] OMAP2430: " Manjunatha GK
@ 2010-08-24 11:30   ` Mika Westerberg
  2010-08-24 14:32     ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Mika Westerberg @ 2010-08-24 11:30 UTC (permalink / raw)
  To: Manjunatha GK; +Cc: linux-omap, Benoit Cousson, Kevin Hilman, Santosh Shilimkar

Hi,

On Tue, Aug 24, 2010 at 04:34:18PM +0530, Manjunatha GK wrote:
> This patch adds OMAP2430 DMA hwmod structures.
> 
> Signed-off-by: Manjunatha GK <manjugk@ti.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> ---
>  arch/arm/mach-omap2/omap_hwmod_2430_data.c |   85 ++++++++++++++++++++++++++++
>  1 files changed, 85 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 4526628..3d79a52 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
> @@ -33,6 +33,7 @@ static struct omap_hwmod omap2430_mpu_hwmod;
>  static struct omap_hwmod omap2430_iva_hwmod;
>  static struct omap_hwmod omap2430_l3_main_hwmod;
>  static struct omap_hwmod omap2430_l4_core_hwmod;
> +static struct omap_hwmod omap2430_dma_system_hwmod;
>  
>  /* L3 -> L4_CORE interface */
>  static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
> @@ -165,12 +166,96 @@ static struct omap_hwmod omap2430_iva_hwmod = {
>  	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
>  };
>  
> +/* dma_system */
> +static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
> +	.rev_offs	= 0x0000,
> +	.sysc_offs	= 0x002c,
> +	.syss_offs	= 0x0028,
> +	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
> +			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
> +			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
> +	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
> +			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
> +	.sysc_fields	= &omap_hwmod_sysc_type1,
> +};
> +
> +static struct omap_hwmod_class omap2430_dma_hwmod_class = {
> +	.name = "dma",
> +	.sysc = &omap2430_dma_sysc,
> +};
> +
> +/* dma attributes */
> +static struct omap_dma_dev_attr dma_dev_attr = {
> +	.dev_caps  = DMA_LINKED_LCH | GLOBAL_PRIORITY |
> +				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
                                                          ^^^^^^^^^^^^^

Should this be IS_RW_PRIORITY? Same typo seems to be also in other patches which
add hwmod structures.

Regards,
MW


> +	.lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT,
> +};
> +
> +static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
> +	{ .name = "0", .irq = INT_24XX_SDMA_IRQ0 },
> +	{ .name = "1", .irq = INT_24XX_SDMA_IRQ1 },
> +	{ .name = "2", .irq = INT_24XX_SDMA_IRQ2 },
> +	{ .name = "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",
> +	.slaves		= omap2430_dma_system_slaves,
> +	.slaves_cnt	= ARRAY_SIZE(omap2430_dma_system_slaves),
> +	.masters	= omap2430_dma_system_masters,
> +	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters),
> +	.dev_attr	= &dma_dev_attr,
> +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
> +	.flags		= HWMOD_NO_IDLEST,
> +};
> +
>  static __initdata struct omap_hwmod *omap2430_hwmods[] = {
>  	&omap2430_l3_main_hwmod,
>  	&omap2430_l4_core_hwmod,
>  	&omap2430_l4_wkup_hwmod,
>  	&omap2430_mpu_hwmod,
>  	&omap2430_iva_hwmod,
> +	&omap2430_dma_system_hwmod,
>  	NULL,
>  };
>  
> -- 
> 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	[flat|nested] 62+ messages in thread

* RE: [PATCH v2 03/11] OMAP2430: DMA: HWMOD: Add hwmod data structures
  2010-08-24 11:30   ` Mika Westerberg
@ 2010-08-24 14:32     ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-08-24 14:32 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: linux-omap, Cousson, Benoit, Kevin Hilman, Shilimkar, Santosh



> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@gmail.com] On 
> Behalf Of Mika Westerberg
> Sent: Tuesday, August 24, 2010 5:01 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Kevin 
> Hilman; Shilimkar, Santosh
> Subject: Re: [PATCH v2 03/11] OMAP2430: DMA: HWMOD: Add hwmod 
> data structures
> 
> Hi,
> 
> On Tue, Aug 24, 2010 at 04:34:18PM +0530, Manjunatha GK wrote:
> > This patch adds OMAP2430 DMA hwmod structures.
> > 
> > Signed-off-by: Manjunatha GK <manjugk@ti.com>
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > ---
> >  arch/arm/mach-omap2/omap_hwmod_2430_data.c |   85 
> ++++++++++++++++++++++++++++
> >  1 files changed, 85 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 4526628..3d79a52 100644
> > --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
> > +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
> > @@ -33,6 +33,7 @@ static struct omap_hwmod omap2430_mpu_hwmod;
> >  static struct omap_hwmod omap2430_iva_hwmod;
> >  static struct omap_hwmod omap2430_l3_main_hwmod;
> >  static struct omap_hwmod omap2430_l4_core_hwmod;
> > +static struct omap_hwmod omap2430_dma_system_hwmod;
> >  
> >  /* L3 -> L4_CORE interface */
> >  static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
> > @@ -165,12 +166,96 @@ static struct omap_hwmod 
> omap2430_iva_hwmod = {
> >  	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
> >  };
> >  
> > +/* dma_system */
> > +static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
> > +	.rev_offs	= 0x0000,
> > +	.sysc_offs	= 0x002c,
> > +	.syss_offs	= 0x0028,
> > +	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
> > +			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
> > +			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
> > +	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
> > +			   MSTANDBY_FORCE | MSTANDBY_NO | 
> MSTANDBY_SMART),
> > +	.sysc_fields	= &omap_hwmod_sysc_type1,
> > +};
> > +
> > +static struct omap_hwmod_class omap2430_dma_hwmod_class = {
> > +	.name = "dma",
> > +	.sysc = &omap2430_dma_sysc,
> > +};
> > +
> > +/* dma attributes */
> > +static struct omap_dma_dev_attr dma_dev_attr = {
> > +	.dev_caps  = DMA_LINKED_LCH | GLOBAL_PRIORITY |
> > +				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
>                                                           
> ^^^^^^^^^^^^^
> 
> Should this be IS_RW_PRIORITY? Same typo seems to be also in 
> other patches which
> add hwmod structures.

Thanks for identifying this typo. I will take care of it.

-Manjunath

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

* RE: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (10 preceding siblings ...)
  2010-08-24 11:04 ` [PATCH v2 11/11] sDMA: descriptor autoloading feature Manjunatha GK
@ 2010-09-03 16:21 ` G, Manjunath Kondaiah
  2010-09-03 16:39   ` Cousson, Benoit
                     ` (2 more replies)
  2010-09-03 20:38 ` Kevin Hilman
  12 siblings, 3 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-03 16:21 UTC (permalink / raw)
  To: G, Manjunath Kondaiah, linux-omap
  Cc: Cousson, Benoit, Kevin Hilman, Shilimkar, Santosh, Sawant, Anand

Kevin,
If there are no further comments, can you please stage this patch
series on hwmods-omap4 branch?

It applies cleanly on current commit(669d24d412380528158ba5d15522c9858f4b81a2).

-Manjunath 

> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org 
> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, 
> Manjunath Kondaiah
> Sent: Tuesday, August 24, 2010 4:34 PM
> To: linux-omap@vger.kernel.org
> Cc: Cousson, Benoit; Kevin Hilman; Shilimkar, Santosh
> Subject: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
> 
> This patch series has review comments incorporated which are received
> for v1 version.
> The review comments can be found at:
> http://www.spinics.net/lists/linux-omap/msg34291.html
> http://www.spinics.net/lists/linux-omap/msg34292.html
> http://www.spinics.net/lists/linux-omap/msg34078.html
> http://www.spinics.net/lists/linux-omap/msg34083.html
> 
> These changes are tested on following boards:
> - Zoom3     (OMAP3630)
> - Beagle    (OMAP3530)
> - OMAP4 SDP (OMAP4430)
> I don't have omap1 and omap2 boards and appreciate if 
> some one can test these boards and provides feedback.
> 
> Build tested for both omap1 and omap2 plus boards.
> 
> 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 f6f7f1103b80b4dc0ace8a0314d95d1b1ebca726
> Merge: 79d0b02 597e89c
> Author: Kevin Hilman <khilman@ti.com>
> 
>     Merge branch 'pm-wip/hwmods' into pm-wip/hwmods-omap4-base
> 
> The earlier version of the patches can be found at:
> RFC patches:
> http://www.spinics.net/lists/linux-omap/index.html#33393
> 
> v1 patches:
> http://www.spinics.net/lists/linux-omap/msg34066.html
> 
> 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: Add hwmod data structures
>   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                  |  451 ++++++++
>  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 |   85 ++
>  arch/arm/mach-omap2/omap_hwmod_2430_data.c |   85 ++
>  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   85 ++
>  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   99 ++
>  arch/arm/plat-omap/dma.c                   | 1539 
> ++++------------------------
>  arch/arm/plat-omap/include/plat/dma.h      |  222 +---
>  12 files changed, 2945 insertions(+), 1531 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
> 
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> --
> 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] 62+ messages in thread

* Re: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-09-03 16:21 ` [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah
@ 2010-09-03 16:39   ` Cousson, Benoit
  2010-09-07 11:46     ` G, Manjunath Kondaiah
  2010-09-03 16:44   ` Kevin Hilman
  2010-09-03 22:49   ` Kevin Hilman
  2 siblings, 1 reply; 62+ messages in thread
From: Cousson, Benoit @ 2010-09-03 16:39 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, Kevin Hilman, Shilimkar, Santosh, Sawant, Anand

Hi Manjunath,

On 9/3/2010 6:21 PM, G, Manjunath Kondaiah wrote:
> Kevin,
> If there are no further comments, can you please stage this patch
> series on hwmods-omap4 branch?

I just have few minor comments:
Could you please keep the original credit for this patch:
OMAP4: DMA: HWMOD: Add hwmod data structures

You can change as well the subject as suggested by Kevin for all the 
hwmod data patches with: OMAPX: hwmod data: Add system DMA

And quoting Kevin again "hwmod should not be capitalized, as it's not an 
acronym."

Thanks,
Benoit


> It applies cleanly on current commit(669d24d412380528158ba5d15522c9858f4b81a2).
>
> -Manjunath
>
>> -----Original Message-----
>> From: linux-omap-owner@vger.kernel.org
>> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G,
>> Manjunath Kondaiah
>> Sent: Tuesday, August 24, 2010 4:34 PM
>> To: linux-omap@vger.kernel.org
>> Cc: Cousson, Benoit; Kevin Hilman; Shilimkar, Santosh
>> Subject: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
>>
>> This patch series has review comments incorporated which are received
>> for v1 version.
>> The review comments can be found at:
>> http://www.spinics.net/lists/linux-omap/msg34291.html
>> http://www.spinics.net/lists/linux-omap/msg34292.html
>> http://www.spinics.net/lists/linux-omap/msg34078.html
>> http://www.spinics.net/lists/linux-omap/msg34083.html
>>
>> These changes are tested on following boards:
>> - Zoom3     (OMAP3630)
>> - Beagle    (OMAP3530)
>> - OMAP4 SDP (OMAP4430)
>> I don't have omap1 and omap2 boards and appreciate if
>> some one can test these boards and provides feedback.
>>
>> Build tested for both omap1 and omap2 plus boards.
>>
>> 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 f6f7f1103b80b4dc0ace8a0314d95d1b1ebca726
>> Merge: 79d0b02 597e89c
>> Author: Kevin Hilman<khilman@ti.com>
>>
>>      Merge branch 'pm-wip/hwmods' into pm-wip/hwmods-omap4-base
>>
>> The earlier version of the patches can be found at:
>> RFC patches:
>> http://www.spinics.net/lists/linux-omap/index.html#33393
>>
>> v1 patches:
>> http://www.spinics.net/lists/linux-omap/msg34066.html
>>
>> 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: Add hwmod data structures
>>    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                  |  451 ++++++++
>>   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 |   85 ++
>>   arch/arm/mach-omap2/omap_hwmod_2430_data.c |   85 ++
>>   arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   85 ++
>>   arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   99 ++
>>   arch/arm/plat-omap/dma.c                   | 1539
>> ++++------------------------
>>   arch/arm/plat-omap/include/plat/dma.h      |  222 +---
>>   12 files changed, 2945 insertions(+), 1531 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
>>
>> Cc: Benoit Cousson<b-cousson@ti.com>
>> Cc: Kevin Hilman<khilman@deeprootsystems.com>
>> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
>> --
>> 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] 62+ messages in thread

* Re: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-09-03 16:21 ` [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah
  2010-09-03 16:39   ` Cousson, Benoit
@ 2010-09-03 16:44   ` Kevin Hilman
  2010-09-03 22:49   ` Kevin Hilman
  2 siblings, 0 replies; 62+ messages in thread
From: Kevin Hilman @ 2010-09-03 16:44 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh, Sawant, Anand

"G, Manjunath Kondaiah" <manjugk@ti.com> writes:

> If there are no further comments, can you please stage this patch
> series on hwmods-omap4 branch?

I have not yet reviewed this series.  I hope to get to it today.

Sorry for the lag, but there have been *lots* of PM related patches
posted in the last month, and it's hard to do a thorough review and keep
up.

Kevin

>
> It applies cleanly on current commit(669d24d412380528158ba5d15522c9858f4b81a2).
>
> -Manjunath 
>
>> -----Original Message-----
>> From: linux-omap-owner@vger.kernel.org 
>> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, 
>> Manjunath Kondaiah
>> Sent: Tuesday, August 24, 2010 4:34 PM
>> To: linux-omap@vger.kernel.org
>> Cc: Cousson, Benoit; Kevin Hilman; Shilimkar, Santosh
>> Subject: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
>> 
>> This patch series has review comments incorporated which are received
>> for v1 version.
>> The review comments can be found at:
>> http://www.spinics.net/lists/linux-omap/msg34291.html
>> http://www.spinics.net/lists/linux-omap/msg34292.html
>> http://www.spinics.net/lists/linux-omap/msg34078.html
>> http://www.spinics.net/lists/linux-omap/msg34083.html
>> 
>> These changes are tested on following boards:
>> - Zoom3     (OMAP3630)
>> - Beagle    (OMAP3530)
>> - OMAP4 SDP (OMAP4430)
>> I don't have omap1 and omap2 boards and appreciate if 
>> some one can test these boards and provides feedback.
>> 
>> Build tested for both omap1 and omap2 plus boards.
>> 
>> 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 f6f7f1103b80b4dc0ace8a0314d95d1b1ebca726
>> Merge: 79d0b02 597e89c
>> Author: Kevin Hilman <khilman@ti.com>
>> 
>>     Merge branch 'pm-wip/hwmods' into pm-wip/hwmods-omap4-base
>> 
>> The earlier version of the patches can be found at:
>> RFC patches:
>> http://www.spinics.net/lists/linux-omap/index.html#33393
>> 
>> v1 patches:
>> http://www.spinics.net/lists/linux-omap/msg34066.html
>> 
>> 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: Add hwmod data structures
>>   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                  |  451 ++++++++
>>  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 |   85 ++
>>  arch/arm/mach-omap2/omap_hwmod_2430_data.c |   85 ++
>>  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   85 ++
>>  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   99 ++
>>  arch/arm/plat-omap/dma.c                   | 1539 
>> ++++------------------------
>>  arch/arm/plat-omap/include/plat/dma.h      |  222 +---
>>  12 files changed, 2945 insertions(+), 1531 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
>> 
>> Cc: Benoit Cousson <b-cousson@ti.com>
>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> --
>> 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] 62+ messages in thread

* Re: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
                   ` (11 preceding siblings ...)
  2010-09-03 16:21 ` [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah
@ 2010-09-03 20:38 ` Kevin Hilman
  2010-09-07 11:47   ` G, Manjunath Kondaiah
  12 siblings, 1 reply; 62+ messages in thread
From: Kevin Hilman @ 2010-09-03 20:38 UTC (permalink / raw)
  To: Manjunatha GK; +Cc: linux-omap, Benoit Cousson, Santosh Shilimkar

Manjunatha GK <manjugk@ti.com> writes:

> This patch series has review comments incorporated which are received
> for v1 version.
> The review comments can be found at:
> http://www.spinics.net/lists/linux-omap/msg34291.html
> http://www.spinics.net/lists/linux-omap/msg34292.html
> http://www.spinics.net/lists/linux-omap/msg34078.html
> http://www.spinics.net/lists/linux-omap/msg34083.html
>
> These changes are tested on following boards:
> - Zoom3     (OMAP3630)
> - Beagle    (OMAP3530)
> - OMAP4 SDP (OMAP4430)
> I don't have omap1 and omap2 boards and appreciate if 
> some one can test these boards and provides feedback.
>
> Build tested for both omap1 and omap2 plus boards.

Your team now has OMAP2 hardware, please test on OMAP2 as well as you're
making significant changes that affect code in OMAP2, 3 and 4.

Kevin

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

* Re: [PATCH v2 10/11] OMAP: DMA: Use DMA device attributes
  2010-08-24 11:04 ` [PATCH v2 10/11] OMAP: DMA: Use DMA device attributes Manjunatha GK
@ 2010-09-03 20:45   ` Kevin Hilman
  2010-09-07 11:47     ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Kevin Hilman @ 2010-09-03 20:45 UTC (permalink / raw)
  To: Manjunatha GK; +Cc: linux-omap, Benoit Cousson, Santosh Shilimkar

Manjunatha GK <manjugk@ti.com> writes:

> 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>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>

[...]

>  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)
> @@ -754,14 +459,12 @@ int omap_request_dma(int dev_id, const char *dev_name,
>  	chan = dma_chan + free_ch;
>  	chan->dev_id = dev_id;
>  
> -	pm_runtime_get_sync(&ddev->dev);
> -
> -	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);

You access HW registers here.

> +	pm_runtime_get_sync(&ddev->dev);

But don't actually enable HW until here.  

IOW, you need to have the 'get' before you access the HW.

Kevin

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

* Re: [PATCH v2 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-08-24 11:04 ` [PATCH v2 04/11] OMAP3: " Manjunatha GK
@ 2010-09-03 20:51   ` Kevin Hilman
  2010-09-04 14:45     ` Cousson, Benoit
  2010-09-08  1:52     ` G, Manjunath Kondaiah
  0 siblings, 2 replies; 62+ messages in thread
From: Kevin Hilman @ 2010-09-03 20:51 UTC (permalink / raw)
  To: Manjunatha GK; +Cc: linux-omap, Benoit Cousson, Santosh Shilimkar

Manjunatha GK <manjugk@ti.com> writes:

> This patch adds OMAP3 DMA hwmod structures.

Subject should be something like: OMAP3: hwmod data: add system DMA

> Signed-off-by: Manjunatha GK <manjugk@ti.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> ---
>  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   85 ++++++++++++++++++++++++++++
>  1 files changed, 85 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 5d8eb58..0979c51 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,89 @@ 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",

This clock dosn't exist in l-o, which I see due to the boot message:

    omap_hwmod: dma: cannot clk_get main_clk l3_div_ck  

I think you mean core_l3_ick here.

> +	.user		= OCP_USER_MPU | OCP_USER_SDMA,
> +};
> +
> +/* dma attributes */
> +static struct omap_dma_dev_attr dma_dev_attr = {
> +	.dev_caps  = DMA_LINKED_LCH | GLOBAL_PRIORITY |
> +				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORIY,
> +	.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 = "0", .irq = INT_24XX_SDMA_IRQ0 },
> +	{ .name = "1", .irq = INT_24XX_SDMA_IRQ1 },
> +	{ .name = "2", .irq = INT_24XX_SDMA_IRQ2 },
> +	{ .name = "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",

This clock doesn't exist in l-o, resulting in the boot message:

   omap_hwmod: dma: cannot clk_get interface_clk l4_div_ck   

I think you meant "core_l4_ick" here.

> +	.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",
> +	.slaves		= omap3xxx_dma_system_slaves,
> +	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves),
> +	.masters	= omap3xxx_dma_system_masters,
> +	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
> +	.dev_attr	= &dma_dev_attr,
> +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
> +	.flags		= HWMOD_NO_IDLEST,

hmm, I see an ST_DMA bit in CM_IDLEST1_CORE for DMA.

Having this also masks the fact that you haven't filled out the
.prcm.omap2 fields of the hwmod, at least the idlest ones are needed
here.

Kevin

> +};
> +
>  static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
>  	&omap3xxx_l3_main_hwmod,
>  	&omap3xxx_l4_core_hwmod,
> @@ -204,6 +288,7 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
>  	&omap3xxx_l4_wkup_hwmod,
>  	&omap3xxx_mpu_hwmod,
>  	&omap3xxx_iva_hwmod,
> +	&omap3xxx_dma_system_hwmod,
>  	NULL,
>  };



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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-08-24 11:04 ` [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration Manjunatha GK
@ 2010-09-03 20:59   ` Kevin Hilman
  2010-09-07 11:47     ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Kevin Hilman @ 2010-09-03 20:59 UTC (permalink / raw)
  To: Manjunatha GK; +Cc: linux-omap, Benoit Cousson, Santosh Shilimkar

Manjunatha GK <manjugk@ti.com> writes:

> 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>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@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..f369bee
> --- /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);		\
> +})

I know these are copy paste from the original code, but please convert
into static inline functions.

Also, I don't see dma_write() used in this patch.

> +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,

missing indentation

> +	},
> +};

[...]

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

* Re: [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver
  2010-08-24 11:04 ` [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver Manjunatha GK
@ 2010-09-03 22:34   ` Kevin Hilman
  2010-09-07 11:47     ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Kevin Hilman @ 2010-09-03 22:34 UTC (permalink / raw)
  To: Manjunatha GK; +Cc: linux-omap, Benoit Cousson, Santosh Shilimkar

Manjunatha GK <manjugk@ti.com> writes:

> 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.
>
> Also, it enables and uses run time PM API's
>
> Signed-off-by: Manjunatha GK <manjugk@ti.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@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               |  244 +++++++++++++++++---------------
>  arch/arm/plat-omap/include/plat/dma.h  |  157 ++-------------------
>  6 files changed, 290 insertions(+), 264 deletions(-)
>
> diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
> index 9a304d8..b7dfc54 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 */

These should not be needed anymore as this is now an OMAP1-specific
header.

> +/* 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 9b44773..6a8b231 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 pm.o
> +obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.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 */

Why exactly are these here?

> +/* 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;
> +};

Seems like this struct should stay common, as it's basically the same
across all OMAPs.  Only chaining fields are different, and they can just
be unused on OMAP1.

Also, this breaks multi-OMAP as this struct is used in plat-omap/dma.c
(OMAP1 and OMAP2+) but defined differently for OMAP1 and OMAP2+.

[...]

Kevin

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

* Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-08-24 11:04 ` [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling Manjunatha GK
@ 2010-09-03 22:42   ` Kevin Hilman
  2010-09-07 11:48     ` G, Manjunath Kondaiah
  2010-09-17 15:45   ` Cousson, Benoit
  1 sibling, 1 reply; 62+ messages in thread
From: Kevin Hilman @ 2010-09-03 22:42 UTC (permalink / raw)
  To: Manjunatha GK; +Cc: linux-omap, Benoit Cousson, Santosh Shilimkar

Manjunatha GK <manjugk@ti.com> writes:

> 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>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@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 26ab6e3..615c5f5 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;

This isn't needed as you just kzalloc'd pdata.

> +	if (cpu_class_is_omap1() && !cpu_is_omap15xx())

You don't need cpu_class_is_omap1() as this is OMAP1 specific code.

> +		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 f369bee..8832bd1 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;

not needed, see above

> +	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 :

fix multi-line comment style

> +	 * 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 36c3dde..409586a 100644
> --- a/arch/arm/plat-omap/dma.c
> +++ b/arch/arm/plat-omap/dma.c
> @@ -187,6 +187,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)

Please use (or extend) hwmod layer for modifying device SYSCONFIG.

> +{
> +	u32 l;
> +
> +	/*
> +	 * DMA Errata:
> +	 * Special programming model needed to disable DMA before end of block
> +	 */

Please reference Errata#

> +	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)
>  {
> @@ -971,22 +990,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;
> @@ -1660,7 +1673,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))) {
> @@ -1675,15 +1688,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++) {
>  
> @@ -1702,8 +1708,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 a44b11b..ca251ac 100644
> --- a/arch/arm/plat-omap/include/plat/dma.h
> +++ b/arch/arm/plat-omap/include/plat/dma.h
> @@ -269,6 +269,14 @@
>  #define IS_WORD_16			(1 << 0xC)
>  #define IS_RW_PRIORIY			(1 << 0xD)
>  
> +/* 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,
> @@ -346,6 +354,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);

Kevin

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

* Re: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-09-03 16:21 ` [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah
  2010-09-03 16:39   ` Cousson, Benoit
  2010-09-03 16:44   ` Kevin Hilman
@ 2010-09-03 22:49   ` Kevin Hilman
  2010-09-07 11:48     ` G, Manjunath Kondaiah
  2 siblings, 1 reply; 62+ messages in thread
From: Kevin Hilman @ 2010-09-03 22:49 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh, Sawant, Anand

"G, Manjunath Kondaiah" <manjugk@ti.com> writes:

> If there are no further comments, can you please stage this patch
> series on hwmods-omap4 branch?

Reviewed.  Still a long ways to go..., also  I didn't see you address
the typo pointed out by Mika Westerberg on PATCH 03/11.

Also, testing on omap3430/n900, I noticed an interesting failure during
boot.  During boot (in the middle of omap3_pm_init(), a DMA interrupt
fires and the SPI RX callback is called which faults when accessing it's
registers.

I did not debug this further, but is something that needs investigation.

Also, in the next version, please report how it was tested on the
various OMAPs.  In particular, what peripherals using DMA were tested.
Just a boot test is not sufficient when making major functional changes
like this.  Drivers using DMA need to be tested as well.

Kevin



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

* Re: [PATCH v2 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-09-03 20:51   ` Kevin Hilman
@ 2010-09-04 14:45     ` Cousson, Benoit
  2010-09-08  1:52     ` G, Manjunath Kondaiah
  1 sibling, 0 replies; 62+ messages in thread
From: Cousson, Benoit @ 2010-09-04 14:45 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: G, Manjunath Kondaiah, linux-omap, Shilimkar, Santosh

Hi Kevin,

On 9/3/2010 10:51 PM, Kevin Hilman wrote:
> Manjunatha GK<manjugk@ti.com>  writes:

[...]

>> +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",
>> +	.slaves		= omap3xxx_dma_system_slaves,
>> +	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves),
>> +	.masters	= omap3xxx_dma_system_masters,
>> +	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
>> +	.dev_attr	=&dma_dev_attr,
>> +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
>> +	.flags		= HWMOD_NO_IDLEST,
>
> hmm, I see an ST_DMA bit in CM_IDLEST1_CORE for DMA.

In fact in the case of the SDMA, the ST_DMA is the standby status and 
not the idle status... This is indeed not confusing at all...

This bit will just provide information about the master port activity 
(MStandby). Extract from the TRM:
In case of Smart-Standby: MStandby is asserted if at least one of the
following two conditions is satisfied:
1. All the channels are disabled
2. There is no non-synchronized channel enabled and or no DMA request 
input is asserted and no request in the read and write port scheduler 
state machine.

This information is unfortunately useless for the OCP slave port point 
of view.

There are a couple of other initiators that does not have any idle 
status: IVA, MPU and SGX. USB_OTG has both idle and standby.

Regards,
Benoit

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

* RE: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-09-03 16:39   ` Cousson, Benoit
@ 2010-09-07 11:46     ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-07 11:46 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: linux-omap, Kevin Hilman, Shilimkar, Santosh, Sawant, Anand

 

> -----Original Message-----
> From: Cousson, Benoit 
> Sent: Friday, September 03, 2010 10:10 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Kevin Hilman; Shilimkar, 
> Santosh; Sawant, Anand
> Subject: Re: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as 
> platform driver
> 
> Hi Manjunath,
> 
> On 9/3/2010 6:21 PM, G, Manjunath Kondaiah wrote:
> > Kevin,
> > If there are no further comments, can you please stage this patch
> > series on hwmods-omap4 branch?
> 
> I just have few minor comments:
> Could you please keep the original credit for this patch:
> OMAP4: DMA: HWMOD: Add hwmod data structures
> 
> You can change as well the subject as suggested by Kevin for all the 
> hwmod data patches with: OMAPX: hwmod data: Add system DMA
> 
> And quoting Kevin again "hwmod should not be capitalized, as 
> it's not an 
> acronym."

Ok.

- Manjunath 

[...]
 

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

* RE: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-09-03 20:38 ` Kevin Hilman
@ 2010-09-07 11:47   ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-07 11:47 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh



> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Saturday, September 04, 2010 2:09 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as 
> platform driver
> 
> Manjunatha GK <manjugk@ti.com> writes:
> 
> > This patch series has review comments incorporated which 
> are received
> > for v1 version.
> > The review comments can be found at:
> > http://www.spinics.net/lists/linux-omap/msg34291.html
> > http://www.spinics.net/lists/linux-omap/msg34292.html
> > http://www.spinics.net/lists/linux-omap/msg34078.html
> > http://www.spinics.net/lists/linux-omap/msg34083.html
> >
> > These changes are tested on following boards:
> > - Zoom3     (OMAP3630)
> > - Beagle    (OMAP3530)
> > - OMAP4 SDP (OMAP4430)
> > I don't have omap1 and omap2 boards and appreciate if 
> > some one can test these boards and provides feedback.
> >
> > Build tested for both omap1 and omap2 plus boards.
> 
> Your team now has OMAP2 hardware, please test on OMAP2 as 
> well as you're
> making significant changes that affect code in OMAP2, 3 and 4.

Let me check omap2 board boot status. If it is working, I can
test next version of patches on omap2 also.

-Manjunath

> 
> Kevin
> 

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

* RE: [PATCH v2 10/11] OMAP: DMA: Use DMA device attributes
  2010-09-03 20:45   ` Kevin Hilman
@ 2010-09-07 11:47     ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-07 11:47 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh




> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Saturday, September 04, 2010 2:16 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 10/11] OMAP: DMA: Use DMA device attributes
> 
> Manjunatha GK <manjugk@ti.com> writes:
> 
> > 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>
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> 
> [...]
> 
> >  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)
> > @@ -754,14 +459,12 @@ int omap_request_dma(int dev_id, 
> const char *dev_name,
> >  	chan = dma_chan + free_ch;
> >  	chan->dev_id = dev_id;
> >  
> > -	pm_runtime_get_sync(&ddev->dev);
> > -
> > -	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);
> 
> You access HW registers here.
> 
> > +	pm_runtime_get_sync(&ddev->dev);
> 
> But don't actually enable HW until here.  
> 
> IOW, you need to have the 'get' before you access the HW.

Thanks for pointing out this. I will take care of it.

-Manjunath

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

* RE: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-03 20:59   ` Kevin Hilman
@ 2010-09-07 11:47     ` G, Manjunath Kondaiah
  2010-09-14 10:18       ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-07 11:47 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh



> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Saturday, September 04, 2010 2:30 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
> registration
> 
> Manjunatha GK <manjugk@ti.com> writes:
> 
> > This patch converts omap2/3/4 dma driver into platform
> > devices through using omap hwmod, omap device and runtime pm
> > frameworks.

[..]

> > +
> > +#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);	
> 	\
> > +})
> 
> I know these are copy paste from the original code, but please convert
> into static inline functions.

Ok.

> 
> Also, I don't see dma_write() used in this patch.

This is initial patch for splitting mach-omap1 and mach-omap2 contents.
dma_write is used in later patches. Please refer to Patch #11

-Manjunath


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

* RE: [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver
  2010-09-03 22:34   ` Kevin Hilman
@ 2010-09-07 11:47     ` G, Manjunath Kondaiah
  2010-09-07 22:45       ` Kevin Hilman
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-07 11:47 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh




> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Saturday, September 04, 2010 4:04 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 08/11] OMAP: DMA: Convert DMA library 
> into DMA platform Driver
> 
> Manjunatha GK <manjugk@ti.com> writes:
> 
> > 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.
> >
> > Also, it enables and uses run time PM API's
> >
> > Signed-off-by: Manjunatha GK <manjugk@ti.com>
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@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               |  244 
> +++++++++++++++++---------------
> >  arch/arm/plat-omap/include/plat/dma.h  |  157 ++-------------------
> >  6 files changed, 290 insertions(+), 264 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap1/Makefile 
> b/arch/arm/mach-omap1/Makefile
> > index 9a304d8..b7dfc54 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 */
> 
> These should not be needed anymore as this is now an OMAP1-specific
> header.

Because it is OMAP1 specific header, there are common API's used between
omap1 and omap2 plus in plat-omap/dma.c which needs these defines otherwise
build will break for omap1 since these defines exists omap2 specific header
Which is in respective mach directory.

> 
> > +/* 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 9b44773..6a8b231 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 pm.o
> > +obj-y := id.o io.o control.o mux.o devices.o serial.o 
> gpmc.o timer-gp.o pm.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 */
> 
> Why exactly are these here?

-Ditto-

> 
> > +/* 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;
> > +};
> 
> Seems like this struct should stay common, as it's basically the same
> across all OMAPs.  Only chaining fields are different, and 
> they can just
> be unused on OMAP1.

I can move to plat-omap dma header.

> 
> Also, this breaks multi-OMAP as this struct is used in plat-omap/dma.c
> (OMAP1 and OMAP2+) but defined differently for OMAP1 and OMAP2+.
> 

This will not break multi-OMAP build, since plat-omap has only generic API's
Which are free from chain parameters. Chain parameters are used only in 
mach-omap2/dma.c hence build passes for both multi omap and omap1 defconfigs.

-Manjunath

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

* RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-03 22:42   ` Kevin Hilman
@ 2010-09-07 11:48     ` G, Manjunath Kondaiah
  2010-09-14 10:12       ` G, Manjunath Kondaiah
  2010-09-17  5:05       ` G, Manjunath Kondaiah
  0 siblings, 2 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-07 11:48 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh



> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Saturday, September 04, 2010 4:12 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic 
> errata handling
> 
> Manjunatha GK <manjugk@ti.com> writes:
> 
> > 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>
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@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 26ab6e3..615c5f5 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;
> 
> This isn't needed as you just kzalloc'd pdata.
ok
> 
> > +	if (cpu_class_is_omap1() && !cpu_is_omap15xx())
> 
> You don't need cpu_class_is_omap1() as this is OMAP1 specific code.
Ok. Looks like copy, paste issue from plat-omap dma.c. I will fix it.
> 
> > +		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 f369bee..8832bd1 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;
> 
> not needed, see above
ok
> 
> > +	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 :
> 
> fix multi-line comment style
Ok.

> 
> > +	 * 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 36c3dde..409586a 100644
> > --- a/arch/arm/plat-omap/dma.c
> > +++ b/arch/arm/plat-omap/dma.c
> > @@ -187,6 +187,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)
> 
> Please use (or extend) hwmod layer for modifying device SYSCONFIG.

I will check this.

> 
> > +{
> > +	u32 l;
> > +
> > +	/*
> > +	 * DMA Errata:
> > +	 * Special programming model needed to disable DMA 
> before end of block
> > +	 */
> 
> Please reference Errata#

ok. Original code doesn't have errata number, I will check errata
document.

-Manjunath


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

* RE: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-09-03 22:49   ` Kevin Hilman
@ 2010-09-07 11:48     ` G, Manjunath Kondaiah
  2010-09-08  8:43       ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-07 11:48 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh, Sawant, Anand

 

> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Saturday, September 04, 2010 4:20 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, 
> Santosh; Sawant, Anand
> Subject: Re: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as 
> platform driver
> 
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> 
> > If there are no further comments, can you please stage this patch
> > series on hwmods-omap4 branch?
> 
> Reviewed.  Still a long ways to go..., also  I didn't see you address
> the typo pointed out by Mika Westerberg on PATCH 03/11.
Sorry. I fixed it in my internal version and forgot to take that change.
Thanks for pointing this.

> 
> Also, testing on omap3430/n900, I noticed an interesting 
> failure during
> boot.  During boot (in the middle of omap3_pm_init(), a DMA interrupt
> fires and the SPI RX callback is called which faults when 
> accessing it's
> registers.

Not sure about n900, I will check if I get N900.

> 
> I did not debug this further, but is something that needs 
> investigation.
> 
> Also, in the next version, please report how it was tested on the
> various OMAPs.  In particular, what peripherals using DMA were tested.
> Just a boot test is not sufficient when making major 
> functional changes
> like this.  Drivers using DMA need to be tested as well.

This patch series has been tested with various use cases like:
1. Memory to Memory DMA test cases from test code:
http://dev.omapzoom.org/?p=richo/device_driver_test.git;a=shortlog;h=refs/heads/master

2. SD/MMC test cases(on zoom3, omap4 SDP and beagle)
3. Ethernet testing (on omap4 SDP with McSPI interface for both Rx and Tx - Also used
   NFS file system)

I will provide these details in next version patches.

-Manjunath

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

* Re: [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver
  2010-09-07 11:47     ` G, Manjunath Kondaiah
@ 2010-09-07 22:45       ` Kevin Hilman
  2010-09-08  1:46         ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Kevin Hilman @ 2010-09-07 22:45 UTC (permalink / raw)
  To: G, Manjunath Kondaiah; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh

"G, Manjunath Kondaiah" <manjugk@ti.com> writes:

[...]

>> > 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 */
>> 
>> These should not be needed anymore as this is now an OMAP1-specific
>> header.
>
> Because it is OMAP1 specific header, there are common API's used between
> omap1 and omap2 plus in plat-omap/dma.c which needs these defines otherwise
> build will break for omap1 since these defines exists omap2 specific header
> Which is in respective mach directory.

OK, then the split you are proposing is not the right thing to do, or
more likely, the split was not taken far enough.

defines that are used in common code should be defined in a common
header, rather than duplicating them in both omap1 and omap2+ code.

When you find yourself putting OMAP1 defines in OMAP2+ code and vice
versa, it should be an indication that there is still some abstraction
missing in the split

Kevin

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

* RE: [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver
  2010-09-07 22:45       ` Kevin Hilman
@ 2010-09-08  1:46         ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-08  1:46 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh




> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Wednesday, September 08, 2010 4:15 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 08/11] OMAP: DMA: Convert DMA library 
> into DMA platform Driver
> 
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> 
> [...]
> 
> >> > 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 */
> >> 
> >> These should not be needed anymore as this is now an OMAP1-specific
> >> header.
> >
> > Because it is OMAP1 specific header, there are common API's 
> used between
> > omap1 and omap2 plus in plat-omap/dma.c which needs these 
> defines otherwise
> > build will break for omap1 since these defines exists omap2 
> specific header
> > Which is in respective mach directory.
> 
> OK, then the split you are proposing is not the right thing to do, or
> more likely, the split was not taken far enough.
> 
> defines that are used in common code should be defined in a common
> header, rather than duplicating them in both omap1 and omap2+ code.

It cannot be moved to common header since it will have duplicated #defines
(one from mach header and other one from common header.
> 
> When you find yourself putting OMAP1 defines in OMAP2+ code and vice
> versa, it should be an indication that there is still some abstraction
> missing in the split

These common API's use device attributes to differentiate between omap1 and omap2
plus code. If we want to eliminate this, we should move these api's to respective
mach directory. In that case, both omap1 and omap2plus dma drivers will become
separate drivers. The rationale behind spilit is, tried to common API's as for as 
possible in plat-oma dma and move omap1 and omap2plus specific code respectivem 
mach dma.

-Manjunath

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

* RE: [PATCH v2 04/11] OMAP3: DMA: HWMOD: Add hwmod data structures
  2010-09-03 20:51   ` Kevin Hilman
  2010-09-04 14:45     ` Cousson, Benoit
@ 2010-09-08  1:52     ` G, Manjunath Kondaiah
  1 sibling, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-08  1:52 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh



> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Saturday, September 04, 2010 2:22 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 04/11] OMAP3: DMA: HWMOD: Add hwmod 
> data structures
> 
> Manjunatha GK <manjugk@ti.com> writes:
> 
> > This patch adds OMAP3 DMA hwmod structures.
> 

[..]

> > +
> > +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",
> > +	.slaves		= omap3xxx_dma_system_slaves,
> > +	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves),
> > +	.masters	= omap3xxx_dma_system_masters,
> > +	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
> > +	.dev_attr	= &dma_dev_attr,
> > +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
> > +	.flags		= HWMOD_NO_IDLEST,
> 
> hmm, I see an ST_DMA bit in CM_IDLEST1_CORE for DMA.
> 
> Having this also masks the fact that you haven't filled out the
> .prcm.omap2 fields of the hwmod, at least the idlest ones are needed
> here.

Ok. I will introduce .prcm entries as:
	.prcm = {
		.omap2 = {
			.prcm_reg_id		= 1,
			.module_bit		= OMAP3430_ST_SDMA_SHIFT,
			.module_offs		= CORE_MOD,
			.idlest_reg_id		= 1,
			.idlest_idle_bit	= OMAP3430_ST_SDMA_SHIFT,
		},
	}
	.flags = HWMOD_SET_DEFAULT_CLOCKACT,

-Manjunath


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

* RE: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver
  2010-09-07 11:48     ` G, Manjunath Kondaiah
@ 2010-09-08  8:43       ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-08  8:43 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh, Sawant, Anand




> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org 
> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, 
> Manjunath Kondaiah
> Sent: Tuesday, September 07, 2010 5:18 PM
> To: Kevin Hilman
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, 
> Santosh; Sawant, Anand
> Subject: RE: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as 
> platform driver
> 
>  
> 
> > -----Original Message-----
> > From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> > Sent: Saturday, September 04, 2010 4:20 AM
> > To: G, Manjunath Kondaiah
> > Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, 
> > Santosh; Sawant, Anand
> > Subject: Re: [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as 
> > platform driver
> > 
> > "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> > 
> > > If there are no further comments, can you please stage this patch
> > > series on hwmods-omap4 branch?
> > 
> > Reviewed.  Still a long ways to go..., also  I didn't see 
> you address
> > the typo pointed out by Mika Westerberg on PATCH 03/11.
> Sorry. I fixed it in my internal version and forgot to take 
> that change.
> Thanks for pointing this.

It is not mistake. I was cross checking the review comments and 
Mika Westerberg comment is for v2 version of 03/11 patch and your review is also 
for v2 version of the series hence Mika Westerberg comments will get addressed 
in v3 series.

-Manjunath

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

* RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-07 11:48     ` G, Manjunath Kondaiah
@ 2010-09-14 10:12       ` G, Manjunath Kondaiah
  2010-09-17  5:05       ` G, Manjunath Kondaiah
  1 sibling, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-14 10:12 UTC (permalink / raw)
  To: G, Manjunath Kondaiah, Kevin Hilman
  Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh

Kevin, 

> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org 
> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, 
> Manjunath Kondaiah
> Sent: Tuesday, September 07, 2010 5:18 PM
> To: Kevin Hilman
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: RE: [PATCH v2 09/11] OMAP: DMA: Implement generic 
> errata handling
> 
> 
> 
> > -----Original Message-----
> > From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
> > Sent: Saturday, September 04, 2010 4:12 AM
> > To: G, Manjunath Kondaiah
> > Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> > Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata 
> > handling
> > 
> > Manjunatha GK <manjugk@ti.com> writes:
> > 
> > > 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>
> > > Cc: Benoit Cousson <b-cousson@ti.com>
> > > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > > Cc: Santosh Shilimkar <santosh.shilimkar@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 26ab6e3..615c5f5 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;
> > 
> > This isn't needed as you just kzalloc'd pdata.
> ok
> > 
> > > +	if (cpu_class_is_omap1() && !cpu_is_omap15xx())
> > 
> > You don't need cpu_class_is_omap1() as this is OMAP1 specific code.
> Ok. Looks like copy, paste issue from plat-omap dma.c. I will fix it.
> > 
> > > +		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 
> > > f369bee..8832bd1 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;
> > 
> > not needed, see above
> ok
> > 
> > > +	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 :
> > 
> > fix multi-line comment style
> Ok.
> 
> > 
> > > +	 * 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 36c3dde..409586a 100644
> > > --- a/arch/arm/plat-omap/dma.c
> > > +++ b/arch/arm/plat-omap/dma.c
> > > @@ -187,6 +187,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)
> > 
> > Please use (or extend) hwmod layer for modifying device SYSCONFIG.
> 
> I will check this.

I propose following options for addressing this errata:
Option 1:
Creating 2 new API's with 1 static function in omap_hwmod.c for handling 
midle mode errata issues.

static int _get_master_standbymode(oh, u32 *idlemode, u32 v);
int omap_hwmod_set_master_idlemode(struct omap_hwmod *oh, u8 idlemode);
int omap_hwmod_get_master_idlemode(struct omap_hwmod *oh, u32 *idlemode);

In dma driver, the api's will be used as:
omap_hwmod_get_master_idlemode(oh, midle_mode);
omap_hwmod_set_master_idlemode(oh, 1);
/* disable channels which completed data transfer */
...
/* Restore original standby mode values */
omap_hwmod_set_master_idlemode(oh, *midle_mode)


Option 2:
Create 1 new exported API for modifying sysconfig standby mode bits.
In this case, restoring original standby mode value is through accessing
sysc flags and _sysc_cache values through oh in DMA driver.

I feel option #1 seems to be cleaner approach since it avoids accessing 
oh contents in driver. Let me know if you have objections for the same.

/Code snippet for option 1 */
static int _get_master_standbymode(oh, u32 *idlemode)
{
	u32 mstandby_mask;
	u8 mstandby_shift;

	...

	mstandby_shift = oh->class->sysc->sysc_fields->midle_shift;
	mstandby_mask = (0x3 << mstandby_shift);
	*idle_mode = ((oh->_sysc_cache) & mstandby_mask) >> mstandby_shift;

	return 0;
}

int omap_hwmod_set_master_idlemode(struct omap_hwmod *oh, u8 idlemode)
{
	u32 v;
	int retval = 0;
	...
	v = oh->_sysc_cache;

	retval = _set_master_standbymode(oh, idlemode, &v);
	if (!retval)
		_write_sysconfig(v, oh);

	return retval;
}

int omap_hwmod_get_master_idlemode(struct omap_hwmod *oh, u32 *idlemode)
{
	u32 v;
	int retval = 0;
	...
	retval = _get_master_standbymode(oh, idlemode);
	return retval;
}


-Manjunath

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

* RE: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-07 11:47     ` G, Manjunath Kondaiah
@ 2010-09-14 10:18       ` G, Manjunath Kondaiah
  2010-09-14 10:24         ` Felipe Balbi
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-14 10:18 UTC (permalink / raw)
  To: G, Manjunath Kondaiah, Kevin Hilman
  Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh


Kevin,

> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org 
> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, 
> Manjunath Kondaiah
> Sent: Tuesday, September 07, 2010 5:17 PM
> To: Kevin Hilman
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: RE: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
> registration
> 
> 
> 
> > -----Original Message-----
> > From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
> > Sent: Saturday, September 04, 2010 2:30 AM
> > To: G, Manjunath Kondaiah
> > Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> > Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
> > registration
> > 
> > Manjunatha GK <manjugk@ti.com> writes:
> > 
> > > This patch converts omap2/3/4 dma driver into platform devices 
> > > through using omap hwmod, omap device and runtime pm frameworks.
> 
> [..]
> 
> > > +
> > > +#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);	
> > 	\
> > > +})
> > 
> > I know these are copy paste from the original code, but 
> please convert 
> > into static inline functions.
> 
> Ok.

How static inline functions are better than this? 

-Manjunath


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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-14 10:18       ` G, Manjunath Kondaiah
@ 2010-09-14 10:24         ` Felipe Balbi
  2010-09-14 11:44           ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Felipe Balbi @ 2010-09-14 10:24 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: Kevin Hilman, linux-omap, Cousson, Benoit, Shilimkar, Santosh

Hi,

On Tue, Sep 14, 2010 at 05:18:52AM -0500, G, Manjunath Kondaiah wrote:
>How static inline functions are better than this?

static inline function will at least give you type checking ??

-- 
balbi

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

* RE: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-14 10:24         ` Felipe Balbi
@ 2010-09-14 11:44           ` G, Manjunath Kondaiah
  2010-09-14 11:57             ` Felipe Balbi
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-14 11:44 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: Kevin Hilman, linux-omap, Cousson, Benoit, Shilimkar, Santosh



> -----Original Message-----
> From: Balbi, Felipe 
> Sent: Tuesday, September 14, 2010 3:54 PM
> To: G, Manjunath Kondaiah
> Cc: Kevin Hilman; linux-omap@vger.kernel.org; Cousson, 
> Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
> registration
> 
> Hi,
> 
> On Tue, Sep 14, 2010 at 05:18:52AM -0500, G, Manjunath Kondaiah wrote:
> >How static inline functions are better than this?
> 
> static inline function will at least give you type checking ??

If so, even inline function has certain disadvantages such as, 
A. somtimes the compiler may not be able to inline as many functions as the programmer indicates.
B. Inline functions might increcase compilation time

The issue in DMA driver is, if I replace dma_read/dma_write macros with inline functions, 
I need to remove OMAP_DMA4_##reg macro in dma_read and dma write functions and 
I have to expand the register names all over the place in DMA driver(like instead of CAPS0, it 
should be OMAP_DMA4_CAPS0, having only CAPS0 will be easier to read).

-Manjunath

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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-14 11:44           ` G, Manjunath Kondaiah
@ 2010-09-14 11:57             ` Felipe Balbi
  2010-09-14 14:11               ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Felipe Balbi @ 2010-09-14 11:57 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: Balbi, Felipe, Kevin Hilman, linux-omap, Cousson, Benoit,
	Shilimkar, Santosh

On Tue, Sep 14, 2010 at 06:44:01AM -0500, G, Manjunath Kondaiah wrote:
>
>
>> -----Original Message-----
>> From: Balbi, Felipe
>> Sent: Tuesday, September 14, 2010 3:54 PM
>> To: G, Manjunath Kondaiah
>> Cc: Kevin Hilman; linux-omap@vger.kernel.org; Cousson,
>> Benoit; Shilimkar, Santosh
>> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device
>> registration
>>
>> Hi,
>>
>> On Tue, Sep 14, 2010 at 05:18:52AM -0500, G, Manjunath Kondaiah wrote:
>> >How static inline functions are better than this?
>>
>> static inline function will at least give you type checking ??
>
>If so, even inline function has certain disadvantages such as, A.
>somtimes the compiler may not be able to inline as many functions as
>the programmer indicates.

show me one such example.

> B. Inline functions might increcase compilation time

it's possible, for sure. But for the case you just showed the arguments
are even constant, so there's more room for compile-time optimization.
In the end, GCC will replace your calls with:

address = value;

or, when reading:

return address

>The issue in DMA driver is, if I replace dma_read/dma_write macros with
>inline functions, I need to remove OMAP_DMA4_##reg macro in dma_read
>and dma write functions and I have to expand the register names all
>over the place in DMA driver(like instead of CAPS0, it should be
>OMAP_DMA4_CAPS0, having only CAPS0 will be easier to read).

it might be easier to read but this is a recipe for disaster. Avoid
using those macros for part of the actual symbol/define/whatever name
like that. If someone later decides to change something, it will be a
pain. With those macros you also kill any possibility of using
ctags/cscope for source code cross-referencing. When a developers
searchs for the definition of CAPS0, he won't find it, as it's called
OMAP_DMA4_CAPS0. So remove those silly things and change the defines to
static inline functions.

-- 
balbi

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

* RE: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-14 11:57             ` Felipe Balbi
@ 2010-09-14 14:11               ` G, Manjunath Kondaiah
  2010-09-15  7:11                 ` Felipe Balbi
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-14 14:11 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: Kevin Hilman, linux-omap, Cousson, Benoit, Shilimkar, Santosh




> -----Original Message-----
> From: Balbi, Felipe 
> Sent: Tuesday, September 14, 2010 5:27 PM
> To: G, Manjunath Kondaiah
> Cc: Balbi, Felipe; Kevin Hilman; linux-omap@vger.kernel.org; 
> Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
> registration
> 
> On Tue, Sep 14, 2010 at 06:44:01AM -0500, G, Manjunath Kondaiah wrote:
> >
> >
> >> -----Original Message-----
> >> From: Balbi, Felipe
> >> Sent: Tuesday, September 14, 2010 3:54 PM
> >> To: G, Manjunath Kondaiah
> >> Cc: Kevin Hilman; linux-omap@vger.kernel.org; Cousson,
> >> Benoit; Shilimkar, Santosh
> >> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device
> >> registration
> >>
> >> Hi,
> >>
> >> On Tue, Sep 14, 2010 at 05:18:52AM -0500, G, Manjunath 
> Kondaiah wrote:
> >> >How static inline functions are better than this?
> >>
> >> static inline function will at least give you type checking ??
> >
> >If so, even inline function has certain disadvantages such as, A.
> >somtimes the compiler may not be able to inline as many functions as
> >the programmer indicates.
> 
> show me one such example.

There are several places in kernel code
(ex: tools/perf/util/include/linux/bitops.h:static __always_inline int test_bit(unsigned int nr, const unsigned long *addr))
which are using __always_inline attribute to make sure functions are inlined.

> 
> > B. Inline functions might increcase compilation time
> 
> it's possible, for sure. But for the case you just showed the 
> arguments
> are even constant, so there's more room for compile-time optimization.
> In the end, GCC will replace your calls with:
> 
> address = value;
> 
> or, when reading:
> 
> return address
> 
> >The issue in DMA driver is, if I replace dma_read/dma_write 
> macros with
> >inline functions, I need to remove OMAP_DMA4_##reg macro in dma_read
> >and dma write functions and I have to expand the register names all
> >over the place in DMA driver(like instead of CAPS0, it should be
> >OMAP_DMA4_CAPS0, having only CAPS0 will be easier to read).
> 
> it might be easier to read but this is a recipe for disaster. Avoid
> using those macros for part of the actual symbol/define/whatever name
> like that. If someone later decides to change something, it will be a
> pain. With those macros you also kill any possibility of using
> ctags/cscope for source code cross-referencing. When a developers
> searchs for the definition of CAPS0, he won't find it, as it's called
> OMAP_DMA4_CAPS0. So remove those silly things and change the 
> defines to
> static inline functions.

Ok, Agreed.  We can have inline functions and expanding all macros in mach-omap
dma driver code.
However, there is common dma driver(in plat-omap) which has code for both omap1
and omap2plus which uses this macro.

-Manjunath

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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-14 14:11               ` G, Manjunath Kondaiah
@ 2010-09-15  7:11                 ` Felipe Balbi
  2010-09-16  3:40                   ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Felipe Balbi @ 2010-09-15  7:11 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: Balbi, Felipe, Kevin Hilman, linux-omap, Cousson, Benoit,
	Shilimkar, Santosh

Hi,

On Tue, Sep 14, 2010 at 09:11:26AM -0500, G, Manjunath Kondaiah wrote:
>There are several places in kernel code (ex:
>tools/perf/util/include/linux/bitops.h:static __always_inline int
>test_bit(unsigned int nr, const unsigned long *addr)) which are using
>__always_inline attribute to make sure functions are inlined.

those are special cases. Generally, compiler is much better than humans
for choosing what should be inlined or not.

>Ok, Agreed.  We can have inline functions and expanding all macros in mach-omap
>dma driver code.
>However, there is common dma driver(in plat-omap) which has code for both omap1
>and omap2plus which uses this macro.

well, that can be patched, right ?

-- 
balbi

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

* RE: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-15  7:11                 ` Felipe Balbi
@ 2010-09-16  3:40                   ` G, Manjunath Kondaiah
  2010-09-16  6:03                     ` Felipe Balbi
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-16  3:40 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: Kevin Hilman, linux-omap, Cousson, Benoit, Shilimkar, Santosh

Hi,

> -----Original Message-----
> From: Balbi, Felipe 
> Sent: Wednesday, September 15, 2010 12:41 PM
> To: G, Manjunath Kondaiah
> Cc: Balbi, Felipe; Kevin Hilman; linux-omap@vger.kernel.org; 
> Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
> registration
> 
> Hi,
> 
> On Tue, Sep 14, 2010 at 09:11:26AM -0500, G, Manjunath Kondaiah wrote:
> >There are several places in kernel code (ex:
> >tools/perf/util/include/linux/bitops.h:static __always_inline int 
> >test_bit(unsigned int nr, const unsigned long *addr)) which 
> are using 
> >__always_inline attribute to make sure functions are inlined.
> 
> those are special cases. Generally, compiler is much better 
> than humans for choosing what should be inlined or not.
> 
> >Ok, Agreed.  We can have inline functions and expanding all 
> macros in 
> >mach-omap dma driver code.
> >However, there is common dma driver(in plat-omap) which has code for 
> >both omap1 and omap2plus which uses this macro.
> 
> well, that can be patched, right ?

In that case, the dma_read/dma_write macros will be splitted into:

static inline void omap1_dma_write(...);
static inline void omap2_dma_write(...);
static inline u32 omap1_dma_read(...);
static inline u32 omap2_dma_read(...);

i.e., Two macro definitions will expand into four internal functions.

-Manjunath

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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-16  3:40                   ` G, Manjunath Kondaiah
@ 2010-09-16  6:03                     ` Felipe Balbi
  2010-09-16  6:32                       ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Felipe Balbi @ 2010-09-16  6:03 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: Balbi, Felipe, Kevin Hilman, linux-omap, Cousson, Benoit,
	Shilimkar, Santosh

Hi,

On Wed, Sep 15, 2010 at 10:40:08PM -0500, G, Manjunath Kondaiah wrote:
>In that case, the dma_read/dma_write macros will be splitted into:
>
>static inline void omap1_dma_write(...);
>static inline void omap2_dma_write(...);
>static inline u32 omap1_dma_read(...);
>static inline u32 omap2_dma_read(...);
>
>i.e., Two macro definitions will expand into four internal functions.

why do you need separate methods for omap1 and omap2 ??

-- 
balbi

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

* RE: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-16  6:03                     ` Felipe Balbi
@ 2010-09-16  6:32                       ` G, Manjunath Kondaiah
  2010-09-16  6:40                         ` Felipe Balbi
  2010-09-16 14:16                         ` Kevin Hilman
  0 siblings, 2 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-16  6:32 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: Kevin Hilman, linux-omap, Cousson, Benoit, Shilimkar, Santosh




> -----Original Message-----
> From: Balbi, Felipe 
> Sent: Thursday, September 16, 2010 11:33 AM
> To: G, Manjunath Kondaiah
> Cc: Balbi, Felipe; Kevin Hilman; linux-omap@vger.kernel.org; 
> Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
> registration
> 
> Hi,
> 
> On Wed, Sep 15, 2010 at 10:40:08PM -0500, G, Manjunath Kondaiah wrote:
> >In that case, the dma_read/dma_write macros will be splitted into:
> >
> >static inline void omap1_dma_write(...); static inline void 
> >omap2_dma_write(...); static inline u32 omap1_dma_read(...); static 
> >inline u32 omap2_dma_read(...);
> >
> >i.e., Two macro definitions will expand into four internal functions.
> 
> why do you need separate methods for omap1 and omap2 ??

Current macro definition is:

#define dma_read(reg)                                                   \
({                                                                      \
        u32 __val;                                                      \
        if (cpu_class_is_omap1())                                       \
                __val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg);   \
        else                                                            \
                __val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg);   \
        __val;                                                          \
})

Since we are expanding abbrevated register offsets into full macro, hence
these macros should be used in respective read/write functions(omap1 and omap2plus).

Any other better methods?

-Manjunath

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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-16  6:32                       ` G, Manjunath Kondaiah
@ 2010-09-16  6:40                         ` Felipe Balbi
  2010-09-16  6:53                           ` G, Manjunath Kondaiah
  2010-09-16 14:16                         ` Kevin Hilman
  1 sibling, 1 reply; 62+ messages in thread
From: Felipe Balbi @ 2010-09-16  6:40 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: Balbi, Felipe, Kevin Hilman, linux-omap, Cousson, Benoit,
	Shilimkar, Santosh

Hi,

On Thu, Sep 16, 2010 at 01:32:58AM -0500, G, Manjunath Kondaiah wrote:
>#define dma_read(reg)                                                   \
>({                                                                      \
>        u32 __val;                                                      \
>        if (cpu_class_is_omap1())                                       \
>                __val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg);   \
>        else                                                            \
>                __val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg);   \
>        __val;                                                          \
>})
>
>Since we are expanding abbrevated register offsets into full macro,
>hence these macros should be used in respective read/write
>functions(omap1 and omap2plus).
>
>Any other better methods?

generally we always define static inlines for read{b,w,l} and write{b,
w, l}, so instead of calling them omap1_* and omap2_* call them
something like omap_dma_readw(), omap_dma_readl().

-- 
balbi

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

* RE: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-16  6:40                         ` Felipe Balbi
@ 2010-09-16  6:53                           ` G, Manjunath Kondaiah
  2010-09-16  6:58                             ` Cousson, Benoit
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-16  6:53 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: Kevin Hilman, linux-omap, Cousson, Benoit, Shilimkar, Santosh

Balbi,
> -----Original Message-----
> From: Balbi, Felipe 
> Sent: Thursday, September 16, 2010 12:11 PM
> To: G, Manjunath Kondaiah
> Cc: Balbi, Felipe; Kevin Hilman; linux-omap@vger.kernel.org; 
> Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
> registration
> 
> Hi,
> 
> On Thu, Sep 16, 2010 at 01:32:58AM -0500, G, Manjunath Kondaiah wrote:
> >#define dma_read(reg)                                        
>            \
> >({                                                           
>            \
> >        u32 __val;                                           
>            \
> >        if (cpu_class_is_omap1())                            
>            \
> >                __val = __raw_readw(omap_dma_base + 
> OMAP1_DMA_##reg);   \
> >        else                                                 
>            \
> >                __val = __raw_readl(omap_dma_base + 
> OMAP_DMA4_##reg);   \
> >        __val;                                               
>            \
> >})
> >
> >Since we are expanding abbrevated register offsets into full macro, 
> >hence these macros should be used in respective read/write
> >functions(omap1 and omap2plus).
> >
> >Any other better methods?
> 
> generally we always define static inlines for read{b,w,l} and 
> write{b, w, l}, so instead of calling them omap1_* and 
> omap2_* call them something like omap_dma_readw(), omap_dma_readl().

I am ok with naming convention. But two macros will get converted into
four static inline functions and respective functions will get repeated in
mach-omap1 and mach-omap2.

Due to this, two macros in plat-omap will get converted into 8 static inline 
functions.

-Manjunath


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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-16  6:53                           ` G, Manjunath Kondaiah
@ 2010-09-16  6:58                             ` Cousson, Benoit
  2010-09-16  7:05                               ` Felipe Balbi
  0 siblings, 1 reply; 62+ messages in thread
From: Cousson, Benoit @ 2010-09-16  6:58 UTC (permalink / raw)
  To: Balbi, Felipe
  Cc: G, Manjunath Kondaiah, Kevin Hilman, linux-omap, Shilimkar, Santosh

Hi Felipe,

On 9/16/2010 8:53 AM, G, Manjunath Kondaiah wrote:
> Balbi,

Stupid question, is your first name Felipe or balbi?
You sign with balbi... that's with it is confusing...

Thanks,
Benoit


>> -----Original Message-----
>> From: Balbi, Felipe
>> Sent: Thursday, September 16, 2010 12:11 PM
>> To: G, Manjunath Kondaiah
>> Cc: Balbi, Felipe; Kevin Hilman; linux-omap@vger.kernel.org;
>> Cousson, Benoit; Shilimkar, Santosh
>> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device
>> registration
>>
>> Hi,
>>
>> On Thu, Sep 16, 2010 at 01:32:58AM -0500, G, Manjunath Kondaiah wrote:
>>> #define dma_read(reg)
>>             \
>>> ({
>>             \
>>>         u32 __val;
>>             \
>>>         if (cpu_class_is_omap1())
>>             \
>>>                 __val = __raw_readw(omap_dma_base +
>> OMAP1_DMA_##reg);   \
>>>         else
>>             \
>>>                 __val = __raw_readl(omap_dma_base +
>> OMAP_DMA4_##reg);   \
>>>         __val;
>>             \
>>> })
>>>
>>> Since we are expanding abbrevated register offsets into full macro,
>>> hence these macros should be used in respective read/write
>>> functions(omap1 and omap2plus).
>>>
>>> Any other better methods?
>>
>> generally we always define static inlines for read{b,w,l} and
>> write{b, w, l}, so instead of calling them omap1_* and
>> omap2_* call them something like omap_dma_readw(), omap_dma_readl().
>
> I am ok with naming convention. But two macros will get converted into
> four static inline functions and respective functions will get repeated in
> mach-omap1 and mach-omap2.
>
> Due to this, two macros in plat-omap will get converted into 8 static inline
> functions.
>
> -Manjunath
>


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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-16  6:58                             ` Cousson, Benoit
@ 2010-09-16  7:05                               ` Felipe Balbi
  0 siblings, 0 replies; 62+ messages in thread
From: Felipe Balbi @ 2010-09-16  7:05 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Balbi, Felipe, G, Manjunath Kondaiah, Kevin Hilman, linux-omap,
	Shilimkar, Santosh

Hi,

On Thu, Sep 16, 2010 at 01:58:13AM -0500, Cousson, Benoit wrote:
>Stupid question, is your first name Felipe or balbi?
>You sign with balbi... that's with it is confusing...

Felipe.

Balbi is family name.

-- 
balbi

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

* Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
  2010-09-16  6:32                       ` G, Manjunath Kondaiah
  2010-09-16  6:40                         ` Felipe Balbi
@ 2010-09-16 14:16                         ` Kevin Hilman
  1 sibling, 0 replies; 62+ messages in thread
From: Kevin Hilman @ 2010-09-16 14:16 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: Balbi, Felipe, linux-omap, Cousson, Benoit, Shilimkar, Santosh

"G, Manjunath Kondaiah" <manjugk@ti.com> writes:

>> -----Original Message-----
>> From: Balbi, Felipe 
>> Sent: Thursday, September 16, 2010 11:33 AM
>> To: G, Manjunath Kondaiah
>> Cc: Balbi, Felipe; Kevin Hilman; linux-omap@vger.kernel.org; 
>> Cousson, Benoit; Shilimkar, Santosh
>> Subject: Re: [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device 
>> registration
>> 
>> Hi,
>> 
>> On Wed, Sep 15, 2010 at 10:40:08PM -0500, G, Manjunath Kondaiah wrote:
>> >In that case, the dma_read/dma_write macros will be splitted into:
>> >
>> >static inline void omap1_dma_write(...); static inline void 
>> >omap2_dma_write(...); static inline u32 omap1_dma_read(...); static 
>> >inline u32 omap2_dma_read(...);
>> >
>> >i.e., Two macro definitions will expand into four internal functions.
>> 
>> why do you need separate methods for omap1 and omap2 ??
>
> Current macro definition is:
>
> #define dma_read(reg)                                                   \
> ({                                                                      \
>         u32 __val;                                                      \
>         if (cpu_class_is_omap1())                                       \
>                 __val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg);   \
>         else                                                            \
>                 __val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg);   \
>         __val;                                                          \
> })
>
> Since we are expanding abbrevated register offsets into full macro, hence
> these macros should be used in respective read/write functions(omap1 and omap2plus).
>
> Any other better methods?

Yes.

This is a common problem and is handled in many OMAP drivers using
methods like Felipe described.

There are many examples, but a recent one is the i2c driver which has
different register map between omap2/3 and omap4.  Have a look
at drivers/i2c/busses/i2c-omap.c

Kevin

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

* RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-07 11:48     ` G, Manjunath Kondaiah
  2010-09-14 10:12       ` G, Manjunath Kondaiah
@ 2010-09-17  5:05       ` G, Manjunath Kondaiah
  2010-09-17  7:24         ` Cousson, Benoit
  1 sibling, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-17  5:05 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, Cousson, Benoit, Shilimkar, Santosh

Kevin,

> -----Original Message-----
> From: G, Manjunath Kondaiah 
> Sent: Tuesday, September 14, 2010 3:42 PM
> To: G, Manjunath Kondaiah; Kevin Hilman
> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> Subject: RE: [PATCH v2 09/11] OMAP: DMA: Implement generic 
> errata handling
> 
> Kevin, 
> 
> > -----Original Message-----
> > From: linux-omap-owner@vger.kernel.org 
> > [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, Manjunath 
> > Kondaiah
> > Sent: Tuesday, September 07, 2010 5:18 PM
> > To: Kevin Hilman
> > Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> > Subject: RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata 
> > handling
> > 
> > 
> > 
> > > -----Original Message-----
> > > From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
> > > Sent: Saturday, September 04, 2010 4:12 AM
> > > To: G, Manjunath Kondaiah
> > > Cc: linux-omap@vger.kernel.org; Cousson, Benoit; 
> Shilimkar, Santosh
> > > Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata 
> > > handling
> > > 
> > > Manjunatha GK <manjugk@ti.com> writes:
> > > 
> > > > 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>
> > > > Cc: Benoit Cousson <b-cousson@ti.com>
> > > > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > > > Cc: Santosh Shilimkar <santosh.shilimkar@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 26ab6e3..615c5f5 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;
> > > 
> > > This isn't needed as you just kzalloc'd pdata.
> > ok
> > > 
> > > > +	if (cpu_class_is_omap1() && !cpu_is_omap15xx())
> > > 
> > > You don't need cpu_class_is_omap1() as this is OMAP1 
> specific code.
> > Ok. Looks like copy, paste issue from plat-omap dma.c. I 
> will fix it.
> > > 
> > > > +		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
> > > > f369bee..8832bd1 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;
> > > 
> > > not needed, see above
> > ok
> > > 
> > > > +	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 :
> > > 
> > > fix multi-line comment style
> > Ok.
> > 
> > > 
> > > > +	 * 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 36c3dde..409586a 100644
> > > > --- a/arch/arm/plat-omap/dma.c
> > > > +++ b/arch/arm/plat-omap/dma.c
> > > > @@ -187,6 +187,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)
> > > 
> > > Please use (or extend) hwmod layer for modifying device SYSCONFIG.
> > 
> > I will check this.
> 
> I propose following options for addressing this errata:
> Option 1:
> Creating 2 new API's with 1 static function in omap_hwmod.c 
> for handling midle mode errata issues.
> 
> static int _get_master_standbymode(oh, u32 *idlemode, u32 v); 
> int omap_hwmod_set_master_idlemode(struct omap_hwmod *oh, u8 
> idlemode); int omap_hwmod_get_master_idlemode(struct 
> omap_hwmod *oh, u32 *idlemode);
> 
> In dma driver, the api's will be used as:
> omap_hwmod_get_master_idlemode(oh, midle_mode); 
> omap_hwmod_set_master_idlemode(oh, 1);
> /* disable channels which completed data transfer */ ...
> /* Restore original standby mode values */ 
> omap_hwmod_set_master_idlemode(oh, *midle_mode)
> 
> 
> Option 2:
> Create 1 new exported API for modifying sysconfig standby mode bits.
> In this case, restoring original standby mode value is 
> through accessing sysc flags and _sysc_cache values through 
> oh in DMA driver.
> 
> I feel option #1 seems to be cleaner approach since it avoids 
> accessing oh contents in driver. Let me know if you have 
> objections for the same.
> 
> /Code snippet for option 1 */
> static int _get_master_standbymode(oh, u32 *idlemode) {
> 	u32 mstandby_mask;
> 	u8 mstandby_shift;
> 
> 	...
> 
> 	mstandby_shift = oh->class->sysc->sysc_fields->midle_shift;
> 	mstandby_mask = (0x3 << mstandby_shift);
> 	*idle_mode = ((oh->_sysc_cache) & mstandby_mask) >> 
> mstandby_shift;
> 
> 	return 0;
> }
> 
> int omap_hwmod_set_master_idlemode(struct omap_hwmod *oh, u8 
> idlemode) {
> 	u32 v;
> 	int retval = 0;
> 	...
> 	v = oh->_sysc_cache;
> 
> 	retval = _set_master_standbymode(oh, idlemode, &v);
> 	if (!retval)
> 		_write_sysconfig(v, oh);
> 
> 	return retval;
> }
> 
> int omap_hwmod_get_master_idlemode(struct omap_hwmod *oh, u32 
> *idlemode) {
> 	u32 v;
> 	int retval = 0;
> 	...
> 	retval = _get_master_standbymode(oh, idlemode);
> 	return retval;
> }
> 

I assume you are ok with option #1. Let me know if you have any
issues/concenrs with above approach. I am in the process of consolidating
all the review comments and addressing all applicable review comments.

-Manjunath


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

* Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17  5:05       ` G, Manjunath Kondaiah
@ 2010-09-17  7:24         ` Cousson, Benoit
  2010-09-17  8:09           ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Cousson, Benoit @ 2010-09-17  7:24 UTC (permalink / raw)
  To: G, Manjunath Kondaiah; +Cc: Kevin Hilman, linux-omap, Shilimkar, Santosh

Hi Manjunath,

On 9/17/2010 7:05 AM, G, Manjunath Kondaiah wrote:
> Kevin,
>
>> -----Original Message-----
>> From: G, Manjunath Kondaiah
>> Sent: Tuesday, September 14, 2010 3:42 PM
>> To: G, Manjunath Kondaiah; Kevin Hilman
>> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
>> Subject: RE: [PATCH v2 09/11] OMAP: DMA: Implement generic
>> errata handling
>>
>> Kevin,
>>
>>> -----Original Message-----
>>> From: linux-omap-owner@vger.kernel.org
>>> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, Manjunath
>>> Kondaiah
>>> Sent: Tuesday, September 07, 2010 5:18 PM
>>> To: Kevin Hilman
>>> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
>>> Subject: RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata
>>> handling
>>>
>>>
>>>
>>>> -----Original Message-----
>>>> From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>> Sent: Saturday, September 04, 2010 4:12 AM
>>>> To: G, Manjunath Kondaiah
>>>> Cc: linux-omap@vger.kernel.org; Cousson, Benoit;
>> Shilimkar, Santosh
>>>> Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata
>>>> handling
>>>>
>>>> Manjunatha GK<manjugk@ti.com>  writes:
>>>>
>>>>> 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>
>>>>> Cc: Benoit Cousson<b-cousson@ti.com>
>>>>> Cc: Kevin Hilman<khilman@deeprootsystems.com>
>>>>> Cc: Santosh Shilimkar<santosh.shilimkar@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 26ab6e3..615c5f5 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;
>>>>
>>>> This isn't needed as you just kzalloc'd pdata.
>>> ok
>>>>
>>>>> +	if (cpu_class_is_omap1()&&  !cpu_is_omap15xx())
>>>>
>>>> You don't need cpu_class_is_omap1() as this is OMAP1
>> specific code.
>>> Ok. Looks like copy, paste issue from plat-omap dma.c. I
>> will fix it.
>>>>
>>>>> +		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
>>>>> f369bee..8832bd1 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;
>>>>
>>>> not needed, see above
>>> ok
>>>>
>>>>> +	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 :
>>>>
>>>> fix multi-line comment style
>>> Ok.
>>>
>>>>
>>>>> +	 * 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 36c3dde..409586a 100644
>>>>> --- a/arch/arm/plat-omap/dma.c
>>>>> +++ b/arch/arm/plat-omap/dma.c
>>>>> @@ -187,6 +187,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)
>>>>
>>>> Please use (or extend) hwmod layer for modifying device SYSCONFIG.
>>>
>>> I will check this.
>>
>> I propose following options for addressing this errata:
>> Option 1:
>> Creating 2 new API's with 1 static function in omap_hwmod.c
>> for handling midle mode errata issues.
>>
>> static int _get_master_standbymode(oh, u32 *idlemode, u32 v);
>> int omap_hwmod_set_master_idlemode(struct omap_hwmod *oh, u8
>> idlemode); int omap_hwmod_get_master_idlemode(struct
>> omap_hwmod *oh, u32 *idlemode);
>>
>> In dma driver, the api's will be used as:
>> omap_hwmod_get_master_idlemode(oh, midle_mode);
>> omap_hwmod_set_master_idlemode(oh, 1);
>> /* disable channels which completed data transfer */ ...
>> /* Restore original standby mode values */
>> omap_hwmod_set_master_idlemode(oh, *midle_mode)
>>
>>
>> Option 2:
>> Create 1 new exported API for modifying sysconfig standby mode bits.
>> In this case, restoring original standby mode value is
>> through accessing sysc flags and _sysc_cache values through
>> oh in DMA driver.
>>
>> I feel option #1 seems to be cleaner approach since it avoids
>> accessing oh contents in driver. Let me know if you have
>> objections for the same.
>>
>> /Code snippet for option 1 */
>> static int _get_master_standbymode(oh, u32 *idlemode) {
>> 	u32 mstandby_mask;
>> 	u8 mstandby_shift;
>>
>> 	...
>>
>> 	mstandby_shift = oh->class->sysc->sysc_fields->midle_shift;
>> 	mstandby_mask = (0x3<<  mstandby_shift);
>> 	*idle_mode = ((oh->_sysc_cache)&  mstandby_mask)>>
>> mstandby_shift;
>>
>> 	return 0;
>> }
>>
>> int omap_hwmod_set_master_idlemode(struct omap_hwmod *oh, u8
>> idlemode) {
>> 	u32 v;
>> 	int retval = 0;
>> 	...
>> 	v = oh->_sysc_cache;
>>
>> 	retval = _set_master_standbymode(oh, idlemode,&v);
>> 	if (!retval)
>> 		_write_sysconfig(v, oh);
>>
>> 	return retval;
>> }
>>
>> int omap_hwmod_get_master_idlemode(struct omap_hwmod *oh, u32
>> *idlemode) {
>> 	u32 v;
>> 	int retval = 0;
>> 	...
>> 	retval = _get_master_standbymode(oh, idlemode);
>> 	return retval;
>> }
>>
>
> I assume you are ok with option #1. Let me know if you have any
> issues/concenrs with above approach. I am in the process of consolidating
> all the review comments and addressing all applicable review comments.

Not really, the option #1 will still require you to use the oh pointer, 
which is supposed to be private to the omap_device.

What is still not clear is why and when you need to change the sysconfig 
setting.

Do you have a details explanation? Ideally you should try to couple the 
sysconfig change along with pm_runtime / hwmod state change, then we 
will be able to handle that smoothly in the framework.

If you cannot do that, you will need to add an omap_device API as well.

Regards,
Benoit


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

* RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17  7:24         ` Cousson, Benoit
@ 2010-09-17  8:09           ` G, Manjunath Kondaiah
  2010-09-17 10:29             ` Cousson, Benoit
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-17  8:09 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Kevin Hilman, linux-omap, Shilimkar, Santosh

Hi Benoit, 

> -----Original Message-----
> From: Cousson, Benoit 
> Sent: Friday, September 17, 2010 12:55 PM
> To: G, Manjunath Kondaiah
> Cc: Kevin Hilman; linux-omap@vger.kernel.org; Shilimkar, Santosh
> Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic 
> errata handling
> 
> Hi Manjunath,
> 
> On 9/17/2010 7:05 AM, G, Manjunath Kondaiah wrote:
> > Kevin,
> >
> >> -----Original Message-----
> >> From: G, Manjunath Kondaiah
> >> Sent: Tuesday, September 14, 2010 3:42 PM
> >> To: G, Manjunath Kondaiah; Kevin Hilman
> >> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; Shilimkar, Santosh
> >> Subject: RE: [PATCH v2 09/11] OMAP: DMA: Implement generic
> >> errata handling
> >>
> >> Kevin,
> >>
> >>> -----Original Message-----
> >>> From: linux-omap-owner@vger.kernel.org
> >>> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of G, 
> Manjunath
> >>> Kondaiah
> >>> Sent: Tuesday, September 07, 2010 5:18 PM
> >>> To: Kevin Hilman
> >>> Cc: linux-omap@vger.kernel.org; Cousson, Benoit; 
> Shilimkar, Santosh
> >>> Subject: RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata
> >>> handling
> >>>
> >>>
> >>>
> >>>> -----Original Message-----
> >>>> From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
> >>>> Sent: Saturday, September 04, 2010 4:12 AM
> >>>> To: G, Manjunath Kondaiah
> >>>> Cc: linux-omap@vger.kernel.org; Cousson, Benoit;
> >> Shilimkar, Santosh
> >>>> Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata
> >>>> handling
> >>>>
> >>>> Manjunatha GK<manjugk@ti.com>  writes:
> >>>>
> >>>>> 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>
> >>>>> Cc: Benoit Cousson<b-cousson@ti.com>
> >>>>> Cc: Kevin Hilman<khilman@deeprootsystems.com>
> >>>>> Cc: Santosh Shilimkar<santosh.shilimkar@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 26ab6e3..615c5f5 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;
> >>>>
> >>>> This isn't needed as you just kzalloc'd pdata.
> >>> ok
> >>>>
> >>>>> +	if (cpu_class_is_omap1()&&  !cpu_is_omap15xx())
> >>>>
> >>>> You don't need cpu_class_is_omap1() as this is OMAP1
> >> specific code.
> >>> Ok. Looks like copy, paste issue from plat-omap dma.c. I
> >> will fix it.
> >>>>
> >>>>> +		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
> >>>>> f369bee..8832bd1 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;
> >>>>
> >>>> not needed, see above
> >>> ok
> >>>>
> >>>>> +	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 :
> >>>>
> >>>> fix multi-line comment style
> >>> Ok.
> >>>
> >>>>
> >>>>> +	 * 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 36c3dde..409586a 100644
> >>>>> --- a/arch/arm/plat-omap/dma.c
> >>>>> +++ b/arch/arm/plat-omap/dma.c
> >>>>> @@ -187,6 +187,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)
> >>>>
> >>>> Please use (or extend) hwmod layer for modifying device 
> SYSCONFIG.
> >>>
> >>> I will check this.
> >>
> >> I propose following options for addressing this errata:
> >> Option 1:
> >> Creating 2 new API's with 1 static function in omap_hwmod.c
> >> for handling midle mode errata issues.
> >>
> >> static int _get_master_standbymode(oh, u32 *idlemode, u32 v);
> >> int omap_hwmod_set_master_idlemode(struct omap_hwmod *oh, u8
> >> idlemode); int omap_hwmod_get_master_idlemode(struct
> >> omap_hwmod *oh, u32 *idlemode);
> >>
> >> In dma driver, the api's will be used as:
> >> omap_hwmod_get_master_idlemode(oh, midle_mode);
> >> omap_hwmod_set_master_idlemode(oh, 1);
> >> /* disable channels which completed data transfer */ ...
> >> /* Restore original standby mode values */
> >> omap_hwmod_set_master_idlemode(oh, *midle_mode)
> >>
> >>
> >> Option 2:
> >> Create 1 new exported API for modifying sysconfig standby 
> mode bits.
> >> In this case, restoring original standby mode value is
> >> through accessing sysc flags and _sysc_cache values through
> >> oh in DMA driver.
> >>
> >> I feel option #1 seems to be cleaner approach since it avoids
> >> accessing oh contents in driver. Let me know if you have
> >> objections for the same.
> >>
> >> /Code snippet for option 1 */
> >> static int _get_master_standbymode(oh, u32 *idlemode) {
> >> 	u32 mstandby_mask;
> >> 	u8 mstandby_shift;
> >>
> >> 	...
> >>
> >> 	mstandby_shift = oh->class->sysc->sysc_fields->midle_shift;
> >> 	mstandby_mask = (0x3<<  mstandby_shift);
> >> 	*idle_mode = ((oh->_sysc_cache)&  mstandby_mask)>>
> >> mstandby_shift;
> >>
> >> 	return 0;
> >> }
> >>
> >> int omap_hwmod_set_master_idlemode(struct omap_hwmod *oh, u8
> >> idlemode) {
> >> 	u32 v;
> >> 	int retval = 0;
> >> 	...
> >> 	v = oh->_sysc_cache;
> >>
> >> 	retval = _set_master_standbymode(oh, idlemode,&v);
> >> 	if (!retval)
> >> 		_write_sysconfig(v, oh);
> >>
> >> 	return retval;
> >> }
> >>
> >> int omap_hwmod_get_master_idlemode(struct omap_hwmod *oh, u32
> >> *idlemode) {
> >> 	u32 v;
> >> 	int retval = 0;
> >> 	...
> >> 	retval = _get_master_standbymode(oh, idlemode);
> >> 	return retval;
> >> }
> >>
> >
> > I assume you are ok with option #1. Let me know if you have any
> > issues/concenrs with above approach. I am in the process of 
> consolidating
> > all the review comments and addressing all applicable 
> review comments.
> 
> Not really, the option #1 will still require you to use the 
> oh pointer, 
> which is supposed to be private to the omap_device.
> 
> What is still not clear is why and when you need to change 
> the sysconfig 
> setting.

It is required before stopping DMA chain transfer. 

> 
> Do you have a details explanation? Ideally you should try to 
> couple the 
> sysconfig change along with pm_runtime / hwmod state change, then we 
> will be able to handle that smoothly in the framework.

Since channel is already requested(and there is possibility of other channels
also used at the same time), using pm_runtime API's will only increase
usage count and will not invoke omap_device_enable.

> 
> If you cannot do that, you will need to add an omap_device 
> API as well.

There is already one such API exists in hwmod layer for handling this type
of errata(omap_hwmod_set_slave_idlemode in omap_hwmod.c).
Above proposal is based on similar implementation.

-Manjunath




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

* Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17  8:09           ` G, Manjunath Kondaiah
@ 2010-09-17 10:29             ` Cousson, Benoit
  2010-09-17 11:28               ` G, Manjunath Kondaiah
  0 siblings, 1 reply; 62+ messages in thread
From: Cousson, Benoit @ 2010-09-17 10:29 UTC (permalink / raw)
  To: G, Manjunath Kondaiah; +Cc: Kevin Hilman, linux-omap, Shilimkar, Santosh

On 9/17/2010 10:09 AM, G, Manjunath Kondaiah wrote:
> Hi Benoit,
>

<...>

>>>
>>> I assume you are ok with option #1. Let me know if you have any
>>> issues/concenrs with above approach. I am in the process of
>> consolidating
>>> all the review comments and addressing all applicable
>> review comments.
>>
>> Not really, the option #1 will still require you to use the
>> oh pointer,
>> which is supposed to be private to the omap_device.
>>
>> What is still not clear is why and when you need to change
>> the sysconfig
>> setting.
>
> It is required before stopping DMA chain transfer.

OK, but why? What happen if you do not do that? Could you please give 
the full errata description to help us understanding?

>> Do you have a details explanation? Ideally you should try to
>> couple the
>> sysconfig change along with pm_runtime / hwmod state change, then we
>> will be able to handle that smoothly in the framework.
>
> Since channel is already requested(and there is possibility of other channels
> also used at the same time), using pm_runtime API's will only increase
> usage count and will not invoke omap_device_enable.

This is the part that is not clear, and where the full errata should 
help, because if you do have other channel in use, you will not be able 
to do any clock gating anyway, that why changing the sysconfig at that 
time might be useless.

>> If you cannot do that, you will need to add an omap_device
>> API as well.
>
> There is already one such API exists in hwmod layer for handling this type
> of errata(omap_hwmod_set_slave_idlemode in omap_hwmod.c).
> Above proposal is based on similar implementation.

Maybe, but this is not enough. In both case you should not use directly 
this API from the driver, so if you want to use that kind of approach, 
you will need the omap_device layer as well.


Regards,
Benoit

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

* RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17 10:29             ` Cousson, Benoit
@ 2010-09-17 11:28               ` G, Manjunath Kondaiah
  2010-09-17 14:51                 ` Cousson, Benoit
  0 siblings, 1 reply; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-17 11:28 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Kevin Hilman, linux-omap, Shilimkar, Santosh


 

> -----Original Message-----
> From: Cousson, Benoit 
> Sent: Friday, September 17, 2010 3:59 PM
> To: G, Manjunath Kondaiah
> Cc: Kevin Hilman; linux-omap@vger.kernel.org; Shilimkar, Santosh
> Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic 
> errata handling
> 
> On 9/17/2010 10:09 AM, G, Manjunath Kondaiah wrote:
> > Hi Benoit,
> >
> 
> <...>
> 
> >>>
> >>> I assume you are ok with option #1. Let me know if you have any 
> >>> issues/concenrs with above approach. I am in the process of
> >> consolidating
> >>> all the review comments and addressing all applicable
> >> review comments.
> >>
> >> Not really, the option #1 will still require you to use the oh 
> >> pointer, which is supposed to be private to the omap_device.
> >>
> >> What is still not clear is why and when you need to change the 
> >> sysconfig setting.
> >
> > It is required before stopping DMA chain transfer.
> 
> OK, but why? What happen if you do not do that? Could you 
> please give the full errata description to help us understanding?

Here is summary of errata description:

Software will program DMA to transfer an arbitrary high number of data, and disable the DMA
channel whenever it is sure that all the data have been read from the source and transferred to the
destination.

When doing this, software must ensure that the DMA is configured in No Standby mode
(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01"). If this is not the case, the software may disable the
channel when it is transitioning to standby state. This would cause the DMA internal 
FIFO pointer not to be reset correctly and available DMA FIFO space to be artificially 
decreased. The consequences range from unnecessary unaligned accesses performed,
to complete DMA transfer hanging.

WORKAROUND
The correct procedure to disable a DMA channel before it reaches end of block is:
1. Set OCP_SYSCONFIG.MIDLEMODE to "01"
2. Disable DMA channel by writing bit DMA4_CCR_i[7].Enable='0'
3. Ensure current DMA transfer is completed by polling the relevant DMA4_CCR_i[9].RD_ACTIVE/
DMA4_CCR_i[10].WR_ACTIVE bit.
4. Restore OCP_SYSCONFIG.MIDLEMODE to its previous value.


> 
> >> Do you have a details explanation? Ideally you should try 
> to couple 
> >> the sysconfig change along with pm_runtime / hwmod state 
> change, then 
> >> we will be able to handle that smoothly in the framework.
> >
> > Since channel is already requested(and there is possibility 
> of other 
> > channels also used at the same time), using pm_runtime 
> API's will only 
> > increase usage count and will not invoke omap_device_enable.
> 
> This is the part that is not clear, and where the full errata 
> should help, because if you do have other channel in use, you 
> will not be able to do any clock gating anyway, that why 
> changing the sysconfig at that time might be useless.

Errata description provided.

> 
> >> If you cannot do that, you will need to add an omap_device API as 
> >> well.
> >
> > There is already one such API exists in hwmod layer for 
> handling this 
> > type of errata(omap_hwmod_set_slave_idlemode in omap_hwmod.c).
> > Above proposal is based on similar implementation.
> 
> Maybe, but this is not enough. In both case you should not 
> use directly this API from the driver, so if you want to use 
> that kind of approach, you will need the omap_device layer as well.

Does that mean, extending omap device layer for modifying sysconfig?

-Manjunath

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

* Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17 11:28               ` G, Manjunath Kondaiah
@ 2010-09-17 14:51                 ` Cousson, Benoit
  2010-09-17 15:32                   ` Kevin Hilman
  2010-09-18  1:10                   ` G, Manjunath Kondaiah
  0 siblings, 2 replies; 62+ messages in thread
From: Cousson, Benoit @ 2010-09-17 14:51 UTC (permalink / raw)
  To: G, Manjunath Kondaiah; +Cc: Kevin Hilman, linux-omap, Shilimkar, Santosh

On 9/17/2010 1:28 PM, G, Manjunath Kondaiah wrote:
>> From: Cousson, Benoit
>> Sent: Friday, September 17, 2010 3:59 PM
>>
>> On 9/17/2010 10:09 AM, G, Manjunath Kondaiah wrote:
>>> Hi Benoit,
>>>
>>
>> <...>
>>
>>>>>
>>>>> I assume you are ok with option #1. Let me know if you have any
>>>>> issues/concenrs with above approach. I am in the process of
>>>> consolidating
>>>>> all the review comments and addressing all applicable
>>>> review comments.
>>>>
>>>> Not really, the option #1 will still require you to use the oh
>>>> pointer, which is supposed to be private to the omap_device.
>>>>
>>>> What is still not clear is why and when you need to change the
>>>> sysconfig setting.
>>>
>>> It is required before stopping DMA chain transfer.
>>
>> OK, but why? What happen if you do not do that? Could you
>> please give the full errata description to help us understanding?
>
> Here is summary of errata description:
>
> Software will program DMA to transfer an arbitrary high number of data, and disable the DMA
> channel whenever it is sure that all the data have been read from the source and transferred to the
> destination.
>
> When doing this, software must ensure that the DMA is configured in No Standby mode
> (DMAx_OCP_SYSCONFIG.MIDLEMODE = "01"). If this is not the case, the software may disable the
> channel when it is transitioning to standby state. This would cause the DMA internal
> FIFO pointer not to be reset correctly and available DMA FIFO space to be artificially
> decreased. The consequences range from unnecessary unaligned accesses performed,
> to complete DMA transfer hanging.

Thanks for the details.

That's an interesting bug to handle...

And what happen if you do not disable the DMA channel at that time?


> WORKAROUND
> The correct procedure to disable a DMA channel before it reaches end of block is:

That part is not clear: Why do we have to disable a channel before its 
completion? Cannot we wait?

> 1. Set OCP_SYSCONFIG.MIDLEMODE to "01"
> 2. Disable DMA channel by writing bit DMA4_CCR_i[7].Enable='0'
> 3. Ensure current DMA transfer is completed by polling the relevant DMA4_CCR_i[9].RD_ACTIVE/
> DMA4_CCR_i[10].WR_ACTIVE bit.
> 4. Restore OCP_SYSCONFIG.MIDLEMODE to its previous value.

>>>> Do you have a details explanation? Ideally you should try
>> to couple
>>>> the sysconfig change along with pm_runtime / hwmod state
>> change, then
>>>> we will be able to handle that smoothly in the framework.
>>>
>>> Since channel is already requested(and there is possibility
>> of other
>>> channels also used at the same time), using pm_runtime
>> API's will only
>>> increase usage count and will not invoke omap_device_enable.
>>
>> This is the part that is not clear, and where the full errata
>> should help, because if you do have other channel in use, you
>> will not be able to do any clock gating anyway, that why
>> changing the sysconfig at that time might be useless.
>
> Errata description provided.
>
>>
>>>> If you cannot do that, you will need to add an omap_device API as
>>>> well.
>>>
>>> There is already one such API exists in hwmod layer for
>> handling this
>>> type of errata(omap_hwmod_set_slave_idlemode in omap_hwmod.c).
>>> Above proposal is based on similar implementation.
>>
>> Maybe, but this is not enough. In both case you should not
>> use directly this API from the driver, so if you want to use
>> that kind of approach, you will need the omap_device layer as well.
>
> Does that mean, extending omap device layer for modifying sysconfig?

Yes,

Benoit

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

* Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17 14:51                 ` Cousson, Benoit
@ 2010-09-17 15:32                   ` Kevin Hilman
  2010-09-18  1:19                     ` G, Manjunath Kondaiah
  2010-09-18  1:10                   ` G, Manjunath Kondaiah
  1 sibling, 1 reply; 62+ messages in thread
From: Kevin Hilman @ 2010-09-17 15:32 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: G, Manjunath Kondaiah, linux-omap, Shilimkar, Santosh

"Cousson, Benoit" <b-cousson@ti.com> writes:

[...]

>>>>> If you cannot do that, you will need to add an omap_device API as
>>>>> well.
>>>>
>>>> There is already one such API exists in hwmod layer for handling
>>>> this type of errata(omap_hwmod_set_slave_idlemode in omap_hwmod.c).
>>>> Above proposal is based on similar implementation.
>>>
>>> Maybe, but this is not enough. In both case you should not use
>>> directly this API from the driver, so if you want to use that kind
>>> of approach, you will need the omap_device layer as well.
>>
>> Does that mean, extending omap device layer for modifying sysconfig?
>
> Yes,
>

Just to re-iterate Benoit's point:

Driver's should not have any knowledge of omap_hwmods.  All the
interaction with hwmods is done via the omap_device layer. 

So, if it is decide that you need a new API for this sysconfig change,
you have to add it to *both* the hwmod layer and the omap_device layer.

As with all the other functions, driver calls omap_device, and
omap_device calls omap_hwmod as needed.

Kevin

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

* Re: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-08-24 11:04 ` [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling Manjunatha GK
  2010-09-03 22:42   ` Kevin Hilman
@ 2010-09-17 15:45   ` Cousson, Benoit
  2010-09-18  1:15     ` G, Manjunath Kondaiah
  1 sibling, 1 reply; 62+ messages in thread
From: Cousson, Benoit @ 2010-09-17 15:45 UTC (permalink / raw)
  To: G, Manjunath Kondaiah; +Cc: linux-omap, Kevin Hilman, Shilimkar, Santosh

On 8/24/2010 1:04 PM, G, Manjunath Kondaiah wrote:
> This patch introduces generic way of handling all OMAP DMA
> errata's which are applicable for OMAP1 and OMAP2PLUS processors.

<...>

> diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
> index f369bee..8832bd1 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;
> +

The DMA_SYSCONFIG_ERRATA does not seems to be initialized there. How are 
you enabling that errata?

Benoit

>   	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 36c3dde..409586a 100644
> --- a/arch/arm/plat-omap/dma.c
> +++ b/arch/arm/plat-omap/dma.c
> @@ -187,6 +187,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)
>   {
> @@ -971,22 +990,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;
> @@ -1660,7 +1673,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))) {
> @@ -1675,15 +1688,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++) {
>
> @@ -1702,8 +1708,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 a44b11b..ca251ac 100644
> --- a/arch/arm/plat-omap/include/plat/dma.h
> +++ b/arch/arm/plat-omap/include/plat/dma.h
> @@ -269,6 +269,14 @@
>   #define IS_WORD_16			(1<<  0xC)
>   #define IS_RW_PRIORIY			(1<<  0xD)
>
> +/* 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,
> @@ -346,6 +354,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);


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

* RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17 14:51                 ` Cousson, Benoit
  2010-09-17 15:32                   ` Kevin Hilman
@ 2010-09-18  1:10                   ` G, Manjunath Kondaiah
  1 sibling, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-18  1:10 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Kevin Hilman, linux-omap, Shilimkar, Santosh

 

> -----Original Message-----
> From: Cousson, Benoit 
> Sent: Friday, September 17, 2010 8:21 PM
> To: G, Manjunath Kondaiah
> Cc: Kevin Hilman; linux-omap@vger.kernel.org; Shilimkar, Santosh
> Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic 
> errata handling
> 
> On 9/17/2010 1:28 PM, G, Manjunath Kondaiah wrote:
> >> From: Cousson, Benoit
> >> Sent: Friday, September 17, 2010 3:59 PM
> >>
> >> On 9/17/2010 10:09 AM, G, Manjunath Kondaiah wrote:
> >>> Hi Benoit,
> >>>
> >>
> >> <...>
> >>
> >>>>>
> >>>>> I assume you are ok with option #1. Let me know if you have any 
> >>>>> issues/concenrs with above approach. I am in the process of
> >>>> consolidating
> >>>>> all the review comments and addressing all applicable
> >>>> review comments.
> >>>>
> >>>> Not really, the option #1 will still require you to use the oh 
> >>>> pointer, which is supposed to be private to the omap_device.
> >>>>
> >>>> What is still not clear is why and when you need to change the 
> >>>> sysconfig setting.
> >>>
> >>> It is required before stopping DMA chain transfer.
> >>
> >> OK, but why? What happen if you do not do that? Could you 
> please give 
> >> the full errata description to help us understanding?
> >
> > Here is summary of errata description:
> >
> > Software will program DMA to transfer an arbitrary high number of 
> > data, and disable the DMA channel whenever it is sure that all the 
> > data have been read from the source and transferred to the 
> destination.
> >
> > When doing this, software must ensure that the DMA is 
> configured in No 
> > Standby mode (DMAx_OCP_SYSCONFIG.MIDLEMODE = "01"). If this 
> is not the 
> > case, the software may disable the channel when it is 
> transitioning to 
> > standby state. This would cause the DMA internal FIFO 
> pointer not to 
> > be reset correctly and available DMA FIFO space to be artificially 
> > decreased. The consequences range from unnecessary 
> unaligned accesses performed, to complete DMA transfer hanging.
> 
> Thanks for the details.
> 
> That's an interesting bug to handle...
> 
> And what happen if you do not disable the DMA channel at that time?

I don't know since this errata is applicable only for 3430 ES1.0 and
from ES2.0 onwards it is fixed. This was implemented during 3430 post wakeup
period.

> 
> 
> > WORKAROUND
> > The correct procedure to disable a DMA channel before it 
> reaches end of block is:
> 
> That part is not clear: Why do we have to disable a channel 
> before its completion? Cannot we wait?

Not before completion, it is after completion of data transfer and before
disabling channel, sysconfig register needs to be set to standby mode.

> 
> > 1. Set OCP_SYSCONFIG.MIDLEMODE to "01"
> > 2. Disable DMA channel by writing bit DMA4_CCR_i[7].Enable='0'
> > 3. Ensure current DMA transfer is completed by polling the relevant 
> > DMA4_CCR_i[9].RD_ACTIVE/ DMA4_CCR_i[10].WR_ACTIVE bit.
> > 4. Restore OCP_SYSCONFIG.MIDLEMODE to its previous value.
> 
> >>>> Do you have a details explanation? Ideally you should try
> >> to couple
> >>>> the sysconfig change along with pm_runtime / hwmod state
> >> change, then
> >>>> we will be able to handle that smoothly in the framework.
> >>>
> >>> Since channel is already requested(and there is possibility
> >> of other
> >>> channels also used at the same time), using pm_runtime
> >> API's will only
> >>> increase usage count and will not invoke omap_device_enable.
> >>
> >> This is the part that is not clear, and where the full 
> errata should 
> >> help, because if you do have other channel in use, you will not be 
> >> able to do any clock gating anyway, that why changing the 
> sysconfig 
> >> at that time might be useless.
> >
> > Errata description provided.
> >
> >>
> >>>> If you cannot do that, you will need to add an 
> omap_device API as 
> >>>> well.
> >>>
> >>> There is already one such API exists in hwmod layer for
> >> handling this
> >>> type of errata(omap_hwmod_set_slave_idlemode in omap_hwmod.c).
> >>> Above proposal is based on similar implementation.
> >>
> >> Maybe, but this is not enough. In both case you should not use 
> >> directly this API from the driver, so if you want to use 
> that kind of 
> >> approach, you will need the omap_device layer as well.
> >
> > Does that mean, extending omap device layer for modifying sysconfig?
> 
> Yes,

This part is not clear. Is it implementing new API in omap device layer or
extending existing API? 

-Manjunath

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

* RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17 15:45   ` Cousson, Benoit
@ 2010-09-18  1:15     ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-18  1:15 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: linux-omap, Kevin Hilman, Shilimkar, Santosh




> -----Original Message-----
> From: Cousson, Benoit 
> Sent: Friday, September 17, 2010 9:15 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap@vger.kernel.org; Kevin Hilman; Shilimkar, Santosh
> Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic 
> errata handling
> 
> On 8/24/2010 1:04 PM, G, Manjunath Kondaiah wrote:
> > This patch introduces generic way of handling all OMAP DMA errata's 
> > which are applicable for OMAP1 and OMAP2PLUS processors.
> 
> <...>
> 
> > diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c 
> > index f369bee..8832bd1 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;
> > +
> 
> The DMA_SYSCONFIG_ERRATA does not seems to be initialized 
> there. How are you enabling that errata?

Thanks. I have already identified this and taken care in my internal version. It 
will be enabled in next version.

-Manjunath


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

* RE: [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling
  2010-09-17 15:32                   ` Kevin Hilman
@ 2010-09-18  1:19                     ` G, Manjunath Kondaiah
  0 siblings, 0 replies; 62+ messages in thread
From: G, Manjunath Kondaiah @ 2010-09-18  1:19 UTC (permalink / raw)
  To: Kevin Hilman, Cousson, Benoit; +Cc: linux-omap, Shilimkar, Santosh



> -----Original Message-----
> From: Kevin Hilman [mailto:khilman@deeprootsystems.com] 
> Sent: Friday, September 17, 2010 9:02 PM
> To: Cousson, Benoit
> Cc: G, Manjunath Kondaiah; linux-omap@vger.kernel.org; 
> Shilimkar, Santosh
> Subject: Re: [PATCH v2 09/11] OMAP: DMA: Implement generic 
> errata handling
> 
> "Cousson, Benoit" <b-cousson@ti.com> writes:
> 
> [...]
> 
> >>>>> If you cannot do that, you will need to add an 
> omap_device API as 
> >>>>> well.
> >>>>
> >>>> There is already one such API exists in hwmod layer for handling 
> >>>> this type of errata(omap_hwmod_set_slave_idlemode in 
> omap_hwmod.c).
> >>>> Above proposal is based on similar implementation.
> >>>
> >>> Maybe, but this is not enough. In both case you should not use 
> >>> directly this API from the driver, so if you want to use 
> that kind 
> >>> of approach, you will need the omap_device layer as well.
> >>
> >> Does that mean, extending omap device layer for modifying 
> sysconfig?
> >
> > Yes,
> >
> 
> Just to re-iterate Benoit's point:
> 
> Driver's should not have any knowledge of omap_hwmods.  All 
> the interaction with hwmods is done via the omap_device layer. 
> 
> So, if it is decide that you need a new API for this 
> sysconfig change, you have to add it to *both* the hwmod 
> layer and the omap_device layer.
> 
> As with all the other functions, driver calls omap_device, 
> and omap_device calls omap_hwmod as needed.

Ok. Agreed.

-Manjunath
 

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

end of thread, other threads:[~2010-09-18  1:19 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-24 11:04 [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver Manjunatha GK
2010-08-24 11:04 ` [PATCH v2 01/11] OMAP: DMA: Introduce DMA device attributes Manjunatha GK
2010-08-24 11:04 ` [PATCH v2 02/11] OMAP2420: DMA: HWMOD: Add hwmod data structures Manjunatha GK
2010-08-24 11:04 ` [PATCH v2 03/11] OMAP2430: " Manjunatha GK
2010-08-24 11:30   ` Mika Westerberg
2010-08-24 14:32     ` G, Manjunath Kondaiah
2010-08-24 11:04 ` [PATCH v2 04/11] OMAP3: " Manjunatha GK
2010-09-03 20:51   ` Kevin Hilman
2010-09-04 14:45     ` Cousson, Benoit
2010-09-08  1:52     ` G, Manjunath Kondaiah
2010-08-24 11:04 ` [PATCH v2 05/11] OMAP4: " Manjunatha GK
2010-08-24 11:04 ` [PATCH v2 06/11] OMAP1: DMA: Introduce DMA driver as platform driver Manjunatha GK
2010-08-24 11:04 ` [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration Manjunatha GK
2010-09-03 20:59   ` Kevin Hilman
2010-09-07 11:47     ` G, Manjunath Kondaiah
2010-09-14 10:18       ` G, Manjunath Kondaiah
2010-09-14 10:24         ` Felipe Balbi
2010-09-14 11:44           ` G, Manjunath Kondaiah
2010-09-14 11:57             ` Felipe Balbi
2010-09-14 14:11               ` G, Manjunath Kondaiah
2010-09-15  7:11                 ` Felipe Balbi
2010-09-16  3:40                   ` G, Manjunath Kondaiah
2010-09-16  6:03                     ` Felipe Balbi
2010-09-16  6:32                       ` G, Manjunath Kondaiah
2010-09-16  6:40                         ` Felipe Balbi
2010-09-16  6:53                           ` G, Manjunath Kondaiah
2010-09-16  6:58                             ` Cousson, Benoit
2010-09-16  7:05                               ` Felipe Balbi
2010-09-16 14:16                         ` Kevin Hilman
2010-08-24 11:04 ` [PATCH v2 08/11] OMAP: DMA: Convert DMA library into DMA platform Driver Manjunatha GK
2010-09-03 22:34   ` Kevin Hilman
2010-09-07 11:47     ` G, Manjunath Kondaiah
2010-09-07 22:45       ` Kevin Hilman
2010-09-08  1:46         ` G, Manjunath Kondaiah
2010-08-24 11:04 ` [PATCH v2 09/11] OMAP: DMA: Implement generic errata handling Manjunatha GK
2010-09-03 22:42   ` Kevin Hilman
2010-09-07 11:48     ` G, Manjunath Kondaiah
2010-09-14 10:12       ` G, Manjunath Kondaiah
2010-09-17  5:05       ` G, Manjunath Kondaiah
2010-09-17  7:24         ` Cousson, Benoit
2010-09-17  8:09           ` G, Manjunath Kondaiah
2010-09-17 10:29             ` Cousson, Benoit
2010-09-17 11:28               ` G, Manjunath Kondaiah
2010-09-17 14:51                 ` Cousson, Benoit
2010-09-17 15:32                   ` Kevin Hilman
2010-09-18  1:19                     ` G, Manjunath Kondaiah
2010-09-18  1:10                   ` G, Manjunath Kondaiah
2010-09-17 15:45   ` Cousson, Benoit
2010-09-18  1:15     ` G, Manjunath Kondaiah
2010-08-24 11:04 ` [PATCH v2 10/11] OMAP: DMA: Use DMA device attributes Manjunatha GK
2010-09-03 20:45   ` Kevin Hilman
2010-09-07 11:47     ` G, Manjunath Kondaiah
2010-08-24 11:04 ` [PATCH v2 11/11] sDMA: descriptor autoloading feature Manjunatha GK
2010-09-03 16:21 ` [PATCH v2 00/11] OMAP: DMA: HWMOD and DMA as platform driver G, Manjunath Kondaiah
2010-09-03 16:39   ` Cousson, Benoit
2010-09-07 11:46     ` G, Manjunath Kondaiah
2010-09-03 16:44   ` Kevin Hilman
2010-09-03 22:49   ` Kevin Hilman
2010-09-07 11:48     ` G, Manjunath Kondaiah
2010-09-08  8:43       ` G, Manjunath Kondaiah
2010-09-03 20:38 ` Kevin Hilman
2010-09-07 11:47   ` 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.