* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-10-26 14:48 ` Nishanth Menon
2010-11-09 21:37 ` Kevin Hilman
2010-10-26 13:25 ` [PATCH v3 02/13] OMAP: DMA: Introduce errata handling feature G, Manjunath Kondaiah
` (13 subsequent siblings)
14 siblings, 2 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
The low level read/write macros are replaced with static inline functions
and register offsets are handled through static register offset tables
mapped through enumeration constants.
The objective of this patch is to prepare for omap dma driver cleanup
and dma hwmod implementation. The code optimization and moving machine
specific code to respective mach-omapx dma file will be handled in the
rest of this patch series.
Signed-off-by: G, Manjunath Kondaiah <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/dma.c | 739 ++++++++++++++++++++++-----------
arch/arm/plat-omap/include/plat/dma.h | 120 ------
2 files changed, 497 insertions(+), 362 deletions(-)
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index f5c5b8d..77241e2 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -40,6 +40,147 @@
#undef DEBUG
+enum {
+ GCR1 = 0, GSCR, GRST, HW_ID,
+ PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
+ PCHD_ID, CAPS1_0_U, CAPS1_0_L, CAPS1_1_U,
+ CAPS1_1_L, CAPS1_2, CAPS1_3, CAPS1_4,
+ PCH2_SR, PCH0_SR, PCH1_SR, PCHD_SR,
+
+ OMAP1_CH_COMMON_START,
+
+ /* Common Registers */
+ CSDP1, CCR1, CICR1, CSR1,
+ CEN1, CFN1, CSFI1, CSEI1,
+ CPC, CSAC1, CDAC1, CDEI1,
+ CDFI1, CLNK_CTRL1,
+
+ /* Channel specific register offsets */
+ CSSA_L, CSSA_U, CDSA_L, CDSA_U,
+ COLOR_L, COLOR_U, CCR1_2, LCH_CTRL,
+
+ OMAP1_CH_COMMON_END,
+};
+
+static u16 reg_map_omap1[] = {
+ [GCR1] = 0x400,
+ [GSCR] = 0x404,
+ [GRST] = 0x408,
+ [HW_ID] = 0x442,
+ [PCH2_ID] = 0x444,
+ [PCH0_ID] = 0x446,
+ [PCH1_ID] = 0x448,
+ [PCHG_ID] = 0x44a,
+ [PCHD_ID] = 0x44c,
+ [CAPS1_0_U] = 0x44e,
+ [CAPS1_0_L] = 0x450,
+ [CAPS1_1_U] = 0x452,
+ [CAPS1_1_L] = 0x454,
+ [CAPS1_2] = 0x456,
+ [CAPS1_3] = 0x458,
+ [CAPS1_4] = 0x45a,
+ [PCH2_SR] = 0x460,
+ [PCH0_SR] = 0x480,
+ [PCH1_SR] = 0x482,
+ [PCHD_SR] = 0x4c0,
+
+ /* Common Registers */
+ [CSDP1] = 0x00,
+ [CCR1] = 0x02,
+ [CICR1] = 0x04,
+ [CSR1] = 0x06,
+ [CEN1] = 0x10,
+ [CFN1] = 0x12,
+ [CSFI1] = 0x14,
+ [CSEI1] = 0x16,
+ [CPC] = 0x18, /* 15xx only */
+ [CSAC1] = 0x18,
+ [CDAC1] = 0x1a,
+ [CDEI1] = 0x1c,
+ [CDFI1] = 0x1e,
+ [CLNK_CTRL1] = 0x28,
+
+ /* Channel specific register offsets */
+ [CSSA_L] = 0x08,
+ [CSSA_U] = 0x0a,
+ [CDSA_L] = 0x0c,
+ [CDSA_U] = 0x0e,
+ [COLOR_L] = 0x20,
+ [COLOR_U] = 0x22,
+ [CCR1_2] = 0x24,
+ [LCH_CTRL] = 0x2a,
+};
+
+enum {
+ REVISION = 0, GCR2, IRQSTATUS_L0, IRQSTATUS_L1,
+ IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0, IRQENABLE_L1,
+ IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS, OCP_SYSCONFIG,
+ CAPS2_0, CAPS2_2, CAPS2_3, CAPS2_4,
+
+ OMAP2_CH_COMMON_START,
+
+ /* Common register offsets */
+ CCR2, CLNK_CTRL2, CICR2, CSR2,
+ CSDP2, CEN2, CFN2, CSEI2,
+ CSFI2, CDEI2, CDFI2, CSAC2,
+ CDAC2,
+
+ /* Channel specific register offsets */
+ CSSA, CDSA, CCEN, CCFN,
+ COLOR,
+
+ /* OMAP4 specific registers */
+ CDP, CNDP, CCDN,
+
+ OMAP2_CH_COMMON_END,
+};
+
+static u16 reg_map_omap2[] = {
+ [REVISION] = 0x00,
+ [GCR2] = 0x78,
+ [IRQSTATUS_L0] = 0x08,
+ [IRQSTATUS_L1] = 0x0c,
+ [IRQSTATUS_L2] = 0x10,
+ [IRQSTATUS_L3] = 0x14,
+ [IRQENABLE_L0] = 0x18,
+ [IRQENABLE_L1] = 0x1c,
+ [IRQENABLE_L2] = 0x20,
+ [IRQENABLE_L3] = 0x24,
+ [SYSSTATUS] = 0x28,
+ [OCP_SYSCONFIG] = 0x2c,
+ [CAPS2_0] = 0x64,
+ [CAPS2_2] = 0x6c,
+ [CAPS2_3] = 0x70,
+ [CAPS2_4] = 0x74,
+
+ /* Common register offsets */
+ [CCR2] = 0x80,
+ [CLNK_CTRL2] = 0x84,
+ [CICR2] = 0x88,
+ [CSR2] = 0x8c,
+ [CSDP2] = 0x90,
+ [CEN2] = 0x94,
+ [CFN2] = 0x98,
+ [CSEI2] = 0xa4,
+ [CSFI2] = 0xa8,
+ [CDEI2] = 0xac,
+ [CDFI2] = 0xb0,
+ [CSAC2] = 0xb4,
+ [CDAC2] = 0xb8,
+
+ /* Channel specific register offsets */
+ [CSSA] = 0x9c,
+ [CDSA] = 0xa0,
+ [CCEN] = 0xbc,
+ [CCFN] = 0xc0,
+ [COLOR] = 0xc4,
+
+ /* OMAP4 specific registers */
+ [CDP] = 0xd0,
+ [CNDP] = 0xd4,
+ [CCDN] = 0xd8,
+};
+
#ifndef CONFIG_ARCH_OMAP1
enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
@@ -137,7 +278,7 @@ 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 void __iomem *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,
@@ -154,23 +295,42 @@ static inline void omap_enable_channel_irq(int lch);
#define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \
__func__);
-#define dma_read(reg) \
-({ \
- u32 __val; \
- if (cpu_class_is_omap1()) \
- __val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg); \
- else \
- __val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg); \
- __val; \
-})
-
-#define dma_write(val, reg) \
-({ \
- if (cpu_class_is_omap1()) \
- __raw_writew((u16)(val), omap_dma_base + OMAP1_DMA_##reg); \
- else \
- __raw_writel((val), omap_dma_base + OMAP_DMA4_##reg); \
-})
+static inline void dma_write(u32 val, int reg, int lch)
+{
+ if (cpu_class_is_omap1()) {
+ if (reg > OMAP1_CH_COMMON_START)
+ __raw_writew(val, dma_base +
+ (reg_map_omap1[reg] + 0x40 * lch));
+ else
+ __raw_writew(val, dma_base + reg_map_omap1[reg]);
+ } else {
+ if (reg > OMAP2_CH_COMMON_START)
+ __raw_writel(val, dma_base +
+ (reg_map_omap2[reg] + 0x60 * lch));
+ else
+ __raw_writel(val, dma_base + reg_map_omap2[reg]);
+ }
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+ u32 val;
+
+ if (cpu_class_is_omap1()) {
+ if (reg > OMAP1_CH_COMMON_START)
+ val = __raw_readw(dma_base +
+ (reg_map_omap1[reg] + 0x40 * lch));
+ else
+ val = __raw_readw(dma_base + reg_map_omap1[reg]);
+ } else {
+ if (reg > OMAP2_CH_COMMON_START)
+ val = __raw_readl(dma_base +
+ (reg_map_omap2[reg] + 0x60 * lch));
+ else
+ val = __raw_readl(dma_base + reg_map_omap2[reg]);
+ }
+ return val;
+}
#ifdef CONFIG_ARCH_OMAP15XX
/* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
@@ -209,11 +369,10 @@ static inline void set_gdma_dev(int req, int dev)
/* Omap1 only */
static void clear_lch_regs(int lch)
{
- int i;
- void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch);
+ int i = OMAP1_CH_COMMON_START;
- for (i = 0; i < 0x2c; i += 2)
- __raw_writew(0, lch_base + i);
+ for (; i <= OMAP1_CH_COMMON_END; i += 1)
+ dma_write(0, i, lch);
}
void omap_set_dma_priority(int lch, int dst_port, int priority)
@@ -248,12 +407,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
if (cpu_class_is_omap2()) {
u32 ccr;
- ccr = dma_read(CCR(lch));
+ ccr = dma_read(CCR2, lch);
if (priority)
ccr |= (1 << 6);
else
ccr &= ~(1 << 6);
- dma_write(ccr, CCR(lch));
+ dma_write(ccr, CCR2, lch);
}
}
EXPORT_SYMBOL(omap_set_dma_priority);
@@ -264,31 +423,36 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
{
u32 l;
- l = dma_read(CSDP(lch));
- l &= ~0x03;
- l |= data_type;
- dma_write(l, CSDP(lch));
-
if (cpu_class_is_omap1()) {
u16 ccr;
- ccr = dma_read(CCR(lch));
+ l = dma_read(CSDP1, lch);
+ l &= ~0x03;
+ l |= data_type;
+ dma_write(l, CSDP1, lch);
+
+ ccr = dma_read(CCR1, lch);
ccr &= ~(1 << 5);
if (sync_mode == OMAP_DMA_SYNC_FRAME)
ccr |= 1 << 5;
- dma_write(ccr, CCR(lch));
+ dma_write(ccr, CCR1, lch);
- ccr = dma_read(CCR2(lch));
+ ccr = dma_read(CCR1_2, lch);
ccr &= ~(1 << 2);
if (sync_mode == OMAP_DMA_SYNC_BLOCK)
ccr |= 1 << 2;
- dma_write(ccr, CCR2(lch));
+ dma_write(ccr, CCR1_2, lch);
}
if (cpu_class_is_omap2() && dma_trigger) {
u32 val;
- val = dma_read(CCR(lch));
+ l = dma_read(CSDP2, lch);
+ l &= ~0x03;
+ l |= data_type;
+ dma_write(l, CSDP2, lch);
+
+ val = dma_read(CCR2, lch);
/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
val &= ~((1 << 23) | (3 << 19) | 0x1f);
@@ -313,11 +477,15 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
} else {
val &= ~(1 << 24); /* dest synch */
}
- dma_write(val, CCR(lch));
+ dma_write(val, CCR2, lch);
+ }
+ if (cpu_class_is_omap1()) {
+ dma_write(elem_count, CEN1, lch);
+ dma_write(frame_count, CFN1, lch);
+ } else {
+ dma_write(elem_count, CEN2, lch);
+ dma_write(frame_count, CFN2, lch);
}
-
- dma_write(elem_count, CEN(lch));
- dma_write(frame_count, CFN(lch));
}
EXPORT_SYMBOL(omap_set_dma_transfer_params);
@@ -328,7 +496,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
if (cpu_class_is_omap1()) {
u16 w;
- w = dma_read(CCR2(lch));
+ w = dma_read(CCR1_2, lch);
w &= ~0x03;
switch (mode) {
@@ -343,23 +511,23 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
default:
BUG();
}
- dma_write(w, CCR2(lch));
+ dma_write(w, CCR1_2, lch);
- w = dma_read(LCH_CTRL(lch));
+ w = dma_read(LCH_CTRL, lch);
w &= ~0x0f;
/* Default is channel type 2D */
if (mode) {
- dma_write((u16)color, COLOR_L(lch));
- dma_write((u16)(color >> 16), COLOR_U(lch));
+ dma_write((u16)color, COLOR_L, lch);
+ dma_write((u16)(color >> 16), COLOR_U, lch);
w |= 1; /* Channel type G */
}
- dma_write(w, LCH_CTRL(lch));
+ dma_write(w, LCH_CTRL, lch);
}
if (cpu_class_is_omap2()) {
u32 val;
- val = dma_read(CCR(lch));
+ val = dma_read(CCR2, lch);
val &= ~((1 << 17) | (1 << 16));
switch (mode) {
@@ -374,10 +542,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
default:
BUG();
}
- dma_write(val, CCR(lch));
+ dma_write(val, CCR2, lch);
color &= 0xffffff;
- dma_write(color, COLOR(lch));
+ dma_write(color, COLOR, lch);
}
}
EXPORT_SYMBOL(omap_set_dma_color_mode);
@@ -387,10 +555,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
if (cpu_class_is_omap2()) {
u32 csdp;
- csdp = dma_read(CSDP(lch));
+ csdp = dma_read(CSDP2, lch);
csdp &= ~(0x3 << 16);
csdp |= (mode << 16);
- dma_write(csdp, CSDP(lch));
+ dma_write(csdp, CSDP2, lch);
}
}
EXPORT_SYMBOL(omap_set_dma_write_mode);
@@ -400,10 +568,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
u32 l;
- l = dma_read(LCH_CTRL(lch));
+ l = dma_read(LCH_CTRL, lch);
l &= ~0x7;
l |= mode;
- dma_write(l, LCH_CTRL(lch));
+ dma_write(l, LCH_CTRL, lch);
}
}
EXPORT_SYMBOL(omap_set_dma_channel_mode);
@@ -418,27 +586,38 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
if (cpu_class_is_omap1()) {
u16 w;
- w = dma_read(CSDP(lch));
+ w = dma_read(CSDP1, lch);
w &= ~(0x1f << 2);
w |= src_port << 2;
- dma_write(w, CSDP(lch));
- }
+ dma_write(w, CSDP1, lch);
+
+ l = dma_read(CCR1, lch);
+ } else
+ l = dma_read(CCR2, lch);
- l = dma_read(CCR(lch));
l &= ~(0x03 << 12);
l |= src_amode << 12;
- dma_write(l, CCR(lch));
+
+ if (cpu_class_is_omap1())
+ dma_write(l, CCR1, lch);
+ else
+ dma_write(l, CCR2, lch);
if (cpu_class_is_omap1()) {
- dma_write(src_start >> 16, CSSA_U(lch));
- dma_write((u16)src_start, CSSA_L(lch));
+ dma_write(src_start >> 16, CSSA_U, lch);
+ dma_write((u16)src_start, CSSA_L, lch);
}
if (cpu_class_is_omap2())
- dma_write(src_start, CSSA(lch));
+ dma_write(src_start, CSSA, lch);
- dma_write(src_ei, CSEI(lch));
- dma_write(src_fi, CSFI(lch));
+ if (cpu_class_is_omap1()) {
+ dma_write(src_ei, CSEI1, lch);
+ dma_write(src_fi, CSFI1, lch);
+ } else {
+ dma_write(src_ei, CSEI2, lch);
+ dma_write(src_fi, CSFI2, lch);
+ }
}
EXPORT_SYMBOL(omap_set_dma_src_params);
@@ -466,8 +645,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx)
if (cpu_class_is_omap2())
return;
- dma_write(eidx, CSEI(lch));
- dma_write(fidx, CSFI(lch));
+ dma_write(eidx, CSEI1, lch);
+ dma_write(fidx, CSFI1, lch);
}
EXPORT_SYMBOL(omap_set_dma_src_index);
@@ -475,11 +654,19 @@ void omap_set_dma_src_data_pack(int lch, int enable)
{
u32 l;
- l = dma_read(CSDP(lch));
+ if (cpu_class_is_omap1())
+ l = dma_read(CSDP1, lch);
+ else
+ l = dma_read(CSDP2, lch);
+
l &= ~(1 << 6);
if (enable)
l |= (1 << 6);
- dma_write(l, CSDP(lch));
+
+ if (cpu_class_is_omap1())
+ dma_write(l, CSDP1, lch);
+ else
+ dma_write(l, CSDP2, lch);
}
EXPORT_SYMBOL(omap_set_dma_src_data_pack);
@@ -488,7 +675,11 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
unsigned int burst = 0;
u32 l;
- l = dma_read(CSDP(lch));
+ if (cpu_class_is_omap2())
+ l = dma_read(CSDP2, lch);
+ else
+ l = dma_read(CSDP1, lch);
+
l &= ~(0x03 << 7);
switch (burst_mode) {
@@ -524,7 +715,11 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
}
l |= (burst << 7);
- dma_write(l, CSDP(lch));
+
+ if (cpu_class_is_omap2())
+ dma_write(l, CSDP2, lch);
+ else
+ dma_write(l, CSDP1, lch);
}
EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
@@ -536,27 +731,38 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
u32 l;
if (cpu_class_is_omap1()) {
- l = dma_read(CSDP(lch));
+ l = dma_read(CSDP1, lch);
l &= ~(0x1f << 9);
l |= dest_port << 9;
- dma_write(l, CSDP(lch));
- }
+ dma_write(l, CSDP1, lch);
+
+ l = dma_read(CCR1, lch);
+ } else
+ l = dma_read(CCR2, lch);
- l = dma_read(CCR(lch));
l &= ~(0x03 << 14);
l |= dest_amode << 14;
- dma_write(l, CCR(lch));
+
+ if (cpu_class_is_omap1())
+ dma_write(l, CCR1, lch);
+ else
+ dma_write(l, CCR2, lch);
if (cpu_class_is_omap1()) {
- dma_write(dest_start >> 16, CDSA_U(lch));
- dma_write(dest_start, CDSA_L(lch));
+ dma_write(dest_start >> 16, CDSA_U, lch);
+ dma_write(dest_start, CDSA_L, lch);
}
if (cpu_class_is_omap2())
- dma_write(dest_start, CDSA(lch));
+ dma_write(dest_start, CDSA, lch);
- dma_write(dst_ei, CDEI(lch));
- dma_write(dst_fi, CDFI(lch));
+ if (cpu_class_is_omap1()) {
+ dma_write(dst_ei, CDEI1, lch);
+ dma_write(dst_fi, CDFI1, lch);
+ } else {
+ dma_write(dst_ei, CDEI2, lch);
+ dma_write(dst_fi, CDFI2, lch);
+ }
}
EXPORT_SYMBOL(omap_set_dma_dest_params);
@@ -565,8 +771,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx)
if (cpu_class_is_omap2())
return;
- dma_write(eidx, CDEI(lch));
- dma_write(fidx, CDFI(lch));
+ dma_write(eidx, CDEI1, lch);
+ dma_write(fidx, CDFI1, lch);
}
EXPORT_SYMBOL(omap_set_dma_dest_index);
@@ -574,11 +780,19 @@ void omap_set_dma_dest_data_pack(int lch, int enable)
{
u32 l;
- l = dma_read(CSDP(lch));
+ if (cpu_class_is_omap2())
+ l = dma_read(CSDP2, lch);
+ else
+ l = dma_read(CSDP1, lch);
+
l &= ~(1 << 13);
if (enable)
l |= 1 << 13;
- dma_write(l, CSDP(lch));
+
+ if (cpu_class_is_omap2())
+ dma_write(l, CSDP2, lch);
+ else
+ dma_write(l, CSDP1, lch);
}
EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
@@ -586,8 +800,11 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
{
unsigned int burst = 0;
u32 l;
+ if (cpu_class_is_omap2())
+ l = dma_read(CSDP2, lch);
+ else
+ l = dma_read(CSDP1, lch);
- l = dma_read(CSDP(lch));
l &= ~(0x03 << 14);
switch (burst_mode) {
@@ -619,8 +836,13 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
BUG();
return;
}
+
l |= (burst << 14);
- dma_write(l, CSDP(lch));
+
+ if (cpu_class_is_omap2())
+ dma_write(l, CSDP2, lch);
+ else
+ dma_write(l, CSDP1, lch);
}
EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
@@ -629,19 +851,21 @@ 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));
+ if (cpu_class_is_omap1()) {
+ status = dma_read(CSR1, lch);
+ dma_write(dma_chan[lch].enabled_irqs, CICR1, lch);
+ } else if (cpu_class_is_omap2()) {
+ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR2, lch);
+ dma_write(dma_chan[lch].enabled_irqs, CICR2, lch);
+ }
}
static void omap_disable_channel_irq(int lch)
{
if (cpu_class_is_omap2())
- dma_write(0, CICR(lch));
+ dma_write(0, CICR2, lch);
+ else
+ dma_write(0, CICR1, lch);
}
void omap_enable_dma_irq(int lch, u16 bits)
@@ -660,44 +884,44 @@ static inline void enable_lnk(int lch)
{
u32 l;
- l = dma_read(CLNK_CTRL(lch));
-
- if (cpu_class_is_omap1())
+ if (cpu_class_is_omap1()) {
+ l = dma_read(CLNK_CTRL1, lch);
l &= ~(1 << 14);
+ } else
+ l = dma_read(CLNK_CTRL2, lch);
/* 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 (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));
+ dma_write(l, CLNK_CTRL2, lch);
+ } else
+ dma_write(l, CLNK_CTRL1, 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));
+ l = dma_read(CLNK_CTRL1, lch);
+ dma_write(0, CICR1, lch);
/* Set the STOP_LNK bit */
l |= 1 << 14;
+ dma_write(l, CLNK_CTRL1, lch);
}
if (cpu_class_is_omap2()) {
+ l = dma_read(CLNK_CTRL2, lch);
omap_disable_channel_irq(lch);
/* Clear the ENABLE_LNK bit */
l &= ~(1 << 15);
+ dma_write(l, CLNK_CTRL2, lch);
}
-
- dma_write(l, CLNK_CTRL(lch));
dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
}
@@ -710,9 +934,9 @@ static inline void omap2_enable_irq_lch(int lch)
return;
spin_lock_irqsave(&dma_chan_lock, flags);
- val = dma_read(IRQENABLE_L0);
+ val = dma_read(IRQENABLE_L0, 0);
val |= 1 << lch;
- dma_write(val, IRQENABLE_L0);
+ dma_write(val, IRQENABLE_L0, 0);
spin_unlock_irqrestore(&dma_chan_lock, flags);
}
@@ -725,9 +949,9 @@ static inline void omap2_disable_irq_lch(int lch)
return;
spin_lock_irqsave(&dma_chan_lock, flags);
- val = dma_read(IRQENABLE_L0);
+ val = dma_read(IRQENABLE_L0, 0);
val &= ~(1 << lch);
- dma_write(val, IRQENABLE_L0);
+ dma_write(val, IRQENABLE_L0, 0);
spin_unlock_irqrestore(&dma_chan_lock, flags);
}
@@ -792,17 +1016,17 @@ int omap_request_dma(int dev_id, const char *dev_name,
* Disable the 1510 compatibility mode and set the sync device
* id.
*/
- dma_write(dev_id | (1 << 10), CCR(free_ch));
+ dma_write(dev_id | (1 << 10), CCR1, free_ch);
} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
- dma_write(dev_id, CCR(free_ch));
+ dma_write(dev_id, CCR1, free_ch);
}
if (cpu_class_is_omap2()) {
omap2_enable_irq_lch(free_ch);
omap_enable_channel_irq(free_ch);
/* Clear the CSR register and IRQ status register */
- dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch));
- dma_write(1 << free_ch, IRQSTATUS_L0);
+ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR2, free_ch);
+ dma_write(1 << free_ch, IRQSTATUS_L0, 0);
}
*dma_ch_out = free_ch;
@@ -823,23 +1047,23 @@ void omap_free_dma(int lch)
if (cpu_class_is_omap1()) {
/* Disable all DMA interrupts for the channel. */
- dma_write(0, CICR(lch));
+ dma_write(0, CICR1, lch);
/* Make sure the DMA transfer is stopped. */
- dma_write(0, CCR(lch));
+ dma_write(0, CCR1, lch);
}
if (cpu_class_is_omap2()) {
omap2_disable_irq_lch(lch);
/* Clear the CSR register and IRQ status register */
- dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));
- dma_write(1 << lch, IRQSTATUS_L0);
+ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR2, lch);
+ dma_write(1 << lch, IRQSTATUS_L0, 0);
/* Disable all DMA interrupts for the channel. */
- dma_write(0, CICR(lch));
+ dma_write(0, CICR2, lch);
/* Make sure the DMA transfer is stopped. */
- dma_write(0, CCR(lch));
+ dma_write(0, CCR2, lch);
omap_clear_dma(lch);
}
@@ -880,7 +1104,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
reg |= (0x3 & tparams) << 12;
reg |= (arb_rate & 0xff) << 16;
- dma_write(reg, GCR);
+ dma_write(reg, GCR2, 0);
}
EXPORT_SYMBOL(omap_dma_set_global_params);
@@ -903,14 +1127,18 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
printk(KERN_ERR "Invalid channel id\n");
return -EINVAL;
}
- l = dma_read(CCR(lch));
- l &= ~((1 << 6) | (1 << 26));
- if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx())
+
+ if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ l = dma_read(CCR2, lch);
+ l &= ~((1 << 6) | (1 << 26));
l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
- else
+ dma_write(l, CCR2, lch);
+ } else {
+ l = dma_read(CCR1, lch);
+ l &= ~((1 << 6) | (1 << 26));
l |= ((read_prio & 0x1) << 6);
-
- dma_write(l, CCR(lch));
+ dma_write(l, CCR1, lch);
+ }
return 0;
}
@@ -929,19 +1157,19 @@ void omap_clear_dma(int lch)
if (cpu_class_is_omap1()) {
u32 l;
- l = dma_read(CCR(lch));
+ l = dma_read(CCR1, lch);
l &= ~OMAP_DMA_CCR_EN;
- dma_write(l, CCR(lch));
+ dma_write(l, CCR1, lch);
/* Clear pending interrupts */
- l = dma_read(CSR(lch));
+ l = dma_read(CSR1, lch);
}
if (cpu_class_is_omap2()) {
- int i;
- void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch);
- for (i = 0; i < 0x44; i += 4)
- __raw_writel(0, lch_base + i);
+ int i = OMAP2_CH_COMMON_START;
+
+ for (; i <= OMAP2_CH_COMMON_END; i++)
+ dma_write(0, i, lch);
}
local_irq_restore(flags);
@@ -957,9 +1185,12 @@ void omap_start_dma(int lch)
* before starting dma transfer.
*/
if (cpu_is_omap15xx())
- dma_write(0, CPC(lch));
+ dma_write(0, CPC, lch);
+ else if (cpu_class_is_omap1())
+ dma_write(0, CDAC1, lch);
else
- dma_write(0, CDAC(lch));
+ dma_write(0, CDAC2, lch);
+
if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
int next_lch, cur_lch;
@@ -989,29 +1220,33 @@ void omap_start_dma(int lch)
(cpu_is_omap243x() && omap_type() <= OMAP2430_REV_ES1_0)) {
/* Errata: Need to write lch even if not using chaining */
- dma_write(lch, CLNK_CTRL(lch));
+ dma_write(lch, CLNK_CTRL2, lch);
}
omap_enable_channel_irq(lch);
- l = dma_read(CCR(lch));
-
- /*
- * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
- * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and
- * bursting is enabled. This might result in data gets stalled in
- * FIFO at the end of the block.
- * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
- * guarantee no data will stay in the DMA FIFO in case inter frame
- * buffering occurs.
- */
- if (cpu_is_omap2420() ||
- (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0)))
- l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
-
- l |= OMAP_DMA_CCR_EN;
- dma_write(l, CCR(lch));
+ if (cpu_class_is_omap1()) {
+ l = dma_read(CCR1, lch);
+ l |= OMAP_DMA_CCR_EN;
+ dma_write(l, CCR1, lch);
+ } else {
+ l = dma_read(CCR2, lch);
+ /*
+ * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
+ * OMAP2430ES1.0): DMA will wrongly buffer elements if packing
+ * and bursting is enabled. This might result in data gets
+ * stalled in FIFO@the end of the block.
+ * Workaround: DMA channels must have BUFFERING_DISABLED bit
+ * set to guarantee no data will stay in the DMA FIFO in case
+ * inter frame buffering occurs.
+ */
+ if (cpu_is_omap2420() || (cpu_is_omap2430() &&
+ (omap_type() == OMAP2430_REV_ES1_0)))
+ l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
+ l |= OMAP_DMA_CCR_EN;
+ dma_write(l, CCR2, lch);
+ }
dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
}
EXPORT_SYMBOL(omap_start_dma);
@@ -1022,41 +1257,45 @@ void omap_stop_dma(int lch)
/* Disable all interrupts on the channel */
if (cpu_class_is_omap1())
- dma_write(0, CICR(lch));
+ dma_write(0, CICR1, lch);
- l = dma_read(CCR(lch));
/* OMAP3 Errata i541: sDMA FIFO draining does not finish */
if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
int i = 0;
u32 sys_cf;
/* Configure No-Standby */
- l = dma_read(OCP_SYSCONFIG);
+ l = dma_read(OCP_SYSCONFIG, 0);
sys_cf = l;
l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
- dma_write(l , OCP_SYSCONFIG);
+ dma_write(l , OCP_SYSCONFIG, 0);
- l = dma_read(CCR(lch));
+ l = dma_read(CCR2, lch);
l &= ~OMAP_DMA_CCR_EN;
- dma_write(l, CCR(lch));
+ dma_write(l, CCR2, lch);
/* Wait for sDMA FIFO drain */
- l = dma_read(CCR(lch));
+ l = dma_read(CCR2, lch);
while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
OMAP_DMA_CCR_WR_ACTIVE))) {
udelay(5);
i++;
- l = dma_read(CCR(lch));
+ l = dma_read(CCR2, lch);
}
if (i >= 100)
printk(KERN_ERR "DMA drain did not complete on "
"lch %d\n", lch);
/* Restore OCP_SYSCONFIG */
- dma_write(sys_cf, OCP_SYSCONFIG);
+ dma_write(sys_cf, OCP_SYSCONFIG, 0);
+ } else if (cpu_class_is_omap1()) {
+ l = dma_read(CCR1, lch);
+ l &= ~OMAP_DMA_CCR_EN;
+ dma_write(l, CCR1, lch);
} else {
+ l = dma_read(CCR2, lch);
l &= ~OMAP_DMA_CCR_EN;
- dma_write(l, CCR(lch));
+ dma_write(l, CCR2, lch);
}
if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
@@ -1122,19 +1361,25 @@ dma_addr_t omap_get_dma_src_pos(int lch)
dma_addr_t offset = 0;
if (cpu_is_omap15xx())
- offset = dma_read(CPC(lch));
+ offset = dma_read(CPC, lch);
+ else if (cpu_class_is_omap1())
+ offset = dma_read(CSAC1, lch);
else
- offset = dma_read(CSAC(lch));
+ offset = dma_read(CSAC2, lch);
/*
* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
* read before the DMA controller finished disabling the channel.
*/
- if (!cpu_is_omap15xx() && offset == 0)
- offset = dma_read(CSAC(lch));
+ if (!cpu_is_omap15xx() && offset == 0) {
+ if (cpu_class_is_omap1())
+ offset = dma_read(CSAC1, lch);
+ else
+ offset = dma_read(CSAC2, lch);
+ }
if (cpu_class_is_omap1())
- offset |= (dma_read(CSSA_U(lch)) << 16);
+ offset |= (dma_read(CSSA_U, lch) << 16);
return offset;
}
@@ -1153,19 +1398,25 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
dma_addr_t offset = 0;
if (cpu_is_omap15xx())
- offset = dma_read(CPC(lch));
+ offset = dma_read(CPC, lch);
+ else if (cpu_class_is_omap1())
+ offset = dma_read(CDAC1, lch);
else
- offset = dma_read(CDAC(lch));
+ offset = dma_read(CDAC2, lch);
/*
* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
* read before the DMA controller finished disabling the channel.
*/
- if (!cpu_is_omap15xx() && offset == 0)
- offset = dma_read(CDAC(lch));
+ if (!cpu_is_omap15xx() && offset == 0) {
+ if (cpu_class_is_omap1())
+ offset = dma_read(CDAC1, lch);
+ else
+ offset = dma_read(CDAC2, lch);
+ }
if (cpu_class_is_omap1())
- offset |= (dma_read(CDSA_U(lch)) << 16);
+ offset |= (dma_read(CDSA_U, lch) << 16);
return offset;
}
@@ -1173,7 +1424,10 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos);
int omap_get_dma_active_status(int lch)
{
- return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0;
+ if (cpu_class_is_omap1())
+ return (dma_read(CCR1, lch) & OMAP_DMA_CCR_EN) != 0;
+ else
+ return (dma_read(CCR2, lch) & OMAP_DMA_CCR_EN) != 0;
}
EXPORT_SYMBOL(omap_get_dma_active_status);
@@ -1181,14 +1435,15 @@ int omap_dma_running(void)
{
int lch;
- if (cpu_class_is_omap1())
- if (omap_lcd_dma_running())
- return 1;
-
- for (lch = 0; lch < dma_chan_count; lch++)
- if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN)
- return 1;
-
+ for (lch = 0; lch < dma_chan_count; lch++) {
+ if (cpu_class_is_omap1()) {
+ if (dma_read(CCR1, lch) & OMAP_DMA_CCR_EN)
+ return 1;
+ } else {
+ if (dma_read(CCR2, lch) & OMAP_DMA_CCR_EN)
+ return 1;
+ }
+ }
return 0;
}
@@ -1201,8 +1456,8 @@ void omap_dma_link_lch(int lch_head, int lch_queue)
{
if (omap_dma_in_1510_mode()) {
if (lch_head == lch_queue) {
- dma_write(dma_read(CCR(lch_head)) | (3 << 8),
- CCR(lch_head));
+ dma_write(dma_read(CCR1, lch_head) | (3 << 8),
+ CCR1, lch_head);
return;
}
printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1228,8 +1483,8 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
{
if (omap_dma_in_1510_mode()) {
if (lch_head == lch_queue) {
- dma_write(dma_read(CCR(lch_head)) & ~(3 << 8),
- CCR(lch_head));
+ dma_write(dma_read(CCR1, lch_head) & ~(3 << 8),
+ CCR1, lch_head);
return;
}
printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1281,15 +1536,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue)
lch_queue;
}
- l = dma_read(CLNK_CTRL(lch_head));
+ l = dma_read(CLNK_CTRL2, lch_head);
l &= ~(0x1f);
l |= lch_queue;
- dma_write(l, CLNK_CTRL(lch_head));
+ dma_write(l, CLNK_CTRL2, lch_head);
- l = dma_read(CLNK_CTRL(lch_queue));
+ l = dma_read(CLNK_CTRL2, lch_queue);
l &= ~(0x1f);
l |= (dma_chan[lch_queue].next_linked_ch);
- dma_write(l, CLNK_CTRL(lch_queue));
+ dma_write(l, CLNK_CTRL2, lch_queue);
}
/**
@@ -1565,13 +1820,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
/* Set the params to the free channel */
if (src_start != 0)
- dma_write(src_start, CSSA(lch));
+ dma_write(src_start, CSSA, lch);
if (dest_start != 0)
- dma_write(dest_start, CDSA(lch));
+ dma_write(dest_start, CDSA, lch);
/* Write the buffer size */
- dma_write(elem_count, CEN(lch));
- dma_write(frame_count, CFN(lch));
+ dma_write(elem_count, CEN2, lch);
+ dma_write(frame_count, CFN2, lch);
/*
* If the chain is dynamically linked,
@@ -1605,7 +1860,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
dma_chan[lch].state = DMA_CH_QUEUED;
start_dma = 0;
if (0 == ((1 << 7) & dma_read(
- CCR(dma_chan[lch].prev_linked_ch)))) {
+ CCR2, dma_chan[lch].prev_linked_ch))) {
disable_lnk(dma_chan[lch].
prev_linked_ch);
pr_debug("\n prev ch is stopped\n");
@@ -1621,7 +1876,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
}
omap_enable_channel_irq(lch);
- l = dma_read(CCR(lch));
+ l = dma_read(CCR2, lch);
if ((0 == (l & (1 << 24))))
l &= ~(1 << 25);
@@ -1632,12 +1887,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
l |= (1 << 7);
dma_chan[lch].state = DMA_CH_STARTED;
pr_debug("starting %d\n", lch);
- dma_write(l, CCR(lch));
+ dma_write(l, CCR2, lch);
} else
start_dma = 0;
} else {
if (0 == (l & (1 << 7)))
- dma_write(l, CCR(lch));
+ dma_write(l, CCR2, lch);
}
dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
}
@@ -1682,7 +1937,7 @@ int omap_start_dma_chain_transfers(int chain_id)
omap_enable_channel_irq(channels[0]);
}
- l = dma_read(CCR(channels[0]));
+ l = dma_read(CCR2, channels[0]);
l |= (1 << 7);
dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
dma_chan[channels[0]].state = DMA_CH_STARTED;
@@ -1691,7 +1946,7 @@ int omap_start_dma_chain_transfers(int chain_id)
l &= ~(1 << 25);
else
l |= (1 << 25);
- dma_write(l, CCR(channels[0]));
+ dma_write(l, CCR2, channels[0]);
dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
@@ -1730,18 +1985,18 @@ int omap_stop_dma_chain_transfers(int chain_id)
* DMA Errata:
* Special programming model needed to disable DMA before end of block
*/
- sys_cf = dma_read(OCP_SYSCONFIG);
+ sys_cf = dma_read(OCP_SYSCONFIG, 0);
l = sys_cf;
/* Middle mode reg set no Standby */
l &= ~((1 << 12)|(1 << 13));
- dma_write(l, OCP_SYSCONFIG);
+ dma_write(l, OCP_SYSCONFIG, 0);
for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
/* Stop the Channel transmission */
- l = dma_read(CCR(channels[i]));
+ l = dma_read(CCR2, channels[i]);
l &= ~(1 << 7);
- dma_write(l, CCR(channels[i]));
+ dma_write(l, CCR2, channels[i]);
/* Disable the link in all the channels */
disable_lnk(channels[i]);
@@ -1754,7 +2009,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
OMAP_DMA_CHAIN_QINIT(chain_id);
/* Errata - put in the old value */
- dma_write(sys_cf, OCP_SYSCONFIG);
+ dma_write(sys_cf, OCP_SYSCONFIG, 0);
return 0;
}
@@ -1796,8 +2051,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
/* Get the current channel */
lch = channels[dma_linked_lch[chain_id].q_head];
- *ei = dma_read(CCEN(lch));
- *fi = dma_read(CCFN(lch));
+ *ei = dma_read(CCEN, lch);
+ *fi = dma_read(CCFN, lch);
return 0;
}
@@ -1834,7 +2089,7 @@ int omap_get_dma_chain_dst_pos(int chain_id)
/* Get the current channel */
lch = channels[dma_linked_lch[chain_id].q_head];
- return dma_read(CDAC(lch));
+ return dma_read(CDAC2, lch);
}
EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
@@ -1868,7 +2123,7 @@ int omap_get_dma_chain_src_pos(int chain_id)
/* Get the current channel */
lch = channels[dma_linked_lch[chain_id].q_head];
- return dma_read(CSAC(lch));
+ return dma_read(CSAC2, lch);
}
EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
#endif /* ifndef CONFIG_ARCH_OMAP1 */
@@ -1885,7 +2140,7 @@ static int omap1_dma_handle_ch(int ch)
csr = dma_chan[ch].saved_csr;
dma_chan[ch].saved_csr = 0;
} else
- csr = dma_read(CSR(ch));
+ csr = dma_read(CSR1, ch);
if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
dma_chan[ch + 6].saved_csr = csr >> 7;
csr &= 0x7f;
@@ -1938,13 +2193,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
static int omap2_dma_handle_ch(int ch)
{
- u32 status = dma_read(CSR(ch));
+ u32 status = dma_read(CSR2, ch);
if (!status) {
if (printk_ratelimit())
printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
ch);
- dma_write(1 << ch, IRQSTATUS_L0);
+ dma_write(1 << ch, IRQSTATUS_L0, 0);
return 0;
}
if (unlikely(dma_chan[ch].dev_id == -1)) {
@@ -1968,9 +2223,9 @@ static int omap2_dma_handle_ch(int ch)
*/
u32 ccr;
- ccr = dma_read(CCR(ch));
+ ccr = dma_read(CCR2, ch);
ccr &= ~OMAP_DMA_CCR_EN;
- dma_write(ccr, CCR(ch));
+ dma_write(ccr, CCR2, ch);
dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
}
}
@@ -1981,14 +2236,14 @@ static int omap2_dma_handle_ch(int ch)
printk(KERN_INFO "DMA misaligned error with device %d\n",
dma_chan[ch].dev_id);
- dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch));
- dma_write(1 << ch, IRQSTATUS_L0);
+ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR2, ch);
+ dma_write(1 << ch, IRQSTATUS_L0, 0);
/* If the ch is not chained then chain_id will be -1 */
if (dma_chan[ch].chain_id != -1) {
int chain_id = dma_chan[ch].chain_id;
dma_chan[ch].state = DMA_CH_NOTSTARTED;
- if (dma_read(CLNK_CTRL(ch)) & (1 << 15))
+ if (dma_read(CLNK_CTRL2, ch) & (1 << 15))
dma_chan[dma_chan[ch].next_linked_ch].state =
DMA_CH_STARTED;
if (dma_linked_lch[chain_id].chain_mode ==
@@ -1998,10 +2253,10 @@ static int omap2_dma_handle_ch(int ch)
if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
OMAP_DMA_CHAIN_INCQHEAD(chain_id);
- status = dma_read(CSR(ch));
+ status = dma_read(CSR2, ch);
}
- dma_write(status, CSR(ch));
+ dma_write(status, CSR2, ch);
if (likely(dma_chan[ch].callback != NULL))
dma_chan[ch].callback(ch, status, dma_chan[ch].data);
@@ -2015,13 +2270,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
u32 val, enable_reg;
int i;
- val = dma_read(IRQSTATUS_L0);
+ val = dma_read(IRQSTATUS_L0, 0);
if (val == 0) {
if (printk_ratelimit())
printk(KERN_WARNING "Spurious DMA IRQ\n");
return IRQ_HANDLED;
}
- enable_reg = dma_read(IRQENABLE_L0);
+ enable_reg = dma_read(IRQENABLE_L0, 0);
val &= enable_reg; /* Dispatch only relevant interrupts */
for (i = 0; i < dma_lch_count && val != 0; i++) {
if (val & 1)
@@ -2047,21 +2302,21 @@ static struct irqaction omap24xx_dma_irq;
void omap_dma_global_context_save(void)
{
omap_dma_global_context.dma_irqenable_l0 =
- dma_read(IRQENABLE_L0);
+ dma_read(IRQENABLE_L0, 0);
omap_dma_global_context.dma_ocp_sysconfig =
- dma_read(OCP_SYSCONFIG);
- omap_dma_global_context.dma_gcr = dma_read(GCR);
+ dma_read(OCP_SYSCONFIG, 0);
+ omap_dma_global_context.dma_gcr = dma_read(GCR2, 0);
}
void omap_dma_global_context_restore(void)
{
int ch;
- dma_write(omap_dma_global_context.dma_gcr, GCR);
+ dma_write(omap_dma_global_context.dma_gcr, GCR2, 0);
dma_write(omap_dma_global_context.dma_ocp_sysconfig,
- OCP_SYSCONFIG);
+ OCP_SYSCONFIG, 0);
dma_write(omap_dma_global_context.dma_irqenable_l0,
- IRQENABLE_L0);
+ IRQENABLE_L0, 0);
/*
* A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
@@ -2070,7 +2325,7 @@ void omap_dma_global_context_restore(void)
* affects only secure devices.
*/
if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
- dma_write(0x3 , IRQSTATUS_L0);
+ dma_write(0x3 , IRQSTATUS_L0, 0);
for (ch = 0; ch < dma_chan_count; ch++)
if (dma_chan[ch].dev_id != -1)
@@ -2101,8 +2356,8 @@ static int __init omap_init_dma(void)
return -ENODEV;
}
- omap_dma_base = ioremap(base, SZ_4K);
- BUG_ON(!omap_dma_base);
+ dma_base = ioremap(base, SZ_4K);
+ BUG_ON(!dma_base);
if (cpu_class_is_omap2() && omap_dma_reserve_channels
&& (omap_dma_reserve_channels <= dma_lch_count))
@@ -2130,26 +2385,26 @@ static int __init omap_init_dma(void)
enable_1510_mode = 1;
} else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
printk(KERN_INFO "OMAP DMA hardware version %d\n",
- dma_read(HW_ID));
+ dma_read(HW_ID, 0));
printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
- (dma_read(CAPS_0_U) << 16) |
- dma_read(CAPS_0_L),
- (dma_read(CAPS_1_U) << 16) |
- dma_read(CAPS_1_L),
- dma_read(CAPS_2), dma_read(CAPS_3),
- dma_read(CAPS_4));
+ (dma_read(CAPS1_0_U, 0) << 16) |
+ dma_read(CAPS1_0_L, 0),
+ (dma_read(CAPS1_1_U, 0) << 16) |
+ dma_read(CAPS1_1_L, 0),
+ dma_read(CAPS1_2, 0), dma_read(CAPS1_3, 0),
+ dma_read(CAPS1_4, 0));
if (!enable_1510_mode) {
u16 w;
/* Disable OMAP 3.0/3.1 compatibility mode. */
- w = dma_read(GSCR);
+ w = dma_read(GSCR, 0);
w |= 1 << 3;
- dma_write(w, GSCR);
+ dma_write(w, GSCR, 0);
dma_chan_count = 16;
} else
dma_chan_count = 9;
} else if (cpu_class_is_omap2()) {
- u8 revision = dma_read(REVISION) & 0xff;
+ u8 revision = dma_read(REVISION, 0) & 0xff;
printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
revision >> 4, revision & 0xf);
dma_chan_count = dma_lch_count;
@@ -2208,14 +2463,14 @@ static int __init omap_init_dma(void)
if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
/* Enable smartidle idlemodes and autoidle */
- u32 v = dma_read(OCP_SYSCONFIG);
+ u32 v = dma_read(OCP_SYSCONFIG, 0);
v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
DMA_SYSCONFIG_SIDLEMODE_MASK |
DMA_SYSCONFIG_AUTOIDLE);
v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
DMA_SYSCONFIG_AUTOIDLE);
- dma_write(v , OCP_SYSCONFIG);
+ dma_write(v , OCP_SYSCONFIG, 0);
/* reserve dma channels 0 and 1 in high security devices */
if (cpu_is_omap34xx() &&
(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
@@ -2232,7 +2487,7 @@ out_free:
kfree(dma_chan);
out_unmap:
- iounmap(omap_dma_base);
+ iounmap(dma_base);
return r;
}
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 0cce4ca..27578f3 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -27,134 +27,14 @@
/* Hardware registers for omap1 */
#define OMAP1_DMA_BASE (0xfffed800)
-#define OMAP1_DMA_GCR 0x400
-#define OMAP1_DMA_GSCR 0x404
-#define OMAP1_DMA_GRST 0x408
-#define OMAP1_DMA_HW_ID 0x442
-#define OMAP1_DMA_PCH2_ID 0x444
-#define OMAP1_DMA_PCH0_ID 0x446
-#define OMAP1_DMA_PCH1_ID 0x448
-#define OMAP1_DMA_PCHG_ID 0x44a
-#define OMAP1_DMA_PCHD_ID 0x44c
-#define OMAP1_DMA_CAPS_0_U 0x44e
-#define OMAP1_DMA_CAPS_0_L 0x450
-#define OMAP1_DMA_CAPS_1_U 0x452
-#define OMAP1_DMA_CAPS_1_L 0x454
-#define OMAP1_DMA_CAPS_2 0x456
-#define OMAP1_DMA_CAPS_3 0x458
-#define OMAP1_DMA_CAPS_4 0x45a
-#define OMAP1_DMA_PCH2_SR 0x460
-#define OMAP1_DMA_PCH0_SR 0x480
-#define OMAP1_DMA_PCH1_SR 0x482
-#define OMAP1_DMA_PCHD_SR 0x4c0
-
/* Hardware registers for omap2 and omap3 */
#define OMAP24XX_DMA4_BASE (L4_24XX_BASE + 0x56000)
#define OMAP34XX_DMA4_BASE (L4_34XX_BASE + 0x56000)
#define OMAP44XX_DMA4_BASE (L4_44XX_BASE + 0x56000)
-#define OMAP_DMA4_REVISION 0x00
-#define OMAP_DMA4_GCR 0x78
-#define OMAP_DMA4_IRQSTATUS_L0 0x08
-#define OMAP_DMA4_IRQSTATUS_L1 0x0c
-#define OMAP_DMA4_IRQSTATUS_L2 0x10
-#define OMAP_DMA4_IRQSTATUS_L3 0x14
-#define OMAP_DMA4_IRQENABLE_L0 0x18
-#define OMAP_DMA4_IRQENABLE_L1 0x1c
-#define OMAP_DMA4_IRQENABLE_L2 0x20
-#define OMAP_DMA4_IRQENABLE_L3 0x24
-#define OMAP_DMA4_SYSSTATUS 0x28
-#define OMAP_DMA4_OCP_SYSCONFIG 0x2c
-#define OMAP_DMA4_CAPS_0 0x64
-#define OMAP_DMA4_CAPS_2 0x6c
-#define OMAP_DMA4_CAPS_3 0x70
-#define OMAP_DMA4_CAPS_4 0x74
-
#define OMAP1_LOGICAL_DMA_CH_COUNT 17
#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */
-/* Common channel specific registers for omap1 */
-#define OMAP1_DMA_CH_BASE(n) (0x40 * (n) + 0x00)
-#define OMAP1_DMA_CSDP(n) (0x40 * (n) + 0x00)
-#define OMAP1_DMA_CCR(n) (0x40 * (n) + 0x02)
-#define OMAP1_DMA_CICR(n) (0x40 * (n) + 0x04)
-#define OMAP1_DMA_CSR(n) (0x40 * (n) + 0x06)
-#define OMAP1_DMA_CEN(n) (0x40 * (n) + 0x10)
-#define OMAP1_DMA_CFN(n) (0x40 * (n) + 0x12)
-#define OMAP1_DMA_CSFI(n) (0x40 * (n) + 0x14)
-#define OMAP1_DMA_CSEI(n) (0x40 * (n) + 0x16)
-#define OMAP1_DMA_CPC(n) (0x40 * (n) + 0x18) /* 15xx only */
-#define OMAP1_DMA_CSAC(n) (0x40 * (n) + 0x18)
-#define OMAP1_DMA_CDAC(n) (0x40 * (n) + 0x1a)
-#define OMAP1_DMA_CDEI(n) (0x40 * (n) + 0x1c)
-#define OMAP1_DMA_CDFI(n) (0x40 * (n) + 0x1e)
-#define OMAP1_DMA_CLNK_CTRL(n) (0x40 * (n) + 0x28)
-
-/* Common channel specific registers for omap2 */
-#define OMAP_DMA4_CH_BASE(n) (0x60 * (n) + 0x80)
-#define OMAP_DMA4_CCR(n) (0x60 * (n) + 0x80)
-#define OMAP_DMA4_CLNK_CTRL(n) (0x60 * (n) + 0x84)
-#define OMAP_DMA4_CICR(n) (0x60 * (n) + 0x88)
-#define OMAP_DMA4_CSR(n) (0x60 * (n) + 0x8c)
-#define OMAP_DMA4_CSDP(n) (0x60 * (n) + 0x90)
-#define OMAP_DMA4_CEN(n) (0x60 * (n) + 0x94)
-#define OMAP_DMA4_CFN(n) (0x60 * (n) + 0x98)
-#define OMAP_DMA4_CSEI(n) (0x60 * (n) + 0xa4)
-#define OMAP_DMA4_CSFI(n) (0x60 * (n) + 0xa8)
-#define OMAP_DMA4_CDEI(n) (0x60 * (n) + 0xac)
-#define OMAP_DMA4_CDFI(n) (0x60 * (n) + 0xb0)
-#define OMAP_DMA4_CSAC(n) (0x60 * (n) + 0xb4)
-#define OMAP_DMA4_CDAC(n) (0x60 * (n) + 0xb8)
-
-/* Channel specific registers only on omap1 */
-#define OMAP1_DMA_CSSA_L(n) (0x40 * (n) + 0x08)
-#define OMAP1_DMA_CSSA_U(n) (0x40 * (n) + 0x0a)
-#define OMAP1_DMA_CDSA_L(n) (0x40 * (n) + 0x0c)
-#define OMAP1_DMA_CDSA_U(n) (0x40 * (n) + 0x0e)
-#define OMAP1_DMA_COLOR_L(n) (0x40 * (n) + 0x20)
-#define OMAP1_DMA_COLOR_U(n) (0x40 * (n) + 0x22)
-#define OMAP1_DMA_CCR2(n) (0x40 * (n) + 0x24)
-#define OMAP1_DMA_LCH_CTRL(n) (0x40 * (n) + 0x2a) /* not on 15xx */
-#define OMAP1_DMA_CCEN(n) 0
-#define OMAP1_DMA_CCFN(n) 0
-
-/* Channel specific registers only on omap2 */
-#define OMAP_DMA4_CSSA(n) (0x60 * (n) + 0x9c)
-#define OMAP_DMA4_CDSA(n) (0x60 * (n) + 0xa0)
-#define OMAP_DMA4_CCEN(n) (0x60 * (n) + 0xbc)
-#define OMAP_DMA4_CCFN(n) (0x60 * (n) + 0xc0)
-#define OMAP_DMA4_COLOR(n) (0x60 * (n) + 0xc4)
-
-/* Additional registers available on OMAP4 */
-#define OMAP_DMA4_CDP(n) (0x60 * (n) + 0xd0)
-#define OMAP_DMA4_CNDP(n) (0x60 * (n) + 0xd4)
-#define OMAP_DMA4_CCDN(n) (0x60 * (n) + 0xd8)
-
-/* Dummy defines to keep multi-omap compiles happy */
-#define OMAP1_DMA_REVISION 0
-#define OMAP1_DMA_IRQSTATUS_L0 0
-#define OMAP1_DMA_IRQENABLE_L0 0
-#define OMAP1_DMA_OCP_SYSCONFIG 0
-#define OMAP_DMA4_HW_ID 0
-#define OMAP_DMA4_CAPS_0_L 0
-#define OMAP_DMA4_CAPS_0_U 0
-#define OMAP_DMA4_CAPS_1_L 0
-#define OMAP_DMA4_CAPS_1_U 0
-#define OMAP_DMA4_GSCR 0
-#define OMAP_DMA4_CPC(n) 0
-
-#define OMAP_DMA4_LCH_CTRL(n) 0
-#define OMAP_DMA4_COLOR_L(n) 0
-#define OMAP_DMA4_COLOR_U(n) 0
-#define OMAP_DMA4_CCR2(n) 0
-#define OMAP1_DMA_CSSA(n) 0
-#define OMAP1_DMA_CDSA(n) 0
-#define OMAP_DMA4_CSSA_L(n) 0
-#define OMAP_DMA4_CSSA_U(n) 0
-#define OMAP_DMA4_CDSA_L(n) 0
-#define OMAP_DMA4_CDSA_U(n) 0
-#define OMAP1_DMA_COLOR(n) 0
-
/*----------------------------------------------------------------------------*/
/* DMA channels for omap1 */
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-10-26 13:25 ` [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions G, Manjunath Kondaiah
@ 2010-10-26 14:48 ` Nishanth Menon
2010-10-27 3:54 ` G, Manjunath Kondaiah
2010-11-09 21:37 ` Kevin Hilman
1 sibling, 1 reply; 50+ messages in thread
From: Nishanth Menon @ 2010-10-26 14:48 UTC (permalink / raw)
To: linux-arm-kernel
G, Manjunath Kondaiah had written, on 10/26/2010 08:25 AM, the following:
[...]
>
> diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
> index f5c5b8d..77241e2 100644
> --- a/arch/arm/plat-omap/dma.c
> +++ b/arch/arm/plat-omap/dma.c
> @@ -40,6 +40,147 @@
>
> #undef DEBUG
>
> +enum {
> + GCR1 = 0, GSCR, GRST, HW_ID,
> + PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
> + PCHD_ID, CAPS1_0_U, CAPS1_0_L, CAPS1_1_U,
> + CAPS1_1_L, CAPS1_2, CAPS1_3, CAPS1_4,
> + PCH2_SR, PCH0_SR, PCH1_SR, PCHD_SR,
[...]
> +};
> +
> +static u16 reg_map_omap1[] = {
> + [GCR1] = 0x400,
> + [GSCR] = 0x404,
> + [GRST] = 0x408,
> + [HW_ID] = 0x442,
> + [PCH2_ID] = 0x444,
> + [PCH0_ID] = 0x446,
> + [PCH1_ID] = 0x448,
> + [PCHG_ID] = 0x44a,
> + [PCHD_ID] = 0x44c,
[...]
> + [LCH_CTRL] = 0x2a,
> +};
> +
> +enum {
> + REVISION = 0, GCR2, IRQSTATUS_L0, IRQSTATUS_L1,
> + IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0, IRQENABLE_L1,
[...]
> +
> + /* OMAP4 specific registers */
> + CDP, CNDP, CCDN,
> +
> + OMAP2_CH_COMMON_END,
> +};
> +
> +static u16 reg_map_omap2[] = {
> + [REVISION] = 0x00,
> + [GCR2] = 0x78,
> + [IRQSTATUS_L0] = 0x08,
> + [IRQSTATUS_L1] = 0x0c,
[..]
> + /* OMAP4 specific registers */
> + [CDP] = 0xd0,
> + [CNDP] = 0xd4,
> + [CCDN] = 0xd8,
> +};
> +
dumb question: any reason why a struct wont do?
struct reg_map_omap2 {
u16 revision;
...
...
}
[..]
>
> -#define dma_read(reg) \
> -({ \
> - u32 __val; \
> - if (cpu_class_is_omap1()) \
> - __val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg); \
> - else \
> - __val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg); \
> - __val; \
> -})
> -
> -#define dma_write(val, reg) \
> -({ \
> - if (cpu_class_is_omap1()) \
> - __raw_writew((u16)(val), omap_dma_base + OMAP1_DMA_##reg); \
> - else \
> - __raw_writel((val), omap_dma_base + OMAP_DMA4_##reg); \
> -})
> +static inline void dma_write(u32 val, int reg, int lch)
> +{
> + if (cpu_class_is_omap1()) {
> + if (reg > OMAP1_CH_COMMON_START)
> + __raw_writew(val, dma_base +
> + (reg_map_omap1[reg] + 0x40 * lch));
> + else
> + __raw_writew(val, dma_base + reg_map_omap1[reg]);
> + } else {
> + if (reg > OMAP2_CH_COMMON_START)
> + __raw_writel(val, dma_base +
> + (reg_map_omap2[reg] + 0x60 * lch));
> + else
> + __raw_writel(val, dma_base + reg_map_omap2[reg]);
> + }
> +}
> +
> +static inline u32 dma_read(int reg, int lch)
> +{
> + u32 val;
> +
> + if (cpu_class_is_omap1()) {
> + if (reg > OMAP1_CH_COMMON_START)
> + val = __raw_readw(dma_base +
> + (reg_map_omap1[reg] + 0x40 * lch));
> + else
> + val = __raw_readw(dma_base + reg_map_omap1[reg]);
> + } else {
> + if (reg > OMAP2_CH_COMMON_START)
> + val = __raw_readl(dma_base +
> + (reg_map_omap2[reg] + 0x60 * lch));
> + else
> + val = __raw_readl(dma_base + reg_map_omap2[reg]);
> + }
> + return val;
> +}
What is the benefit of using inline function here? would'nt we increase
code size? cant we use a function pointer initialized to class1 or rest?
Quote from CodingStyle (15):
"A reasonable rule of thumb is to not put inline at functions that have more
than 3 lines of code in them. An exception to this rule are the cases where
a parameter is known to be a compiletime constant, and as a result of this
constantness you *know* the compiler will be able to optimize most of your
function away at compile time. For a good example of this later case, see
the kmalloc() inline function.
"
is the expectation that cpu_class_is_omap1 compile time constant hence
the actual compiled in code is smaller -candidate for inline?
>
> #ifdef CONFIG_ARCH_OMAP15XX
> /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
> @@ -209,11 +369,10 @@ static inline void set_gdma_dev(int req, int dev)
> /* Omap1 only */
> static void clear_lch_regs(int lch)
> {
> - int i;
> - void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch);
> + int i = OMAP1_CH_COMMON_START;
>
> - for (i = 0; i < 0x2c; i += 2)
> - __raw_writew(0, lch_base + i);
> + for (; i <= OMAP1_CH_COMMON_END; i += 1)
> + dma_write(0, i, lch);
> }
>
> void omap_set_dma_priority(int lch, int dst_port, int priority)
> @@ -248,12 +407,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
> if (cpu_class_is_omap2()) {
> u32 ccr;
>
> - ccr = dma_read(CCR(lch));
> + ccr = dma_read(CCR2, lch);
> if (priority)
> ccr |= (1 << 6);
> else
> ccr &= ~(1 << 6);
> - dma_write(ccr, CCR(lch));
> + dma_write(ccr, CCR2, lch);
> }
> }
> EXPORT_SYMBOL(omap_set_dma_priority);
> @@ -264,31 +423,36 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
> {
> u32 l;
>
> - l = dma_read(CSDP(lch));
> - l &= ~0x03;
> - l |= data_type;
> - dma_write(l, CSDP(lch));
> -
> if (cpu_class_is_omap1()) {
> u16 ccr;
>
> - ccr = dma_read(CCR(lch));
> + l = dma_read(CSDP1, lch);
> + l &= ~0x03;
> + l |= data_type;
> + dma_write(l, CSDP1, lch);
> +
> + ccr = dma_read(CCR1, lch);
> ccr &= ~(1 << 5);
> if (sync_mode == OMAP_DMA_SYNC_FRAME)
> ccr |= 1 << 5;
> - dma_write(ccr, CCR(lch));
> + dma_write(ccr, CCR1, lch);
>
> - ccr = dma_read(CCR2(lch));
> + ccr = dma_read(CCR1_2, lch);
> ccr &= ~(1 << 2);
> if (sync_mode == OMAP_DMA_SYNC_BLOCK)
> ccr |= 1 << 2;
> - dma_write(ccr, CCR2(lch));
> + dma_write(ccr, CCR1_2, lch);
> }
>
> if (cpu_class_is_omap2() && dma_trigger) {
> u32 val;
>
> - val = dma_read(CCR(lch));
> + l = dma_read(CSDP2, lch);
> + l &= ~0x03;
> + l |= data_type;
> + dma_write(l, CSDP2, lch);
This seems to me to be a replication mess :( compared to the original
CSDP(lch) - which mapped to class1 or class2 as needed - same elsewhere.
Code is becoming pretty much needing a refactoring as a result :(
[...]
--
Regards,
Nishanth Menon
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-10-26 14:48 ` Nishanth Menon
@ 2010-10-27 3:54 ` G, Manjunath Kondaiah
2010-10-27 14:26 ` Menon, Nishanth
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-27 3:54 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Menon, Nishanth
> Sent: Tuesday, October 26, 2010 8:19 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit; Kevin
> Hilman; Shilimkar, Santosh
> Subject: Re: [PATCH v3 01/13] OMAP: DMA: Replace read/write
> macros with functions
>
> G, Manjunath Kondaiah had written, on 10/26/2010 08:25 AM,
> the following:
> [...]
> >
> > diff --git a/arch/arm/plat-omap/dma.c
> b/arch/arm/plat-omap/dma.c index
> > f5c5b8d..77241e2 100644
> > --- a/arch/arm/plat-omap/dma.c
> > +++ b/arch/arm/plat-omap/dma.c
> > @@ -40,6 +40,147 @@
> >
[...]
> > +static u16 reg_map_omap2[] = {
> > + [REVISION] = 0x00,
> > + [GCR2] = 0x78,
> > + [IRQSTATUS_L0] = 0x08,
> > + [IRQSTATUS_L1] = 0x0c,
> [..]
> > + /* OMAP4 specific registers */
> > + [CDP] = 0xd0,
> > + [CNDP] = 0xd4,
> > + [CCDN] = 0xd8,
> > +};
> > +
> dumb question: any reason why a struct wont do?
> struct reg_map_omap2 {
> u16 revision;
> ...
> ...
> }
This approach is as per i2c driver as suggested by kevin.
http://www.spinics.net/lists/linux-omap/msg36446.html
>
> [..]
> >
> > -#define dma_read(reg)
> \
> > -({
> \
> > - u32 __val;
> \
> > - if (cpu_class_is_omap1())
> \
> > - __val = __raw_readw(omap_dma_base +
> OMAP1_DMA_##reg); \
> > - else
> \
> > - __val = __raw_readl(omap_dma_base +
> OMAP_DMA4_##reg); \
> > - __val;
> \
> > -})
> > -
> > -#define dma_write(val, reg)
> \
> > -({
> \
> > - if (cpu_class_is_omap1())
> \
> > - __raw_writew((u16)(val), omap_dma_base +
> OMAP1_DMA_##reg); \
> > - else
> \
> > - __raw_writel((val), omap_dma_base +
> OMAP_DMA4_##reg); \
> > -})
> > +static inline void dma_write(u32 val, int reg, int lch) {
> > + if (cpu_class_is_omap1()) {
> > + if (reg > OMAP1_CH_COMMON_START)
> > + __raw_writew(val, dma_base +
> > + (reg_map_omap1[reg] + 0x40 * lch));
> > + else
> > + __raw_writew(val, dma_base +
> reg_map_omap1[reg]);
> > + } else {
> > + if (reg > OMAP2_CH_COMMON_START)
> > + __raw_writel(val, dma_base +
> > + (reg_map_omap2[reg] + 0x60 * lch));
> > + else
> > + __raw_writel(val, dma_base +
> reg_map_omap2[reg]);
> > + }
> > +}
> > +
> > +static inline u32 dma_read(int reg, int lch) {
> > + u32 val;
> > +
> > + if (cpu_class_is_omap1()) {
> > + if (reg > OMAP1_CH_COMMON_START)
> > + val = __raw_readw(dma_base +
> > + (reg_map_omap1[reg]
> + 0x40 * lch));
> > + else
> > + val = __raw_readw(dma_base +
> reg_map_omap1[reg]);
> > + } else {
> > + if (reg > OMAP2_CH_COMMON_START)
> > + val = __raw_readl(dma_base +
> > + (reg_map_omap2[reg]
> + 0x60 * lch));
> > + else
> > + val = __raw_readl(dma_base +
> reg_map_omap2[reg]);
> > + }
> > + return val;
> > +}
> What is the benefit of using inline function here? would'nt
> we increase code size? cant we use a function pointer
> initialized to class1 or rest?
> Quote from CodingStyle (15):
> "A reasonable rule of thumb is to not put inline at functions
> that have more than 3 lines of code in them. An exception to
> this rule are the cases where a parameter is known to be a
> compiletime constant, and as a result of this constantness
> you *know* the compiler will be able to optimize most of your
> function away at compile time. For a good example of this
> later case, see the kmalloc() inline function.
> "
> is the expectation that cpu_class_is_omap1 compile time
> constant hence the actual compiled in code is smaller
> -candidate for inline?
Detailed discussion and alignment can be found at:
http://www.spinics.net/lists/linux-omap/thrd6.html
Search for:
[PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
>
> >
> > #ifdef CONFIG_ARCH_OMAP15XX
> > /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0
> > if (cpu_class_is_omap1()) {
[...]
> > u16 ccr;
> >
> > - ccr = dma_read(CCR(lch));
> > + l = dma_read(CSDP1, lch);
> > + l &= ~0x03;
> > + l |= data_type;
> > + dma_write(l, CSDP1, lch);
> > +
> > + ccr = dma_read(CCR1, lch);
> > ccr &= ~(1 << 5);
> > if (sync_mode == OMAP_DMA_SYNC_FRAME)
> > ccr |= 1 << 5;
> > - dma_write(ccr, CCR(lch));
> > + dma_write(ccr, CCR1, lch);
> >
> > - ccr = dma_read(CCR2(lch));
> > + ccr = dma_read(CCR1_2, lch);
> > ccr &= ~(1 << 2);
> > if (sync_mode == OMAP_DMA_SYNC_BLOCK)
> > ccr |= 1 << 2;
> > - dma_write(ccr, CCR2(lch));
> > + dma_write(ccr, CCR1_2, lch);
> > }
> >
> > if (cpu_class_is_omap2() && dma_trigger) {
> > u32 val;
> >
> > - val = dma_read(CCR(lch));
> > + l = dma_read(CSDP2, lch);
> > + l &= ~0x03;
> > + l |= data_type;
> > + dma_write(l, CSDP2, lch);
> This seems to me to be a replication mess :( compared to the original
> CSDP(lch) - which mapped to class1 or class2 as needed - same
> elsewhere.
> Code is becoming pretty much needing a refactoring as a result :(
>
> [...]
This is interim patch towards hwmod and driver cleanup. As mentioned in the
patch description, objective is to replace lowlevel read/write macros with
inline functions. For few registers(between omap1 and omap2+), the offset is
different. Earlier, this offset difference was handled through macros.
Now, it is replaced with inline functions, the code should be seperated for
handling between omap1 and omap2+. It will get cleaned up once the code is
moved respective mach-omapx directories.
You can have look at: PATCH 11/13
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-10-27 3:54 ` G, Manjunath Kondaiah
@ 2010-10-27 14:26 ` Menon, Nishanth
2010-10-29 8:15 ` G, Manjunath Kondaiah
0 siblings, 1 reply; 50+ messages in thread
From: Menon, Nishanth @ 2010-10-27 14:26 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: G, Manjunath Kondaiah
> Sent: Tuesday, October 26, 2010 10:55 PM
[..]
> > [...]
> > >
> > > diff --git a/arch/arm/plat-omap/dma.c
> > b/arch/arm/plat-omap/dma.c index
> > > f5c5b8d..77241e2 100644
> > > --- a/arch/arm/plat-omap/dma.c
> > > +++ b/arch/arm/plat-omap/dma.c
> > > @@ -40,6 +40,147 @@
> > >
> [...]
> > > +static u16 reg_map_omap2[] = {
> > > + [REVISION] = 0x00,
> > > + [GCR2] = 0x78,
> > > + [IRQSTATUS_L0] = 0x08,
> > > + [IRQSTATUS_L1] = 0x0c,
> > [..]
> > > + /* OMAP4 specific registers */
> > > + [CDP] = 0xd0,
> > > + [CNDP] = 0xd4,
> > > + [CCDN] = 0xd8,
> > > +};
> > > +
> > dumb question: any reason why a struct wont do?
> > struct reg_map_omap2 {
> > u16 revision;
> > ...
> > ...
> > }
>
> This approach is as per i2c driver as suggested by kevin.
> http://www.spinics.net/lists/linux-omap/msg36446.html
Thanks for pointing this out. I2c has what 18 registers while dma has over 40 registers :( patch 11 [1] now I understand this step -> this merges
together at later patchset - it starts to make sense now. It becomes reg_map. Thanks - looks like a good change in the eventual code.
[...]
> > > +static inline void dma_write(u32 val, int reg, int lch) {
> > > + if (cpu_class_is_omap1()) {
> > > + if (reg > OMAP1_CH_COMMON_START)
> > > + __raw_writew(val, dma_base +
> > > + (reg_map_omap1[reg] + 0x40 * lch));
> > > + else
> > > + __raw_writew(val, dma_base +
> > reg_map_omap1[reg]);
> > > + } else {
> > > + if (reg > OMAP2_CH_COMMON_START)
> > > + __raw_writel(val, dma_base +
> > > + (reg_map_omap2[reg] + 0x60 * lch));
> > > + else
> > > + __raw_writel(val, dma_base +
> > reg_map_omap2[reg]);
> > > + }
> > > +}
Eventual code looks like this:
62 static inline void dma_write(u32 val, int reg, int lch)
63 {
64 if (d->dev_caps & IS_WORD_16) {
65 if (reg >= CH_COMMON_START)
66 __raw_writew(val, dma_base +
67 (reg_map[reg] + 0x40 * lch));
68 else
69 __raw_writew(val, dma_base + reg_map[reg]);
70 } else {
71 if (reg > CH_COMMON_START)
72 __raw_writel(val, dma_base +
73 (reg_map[reg] + 0x60 * lch));
74 else
75 __raw_writel(val, dma_base + reg_map[reg]);
76 }
77 }
I don't really see how inline will really help here!
> > > +
> > > +static inline u32 dma_read(int reg, int lch) {
> > > + u32 val;
> > > +
> > > + if (cpu_class_is_omap1()) {
> > > + if (reg > OMAP1_CH_COMMON_START)
> > > + val = __raw_readw(dma_base +
> > > + (reg_map_omap1[reg]
> > + 0x40 * lch));
> > > + else
> > > + val = __raw_readw(dma_base +
> > reg_map_omap1[reg]);
> > > + } else {
> > > + if (reg > OMAP2_CH_COMMON_START)
> > > + val = __raw_readl(dma_base +
> > > + (reg_map_omap2[reg]
> > + 0x60 * lch));
> > > + else
> > > + val = __raw_readl(dma_base +
> > reg_map_omap2[reg]);
> > > + }
> > > + return val;
> > > +}
> > What is the benefit of using inline function here? would'nt
> > we increase code size? cant we use a function pointer
> > initialized to class1 or rest?
> > Quote from CodingStyle (15):
> > "A reasonable rule of thumb is to not put inline at functions
> > that have more than 3 lines of code in them. An exception to
> > this rule are the cases where a parameter is known to be a
> > compiletime constant, and as a result of this constantness
> > you *know* the compiler will be able to optimize most of your
> > function away at compile time. For a good example of this
> > later case, see the kmalloc() inline function.
> > "
> > is the expectation that cpu_class_is_omap1 compile time
> > constant hence the actual compiled in code is smaller
> > -candidate for inline?
>
> Detailed discussion and alignment can be found at:
> http://www.spinics.net/lists/linux-omap/thrd6.html
Better link:
http://marc.info/?t=128264802300006&r=1&w=2
>
> Search for:
> [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
http://marc.info/?l=linux-omap&m=128464661906497&w=2
my question is slightly different here - debate of suggestion to use inline
is based on the size of code involved, the discussion in the thread
discussed around 3 lines of code, which made sense, unfortunately, the
thread does not answer my question unfortunately for *this* specific patch
- OR do you wish to point me to some specific link which answers this?
>
>
> >
> > >
> > > #ifdef CONFIG_ARCH_OMAP15XX
> > > /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0
> > > if (cpu_class_is_omap1()) {
> [...]
> > > u16 ccr;
> > >
> > > - ccr = dma_read(CCR(lch));
> > > + l = dma_read(CSDP1, lch);
> > > + l &= ~0x03;
> > > + l |= data_type;
> > > + dma_write(l, CSDP1, lch);
> > > +
> > > + ccr = dma_read(CCR1, lch);
> > > ccr &= ~(1 << 5);
> > > if (sync_mode == OMAP_DMA_SYNC_FRAME)
> > > ccr |= 1 << 5;
> > > - dma_write(ccr, CCR(lch));
> > > + dma_write(ccr, CCR1, lch);
> > >
> > > - ccr = dma_read(CCR2(lch));
> > > + ccr = dma_read(CCR1_2, lch);
> > > ccr &= ~(1 << 2);
> > > if (sync_mode == OMAP_DMA_SYNC_BLOCK)
> > > ccr |= 1 << 2;
> > > - dma_write(ccr, CCR2(lch));
> > > + dma_write(ccr, CCR1_2, lch);
> > > }
> > >
> > > if (cpu_class_is_omap2() && dma_trigger) {
> > > u32 val;
> > >
> > > - val = dma_read(CCR(lch));
> > > + l = dma_read(CSDP2, lch);
> > > + l &= ~0x03;
> > > + l |= data_type;
> > > + dma_write(l, CSDP2, lch);
> > This seems to me to be a replication mess :( compared to the original
> > CSDP(lch) - which mapped to class1 or class2 as needed - same
> > elsewhere.
> > Code is becoming pretty much needing a refactoring as a result :(
> >
> > [...]
>
> This is interim patch towards hwmod and driver cleanup. As mentioned in
> the
> patch description, objective is to replace lowlevel read/write macros with
> inline functions. For few registers(between omap1 and omap2+), the offset
> is
> different. Earlier, this offset difference was handled through macros.
> Now, it is replaced with inline functions, the code should be seperated
> for
> handling between omap1 and omap2+. It will get cleaned up once the code is
> moved respective mach-omapx directories.
>
> You can have look at: PATCH 11/13
Ok looks like it never made to ML :( [1] as you refered to in a later patch
Makes sense to me now. Thanks.
[1] http://dev.omapzoom.org/?p=manju/kernel-omap3-dev.git;a=commitdiff;h=7457a6b4248772aaa52dfb13a170f891596a512a
Regards,
Nishanth Menon
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-10-27 14:26 ` Menon, Nishanth
@ 2010-10-29 8:15 ` G, Manjunath Kondaiah
0 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-29 8:15 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Menon, Nishanth
> Sent: Wednesday, October 27, 2010 7:56 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit; Kevin
> Hilman; Shilimkar, Santosh
> Subject: RE: [PATCH v3 01/13] OMAP: DMA: Replace read/write
> macros with functions
>
[...]
> > This approach is as per i2c driver as suggested by kevin.
> > http://www.spinics.net/lists/linux-omap/msg36446.html
> Thanks for pointing this out. I2c has what 18 registers while
> dma has over 40 registers :( patch 11 [1] now I understand
> this step -> this merges
> together at later patchset - it starts to make sense now. It
> becomes reg_map. Thanks - looks like a good change in the
> eventual code.
>
>
> [...]
> > > > +static inline void dma_write(u32 val, int reg, int lch) {
> > > > + if (cpu_class_is_omap1()) {
> > > > + if (reg > OMAP1_CH_COMMON_START)
> > > > + __raw_writew(val, dma_base +
> > > > + (reg_map_omap1[reg] +
> 0x40 * lch));
> > > > + else
> > > > + __raw_writew(val, dma_base +
> > > reg_map_omap1[reg]);
> > > > + } else {
> > > > + if (reg > OMAP2_CH_COMMON_START)
> > > > + __raw_writel(val, dma_base +
> > > > + (reg_map_omap2[reg] +
> 0x60 * lch));
> > > > + else
> > > > + __raw_writel(val, dma_base +
> > > reg_map_omap2[reg]);
> > > > + }
> > > > +}
> Eventual code looks like this:
>
> 62 static inline void dma_write(u32 val, int reg, int lch)
> 63 {
> 64 if (d->dev_caps & IS_WORD_16) {
> 65 if (reg >= CH_COMMON_START)
> 66 __raw_writew(val, dma_base +
> 67 (reg_map[reg] + 0x40 * lch));
> 68 else
> 69 __raw_writew(val, dma_base + reg_map[reg]);
> 70 } else {
> 71 if (reg > CH_COMMON_START)
> 72 __raw_writel(val, dma_base +
> 73 (reg_map[reg] + 0x60 * lch));
> 74 else
> 75 __raw_writel(val, dma_base + reg_map[reg]);
> 76 }
> 77 }
> I don't really see how inline will really help here!
>
> > > > +
> > > > +static inline u32 dma_read(int reg, int lch) {
> > > > + u32 val;
> > > > +
> > > > + if (cpu_class_is_omap1()) {
> > > > + if (reg > OMAP1_CH_COMMON_START)
> > > > + val = __raw_readw(dma_base +
> > > > + (reg_map_omap1[reg]
> > > + 0x40 * lch));
> > > > + else
> > > > + val = __raw_readw(dma_base +
> > > reg_map_omap1[reg]);
> > > > + } else {
> > > > + if (reg > OMAP2_CH_COMMON_START)
> > > > + val = __raw_readl(dma_base +
> > > > + (reg_map_omap2[reg]
> > > + 0x60 * lch));
> > > > + else
> > > > + val = __raw_readl(dma_base +
> > > reg_map_omap2[reg]);
> > > > + }
> > > > + return val;
> > > > +}
> > > What is the benefit of using inline function here? would'nt
> > > we increase code size? cant we use a function pointer
> > > initialized to class1 or rest?
> > > Quote from CodingStyle (15):
> > > "A reasonable rule of thumb is to not put inline at functions
> > > that have more than 3 lines of code in them. An exception to
> > > this rule are the cases where a parameter is known to be a
> > > compiletime constant, and as a result of this constantness
> > > you *know* the compiler will be able to optimize most of your
> > > function away at compile time. For a good example of this
> > > later case, see the kmalloc() inline function.
> > > "
> > > is the expectation that cpu_class_is_omap1 compile time
> > > constant hence the actual compiled in code is smaller
> > > -candidate for inline?
> >
> > Detailed discussion and alignment can be found at:
> > http://www.spinics.net/lists/linux-omap/thrd6.html
> Better link:
> http://marc.info/?t=128264802300006&r=1&w=2
>
> >
> > Search for:
> > [PATCH v2 07/11] OMAP2/3/4: DMA: HWMOD: Device registration
>
> http://marc.info/?l=linux-omap&m=128464661906497&w=2
> my question is slightly different here - debate of suggestion
> to use inline
> is based on the size of code involved, the discussion in the thread
> discussed around 3 lines of code, which made sense,
> unfortunately, the
> thread does not answer my question unfortunately for *this*
> specific patch
> - OR do you wish to point me to some specific link which answers this?
for plat-omap dma code, these read/write api's can be replaced with function
pointers.
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-10-26 13:25 ` [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions G, Manjunath Kondaiah
2010-10-26 14:48 ` Nishanth Menon
@ 2010-11-09 21:37 ` Kevin Hilman
2010-11-10 14:01 ` G, Manjunath Kondaiah
1 sibling, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 21:37 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> The low level read/write macros are replaced with static inline functions
> and register offsets are handled through static register offset tables
> mapped through enumeration constants.
>
> The objective of this patch is to prepare for omap dma driver cleanup
> and dma hwmod implementation. The code optimization and moving machine
> specific code to respective mach-omapx dma file will be handled in the
> rest of this patch series.
[...]
> -#define dma_write(val, reg) \
> -({ \
> - if (cpu_class_is_omap1()) \
> - __raw_writew((u16)(val), omap_dma_base + OMAP1_DMA_##reg); \
> - else \
> - __raw_writel((val), omap_dma_base + OMAP_DMA4_##reg); \
> -})
> +static inline void dma_write(u32 val, int reg, int lch)
> +{
> + if (cpu_class_is_omap1()) {
Reminder: any use of cpu_is_* checks outside of init code will be NAK'd.
cpu_is_* check do not belong at runtime, especially in a crucial path
like this.
> + if (reg > OMAP1_CH_COMMON_START)
> + __raw_writew(val, dma_base +
> + (reg_map_omap1[reg] + 0x40 * lch));
> + else
> + __raw_writew(val, dma_base + reg_map_omap1[reg]);
> + } else {
> + if (reg > OMAP2_CH_COMMON_START)
> + __raw_writel(val, dma_base +
> + (reg_map_omap2[reg] + 0x60 * lch));
> + else
> + __raw_writel(val, dma_base + reg_map_omap2[reg]);
> + }
> +}
The register base offset, register array and the stride (offset between
instances: 0x40 or 0x60) are detectable at init time, and there's no
reason to have conditional code for them. IOW, they should be init time
constants. Doing so would greatly simply these functions. In fact the
CH_COMMON_START could also be an init time constant as well. So, given
the following init_time constants: dma_ch_common_start, dma_stride,
reg_map, the above would be reduced to something actually worth
inlining, for example (not actually tested):
static inline void dma_write(u32 val, int reg, int lch)
{
u8 stride = (reg > dma_ch_common_start) ? dma_stride : 0;
__raw_writel(val, dma_base + (reg_map[reg] + stride * lch));
}
Same applies to dma_read().
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-11-09 21:37 ` Kevin Hilman
@ 2010-11-10 14:01 ` G, Manjunath Kondaiah
2010-11-10 16:03 ` Kevin Hilman
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 14:01 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 3:08 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Shilimkar, Santosh
> Subject: Re: [PATCH v3 01/13] OMAP: DMA: Replace read/write
> macros with functions
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
> > The low level read/write macros are replaced with static
> inline functions
> > and register offsets are handled through static register
> offset tables
> > mapped through enumeration constants.
> >
> > The objective of this patch is to prepare for omap dma
> driver cleanup
> > and dma hwmod implementation. The code optimization and
> moving machine
> > specific code to respective mach-omapx dma file will be
> handled in the
> > rest of this patch series.
>
> [...]
>
> > -#define dma_write(val, reg)
> \
> > -({
> \
> > - if (cpu_class_is_omap1())
> \
> > - __raw_writew((u16)(val), omap_dma_base +
> OMAP1_DMA_##reg); \
> > - else
> \
> > - __raw_writel((val), omap_dma_base +
> OMAP_DMA4_##reg); \
> > -})
> > +static inline void dma_write(u32 val, int reg, int lch)
> > +{
> > + if (cpu_class_is_omap1()) {
>
> Reminder: any use of cpu_is_* checks outside of init code
> will be NAK'd.
>
> cpu_is_* check do not belong at runtime, especially in a crucial path
> like this.
ok. removed cpu_is_* checks and taken care in init.
>
> > + if (reg > OMAP1_CH_COMMON_START)
> > + __raw_writew(val, dma_base +
> > + (reg_map_omap1[reg] + 0x40 * lch));
> > + else
> > + __raw_writew(val, dma_base +
> reg_map_omap1[reg]);
> > + } else {
> > + if (reg > OMAP2_CH_COMMON_START)
> > + __raw_writel(val, dma_base +
> > + (reg_map_omap2[reg] + 0x60 * lch));
> > + else
> > + __raw_writel(val, dma_base +
> reg_map_omap2[reg]);
> > + }
> > +}
>
> The register base offset, register array and the stride
> (offset between
> instances: 0x40 or 0x60) are detectable at init time, and there's no
> reason to have conditional code for them. IOW, they should
> be init time
> constants. Doing so would greatly simply these functions.
> In fact the
> CH_COMMON_START could also be an init time constant as well.
> So, given
> the following init_time constants: dma_ch_common_start, dma_stride,
> reg_map, the above would be reduced to something actually worth
> inlining, for example (not actually tested):
>
> static inline void dma_write(u32 val, int reg, int lch)
> {
> u8 stride = (reg > dma_ch_common_start) ? dma_stride : 0;
>
> __raw_writel(val, dma_base + (reg_map[reg] + stride * lch));
> }
>
> Same applies to dma_read().
Thanks for the suggestion. It is taken care along with Tony's comment
for handling these read/write's between omap1 and omap2+.
Here is code snippet for handling both omap1(includes 16 bit
registers) and omap2+
static inline void dma_write(u32 val, int reg, int lch)
{
u8 stride;
u32 offset;
stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
offset = reg_map[reg] + (stride * lch);
if (dma_stride == 0x40) {
__raw_writew(val, omap_dma_base + offset);
if ((reg > CLNK_CTRL && reg < CCR2) ||
(reg > PCHD_ID && reg < CAPS_2)) {
u32 offset2 = reg_map[reg] + 2 + (stride * lch);
__raw_writew(val >> 16, omap_dma_base + offset2);
}
} else
__raw_writel(val, omap_dma_base + offset);
}
static inline u32 dma_read(int reg, int lch)
{
u8 stride;
u32 offset, val;
stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
offset = reg_map[reg] + (stride * lch);
if (dma_stride == 0x40) {
val = __raw_readw(omap_dma_base + offset);
if ((reg > CLNK_CTRL && reg < CCR2) ||
(reg > PCHD_ID && reg < CAPS_2)) {
u16 upper;
u32 offset2 = reg_map[reg] + 2 + (stride * lch);
upper = __raw_readw(omap_dma_base + offset2);
val |= (upper << 16);
}
} else
val = __raw_readl(omap_dma_base + offset);
return val;
}
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-11-10 14:01 ` G, Manjunath Kondaiah
@ 2010-11-10 16:03 ` Kevin Hilman
2010-11-10 17:16 ` G, Manjunath Kondaiah
0 siblings, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-10 16:03 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
[...]
>> > + if (reg > OMAP1_CH_COMMON_START)
>> > + __raw_writew(val, dma_base +
>> > + (reg_map_omap1[reg] + 0x40 * lch));
>> > + else
>> > + __raw_writew(val, dma_base +
>> reg_map_omap1[reg]);
>> > + } else {
>> > + if (reg > OMAP2_CH_COMMON_START)
>> > + __raw_writel(val, dma_base +
>> > + (reg_map_omap2[reg] + 0x60 * lch));
>> > + else
>> > + __raw_writel(val, dma_base +
>> reg_map_omap2[reg]);
>> > + }
>> > +}
>>
>> The register base offset, register array and the stride (offset
>> between instances: 0x40 or 0x60) are detectable at init time, and
>> there's no reason to have conditional code for them. IOW, they
>> should be init time constants. Doing so would greatly simply these
>> functions. In fact the CH_COMMON_START could also be an init time
>> constant as well. So, given the following init_time constants:
>> dma_ch_common_start, dma_stride, reg_map, the above would be reduced
>> to something actually worth inlining, for example (not actually
>> tested):
>>
>> static inline void dma_write(u32 val, int reg, int lch)
>> {
>> u8 stride = (reg > dma_ch_common_start) ? dma_stride : 0;
>>
>> __raw_writel(val, dma_base + (reg_map[reg] + stride * lch));
>> }
>>
>> Same applies to dma_read().
>
> Thanks for the suggestion. It is taken care along with Tony's comment
> for handling these read/write's between omap1 and omap2+.
>
> Here is code snippet for handling both omap1(includes 16 bit
> registers) and omap2+
>
> static inline void dma_write(u32 val, int reg, int lch)
> {
> u8 stride;
> u32 offset;
>
> stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
> offset = reg_map[reg] + (stride * lch);
>
> if (dma_stride == 0x40) {
The use of hard-coded constants still isn't right here. This is
bascally the same as a cpu_is_omap1 check. After you separate out the
device files, I thought you had separate omap1 and omap2+ versions of
these, so I don't follow the need for this.
> __raw_writew(val, omap_dma_base + offset);
This could be moved before the 'if' and the 'else' clause removed.
> if ((reg > CLNK_CTRL && reg < CCR2) ||
> (reg > PCHD_ID && reg < CAPS_2)) {
> u32 offset2 = reg_map[reg] + 2 + (stride * lch);
> __raw_writew(val >> 16, omap_dma_base + offset2);
> }
> } else
> __raw_writel(val, omap_dma_base + offset);
> }
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-11-10 16:03 ` Kevin Hilman
@ 2010-11-10 17:16 ` G, Manjunath Kondaiah
2010-11-10 17:35 ` Kevin Hilman
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 17:16 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 9:33 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Shilimkar, Santosh
> Subject: Re: [PATCH v3 01/13] OMAP: DMA: Replace read/write
> macros with functions
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
> [...]
>
> >> > + if (reg > OMAP1_CH_COMMON_START)
> >> > + __raw_writew(val, dma_base +
> >> > + (reg_map_omap1[reg] +
> 0x40 * lch));
> >> > + else
> >> > + __raw_writew(val, dma_base +
> >> reg_map_omap1[reg]);
> >> > + } else {
> >> > + if (reg > OMAP2_CH_COMMON_START)
> >> > + __raw_writel(val, dma_base +
> >> > + (reg_map_omap2[reg] +
> 0x60 * lch));
> >> > + else
> >> > + __raw_writel(val, dma_base +
> >> reg_map_omap2[reg]);
> >> > + }
> >> > +}
> >>
> >> The register base offset, register array and the stride (offset
> >> between instances: 0x40 or 0x60) are detectable at init time, and
> >> there's no reason to have conditional code for them. IOW, they
> >> should be init time constants. Doing so would greatly simply these
> >> functions. In fact the CH_COMMON_START could also be an init time
> >> constant as well. So, given the following init_time constants:
> >> dma_ch_common_start, dma_stride, reg_map, the above would
> be reduced
> >> to something actually worth inlining, for example (not actually
> >> tested):
> >>
> >> static inline void dma_write(u32 val, int reg, int lch)
> >> {
> >> u8 stride = (reg > dma_ch_common_start) ? dma_stride : 0;
> >>
> >> __raw_writel(val, dma_base + (reg_map[reg] +
> stride * lch));
> >> }
> >>
> >> Same applies to dma_read().
> >
> > Thanks for the suggestion. It is taken care along with
> Tony's comment
> > for handling these read/write's between omap1 and omap2+.
> >
> > Here is code snippet for handling both omap1(includes 16 bit
> > registers) and omap2+
> >
> > static inline void dma_write(u32 val, int reg, int lch)
> > {
> > u8 stride;
> > u32 offset;
> >
> > stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
> > offset = reg_map[reg] + (stride * lch);
> >
> > if (dma_stride == 0x40) {
>
> The use of hard-coded constants still isn't right here. This is
> bascally the same as a cpu_is_omap1 check. After you separate out the
> device files, I thought you had separate omap1 and omap2+ versions of
> these, so I don't follow the need for this.
This code will be moved to respective mach-omapx dma files and this
conditional check vanishes automatically in PATCH 10/13. Since this patch
targets replacing read/write macros with inline functions, no functionality
changes(except change in logic for handling 16bit registers for omap1)
are done with new patch hence handling omap1 and omap2+ is
done this way.
I hope having the conditional check in this interim patch is ok.
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions
2010-11-10 17:16 ` G, Manjunath Kondaiah
@ 2010-11-10 17:35 ` Kevin Hilman
0 siblings, 0 replies; 50+ messages in thread
From: Kevin Hilman @ 2010-11-10 17:35 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>> -----Original Message-----
>> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
>> Sent: Wednesday, November 10, 2010 9:33 PM
>> To: G, Manjunath Kondaiah
>> Cc: linux-omap at vger.kernel.org;
>> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
>> Shilimkar, Santosh
>> Subject: Re: [PATCH v3 01/13] OMAP: DMA: Replace read/write
>> macros with functions
>>
>> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>>
>> [...]
>>
>> >> > + if (reg > OMAP1_CH_COMMON_START)
>> >> > + __raw_writew(val, dma_base +
>> >> > + (reg_map_omap1[reg] +
>> 0x40 * lch));
>> >> > + else
>> >> > + __raw_writew(val, dma_base +
>> >> reg_map_omap1[reg]);
>> >> > + } else {
>> >> > + if (reg > OMAP2_CH_COMMON_START)
>> >> > + __raw_writel(val, dma_base +
>> >> > + (reg_map_omap2[reg] +
>> 0x60 * lch));
>> >> > + else
>> >> > + __raw_writel(val, dma_base +
>> >> reg_map_omap2[reg]);
>> >> > + }
>> >> > +}
>> >>
>> >> The register base offset, register array and the stride (offset
>> >> between instances: 0x40 or 0x60) are detectable at init time, and
>> >> there's no reason to have conditional code for them. IOW, they
>> >> should be init time constants. Doing so would greatly simply these
>> >> functions. In fact the CH_COMMON_START could also be an init time
>> >> constant as well. So, given the following init_time constants:
>> >> dma_ch_common_start, dma_stride, reg_map, the above would
>> be reduced
>> >> to something actually worth inlining, for example (not actually
>> >> tested):
>> >>
>> >> static inline void dma_write(u32 val, int reg, int lch)
>> >> {
>> >> u8 stride = (reg > dma_ch_common_start) ? dma_stride : 0;
>> >>
>> >> __raw_writel(val, dma_base + (reg_map[reg] +
>> stride * lch));
>> >> }
>> >>
>> >> Same applies to dma_read().
>> >
>> > Thanks for the suggestion. It is taken care along with
>> Tony's comment
>> > for handling these read/write's between omap1 and omap2+.
>> >
>> > Here is code snippet for handling both omap1(includes 16 bit
>> > registers) and omap2+
>> >
>> > static inline void dma_write(u32 val, int reg, int lch)
>> > {
>> > u8 stride;
>> > u32 offset;
>> >
>> > stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
>> > offset = reg_map[reg] + (stride * lch);
>> >
>> > if (dma_stride == 0x40) {
>>
>> The use of hard-coded constants still isn't right here. This is
>> bascally the same as a cpu_is_omap1 check. After you separate out the
>> device files, I thought you had separate omap1 and omap2+ versions of
>> these, so I don't follow the need for this.
>
> This code will be moved to respective mach-omapx dma files and this
> conditional check vanishes automatically in PATCH 10/13. Since this patch
> targets replacing read/write macros with inline functions, no functionality
> changes(except change in logic for handling 16bit registers for omap1)
> are done with new patch hence handling omap1 and omap2+ is
> done this way.
>
> I hope having the conditional check in this interim patch is ok.
Personally, I would rather not have an intermediate step, but if it
makes the series smoother, I guess it's OK.
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 02/13] OMAP: DMA: Introduce errata handling feature
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-11-09 22:12 ` Kevin Hilman
2010-10-26 13:25 ` [PATCH v3 03/13] OMAP: DMA: Introduce DMA device attributes G, Manjunath Kondaiah
` (12 subsequent siblings)
14 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Implement errata handling to use flags instead of cpu_is_*
and cpu_class_* in the code.
The errata flags are initialized at init time and during runtime
we are using the errata variable (via the IS_DMA_ERRATA macro)
to execute the required errata workaround.
Reused errata handling patch from Peter Ujfalusi <peter.ujfalusi@nokia.com>
https://patchwork.kernel.org/patch/231191/
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: Peter Ujfalusi <peter.ujfalusi@nokia.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/dma.c | 134 ++++++++++++++++++++++----------
arch/arm/plat-omap/include/plat/dma.h | 11 +++
2 files changed, 103 insertions(+), 42 deletions(-)
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 77241e2..0ff82d0 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -195,6 +195,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
static int enable_1510_mode;
+static u32 errata;
static struct omap_dma_global_context_registers {
u32 dma_irqenable_l0;
@@ -1216,12 +1217,8 @@ void omap_start_dma(int lch)
cur_lch = next_lch;
} while (next_lch != -1);
- } else if (cpu_is_omap242x() ||
- (cpu_is_omap243x() && omap_type() <= OMAP2430_REV_ES1_0)) {
-
- /* Errata: Need to write lch even if not using chaining */
+ } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
dma_write(lch, CLNK_CTRL2, lch);
- }
omap_enable_channel_irq(lch);
@@ -1231,17 +1228,8 @@ void omap_start_dma(int lch)
dma_write(l, CCR1, lch);
} else {
l = dma_read(CCR2, lch);
- /*
- * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
- * OMAP2430ES1.0): DMA will wrongly buffer elements if packing
- * and bursting is enabled. This might result in data gets
- * stalled in FIFO@the end of the block.
- * Workaround: DMA channels must have BUFFERING_DISABLED bit
- * set to guarantee no data will stay in the DMA FIFO in case
- * inter frame buffering occurs.
- */
- if (cpu_is_omap2420() || (cpu_is_omap2430() &&
- (omap_type() == OMAP2430_REV_ES1_0)))
+
+ if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
l |= OMAP_DMA_CCR_EN;
@@ -1253,14 +1241,14 @@ EXPORT_SYMBOL(omap_start_dma);
void omap_stop_dma(int lch)
{
- u32 l;
+ u32 l = 0;
/* Disable all interrupts on the channel */
if (cpu_class_is_omap1())
dma_write(0, CICR1, lch);
- /* OMAP3 Errata i541: sDMA FIFO draining does not finish */
- if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
+ if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
+ (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
int i = 0;
u32 sys_cf;
@@ -1367,11 +1355,7 @@ dma_addr_t omap_get_dma_src_pos(int lch)
else
offset = dma_read(CSAC2, lch);
- /*
- * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
- * read before the DMA controller finished disabling the channel.
- */
- if (!cpu_is_omap15xx() && offset == 0) {
+ if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) {
if (cpu_class_is_omap1())
offset = dma_read(CSAC1, lch);
else
@@ -1966,7 +1950,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
{
int *channels;
u32 l, i;
- u32 sys_cf;
+ u32 sys_cf = 0;
/* Check for input params */
if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
@@ -1981,15 +1965,13 @@ int omap_stop_dma_chain_transfers(int chain_id)
}
channels = dma_linked_lch[chain_id].linked_dmach_q;
- /*
- * DMA Errata:
- * Special programming model needed to disable DMA before end of block
- */
- sys_cf = dma_read(OCP_SYSCONFIG, 0);
- l = sys_cf;
- /* Middle mode reg set no Standby */
- l &= ~((1 << 12)|(1 << 13));
- dma_write(l, OCP_SYSCONFIG, 0);
+ if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
+ sys_cf = dma_read(OCP_SYSCONFIG, 0);
+ l = sys_cf;
+ /* Middle mode reg set no Standby */
+ l &= ~((1 << 12)|(1 << 13));
+ dma_write(l, OCP_SYSCONFIG, 0);
+ }
for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
@@ -2008,8 +1990,8 @@ int omap_stop_dma_chain_transfers(int chain_id)
/* Reset the Queue pointers */
OMAP_DMA_CHAIN_QINIT(chain_id);
- /* Errata - put in the old value */
- dma_write(sys_cf, OCP_SYSCONFIG, 0);
+ if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+ dma_write(sys_cf, OCP_SYSCONFIG, 0);
return 0;
}
@@ -2215,12 +2197,7 @@ static int omap2_dma_handle_ch(int ch)
if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
printk(KERN_INFO "DMA transaction error with device %d\n",
dma_chan[ch].dev_id);
- if (cpu_class_is_omap2()) {
- /*
- * Errata: sDMA Channel is not disabled
- * after a transaction error. So we explicitely
- * disable the channel
- */
+ if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
u32 ccr;
ccr = dma_read(CCR2, ch);
@@ -2332,6 +2309,76 @@ void omap_dma_global_context_restore(void)
omap_clear_dma(ch);
}
+static void configure_dma_errata(void)
+{
+
+ /*
+ * Erratas applicable for OMAP2430ES1.0 and all omap2420
+ *
+ * I.
+ * Errata ID: XX Inter Frame DMA buffering issue DMA will wrongly
+ * buffer elements if packing and bursting is enabled. This might
+ * result in data gets stalled in FIFO@the end of the block.
+ * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+ * guarantee no data will stay in the DMA FIFO in case inter frame
+ * buffering occurs
+ *
+ * II.
+ * Errata ID: XX DMA may hang when several channels are used in parallel
+ * In the following configuration, DMA channel hanging can occur:
+ * a. Channel i, hardware synchronized, is enabled
+ * b. Another channel (Channel x), software synchronized, is enabled.
+ * c. Channel i is disabled before end of transfer
+ * d. Channel i is reenabled.
+ * e. Steps 1 to 4 are repeated a certain number of times.
+ * f. A third channel (Channel y), software synchronized, is enabled.
+ * Channel x and Channel y may hang immediately after step 'f'.
+ * Workaround:
+ * For any channel used - make sure NextLCH_ID is set to the value j.
+ */
+ if (cpu_is_omap2420() || (cpu_is_omap2430() &&
+ (omap_type() == OMAP2430_REV_ES1_0))) {
+
+ SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
+ SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
+ }
+
+ /*
+ * Errata ID: i378: OMAP2plus: sDMA Channel is not disabled
+ * after a transaction error.
+ * Workaround: SW should explicitely disable the channel.
+ */
+ if (cpu_class_is_omap2())
+ SET_DMA_ERRATA(DMA_ERRATA_i378);
+
+ /*
+ * Errata ID: i541: sDMA FIFO draining does not finish
+ * If sDMA channel is disabled on the fly, sDMA enters standby even
+ * through FIFO Drain is still in progress
+ * Workaround: Put sDMA in NoStandby more before a logical channel is
+ * disabled, then put it back to SmartStandby right after the channel
+ * finishes FIFO draining.
+ */
+ if (cpu_is_omap34xx())
+ SET_DMA_ERRATA(DMA_ERRATA_i541);
+
+ /*
+ * Errata ID: i88 : Special programming model needed to disable DMA
+ * before end of block.
+ * Workaround: software must ensure that the DMA is configured in No
+ * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
+ */
+ if (omap_type() == OMAP3430_REV_ES1_0)
+ SET_DMA_ERRATA(DMA_ERRATA_i88);
+
+ /*
+ * Errata 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+ * read before the DMA controller finished disabling the channel.
+ */
+ if (!cpu_is_omap15xx())
+ SET_DMA_ERRATA(DMA_ERRATA_3_3);
+}
+
/*----------------------------------------------------------------------------*/
static int __init omap_init_dma(void)
@@ -2481,6 +2528,9 @@ static int __init omap_init_dma(void)
}
}
+ /* Configure errata handling for all omap's */
+ configure_dma_errata();
+
return 0;
out_free:
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 27578f3..5e28d26 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -285,6 +285,17 @@
#define DMA_CH_PRIO_HIGH 0x1
#define DMA_CH_PRIO_LOW 0x0 /* Def */
+/* Errata handling */
+#define IS_DMA_ERRATA(id) (errata &= (id))
+#define SET_DMA_ERRATA(id) (errata |= (id))
+
+#define DMA_ERRATA_IFRAME_BUFFERING (1 << 0)
+#define DMA_ERRATA_PARALLEL_CHANNELS (1 << 1)
+#define DMA_ERRATA_i378 (1 << 2)
+#define DMA_ERRATA_i541 (1 << 3)
+#define DMA_ERRATA_i88 (1 << 4)
+#define DMA_ERRATA_3_3 (1 << 5)
+
enum omap_dma_burst_mode {
OMAP_DMA_DATA_BURST_DIS = 0,
OMAP_DMA_DATA_BURST_4,
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 02/13] OMAP: DMA: Introduce errata handling feature
2010-10-26 13:25 ` [PATCH v3 02/13] OMAP: DMA: Introduce errata handling feature G, Manjunath Kondaiah
@ 2010-11-09 22:12 ` Kevin Hilman
2010-11-10 14:02 ` G, Manjunath Kondaiah
0 siblings, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 22:12 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> Implement errata handling to use flags instead of cpu_is_*
> and cpu_class_* in the code.
>
> The errata flags are initialized at init time and during runtime
> we are using the errata variable (via the IS_DMA_ERRATA macro)
> to execute the required errata workaround.
>
> Reused errata handling patch from Peter Ujfalusi <peter.ujfalusi@nokia.com>
> https://patchwork.kernel.org/patch/231191/
When starting from someone else's work, would be very helpful to
reviewers (and original authors) if you summarized what you
changed/fixed/updated etc.
> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@nokia.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/dma.c | 134 ++++++++++++++++++++++----------
> arch/arm/plat-omap/include/plat/dma.h | 11 +++
> 2 files changed, 103 insertions(+), 42 deletions(-)
>
> diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
> index 77241e2..0ff82d0 100644
> --- a/arch/arm/plat-omap/dma.c
> +++ b/arch/arm/plat-omap/dma.c
> @@ -195,6 +195,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
> #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
>
> static int enable_1510_mode;
> +static u32 errata;
>
> static struct omap_dma_global_context_registers {
> u32 dma_irqenable_l0;
> @@ -1216,12 +1217,8 @@ void omap_start_dma(int lch)
>
> cur_lch = next_lch;
> } while (next_lch != -1);
> - } else if (cpu_is_omap242x() ||
> - (cpu_is_omap243x() && omap_type() <= OMAP2430_REV_ES1_0)) {
> -
> - /* Errata: Need to write lch even if not using chaining */
> + } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
> dma_write(lch, CLNK_CTRL2, lch);
> - }
>
> omap_enable_channel_irq(lch);
>
> @@ -1231,17 +1228,8 @@ void omap_start_dma(int lch)
> dma_write(l, CCR1, lch);
> } else {
> l = dma_read(CCR2, lch);
> - /*
> - * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
> - * OMAP2430ES1.0): DMA will wrongly buffer elements if packing
> - * and bursting is enabled. This might result in data gets
> - * stalled in FIFO at the end of the block.
> - * Workaround: DMA channels must have BUFFERING_DISABLED bit
> - * set to guarantee no data will stay in the DMA FIFO in case
> - * inter frame buffering occurs.
> - */
> - if (cpu_is_omap2420() || (cpu_is_omap2430() &&
> - (omap_type() == OMAP2430_REV_ES1_0)))
> +
> + if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
> l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
>
> l |= OMAP_DMA_CCR_EN;
> @@ -1253,14 +1241,14 @@ EXPORT_SYMBOL(omap_start_dma);
>
> void omap_stop_dma(int lch)
> {
> - u32 l;
> + u32 l = 0;
>
> /* Disable all interrupts on the channel */
> if (cpu_class_is_omap1())
> dma_write(0, CICR1, lch);
>
> - /* OMAP3 Errata i541: sDMA FIFO draining does not finish */
> - if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
> + if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
> + (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
> int i = 0;
> u32 sys_cf;
>
> @@ -1367,11 +1355,7 @@ dma_addr_t omap_get_dma_src_pos(int lch)
> else
> offset = dma_read(CSAC2, lch);
>
> - /*
> - * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
> - * read before the DMA controller finished disabling the channel.
> - */
> - if (!cpu_is_omap15xx() && offset == 0) {
> + if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) {
> if (cpu_class_is_omap1())
> offset = dma_read(CSAC1, lch);
> else
> @@ -1966,7 +1950,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
> {
> int *channels;
> u32 l, i;
> - u32 sys_cf;
> + u32 sys_cf = 0;
>
> /* Check for input params */
> if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
> @@ -1981,15 +1965,13 @@ int omap_stop_dma_chain_transfers(int chain_id)
> }
> channels = dma_linked_lch[chain_id].linked_dmach_q;
>
> - /*
> - * DMA Errata:
> - * Special programming model needed to disable DMA before end of block
> - */
> - sys_cf = dma_read(OCP_SYSCONFIG, 0);
> - l = sys_cf;
> - /* Middle mode reg set no Standby */
> - l &= ~((1 << 12)|(1 << 13));
> - dma_write(l, OCP_SYSCONFIG, 0);
> + if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
> + sys_cf = dma_read(OCP_SYSCONFIG, 0);
> + l = sys_cf;
> + /* Middle mode reg set no Standby */
> + l &= ~((1 << 12)|(1 << 13));
> + dma_write(l, OCP_SYSCONFIG, 0);
> + }
>
> for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
>
> @@ -2008,8 +1990,8 @@ int omap_stop_dma_chain_transfers(int chain_id)
> /* Reset the Queue pointers */
> OMAP_DMA_CHAIN_QINIT(chain_id);
>
> - /* Errata - put in the old value */
> - dma_write(sys_cf, OCP_SYSCONFIG, 0);
> + if (IS_DMA_ERRATA(DMA_ERRATA_i88))
> + dma_write(sys_cf, OCP_SYSCONFIG, 0);
> return 0;
> }
> @@ -2215,12 +2197,7 @@ static int omap2_dma_handle_ch(int ch)
> if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
> printk(KERN_INFO "DMA transaction error with device %d\n",
> dma_chan[ch].dev_id);
> - if (cpu_class_is_omap2()) {
> - /*
> - * Errata: sDMA Channel is not disabled
> - * after a transaction error. So we explicitely
> - * disable the channel
> - */
> + if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
> u32 ccr;
>
> ccr = dma_read(CCR2, ch);
> @@ -2332,6 +2309,76 @@ void omap_dma_global_context_restore(void)
> omap_clear_dma(ch);
> }
>
> +static void configure_dma_errata(void)
> +{
> +
> + /*
> + * Erratas applicable for OMAP2430ES1.0 and all omap2420
> + *
> + * I.
> + * Errata ID: XX Inter Frame DMA buffering issue DMA will wrongly
> + * buffer elements if packing and bursting is enabled. This might
> + * result in data gets stalled in FIFO at the end of the block.
> + * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
> + * guarantee no data will stay in the DMA FIFO in case inter frame
> + * buffering occurs
> + *
> + * II.
> + * Errata ID: XX DMA may hang when several channels are used in parallel
> + * In the following configuration, DMA channel hanging can occur:
> + * a. Channel i, hardware synchronized, is enabled
> + * b. Another channel (Channel x), software synchronized, is enabled.
> + * c. Channel i is disabled before end of transfer
> + * d. Channel i is reenabled.
> + * e. Steps 1 to 4 are repeated a certain number of times.
> + * f. A third channel (Channel y), software synchronized, is enabled.
> + * Channel x and Channel y may hang immediately after step 'f'.
> + * Workaround:
> + * For any channel used - make sure NextLCH_ID is set to the value j.
> + */
> + if (cpu_is_omap2420() || (cpu_is_omap2430() &&
> + (omap_type() == OMAP2430_REV_ES1_0))) {
> +
> + SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
> + SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
> + }
> +
> + /*
> + * Errata ID: i378: OMAP2plus: sDMA Channel is not disabled
> + * after a transaction error.
> + * Workaround: SW should explicitely disable the channel.
> + */
> + if (cpu_class_is_omap2())
> + SET_DMA_ERRATA(DMA_ERRATA_i378);
> +
> + /*
> + * Errata ID: i541: sDMA FIFO draining does not finish
> + * If sDMA channel is disabled on the fly, sDMA enters standby even
> + * through FIFO Drain is still in progress
> + * Workaround: Put sDMA in NoStandby more before a logical channel is
> + * disabled, then put it back to SmartStandby right after the channel
> + * finishes FIFO draining.
> + */
> + if (cpu_is_omap34xx())
> + SET_DMA_ERRATA(DMA_ERRATA_i541);
> +
> + /*
> + * Errata ID: i88 : Special programming model needed to disable DMA
> + * before end of block.
> + * Workaround: software must ensure that the DMA is configured in No
> + * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
> + */
> + if (omap_type() == OMAP3430_REV_ES1_0)
> + SET_DMA_ERRATA(DMA_ERRATA_i88);
> +
> + /*
> + * Errata 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
This doesn't look like a unique errata identifier. Chapter 3 is usually
the 'Cautions' section, and I don't listed in either the 34xx (v5.9),
36xx (v1.3) or 44xx (v1.3) errata docs under this number, and don't see
that number in either of the 24xx errata docs either. Please clarify.
> + * read before the DMA controller finished disabling the channel.
> + */
> + if (!cpu_is_omap15xx())
> + SET_DMA_ERRATA(DMA_ERRATA_3_3);
> +}
> +
> /*----------------------------------------------------------------------------*/
>
> static int __init omap_init_dma(void)
> @@ -2481,6 +2528,9 @@ static int __init omap_init_dma(void)
> }
> }
>
> + /* Configure errata handling for all omap's */
> + configure_dma_errata();
> +
> return 0;
>
> out_free:
> diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
> index 27578f3..5e28d26 100644
> --- a/arch/arm/plat-omap/include/plat/dma.h
> +++ b/arch/arm/plat-omap/include/plat/dma.h
> @@ -285,6 +285,17 @@
> #define DMA_CH_PRIO_HIGH 0x1
> #define DMA_CH_PRIO_LOW 0x0 /* Def */
>
> +/* Errata handling */
> +#define IS_DMA_ERRATA(id) (errata &= (id))
Why the '&=' here? I guess it should just be a '&' The '=' was not in
Peter's original.
> +#define SET_DMA_ERRATA(id) (errata |= (id))
> +
> +#define DMA_ERRATA_IFRAME_BUFFERING (1 << 0)
> +#define DMA_ERRATA_PARALLEL_CHANNELS (1 << 1)
> +#define DMA_ERRATA_i378 (1 << 2)
> +#define DMA_ERRATA_i541 (1 << 3)
> +#define DMA_ERRATA_i88 (1 << 4)
> +#define DMA_ERRATA_3_3 (1 << 5)
Please use BIT()
> enum omap_dma_burst_mode {
> OMAP_DMA_DATA_BURST_DIS = 0,
> OMAP_DMA_DATA_BURST_4,
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 02/13] OMAP: DMA: Introduce errata handling feature
2010-11-09 22:12 ` Kevin Hilman
@ 2010-11-10 14:02 ` G, Manjunath Kondaiah
2010-11-10 16:26 ` Kevin Hilman
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 14:02 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 3:43 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Peter Ujfalusi;
> Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v3 02/13] OMAP: DMA: Introduce errata
> handling feature
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
> > Implement errata handling to use flags instead of cpu_is_*
> > and cpu_class_* in the code.
> >
> > The errata flags are initialized at init time and during runtime
> > we are using the errata variable (via the IS_DMA_ERRATA macro)
> > to execute the required errata workaround.
> >
> > Reused errata handling patch from Peter Ujfalusi
> <peter.ujfalusi@nokia.com>
> > https://patchwork.kernel.org/patch/231191/
>
> When starting from someone else's work, would be very helpful to
> reviewers (and original authors) if you summarized what you
> changed/fixed/updated etc.
ok. I will update patch summary.
>
> > Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> > Cc: Peter Ujfalusi <peter.ujfalusi@nokia.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/dma.c | 134
> ++++++++++++++++++++++----------
[...]
> > + if (omap_type() == OMAP3430_REV_ES1_0)
> > + SET_DMA_ERRATA(DMA_ERRATA_i88);
> > +
> > + /*
> > + * Errata 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
>
> This doesn't look like a unique errata identifier. Chapter 3
> is usually
> the 'Cautions' section, and I don't listed in either the 34xx (v5.9),
> 36xx (v1.3) or 44xx (v1.3) errata docs under this number, and
> don't see
> that number in either of the 24xx errata docs either.
> Please clarify.
Even I tried to find this info from errata docs prior to migrating
all errata's to generic errata handling. This code was exising earlier,
hence I retained it "as is", no documentation exists for this errata.
>
> > + * read before the DMA controller finished disabling
> the channel.
> > + */
> > + if (!cpu_is_omap15xx())
> > + SET_DMA_ERRATA(DMA_ERRATA_3_3);
> > +}
> > +
> >
> /*------------------------------------------------------------
> ----------------*/
> >
> > static int __init omap_init_dma(void)
> > @@ -2481,6 +2528,9 @@ static int __init omap_init_dma(void)
> > }
> > }
> >
> > + /* Configure errata handling for all omap's */
> > + configure_dma_errata();
> > +
> > return 0;
> >
> > out_free:
> > diff --git a/arch/arm/plat-omap/include/plat/dma.h
> b/arch/arm/plat-omap/include/plat/dma.h
> > index 27578f3..5e28d26 100644
> > --- a/arch/arm/plat-omap/include/plat/dma.h
> > +++ b/arch/arm/plat-omap/include/plat/dma.h
> > @@ -285,6 +285,17 @@
> > #define DMA_CH_PRIO_HIGH 0x1
> > #define DMA_CH_PRIO_LOW 0x0 /* Def */
> >
> > +/* Errata handling */
> > +#define IS_DMA_ERRATA(id) (errata &= (id))
>
> Why the '&=' here? I guess it should just be a '&' The '='
> was not in
> Peter's original.
correct. There was bug in peter's original patch for SET_DMA_ERRATA(id)
it was | instead |=, while fixing set_dma_errata, accidentally, I have
changed is_dma_errata also. Will fix it.
>
> > +#define SET_DMA_ERRATA(id) (errata |= (id))
> > +
> > +#define DMA_ERRATA_IFRAME_BUFFERING (1 << 0)
> > +#define DMA_ERRATA_PARALLEL_CHANNELS (1 << 1)
> > +#define DMA_ERRATA_i378 (1 << 2)
> > +#define DMA_ERRATA_i541 (1 << 3)
> > +#define DMA_ERRATA_i88 (1 << 4)
> > +#define DMA_ERRATA_3_3 (1 << 5)
>
> Please use BIT()
ok.
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 02/13] OMAP: DMA: Introduce errata handling feature
2010-11-10 14:02 ` G, Manjunath Kondaiah
@ 2010-11-10 16:26 ` Kevin Hilman
2010-11-10 17:39 ` G, Manjunath Kondaiah
0 siblings, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-10 16:26 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
[...]
>> > + if (omap_type() == OMAP3430_REV_ES1_0)
>> > + SET_DMA_ERRATA(DMA_ERRATA_i88);
>> > +
>> > + /*
>> > + * Errata 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
>>
>> This doesn't look like a unique errata identifier. Chapter 3
>> is usually
>> the 'Cautions' section, and I don't listed in either the 34xx (v5.9),
>> 36xx (v1.3) or 44xx (v1.3) errata docs under this number, and
>> don't see
>> that number in either of the 24xx errata docs either.
>> Please clarify.
>
> Even I tried to find this info from errata docs prior to migrating
> all errata's to generic errata handling. This code was exising earlier,
> hence I retained it "as is", no documentation exists for this errata.
>
Hmm, OK.
According to the code, it seems to affect every IP execpt 1510, yet it's
not documented in any of the errata docs.
I wonder what happens if it is removed?
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 02/13] OMAP: DMA: Introduce errata handling feature
2010-11-10 16:26 ` Kevin Hilman
@ 2010-11-10 17:39 ` G, Manjunath Kondaiah
0 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 17:39 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 9:56 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Peter Ujfalusi;
> Cousson, Benoit; Shilimkar, Santosh
> Subject: Re: [PATCH v3 02/13] OMAP: DMA: Introduce errata
> handling feature
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
> [...]
>
> >> > + if (omap_type() == OMAP3430_REV_ES1_0)
> >> > + SET_DMA_ERRATA(DMA_ERRATA_i88);
> >> > +
> >> > + /*
> >> > + * Errata 3.2/3.3: sometimes 0 is returned if
> CSAC/CDAC is
> >>
> >> This doesn't look like a unique errata identifier. Chapter 3
> >> is usually
> >> the 'Cautions' section, and I don't listed in either the
> 34xx (v5.9),
> >> 36xx (v1.3) or 44xx (v1.3) errata docs under this number, and
> >> don't see
> >> that number in either of the 24xx errata docs either.
> >> Please clarify.
> >
> > Even I tried to find this info from errata docs prior to migrating
> > all errata's to generic errata handling. This code was
> exising earlier,
> > hence I retained it "as is", no documentation exists for
> this errata.
> >
>
> Hmm, OK.
>
> According to the code, it seems to affect every IP execpt
> 1510, yet it's
> not documented in any of the errata docs.
>
> I wonder what happens if it is removed?
This errata work around is used in two API's:
1. omap_get_dma_src_pos
2. omap_get_dma_dst_pos
which are used in sound and usb drivers.
we can run sound and usb unit tests which are using above two
API's and if there no issues, drop this errata work around?
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 03/13] OMAP: DMA: Introduce DMA device attributes
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 01/13] OMAP: DMA: Replace read/write macros with functions G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 02/13] OMAP: DMA: Introduce errata handling feature G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-11-09 21:46 ` Kevin Hilman
2010-10-26 13:25 ` [PATCH v3 04/13] OMAP2420: DMA: hwmod: add system DMA G, Manjunath Kondaiah
` (11 subsequent siblings)
14 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
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: G, Manjunath Kondaiah <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 | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 5e28d26..9757b22 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -296,6 +296,22 @@
#define DMA_ERRATA_i88 (1 << 4)
#define DMA_ERRATA_3_3 (1 << 5)
+/* 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_PRIORITY (1 << 0xD)
+
enum omap_dma_burst_mode {
OMAP_DMA_DATA_BURST_DIS = 0,
OMAP_DMA_DATA_BURST_4,
@@ -361,6 +377,10 @@ struct omap_dma_channel_params {
#endif
};
+struct omap_dma_dev_attr {
+ u32 dev_caps;
+ u16 lch_count;
+};
extern void omap_set_dma_priority(int lch, int dst_port, int priority);
extern int omap_request_dma(int dev_id, const char *dev_name,
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 03/13] OMAP: DMA: Introduce DMA device attributes
2010-10-26 13:25 ` [PATCH v3 03/13] OMAP: DMA: Introduce DMA device attributes G, Manjunath Kondaiah
@ 2010-11-09 21:46 ` Kevin Hilman
0 siblings, 0 replies; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 21:46 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> 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: G, Manjunath Kondaiah <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 | 20 ++++++++++++++++++++
> 1 files changed, 20 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
> index 5e28d26..9757b22 100644
> --- a/arch/arm/plat-omap/include/plat/dma.h
> +++ b/arch/arm/plat-omap/include/plat/dma.h
> @@ -296,6 +296,22 @@
> #define DMA_ERRATA_i88 (1 << 4)
> #define DMA_ERRATA_3_3 (1 << 5)
>
> +/* 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_PRIORITY (1 << 0xD)
Please use BIT() for these.
> enum omap_dma_burst_mode {
> OMAP_DMA_DATA_BURST_DIS = 0,
> OMAP_DMA_DATA_BURST_4,
> @@ -361,6 +377,10 @@ struct omap_dma_channel_params {
> #endif
> };
>
> +struct omap_dma_dev_attr {
> + u32 dev_caps;
> + u16 lch_count;
> +};
>
> extern void omap_set_dma_priority(int lch, int dst_port, int priority);
> extern int omap_request_dma(int dev_id, const char *dev_name,
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 04/13] OMAP2420: DMA: hwmod: add system DMA
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (2 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 03/13] OMAP: DMA: Introduce DMA device attributes G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-11-09 23:13 ` Kevin Hilman
2010-10-26 13:25 ` [PATCH v3 05/13] OMAP2430: " G, Manjunath Kondaiah
` (10 subsequent siblings)
14 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Add OMAP2420 DMA hwmod structures.
Signed-off-by: G, Manjunath Kondaiah <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 a1a3dd6..3a51392 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -38,6 +38,7 @@ static struct omap_hwmod omap2420_iva_hwmod;
static struct omap_hwmod omap2420_l3_main_hwmod;
static struct omap_hwmod omap2420_l4_core_hwmod;
static struct omap_hwmod omap2420_wd_timer2_hwmod;
+static struct omap_hwmod omap2420_dma_system_hwmod;
/* L3 -> L4_CORE interface */
static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -557,6 +558,89 @@ static struct omap_hwmod omap2420_i2c2_hwmod = {
.flags = HWMOD_16BIT_REG,
};
+/* system dma */
+static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x002c,
+ .syss_offs = 0x0028,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+ SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_dma_hwmod_class = {
+ .name = "dma",
+ .sysc = &omap2420_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+ .dev_caps = 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,
@@ -569,6 +653,7 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = {
&omap2420_uart3_hwmod,
&omap2420_i2c1_hwmod,
&omap2420_i2c2_hwmod,
+ &omap2420_dma_system_hwmod,
NULL,
};
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 04/13] OMAP2420: DMA: hwmod: add system DMA
2010-10-26 13:25 ` [PATCH v3 04/13] OMAP2420: DMA: hwmod: add system DMA G, Manjunath Kondaiah
@ 2010-11-09 23:13 ` Kevin Hilman
2010-11-11 23:04 ` Kevin Hilman
0 siblings, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 23:13 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> Add OMAP2420 DMA hwmod structures.
s/structures/data/
Also, as pointed out in many other hwmod reviews, when adding hwmod
data, subject should be something like:
OMAP2420: hwmod_data: add system DMA
Kevin
> Signed-off-by: G, Manjunath Kondaiah <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 a1a3dd6..3a51392 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
> @@ -38,6 +38,7 @@ static struct omap_hwmod omap2420_iva_hwmod;
> static struct omap_hwmod omap2420_l3_main_hwmod;
> static struct omap_hwmod omap2420_l4_core_hwmod;
> static struct omap_hwmod omap2420_wd_timer2_hwmod;
> +static struct omap_hwmod omap2420_dma_system_hwmod;
>
> /* L3 -> L4_CORE interface */
> static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
> @@ -557,6 +558,89 @@ static struct omap_hwmod omap2420_i2c2_hwmod = {
> .flags = HWMOD_16BIT_REG,
> };
>
> +/* system dma */
> +static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = {
> + .rev_offs = 0x0000,
> + .sysc_offs = 0x002c,
> + .syss_offs = 0x0028,
> + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
> + SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
> + SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
> + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
> + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
> + .sysc_fields = &omap_hwmod_sysc_type1,
> +};
> +
> +static struct omap_hwmod_class omap2420_dma_hwmod_class = {
> + .name = "dma",
> + .sysc = &omap2420_dma_sysc,
> +};
> +
> +/* dma attributes */
> +static struct omap_dma_dev_attr dma_dev_attr = {
> + .dev_caps = 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,
> @@ -569,6 +653,7 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = {
> &omap2420_uart3_hwmod,
> &omap2420_i2c1_hwmod,
> &omap2420_i2c2_hwmod,
> + &omap2420_dma_system_hwmod,
> NULL,
> };
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 04/13] OMAP2420: DMA: hwmod: add system DMA
2010-11-09 23:13 ` Kevin Hilman
@ 2010-11-11 23:04 ` Kevin Hilman
0 siblings, 0 replies; 50+ messages in thread
From: Kevin Hilman @ 2010-11-11 23:04 UTC (permalink / raw)
To: linux-arm-kernel
Kevin Hilman <khilman@deeprootsystems.com> writes:
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
>> Add OMAP2420 DMA hwmod structures.
>
> s/structures/data/
>
> Also, as pointed out in many other hwmod reviews, when adding hwmod
> data, subject should be something like:
>
> OMAP2420: hwmod_data: add system DMA
>
Oops... no underscore here please. IOW:
OMAP2420: hwmod data: add system DMA
Sorry for the confusion,
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 05/13] OMAP2430: DMA: hwmod: add system DMA
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (3 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 04/13] OMAP2420: DMA: hwmod: add system DMA G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 06/13] OMAP3: " G, Manjunath Kondaiah
` (9 subsequent siblings)
14 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Add OMAP2430 DMA hwmod structures.
Signed-off-by: G, Manjunath Kondaiah <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 7cf0d3a..d3b7239 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -38,6 +38,7 @@ static struct omap_hwmod omap2430_iva_hwmod;
static struct omap_hwmod omap2430_l3_main_hwmod;
static struct omap_hwmod omap2430_l4_core_hwmod;
static struct omap_hwmod omap2430_wd_timer2_hwmod;
+static struct omap_hwmod omap2430_dma_system_hwmod;
/* L3 -> L4_CORE interface */
static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -569,6 +570,89 @@ static struct omap_hwmod omap2430_i2c2_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
+/* dma_system */
+static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x002c,
+ .syss_offs = 0x0028,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+ SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dma_hwmod_class = {
+ .name = "dma",
+ .sysc = &omap2430_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+ .dev_caps = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+ IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+ .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,
@@ -581,6 +665,7 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = {
&omap2430_uart3_hwmod,
&omap2430_i2c1_hwmod,
&omap2430_i2c2_hwmod,
+ &omap2430_dma_system_hwmod,
NULL,
};
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 06/13] OMAP3: DMA: hwmod: add system DMA
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (4 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 05/13] OMAP2430: " G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-11-03 12:59 ` G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 07/13] OMAP4: " G, Manjunath Kondaiah
` (8 subsequent siblings)
14 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Add OMAP3 DMA hwmod structures.
Signed-off-by: G, Manjunath Kondaiah <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 | 93 ++++++++++++++++++++++++++++
1 files changed, 93 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 ed6bf4a..4a5231c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -45,6 +45,7 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
static struct omap_hwmod omap3xxx_i2c1_hwmod;
static struct omap_hwmod omap3xxx_i2c2_hwmod;
static struct omap_hwmod omap3xxx_i2c3_hwmod;
+static struct omap_hwmod omap3xxx_dma_system_hwmod;
/* L3 -> L4_CORE interface */
static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -736,6 +737,97 @@ static struct omap_hwmod omap3xxx_i2c3_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = {
+ .master = &omap3xxx_dma_system_hwmod,
+ .slave = &omap3xxx_l3_main_hwmod,
+ .clk = "core_l3_ick",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+ .dev_caps = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+ IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+ .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 = "core_l4_ick",
+ .addr = omap3xxx_dma_system_addrs,
+ .addr_cnt = ARRAY_SIZE(omap3xxx_dma_system_addrs),
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
+ &omap3xxx_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap3xxx_dma_system_hwmod = {
+ .name = "dma",
+ .class = &omap3xxx_dma_hwmod_class,
+ .mpu_irqs = omap3xxx_dma_system_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dma_system_irqs),
+ .main_clk = "core_l3_ick",
+ .prcm = {
+ .omap2 = {
+ .prcm_reg_id = 1,
+ .module_bit = OMAP3430_ST_SDMA_SHIFT,
+ .idlest_reg_id = 1,
+ .idlest_idle_bit = OMAP3430_ST_SDMA_SHIFT,
+ },
+ },
+ .slaves = omap3xxx_dma_system_slaves,
+ .slaves_cnt = ARRAY_SIZE(omap3xxx_dma_system_slaves),
+ .masters = omap3xxx_dma_system_masters,
+ .masters_cnt = ARRAY_SIZE(omap3xxx_dma_system_masters),
+ .dev_attr = &dma_dev_attr,
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+ .flags = HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&omap3xxx_l3_main_hwmod,
&omap3xxx_l4_core_hwmod,
@@ -751,6 +843,7 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
&omap3xxx_i2c1_hwmod,
&omap3xxx_i2c2_hwmod,
&omap3xxx_i2c3_hwmod,
+ &omap3xxx_dma_system_hwmod,
NULL,
};
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 06/13] OMAP3: DMA: hwmod: add system DMA
2010-10-26 13:25 ` [PATCH v3 06/13] OMAP3: " G, Manjunath Kondaiah
@ 2010-11-03 12:59 ` G, Manjunath Kondaiah
2010-11-04 4:29 ` Cousson, Benoit
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-03 12:59 UTC (permalink / raw)
To: linux-arm-kernel
Kevin/Benoit,
> -----Original Message-----
> From: linux-omap-owner at vger.kernel.org
> [mailto:linux-omap-owner at vger.kernel.org] On Behalf Of G,
> Manjunath Kondaiah
> Sent: Tuesday, October 26, 2010 6:55 PM
> To: linux-omap at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Kevin Hilman; Shilimkar, Santosh
> Subject: [PATCH v3 06/13] OMAP3: DMA: hwmod: add system DMA
>
> Add OMAP3 DMA hwmod structures.
>
> Signed-off-by: G, Manjunath Kondaiah <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 | 93
> ++++++++++++++++++++++++++++
> 1 files changed, 93 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 ed6bf4a..4a5231c 100644
[...]
> + .prcm = {
> + .omap2 = {
> + .prcm_reg_id = 1,
> + .module_bit =
> OMAP3430_ST_SDMA_SHIFT,
> + .idlest_reg_id = 1,
> + .idlest_idle_bit =
> OMAP3430_ST_SDMA_SHIFT,
Looks like the .module_offs field is missing here. Since
ST_SDMA bit belongs to CM_IDLEST1_CORE register, .module_offs should
be CORE_MOD.
But, it is observed that, using .module_offs results in warning dump
during bootup. This is due to, ST_SDMA bit in standby mode. Since
there is no fclk for DMA, this bit will never change till DMA channel
is requested for data transfer.
We might have to bypass calling "omap2_cm_wait_module_ready" in
"_wait_target_ready" in omap_hwmod.c
With exising flags, we can use "HWMOD_NO_IDLEST" flag, but this
flag has different meaning. How about using new flag like
"HWMOD_NO_FCLK_OPCLK" and if it is set, return without calling
"omap2_cm_wait_module_ready"
Any better suggestion to handle this issue?
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 06/13] OMAP3: DMA: hwmod: add system DMA
2010-11-03 12:59 ` G, Manjunath Kondaiah
@ 2010-11-04 4:29 ` Cousson, Benoit
2010-11-04 7:01 ` G, Manjunath Kondaiah
0 siblings, 1 reply; 50+ messages in thread
From: Cousson, Benoit @ 2010-11-04 4:29 UTC (permalink / raw)
To: linux-arm-kernel
Hi Manjunath,
On 11/3/2010 8:59 AM, G, Manjunath Kondaiah wrote:
> Kevin/Benoit,
>
>> [mailto:linux-omap-owner at vger.kernel.org] On Behalf Of G,
>> Manjunath Kondaiah
>> Sent: Tuesday, October 26, 2010 6:55 PM
>>
>> Add OMAP3 DMA hwmod structures.
>>
>> Signed-off-by: G, Manjunath Kondaiah<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 | 93
>> ++++++++++++++++++++++++++++
>> 1 files changed, 93 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 ed6bf4a..4a5231c 100644
> [...]
>> + .prcm = {
>> + .omap2 = {
>> + .prcm_reg_id = 1,
>> + .module_bit =
>> OMAP3430_ST_SDMA_SHIFT,
>> + .idlest_reg_id = 1,
>> + .idlest_idle_bit =
>> OMAP3430_ST_SDMA_SHIFT,
>
> Looks like the .module_offs field is missing here. Since
> ST_SDMA bit belongs to CM_IDLEST1_CORE register, .module_offs should
> be CORE_MOD.
>
> But, it is observed that, using .module_offs results in warning dump
> during bootup. This is due to, ST_SDMA bit in standby mode. Since
> there is no fclk for DMA, this bit will never change till DMA channel
> is requested for data transfer.
>
> We might have to bypass calling "omap2_cm_wait_module_ready" in
> "_wait_target_ready" in omap_hwmod.c
>
> With exising flags, we can use "HWMOD_NO_IDLEST" flag, but this
> flag has different meaning. How about using new flag like
> "HWMOD_NO_FCLK_OPCLK" and if it is set, return without calling
> "omap2_cm_wait_module_ready"
>
> Any better suggestion to handle this issue?
Well, yes, use HWMOD_NO_IDLEST and remove idlest_reg_id &
idlest_idle_bit entries in the omap2 structure.
ST_SDMA is the standby status of the SDMA, but there is no idle status
on that IP, so you cannot do anything.
The standby will just reflect the activity of the master port of the
DMA, but it will give you no information about the slave port and thus
we do not have any module ready information.
Regards,
Benoit
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 06/13] OMAP3: DMA: hwmod: add system DMA
2010-11-04 4:29 ` Cousson, Benoit
@ 2010-11-04 7:01 ` G, Manjunath Kondaiah
2010-11-04 12:30 ` Cousson, Benoit
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-04 7:01 UTC (permalink / raw)
To: linux-arm-kernel
Hi Benoit,
> -----Original Message-----
> From: Cousson, Benoit
> Sent: Thursday, November 04, 2010 9:59 AM
> To: G, Manjunath Kondaiah
> Cc: Kevin Hilman; linux-arm-kernel at lists.infradead.org;
> Shilimkar, Santosh; linux-omap at vger.kernel.org
> Subject: Re: [PATCH v3 06/13] OMAP3: DMA: hwmod: add system DMA
>
> Hi Manjunath,
>
> On 11/3/2010 8:59 AM, G, Manjunath Kondaiah wrote:
> > Kevin/Benoit,
> >
> >> [mailto:linux-omap-owner at vger.kernel.org] On Behalf Of G,
> >> Manjunath Kondaiah
> >> Sent: Tuesday, October 26, 2010 6:55 PM
> >>
> >> Add OMAP3 DMA hwmod structures.
> >>
> >> Signed-off-by: G, Manjunath Kondaiah<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 | 93
> >> ++++++++++++++++++++++++++++
> >> 1 files changed, 93 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 ed6bf4a..4a5231c 100644
> > [...]
> >> + .prcm = {
> >> + .omap2 = {
> >> + .prcm_reg_id = 1,
> >> + .module_bit =
> >> OMAP3430_ST_SDMA_SHIFT,
> >> + .idlest_reg_id = 1,
> >> + .idlest_idle_bit =
> >> OMAP3430_ST_SDMA_SHIFT,
> >
> > Looks like the .module_offs field is missing here. Since
> > ST_SDMA bit belongs to CM_IDLEST1_CORE register, .module_offs should
> > be CORE_MOD.
> >
> > But, it is observed that, using .module_offs results in warning dump
> > during bootup. This is due to, ST_SDMA bit in standby mode. Since
> > there is no fclk for DMA, this bit will never change till
> DMA channel
> > is requested for data transfer.
> >
> > We might have to bypass calling "omap2_cm_wait_module_ready" in
> > "_wait_target_ready" in omap_hwmod.c
> >
> > With exising flags, we can use "HWMOD_NO_IDLEST" flag, but this
> > flag has different meaning. How about using new flag like
> > "HWMOD_NO_FCLK_OPCLK" and if it is set, return without calling
> > "omap2_cm_wait_module_ready"
> >
> > Any better suggestion to handle this issue?
>
> Well, yes, use HWMOD_NO_IDLEST and remove idlest_reg_id &
> idlest_idle_bit entries in the omap2 structure.
>
> ST_SDMA is the standby status of the SDMA, but there is no
> idle status
> on that IP, so you cannot do anything.
> The standby will just reflect the activity of the master port of the
> DMA, but it will give you no information about the slave port
> and thus
> we do not have any module ready information.
Thanks for the feedback.
This change is introduced as per kevin's review comment at:
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg34278.html
I am ok to use "HWMOD_NO_IDLEST" if kevin also agrees
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 06/13] OMAP3: DMA: hwmod: add system DMA
2010-11-04 7:01 ` G, Manjunath Kondaiah
@ 2010-11-04 12:30 ` Cousson, Benoit
2010-11-04 15:48 ` Kevin Hilman
0 siblings, 1 reply; 50+ messages in thread
From: Cousson, Benoit @ 2010-11-04 12:30 UTC (permalink / raw)
To: linux-arm-kernel
On 11/4/2010 3:01 AM, G, Manjunath Kondaiah wrote:
> Hi Benoit,
>
>> From: Cousson, Benoit
>> Sent: Thursday, November 04, 2010 9:59 AM
>>
>> Hi Manjunath,
>>
>> On 11/3/2010 8:59 AM, G, Manjunath Kondaiah wrote:
>>> Kevin/Benoit,
>>>
>>>> [mailto:linux-omap-owner at vger.kernel.org] On Behalf Of G,
>>>> Manjunath Kondaiah
>>>> Sent: Tuesday, October 26, 2010 6:55 PM
>>>>
>>>> Add OMAP3 DMA hwmod structures.
>>>>
>>>> Signed-off-by: G, Manjunath Kondaiah<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 | 93
>>>> ++++++++++++++++++++++++++++
>>>> 1 files changed, 93 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 ed6bf4a..4a5231c 100644
>>> [...]
>>>> + .prcm = {
>>>> + .omap2 = {
>>>> + .prcm_reg_id = 1,
>>>> + .module_bit =
>>>> OMAP3430_ST_SDMA_SHIFT,
>>>> + .idlest_reg_id = 1,
>>>> + .idlest_idle_bit =
>>>> OMAP3430_ST_SDMA_SHIFT,
>>>
>>> Looks like the .module_offs field is missing here. Since
>>> ST_SDMA bit belongs to CM_IDLEST1_CORE register, .module_offs should
>>> be CORE_MOD.
>>>
>>> But, it is observed that, using .module_offs results in warning dump
>>> during bootup. This is due to, ST_SDMA bit in standby mode. Since
>>> there is no fclk for DMA, this bit will never change till
>> DMA channel
>>> is requested for data transfer.
>>>
>>> We might have to bypass calling "omap2_cm_wait_module_ready" in
>>> "_wait_target_ready" in omap_hwmod.c
>>>
>>> With exising flags, we can use "HWMOD_NO_IDLEST" flag, but this
>>> flag has different meaning. How about using new flag like
>>> "HWMOD_NO_FCLK_OPCLK" and if it is set, return without calling
>>> "omap2_cm_wait_module_ready"
>>>
>>> Any better suggestion to handle this issue?
>>
>> Well, yes, use HWMOD_NO_IDLEST and remove idlest_reg_id&
>> idlest_idle_bit entries in the omap2 structure.
>>
>> ST_SDMA is the standby status of the SDMA, but there is no
>> idle status
>> on that IP, so you cannot do anything.
>> The standby will just reflect the activity of the master port of the
>> DMA, but it will give you no information about the slave port
>> and thus
>> we do not have any module ready information.
>
> Thanks for the feedback.
>
> This change is introduced as per kevin's review comment at:
> http://www.mail-archive.com/linux-omap at vger.kernel.org/msg34278.html
Well this register is confusing, because he uses the same naming
convention but with a difference meaning:
ST_SDMA: System DMA standby status.
- 0x0: System DMA is active.
- 0x1: System DMA is in standby mode.
> I am ok to use "HWMOD_NO_IDLEST" if kevin also agrees
He will... Otherwise I will throw him into the New England Aquarium like
Linus :-)
Benoit
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 06/13] OMAP3: DMA: hwmod: add system DMA
2010-11-04 12:30 ` Cousson, Benoit
@ 2010-11-04 15:48 ` Kevin Hilman
0 siblings, 0 replies; 50+ messages in thread
From: Kevin Hilman @ 2010-11-04 15:48 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 2010-11-04 at 08:30 -0400, Cousson, Benoit wrote:
[...]
> >>> Any better suggestion to handle this issue?
> >>
> >> Well, yes, use HWMOD_NO_IDLEST and remove idlest_reg_id&
> >> idlest_idle_bit entries in the omap2 structure.
> >>
> >> ST_SDMA is the standby status of the SDMA, but there is no
> >> idle status
> >> on that IP, so you cannot do anything.
> >> The standby will just reflect the activity of the master port of
> the
> >> DMA, but it will give you no information about the slave port
> >> and thus
> >> we do not have any module ready information.
> >
> > Thanks for the feedback.
> >
> > This change is introduced as per kevin's review comment at:
> > http://www.mail-archive.com/linux-omap at vger.kernel.org/msg34278.html
>
> Well this register is confusing, because he uses the same naming
> convention but with a difference meaning:
>
> ST_SDMA: System DMA standby status.
> - 0x0: System DMA is active.
> - 0x1: System DMA is in standby mode.
>
> > I am ok to use "HWMOD_NO_IDLEST" if kevin also agrees
I agree.
> He will... Otherwise I will throw him into the New England Aquarium
> like Linus :-)
...if he tried, I think he would end up in the fish tank before me. ;)
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 07/13] OMAP4: DMA: hwmod: add system DMA
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (5 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 06/13] OMAP3: " G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 08/13] OMAP1: DMA: Introduce DMA driver as platform device G, Manjunath Kondaiah
` (7 subsequent siblings)
14 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
From: Benoit Cousson <b-cousson@ti.com>
Add OMAP4 DMA hwmod structures.
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: 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 0d5c6eb..f749f0d 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -22,6 +22,7 @@
#include <plat/omap_hwmod.h>
#include <plat/cpu.h>
+#include <plat/dma.h>
#include "omap_hwmod_common_data.h"
@@ -35,6 +36,7 @@
#define OMAP44XX_DMA_REQ_START 1
/* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_dma_system_hwmod;
static struct omap_hwmod omap44xx_dmm_hwmod;
static struct omap_hwmod omap44xx_emif_fw_hwmod;
static struct omap_hwmod omap44xx_l3_instr_hwmod;
@@ -215,6 +217,14 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+/* dma_system -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
+ .master = &omap44xx_dma_system_hwmod,
+ .slave = &omap44xx_l3_main_2_hwmod,
+ .clk = "l3_div_ck",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
/* l4_cfg -> l3_main_2 */
static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
.master = &omap44xx_l4_cfg_hwmod,
@@ -226,6 +236,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
/* l3_main_2 slave ports */
static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
&omap44xx_l3_main_1__l3_main_2,
+ &omap44xx_dma_system__l3_main_2,
&omap44xx_l4_cfg__l3_main_2,
};
@@ -1043,6 +1054,92 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
+/*
+ * 'dma' class
+ * dma controller for data exchange between memory to memory (i.e. internal or
+ * external memory) and gp peripherals to memory or memory to gp peripherals
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dma_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x002c,
+ .syss_offs = 0x0028,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+ SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_dma_hwmod_class = {
+ .name = "dma",
+ .sysc = &omap44xx_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+ .dev_caps = DMA_LINKED_LCH | GLOBAL_PRIORITY |
+ IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+ .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,
@@ -1077,6 +1174,8 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_uart2_hwmod,
&omap44xx_uart3_hwmod,
&omap44xx_uart4_hwmod,
+ /* dma class */
+ &omap44xx_dma_system_hwmod,
NULL,
};
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 08/13] OMAP1: DMA: Introduce DMA driver as platform device
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (6 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 07/13] OMAP4: " G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-11-09 22:23 ` Kevin Hilman
2010-10-26 13:25 ` [PATCH v3 09/13] OMAP2+: DMA: hwmod: Device registration G, Manjunath Kondaiah
` (6 subsequent siblings)
14 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Register OMAP1 DMA driver as platform device and add support
for registering through platform device layer using resource
structures.
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: 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 | 182 ++++++++++++++++++++++++++++++++
arch/arm/mach-omap1/include/mach/dma.h | 29 +++++
2 files changed, 211 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..e756069
--- /dev/null
+++ b/arch/arm/mach-omap1/dma.c
@@ -0,0 +1,182 @@
+/*
+ * 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
+ * - G, Manjunath Kondaiah <manjugk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/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 OMAP1_DMA_BASE (0xfffed800)
+
+static struct resource res[] __initdata = {
+ [0] = {
+ .start = OMAP1_DMA_BASE,
+ .end = OMAP1_DMA_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "0",
+ .start = INT_DMA_CH0_6,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .name = "1",
+ .start = INT_DMA_CH1_7,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .name = "2",
+ .start = INT_DMA_CH2_8,
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .name = "3",
+ .start = INT_DMA_CH3,
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .name = "4",
+ .start = INT_DMA_CH4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .name = "5",
+ .start = INT_DMA_CH5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [7] = {
+ .name = "6",
+ .start = INT_DMA_LCD,
+ .flags = IORESOURCE_IRQ,
+ },
+ /* irq's for omap16xx and omap7xx */
+ [8] = {
+ .name = "7",
+ .start = 53 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [9] = {
+ .name = "8",
+ .start = 54 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [10] = {
+ .name = "9",
+ .start = 55 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [11] = {
+ .name = "10",
+ .start = 56 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [12] = {
+ .name = "11",
+ .start = 57 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [13] = {
+ .name = "12",
+ .start = 58 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [14] = {
+ .name = "13",
+ .start = 59 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [15] = {
+ .name = "14",
+ .start = 60 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [16] = {
+ .name = "15",
+ .start = 61 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+ [17] = {
+ .name = "16",
+ .start = 62 + IH2_BASE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int __init omap1_system_dma_init(void)
+{
+ struct omap_system_dma_plat_info *p;
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = platform_device_alloc("omap_dma_system", 0);
+ if (!pdev) {
+ pr_err("%s: Unable to device alloc for dma\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+ if (ret) {
+ pr_err("%s: Unable to add resources for %s%d\n",
+ __func__, pdev->name, pdev->id);
+ goto exit_device_del;
+ }
+
+ p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+ if (!p) {
+ dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
+ __func__, pdev->name);
+ ret = -ENOMEM;
+ goto exit_device_put;
+ }
+
+ ret = platform_device_add_data(pdev, p, sizeof(*p));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+ __func__, pdev->name, pdev->id);
+ goto exit_device_put;
+ }
+ ret = platform_device_add(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+ __func__, pdev->name, pdev->id);
+ goto exit_device_put;
+ }
+ return ret;
+
+exit_device_put:
+ platform_device_put(pdev);
+exit_device_del:
+ platform_device_del(pdev);
+
+ return ret;
+}
+arch_initcall(omap1_system_dma_init);
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..7949e3f
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/dma.h
@@ -0,0 +1,29 @@
+/*
+ * 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 G, Manjunath Kondaiah <manjugk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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
+
+#endif /* __ASM_ARCH_OMAP1_DMA_H */
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 08/13] OMAP1: DMA: Introduce DMA driver as platform device
2010-10-26 13:25 ` [PATCH v3 08/13] OMAP1: DMA: Introduce DMA driver as platform device G, Manjunath Kondaiah
@ 2010-11-09 22:23 ` Kevin Hilman
2010-11-10 14:02 ` G, Manjunath Kondaiah
0 siblings, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 22:23 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> Register OMAP1 DMA driver as platform device and add support
> for registering through platform device layer using resource
> structures.
>
> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> Cc: 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 | 182 ++++++++++++++++++++++++++++++++
> arch/arm/mach-omap1/include/mach/dma.h | 29 +++++
> 2 files changed, 211 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..e756069
> --- /dev/null
> +++ b/arch/arm/mach-omap1/dma.c
> @@ -0,0 +1,182 @@
> +/*
> + * 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
> + * - G, Manjunath Kondaiah <manjugk@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/slab.h>
> +#include <linux/pm_runtime.h>
no pm_runtime API usage in this patch. Please add only when needed.
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/sched.h>
why is sched.h needed?
> +#include <linux/spinlock.h>
ditto
> +#include <linux/errno.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/device.h>
When creating a new file like this, it's important to only include
headers that are actually used/needed.
> +#include <plat/dma.h>
> +#include <plat/tc.h>
> +
> +#define OMAP1_DMA_BASE (0xfffed800)
> +
> +static struct resource res[] __initdata = {
> + [0] = {
> + .start = OMAP1_DMA_BASE,
> + .end = OMAP1_DMA_BASE + SZ_2K - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .name = "0",
> + .start = INT_DMA_CH0_6,
> + .flags = IORESOURCE_IRQ,
> + },
> + [2] = {
> + .name = "1",
> + .start = INT_DMA_CH1_7,
> + .flags = IORESOURCE_IRQ,
> + },
> + [3] = {
> + .name = "2",
> + .start = INT_DMA_CH2_8,
> + .flags = IORESOURCE_IRQ,
> + },
> + [4] = {
> + .name = "3",
> + .start = INT_DMA_CH3,
> + .flags = IORESOURCE_IRQ,
> + },
> + [5] = {
> + .name = "4",
> + .start = INT_DMA_CH4,
> + .flags = IORESOURCE_IRQ,
> + },
> + [6] = {
> + .name = "5",
> + .start = INT_DMA_CH5,
> + .flags = IORESOURCE_IRQ,
> + },
> + [7] = {
> + .name = "6",
> + .start = INT_DMA_LCD,
> + .flags = IORESOURCE_IRQ,
> + },
> + /* irq's for omap16xx and omap7xx */
> + [8] = {
> + .name = "7",
> + .start = 53 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [9] = {
> + .name = "8",
> + .start = 54 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [10] = {
> + .name = "9",
> + .start = 55 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [11] = {
> + .name = "10",
> + .start = 56 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [12] = {
> + .name = "11",
> + .start = 57 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [13] = {
> + .name = "12",
> + .start = 58 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [14] = {
> + .name = "13",
> + .start = 59 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [15] = {
> + .name = "14",
> + .start = 60 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [16] = {
> + .name = "15",
> + .start = 61 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> + [17] = {
> + .name = "16",
> + .start = 62 + IH2_BASE,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +static int __init omap1_system_dma_init(void)
> +{
> + struct omap_system_dma_plat_info *p;
> + struct platform_device *pdev;
> + int ret;
> +
> + pdev = platform_device_alloc("omap_dma_system", 0);
> + if (!pdev) {
> + pr_err("%s: Unable to device alloc for dma\n",
> + __func__);
> + return -ENOMEM;
> + }
> +
> + ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
> + if (ret) {
> + pr_err("%s: Unable to add resources for %s%d\n",
> + __func__, pdev->name, pdev->id);
> + goto exit_device_del;
> + }
> +
> + p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
> + if (!p) {
> + dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
> + __func__, pdev->name);
> + ret = -ENOMEM;
> + goto exit_device_put;
> + }
> +
> + ret = platform_device_add_data(pdev, p, sizeof(*p));
> + if (ret) {
> + dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
> + __func__, pdev->name, pdev->id);
> + goto exit_device_put;
> + }
> + ret = platform_device_add(pdev);
> + if (ret) {
> + dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
> + __func__, pdev->name, pdev->id);
> + goto exit_device_put;
> + }
> + return ret;
> +
> +exit_device_put:
> + platform_device_put(pdev);
> +exit_device_del:
> + platform_device_del(pdev);
> +
> + return ret;
> +}
> +arch_initcall(omap1_system_dma_init);
> 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..7949e3f
> --- /dev/null
> +++ b/arch/arm/mach-omap1/include/mach/dma.h
> @@ -0,0 +1,29 @@
> +/*
> + * 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 G, Manjunath Kondaiah <manjugk@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * 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
> +
> +#endif /* __ASM_ARCH_OMAP1_DMA_H */
Please don't create an empty header. Just create it in the series when
(if) it's needed. Same goes for next patch.
I see you populate mach/dma.h later in the series, but I don't
understand why those values need to be in the header. More comments on
those patches...
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 08/13] OMAP1: DMA: Introduce DMA driver as platform device
2010-11-09 22:23 ` Kevin Hilman
@ 2010-11-10 14:02 ` G, Manjunath Kondaiah
0 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 14:02 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 3:54 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Shilimkar, Santosh
> Subject: Re: [PATCH v3 08/13] OMAP1: DMA: Introduce DMA
> driver as platform device
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
> > Register OMAP1 DMA driver as platform device and add support
> > for registering through platform device layer using resource
> > structures.
> >
> > Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> > Cc: 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 | 182
> ++++++++++++++++++++++++++++++++
> > arch/arm/mach-omap1/include/mach/dma.h | 29 +++++
> > 2 files changed, 211 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..e756069
> > --- /dev/null
> > +++ b/arch/arm/mach-omap1/dma.c
> > @@ -0,0 +1,182 @@
> > +/*
> > + * 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
> > + * - G, Manjunath Kondaiah <manjugk@ti.com>
> > + *
> > + * This program is free software; you can redistribute it
> and/or modify
> > + * it under the terms of the GNU General Public License
> version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/err.h>
> > +#include <linux/slab.h>
> > +#include <linux/pm_runtime.h>
>
> no pm_runtime API usage in this patch. Please add only when needed.
>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/init.h>
> > +#include <linux/sched.h>
>
> why is sched.h needed?
>
> > +#include <linux/spinlock.h>
>
> ditto
>
> > +#include <linux/errno.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/device.h>
>
> When creating a new file like this, it's important to only include
> headers that are actually used/needed.
Ok. I will check these headers. It was copy paste from old dma driver.
>
> > +#include <plat/dma.h>
> > +#include <plat/tc.h>
> > +
[...]
> > 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..7949e3f
> > --- /dev/null
> > +++ b/arch/arm/mach-omap1/include/mach/dma.h
> > @@ -0,0 +1,29 @@
> > +/*
> > + * 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 G, Manjunath Kondaiah <manjugk@ti.com>
> > + *
> > + * This program is free software; you can redistribute it
> and/or modify
> > + * it under the terms of the GNU General Public License as
> published by
> > + * the Free Software Foundation; either version 2 of the
> License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * 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
> > +
> > +#endif /* __ASM_ARCH_OMAP1_DMA_H */
>
> Please don't create an empty header. Just create it in the
> series when
> (if) it's needed. Same goes for next patch.
ok.
-Manjunath
>
> I see you populate mach/dma.h later in the series, but I don't
> understand why those values need to be in the header. More
> comments on
> those patches...
>
> Kevin
>
>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 09/13] OMAP2+: DMA: hwmod: Device registration
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (7 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 08/13] OMAP1: DMA: Introduce DMA driver as platform device G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver G, Manjunath Kondaiah
` (5 subsequent siblings)
14 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Prepare omap2+ dma driver to use hwmod infrastructure
so that DMA driver can register as platform device.
Signed-off-by: G, Manjunath Kondaiah <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 | 86 ++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/include/mach/dma.h | 32 ++++++++++++
2 files changed, 118 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..30b20cd
--- /dev/null
+++ b/arch/arm/mach-omap2/dma.c
@@ -0,0 +1,86 @@
+/*
+ * 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
+ * - G, Manjunath Kondaiah <manjugk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/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>
+
+static struct omap_device_pm_latency omap2_dma_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+/* One time initializations */
+static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
+{
+ struct omap_device *od;
+ struct omap_system_dma_plat_info *p;
+ char *name = "omap_system_dma";
+
+ p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+ if (!p) {
+ pr_err("%s: Unable to allocate pdata for %s:%s\n",
+ __func__, name, oh->name);
+ return -ENOMEM;
+ }
+ od = omap_device_build(name, 0, oh, p, sizeof(*p),
+ omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+
+ if (IS_ERR(od)) {
+ pr_err("%s: Cant build omap_device for %s:%s.\n",
+ __func__, name, oh->name);
+ kfree(p);
+ return IS_ERR(od);
+ }
+ kfree(p);
+
+ 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..d0a7d5b
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+ * - G, Manjunath Kondaiah <manjugk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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
+
+#endif /* __ASM_ARCH_OMAP2_DMA_H */
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (8 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 09/13] OMAP2+: DMA: hwmod: Device registration G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-11-09 22:26 ` Kevin Hilman
2010-11-09 23:29 ` Kevin Hilman
2010-10-26 13:25 ` [PATCH v3 11/13] OMAP: DMA: Use DMA device attributes G, Manjunath Kondaiah
` (4 subsequent siblings)
14 siblings, 2 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Convert DMA library into DMA platform driver and make use
of platform data provided by HWMOD data base for OMAP2PLUS onwards.
For OMAP1 processors, the DMA driver in mach-omap uses resource
structures for getting platform data.
Signed-off-by: G, Manjunath Kondaiah <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/dma.c | 180 ++++++++++++++++++-
arch/arm/mach-omap2/Makefile | 2 +-
arch/arm/mach-omap2/dma.c | 209 +++++++++++++++++++++-
arch/arm/mach-omap2/include/mach/dma.h | 3 +
arch/arm/plat-omap/dma.c | 321 +++++++++++---------------------
arch/arm/plat-omap/include/plat/dma.h | 50 ++++--
7 files changed, 538 insertions(+), 229 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/dma.c b/arch/arm/mach-omap1/dma.c
index e756069..38a7294 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -35,6 +35,81 @@
#include <plat/tc.h>
#define OMAP1_DMA_BASE (0xfffed800)
+#define OMAP1_LOGICAL_DMA_CH_COUNT 17
+
+static u32 errata;
+static u32 enable_1510_mode;
+
+enum {
+ GCR1 = 0, GSCR, GRST, HW_ID,
+ PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
+ PCHD_ID, CAPS_0_U, CAPS_0_L, CAPS_1_U,
+ CAPS_1_L, CAPS_2, CAPS_3, CAPS_4,
+ PCH2_SR, PCH0_SR, PCH1_SR, PCHD_SR,
+
+ CH_COMMON_START,
+
+ /* Common Registers */
+ CSDP1, CCR1, CICR1, CSR1,
+ CEN1, CFN1, CSFI1, CSEI1,
+ CPC, CSAC1, CDAC1, CDEI1,
+ CDFI1, CLNK_CTRL1,
+
+ /* Channel specific register offsets */
+ CSSA_L, CSSA_U, CDSA_L, CDSA_U,
+ COLOR_L, COLOR_U, CCR1_2, LCH_CTRL,
+
+ CH_COMMON_END,
+};
+
+static u16 reg_map[] = {
+ [GCR1] = 0x400,
+ [GSCR] = 0x404,
+ [GRST] = 0x408,
+ [HW_ID] = 0x442,
+ [PCH2_ID] = 0x444,
+ [PCH0_ID] = 0x446,
+ [PCH1_ID] = 0x448,
+ [PCHG_ID] = 0x44a,
+ [PCHD_ID] = 0x44c,
+ [CAPS_0_U] = 0x44e,
+ [CAPS_0_L] = 0x450,
+ [CAPS_1_U] = 0x452,
+ [CAPS_1_L] = 0x454,
+ [CAPS_2] = 0x456,
+ [CAPS_3] = 0x458,
+ [CAPS_4] = 0x45a,
+ [PCH2_SR] = 0x460,
+ [PCH0_SR] = 0x480,
+ [PCH1_SR] = 0x482,
+ [PCHD_SR] = 0x4c0,
+
+ /* Common Registers */
+ [CSDP1] = 0x00,
+ [CCR1] = 0x02,
+ [CICR1] = 0x04,
+ [CSR1] = 0x06,
+ [CEN1] = 0x10,
+ [CFN1] = 0x12,
+ [CSFI1] = 0x14,
+ [CSEI1] = 0x16,
+ [CPC] = 0x18, /* 15xx only */
+ [CSAC1] = 0x18,
+ [CDAC1] = 0x1a,
+ [CDEI1] = 0x1c,
+ [CDFI1] = 0x1e,
+ [CLNK_CTRL1] = 0x28,
+
+ /* Channel specific register offsets */
+ [CSSA_L] = 0x08,
+ [CSSA_U] = 0x0a,
+ [CDSA_L] = 0x0c,
+ [CDSA_U] = 0x0e,
+ [COLOR_L] = 0x20,
+ [COLOR_U] = 0x22,
+ [CCR1_2] = 0x24,
+ [LCH_CTRL] = 0x2a,
+};
static struct resource res[] __initdata = {
[0] = {
@@ -130,9 +205,64 @@ static struct resource res[] __initdata = {
},
};
+static void __iomem *dma_base;
+static inline void dma_write(u16 val, int reg, int lch)
+{
+ if (reg > CH_COMMON_START)
+ __raw_writew(val, dma_base + (reg_map[reg] + 0x40 * lch));
+ else
+ __raw_writew(val, dma_base + reg_map[reg]);
+}
+
+static inline u16 dma_read(int reg, int lch)
+{
+ if (reg > CH_COMMON_START)
+ return __raw_readw(dma_base + (reg_map[reg] + 0x40 * lch));
+ else
+ return __raw_readw(dma_base + reg_map[reg]);
+}
+
+static void omap1_show_dma_caps(void)
+{
+ if (enable_1510_mode) {
+ printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
+ } else {
+ u16 w;
+ printk(KERN_INFO "OMAP DMA hardware version %d\n",
+ dma_read(HW_ID, 0));
+ printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
+ (dma_read(CAPS_0_U, 0) << 16) |
+ dma_read(CAPS_0_L, 0),
+ (dma_read(CAPS_1_U, 0) << 16) |
+ dma_read(CAPS_1_L, 0),
+ dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
+ dma_read(CAPS_4, 0));
+
+ /* Disable OMAP 3.0/3.1 compatibility mode. */
+ w = dma_read(GSCR, 0);
+ w |= 1 << 3;
+ dma_write(w, GSCR, 0);
+ }
+ return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+ /*
+ * Errata 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+ * read before the DMA controller finished disabling the channel.
+ */
+ if (!cpu_is_omap15xx())
+ SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+ return errata;
+}
+
static int __init omap1_system_dma_init(void)
{
struct omap_system_dma_plat_info *p;
+ struct omap_dma_dev_attr *d;
struct platform_device *pdev;
int ret;
@@ -158,20 +288,66 @@ static int __init omap1_system_dma_init(void)
goto exit_device_put;
}
+ d = p->dma_attr;
+ d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+ (d->lch_count), GFP_KERNEL);
+ if (!d->chan) {
+ dev_err(&pdev->dev, "%s: Memory allocation failed"
+ "for d->chan!!!\n", __func__);
+ goto exit_release_p;
+ }
+
+ /* Valid attributes for omap1 plus processors */
+ if (cpu_is_omap15xx())
+ d->dev_caps = ENABLE_1510_MODE;
+ enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
+
+ d->dev_caps |= SRC_PORT;
+ d->dev_caps |= DST_PORT;
+ d->dev_caps |= SRC_INDEX;
+ d->dev_caps |= DST_INDEX;
+ d->dev_caps |= IS_BURST_ONLY4;
+ d->dev_caps |= CLEAR_CSR_ON_READ;
+ d->dev_caps |= IS_WORD_16;
+
+ d->lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
+
+ if (cpu_is_omap15xx())
+ d->chan_count = 9;
+ else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+ if (!(d->dev_caps & ENABLE_1510_MODE))
+ d->chan_count = 16;
+ else
+ d->chan_count = 9;
+ }
+
+ p->omap_dma_base = (void __iomem *)res[0].start;
+ dma_base = p->omap_dma_base;
+
+ p->show_dma_caps = omap1_show_dma_caps;
+ p->disable_irq_lch = NULL;
+
+ /* Configure errata handling for all omap1+ */
+ p->errata = configure_dma_errata();
+
ret = platform_device_add_data(pdev, p, sizeof(*p));
if (ret) {
dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
__func__, pdev->name, pdev->id);
- goto exit_device_put;
+ goto exit_release_chan;
}
ret = platform_device_add(pdev);
if (ret) {
dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
__func__, pdev->name, pdev->id);
- goto exit_device_put;
+ goto exit_release_chan;
}
return ret;
+exit_release_chan:
+ kfree(d->chan);
+exit_release_p:
+ kfree(p);
exit_device_put:
platform_device_put(pdev);
exit_device_del:
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 7352412..5d250c8 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -4,7 +4,7 @@
# Common support
obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
- common.o
+ common.o dma.o
omap-2-3-common = irq.o sdrc.o prm2xxx_3xxx.o
hwmod-common = omap_hwmod.o \
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 30b20cd..5ca519b 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -39,6 +39,79 @@
#include <plat/omap_device.h>
#include <plat/dma.h>
+static u32 errata;
+static struct omap_dma_dev_attr *d;
+
+enum {
+ REVISION = 0, GCR2, IRQSTATUS_L0, IRQSTATUS_L1,
+ IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0, IRQENABLE_L1,
+ IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS, OCP_SYSCONFIG,
+ CAPS_0, CAPS_2, CAPS_3, CAPS_4,
+
+ CH_COMMON_START,
+
+ /* Common register offsets */
+ CCR2, CLNK_CTRL2, CICR2, CSR2,
+ CSDP2, CEN2, CFN2, CSEI2,
+ CSFI2, CDEI2, CDFI2, CSAC2,
+ CDAC2,
+
+ /* Channel specific register offsets */
+ CSSA, CDSA, CCEN, CCFN,
+ COLOR,
+
+ /* OMAP4 specific registers */
+ CDP, CNDP, CCDN,
+
+ CH_COMMON_END,
+};
+
+static u16 reg_map[] = {
+ [REVISION] = 0x00,
+ [GCR2] = 0x78,
+ [IRQSTATUS_L0] = 0x08,
+ [IRQSTATUS_L1] = 0x0c,
+ [IRQSTATUS_L2] = 0x10,
+ [IRQSTATUS_L3] = 0x14,
+ [IRQENABLE_L0] = 0x18,
+ [IRQENABLE_L1] = 0x1c,
+ [IRQENABLE_L2] = 0x20,
+ [IRQENABLE_L3] = 0x24,
+ [SYSSTATUS] = 0x28,
+ [OCP_SYSCONFIG] = 0x2c,
+ [CAPS_0] = 0x64,
+ [CAPS_2] = 0x6c,
+ [CAPS_3] = 0x70,
+ [CAPS_4] = 0x74,
+
+ /* Common register offsets */
+ [CCR2] = 0x80,
+ [CLNK_CTRL2] = 0x84,
+ [CICR2] = 0x88,
+ [CSR2] = 0x8c,
+ [CSDP2] = 0x90,
+ [CEN2] = 0x94,
+ [CFN2] = 0x98,
+ [CSEI2] = 0xa4,
+ [CSFI2] = 0xa8,
+ [CDEI2] = 0xac,
+ [CDFI2] = 0xb0,
+ [CSAC2] = 0xb4,
+ [CDAC2] = 0xb8,
+
+ /* Channel specific register offsets */
+ [CSSA] = 0x9c,
+ [CDSA] = 0xa0,
+ [CCEN] = 0xbc,
+ [CCFN] = 0xc0,
+ [COLOR] = 0xc4,
+
+ /* OMAP4 specific registers */
+ [CDP] = 0xd0,
+ [CNDP] = 0xd4,
+ [CCDN] = 0xd8,
+};
+
static struct omap_device_pm_latency omap2_dma_latency[] = {
{
.deactivate_func = omap_device_idle_hwmods,
@@ -47,12 +120,118 @@ static struct omap_device_pm_latency omap2_dma_latency[] = {
},
};
+static void __iomem *dma_base;
+static inline void dma_write(u32 val, int reg, int lch)
+{
+ if (reg > CH_COMMON_START)
+ __raw_writel(val, dma_base + (reg_map[reg] + 0x60 * lch));
+ else
+ __raw_writel(val, dma_base + reg_map[reg]);
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+ if (reg > CH_COMMON_START)
+ return __raw_readl(dma_base + (reg_map[reg] + 0x60 * lch));
+ else
+ return __raw_readl(dma_base + reg_map[reg]);
+}
+
+static inline void disable_irq_lch(int lch)
+{
+ u32 val;
+
+ val = dma_read(IRQENABLE_L0, lch);
+ val &= ~(1 << lch);
+ dma_write(val, IRQENABLE_L0, lch);
+}
+
+static void omap2_show_dma_caps(void)
+{
+ u8 revision = dma_read(REVISION, 0) & 0xff;
+ printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
+ revision >> 4, revision & 0xf);
+ return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+ /*
+ * Erratas applicable for OMAP2430ES1.0 and all omap2420
+ *
+ * I.
+ * Errata ID: XX Inter Frame DMA buffering issue DMA will wrongly
+ * buffer elements if packing and bursting is enabled. This might
+ * result in data gets stalled in FIFO at the end of the block.
+ * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+ * guarantee no data will stay in the DMA FIFO in case inter frame
+ * buffering occurs
+ *
+ * II.
+ * Errata ID: XX DMA may hang when several channels are used in parallel
+ * In the following configuration, DMA channel hanging can occur:
+ * a. Channel i, hardware synchronized, is enabled
+ * b. Another channel (Channel x), software synchronized, is enabled.
+ * c. Channel i is disabled before end of transfer
+ * d. Channel i is reenabled.
+ * e. Steps 1 to 4 are repeated a certain number of times.
+ * f. A third channel (Channel y), software synchronized, is enabled.
+ * Channel x and Channel y may hang immediately after step 'f'.
+ * Workaround:
+ * For any channel used - make sure NextLCH_ID is set to the value j.
+ */
+ if (cpu_is_omap2420() || (cpu_is_omap2430() &&
+ (omap_type() == OMAP2430_REV_ES1_0))) {
+
+ SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
+ SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
+ }
+
+ /*
+ * Errata ID: i378: OMAP2plus: sDMA Channel is not disabled
+ * after a transaction error.
+ * Workaround: SW should explicitely disable the channel.
+ */
+ if (cpu_class_is_omap2())
+ SET_DMA_ERRATA(DMA_ERRATA_i378);
+
+ /*
+ * Errata ID: i541: sDMA FIFO draining does not finish
+ * If sDMA channel is disabled on the fly, sDMA enters standby even
+ * through FIFO Drain is still in progress
+ * Workaround: Put sDMA in NoStandby more before a logical channel is
+ * disabled, then put it back to SmartStandby right after the channel
+ * finishes FIFO draining.
+ */
+ if (cpu_is_omap34xx())
+ SET_DMA_ERRATA(DMA_ERRATA_i541);
+
+ /*
+ * Errata ID: i88 : Special programming model needed to disable DMA
+ * before end of block.
+ * Workaround: software must ensure that the DMA is configured in No
+ * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
+ */
+ if (omap_type() == OMAP3430_REV_ES1_0)
+ SET_DMA_ERRATA(DMA_ERRATA_i88);
+
+ /*
+ * Errata 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+ * read before the DMA controller finished disabling the channel.
+ */
+ SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+ return errata;
+}
+
/* One time initializations */
static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
{
struct omap_device *od;
struct omap_system_dma_plat_info *p;
- char *name = "omap_system_dma";
+ struct resource *mem;
+ char *name = "omap_dma_system";
p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
if (!p) {
@@ -60,6 +239,14 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
__func__, name, oh->name);
return -ENOMEM;
}
+ p->regs = reg_map;
+ p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr;
+ p->disable_irq_lch = disable_irq_lch;
+ p->show_dma_caps = omap2_show_dma_caps;
+
+ /* Configure errata handling for all omap2+'s */
+ p->errata = configure_dma_errata();
+
od = omap_device_build(name, 0, oh, p, sizeof(*p),
omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
@@ -71,6 +258,26 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
}
kfree(p);
+ mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__);
+ return -EINVAL;
+ }
+
+ dma_base = ioremap(mem->start, resource_size(mem));
+ if (!dma_base) {
+ dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__);
+ return -ENOMEM;
+ }
+
+ d = oh->dev_attr;
+ d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+ (d->lch_count), GFP_KERNEL);
+
+ if (!d->chan) {
+ dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+ return -ENOMEM;
+ }
return 0;
}
diff --git a/arch/arm/mach-omap2/include/mach/dma.h b/arch/arm/mach-omap2/include/mach/dma.h
index d0a7d5b..d13c5c0 100644
--- a/arch/arm/mach-omap2/include/mach/dma.h
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -29,4 +29,7 @@
#ifndef __ASM_ARCH_OMAP2_DMA_H
#define __ASM_ARCH_OMAP2_DMA_H
+/* Should be part of hwmod data base ? */
+#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */
+
#endif /* __ASM_ARCH_OMAP2_DMA_H */
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 0ff82d0..d8e9886 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -15,6 +15,10 @@
*
* Support functions for the OMAP internal DMA channels.
*
+ * Copyright (C) 2010 Texas Instruments
+ * Converted DMA library into DMA platform driver.
+ * - G, Manjunath Kondaiah <manjugk@ti.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -194,6 +198,9 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
+static struct omap_system_dma_plat_info *p;
+static struct omap_dma_dev_attr *d;
+static u16 *reg_map;
static int enable_1510_mode;
static u32 errata;
@@ -203,27 +210,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;
@@ -280,15 +266,6 @@ static int omap_dma_reserve_channels;
static spinlock_t dma_chan_lock;
static struct omap_dma_lch *dma_chan;
static void __iomem *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 inline void disable_lnk(int lch);
static void omap_disable_channel_irq(int lch);
static inline void omap_enable_channel_irq(int lch);
@@ -1195,7 +1172,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 */
@@ -1288,7 +1265,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 {
@@ -1494,8 +1471,6 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
}
EXPORT_SYMBOL(omap_dma_unlink_lch);
-/*----------------------------------------------------------------------------*/
-
#ifndef CONFIG_ARCH_OMAP1
/* Create chain of DMA channesls */
static void create_dma_lch_chain(int lch_head, int lch_queue)
@@ -2309,159 +2284,59 @@ void omap_dma_global_context_restore(void)
omap_clear_dma(ch);
}
-static void configure_dma_errata(void)
+static int __devinit omap_system_dma_probe(struct platform_device *pdev)
{
-
- /*
- * Erratas applicable for OMAP2430ES1.0 and all omap2420
- *
- * I.
- * Errata ID: XX Inter Frame DMA buffering issue DMA will wrongly
- * buffer elements if packing and bursting is enabled. This might
- * result in data gets stalled in FIFO at the end of the block.
- * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
- * guarantee no data will stay in the DMA FIFO in case inter frame
- * buffering occurs
- *
- * II.
- * Errata ID: XX DMA may hang when several channels are used in parallel
- * In the following configuration, DMA channel hanging can occur:
- * a. Channel i, hardware synchronized, is enabled
- * b. Another channel (Channel x), software synchronized, is enabled.
- * c. Channel i is disabled before end of transfer
- * d. Channel i is reenabled.
- * e. Steps 1 to 4 are repeated a certain number of times.
- * f. A third channel (Channel y), software synchronized, is enabled.
- * Channel x and Channel y may hang immediately after step 'f'.
- * Workaround:
- * For any channel used - make sure NextLCH_ID is set to the value j.
- */
- if (cpu_is_omap2420() || (cpu_is_omap2430() &&
- (omap_type() == OMAP2430_REV_ES1_0))) {
-
- SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING);
- SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS);
+ 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;
}
- /*
- * Errata ID: i378: OMAP2plus: sDMA Channel is not disabled
- * after a transaction error.
- * Workaround: SW should explicitely disable the channel.
- */
- if (cpu_class_is_omap2())
- SET_DMA_ERRATA(DMA_ERRATA_i378);
-
- /*
- * Errata ID: i541: sDMA FIFO draining does not finish
- * If sDMA channel is disabled on the fly, sDMA enters standby even
- * through FIFO Drain is still in progress
- * Workaround: Put sDMA in NoStandby more before a logical channel is
- * disabled, then put it back to SmartStandby right after the channel
- * finishes FIFO draining.
- */
- if (cpu_is_omap34xx())
- SET_DMA_ERRATA(DMA_ERRATA_i541);
-
- /*
- * Errata ID: i88 : Special programming model needed to disable DMA
- * before end of block.
- * Workaround: software must ensure that the DMA is configured in No
- * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01")
- */
- if (omap_type() == OMAP3430_REV_ES1_0)
- SET_DMA_ERRATA(DMA_ERRATA_i88);
-
- /*
- * Errata 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
- * read before the DMA controller finished disabling the channel.
- */
- if (!cpu_is_omap15xx())
- SET_DMA_ERRATA(DMA_ERRATA_3_3);
-}
+ p = pdata;
+ d = p->dma_attr;
+ reg_map = pdata->regs;
+ errata = p->errata;
-/*----------------------------------------------------------------------------*/
-
-static int __init omap_init_dma(void)
-{
- unsigned long base;
- int ch, r;
-
- if (cpu_class_is_omap1()) {
- base = OMAP1_DMA_BASE;
- dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
- } else if (cpu_is_omap24xx()) {
- base = OMAP24XX_DMA4_BASE;
- dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
- } else if (cpu_is_omap34xx()) {
- base = OMAP34XX_DMA4_BASE;
- dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
- } else if (cpu_is_omap44xx()) {
- base = OMAP44XX_DMA4_BASE;
- dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
- } else {
- pr_err("DMA init failed for unsupported omap\n");
- return -ENODEV;
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+ return -EINVAL;
}
- dma_base = ioremap(base, SZ_4K);
- BUG_ON(!dma_base);
+ dma_base = ioremap(mem->start, resource_size(mem));
+ if (!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 = dma_lch_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, 0));
- printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
- (dma_read(CAPS1_0_U, 0) << 16) |
- dma_read(CAPS1_0_L, 0),
- (dma_read(CAPS1_1_U, 0) << 16) |
- dma_read(CAPS1_1_L, 0),
- dma_read(CAPS1_2, 0), dma_read(CAPS1_3, 0),
- dma_read(CAPS1_4, 0));
- if (!enable_1510_mode) {
- u16 w;
-
- /* Disable OMAP 3.0/3.1 compatibility mode. */
- w = dma_read(GSCR, 0);
- w |= 1 << 3;
- dma_write(w, GSCR, 0);
- dma_chan_count = 16;
- } else
- dma_chan_count = 9;
- } else if (cpu_class_is_omap2()) {
- u8 revision = dma_read(REVISION, 0) & 0xff;
- printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
- revision >> 4, revision & 0xf);
- dma_chan_count = dma_lch_count;
- } else {
- dma_chan_count = 0;
- return 0;
- }
+ p->show_dma_caps();
spin_lock_init(&dma_chan_lock);
-
for (ch = 0; ch < dma_chan_count; ch++) {
omap_clear_dma(ch);
if (cpu_class_is_omap2())
@@ -2478,19 +2353,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;
+ dev_err(&pdev->dev, "unable to request IRQ %d"
+ "for DMA (error %d)\n", dma_irq, ret);
+ for (irq_rel = 0; irq_rel < ch;
+ irq_rel++) {
+ dma_irq = platform_get_irq(pdev,
+ irq_rel);
+ free_irq(dma_irq, (void *)
+ (irq_rel + 1));
+ goto exit_dma_chan;
+ }
}
}
}
@@ -2500,49 +2386,62 @@ static int __init omap_init_dma(void)
DMA_DEFAULT_FIFO_DEPTH, 0);
if (cpu_class_is_omap2()) {
- int irq;
- if (cpu_is_omap44xx())
- irq = OMAP44XX_IRQ_SDMA_0;
- else
- irq = INT_24XX_SDMA_IRQ0;
- setup_irq(irq, &omap24xx_dma_irq);
- }
-
- if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
- /* Enable smartidle idlemodes and autoidle */
- u32 v = dma_read(OCP_SYSCONFIG, 0);
- v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
- DMA_SYSCONFIG_SIDLEMODE_MASK |
- DMA_SYSCONFIG_AUTOIDLE);
- v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
- DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
- DMA_SYSCONFIG_AUTOIDLE);
- dma_write(v , OCP_SYSCONFIG, 0);
- /* reserve dma channels 0 and 1 in high security devices */
- if (cpu_is_omap34xx() &&
- (omap_type() != OMAP2_DEVICE_TYPE_GP)) {
- printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
- "HS ROM code\n");
- dma_chan[0].dev_id = 0;
- dma_chan[1].dev_id = 1;
- }
+ strcpy(irq_name, "0");
+ dma_irq = platform_get_irq_byname(pdev, irq_name);
+ setup_irq(dma_irq, &omap24xx_dma_irq);
}
- /* Configure errata handling for all omap's */
- configure_dma_errata();
-
+ /* reserve dma channels 0 and 1 in high security devices */
+ if (cpu_is_omap34xx() &&
+ (omap_type() != OMAP2_DEVICE_TYPE_GP)) {
+ printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
+ "HS ROM code\n");
+ dma_chan[0].dev_id = 0;
+ dma_chan[1].dev_id = 1;
+ }
return 0;
-out_free:
+exit_dma_chan:
kfree(dma_chan);
+exit_unmap:
+ iounmap(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(dma_base);
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, resource_size(mem));
+ return 0;
+}
+
+static struct platform_driver omap_system_dma_driver = {
+ .probe = omap_system_dma_probe,
+ .remove = omap_system_dma_remove,
+ .driver = {
+ .name = "omap_dma_system"
+ },
+};
- return r;
+static int __init omap_system_dma_init(void)
+{
+ return platform_driver_register(&omap_system_dma_driver);
+}
+arch_initcall(omap_system_dma_init);
+
+static void __exit omap_system_dma_exit(void)
+{
+ platform_driver_unregister(&omap_system_dma_driver);
}
-arch_initcall(omap_init_dma);
+MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
/*
* Reserve the omap SDMA channels using cmdline bootarg
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 9757b22..e3a927d 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -21,21 +21,15 @@
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
-/* Move omap4 specific defines to dma-44xx.h */
-#include "dma-44xx.h"
-
-/* Hardware registers for omap1 */
-#define OMAP1_DMA_BASE (0xfffed800)
-
-/* 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)
+#include <linux/platform_device.h>
-#define OMAP1_LOGICAL_DMA_CH_COUNT 17
-#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */
+/*
+ * TODO: These dma channel defines should go away once all
+ * the omap drivers hwmod adapted.
+ */
-/*----------------------------------------------------------------------------*/
+/* Move omap4 specific defines to dma-44xx.h */
+#include "dma-44xx.h"
/* DMA channels for omap1 */
#define OMAP_DMA_NO_DEVICE 0
@@ -377,9 +371,39 @@ struct omap_dma_channel_params {
#endif
};
+#include <mach/dma.h>
+struct omap_dma_lch {
+ int next_lch;
+ int dev_id;
+ u16 saved_csr;
+ u16 enabled_irqs;
+ const char *dev_name;
+ void (*callback)(int lch, u16 ch_status, void *data);
+ void *data;
+ long flags;
+ /* required for Dynamic chaining */
+ int prev_linked_ch;
+ int next_linked_ch;
+ int state;
+ int chain_id;
+ int status;
+};
+
struct omap_dma_dev_attr {
u32 dev_caps;
u16 lch_count;
+ u16 chan_count;
+ struct omap_dma_lch *chan;
+};
+
+/* System DMA platform data structure */
+struct omap_system_dma_plat_info {
+ struct omap_dma_dev_attr *dma_attr;
+ void __iomem *omap_dma_base;
+ u32 errata;
+ u16 *regs;
+ void (*disable_irq_lch)(int lch);
+ void (*show_dma_caps)(void);
};
extern void omap_set_dma_priority(int lch, int dst_port, int priority);
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver
2010-10-26 13:25 ` [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver G, Manjunath Kondaiah
@ 2010-11-09 22:26 ` Kevin Hilman
2010-11-10 14:02 ` G, Manjunath Kondaiah
2010-11-09 23:29 ` Kevin Hilman
1 sibling, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 22:26 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> Convert DMA library into DMA platform driver and make use
> of platform data provided by HWMOD data base for OMAP2PLUS onwards.
> For OMAP1 processors, the DMA driver in mach-omap uses resource
> structures for getting platform data.
>
> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
[...]
> diff --git a/arch/arm/mach-omap2/include/mach/dma.h b/arch/arm/mach-omap2/include/mach/dma.h
> index d0a7d5b..d13c5c0 100644
> --- a/arch/arm/mach-omap2/include/mach/dma.h
> +++ b/arch/arm/mach-omap2/include/mach/dma.h
> @@ -29,4 +29,7 @@
> #ifndef __ASM_ARCH_OMAP2_DMA_H
> #define __ASM_ARCH_OMAP2_DMA_H
>
> +/* Should be part of hwmod data base ? */
> +#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */
> +
There are no users of this in this patch, all users are removed.
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver
2010-11-09 22:26 ` Kevin Hilman
@ 2010-11-10 14:02 ` G, Manjunath Kondaiah
2010-11-10 16:24 ` Kevin Hilman
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 14:02 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 3:56 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Shilimkar, Santosh
> Subject: Re: [PATCH v3 10/13] OMAP: DMA: Convert DMA library
> into DMA platform Driver
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
> > Convert DMA library into DMA platform driver and make use
> > of platform data provided by HWMOD data base for OMAP2PLUS onwards.
> > For OMAP1 processors, the DMA driver in mach-omap uses resource
> > structures for getting platform data.
> >
> > Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>
> [...]
>
> > diff --git a/arch/arm/mach-omap2/include/mach/dma.h
> b/arch/arm/mach-omap2/include/mach/dma.h
> > index d0a7d5b..d13c5c0 100644
> > --- a/arch/arm/mach-omap2/include/mach/dma.h
> > +++ b/arch/arm/mach-omap2/include/mach/dma.h
> > @@ -29,4 +29,7 @@
> > #ifndef __ASM_ARCH_OMAP2_DMA_H
> > #define __ASM_ARCH_OMAP2_DMA_H
> >
> > +/* Should be part of hwmod data base ? */
> > +#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /*
> REVISIT: Is this 32 + 2? */
> > +
>
> There are no users of this in this patch, all users are removed.
This macro is used in hwmod data base. Do you mean hard coding this
value in hwmod db and remove header?
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver
2010-11-10 14:02 ` G, Manjunath Kondaiah
@ 2010-11-10 16:24 ` Kevin Hilman
2010-11-10 17:23 ` G, Manjunath Kondaiah
0 siblings, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-10 16:24 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>> -----Original Message-----
>> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
>> Sent: Wednesday, November 10, 2010 3:56 AM
>> To: G, Manjunath Kondaiah
>> Cc: linux-omap at vger.kernel.org;
>> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
>> Shilimkar, Santosh
>> Subject: Re: [PATCH v3 10/13] OMAP: DMA: Convert DMA library
>> into DMA platform Driver
>>
>> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>>
>> > Convert DMA library into DMA platform driver and make use
>> > of platform data provided by HWMOD data base for OMAP2PLUS onwards.
>> > For OMAP1 processors, the DMA driver in mach-omap uses resource
>> > structures for getting platform data.
>> >
>> > Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
>> > Cc: Benoit Cousson <b-cousson@ti.com>
>> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
>> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>
>> [...]
>>
>> > diff --git a/arch/arm/mach-omap2/include/mach/dma.h
>> b/arch/arm/mach-omap2/include/mach/dma.h
>> > index d0a7d5b..d13c5c0 100644
>> > --- a/arch/arm/mach-omap2/include/mach/dma.h
>> > +++ b/arch/arm/mach-omap2/include/mach/dma.h
>> > @@ -29,4 +29,7 @@
>> > #ifndef __ASM_ARCH_OMAP2_DMA_H
>> > #define __ASM_ARCH_OMAP2_DMA_H
>> >
>> > +/* Should be part of hwmod data base ? */
>> > +#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /*
>> REVISIT: Is this 32 + 2? */
>> > +
>>
>> There are no users of this in this patch, all users are removed.
>
> This macro is used in hwmod data base. Do you mean hard coding this
> value in hwmod db and remove header?
What I mean is that from a reviewers perspective of this patch, you
added a new #define that is not used anywhere in this patch. a #define
should be added along with any users of it.
That being said, the number of channels of the DMA IP sounds like
something that should indeed be associated with the hwmod as it is a
fixed HW feature.
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver
2010-11-10 16:24 ` Kevin Hilman
@ 2010-11-10 17:23 ` G, Manjunath Kondaiah
2010-11-10 17:56 ` Kevin Hilman
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 17:23 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 9:54 PM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Shilimkar, Santosh
> Subject: Re: [PATCH v3 10/13] OMAP: DMA: Convert DMA library
> into DMA platform Driver
>
[...]
> >> > +#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /*
> >> REVISIT: Is this 32 + 2? */
> >> > +
> >>
> >> There are no users of this in this patch, all users are removed.
> >
> > This macro is used in hwmod data base. Do you mean hard coding this
> > value in hwmod db and remove header?
>
> What I mean is that from a reviewers perspective of this patch, you
> added a new #define that is not used anywhere in this patch.
> a #define
> should be added along with any users of it.
No. This macro is used in omap2+ hwmod db through plat/dma.h which includes
mach/dma.h
>
> That being said, the number of channels of the DMA IP sounds like
> something that should indeed be associated with the hwmod as it is a
> fixed HW feature.
If so, I can remove this macro and hard code in hwmod db.
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver
2010-11-10 17:23 ` G, Manjunath Kondaiah
@ 2010-11-10 17:56 ` Kevin Hilman
0 siblings, 0 replies; 50+ messages in thread
From: Kevin Hilman @ 2010-11-10 17:56 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>> >> > +#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /*
>> >> REVISIT: Is this 32 + 2? */
>> >> > +
>> >>
>> >> There are no users of this in this patch, all users are removed.
>> >
>> > This macro is used in hwmod data base. Do you mean hard coding this
>> > value in hwmod db and remove header?
>>
>> What I mean is that from a reviewers perspective of this patch, you
>> added a new #define that is not used anywhere in this patch.
>> a #define
>> should be added along with any users of it.
>
> No. This macro is used in omap2+ hwmod db through plat/dma.h which includes
> mach/dma.h
Which is not part of this patch.
Again, as a general rule, don't introduce code (#defines, headers,
functions, anything) in a patch if it is not used.
>>
>> That being said, the number of channels of the DMA IP sounds like
>> something that should indeed be associated with the hwmod as it is a
>> fixed HW feature.
>>
> If so, I can remove this macro and hard code in hwmod db.
OK, good.
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver
2010-10-26 13:25 ` [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver G, Manjunath Kondaiah
2010-11-09 22:26 ` Kevin Hilman
@ 2010-11-09 23:29 ` Kevin Hilman
2010-11-10 14:02 ` G, Manjunath Kondaiah
1 sibling, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 23:29 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> Convert DMA library into DMA platform driver and make use
> of platform data provided by HWMOD data base for OMAP2PLUS onwards.
> For OMAP1 processors, the DMA driver in mach-omap uses resource
> structures for getting platform data.
>
> Signed-off-by: G, Manjunath Kondaiah <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/dma.c | 180 ++++++++++++++++++-
> arch/arm/mach-omap2/Makefile | 2 +-
> arch/arm/mach-omap2/dma.c | 209 +++++++++++++++++++++-
> arch/arm/mach-omap2/include/mach/dma.h | 3 +
> arch/arm/plat-omap/dma.c | 321 +++++++++++---------------------
> arch/arm/plat-omap/include/plat/dma.h | 50 ++++--
> 7 files changed, 538 insertions(+), 229 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/dma.c b/arch/arm/mach-omap1/dma.c
> index e756069..38a7294 100644
> --- a/arch/arm/mach-omap1/dma.c
> +++ b/arch/arm/mach-omap1/dma.c
> @@ -35,6 +35,81 @@
> #include <plat/tc.h>
>
> #define OMAP1_DMA_BASE (0xfffed800)
> +#define OMAP1_LOGICAL_DMA_CH_COUNT 17
> +
> +static u32 errata;
> +static u32 enable_1510_mode;
> +
> +enum {
> + GCR1 = 0, GSCR, GRST, HW_ID,
> + PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
> + PCHD_ID, CAPS_0_U, CAPS_0_L, CAPS_1_U,
> + CAPS_1_L, CAPS_2, CAPS_3, CAPS_4,
> + PCH2_SR, PCH0_SR, PCH1_SR, PCHD_SR,
> +
> + CH_COMMON_START,
> +
> + /* Common Registers */
> + CSDP1, CCR1, CICR1, CSR1,
> + CEN1, CFN1, CSFI1, CSEI1,
> + CPC, CSAC1, CDAC1, CDEI1,
> + CDFI1, CLNK_CTRL1,
> +
> + /* Channel specific register offsets */
> + CSSA_L, CSSA_U, CDSA_L, CDSA_U,
> + COLOR_L, COLOR_U, CCR1_2, LCH_CTRL,
> +
> + CH_COMMON_END,
> +};
These reg_map enums are added here, then promptly moved in the following
patch. Please just put them in the right place earlier in the series.
Also, at this point, similar versions also still exist in
plat-omap/dma.c
This may be a good technique for inflating the number of lines changed
in the git history, but it is not review friendly.
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver
2010-11-09 23:29 ` Kevin Hilman
@ 2010-11-10 14:02 ` G, Manjunath Kondaiah
0 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 14:02 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 4:59 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Shilimkar, Santosh
> Subject: Re: [PATCH v3 10/13] OMAP: DMA: Convert DMA library
> into DMA platform Driver
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
[...]
> >
> > obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
> > diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
> > index e756069..38a7294 100644
> > --- a/arch/arm/mach-omap1/dma.c
> > +++ b/arch/arm/mach-omap1/dma.c
> > @@ -35,6 +35,81 @@
> > #include <plat/tc.h>
> >
> > #define OMAP1_DMA_BASE (0xfffed800)
> > +#define OMAP1_LOGICAL_DMA_CH_COUNT 17
> > +
> > +static u32 errata;
> > +static u32 enable_1510_mode;
> > +
> > +enum {
> > + GCR1 = 0, GSCR, GRST, HW_ID,
> > + PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
> > + PCHD_ID, CAPS_0_U, CAPS_0_L, CAPS_1_U,
> > + CAPS_1_L, CAPS_2, CAPS_3, CAPS_4,
> > + PCH2_SR, PCH0_SR, PCH1_SR, PCHD_SR,
> > +
> > + CH_COMMON_START,
> > +
> > + /* Common Registers */
> > + CSDP1, CCR1, CICR1, CSR1,
> > + CEN1, CFN1, CSFI1, CSEI1,
> > + CPC, CSAC1, CDAC1, CDEI1,
> > + CDFI1, CLNK_CTRL1,
> > +
> > + /* Channel specific register offsets */
> > + CSSA_L, CSSA_U, CDSA_L, CDSA_U,
> > + COLOR_L, COLOR_U, CCR1_2, LCH_CTRL,
> > +
> > + CH_COMMON_END,
> > +};
>
> These reg_map enums are added here, then promptly moved in
> the following
> patch. Please just put them in the right place earlier in the series.
> Also, at this point, similar versions also still exist in
> plat-omap/dma.c
>
> This may be a good technique for inflating the number of lines changed
> in the git history, but it is not review friendly.
Thanks. With Tony's suggestion, these duplicate enums will not exist with
next version since there will be common enum in plat-omap from patch-1 of
the series. only reg_map tables will be moved to respective mach-omap dma
files from plat-omap.
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 11/13] OMAP: DMA: Use DMA device attributes
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (9 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 10/13] OMAP: DMA: Convert DMA library into DMA platform Driver G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 12/13] OMAP2+: DMA: descriptor autoloading feature G, Manjunath Kondaiah
` (3 subsequent siblings)
14 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Existing DMA API's are using cpu_*is_* checks for differentiating
omap1 and omap2plus code.
Replace cpu_*is_* checks with DMA device attributes and
also move API's which are OMAP1 and OMAP2plus specific into respective
mach-omap dma driver files.
Signed-off-by: G, Manjunath Kondaiah <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 | 385 ++++++-
arch/arm/mach-omap1/include/mach/dma.h | 22 +
arch/arm/mach-omap2/dma.c | 1099 ++++++++++++++++++-
arch/arm/mach-omap2/include/mach/dma.h | 51 +
arch/arm/plat-omap/dma.c | 1872 +++-----------------------------
arch/arm/plat-omap/include/plat/dma.h | 77 +-
6 files changed, 1670 insertions(+), 1836 deletions(-)
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 38a7294..d373458 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -36,34 +36,16 @@
#define OMAP1_DMA_BASE (0xfffed800)
#define OMAP1_LOGICAL_DMA_CH_COUNT 17
+#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
static u32 errata;
static u32 enable_1510_mode;
-enum {
- GCR1 = 0, GSCR, GRST, HW_ID,
- PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
- PCHD_ID, CAPS_0_U, CAPS_0_L, CAPS_1_U,
- CAPS_1_L, CAPS_2, CAPS_3, CAPS_4,
- PCH2_SR, PCH0_SR, PCH1_SR, PCHD_SR,
-
- CH_COMMON_START,
-
- /* Common Registers */
- CSDP1, CCR1, CICR1, CSR1,
- CEN1, CFN1, CSFI1, CSEI1,
- CPC, CSAC1, CDAC1, CDEI1,
- CDFI1, CLNK_CTRL1,
-
- /* Channel specific register offsets */
- CSSA_L, CSSA_U, CDSA_L, CDSA_U,
- COLOR_L, COLOR_U, CCR1_2, LCH_CTRL,
-
- CH_COMMON_END,
-};
+static struct omap_dma_lch *dma_chan;
+static struct omap_dma_dev_attr *d;
static u16 reg_map[] = {
- [GCR1] = 0x400,
+ [GCR] = 0x400,
[GSCR] = 0x404,
[GRST] = 0x408,
[HW_ID] = 0x442,
@@ -85,20 +67,20 @@ static u16 reg_map[] = {
[PCHD_SR] = 0x4c0,
/* Common Registers */
- [CSDP1] = 0x00,
- [CCR1] = 0x02,
- [CICR1] = 0x04,
- [CSR1] = 0x06,
- [CEN1] = 0x10,
- [CFN1] = 0x12,
- [CSFI1] = 0x14,
- [CSEI1] = 0x16,
+ [CSDP] = 0x00,
+ [CCR] = 0x02,
+ [CICR] = 0x04,
+ [CSR] = 0x06,
+ [CEN] = 0x10,
+ [CFN] = 0x12,
+ [CSFI] = 0x14,
+ [CSEI] = 0x16,
[CPC] = 0x18, /* 15xx only */
- [CSAC1] = 0x18,
- [CDAC1] = 0x1a,
- [CDEI1] = 0x1c,
- [CDFI1] = 0x1e,
- [CLNK_CTRL1] = 0x28,
+ [CSAC] = 0x18,
+ [CDAC] = 0x1a,
+ [CDEI] = 0x1c,
+ [CDFI] = 0x1e,
+ [CLNK_CTRL] = 0x28,
/* Channel specific register offsets */
[CSSA_L] = 0x08,
@@ -107,7 +89,7 @@ static u16 reg_map[] = {
[CDSA_U] = 0x0e,
[COLOR_L] = 0x20,
[COLOR_U] = 0x22,
- [CCR1_2] = 0x24,
+ [CCR2] = 0x24,
[LCH_CTRL] = 0x2a,
};
@@ -222,6 +204,195 @@ static inline u16 dma_read(int reg, int lch)
return __raw_readw(dma_base + reg_map[reg]);
}
+static void
+set_src_params(int lch, unsigned long src_start, int src_ei, int src_fi)
+{
+ dma_write(src_start >> 16, CSSA_U, lch);
+ dma_write((u16)src_start, CSSA_L, lch);
+
+ dma_write(src_ei, CSEI, lch);
+ dma_write(src_fi, CSFI, lch);
+}
+
+static void set_dest_params(int lch, unsigned long dest_start, int dst_ei,
+ int dst_fi)
+{
+ dma_write(dest_start >> 16, CDSA_U, lch);
+ dma_write(dest_start, CDSA_L, lch);
+
+ dma_write(dst_ei, CDEI, lch);
+ dma_write(dst_fi, CDFI, lch);
+}
+
+static inline void omap1_enable_channel_irq(int lch)
+{
+ u32 status;
+
+ /* Clear CSR */
+ status = dma_read(CSR, lch);
+ dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
+}
+
+static void omap1_disable_channel_irq(int lch)
+{
+ dma_write(0, CICR, lch);
+}
+
+static inline void omap1_enable_lnk(int lch)
+{
+ u32 l;
+
+ l = dma_read(CLNK_CTRL, lch);
+ l &= ~(1 << 14);
+
+ /* Set the ENABLE_LNK bits */
+ if (dma_chan[lch].next_lch != -1)
+ l = dma_chan[lch].next_lch | (1 << 15);
+
+ dma_write(l, CLNK_CTRL, lch);
+}
+
+static inline void omap1_disable_lnk(int lch)
+{
+ u32 l;
+
+ /* Disable interrupts */
+ l = dma_read(CLNK_CTRL, lch);
+ dma_write(0, CICR, lch);
+ /* Set the STOP_LNK bit */
+ l |= 1 << 14;
+ dma_write(l, CLNK_CTRL, lch);
+
+ dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+}
+
+static dma_addr_t get_src_pos(int lch)
+{
+ dma_addr_t offset = 0;
+
+ if (enable_1510_mode)
+ offset = dma_read(CPC, lch);
+ else
+ offset = dma_read(CSAC, lch);
+
+ if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
+ offset = dma_read(CSAC, lch);
+
+ offset |= (dma_read(CSSA_U, lch) << 16);
+
+ return offset;
+}
+
+static dma_addr_t get_dst_pos(int lch)
+{
+ dma_addr_t offset = 0;
+
+ if (enable_1510_mode)
+ offset = dma_read(CPC, lch);
+ else
+ offset = dma_read(CDAC, lch);
+
+ if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
+ offset = dma_read(CDAC, lch);
+
+ offset |= (dma_read(CDSA_U, lch) << 16);
+
+ return offset;
+}
+
+static void
+set_transfer_params(int lch, int data_type, int sync_mode, int dma_trigger,
+ int src_or_dst_synch)
+{
+ u16 ccr;
+ u32 l;
+
+ l = dma_read(CSDP, lch);
+ l &= ~0x03;
+ l |= data_type;
+ dma_write(l, CSDP, lch);
+
+ ccr = dma_read(CCR, lch);
+ ccr &= ~(1 << 5);
+ if (sync_mode == OMAP_DMA_SYNC_FRAME)
+ ccr |= 1 << 5;
+ dma_write(ccr, CCR, lch);
+
+ ccr = dma_read(CCR2, lch);
+ ccr &= ~(1 << 2);
+ if (sync_mode == OMAP_DMA_SYNC_BLOCK)
+ ccr |= 1 << 2;
+ dma_write(ccr, CCR2, lch);
+}
+
+static void cpc_cdac_init(int lch)
+{
+ if (enable_1510_mode)
+ dma_write(0, CPC, lch);
+ else
+ dma_write(0, CDAC, lch);
+}
+
+static void omap1_clear_lch_regs(int lch)
+{
+ int i = CH_COMMON_START + 1;
+
+ for (; i <= CH_COMMON_END; i += 1)
+ dma_write(0, i, lch);
+}
+
+static inline int omap1_get_gdma_dev(int req)
+{
+ u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
+ int shift = ((req - 1) % 5) * 6;
+
+ return ((omap_readl(reg) >> shift) & 0x3f) + 1;
+}
+
+static inline void omap1_set_gdma_dev(int req, int dev)
+{
+ u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
+ int shift = ((req - 1) % 5) * 6;
+ u32 l;
+
+ l = omap_readl(reg);
+ l &= ~(0x3f << shift);
+ l |= (dev - 1) << shift;
+ omap_writel(l, reg);
+}
+
+static void set_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
+{
+ u16 w;
+
+ w = dma_read(CCR2, lch);
+ w &= ~0x03;
+
+ switch (mode) {
+ case OMAP_DMA_CONSTANT_FILL:
+ w |= 0x01;
+ break;
+ case OMAP_DMA_TRANSPARENT_COPY:
+ w |= 0x02;
+ break;
+ case OMAP_DMA_COLOR_DIS:
+ break;
+ default:
+ BUG();
+ }
+ dma_write(w, CCR2, lch);
+
+ w = dma_read(LCH_CTRL, lch);
+ w &= ~0x0f;
+ /* Default is channel type 2D */
+ if (mode) {
+ dma_write((u16)color, COLOR_L, lch);
+ dma_write((u16)(color >> 16), COLOR_U, lch);
+ w |= 1; /* Channel type G */
+ }
+ dma_write(w, LCH_CTRL, lch);
+}
+
static void omap1_show_dma_caps(void)
{
if (enable_1510_mode) {
@@ -259,12 +430,93 @@ static u32 configure_dma_errata(void)
return errata;
}
+static int omap1_dma_handle_ch(int ch)
+{
+ u32 csr;
+
+ if (enable_1510_mode && ch >= 6) {
+ csr = dma_chan[ch].saved_csr;
+ dma_chan[ch].saved_csr = 0;
+ } else
+ csr = dma_read(CSR, ch);
+ if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
+ dma_chan[ch + 6].saved_csr = csr >> 7;
+ csr &= 0x7f;
+ }
+ if ((csr & 0x3f) == 0)
+ return 0;
+ if (unlikely(dma_chan[ch].dev_id == -1)) {
+ printk(KERN_WARNING "Spurious interrupt from DMA channel "
+ "%d (CSR %04x)\n", ch, csr);
+ return 0;
+ }
+ if (unlikely(csr & OMAP1_DMA_TOUT_IRQ))
+ printk(KERN_WARNING "DMA timeout with device %d\n",
+ dma_chan[ch].dev_id);
+ if (unlikely(csr & OMAP_DMA_DROP_IRQ))
+ printk(KERN_WARNING "DMA synchronization event drop occurred "
+ "with device %d\n", dma_chan[ch].dev_id);
+ if (likely(csr & OMAP_DMA_BLOCK_IRQ))
+ dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
+ if (likely(dma_chan[ch].callback != NULL))
+ dma_chan[ch].callback(ch, csr, dma_chan[ch].data);
+
+ return 1;
+}
+
+static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
+{
+ int ch = ((int) dev_id) - 1;
+ int handled = 0;
+
+ for (;;) {
+ int handled_now = 0;
+
+ handled_now += omap1_dma_handle_ch(ch);
+ if (enable_1510_mode && dma_chan[ch + 6].saved_csr)
+ handled_now += omap1_dma_handle_ch(ch + 6);
+ if (!handled_now)
+ break;
+ handled += handled_now;
+ }
+
+ return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
+{
+ if (!(d->dev_caps & ENABLE_1510_MODE)) {
+ u32 l;
+
+ l = dma_read(LCH_CTRL, lch);
+ l &= ~0x7;
+ l |= mode;
+ dma_write(l, LCH_CTRL, lch);
+ }
+}
+EXPORT_SYMBOL(omap_set_dma_channel_mode);
+
+void omap_set_dma_src_index(int lch, int eidx, int fidx)
+{
+ dma_write(eidx, CSEI, lch);
+ dma_write(fidx, CSFI, lch);
+}
+EXPORT_SYMBOL(omap_set_dma_src_index);
+
+void omap_set_dma_dest_index(int lch, int eidx, int fidx)
+{
+ dma_write(eidx, CDEI, lch);
+ dma_write(fidx, CDFI, lch);
+}
+EXPORT_SYMBOL(omap_set_dma_dest_index);
+
static int __init omap1_system_dma_init(void)
{
struct omap_system_dma_plat_info *p;
- struct omap_dma_dev_attr *d;
struct platform_device *pdev;
- int ret;
+ int ret, ch, irq_rel;
+ char irq_name[4];
+ int dma_irq = 0;
pdev = platform_device_alloc("omap_dma_system", 0);
if (!pdev) {
@@ -287,8 +539,8 @@ static int __init omap1_system_dma_init(void)
ret = -ENOMEM;
goto exit_device_put;
}
-
d = p->dma_attr;
+
d->chan = kzalloc(sizeof(struct omap_dma_lch) *
(d->lch_count), GFP_KERNEL);
if (!d->chan) {
@@ -321,10 +573,51 @@ static int __init omap1_system_dma_init(void)
d->chan_count = 9;
}
+ for (ch = 0; ch < d->chan_count; ch++) {
+ if (ch >= 6 && enable_1510_mode)
+ continue;
+
+ sprintf(&irq_name[0], "%d", ch);
+ dma_irq = platform_get_irq_byname(pdev, irq_name);
+ if (dma_irq < 0) {
+ dev_err(&pdev->dev, "%s:unable to get irq\n",
+ __func__);
+ ret = dma_irq;
+ goto exit_release_irq;
+ }
+
+ ret = request_irq(dma_irq, omap1_dma_irq_handler, 0, "DMA",
+ (void *) (ch + 1));
+ if (ret != 0)
+ goto exit_release_irq;
+ }
+
p->omap_dma_base = (void __iomem *)res[0].start;
dma_base = p->omap_dma_base;
p->show_dma_caps = omap1_show_dma_caps;
+ p->enable_channel_irq = omap1_enable_channel_irq;
+ p->disable_channel_irq = omap1_disable_channel_irq;
+ p->enable_lnk = omap1_enable_lnk;
+ p->disable_lnk = omap1_disable_lnk;
+ p->clear_lch_regs = omap1_clear_lch_regs;
+ p->set_transfer_params = set_transfer_params;
+ p->set_color_mode = set_color_mode;
+ p->set_src_params = set_src_params;
+ p->set_dest_params = set_dest_params;
+ p->get_src_pos = get_src_pos;
+ p->get_dst_pos = get_dst_pos;
+ p->cpc_cdac_init = cpc_cdac_init;
+
+ if (cpu_is_omap16xx()) {
+ p->get_gdma_dev = omap1_get_gdma_dev;
+ p->set_gdma_dev = omap1_set_gdma_dev;
+ }
+
+ p->enable_irq_lch = NULL;
+ p->disable_irq_lch = NULL;
+ p->clear_channel_int = NULL;
+ p->set_global_params = NULL;
p->disable_irq_lch = NULL;
/* Configure errata handling for all omap1+ */
@@ -342,14 +635,28 @@ static int __init omap1_system_dma_init(void)
__func__, pdev->name, pdev->id);
goto exit_release_chan;
}
+ dma_chan = d->chan;
return ret;
exit_release_chan:
kfree(d->chan);
+
+exit_release_irq:
+ 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));
+ }
+
exit_release_p:
kfree(p);
+
exit_device_put:
platform_device_put(pdev);
+
exit_device_del:
platform_device_del(pdev);
diff --git a/arch/arm/mach-omap1/include/mach/dma.h b/arch/arm/mach-omap1/include/mach/dma.h
index 7949e3f..2ad11ff 100644
--- a/arch/arm/mach-omap1/include/mach/dma.h
+++ b/arch/arm/mach-omap1/include/mach/dma.h
@@ -26,4 +26,26 @@
#ifndef __ASM_ARCH_OMAP1_DMA_H
#define __ASM_ARCH_OMAP1_DMA_H
+enum {
+ GCR = 0, GSCR, GRST, HW_ID,
+ PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
+ PCHD_ID, CAPS_0_U, CAPS_0_L, CAPS_1_U,
+ CAPS_1_L, CAPS_2, CAPS_3, CAPS_4,
+ PCH2_SR, PCH0_SR, PCH1_SR, PCHD_SR,
+
+ CH_COMMON_START,
+
+ /* Common Registers */
+ CSDP, CCR, CICR, CSR,
+ CEN, CFN, CSFI, CSEI,
+ CPC, CSAC, CDAC, CDEI,
+ CDFI, CLNK_CTRL,
+
+ /* Channel specific register offsets */
+ CSSA_L, CSSA_U, CDSA_L, CDSA_U,
+ COLOR_L, COLOR_U, CCR2, LCH_CTRL,
+
+ CH_COMMON_END,
+};
+
#endif /* __ASM_ARCH_OMAP1_DMA_H */
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 5ca519b..6df4835 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -40,35 +40,71 @@
#include <plat/dma.h>
static u32 errata;
+static int dma_chan_count;
+
static struct omap_dma_dev_attr *d;
+static struct dma_link_info *dma_linked_lch;
+static struct omap_dma_lch *dma_chan;
+static struct platform_device *pd;
-enum {
- REVISION = 0, GCR2, IRQSTATUS_L0, IRQSTATUS_L1,
- IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0, IRQENABLE_L1,
- IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS, OCP_SYSCONFIG,
- CAPS_0, CAPS_2, CAPS_3, CAPS_4,
+/* 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)
- CH_COMMON_START,
+#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)
- /* Common register offsets */
- CCR2, CLNK_CTRL2, CICR2, CSR2,
- CSDP2, CEN2, CFN2, CSEI2,
- CSFI2, CDEI2, CDFI2, CSAC2,
- CDAC2,
+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
+};
- /* Channel specific register offsets */
- CSSA, CDSA, CCEN, CCFN,
- COLOR,
+enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
- /* OMAP4 specific registers */
- CDP, CNDP, CCDN,
+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;
- CH_COMMON_END,
};
+static struct omap_dma_global_context_registers {
+ u32 dma_irqenable_l0;
+ u32 dma_gcr;
+} omap_dma_global_context;
+
static u16 reg_map[] = {
[REVISION] = 0x00,
- [GCR2] = 0x78,
+ [GCR] = 0x78,
[IRQSTATUS_L0] = 0x08,
[IRQSTATUS_L1] = 0x0c,
[IRQSTATUS_L2] = 0x10,
@@ -85,19 +121,19 @@ static u16 reg_map[] = {
[CAPS_4] = 0x74,
/* Common register offsets */
- [CCR2] = 0x80,
- [CLNK_CTRL2] = 0x84,
- [CICR2] = 0x88,
- [CSR2] = 0x8c,
- [CSDP2] = 0x90,
- [CEN2] = 0x94,
- [CFN2] = 0x98,
- [CSEI2] = 0xa4,
- [CSFI2] = 0xa8,
- [CDEI2] = 0xac,
- [CDFI2] = 0xb0,
- [CSAC2] = 0xb4,
- [CDAC2] = 0xb8,
+ [CCR] = 0x80,
+ [CLNK_CTRL] = 0x84,
+ [CICR] = 0x88,
+ [CSR] = 0x8c,
+ [CSDP] = 0x90,
+ [CEN] = 0x94,
+ [CFN] = 0x98,
+ [CSEI] = 0xa4,
+ [CSFI] = 0xa8,
+ [CDEI] = 0xac,
+ [CDFI] = 0xb0,
+ [CSAC] = 0xb4,
+ [CDAC] = 0xb8,
/* Channel specific register offsets */
[CSSA] = 0x9c,
@@ -137,7 +173,16 @@ static inline u32 dma_read(int reg, int lch)
return __raw_readl(dma_base + reg_map[reg]);
}
-static inline void disable_irq_lch(int lch)
+static inline void omap2_enable_irq_lch(int lch)
+{
+ u32 val;
+
+ val = dma_read(IRQENABLE_L0, lch);
+ val |= 1 << lch;
+ dma_write(val, IRQENABLE_L0, lch);
+}
+
+static inline void omap2_disable_irq_lch(int lch)
{
u32 val;
@@ -146,6 +191,336 @@ static inline void disable_irq_lch(int lch)
dma_write(val, IRQENABLE_L0, lch);
}
+static inline void omap2_clear_channel_interrupt(int lch)
+{
+ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+ dma_write(1 << lch, IRQSTATUS_L0, lch);
+}
+
+static inline void omap2_enable_channel_irq(int lch)
+{
+ /* Clear CSR */
+ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
+
+ dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
+}
+
+static void omap2_disable_channel_irq(int lch)
+{
+ dma_write(0, CICR, lch);
+}
+
+static inline void omap2_enable_lnk(int lch)
+{
+ u32 l;
+
+ l = dma_read(CLNK_CTRL, lch);
+
+ /* Set the ENABLE_LNK bits */
+ if (dma_chan[lch].next_lch != -1)
+ l = dma_chan[lch].next_lch | (1 << 15);
+
+ if (dma_chan[lch].next_linked_ch != -1)
+ l = dma_chan[lch].next_linked_ch | (1 << 15);
+
+ dma_write(l, CLNK_CTRL, lch);
+}
+
+static inline void omap2_disable_lnk(int lch)
+{
+ u32 l;
+
+ l = dma_read(CLNK_CTRL, lch);
+
+ omap2_disable_channel_irq(lch);
+ /* Clear the ENABLE_LNK bit */
+ l &= ~(1 << 15);
+
+ dma_write(l, CLNK_CTRL, lch);
+ dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+}
+
+static void
+omap2_set_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
+{
+ u32 val;
+
+ val = dma_read(CCR, lch);
+ val &= ~((1 << 17) | (1 << 16));
+
+ switch (mode) {
+ case OMAP_DMA_CONSTANT_FILL:
+ val |= 1 << 16;
+ break;
+ case OMAP_DMA_TRANSPARENT_COPY:
+ val |= 1 << 17;
+ break;
+ case OMAP_DMA_COLOR_DIS:
+ break;
+ default:
+ BUG();
+ }
+ dma_write(val, CCR, lch);
+
+ color &= 0xffffff;
+ dma_write(color, COLOR, lch);
+}
+
+void omap_dma_global_context_save(void)
+{
+ omap_dma_global_context.dma_irqenable_l0 =
+ dma_read(IRQENABLE_L0, 0);
+
+ omap_dma_global_context.dma_gcr = dma_read(GCR, 0);
+}
+
+void omap_dma_global_context_restore(void)
+{
+ int ch;
+
+ dma_write(omap_dma_global_context.dma_gcr, GCR, 0);
+
+ dma_write(omap_dma_global_context.dma_irqenable_l0,
+ IRQENABLE_L0, 0);
+
+ /*
+ * 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, 0);
+
+ for (ch = 0; ch < dma_chan_count; ch++)
+ if (dma_chan[ch].dev_id != -1)
+ omap_clear_dma(ch);
+}
+
+void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
+{
+ u32 csdp;
+
+ csdp = dma_read(CSDP, lch);
+ csdp &= ~(0x3 << 16);
+ csdp |= (mode << 16);
+ dma_write(csdp, CSDP, lch);
+}
+EXPORT_SYMBOL(omap_set_dma_write_mode);
+
+/**
+ * @brief omap_dma_set_global_params : Set global priority settings for dma
+ *
+ * @param arb_rate
+ * @param max_fifo_depth
+ * @param tparams - Number of threads to reserve:
+ * DMA_THREAD_RESERVE_NORM
+ * DMA_THREAD_RESERVE_ONET
+ * DMA_THREAD_RESERVE_TWOT
+ * DMA_THREAD_RESERVE_THREET
+ */
+void
+omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
+{
+ u32 reg;
+
+ if (max_fifo_depth == 0)
+ max_fifo_depth = 1;
+ if (arb_rate == 0)
+ arb_rate = 1;
+
+ reg = 0xff & max_fifo_depth;
+ reg |= (0x3 & tparams) << 12;
+ reg |= (arb_rate & 0xff) << 16;
+
+ dma_write(reg, GCR, 0);
+}
+EXPORT_SYMBOL(omap_dma_set_global_params);
+
+static int omap2_dma_handle_ch(int ch)
+{
+ u32 status = dma_read(CSR, ch);
+
+ if (!status) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
+ ch);
+ dma_write(1 << ch, IRQSTATUS_L0, ch);
+ return 0;
+ }
+ if (unlikely(dma_chan[ch].dev_id == -1)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING "IRQ %04x for non-allocated DMA"
+ "channel %d\n", status, ch);
+ return 0;
+ }
+ if (unlikely(status & OMAP_DMA_DROP_IRQ))
+ printk(KERN_INFO
+ "DMA synchronization event drop occurred with device "
+ "%d\n", dma_chan[ch].dev_id);
+ if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
+ printk(KERN_INFO "DMA transaction error with device %d\n",
+ dma_chan[ch].dev_id);
+ if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
+ u32 ccr;
+
+ ccr = dma_read(CCR, ch);
+ ccr &= ~OMAP_DMA_CCR_EN;
+ dma_write(ccr, CCR, ch);
+ dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
+ }
+ }
+ if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ))
+ printk(KERN_INFO "DMA secure error with device %d\n",
+ dma_chan[ch].dev_id);
+ if (unlikely(status & OMAP2_DMA_MISALIGNED_ERR_IRQ))
+ printk(KERN_INFO "DMA misaligned error with device %d\n",
+ dma_chan[ch].dev_id);
+
+ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
+ dma_write(1 << ch, IRQSTATUS_L0, ch);
+
+ /* If the ch is not chained then chain_id will be -1 */
+ if (dma_chan[ch].chain_id != -1) {
+ int chain_id = dma_chan[ch].chain_id;
+ dma_chan[ch].state = DMA_CH_NOTSTARTED;
+ if (dma_read(CLNK_CTRL, ch) & (1 << 15))
+ dma_chan[dma_chan[ch].next_linked_ch].state =
+ DMA_CH_STARTED;
+ if (dma_linked_lch[chain_id].chain_mode ==
+ OMAP_DMA_DYNAMIC_CHAIN)
+ omap2_disable_lnk(ch);
+
+ if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
+ OMAP_DMA_CHAIN_INCQHEAD(chain_id);
+
+ status = dma_read(CSR, ch);
+ }
+
+ dma_write(status, CSR, ch);
+
+ if (likely(dma_chan[ch].callback != NULL))
+ dma_chan[ch].callback(ch, status, dma_chan[ch].data);
+
+ return 0;
+}
+
+/* STATUS register count is from 1-32 while our is 0-31 */
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+ u32 val, enable_reg;
+ int i;
+
+ val = dma_read(IRQSTATUS_L0, 0);
+ if (val == 0) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING "Spurious DMA IRQ\n");
+ return IRQ_HANDLED;
+ }
+ enable_reg = dma_read(IRQENABLE_L0, 0);
+ val &= enable_reg; /* Dispatch only relevant interrupts */
+ for (i = 0; i < dma_chan_count && val != 0; i++) {
+ if (val & 1)
+ omap2_dma_handle_ch(i);
+ val >>= 1;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap24xx_dma_irq = {
+ .name = "DMA",
+ .handler = irq_handler,
+ .flags = IRQF_DISABLED
+};
+
+static void omap2_set_transfer_params(int lch, int data_type, int sync_mode,
+ int dma_trigger, int src_or_dst_synch)
+{
+ u32 val, l;
+
+ l = dma_read(CSDP, lch);
+ l &= ~0x03;
+ l |= data_type;
+ dma_write(l, CSDP, lch);
+
+ if (dma_trigger) {
+ val = dma_read(CCR, lch);
+
+ /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
+ val &= ~((1 << 23) | (3 << 19) | 0x1f);
+ val |= (dma_trigger & ~0x1f) << 14;
+ val |= dma_trigger & 0x1f;
+
+ if (sync_mode & OMAP_DMA_SYNC_FRAME)
+ val |= 1 << 5;
+ else
+ val &= ~(1 << 5);
+
+ if (sync_mode & OMAP_DMA_SYNC_BLOCK)
+ val |= 1 << 18;
+ else
+ val &= ~(1 << 18);
+
+ if (src_or_dst_synch == OMAP_DMA_DST_SYNC_PREFETCH) {
+ val &= ~(1 << 24); /* dest synch */
+ val |= (1 << 23); /* Prefetch */
+ } else if (src_or_dst_synch) {
+ val |= 1 << 24; /* source synch */
+ } else {
+ val &= ~(1 << 24); /* dest synch */
+ }
+ dma_write(val, CCR, lch);
+ }
+}
+
+static void omap2_set_src_params(int lch, unsigned long src_start, int src_ei,
+ int src_fi)
+{
+ dma_write(src_start, CSSA, lch);
+
+ dma_write(src_ei, CSEI, lch);
+ dma_write(src_fi, CSFI, lch);
+}
+
+static void omap2_set_dest_params(int lch, unsigned long dest_start, int dst_ei,
+ int dst_fi)
+{
+ dma_write(dest_start, CDSA, lch);
+
+ dma_write(dst_ei, CDEI, lch);
+ dma_write(dst_fi, CDFI, lch);
+}
+
+static dma_addr_t omap2_set_src_pos(int lch)
+{
+ dma_addr_t offset = 0;
+
+ offset = dma_read(CSAC, lch);
+
+ if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
+ offset = dma_read(CSAC, lch);
+
+ return offset;
+}
+
+static dma_addr_t omap2_get_dst_pos(int lch)
+{
+ dma_addr_t offset = 0;
+
+ offset = dma_read(CDAC, lch);
+
+ if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && (offset == 0))
+ offset = dma_read(CDAC, lch);
+
+ return offset;
+}
+
+static void omap2_cpc_cdac_init(int lch)
+{
+ dma_write(0, CDAC, lch);
+}
+
static void omap2_show_dma_caps(void)
{
u8 revision = dma_read(REVISION, 0) & 0xff;
@@ -225,12 +600,620 @@ static u32 configure_dma_errata(void)
return errata;
}
+/* Create chain of DMA channesls */
+static void create_dma_lch_chain(int lch_head, int lch_queue)
+{
+ u32 l;
+
+ /* Check if this is the first link in chain */
+ if (dma_chan[lch_head].next_linked_ch == -1) {
+ dma_chan[lch_head].next_linked_ch = lch_queue;
+ dma_chan[lch_head].prev_linked_ch = lch_queue;
+ dma_chan[lch_queue].next_linked_ch = lch_head;
+ dma_chan[lch_queue].prev_linked_ch = lch_head;
+ }
+
+ /* a link exists, link the new channel in circular chain */
+ else {
+ dma_chan[lch_queue].next_linked_ch =
+ dma_chan[lch_head].next_linked_ch;
+ dma_chan[lch_queue].prev_linked_ch = lch_head;
+ dma_chan[lch_head].next_linked_ch = lch_queue;
+ dma_chan[dma_chan[lch_queue].next_linked_ch].prev_linked_ch =
+ lch_queue;
+ }
+
+ l = dma_read(CLNK_CTRL, lch_head);
+ l &= ~(0x1f);
+ l |= lch_queue;
+ dma_write(l, CLNK_CTRL, lch_head);
+
+ l = dma_read(CLNK_CTRL, lch_queue);
+ l &= ~(0x1f);
+ l |= (dma_chan[lch_queue].next_linked_ch);
+ dma_write(l, CLNK_CTRL, lch_queue);
+}
+
+/**
+ * @brief omap_request_dma_chain : Request a chain of DMA channels
+ *
+ * @param dev_id - Device id using the dma channel
+ * @param dev_name - Device name
+ * @param callback - Call back function
+ * @chain_id -
+ * @no_of_chans - Number of channels requested
+ * @chain_mode - Dynamic or static chaining : OMAP_DMA_STATIC_CHAIN
+ * OMAP_DMA_DYNAMIC_CHAIN
+ * @params - Channel parameters
+ *
+ * @return - Success : 0
+ * Failure: -EINVAL/-ENOMEM
+ */
+int omap_request_dma_chain(int dev_id, const char *dev_name,
+ void (*callback) (int lch, u16 ch_status,
+ void *data),
+ int *chain_id, int no_of_chans, int chain_mode,
+ struct omap_dma_channel_params params)
+{
+ int *channels;
+ int i, err;
+
+ /* Is the chain mode valid ? */
+ if (chain_mode != OMAP_DMA_STATIC_CHAIN
+ && chain_mode != OMAP_DMA_DYNAMIC_CHAIN) {
+ printk(KERN_ERR "Invalid chain mode requested\n");
+ return -EINVAL;
+ }
+
+ if (unlikely((no_of_chans < 1
+ || no_of_chans > dma_chan_count))) {
+ printk(KERN_ERR "Invalid Number of channels requested\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Allocate a queue to maintain the status of the channels
+ * in the chain
+ */
+ channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL);
+ if (channels == NULL) {
+ printk(KERN_ERR "omap_dma: No memory for channel queue\n");
+ return -ENOMEM;
+ }
+
+ /* request and reserve DMA channels for the chain */
+ for (i = 0; i < no_of_chans; i++) {
+ err = omap_request_dma(dev_id, dev_name,
+ callback, NULL, &channels[i]);
+ if (err < 0) {
+ int j;
+ for (j = 0; j < i; j++)
+ omap_free_dma(channels[j]);
+ kfree(channels);
+ printk(KERN_ERR "omap_dma: Request failed %d\n", err);
+ return err;
+ }
+ dma_chan[channels[i]].prev_linked_ch = -1;
+ dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+
+ /*
+ * Allowing client drivers to set common parameters now,
+ * so that later only relevant (src_start, dest_start
+ * and element count) can be set
+ */
+ omap_set_dma_params(channels[i], ¶ms);
+ }
+
+ *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], ¶ms);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_modify_dma_chain_params);
+
+/**
+ * @brief omap_free_dma_chain - Free all the logical channels in a chain.
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ * Failure : -EINVAL
+ */
+int omap_free_dma_chain(int chain_id)
+{
+ int *channels;
+ u32 i;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+ for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
+ dma_chan[channels[i]].next_linked_ch = -1;
+ dma_chan[channels[i]].prev_linked_ch = -1;
+ dma_chan[channels[i]].chain_id = -1;
+ dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+ omap_free_dma(channels[i]);
+ }
+
+ kfree(channels);
+
+ dma_linked_lch[chain_id].linked_dmach_q = NULL;
+ dma_linked_lch[chain_id].chain_mode = -1;
+ dma_linked_lch[chain_id].chain_state = -1;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_free_dma_chain);
+
+/**
+ * @brief omap_dma_chain_status - Check if the chain is in
+ * active / inactive state.
+ * @param chain_id
+ *
+ * @return - Success : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ * Failure : -EINVAL
+ */
+int omap_dma_chain_status(int chain_id)
+{
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+ pr_debug("CHAINID=%d, qcnt=%d\n", chain_id,
+ dma_linked_lch[chain_id].q_count);
+
+ if (OMAP_DMA_CHAIN_QEMPTY(chain_id))
+ return OMAP_DMA_CHAIN_INACTIVE;
+
+ return OMAP_DMA_CHAIN_ACTIVE;
+}
+EXPORT_SYMBOL(omap_dma_chain_status);
+
+/**
+ * @brief omap_dma_chain_a_transfer - Get a free channel from a chain,
+ * set the params and start the transfer.
+ *
+ * @param chain_id
+ * @param src_start - buffer start address
+ * @param dest_start - Dest address
+ * @param elem_count
+ * @param frame_count
+ * @param callbk_data - channel callback parameter data.
+ *
+ * @return - Success : 0
+ * Failure: -EINVAL/-EBUSY
+ */
+int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
+ int elem_count, int frame_count, void *callbk_data)
+{
+ int *channels;
+ u32 l, lch;
+ int start_dma = 0;
+
+ /*
+ * if buffer size is less than 1 then there is
+ * no use of starting the chain
+ */
+ if (elem_count < 1) {
+ printk(KERN_ERR "Invalid buffer size\n");
+ return -EINVAL;
+ }
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0
+ || chain_id >= dma_chan_count))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exist\n");
+ return -EINVAL;
+ }
+
+ /* Check if all the channels in chain are in use */
+ if (OMAP_DMA_CHAIN_QFULL(chain_id))
+ return -EBUSY;
+
+ /* Frame count may be negative in case of indexed transfers */
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* Get a free channel */
+ lch = channels[dma_linked_lch[chain_id].q_tail];
+
+ /* Store the callback data */
+ dma_chan[lch].data = callbk_data;
+
+ /* Increment the q_tail */
+ OMAP_DMA_CHAIN_INCQTAIL(chain_id);
+
+ /* Set the params to the free channel */
+ if (src_start != 0)
+ dma_write(src_start, CSSA, lch);
+ if (dest_start != 0)
+ dma_write(dest_start, CDSA, lch);
+
+ /* Write the buffer size */
+ dma_write(elem_count, CEN, lch);
+ dma_write(frame_count, CFN, lch);
+
+ /*
+ * If the chain is dynamically linked,
+ * then we may have to start the chain if its not active
+ */
+ if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) {
+
+ /*
+ * In Dynamic chain, if the chain is not started,
+ * queue the channel
+ */
+ if (dma_linked_lch[chain_id].chain_state ==
+ DMA_CHAIN_NOTSTARTED) {
+ /* Enable the link in previous channel */
+ if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
+ DMA_CH_QUEUED)
+ omap2_enable_lnk(dma_chan[lch].prev_linked_ch);
+ dma_chan[lch].state = DMA_CH_QUEUED;
+ }
+
+ /*
+ * Chain is already started, make sure its active,
+ * if not then start the chain
+ */
+ else {
+ start_dma = 1;
+
+ if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
+ DMA_CH_STARTED) {
+ omap2_enable_lnk(dma_chan[lch].prev_linked_ch);
+ dma_chan[lch].state = DMA_CH_QUEUED;
+ start_dma = 0;
+ if (0 == ((1 << 7) & dma_read(
+ CCR, dma_chan[lch].prev_linked_ch))) {
+ omap2_disable_lnk(dma_chan[lch].
+ prev_linked_ch);
+ pr_debug("\n prev ch is stopped\n");
+ start_dma = 1;
+ }
+ }
+
+ else if (dma_chan[dma_chan[lch].prev_linked_ch].state
+ == DMA_CH_QUEUED) {
+ omap2_enable_lnk(dma_chan[lch].prev_linked_ch);
+ dma_chan[lch].state = DMA_CH_QUEUED;
+ start_dma = 0;
+ }
+ omap2_enable_channel_irq(lch);
+
+ l = dma_read(CCR, lch);
+
+ if ((0 == (l & (1 << 24))))
+ l &= ~(1 << 25);
+ else
+ l |= (1 << 25);
+ if (start_dma == 1) {
+ if (0 == (l & (1 << 7))) {
+ l |= (1 << 7);
+ dma_chan[lch].state = DMA_CH_STARTED;
+ pr_debug("starting %d\n", lch);
+ dma_write(l, CCR, lch);
+ } else
+ start_dma = 0;
+ } else {
+ if (0 == (l & (1 << 7)))
+ dma_write(l, CCR, lch);
+ }
+ dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_dma_chain_a_transfer);
+
+/**
+ * @brief omap_start_dma_chain_transfers - Start the chain
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ * Failure : -EINVAL/-EBUSY
+ */
+int omap_start_dma_chain_transfers(int chain_id)
+{
+ int *channels;
+ u32 l, i;
+
+ if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ if (dma_linked_lch[channels[0]].chain_state == DMA_CHAIN_STARTED) {
+ printk(KERN_ERR "Chain is already started\n");
+ return -EBUSY;
+ }
+
+ if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_STATIC_CHAIN) {
+ for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked;
+ i++) {
+ omap2_enable_lnk(channels[i]);
+ omap2_enable_channel_irq(channels[i]);
+ }
+ } else {
+ omap2_enable_channel_irq(channels[0]);
+ }
+
+ l = dma_read(CCR, channels[0]);
+ l |= (1 << 7);
+ dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
+ dma_chan[channels[0]].state = DMA_CH_STARTED;
+
+ if ((0 == (l & (1 << 24))))
+ l &= ~(1 << 25);
+ else
+ l |= (1 << 25);
+ dma_write(l, CCR, channels[0]);
+
+ dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_start_dma_chain_transfers);
+
+/**
+ * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain.
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ * Failure : EINVAL
+ */
+int omap_stop_dma_chain_transfers(int chain_id)
+{
+ int *channels;
+ u32 l, i;
+ u32 sys_cf = 0;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+ omap_device_mstandby(pd, &sys_cf, true);
+
+ for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
+
+ /* Stop the Channel transmission */
+ l = dma_read(CCR, channels[i]);
+ l &= ~(1 << 7);
+ dma_write(l, CCR, channels[i]);
+
+ /* Disable the link in all the channels */
+ omap2_disable_lnk(channels[i]);
+ dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+
+ }
+ dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
+
+ /* Reset the Queue pointers */
+ OMAP_DMA_CHAIN_QINIT(chain_id);
+
+ if (IS_DMA_ERRATA(DMA_ERRATA_i88))
+ omap_device_mstandby(pd, &sys_cf, false);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_stop_dma_chain_transfers);
+
+/* Get the index of the ongoing DMA in chain */
+/**
+ * @brief omap_get_dma_chain_index - Get the element and frame index
+ * of the ongoing DMA in chain
+ *
+ * @param chain_id
+ * @param ei - Element index
+ * @param fi - Frame index
+ *
+ * @return - Success : 0
+ * Failure : -EINVAL
+ */
+int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
+{
+ int lch;
+ int *channels;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+ if ((!ei) || (!fi))
+ return -EINVAL;
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* Get the current channel */
+ lch = channels[dma_linked_lch[chain_id].q_head];
+
+ *ei = dma_read(CCEN, lch);
+ *fi = dma_read(CCFN, lch);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_get_dma_chain_index);
+
+/**
+ * @brief omap_get_dma_chain_dst_pos - Get the destination position of the
+ * ongoing DMA in chain
+ *
+ * @param chain_id
+ *
+ * @return - Success : Destination position
+ * Failure : -EINVAL
+ */
+int omap_get_dma_chain_dst_pos(int chain_id)
+{
+ int lch;
+ int *channels;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* Get the current channel */
+ lch = channels[dma_linked_lch[chain_id].q_head];
+
+ return dma_read(CDAC, lch);
+}
+EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
+
+/**
+ * @brief omap_get_dma_chain_src_pos - Get the source position
+ * of the ongoing DMA in chain
+ * @param chain_id
+ *
+ * @return - Success : Destination position
+ * Failure : -EINVAL
+ */
+int omap_get_dma_chain_src_pos(int chain_id)
+{
+ int lch;
+ int *channels;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= dma_chan_count))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* Get the current channel */
+ lch = channels[dma_linked_lch[chain_id].q_head];
+
+ return dma_read(CSAC, lch);
+}
+EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
+
/* One time initializations */
static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
{
struct omap_device *od;
struct omap_system_dma_plat_info *p;
struct resource *mem;
+ int dma_irq, ret;
char *name = "omap_dma_system";
p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
@@ -241,8 +1224,31 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
}
p->regs = reg_map;
p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr;
- p->disable_irq_lch = disable_irq_lch;
- p->show_dma_caps = omap2_show_dma_caps;
+
+ p->show_dma_caps = omap2_show_dma_caps;
+ p->cpc_cdac_init = omap2_cpc_cdac_init;
+ p->set_transfer_params = omap2_set_transfer_params;
+ p->set_color_mode = omap2_set_color_mode;
+
+ p->set_src_params = omap2_set_src_params;
+ p->set_dest_params = omap2_set_dest_params;
+ p->get_src_pos = omap2_set_src_pos;
+ p->get_dst_pos = omap2_get_dst_pos;
+
+ p->clear_channel_int = omap2_clear_channel_interrupt;
+
+ p->enable_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_global_params = omap_dma_set_global_params;
+
+ p->clear_lch_regs = NULL;
+ p->get_gdma_dev = NULL;
+ p->set_gdma_dev = NULL;
/* Configure errata handling for all omap2+'s */
p->errata = configure_dma_errata();
@@ -257,6 +1263,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
return IS_ERR(od);
}
kfree(p);
+ pd = &od->pdev;
mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
if (!mem) {
@@ -269,8 +1276,21 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__);
return -ENOMEM;
}
-
d = oh->dev_attr;
+ dma_irq = platform_get_irq_byname(&od->pdev, "0");
+ ret = setup_irq(dma_irq, &omap24xx_dma_irq);
+ if (ret) {
+ dev_err(&od->pdev.dev, "%s:irq handler setup fail\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Get DMA device attributes from hwmod data base */
+ d = (struct omap_dma_dev_attr *)oh->dev_attr;
+
+ /* OMAP2 Plus: physical and logical channel count is same */
+ d->chan_count = d->lch_count;
+ dma_chan_count = d->chan_count;
+
d->chan = kzalloc(sizeof(struct omap_dma_lch) *
(d->lch_count), GFP_KERNEL);
@@ -278,6 +1298,15 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
return -ENOMEM;
}
+
+ dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
+ dma_chan_count, GFP_KERNEL);
+ if (!dma_linked_lch) {
+ kfree(d->chan);
+ return -ENOMEM;
+ }
+ dma_chan = d->chan;
+
return 0;
}
diff --git a/arch/arm/mach-omap2/include/mach/dma.h b/arch/arm/mach-omap2/include/mach/dma.h
index d13c5c0..4313539 100644
--- a/arch/arm/mach-omap2/include/mach/dma.h
+++ b/arch/arm/mach-omap2/include/mach/dma.h
@@ -32,4 +32,55 @@
/* Should be part of hwmod data base ? */
#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */
+/* Chaining modes*/
+#define OMAP_DMA_STATIC_CHAIN 0x1
+#define OMAP_DMA_DYNAMIC_CHAIN 0x2
+#define OMAP_DMA_CHAIN_ACTIVE 0x1
+#define OMAP_DMA_CHAIN_INACTIVE 0x0
+
+enum {
+ REVISION = 0, GCR, IRQSTATUS_L0, IRQSTATUS_L1,
+ IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0, IRQENABLE_L1,
+ IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS, OCP_SYSCONFIG,
+ CAPS_0, CAPS_2, CAPS_3, CAPS_4,
+
+ CH_COMMON_START,
+
+ /* Common register offsets */
+ CCR, CLNK_CTRL, CICR, CSR,
+ CSDP, CEN, CFN, CSEI,
+ CSFI, CDEI, CDFI, CSAC,
+ CDAC,
+
+ /* Channel specific register offsets */
+ CSSA, CDSA, CCEN, CCFN,
+ COLOR,
+
+ CH_COMMON_END,
+
+ /* OMAP4 specific registers */
+ CDP, CNDP, CCDN,
+};
+
+/* 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 d8e9886..eb00b22 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -38,255 +38,41 @@
#include <asm/system.h>
#include <mach/hardware.h>
-#include <plat/dma.h>
+#include <plat/dma.h>
#include <plat/tc.h>
-
-#undef DEBUG
-
-enum {
- GCR1 = 0, GSCR, GRST, HW_ID,
- PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID,
- PCHD_ID, CAPS1_0_U, CAPS1_0_L, CAPS1_1_U,
- CAPS1_1_L, CAPS1_2, CAPS1_3, CAPS1_4,
- PCH2_SR, PCH0_SR, PCH1_SR, PCHD_SR,
-
- OMAP1_CH_COMMON_START,
-
- /* Common Registers */
- CSDP1, CCR1, CICR1, CSR1,
- CEN1, CFN1, CSFI1, CSEI1,
- CPC, CSAC1, CDAC1, CDEI1,
- CDFI1, CLNK_CTRL1,
-
- /* Channel specific register offsets */
- CSSA_L, CSSA_U, CDSA_L, CDSA_U,
- COLOR_L, COLOR_U, CCR1_2, LCH_CTRL,
-
- OMAP1_CH_COMMON_END,
-};
-
-static u16 reg_map_omap1[] = {
- [GCR1] = 0x400,
- [GSCR] = 0x404,
- [GRST] = 0x408,
- [HW_ID] = 0x442,
- [PCH2_ID] = 0x444,
- [PCH0_ID] = 0x446,
- [PCH1_ID] = 0x448,
- [PCHG_ID] = 0x44a,
- [PCHD_ID] = 0x44c,
- [CAPS1_0_U] = 0x44e,
- [CAPS1_0_L] = 0x450,
- [CAPS1_1_U] = 0x452,
- [CAPS1_1_L] = 0x454,
- [CAPS1_2] = 0x456,
- [CAPS1_3] = 0x458,
- [CAPS1_4] = 0x45a,
- [PCH2_SR] = 0x460,
- [PCH0_SR] = 0x480,
- [PCH1_SR] = 0x482,
- [PCHD_SR] = 0x4c0,
-
- /* Common Registers */
- [CSDP1] = 0x00,
- [CCR1] = 0x02,
- [CICR1] = 0x04,
- [CSR1] = 0x06,
- [CEN1] = 0x10,
- [CFN1] = 0x12,
- [CSFI1] = 0x14,
- [CSEI1] = 0x16,
- [CPC] = 0x18, /* 15xx only */
- [CSAC1] = 0x18,
- [CDAC1] = 0x1a,
- [CDEI1] = 0x1c,
- [CDFI1] = 0x1e,
- [CLNK_CTRL1] = 0x28,
-
- /* Channel specific register offsets */
- [CSSA_L] = 0x08,
- [CSSA_U] = 0x0a,
- [CDSA_L] = 0x0c,
- [CDSA_U] = 0x0e,
- [COLOR_L] = 0x20,
- [COLOR_U] = 0x22,
- [CCR1_2] = 0x24,
- [LCH_CTRL] = 0x2a,
-};
-
-enum {
- REVISION = 0, GCR2, IRQSTATUS_L0, IRQSTATUS_L1,
- IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0, IRQENABLE_L1,
- IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS, OCP_SYSCONFIG,
- CAPS2_0, CAPS2_2, CAPS2_3, CAPS2_4,
-
- OMAP2_CH_COMMON_START,
-
- /* Common register offsets */
- CCR2, CLNK_CTRL2, CICR2, CSR2,
- CSDP2, CEN2, CFN2, CSEI2,
- CSFI2, CDEI2, CDFI2, CSAC2,
- CDAC2,
-
- /* Channel specific register offsets */
- CSSA, CDSA, CCEN, CCFN,
- COLOR,
-
- /* OMAP4 specific registers */
- CDP, CNDP, CCDN,
-
- OMAP2_CH_COMMON_END,
-};
-
-static u16 reg_map_omap2[] = {
- [REVISION] = 0x00,
- [GCR2] = 0x78,
- [IRQSTATUS_L0] = 0x08,
- [IRQSTATUS_L1] = 0x0c,
- [IRQSTATUS_L2] = 0x10,
- [IRQSTATUS_L3] = 0x14,
- [IRQENABLE_L0] = 0x18,
- [IRQENABLE_L1] = 0x1c,
- [IRQENABLE_L2] = 0x20,
- [IRQENABLE_L3] = 0x24,
- [SYSSTATUS] = 0x28,
- [OCP_SYSCONFIG] = 0x2c,
- [CAPS2_0] = 0x64,
- [CAPS2_2] = 0x6c,
- [CAPS2_3] = 0x70,
- [CAPS2_4] = 0x74,
-
- /* Common register offsets */
- [CCR2] = 0x80,
- [CLNK_CTRL2] = 0x84,
- [CICR2] = 0x88,
- [CSR2] = 0x8c,
- [CSDP2] = 0x90,
- [CEN2] = 0x94,
- [CFN2] = 0x98,
- [CSEI2] = 0xa4,
- [CSFI2] = 0xa8,
- [CDEI2] = 0xac,
- [CDFI2] = 0xb0,
- [CSAC2] = 0xb4,
- [CDAC2] = 0xb8,
-
- /* Channel specific register offsets */
- [CSSA] = 0x9c,
- [CDSA] = 0xa0,
- [CCEN] = 0xbc,
- [CCFN] = 0xc0,
- [COLOR] = 0xc4,
-
- /* OMAP4 specific registers */
- [CDP] = 0xd0,
- [CNDP] = 0xd4,
- [CCDN] = 0xd8,
-};
-
-#ifndef CONFIG_ARCH_OMAP1
-enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
- DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
-};
-
-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)
+#include <plat/omap_device.h>
static struct omap_system_dma_plat_info *p;
static struct omap_dma_dev_attr *d;
+static struct omap_dma_lch *dma_chan;
+static struct platform_device *pd;
+
static u16 *reg_map;
static int enable_1510_mode;
static u32 errata;
-static struct omap_dma_global_context_registers {
- u32 dma_irqenable_l0;
- u32 dma_ocp_sysconfig;
- u32 dma_gcr;
-} omap_dma_global_context;
-
-struct dma_link_info {
- int *linked_dmach_q;
- int no_of_lchs_linked;
-
- int q_count;
- int q_tail;
- int q_head;
-
- int chain_state;
- int chain_mode;
-
-};
-
-static struct dma_link_info *dma_linked_lch;
-
-#ifndef CONFIG_ARCH_OMAP1
-
-/* Chain handling macros */
-#define OMAP_DMA_CHAIN_QINIT(chain_id) \
- do { \
- dma_linked_lch[chain_id].q_head = \
- dma_linked_lch[chain_id].q_tail = \
- dma_linked_lch[chain_id].q_count = 0; \
- } while (0)
-#define OMAP_DMA_CHAIN_QFULL(chain_id) \
- (dma_linked_lch[chain_id].no_of_lchs_linked == \
- dma_linked_lch[chain_id].q_count)
-#define OMAP_DMA_CHAIN_QLAST(chain_id) \
- do { \
- ((dma_linked_lch[chain_id].no_of_lchs_linked-1) == \
- dma_linked_lch[chain_id].q_count) \
- } while (0)
-#define OMAP_DMA_CHAIN_QEMPTY(chain_id) \
- (0 == dma_linked_lch[chain_id].q_count)
-#define __OMAP_DMA_CHAIN_INCQ(end) \
- ((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked)
-#define OMAP_DMA_CHAIN_INCQHEAD(chain_id) \
- do { \
- __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head); \
- dma_linked_lch[chain_id].q_count--; \
- } while (0)
-
-#define OMAP_DMA_CHAIN_INCQTAIL(chain_id) \
- do { \
- __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_tail); \
- dma_linked_lch[chain_id].q_count++; \
- } while (0)
-#endif
-
static int dma_lch_count;
static int dma_chan_count;
static int omap_dma_reserve_channels;
static spinlock_t dma_chan_lock;
-static struct omap_dma_lch *dma_chan;
static void __iomem *dma_base;
-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__);
static inline void dma_write(u32 val, int reg, int lch)
{
- if (cpu_class_is_omap1()) {
- if (reg > OMAP1_CH_COMMON_START)
+ if (d->dev_caps & IS_WORD_16) {
+ if (reg >= CH_COMMON_START)
__raw_writew(val, dma_base +
- (reg_map_omap1[reg] + 0x40 * lch));
+ (reg_map[reg] + 0x40 * lch));
else
- __raw_writew(val, dma_base + reg_map_omap1[reg]);
+ __raw_writew(val, dma_base + reg_map[reg]);
} else {
- if (reg > OMAP2_CH_COMMON_START)
+ if (reg > CH_COMMON_START)
__raw_writel(val, dma_base +
- (reg_map_omap2[reg] + 0x60 * lch));
+ (reg_map[reg] + 0x60 * lch));
else
- __raw_writel(val, dma_base + reg_map_omap2[reg]);
+ __raw_writel(val, dma_base + reg_map[reg]);
}
}
@@ -294,71 +80,28 @@ static inline u32 dma_read(int reg, int lch)
{
u32 val;
- if (cpu_class_is_omap1()) {
- if (reg > OMAP1_CH_COMMON_START)
+ if (d->dev_caps & IS_WORD_16) {
+ if (reg >= CH_COMMON_START)
val = __raw_readw(dma_base +
- (reg_map_omap1[reg] + 0x40 * lch));
+ (reg_map[reg] + 0x40 * lch));
else
- val = __raw_readw(dma_base + reg_map_omap1[reg]);
+ val = __raw_readw(dma_base + reg_map[reg]);
} else {
- if (reg > OMAP2_CH_COMMON_START)
+ if (reg >= CH_COMMON_START)
val = __raw_readl(dma_base +
- (reg_map_omap2[reg] + 0x60 * lch));
+ (reg_map[reg] + 0x60 * lch));
else
- val = __raw_readl(dma_base + reg_map_omap2[reg]);
+ val = __raw_readl(dma_base + reg_map[reg]);
}
return val;
}
-#ifdef CONFIG_ARCH_OMAP15XX
-/* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
-int omap_dma_in_1510_mode(void)
-{
- 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
-
-/* Omap1 only */
-static void clear_lch_regs(int lch)
-{
- int i = OMAP1_CH_COMMON_START;
-
- for (; i <= OMAP1_CH_COMMON_END; i += 1)
- dma_write(0, i, lch);
-}
-
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;
@@ -380,17 +123,15 @@ 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(CCR2, lch);
+ ccr = dma_read(CCR, lch);
if (priority)
ccr |= (1 << 6);
else
ccr &= ~(1 << 6);
- dma_write(ccr, CCR2, lch);
+ dma_write(ccr, CCR, lch);
}
}
EXPORT_SYMBOL(omap_set_dma_priority);
@@ -399,161 +140,22 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
int frame_count, int sync_mode,
int dma_trigger, int src_or_dst_synch)
{
- u32 l;
-
- if (cpu_class_is_omap1()) {
- u16 ccr;
-
- l = dma_read(CSDP1, lch);
- l &= ~0x03;
- l |= data_type;
- dma_write(l, CSDP1, lch);
-
- ccr = dma_read(CCR1, lch);
- ccr &= ~(1 << 5);
- if (sync_mode == OMAP_DMA_SYNC_FRAME)
- ccr |= 1 << 5;
- dma_write(ccr, CCR1, lch);
-
- ccr = dma_read(CCR1_2, lch);
- ccr &= ~(1 << 2);
- if (sync_mode == OMAP_DMA_SYNC_BLOCK)
- ccr |= 1 << 2;
- dma_write(ccr, CCR1_2, lch);
- }
-
- if (cpu_class_is_omap2() && dma_trigger) {
- u32 val;
+ dma_write(elem_count, CEN, lch);
+ dma_write(frame_count, CFN, lch);
- l = dma_read(CSDP2, lch);
- l &= ~0x03;
- l |= data_type;
- dma_write(l, CSDP2, lch);
-
- val = dma_read(CCR2, lch);
-
- /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
- val &= ~((1 << 23) | (3 << 19) | 0x1f);
- val |= (dma_trigger & ~0x1f) << 14;
- val |= dma_trigger & 0x1f;
-
- if (sync_mode & OMAP_DMA_SYNC_FRAME)
- val |= 1 << 5;
- else
- val &= ~(1 << 5);
-
- if (sync_mode & OMAP_DMA_SYNC_BLOCK)
- val |= 1 << 18;
- else
- val &= ~(1 << 18);
-
- if (src_or_dst_synch == OMAP_DMA_DST_SYNC_PREFETCH) {
- val &= ~(1 << 24); /* dest synch */
- val |= (1 << 23); /* Prefetch */
- } else if (src_or_dst_synch) {
- val |= 1 << 24; /* source synch */
- } else {
- val &= ~(1 << 24); /* dest synch */
- }
- dma_write(val, CCR2, lch);
- }
- if (cpu_class_is_omap1()) {
- dma_write(elem_count, CEN1, lch);
- dma_write(frame_count, CFN1, lch);
- } else {
- dma_write(elem_count, CEN2, lch);
- dma_write(frame_count, CFN2, lch);
- }
+ p->set_transfer_params(lch, data_type, sync_mode, dma_trigger,
+ src_or_dst_synch);
}
EXPORT_SYMBOL(omap_set_dma_transfer_params);
void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
{
- BUG_ON(omap_dma_in_1510_mode());
-
- if (cpu_class_is_omap1()) {
- u16 w;
+ BUG_ON(enable_1510_mode);
+ p->set_color_mode(lch, mode, color);
- w = dma_read(CCR1_2, lch);
- w &= ~0x03;
-
- switch (mode) {
- case OMAP_DMA_CONSTANT_FILL:
- w |= 0x01;
- break;
- case OMAP_DMA_TRANSPARENT_COPY:
- w |= 0x02;
- break;
- case OMAP_DMA_COLOR_DIS:
- break;
- default:
- BUG();
- }
- dma_write(w, CCR1_2, lch);
-
- w = dma_read(LCH_CTRL, lch);
- w &= ~0x0f;
- /* Default is channel type 2D */
- if (mode) {
- dma_write((u16)color, COLOR_L, lch);
- dma_write((u16)(color >> 16), COLOR_U, lch);
- w |= 1; /* Channel type G */
- }
- dma_write(w, LCH_CTRL, lch);
- }
-
- if (cpu_class_is_omap2()) {
- u32 val;
-
- val = dma_read(CCR2, lch);
- val &= ~((1 << 17) | (1 << 16));
-
- switch (mode) {
- case OMAP_DMA_CONSTANT_FILL:
- val |= 1 << 16;
- break;
- case OMAP_DMA_TRANSPARENT_COPY:
- val |= 1 << 17;
- break;
- case OMAP_DMA_COLOR_DIS:
- break;
- default:
- BUG();
- }
- dma_write(val, CCR2, lch);
-
- color &= 0xffffff;
- dma_write(color, COLOR, lch);
- }
}
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(CSDP2, lch);
- csdp &= ~(0x3 << 16);
- csdp |= (mode << 16);
- dma_write(csdp, CSDP2, 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,
@@ -561,41 +163,22 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
{
u32 l;
- if (cpu_class_is_omap1()) {
+ if (d->dev_caps & IS_WORD_16) {
u16 w;
- w = dma_read(CSDP1, lch);
+ w = dma_read(CSDP, lch);
w &= ~(0x1f << 2);
w |= src_port << 2;
- dma_write(w, CSDP1, lch);
+ dma_write(w, CSDP, lch);
- l = dma_read(CCR1, lch);
- } else
- l = dma_read(CCR2, lch);
+ }
+ l = dma_read(CCR, lch);
l &= ~(0x03 << 12);
l |= src_amode << 12;
+ dma_write(l, CCR, lch);
- if (cpu_class_is_omap1())
- dma_write(l, CCR1, lch);
- else
- dma_write(l, CCR2, lch);
-
- if (cpu_class_is_omap1()) {
- dma_write(src_start >> 16, CSSA_U, lch);
- dma_write((u16)src_start, CSSA_L, lch);
- }
-
- if (cpu_class_is_omap2())
- dma_write(src_start, CSSA, lch);
-
- if (cpu_class_is_omap1()) {
- dma_write(src_ei, CSEI1, lch);
- dma_write(src_fi, CSFI1, lch);
- } else {
- dma_write(src_ei, CSEI2, lch);
- dma_write(src_fi, CSFI2, lch);
- }
+ p->set_src_params(lch, src_start, src_ei, src_fi);
}
EXPORT_SYMBOL(omap_set_dma_src_params);
@@ -618,33 +201,15 @@ 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, CSEI1, lch);
- dma_write(fidx, CSFI1, lch);
-}
-EXPORT_SYMBOL(omap_set_dma_src_index);
-
void omap_set_dma_src_data_pack(int lch, int enable)
{
u32 l;
- if (cpu_class_is_omap1())
- l = dma_read(CSDP1, lch);
- else
- l = dma_read(CSDP2, lch);
-
+ l = dma_read(CSDP, lch);
l &= ~(1 << 6);
if (enable)
l |= (1 << 6);
-
- if (cpu_class_is_omap1())
- dma_write(l, CSDP1, lch);
- else
- dma_write(l, CSDP2, lch);
+ dma_write(l, CSDP, lch);
}
EXPORT_SYMBOL(omap_set_dma_src_data_pack);
@@ -653,37 +218,31 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
unsigned int burst = 0;
u32 l;
- if (cpu_class_is_omap2())
- l = dma_read(CSDP2, lch);
- else
- l = dma_read(CSDP1, lch);
-
+ l = dma_read(CSDP, lch);
l &= ~(0x03 << 7);
switch (burst_mode) {
case OMAP_DMA_DATA_BURST_DIS:
break;
case OMAP_DMA_DATA_BURST_4:
- if (cpu_class_is_omap2())
+ if (!(d->dev_caps & IS_BURST_ONLY4))
burst = 0x1;
else
burst = 0x2;
break;
case OMAP_DMA_DATA_BURST_8:
- if (cpu_class_is_omap2()) {
+ if (!(d->dev_caps & IS_BURST_ONLY4))
burst = 0x2;
- break;
- }
+ break;
/*
* not supported by current hardware on OMAP1
* w |= (0x03 << 7);
* fall through
*/
case OMAP_DMA_DATA_BURST_16:
- if (cpu_class_is_omap2()) {
+ if (!(d->dev_caps & IS_BURST_ONLY4))
burst = 0x3;
- break;
- }
+ break;
/*
* OMAP1 don't support burst 16
* fall through
@@ -694,83 +253,41 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
l |= (burst << 7);
- if (cpu_class_is_omap2())
- dma_write(l, CSDP2, lch);
- else
- dma_write(l, CSDP1, lch);
+ dma_write(l, CSDP, lch);
}
EXPORT_SYMBOL(omap_set_dma_src_burst_mode);
/* Note that dest_port is only for OMAP1 */
void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
- unsigned long dest_start,
- int dst_ei, int dst_fi)
+ unsigned long dest_start, int dst_ei, int dst_fi)
{
u32 l;
- if (cpu_class_is_omap1()) {
- l = dma_read(CSDP1, lch);
+ if (d->dev_caps & IS_WORD_16) {
+ l = dma_read(CSDP, lch);
l &= ~(0x1f << 9);
l |= dest_port << 9;
- dma_write(l, CSDP1, lch);
-
- l = dma_read(CCR1, lch);
- } else
- l = dma_read(CCR2, lch);
-
+ dma_write(l, CSDP, lch);
+ }
+ l = dma_read(CCR, lch);
l &= ~(0x03 << 14);
l |= dest_amode << 14;
+ dma_write(l, CCR, lch);
- if (cpu_class_is_omap1())
- dma_write(l, CCR1, lch);
- else
- dma_write(l, CCR2, lch);
-
- if (cpu_class_is_omap1()) {
- dma_write(dest_start >> 16, CDSA_U, lch);
- dma_write(dest_start, CDSA_L, lch);
- }
-
- if (cpu_class_is_omap2())
- dma_write(dest_start, CDSA, lch);
+ p->set_dest_params(lch, dest_start, dst_ei, dst_fi);
- if (cpu_class_is_omap1()) {
- dma_write(dst_ei, CDEI1, lch);
- dma_write(dst_fi, CDFI1, lch);
- } else {
- dma_write(dst_ei, CDEI2, lch);
- dma_write(dst_fi, CDFI2, lch);
- }
}
EXPORT_SYMBOL(omap_set_dma_dest_params);
-void omap_set_dma_dest_index(int lch, int eidx, int fidx)
-{
- if (cpu_class_is_omap2())
- return;
-
- dma_write(eidx, CDEI1, lch);
- dma_write(fidx, CDFI1, lch);
-}
-EXPORT_SYMBOL(omap_set_dma_dest_index);
-
void omap_set_dma_dest_data_pack(int lch, int enable)
{
u32 l;
- if (cpu_class_is_omap2())
- l = dma_read(CSDP2, lch);
- else
- l = dma_read(CSDP1, lch);
-
+ l = dma_read(CSDP, lch);
l &= ~(1 << 13);
if (enable)
l |= 1 << 13;
-
- if (cpu_class_is_omap2())
- dma_write(l, CSDP2, lch);
- else
- dma_write(l, CSDP1, lch);
+ dma_write(l, CSDP, lch);
}
EXPORT_SYMBOL(omap_set_dma_dest_data_pack);
@@ -778,33 +295,29 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
{
unsigned int burst = 0;
u32 l;
- if (cpu_class_is_omap2())
- l = dma_read(CSDP2, lch);
- else
- l = dma_read(CSDP1, lch);
+ l = dma_read(CSDP, lch);
l &= ~(0x03 << 14);
switch (burst_mode) {
case OMAP_DMA_DATA_BURST_DIS:
break;
case OMAP_DMA_DATA_BURST_4:
- if (cpu_class_is_omap2())
+ if (!(d->dev_caps & IS_BURST_ONLY4))
burst = 0x1;
else
burst = 0x2;
break;
case OMAP_DMA_DATA_BURST_8:
- if (cpu_class_is_omap2())
+ if (!(d->dev_caps & IS_BURST_ONLY4))
burst = 0x2;
else
burst = 0x3;
break;
case OMAP_DMA_DATA_BURST_16:
- if (cpu_class_is_omap2()) {
+ if (!(d->dev_caps & IS_BURST_ONLY4))
burst = 0x3;
- break;
- }
+ break;
/*
* OMAP1 don't support burst 16
* fall through
@@ -814,38 +327,11 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
BUG();
return;
}
-
l |= (burst << 14);
-
- if (cpu_class_is_omap2())
- dma_write(l, CSDP2, lch);
- else
- dma_write(l, CSDP1, lch);
+ dma_write(l, CSDP, lch);
}
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(CSR1, lch);
- dma_write(dma_chan[lch].enabled_irqs, CICR1, lch);
- } else if (cpu_class_is_omap2()) {
- dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR2, lch);
- dma_write(dma_chan[lch].enabled_irqs, CICR2, lch);
- }
-}
-
-static void omap_disable_channel_irq(int lch)
-{
- if (cpu_class_is_omap2())
- dma_write(0, CICR2, lch);
- else
- dma_write(0, CICR1, lch);
-}
-
void omap_enable_dma_irq(int lch, u16 bits)
{
dma_chan[lch].enabled_irqs |= bits;
@@ -858,81 +344,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;
-
- if (cpu_class_is_omap1()) {
- l = dma_read(CLNK_CTRL1, lch);
- l &= ~(1 << 14);
- } else
- l = dma_read(CLNK_CTRL2, lch);
-
- /* Set the ENABLE_LNK bits */
- if (dma_chan[lch].next_lch != -1)
- l = dma_chan[lch].next_lch | (1 << 15);
-
- if (cpu_class_is_omap2()) {
- if (dma_chan[lch].next_linked_ch != -1)
- l = dma_chan[lch].next_linked_ch | (1 << 15);
- dma_write(l, CLNK_CTRL2, lch);
- } else
- dma_write(l, CLNK_CTRL1, lch);
-}
-
-static inline void disable_lnk(int lch)
-{
- u32 l;
-
- /* Disable interrupts */
- if (cpu_class_is_omap1()) {
- l = dma_read(CLNK_CTRL1, lch);
- dma_write(0, CICR1, lch);
- /* Set the STOP_LNK bit */
- l |= 1 << 14;
- dma_write(l, CLNK_CTRL1, lch);
- }
-
- if (cpu_class_is_omap2()) {
- l = dma_read(CLNK_CTRL2, lch);
- omap_disable_channel_irq(lch);
- /* Clear the ENABLE_LNK bit */
- l &= ~(1 << 15);
- dma_write(l, CLNK_CTRL2, 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, 0);
- val |= 1 << lch;
- dma_write(val, IRQENABLE_L0, 0);
- 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, 0);
- val &= ~(1 << lch);
- dma_write(val, IRQENABLE_L0, 0);
- 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)
@@ -956,10 +367,9 @@ int omap_request_dma(int dev_id, const char *dev_name,
chan = dma_chan + free_ch;
chan->dev_id = dev_id;
- if (cpu_class_is_omap1())
- clear_lch_regs(free_ch);
-
- if (cpu_class_is_omap2())
+ if (d->dev_caps & IS_WORD_16)
+ p->clear_lch_regs(free_ch);
+ else
omap_clear_dma(free_ch);
spin_unlock_irqrestore(&dma_chan_lock, flags);
@@ -969,46 +379,42 @@ int omap_request_dma(int dev_id, const char *dev_name,
chan->data = data;
chan->flags = 0;
-#ifndef CONFIG_ARCH_OMAP1
- if (cpu_class_is_omap2()) {
+ if (d->dev_caps & DMA_LINKED_LCH) {
chan->chain_id = -1;
chan->next_linked_ch = -1;
}
-#endif
chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
- if (cpu_class_is_omap1())
+ if (d->dev_caps & IS_WORD_16)
chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
- else if (cpu_class_is_omap2())
+ else
chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
OMAP2_DMA_TRANS_ERR_IRQ;
- if (cpu_is_omap16xx()) {
+ if (p->set_gdma_dev) {
/* If the sync device is set, configure it dynamically. */
if (dev_id != 0) {
- set_gdma_dev(free_ch + 1, dev_id);
+ p->set_gdma_dev(free_ch + 1, dev_id);
dev_id = free_ch + 1;
}
/*
* Disable the 1510 compatibility mode and set the sync device
* id.
*/
- dma_write(dev_id | (1 << 10), CCR1, free_ch);
- } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
- dma_write(dev_id, CCR1, free_ch);
- }
+ dma_write(dev_id | (1 << 10), CCR, free_ch);
+ } 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);
+ p->enable_channel_irq(free_ch);
/* Clear the CSR register and IRQ status register */
- dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR2, free_ch);
- dma_write(1 << free_ch, IRQSTATUS_L0, 0);
+ p->clear_channel_int(free_ch);
}
-
*dma_ch_out = free_ch;
-
return 0;
}
EXPORT_SYMBOL(omap_request_dma);
@@ -1023,28 +429,28 @@ 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, CICR1, lch);
+ dma_write(0, CICR, lch);
/* Make sure the DMA transfer is stopped. */
- dma_write(0, CCR1, lch);
+ dma_write(0, CCR, lch);
}
- if (cpu_class_is_omap2()) {
- omap2_disable_irq_lch(lch);
+ if (p->disable_irq_lch) {
+ spin_lock_irqsave(&dma_chan_lock, flags);
+ p->disable_irq_lch(lch);
+ spin_unlock_irqrestore(&dma_chan_lock, flags);
/* Clear the CSR register and IRQ status register */
- dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR2, lch);
- dma_write(1 << lch, IRQSTATUS_L0, 0);
+ p->clear_channel_int(lch);
/* Disable all DMA interrupts for the channel. */
- dma_write(0, CICR2, lch);
+ dma_write(0, CICR, lch);
/* Make sure the DMA transfer is stopped. */
- dma_write(0, CCR2, lch);
+ dma_write(0, CCR, lch);
omap_clear_dma(lch);
}
-
spin_lock_irqsave(&dma_chan_lock, flags);
dma_chan[lch].dev_id = -1;
dma_chan[lch].next_lch = -1;
@@ -1054,39 +460,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, GCR2, 0);
-}
-EXPORT_SYMBOL(omap_dma_set_global_params);
-
-/**
* @brief omap_dma_set_prio_lch : Set channel wise priority settings
*
* @param lch
@@ -1106,17 +479,15 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
return -EINVAL;
}
- if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
- l = dma_read(CCR2, lch);
+ l = dma_read(CCR, lch);
+ if (d->dev_caps & IS_RW_PRIORITY) {
l &= ~((1 << 6) | (1 << 26));
l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
- dma_write(l, CCR2, lch);
} else {
- l = dma_read(CCR1, lch);
- l &= ~((1 << 6) | (1 << 26));
+ l &= ~(1 << 6);
l |= ((read_prio & 0x1) << 6);
- dma_write(l, CCR1, lch);
}
+ dma_write(l, CCR, lch);
return 0;
}
@@ -1132,24 +503,21 @@ 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(CCR1, lch);
+ l = dma_read(CCR, lch);
l &= ~OMAP_DMA_CCR_EN;
- dma_write(l, CCR1, lch);
+ dma_write(l, CCR, lch);
/* Clear pending interrupts */
- l = dma_read(CSR1, lch);
- }
-
- if (cpu_class_is_omap2()) {
- int i = OMAP2_CH_COMMON_START;
+ l = dma_read(CSR, lch);
+ } else {
+ int i = CH_COMMON_START + 1;
- for (; i <= OMAP2_CH_COMMON_END; i++)
+ for (; i < CH_COMMON_END; i++)
dma_write(0, i, lch);
}
-
local_irq_restore(flags);
}
EXPORT_SYMBOL(omap_clear_dma);
@@ -1162,21 +530,16 @@ void omap_start_dma(int lch)
* The CPC/CDAC register needs to be initialized to zero
* before starting dma transfer.
*/
- if (cpu_is_omap15xx())
- dma_write(0, CPC, lch);
- else if (cpu_class_is_omap1())
- dma_write(0, CDAC1, lch);
- else
- dma_write(0, CDAC2, lch);
+ p->cpc_cdac_init(lch);
- if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+ if (!enable_1510_mode && dma_chan[lch].next_lch != -1) {
int next_lch, cur_lch;
char dma_chan_link_map[dma_chan_count];
dma_chan_link_map[lch] = 1;
/* Set the link register of the first channel */
- enable_lnk(lch);
+ p->enable_lnk(lch);
memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
cur_lch = dma_chan[lch].next_lch;
@@ -1189,29 +552,26 @@ void omap_start_dma(int lch)
/* Mark the current channel */
dma_chan_link_map[cur_lch] = 1;
- enable_lnk(cur_lch);
- omap_enable_channel_irq(cur_lch);
+ p->enable_lnk(cur_lch);
+ p->enable_channel_irq(cur_lch);
cur_lch = next_lch;
} while (next_lch != -1);
} else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS))
- dma_write(lch, CLNK_CTRL2, lch);
+ dma_write(lch, CLNK_CTRL, lch);
- omap_enable_channel_irq(lch);
+ p->enable_channel_irq(lch);
- if (cpu_class_is_omap1()) {
- l = dma_read(CCR1, lch);
+ l = dma_read(CCR, lch);
+ if (d->dev_caps & IS_WORD_16)
l |= OMAP_DMA_CCR_EN;
- dma_write(l, CCR1, lch);
- } else {
- l = dma_read(CCR2, lch);
-
+ else {
if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
l |= OMAP_DMA_CCR_EN;
- dma_write(l, CCR2, lch);
}
+ dma_write(l, CCR, lch);
dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
}
EXPORT_SYMBOL(omap_start_dma);
@@ -1221,49 +581,41 @@ void omap_stop_dma(int lch)
u32 l = 0;
/* Disable all interrupts on the channel */
- if (cpu_class_is_omap1())
- dma_write(0, CICR1, lch);
+ if (d->dev_caps & IS_WORD_16)
+ dma_write(0, CICR, lch);
if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
(l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
int i = 0;
- u32 sys_cf;
+ u32 sys_cf = 0;
/* Configure No-Standby */
- l = dma_read(OCP_SYSCONFIG, 0);
- sys_cf = l;
- l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
- l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
- dma_write(l , OCP_SYSCONFIG, 0);
+ omap_device_mstandby(pd, &sys_cf, true);
- l = dma_read(CCR2, lch);
+ l = dma_read(CCR, lch);
l &= ~OMAP_DMA_CCR_EN;
- dma_write(l, CCR2, lch);
+ dma_write(l, CCR, lch);
/* Wait for sDMA FIFO drain */
- l = dma_read(CCR2, lch);
+ l = dma_read(CCR, lch);
while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
OMAP_DMA_CCR_WR_ACTIVE))) {
udelay(5);
i++;
- l = dma_read(CCR2, lch);
+ l = dma_read(CCR, lch);
}
if (i >= 100)
printk(KERN_ERR "DMA drain did not complete on "
"lch %d\n", lch);
/* Restore OCP_SYSCONFIG */
- dma_write(sys_cf, OCP_SYSCONFIG, 0);
- } else if (cpu_class_is_omap1()) {
- l = dma_read(CCR1, lch);
- l &= ~OMAP_DMA_CCR_EN;
- dma_write(l, CCR1, lch);
+ omap_device_mstandby(pd, &sys_cf, false);
} else {
- l = dma_read(CCR2, lch);
+ l = dma_read(CCR, lch);
l &= ~OMAP_DMA_CCR_EN;
- dma_write(l, CCR2, lch);
+ 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];
@@ -1275,7 +627,7 @@ void omap_stop_dma(int lch)
/* Mark the current channel */
dma_chan_link_map[cur_lch] = 1;
- disable_lnk(cur_lch);
+ p->disable_lnk(cur_lch);
next_lch = dma_chan[cur_lch].next_lch;
cur_lch = next_lch;
@@ -1323,26 +675,7 @@ EXPORT_SYMBOL(omap_set_dma_callback);
*/
dma_addr_t omap_get_dma_src_pos(int lch)
{
- dma_addr_t offset = 0;
-
- if (cpu_is_omap15xx())
- offset = dma_read(CPC, lch);
- else if (cpu_class_is_omap1())
- offset = dma_read(CSAC1, lch);
- else
- offset = dma_read(CSAC2, lch);
-
- if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) {
- if (cpu_class_is_omap1())
- offset = dma_read(CSAC1, lch);
- else
- offset = dma_read(CSAC2, lch);
- }
-
- if (cpu_class_is_omap1())
- offset |= (dma_read(CSSA_U, lch) << 16);
-
- return offset;
+ return p->get_src_pos(lch);
}
EXPORT_SYMBOL(omap_get_dma_src_pos);
@@ -1356,39 +689,13 @@ EXPORT_SYMBOL(omap_get_dma_src_pos);
*/
dma_addr_t omap_get_dma_dst_pos(int lch)
{
- dma_addr_t offset = 0;
-
- if (cpu_is_omap15xx())
- offset = dma_read(CPC, lch);
- else if (cpu_class_is_omap1())
- offset = dma_read(CDAC1, lch);
- else
- offset = dma_read(CDAC2, 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 (cpu_class_is_omap1())
- offset = dma_read(CDAC1, lch);
- else
- offset = dma_read(CDAC2, lch);
- }
-
- if (cpu_class_is_omap1())
- offset |= (dma_read(CDSA_U, lch) << 16);
-
- return offset;
+ return p->get_dst_pos(lch);
}
EXPORT_SYMBOL(omap_get_dma_dst_pos);
int omap_get_dma_active_status(int lch)
{
- if (cpu_class_is_omap1())
- return (dma_read(CCR1, lch) & OMAP_DMA_CCR_EN) != 0;
- else
- return (dma_read(CCR2, lch) & OMAP_DMA_CCR_EN) != 0;
+ return (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0;
}
EXPORT_SYMBOL(omap_get_dma_active_status);
@@ -1396,15 +703,14 @@ int omap_dma_running(void)
{
int lch;
- for (lch = 0; lch < dma_chan_count; lch++) {
- if (cpu_class_is_omap1()) {
- if (dma_read(CCR1, lch) & OMAP_DMA_CCR_EN)
- return 1;
- } else {
- if (dma_read(CCR2, lch) & OMAP_DMA_CCR_EN)
- return 1;
- }
- }
+ if (d->dev_caps & IS_WORD_16)
+ if (omap_lcd_dma_running())
+ return 1;
+
+ for (lch = 0; lch < dma_chan_count; lch++)
+ if (dma_read(CCR, lch) & OMAP_DMA_CCR_EN)
+ return 1;
+
return 0;
}
@@ -1415,10 +721,10 @@ 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(CCR1, lch_head) | (3 << 8),
- CCR1, lch_head);
+ dma_write(dma_read(CCR, lch_head) | (3 << 8),
+ CCR, lch_head);
return;
}
printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1442,10 +748,10 @@ 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(CCR1, lch_head) & ~(3 << 8),
- CCR1, lch_head);
+ dma_write(dma_read(CCR, lch_head) & ~(3 << 8),
+ CCR, lch_head);
return;
}
printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
@@ -1471,826 +777,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_CTRL2, lch_head);
- l &= ~(0x1f);
- l |= lch_queue;
- dma_write(l, CLNK_CTRL2, lch_head);
-
- l = dma_read(CLNK_CTRL2, lch_queue);
- l &= ~(0x1f);
- l |= (dma_chan[lch_queue].next_linked_ch);
- dma_write(l, CLNK_CTRL2, 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], ¶ms);
- }
-
- *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], ¶ms);
- }
-
- 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, CEN2, lch);
- dma_write(frame_count, CFN2, 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(
- CCR2, 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(CCR2, 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, CCR2, lch);
- } else
- start_dma = 0;
- } else {
- if (0 == (l & (1 << 7)))
- dma_write(l, CCR2, 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(CCR2, 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, CCR2, channels[0]);
-
- dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
-
- return 0;
-}
-EXPORT_SYMBOL(omap_start_dma_chain_transfers);
-
-/**
- * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain.
- *
- * @param chain_id
- *
- * @return - Success : 0
- * Failure : EINVAL
- */
-int omap_stop_dma_chain_transfers(int chain_id)
-{
- int *channels;
- u32 l, i;
- u32 sys_cf = 0;
-
- /* Check for input params */
- if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
- printk(KERN_ERR "Invalid chain id\n");
- return -EINVAL;
- }
-
- /* Check if the chain exists */
- if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
- printk(KERN_ERR "Chain doesn't exists\n");
- return -EINVAL;
- }
- channels = dma_linked_lch[chain_id].linked_dmach_q;
-
- if (IS_DMA_ERRATA(DMA_ERRATA_i88)) {
- sys_cf = dma_read(OCP_SYSCONFIG, 0);
- l = sys_cf;
- /* Middle mode reg set no Standby */
- l &= ~((1 << 12)|(1 << 13));
- dma_write(l, OCP_SYSCONFIG, 0);
- }
-
- for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
-
- /* Stop the Channel transmission */
- l = dma_read(CCR2, channels[i]);
- l &= ~(1 << 7);
- dma_write(l, CCR2, channels[i]);
-
- /* Disable the link in all the channels */
- disable_lnk(channels[i]);
- dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
-
- }
- dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
-
- /* Reset the Queue pointers */
- OMAP_DMA_CHAIN_QINIT(chain_id);
-
- if (IS_DMA_ERRATA(DMA_ERRATA_i88))
- dma_write(sys_cf, OCP_SYSCONFIG, 0);
-
- return 0;
-}
-EXPORT_SYMBOL(omap_stop_dma_chain_transfers);
-
-/* Get the index of the ongoing DMA in chain */
-/**
- * @brief omap_get_dma_chain_index - Get the element and frame index
- * of the ongoing DMA in chain
- *
- * @param chain_id
- * @param ei - Element index
- * @param fi - Frame index
- *
- * @return - Success : 0
- * Failure : -EINVAL
- */
-int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
-{
- int lch;
- int *channels;
-
- /* Check for input params */
- if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
- printk(KERN_ERR "Invalid chain id\n");
- return -EINVAL;
- }
-
- /* Check if the chain exists */
- if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
- printk(KERN_ERR "Chain doesn't exists\n");
- return -EINVAL;
- }
- if ((!ei) || (!fi))
- return -EINVAL;
-
- channels = dma_linked_lch[chain_id].linked_dmach_q;
-
- /* Get the current channel */
- lch = channels[dma_linked_lch[chain_id].q_head];
-
- *ei = 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(CDAC2, 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(CSAC2, 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(CSR1, 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(CSR2, ch);
-
- if (!status) {
- if (printk_ratelimit())
- printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
- ch);
- dma_write(1 << ch, IRQSTATUS_L0, 0);
- return 0;
- }
- if (unlikely(dma_chan[ch].dev_id == -1)) {
- if (printk_ratelimit())
- printk(KERN_WARNING "IRQ %04x for non-allocated DMA"
- "channel %d\n", status, ch);
- return 0;
- }
- if (unlikely(status & OMAP_DMA_DROP_IRQ))
- printk(KERN_INFO
- "DMA synchronization event drop occurred with device "
- "%d\n", dma_chan[ch].dev_id);
- if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
- printk(KERN_INFO "DMA transaction error with device %d\n",
- dma_chan[ch].dev_id);
- if (IS_DMA_ERRATA(DMA_ERRATA_i378)) {
- u32 ccr;
-
- ccr = dma_read(CCR2, ch);
- ccr &= ~OMAP_DMA_CCR_EN;
- dma_write(ccr, CCR2, 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, CSR2, ch);
- dma_write(1 << ch, IRQSTATUS_L0, 0);
-
- /* 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_CTRL2, 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(CSR2, ch);
- }
-
- dma_write(status, CSR2, 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, 0);
- if (val == 0) {
- if (printk_ratelimit())
- printk(KERN_WARNING "Spurious DMA IRQ\n");
- return IRQ_HANDLED;
- }
- enable_reg = dma_read(IRQENABLE_L0, 0);
- val &= enable_reg; /* Dispatch only relevant interrupts */
- for (i = 0; i < dma_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, 0);
- omap_dma_global_context.dma_ocp_sysconfig =
- dma_read(OCP_SYSCONFIG, 0);
- omap_dma_global_context.dma_gcr = dma_read(GCR2, 0);
-}
-
-void omap_dma_global_context_restore(void)
-{
- int ch;
-
- dma_write(omap_dma_global_context.dma_gcr, GCR2, 0);
- dma_write(omap_dma_global_context.dma_ocp_sysconfig,
- OCP_SYSCONFIG, 0);
- dma_write(omap_dma_global_context.dma_irqenable_l0,
- IRQENABLE_L0, 0);
-
- /*
- * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
- * after secure sram context save and restore. Hence we need to
- * manually clear those IRQs to avoid spurious interrupts. This
- * affects only secure devices.
- */
- if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
- dma_write(0x3 , IRQSTATUS_L0, 0);
-
- for (ch = 0; ch < dma_chan_count; ch++)
- if (dma_chan[ch].dev_id != -1)
- omap_clear_dma(ch);
-}
-
static int __devinit omap_system_dma_probe(struct platform_device *pdev)
{
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"
@@ -2299,6 +790,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
}
p = pdata;
+ pd = pdev;
d = p->dma_attr;
reg_map = pdata->regs;
errata = p->errata;
@@ -2316,84 +808,38 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
goto exit_release_region;
}
- if (cpu_class_is_omap2() && omap_dma_reserve_channels
+ spin_lock_init(&dma_chan_lock);
+
+ 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;
dma_lch_count = d->lch_count;
- dma_chan_count = dma_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) {
- ret = -ENOMEM;
- goto exit_dma_chan;
- }
- }
- enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
-
- p->show_dma_caps();
-
- spin_lock_init(&dma_chan_lock);
for (ch = 0; ch < dma_chan_count; ch++) {
+ unsigned long flags;
omap_clear_dma(ch);
- if (cpu_class_is_omap2())
- omap2_disable_irq_lch(ch);
+ if (p->disable_irq_lch) {
+ spin_lock_irqsave(&dma_chan_lock, flags);
+ p->disable_irq_lch(ch);
+ spin_unlock_irqrestore(&dma_chan_lock, flags);
+ }
dma_chan[ch].dev_id = -1;
dma_chan[ch].next_lch = -1;
-
- if (ch >= 6 && enable_1510_mode)
- continue;
-
- if (cpu_class_is_omap1()) {
- /*
- * request_irq() doesn't like dev_id (ie. ch) being
- * zero, so we have to kludge around this.
- */
- sprintf(&irq_name[0], "%d", ch);
- dma_irq = platform_get_irq_byname(pdev, irq_name);
-
- if (dma_irq < 0) {
- dev_err(&pdev->dev, "%s:unable to get irq\n",
- __func__);
- ret = dma_irq;
- goto exit_unmap;
- }
- ret = request_irq(dma_irq,
- omap1_dma_irq_handler, 0, "DMA",
- (void *) (ch + 1));
- if (ret != 0) {
- int irq_rel;
- dev_err(&pdev->dev, "unable to request IRQ %d"
- "for DMA (error %d)\n", dma_irq, ret);
- for (irq_rel = 0; irq_rel < ch;
- irq_rel++) {
- dma_irq = platform_get_irq(pdev,
- irq_rel);
- free_irq(dma_irq, (void *)
- (irq_rel + 1));
- goto exit_dma_chan;
- }
- }
- }
}
+ enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
- if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx())
- omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
- DMA_DEFAULT_FIFO_DEPTH, 0);
+ p->show_dma_caps();
- 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);
- }
+ if ((d->dev_caps & GLOBAL_PRIORITY) && (p->set_global_params))
+ p->set_global_params(DMA_DEFAULT_ARB_RATE,
+ DMA_DEFAULT_FIFO_DEPTH, 0);
/* 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;
@@ -2401,10 +847,6 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
}
return 0;
-exit_dma_chan:
- kfree(dma_chan);
-exit_unmap:
- iounmap(dma_base);
exit_release_region:
release_mem_region(mem->start, resource_size(mem));
return ret;
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index e3a927d..477f0d2 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -253,32 +253,12 @@
#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
-#define OMAP_DMA_DYNAMIC_CHAIN 0x2
-#define OMAP_DMA_CHAIN_ACTIVE 0x1
-#define OMAP_DMA_CHAIN_INACTIVE 0x0
-#endif
-
#define DMA_CH_PRIO_HIGH 0x1
#define DMA_CH_PRIO_LOW 0x0 /* Def */
+#define OMAP_DMA_ACTIVE 0x01
+#define OMAP2_DMA_CSR_CLEAR_MASK 0xffe
+
/* Errata handling */
#define IS_DMA_ERRATA(id) (errata &= (id))
#define SET_DMA_ERRATA(id) (errata |= (id))
@@ -402,8 +382,34 @@ struct omap_system_dma_plat_info {
void __iomem *omap_dma_base;
u32 errata;
u16 *regs;
- void (*disable_irq_lch)(int lch);
+
void (*show_dma_caps)(void);
+ void (*clear_lch_regs)(int lch);
+ void (*cpc_cdac_init)(int lch);
+ int (*get_gdma_dev)(int req);
+ void (*set_gdma_dev)(int req, int dev);
+ void (*set_transfer_params)(int lch, int data_type, int sync_mode,
+ int dma_trigger, int src_or_dst_synch);
+ void (*set_color_mode)(int lch, enum omap_dma_color_mode mode,
+ u32 color);
+ void (*set_src_params)(int lch, unsigned long src_start, int src_ei,
+ int src_fi);
+ void (*set_dest_params)(int lch, unsigned long dest_start, int dst_ei,
+ int dst_fi);
+ dma_addr_t (*get_src_pos)(int lch);
+ dma_addr_t (*get_dst_pos)(int lch);
+
+ void (*disable_irq_lch)(int lch);
+ void (*enable_irq_lch)(int lch);
+ void (*enable_channel_irq)(int lch);
+ void (*disable_channel_irq)(int lch);
+ void (*enable_lnk)(int lch);
+ void (*disable_lnk)(int lch);
+
+ void (*clear_channel_int)(int lch);
+
+ void (*set_global_params)(int arb_rate,
+ int max_fifo_depth, int tparams);
};
extern void omap_set_dma_priority(int lch, int dst_port, int priority);
@@ -467,29 +473,6 @@ void omap_dma_global_context_restore(void);
extern void omap_dma_disable_irq(int lch);
-/* Chaining APIs */
-#ifndef CONFIG_ARCH_OMAP1
-extern int omap_request_dma_chain(int dev_id, const char *dev_name,
- void (*callback) (int lch, u16 ch_status,
- void *data),
- int *chain_id, int no_of_chans,
- int chain_mode,
- struct omap_dma_channel_params params);
-extern int omap_free_dma_chain(int chain_id);
-extern int omap_dma_chain_a_transfer(int chain_id, int src_start,
- int dest_start, int elem_count,
- int frame_count, void *callbk_data);
-extern int omap_start_dma_chain_transfers(int chain_id);
-extern int omap_stop_dma_chain_transfers(int chain_id);
-extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
-extern int omap_get_dma_chain_dst_pos(int chain_id);
-extern int omap_get_dma_chain_src_pos(int chain_id);
-
-extern int omap_modify_dma_chain_params(int chain_id,
- struct omap_dma_channel_params params);
-extern int omap_dma_chain_status(int chain_id);
-#endif
-
#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
#include <mach/lcd_dma.h>
#else
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 12/13] OMAP2+: DMA: descriptor autoloading feature
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (10 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 11/13] OMAP: DMA: Use DMA device attributes G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-10-26 13:25 ` [PATCH v3 13/13] OMAP: PM: DMA: Enable runtime pm G, Manjunath Kondaiah
` (2 subsequent siblings)
14 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Add sDMA driver support for descriptor autoloading feature.
Descriptor autoloading is OMAP sDMA v5 hardware capability that can be
exploited for scatter gather scenarios, currently available in OMAP3630
and OMAP4430.
The feature works as described below.
1. A sDMA channel is programmed to be in 'linked list' mode.
2) The client (sDMA user) provides a list of descriptors in a linked
list format
3) Each of the 'descriptor' (element in the linked list) contains an
updated set of DMA configuration register values.
4) Client starts DMA transfer.
5) sDMA controller loads the first element to its register configuration
memory and executes the transfer.
6) After completion, loads the next element (in linked list) to
configuration memory and executes the transfer, without MCU
intervention.
7) Interrupt is generated after all transfers are completed; this can be
configured to be done differently.
Configurations and additional features
1) Fast mode & non-fast mode
Fast mode/non-fast decides on how the first transfer begins. In non-fast
mode, the first element in the linked list is loaded only after
completing the
transfer according to the configurations already in the sDMA channel
registers.
In fast mode, the loading of the first element precedes the transfer.
2) Pause / resume of transfers
A transfer can be paused after a descriptor set has been loaded,
provided the pause bit' is set in the linked list element.
An ongoing transfer cannot be paused. If the 'pause bit' is set,
transfer is not started after loading the register set from memory.
Such a transfer can be resumed later.
3) Descriptor types
Three possible configurations of descriptors (initialized as linked list
elements) are possible.
Type 1 provides the maximum flexibility, which contains most register
definitions of a DMA logical channel.
Fewer options are present in type 2.
Type 3 can just modify source/destinations address of transfers. In all
transfers, unmodified registers settings are maintained for the next
transfer.
Patch provides options / API for
1) Setting up a descriptor loading for DMA channel for sg type transfers
2) configuration with linked list elements
3) Starting / pause and resume of the said transfers, query state
4) Clearing the sglist mode
Signed-off-by: Venkatraman S <svenkatr@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Cc: 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 | 257 +++++++++++++++++++++++++++++++++
arch/arm/plat-omap/dma.c | 1 +
arch/arm/plat-omap/include/plat/dma.h | 111 ++++++++++++++-
3 files changed, 368 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 6df4835..397e90e 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -41,6 +41,7 @@
static u32 errata;
static int dma_chan_count;
+static int dma_caps0_status;
static struct omap_dma_dev_attr *d;
static struct dma_link_info *dma_linked_lch;
@@ -240,6 +241,76 @@ static inline void omap2_disable_lnk(int lch)
dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
}
+static inline void omap_dma_list_set_ntype(struct omap_dma_sglist_node *node,
+ int value)
+{
+ node->num_of_elem |= ((value) << 29);
+}
+
+static void omap_set_dma_sglist_pausebit(
+ struct omap_dma_list_config_params *lcfg, int nelem, int set)
+{
+ struct omap_dma_sglist_node *sgn = lcfg->sghead;
+
+ if (nelem > 0 && nelem < lcfg->num_elem) {
+ lcfg->pausenode = nelem;
+ sgn += nelem;
+
+ if (set)
+ sgn->next_desc_add_ptr |= DMA_LIST_DESC_PAUSE;
+ else
+ sgn->next_desc_add_ptr &= ~(DMA_LIST_DESC_PAUSE);
+ }
+}
+
+static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead,
+ dma_addr_t phyaddr, int nelem)
+{
+ struct omap_dma_sglist_node *sgcurr, *sgprev;
+ dma_addr_t elem_paddr = phyaddr;
+
+ for (sgprev = sghead;
+ sgprev < sghead + nelem;
+ sgprev++) {
+
+ sgcurr = sgprev + 1;
+ sgprev->next = sgcurr;
+ elem_paddr += (int)sizeof(*sgcurr);
+ sgprev->next_desc_add_ptr = elem_paddr;
+
+ switch (sgcurr->desc_type) {
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1:
+ omap_dma_list_set_ntype(sgprev, 1);
+ break;
+
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a:
+ /* intentional no break */
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b:
+ omap_dma_list_set_ntype(sgprev, 2);
+ break;
+
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a:
+ /* intentional no break */
+ case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b:
+ omap_dma_list_set_ntype(sgprev, 3);
+ break;
+
+ default:
+ return -EINVAL;
+
+ }
+ if (sgcurr->flags & OMAP_DMA_LIST_SRC_VALID)
+ sgprev->num_of_elem |= DMA_LIST_DESC_SRC_VALID;
+ if (sgcurr->flags & OMAP_DMA_LIST_DST_VALID)
+ sgprev->num_of_elem |= DMA_LIST_DESC_DST_VALID;
+ if (sgcurr->flags & OMAP_DMA_LIST_NOTIFY_BLOCK_END)
+ sgprev->num_of_elem |= DMA_LIST_DESC_BLK_END;
+ }
+ sgprev--;
+ sgprev->next_desc_add_ptr = OMAP_DMA_INVALID_DESCRIPTOR_POINTER;
+ return 0;
+}
+
static void
omap2_set_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
{
@@ -1207,6 +1278,190 @@ int omap_get_dma_chain_src_pos(int chain_id)
}
EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
+int omap_set_dma_sglist_mode(int lch, struct omap_dma_sglist_node *sgparams,
+ dma_addr_t padd, int nelem, struct omap_dma_channel_params *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;
+ u32 sys_cf = 0;
+
+ 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();
+
+ /* Configure No-Standby */
+ if (IS_DMA_ERRATA(DMA_ERRATA_i541))
+ omap_device_mstandby(pd, &sys_cf, true);
+
+ /* Clear pause bit in CDP */
+ l = dma_read(CDP, lch);
+ l &= ~(DMA_LIST_CDP_PAUSEMODE);
+ dma_write(l, CDP, lch);
+
+ omap_start_dma(lch);
+
+ if (IS_DMA_ERRATA(DMA_ERRATA_i541))
+ omap_device_mstandby(pd, &sys_cf, false);
+
+ 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);
+
/* One time initializations */
static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
{
@@ -1245,6 +1500,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
p->disable_lnk = omap2_disable_lnk;
p->set_global_params = omap_dma_set_global_params;
+ p->clear_dma_sglist_mode = omap_clear_dma_sglist_mode;
p->clear_lch_regs = NULL;
p->get_gdma_dev = NULL;
@@ -1306,6 +1562,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
return -ENOMEM;
}
dma_chan = d->chan;
+ dma_caps0_status = dma_read(CAPS_0, 0);
return 0;
}
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index eb00b22..41b14b0 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -450,6 +450,7 @@ void omap_free_dma(int lch)
/* Make sure the DMA transfer is stopped. */
dma_write(0, CCR, lch);
omap_clear_dma(lch);
+ p->clear_dma_sglist_mode(lch);
}
spin_lock_irqsave(&dma_chan_lock, flags);
dma_chan[lch].dev_id = -1;
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 477f0d2..3e324b7 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -351,6 +351,113 @@ struct omap_dma_channel_params {
#endif
};
+/* CDP Register bitmaps */
+#define DMA_LIST_CDP_DST_VALID (BIT(0))
+#define DMA_LIST_CDP_SRC_VALID (BIT(2))
+#define DMA_LIST_CDP_TYPE1 (BIT(4))
+#define DMA_LIST_CDP_TYPE2 (BIT(5))
+#define DMA_LIST_CDP_TYPE3 (BIT(4) | BIT(5))
+#define DMA_LIST_CDP_PAUSEMODE (BIT(7))
+#define DMA_LIST_CDP_LISTMODE (BIT(8))
+#define DMA_LIST_CDP_FASTMODE (BIT(10))
+/* CAPS register bitmaps */
+#define DMA_CAPS_SGLIST_SUPPORT (BIT(20))
+
+#define DMA_LIST_DESC_PAUSE (BIT(0))
+#define DMA_LIST_DESC_SRC_VALID (BIT(24))
+#define DMA_LIST_DESC_DST_VALID (BIT(26))
+#define DMA_LIST_DESC_BLK_END (BIT(28))
+
+#define OMAP_DMA_INVALID_FRAME_COUNT (0xffff)
+#define OMAP_DMA_INVALID_ELEM_COUNT (0xffffff)
+#define OMAP_DMA_INVALID_DESCRIPTOR_POINTER (0xfffffffc)
+
+struct omap_dma_list_config_params {
+ unsigned int num_elem;
+ struct omap_dma_sglist_node *sghead;
+ dma_addr_t sgheadphy;
+ unsigned int pausenode;
+};
+
+struct omap_dma_sglist_type1_params {
+ u32 src_addr;
+ u32 dst_addr;
+ u16 cfn_fn;
+ u16 cicr;
+ u16 dst_elem_idx;
+ u16 src_elem_idx;
+ u32 dst_frame_idx_or_pkt_size;
+ u32 src_frame_idx_or_pkt_size;
+ u32 color;
+ u32 csdp;
+ u32 clnk_ctrl;
+ u32 ccr;
+};
+
+struct omap_dma_sglist_type2a_params {
+ u32 src_addr;
+ u32 dst_addr;
+ u16 cfn_fn;
+ u16 cicr;
+ u16 dst_elem_idx;
+ u16 src_elem_idx;
+ u32 dst_frame_idx_or_pkt_size;
+ u32 src_frame_idx_or_pkt_size;
+};
+
+struct omap_dma_sglist_type2b_params {
+ u32 src_or_dest_addr;
+ u16 cfn_fn;
+ u16 cicr;
+ u16 dst_elem_idx;
+ u16 src_elem_idx;
+ u32 dst_frame_idx_or_pkt_size;
+ u32 src_frame_idx_or_pkt_size;
+};
+
+struct omap_dma_sglist_type3a_params {
+ u32 src_addr;
+ u32 dst_addr;
+};
+
+struct omap_dma_sglist_type3b_params {
+ u32 src_or_dest_addr;
+};
+
+enum omap_dma_sglist_descriptor_select {
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1,
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a,
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b,
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a,
+ OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b,
+};
+
+union omap_dma_sglist_node_type{
+ struct omap_dma_sglist_type1_params t1;
+ struct omap_dma_sglist_type2a_params t2a;
+ struct omap_dma_sglist_type2b_params t2b;
+ struct omap_dma_sglist_type3a_params t3a;
+ struct omap_dma_sglist_type3b_params t3b;
+};
+
+struct omap_dma_sglist_node {
+
+ /* Common elements for all descriptors */
+ dma_addr_t next_desc_add_ptr;
+ u32 num_of_elem;
+ /* Type specific elements */
+ union omap_dma_sglist_node_type sg_node;
+ /* Control fields */
+ unsigned short flags;
+ /* Fields that can be set in flags variable */
+ #define OMAP_DMA_LIST_SRC_VALID BIT(0)
+ #define OMAP_DMA_LIST_DST_VALID BIT(1)
+ #define OMAP_DMA_LIST_NOTIFY_BLOCK_END BIT(2)
+ enum omap_dma_sglist_descriptor_select desc_type;
+ struct omap_dma_sglist_node *next;
+};
+
+
#include <mach/dma.h>
struct omap_dma_lch {
int next_lch;
@@ -367,6 +474,7 @@ struct omap_dma_lch {
int state;
int chain_id;
int status;
+ struct omap_dma_list_config_params list_config;
};
struct omap_dma_dev_attr {
@@ -410,6 +518,7 @@ struct omap_system_dma_plat_info {
void (*set_global_params)(int arb_rate,
int max_fifo_depth, int tparams);
+ void (*clear_dma_sglist_mode)(int lch);
};
extern void omap_set_dma_priority(int lch, int dst_port, int priority);
@@ -472,7 +581,7 @@ void omap_dma_global_context_save(void);
void omap_dma_global_context_restore(void);
extern void omap_dma_disable_irq(int lch);
-
+void omap_clear_dma_sglist_mode(int lch);
#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
#include <mach/lcd_dma.h>
#else
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 13/13] OMAP: PM: DMA: Enable runtime pm
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (11 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 12/13] OMAP2+: DMA: descriptor autoloading feature G, Manjunath Kondaiah
@ 2010-10-26 13:25 ` G, Manjunath Kondaiah
2010-11-09 22:48 ` Kevin Hilman
2010-10-27 4:57 ` [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
2010-11-09 23:11 ` Kevin Hilman
14 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-26 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Enable runtime pm and use pm_runtime_get and pm_runtime_put
for OMAP DMA driver.
Signed-off-by: G, Manjunath Kondaiah <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/dma.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 41b14b0..feac7ee 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -35,6 +35,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include <asm/system.h>
#include <mach/hardware.h>
@@ -367,6 +368,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(&pd->dev);
+
if (d->dev_caps & IS_WORD_16)
p->clear_lch_regs(free_ch);
else
@@ -452,6 +455,7 @@ void omap_free_dma(int lch)
omap_clear_dma(lch);
p->clear_dma_sglist_mode(lch);
}
+ pm_runtime_put(&pd->dev);
spin_lock_irqsave(&dma_chan_lock, flags);
dma_chan[lch].dev_id = -1;
dma_chan[lch].next_lch = -1;
@@ -819,6 +823,11 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
dma_chan_count = d->chan_count;
dma_chan = d->chan;
+ /* Enable run time PM */
+ pm_runtime_enable(&pd->dev);
+
+ /* Accessing hw registers, get clock */
+ pm_runtime_get(&pd->dev);
for (ch = 0; ch < dma_chan_count; ch++) {
unsigned long flags;
omap_clear_dma(ch);
@@ -846,6 +855,10 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
dma_chan[0].dev_id = 0;
dma_chan[1].dev_id = 1;
}
+
+ if (!omap_dma_reserve_channels)
+ pm_runtime_put(&pd->dev);
+
return 0;
exit_release_region:
--
1.7.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v3 13/13] OMAP: PM: DMA: Enable runtime pm
2010-10-26 13:25 ` [PATCH v3 13/13] OMAP: PM: DMA: Enable runtime pm G, Manjunath Kondaiah
@ 2010-11-09 22:48 ` Kevin Hilman
2010-11-10 14:02 ` G, Manjunath Kondaiah
0 siblings, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 22:48 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> Enable runtime pm and use pm_runtime_get and pm_runtime_put
> for OMAP DMA driver.
>
> Signed-off-by: G, Manjunath Kondaiah <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/dma.c | 13 +++++++++++++
> 1 files changed, 13 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
> index 41b14b0..feac7ee 100644
> --- a/arch/arm/plat-omap/dma.c
> +++ b/arch/arm/plat-omap/dma.c
> @@ -35,6 +35,7 @@
> #include <linux/io.h>
> #include <linux/slab.h>
> #include <linux/delay.h>
> +#include <linux/pm_runtime.h>
>
> #include <asm/system.h>
> #include <mach/hardware.h>
> @@ -367,6 +368,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(&pd->dev);
The _get() call is asynchronous. So if the device was actually
idled/disabled, immediately after this call it may still be
idle/disabled. When using the asynchronous versions of the API, the
device should not be touched until the driver's ->runtime_resume()
callback is called.
> if (d->dev_caps & IS_WORD_16)
> p->clear_lch_regs(free_ch);
> else
> @@ -452,6 +455,7 @@ void omap_free_dma(int lch)
> omap_clear_dma(lch);
> p->clear_dma_sglist_mode(lch);
> }
> + pm_runtime_put(&pd->dev);
> spin_lock_irqsave(&dma_chan_lock, flags);
> dma_chan[lch].dev_id = -1;
> dma_chan[lch].next_lch = -1;
> @@ -819,6 +823,11 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
> dma_chan_count = d->chan_count;
> dma_chan = d->chan;
>
> + /* Enable run time PM */
comment is redundant
> + pm_runtime_enable(&pd->dev);
> +
> + /* Accessing hw registers, get clock */
comment is wrong, driver doesn't know anything about clocks.
Just drop comment as it doesn't tell you anything that the following
'get' doesn't.
> + pm_runtime_get(&pd->dev);
see above Re: async calls.
> for (ch = 0; ch < dma_chan_count; ch++) {
> unsigned long flags;
> omap_clear_dma(ch);
> @@ -846,6 +855,10 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
> dma_chan[0].dev_id = 0;
> dma_chan[1].dev_id = 1;
> }
> +
> + if (!omap_dma_reserve_channels)
> + pm_runtime_put(&pd->dev);
> +
So if the reserve channels feature is used, PM is essentially disabled
for sDMA. You should add a warning here to that effect as well.
> return 0;
>
> exit_release_region:
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 13/13] OMAP: PM: DMA: Enable runtime pm
2010-11-09 22:48 ` Kevin Hilman
@ 2010-11-10 14:02 ` G, Manjunath Kondaiah
2010-11-10 16:14 ` Kevin Hilman
0 siblings, 1 reply; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 14:02 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: linux-omap-owner at vger.kernel.org
> [mailto:linux-omap-owner at vger.kernel.org] On Behalf Of Kevin Hilman
> Sent: Wednesday, November 10, 2010 4:18 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Shilimkar, Santosh
> Subject: Re: [PATCH v3 13/13] OMAP: PM: DMA: Enable runtime pm
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
> > Enable runtime pm and use pm_runtime_get and pm_runtime_put
> > for OMAP DMA driver.
> >
> > Signed-off-by: G, Manjunath Kondaiah <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/dma.c | 13 +++++++++++++
> > 1 files changed, 13 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
> > index 41b14b0..feac7ee 100644
> > --- a/arch/arm/plat-omap/dma.c
> > +++ b/arch/arm/plat-omap/dma.c
> > @@ -35,6 +35,7 @@
> > #include <linux/io.h>
> > #include <linux/slab.h>
> > #include <linux/delay.h>
> > +#include <linux/pm_runtime.h>
> >
> > #include <asm/system.h>
> > #include <mach/hardware.h>
> > @@ -367,6 +368,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(&pd->dev);
>
> The _get() call is asynchronous. So if the device was actually
> idled/disabled, immediately after this call it may still be
> idle/disabled. When using the asynchronous versions of the API, the
> device should not be touched until the driver's ->runtime_resume()
> callback is called.
driver runtime_resume will call omap_device_enable. How do we make
we check from driver side, whether omap_device_enable execution is complete
or not.
>
> > if (d->dev_caps & IS_WORD_16)
> > p->clear_lch_regs(free_ch);
> > else
> > @@ -452,6 +455,7 @@ void omap_free_dma(int lch)
> > omap_clear_dma(lch);
> > p->clear_dma_sglist_mode(lch);
> > }
> > + pm_runtime_put(&pd->dev);
> > spin_lock_irqsave(&dma_chan_lock, flags);
> > dma_chan[lch].dev_id = -1;
> > dma_chan[lch].next_lch = -1;
> > @@ -819,6 +823,11 @@ static int __devinit
> omap_system_dma_probe(struct platform_device *pdev)
> > dma_chan_count = d->chan_count;
> > dma_chan = d->chan;
> >
> > + /* Enable run time PM */
>
> comment is redundant
ok.
>
> > + pm_runtime_enable(&pd->dev);
> > +
> > + /* Accessing hw registers, get clock */
>
> comment is wrong, driver doesn't know anything about clocks.
> Just drop comment as it doesn't tell you anything that the following
> 'get' doesn't.
>
> > + pm_runtime_get(&pd->dev);
>
> see above Re: async calls.
>
> > for (ch = 0; ch < dma_chan_count; ch++) {
> > unsigned long flags;
> > omap_clear_dma(ch);
> > @@ -846,6 +855,10 @@ static int __devinit
> omap_system_dma_probe(struct platform_device *pdev)
> > dma_chan[0].dev_id = 0;
> > dma_chan[1].dev_id = 1;
> > }
> > +
> > + if (!omap_dma_reserve_channels)
> > + pm_runtime_put(&pd->dev);
> > +
>
> So if the reserve channels feature is used, PM is essentially disabled
> for sDMA. You should add a warning here to that effect as well.
I will add warning comment.
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 13/13] OMAP: PM: DMA: Enable runtime pm
2010-11-10 14:02 ` G, Manjunath Kondaiah
@ 2010-11-10 16:14 ` Kevin Hilman
0 siblings, 0 replies; 50+ messages in thread
From: Kevin Hilman @ 2010-11-10 16:14 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>>
>> > Enable runtime pm and use pm_runtime_get and pm_runtime_put
>> > for OMAP DMA driver.
>> >
>> > Signed-off-by: G, Manjunath Kondaiah <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/dma.c | 13 +++++++++++++
>> > 1 files changed, 13 insertions(+), 0 deletions(-)
>> >
>> > diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
>> > index 41b14b0..feac7ee 100644
>> > --- a/arch/arm/plat-omap/dma.c
>> > +++ b/arch/arm/plat-omap/dma.c
>> > @@ -35,6 +35,7 @@
>> > #include <linux/io.h>
>> > #include <linux/slab.h>
>> > #include <linux/delay.h>
>> > +#include <linux/pm_runtime.h>
>> >
>> > #include <asm/system.h>
>> > #include <mach/hardware.h>
>> > @@ -367,6 +368,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(&pd->dev);
>>
>> The _get() call is asynchronous. So if the device was actually
>> idled/disabled, immediately after this call it may still be
>> idle/disabled. When using the asynchronous versions of the API, the
>> device should not be touched until the driver's ->runtime_resume()
>> callback is called.
>
> driver runtime_resume will call omap_device_enable. How do we make
> we check from driver side, whether omap_device_enable execution is complete
> or not.
It is complete when the driver's runtime_resume hook is called. The
OMAP runtime PM core calls omap_device_enable() before calling the
driver's callback. See arch/arm/mach-omap2/pm_bus.c for details.
Alternatively, just use _get_sync() which doesn't return until the
device is ready.
Kevin
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (12 preceding siblings ...)
2010-10-26 13:25 ` [PATCH v3 13/13] OMAP: PM: DMA: Enable runtime pm G, Manjunath Kondaiah
@ 2010-10-27 4:57 ` G, Manjunath Kondaiah
2010-11-09 23:11 ` Kevin Hilman
14 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-10-27 4:57 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
> -----Original Message-----
> From: linux-omap-owner at vger.kernel.org
> [mailto:linux-omap-owner at vger.kernel.org] On Behalf Of G,
> Manjunath Kondaiah
> Sent: Tuesday, October 26, 2010 6:55 PM
> To: linux-omap at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Kevin Hilman; Shilimkar, Santosh
> Subject: [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device
>
> This patch series converts DMA library into platform device
> and hwmod adaptation is done for omap2+ processors.
>
[...]
>
> G, Manjunath Kondaiah (12):
[...]
> OMAP: DMA: Use DMA device attributes
Looks like this patch is not getting posted due to its size(~105 KB)
The patch is available for review comments at:
http://dev.omapzoom.org/?p=manju/kernel-omap3-dev.git;a=commitdiff;h=7457a6b4248772aaa52dfb13a170f891596a512a
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device
2010-10-26 13:25 [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
` (13 preceding siblings ...)
2010-10-27 4:57 ` [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device G, Manjunath Kondaiah
@ 2010-11-09 23:11 ` Kevin Hilman
2010-11-10 14:02 ` G, Manjunath Kondaiah
14 siblings, 1 reply; 50+ messages in thread
From: Kevin Hilman @ 2010-11-09 23:11 UTC (permalink / raw)
To: linux-arm-kernel
"G, Manjunath Kondaiah" <manjugk@ti.com> writes:
> This patch series converts DMA library into platform device and hwmod
> adaptation is done for omap2+ processors.
>
> It also replaces cpu_*is* checks by moving omap1 and omap2+ processor
> code into repsective mach-omapx directories. The common code in plat-omap
> will use device attributes for differentiating omap1 and omap2 code.
This summary, and the various changelogs need to be updated to be more
descriptive, particularily in the usage of the words 'device' and
'driver'.
The changelog terminology used is confusing, and sometimes wrong. What
is actually being done is splitting up the current DMA library into 3
parts: a common platform_driver (plat-omap/dma.c), OMAP1 device code
(mach-omap1/dma.c) and OMAP2+ device code (mach-omap2/dma.c)
> Build Report:
> omap1: Success for omap_h2_1610_defconfig
> omap2+: Success for omap2plus_defconfig
>
> Test Report:
> omap2+:(multiboot defconfig boots on all the omap2+ boards listed below):
> OMAP4BLAZE: http://pastebin.com/HVnim30G
> OMAP3630ZOOM3: http://pastebin.com/JJwrtP4F
> OMAP243SDP: http://pastebin.com/mz7cVQL3
>
> omap1 : Not tested
>
> Test cases executed:
> 1. All applicable TI DMA tests which are located at:
> http://dev.omapzoom.org/?p=richo/device_driver_test.git;a=tree;f=dma/test_code;h=0d00de3c0fe6933b405c62da63f694883f3e4b8f;hb=2c50a5a58dea0ffc2d31b827935aeef9b9d11253
>
> 2. Use case tests : TI MMC tests are executed with differenct types of
> files systems such as DOS, ext2, ext3 etc on omap4 blaze and omap3630 zoom3.
> More information can be found at:
> http://dev.omapzoom.org/?p=richo/device_driver_test.git;a=tree;f=mmc/test_code;h=d0bc1984eef46ac45719efb02b5c1f4193422a1b;hb=2c50a5a58dea0ffc2d31b827935aeef9b9d11253
>
> Dependencies:
> This patch series has dependency on omap_device patch:
> https://patchwork.kernel.org/patch/282212/
Thanks for the thorough build and test report. Very nice.
Kevin
> This patch series applies on:
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> Branch: master
> commit a83d12a47c9a8c78a184910150797045d69a1570
> Merge: f9f47f5 c1fb8df
> Author: Tony Lindgren <tony@atomide.com>
> Date: Fri Oct 22 11:21:08 2010 -0700
>
> Linux-omap rebuilt: Updated to v2.6.36, add 24xx uart fix
>
> Changelist summary:
> v3:
> Review comments fixed:
> http://www.listware.net/201008/linux-omap/89002-patch-v2-0011-omap-dma-hwmod-and-dma-as-platform-driver.html
> - created and tested on latest linux-omap master branch(2.6.36 kernel)
>
> v2:
> The review comments which are fixed can be found at:
> http://www.spinics.net/lists/linux-omap/msg34291.html
> http://www.spinics.net/lists/linux-omap/msg34292.html
> http://www.spinics.net/lists/linux-omap/msg34078.html
> http://www.spinics.net/lists/linux-omap/msg34083.html
>
> v1:
> These changes are based on comments received during internal discussions which has changes(compared to previous version) such as:
> - Code optimization
> - Patches are rearranged in more meaningful way so that git bisect works at any
> intermediate patch in the series.
> - Build tested for all omap's(OMAP1 and OMAP2PLUS)
> - Boot tested for OMAP3 and OMAP4(appreciate if some one tests on OMAP1/2)
> - Applicalbe tests are executed on OMAP3 and OMAP4 boards
> - Rebased and added descriptor autoloading feature(only for omap3630 and omap4)
>
>
> Benoit Cousson (1):
> OMAP4: DMA: hwmod: add system DMA
>
> G, Manjunath Kondaiah (12):
> OMAP: DMA: Replace read/write macros with functions
> OMAP: DMA: Introduce errata handling feature
> OMAP: DMA: Introduce DMA device attributes
> OMAP2420: DMA: hwmod: add system DMA
> OMAP2430: DMA: hwmod: add system DMA
> OMAP3: DMA: hwmod: add system DMA
> OMAP1: DMA: Introduce DMA driver as platform device
> OMAP2+: DMA: hwmod: Device registration
> OMAP: DMA: Convert DMA library into DMA platform Driver
> OMAP: DMA: Use DMA device attributes
> sDMA: descriptor autoloading feature
> OMAP: PM: DMA: Enable runtime pm
>
> arch/arm/mach-omap1/Makefile | 2 +-
> arch/arm/mach-omap1/dma.c | 665 ++++++++++
> arch/arm/mach-omap1/include/mach/dma.h | 51 +
> arch/arm/mach-omap2/Makefile | 2 +-
> arch/arm/mach-omap2/dma.c | 1579 ++++++++++++++++++++++++
> arch/arm/mach-omap2/include/mach/dma.h | 86 ++
> 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 | 93 ++
> arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 99 ++
> arch/arm/plat-omap/dma.c | 1850 ++++------------------------
> arch/arm/plat-omap/include/plat/dma.h | 387 ++++---
> 12 files changed, 3207 insertions(+), 1777 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] 50+ messages in thread* [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as platform device
2010-11-09 23:11 ` Kevin Hilman
@ 2010-11-10 14:02 ` G, Manjunath Kondaiah
0 siblings, 0 replies; 50+ messages in thread
From: G, Manjunath Kondaiah @ 2010-11-10 14:02 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
> Sent: Wednesday, November 10, 2010 4:42 AM
> To: G, Manjunath Kondaiah
> Cc: linux-omap at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; Cousson, Benoit;
> Shilimkar, Santosh
> Subject: Re: [PATCH v3 00/13] OMAP: DMA: hwmod and DMA as
> platform device
>
> "G, Manjunath Kondaiah" <manjugk@ti.com> writes:
>
> > This patch series converts DMA library into platform device
> and hwmod
> > adaptation is done for omap2+ processors.
> >
> > It also replaces cpu_*is* checks by moving omap1 and omap2+
> processor
> > code into repsective mach-omapx directories. The common
> code in plat-omap
> > will use device attributes for differentiating omap1 and omap2 code.
>
> This summary, and the various changelogs need to be updated to be more
> descriptive, particularily in the usage of the words 'device' and
> 'driver'.
>
> The changelog terminology used is confusing, and sometimes
> wrong. What
> is actually being done is splitting up the current DMA library into 3
> parts: a common platform_driver (plat-omap/dma.c), OMAP1 device code
> (mach-omap1/dma.c) and OMAP2+ device code (mach-omap2/dma.c)
I will incorporate this with next version.
>
> > Build Report:
> > omap1: Success for omap_h2_1610_defconfig
> > omap2+: Success for omap2plus_defconfig
> >
> > Test Report:
> > omap2+:(multiboot defconfig boots on all the omap2+ boards
> listed below):
> > OMAP4BLAZE: http://pastebin.com/HVnim30G
> > OMAP3630ZOOM3: http://pastebin.com/JJwrtP4F
> > OMAP243SDP: http://pastebin.com/mz7cVQL3
> >
> > omap1 : Not tested
> >
> > Test cases executed:
> > 1. All applicable TI DMA tests which are located at:
> >
> http://dev.omapzoom.org/?p=richo/device_driver_test.git;a=tree
;f=dma/test_code;h=0d00de3c0fe6933b405c62da63f694883f3e4b8f;hb=> 2c50a5a58dea0ffc2d31b827935aeef9b9d11253
> >
> > 2. Use case tests : TI MMC tests are executed with
> differenct types of
> > files systems such as DOS, ext2, ext3 etc on omap4 blaze
> and omap3630 zoom3.
> > More information can be found at:
> >
> http://dev.omapzoom.org/?p=richo/device_driver_test.git;a=tree
;f=mmc/test_code;h=d0bc1984eef46ac45719efb02b5c1f4193422a1b;hb=> 2c50a5a58dea0ffc2d31b827935aeef9b9d11253
> >
> > Dependencies:
> > This patch series has dependency on omap_device patch:
> > https://patchwork.kernel.org/patch/282212/
>
> Thanks for the thorough build and test report. Very nice.
Thanks for the feedback.
-Manjunath
^ permalink raw reply [flat|nested] 50+ messages in thread