* [PATCH 20/26] ARM: omap: clean up DMA register accesses
From: Russell King @ 2014-02-10 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
We can do much better with this by using a structure to describe each
register, rather than code.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/mach-omap1/dma.c | 117 +++++++++++++++++++++-------------------------
arch/arm/mach-omap2/dma.c | 99 +++++++++++++++++++--------------------
include/linux/omap-dma.h | 13 ++++++
3 files changed, 115 insertions(+), 114 deletions(-)
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 11f0b0ee67a3..b680db7a35d4 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -32,53 +32,52 @@
#define OMAP1_DMA_BASE (0xfffed800)
#define OMAP1_LOGICAL_DMA_CH_COUNT 17
-#define OMAP1_DMA_STRIDE 0x40
static u32 errata;
static u32 enable_1510_mode;
-static u16 reg_map[] = {
- [GCR] = 0x400,
- [GSCR] = 0x404,
- [GRST1] = 0x408,
- [HW_ID] = 0x442,
- [PCH2_ID] = 0x444,
- [PCH0_ID] = 0x446,
- [PCH1_ID] = 0x448,
- [PCHG_ID] = 0x44a,
- [PCHD_ID] = 0x44c,
- [CAPS_0] = 0x44e,
- [CAPS_1] = 0x452,
- [CAPS_2] = 0x456,
- [CAPS_3] = 0x458,
- [CAPS_4] = 0x45a,
- [PCH2_SR] = 0x460,
- [PCH0_SR] = 0x480,
- [PCH1_SR] = 0x482,
- [PCHD_SR] = 0x4c0,
+static const struct omap_dma_reg reg_map[] = {
+ [GCR] = { 0x0400, 0x00, OMAP_DMA_REG_16BIT },
+ [GSCR] = { 0x0404, 0x00, OMAP_DMA_REG_16BIT },
+ [GRST1] = { 0x0408, 0x00, OMAP_DMA_REG_16BIT },
+ [HW_ID] = { 0x0442, 0x00, OMAP_DMA_REG_16BIT },
+ [PCH2_ID] = { 0x0444, 0x00, OMAP_DMA_REG_16BIT },
+ [PCH0_ID] = { 0x0446, 0x00, OMAP_DMA_REG_16BIT },
+ [PCH1_ID] = { 0x0448, 0x00, OMAP_DMA_REG_16BIT },
+ [PCHG_ID] = { 0x044a, 0x00, OMAP_DMA_REG_16BIT },
+ [PCHD_ID] = { 0x044c, 0x00, OMAP_DMA_REG_16BIT },
+ [CAPS_0] = { 0x044e, 0x00, OMAP_DMA_REG_2X16BIT },
+ [CAPS_1] = { 0x0452, 0x00, OMAP_DMA_REG_2X16BIT },
+ [CAPS_2] = { 0x0456, 0x00, OMAP_DMA_REG_16BIT },
+ [CAPS_3] = { 0x0458, 0x00, OMAP_DMA_REG_16BIT },
+ [CAPS_4] = { 0x045a, 0x00, OMAP_DMA_REG_16BIT },
+ [PCH2_SR] = { 0x0460, 0x00, OMAP_DMA_REG_16BIT },
+ [PCH0_SR] = { 0x0480, 0x00, OMAP_DMA_REG_16BIT },
+ [PCH1_SR] = { 0x0482, 0x00, OMAP_DMA_REG_16BIT },
+ [PCHD_SR] = { 0x04c0, 0x00, OMAP_DMA_REG_16BIT },
/* Common Registers */
- [CSDP] = 0x00,
- [CCR] = 0x02,
- [CICR] = 0x04,
- [CSR] = 0x06,
- [CEN] = 0x10,
- [CFN] = 0x12,
- [CSFI] = 0x14,
- [CSEI] = 0x16,
- [CPC] = 0x18, /* 15xx only */
- [CSAC] = 0x18,
- [CDAC] = 0x1a,
- [CDEI] = 0x1c,
- [CDFI] = 0x1e,
- [CLNK_CTRL] = 0x28,
+ [CSDP] = { 0x0000, 0x40, OMAP_DMA_REG_16BIT },
+ [CCR] = { 0x0002, 0x40, OMAP_DMA_REG_16BIT },
+ [CICR] = { 0x0004, 0x40, OMAP_DMA_REG_16BIT },
+ [CSR] = { 0x0006, 0x40, OMAP_DMA_REG_16BIT },
+ [CEN] = { 0x0010, 0x40, OMAP_DMA_REG_16BIT },
+ [CFN] = { 0x0012, 0x40, OMAP_DMA_REG_16BIT },
+ [CSFI] = { 0x0014, 0x40, OMAP_DMA_REG_16BIT },
+ [CSEI] = { 0x0016, 0x40, OMAP_DMA_REG_16BIT },
+ [CPC] = { 0x0018, 0x40, OMAP_DMA_REG_16BIT }, /* 15xx only */
+ [CSAC] = { 0x0018, 0x40, OMAP_DMA_REG_16BIT },
+ [CDAC] = { 0x001a, 0x40, OMAP_DMA_REG_16BIT },
+ [CDEI] = { 0x001c, 0x40, OMAP_DMA_REG_16BIT },
+ [CDFI] = { 0x001e, 0x40, OMAP_DMA_REG_16BIT },
+ [CLNK_CTRL] = { 0x0028, 0x40, OMAP_DMA_REG_16BIT },
/* Channel specific register offsets */
- [CSSA] = 0x08,
- [CDSA] = 0x0c,
- [COLOR] = 0x20,
- [CCR2] = 0x24,
- [LCH_CTRL] = 0x2a,
+ [CSSA] = { 0x0008, 0x40, OMAP_DMA_REG_2X16BIT },
+ [CDSA] = { 0x000c, 0x40, OMAP_DMA_REG_2X16BIT },
+ [COLOR] = { 0x0020, 0x40, OMAP_DMA_REG_2X16BIT },
+ [CCR2] = { 0x0024, 0x40, OMAP_DMA_REG_16BIT },
+ [LCH_CTRL] = { 0x002a, 0x40, OMAP_DMA_REG_16BIT },
};
static struct resource res[] __initdata = {
@@ -179,36 +178,28 @@ static struct resource res[] __initdata = {
static void __iomem *dma_base;
static inline void dma_write(u32 val, int reg, int lch)
{
- u8 stride;
- u32 offset;
+ void __iomem *addr = dma_base;
- stride = (reg >= CPC) ? OMAP1_DMA_STRIDE : 0;
- offset = reg_map[reg] + (stride * lch);
+ addr += reg_map[reg].offset;
+ addr += reg_map[reg].stride * lch;
- __raw_writew(val, dma_base + offset);
- if ((reg > CLNK_CTRL && reg < CCEN) ||
- (reg > PCHD_ID && reg < CAPS_2)) {
- u32 offset2 = reg_map[reg] + 2 + (stride * lch);
- __raw_writew(val >> 16, dma_base + offset2);
- }
+ __raw_writew(val, addr);
+ if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT)
+ __raw_writew(val >> 16, addr + 2);
}
static inline u32 dma_read(int reg, int lch)
{
- u8 stride;
- u32 offset, val;
-
- stride = (reg >= CPC) ? OMAP1_DMA_STRIDE : 0;
- offset = reg_map[reg] + (stride * lch);
-
- val = __raw_readw(dma_base + offset);
- if ((reg > CLNK_CTRL && reg < CCEN) ||
- (reg > PCHD_ID && reg < CAPS_2)) {
- u16 upper;
- u32 offset2 = reg_map[reg] + 2 + (stride * lch);
- upper = __raw_readw(dma_base + offset2);
- val |= (upper << 16);
- }
+ void __iomem *addr = dma_base;
+ uint32_t val;
+
+ addr += reg_map[reg].offset;
+ addr += reg_map[reg].stride * lch;
+
+ val = __raw_readw(addr);
+ if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT)
+ val |= __raw_readw(addr + 2) << 16;
+
return val;
}
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index e4ac7ac9a228..e633b48a3fcb 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -35,80 +35,77 @@
#include "omap_hwmod.h"
#include "omap_device.h"
-#define OMAP2_DMA_STRIDE 0x60
-
static u32 errata;
static struct omap_dma_dev_attr *d;
static enum omap_reg_offsets dma_common_ch_end;
-static u16 reg_map[] = {
- [REVISION] = 0x00,
- [GCR] = 0x78,
- [IRQSTATUS_L0] = 0x08,
- [IRQSTATUS_L1] = 0x0c,
- [IRQSTATUS_L2] = 0x10,
- [IRQSTATUS_L3] = 0x14,
- [IRQENABLE_L0] = 0x18,
- [IRQENABLE_L1] = 0x1c,
- [IRQENABLE_L2] = 0x20,
- [IRQENABLE_L3] = 0x24,
- [SYSSTATUS] = 0x28,
- [OCP_SYSCONFIG] = 0x2c,
- [CAPS_0] = 0x64,
- [CAPS_2] = 0x6c,
- [CAPS_3] = 0x70,
- [CAPS_4] = 0x74,
+static const struct omap_dma_reg reg_map[] = {
+ [REVISION] = { 0x0000, 0x00, OMAP_DMA_REG_32BIT },
+ [GCR] = { 0x0078, 0x00, OMAP_DMA_REG_32BIT },
+ [IRQSTATUS_L0] = { 0x0008, 0x00, OMAP_DMA_REG_32BIT },
+ [IRQSTATUS_L1] = { 0x000c, 0x00, OMAP_DMA_REG_32BIT },
+ [IRQSTATUS_L2] = { 0x0010, 0x00, OMAP_DMA_REG_32BIT },
+ [IRQSTATUS_L3] = { 0x0014, 0x00, OMAP_DMA_REG_32BIT },
+ [IRQENABLE_L0] = { 0x0018, 0x00, OMAP_DMA_REG_32BIT },
+ [IRQENABLE_L1] = { 0x001c, 0x00, OMAP_DMA_REG_32BIT },
+ [IRQENABLE_L2] = { 0x0020, 0x00, OMAP_DMA_REG_32BIT },
+ [IRQENABLE_L3] = { 0x0024, 0x00, OMAP_DMA_REG_32BIT },
+ [SYSSTATUS] = { 0x0028, 0x00, OMAP_DMA_REG_32BIT },
+ [OCP_SYSCONFIG] = { 0x002c, 0x00, OMAP_DMA_REG_32BIT },
+ [CAPS_0] = { 0x0064, 0x00, OMAP_DMA_REG_32BIT },
+ [CAPS_2] = { 0x006c, 0x00, OMAP_DMA_REG_32BIT },
+ [CAPS_3] = { 0x0070, 0x00, OMAP_DMA_REG_32BIT },
+ [CAPS_4] = { 0x0074, 0x00, OMAP_DMA_REG_32BIT },
/* Common register offsets */
- [CCR] = 0x80,
- [CLNK_CTRL] = 0x84,
- [CICR] = 0x88,
- [CSR] = 0x8c,
- [CSDP] = 0x90,
- [CEN] = 0x94,
- [CFN] = 0x98,
- [CSEI] = 0xa4,
- [CSFI] = 0xa8,
- [CDEI] = 0xac,
- [CDFI] = 0xb0,
- [CSAC] = 0xb4,
- [CDAC] = 0xb8,
+ [CCR] = { 0x0080, 0x60, OMAP_DMA_REG_32BIT },
+ [CLNK_CTRL] = { 0x0084, 0x60, OMAP_DMA_REG_32BIT },
+ [CICR] = { 0x0088, 0x60, OMAP_DMA_REG_32BIT },
+ [CSR] = { 0x008c, 0x60, OMAP_DMA_REG_32BIT },
+ [CSDP] = { 0x0090, 0x60, OMAP_DMA_REG_32BIT },
+ [CEN] = { 0x0094, 0x60, OMAP_DMA_REG_32BIT },
+ [CFN] = { 0x0098, 0x60, OMAP_DMA_REG_32BIT },
+ [CSEI] = { 0x00a4, 0x60, OMAP_DMA_REG_32BIT },
+ [CSFI] = { 0x00a8, 0x60, OMAP_DMA_REG_32BIT },
+ [CDEI] = { 0x00ac, 0x60, OMAP_DMA_REG_32BIT },
+ [CDFI] = { 0x00b0, 0x60, OMAP_DMA_REG_32BIT },
+ [CSAC] = { 0x00b4, 0x60, OMAP_DMA_REG_32BIT },
+ [CDAC] = { 0x00b8, 0x60, OMAP_DMA_REG_32BIT },
/* Channel specific register offsets */
- [CSSA] = 0x9c,
- [CDSA] = 0xa0,
- [CCEN] = 0xbc,
- [CCFN] = 0xc0,
- [COLOR] = 0xc4,
+ [CSSA] = { 0x009c, 0x60, OMAP_DMA_REG_32BIT },
+ [CDSA] = { 0x00a0, 0x60, OMAP_DMA_REG_32BIT },
+ [CCEN] = { 0x00bc, 0x60, OMAP_DMA_REG_32BIT },
+ [CCFN] = { 0x00c0, 0x60, OMAP_DMA_REG_32BIT },
+ [COLOR] = { 0x00c4, 0x60, OMAP_DMA_REG_32BIT },
/* OMAP4 specific registers */
- [CDP] = 0xd0,
- [CNDP] = 0xd4,
- [CCDN] = 0xd8,
+ [CDP] = { 0x00d0, 0x60, OMAP_DMA_REG_32BIT },
+ [CNDP] = { 0x00d4, 0x60, OMAP_DMA_REG_32BIT },
+ [CCDN] = { 0x00d8, 0x60, OMAP_DMA_REG_32BIT },
};
static void __iomem *dma_base;
static inline void dma_write(u32 val, int reg, int lch)
{
- u8 stride;
- u32 offset;
+ void __iomem *addr = dma_base;
+
+ addr += reg_map[reg].offset;
+ addr += reg_map[reg].stride * lch;
- stride = (reg >= CSDP) ? OMAP2_DMA_STRIDE : 0;
- offset = reg_map[reg] + (stride * lch);
- __raw_writel(val, dma_base + offset);
+ __raw_writel(val, addr);
}
static inline u32 dma_read(int reg, int lch)
{
- u8 stride;
- u32 offset, val;
+ void __iomem *addr = dma_base;
+
+ addr += reg_map[reg].offset;
+ addr += reg_map[reg].stride * lch;
- stride = (reg >= CSDP) ? OMAP2_DMA_STRIDE : 0;
- offset = reg_map[reg] + (stride * lch);
- val = __raw_readl(dma_base + offset);
- return val;
+ return __raw_readl(addr);
}
static void omap2_clear_dma(int lch)
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index 0bb7de77d478..41328725721a 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -271,6 +271,19 @@ struct omap_dma_dev_attr {
struct omap_dma_lch *chan;
};
+enum {
+ OMAP_DMA_REG_NONE,
+ OMAP_DMA_REG_16BIT,
+ OMAP_DMA_REG_2X16BIT,
+ OMAP_DMA_REG_32BIT,
+};
+
+struct omap_dma_reg {
+ u16 offset;
+ u8 stride;
+ u8 type;
+};
+
/* System DMA platform data structure */
struct omap_system_dma_plat_info {
struct omap_dma_dev_attr *dma_attr;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 19/26] ARM: omap: remove almost-const variables
From: Russell King @ 2014-02-10 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
dma_stride and dma_common_ch_start are only ever initialised to one
known value at initialisation, and are private to each of these files.
There's no point these being variables at all.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/mach-omap1/dma.c | 14 ++++----------
arch/arm/mach-omap2/dma.c | 14 +++++---------
2 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index d292055d3117..11f0b0ee67a3 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -36,8 +36,6 @@
static u32 errata;
static u32 enable_1510_mode;
-static u8 dma_stride;
-static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
static u16 reg_map[] = {
[GCR] = 0x400,
@@ -184,7 +182,7 @@ static inline void dma_write(u32 val, int reg, int lch)
u8 stride;
u32 offset;
- stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+ stride = (reg >= CPC) ? OMAP1_DMA_STRIDE : 0;
offset = reg_map[reg] + (stride * lch);
__raw_writew(val, dma_base + offset);
@@ -200,7 +198,7 @@ static inline u32 dma_read(int reg, int lch)
u8 stride;
u32 offset, val;
- stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+ stride = (reg >= CPC) ? OMAP1_DMA_STRIDE : 0;
offset = reg_map[reg] + (stride * lch);
val = __raw_readw(dma_base + offset);
@@ -216,9 +214,9 @@ static inline u32 dma_read(int reg, int lch)
static void omap1_clear_lch_regs(int lch)
{
- int i = dma_common_ch_start;
+ int i;
- for (; i <= dma_common_ch_end; i += 1)
+ for (i = CPC; i <= COLOR; i += 1)
dma_write(0, i, lch);
}
@@ -380,10 +378,6 @@ static int __init omap1_system_dma_init(void)
goto exit_release_chan;
}
- dma_stride = OMAP1_DMA_STRIDE;
- dma_common_ch_start = CPC;
- dma_common_ch_end = COLOR;
-
dma_pdev = platform_device_register_full(&omap_dma_dev_info);
if (IS_ERR(dma_pdev)) {
ret = PTR_ERR(dma_pdev);
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 81c2d3383bc5..e4ac7ac9a228 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -38,11 +38,10 @@
#define OMAP2_DMA_STRIDE 0x60
static u32 errata;
-static u8 dma_stride;
static struct omap_dma_dev_attr *d;
-static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
+static enum omap_reg_offsets dma_common_ch_end;
static u16 reg_map[] = {
[REVISION] = 0x00,
@@ -96,7 +95,7 @@ static inline void dma_write(u32 val, int reg, int lch)
u8 stride;
u32 offset;
- stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+ stride = (reg >= CSDP) ? OMAP2_DMA_STRIDE : 0;
offset = reg_map[reg] + (stride * lch);
__raw_writel(val, dma_base + offset);
}
@@ -106,7 +105,7 @@ static inline u32 dma_read(int reg, int lch)
u8 stride;
u32 offset, val;
- stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+ stride = (reg >= CSDP) ? OMAP2_DMA_STRIDE : 0;
offset = reg_map[reg] + (stride * lch);
val = __raw_readl(dma_base + offset);
return val;
@@ -114,9 +113,9 @@ static inline u32 dma_read(int reg, int lch)
static void omap2_clear_dma(int lch)
{
- int i = dma_common_ch_start;
+ int i;
- for (; i <= dma_common_ch_end; i += 1)
+ for (i = CSDP; i <= dma_common_ch_end; i += 1)
dma_write(0, i, lch);
}
@@ -219,9 +218,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
struct resource *mem;
char *name = "omap_dma_system";
- dma_stride = OMAP2_DMA_STRIDE;
- dma_common_ch_start = CSDP;
-
p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
if (!p) {
pr_err("%s: Unable to allocate pdata for %s:%s\n",
--
1.8.3.1
^ permalink raw reply related
* [PATCH 18/26] ARM: omap: remove references to disable_irq_lch
From: Russell King @ 2014-02-10 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
The disable_irq_lch method is never actually used, so there's not much
point it existing; remove it.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/mach-omap1/dma.c | 1 -
arch/arm/mach-omap2/dma.c | 10 ----------
include/linux/omap-dma.h | 1 -
3 files changed, 12 deletions(-)
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 5bb8ce86d54b..d292055d3117 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -363,7 +363,6 @@ static int __init omap1_system_dma_init(void)
p->clear_dma = omap1_clear_dma;
p->dma_write = dma_write;
p->dma_read = dma_read;
- p->disable_irq_lch = NULL;
p->errata = configure_dma_errata();
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 49fd0d501c9b..81c2d3383bc5 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -112,15 +112,6 @@ static inline u32 dma_read(int reg, int lch)
return val;
}
-static inline void omap2_disable_irq_lch(int lch)
-{
- u32 val;
-
- val = dma_read(IRQENABLE_L0, lch);
- val &= ~(1 << lch);
- dma_write(val, IRQENABLE_L0, lch);
-}
-
static void omap2_clear_dma(int lch)
{
int i = dma_common_ch_start;
@@ -239,7 +230,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
}
p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr;
- p->disable_irq_lch = omap2_disable_irq_lch;
p->show_dma_caps = omap2_show_dma_caps;
p->clear_dma = omap2_clear_dma;
p->dma_write = dma_write;
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index d631658e2237..0bb7de77d478 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -275,7 +275,6 @@ struct omap_dma_dev_attr {
struct omap_system_dma_plat_info {
struct omap_dma_dev_attr *dma_attr;
u32 errata;
- void (*disable_irq_lch)(int lch);
void (*show_dma_caps)(void);
void (*clear_lch_regs)(int lch);
void (*clear_dma)(int lch);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 17/26] dmaengine: omap-dma: cleanup errata 3.3 handling
From: Russell King @ 2014-02-10 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 52 ++++++++++++++++++++++++++++----------------------
1 file changed, 29 insertions(+), 23 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index a1baada7dcd4..1e0018f36384 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -451,28 +451,39 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr)
return size;
}
+/*
+ * OMAP 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
+ * read before the DMA controller finished disabling the channel.
+ */
+static uint32_t omap_dma_chan_read_3_3(struct omap_chan *c, unsigned reg)
+{
+ struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+ uint32_t val;
+
+ val = omap_dma_chan_read(c, reg);
+ if (val == 0 && od->plat->errata & DMA_ERRATA_3_3)
+ val = omap_dma_chan_read(c, reg);
+
+ return val;
+}
+
static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c)
{
struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
- dma_addr_t addr;
+ dma_addr_t addr, cdac;
- if (__dma_omap15xx(od->plat->dma_attr))
+ if (__dma_omap15xx(od->plat->dma_attr)) {
addr = omap_dma_chan_read(c, CPC);
- else
- addr = omap_dma_chan_read(c, CSAC);
-
- if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0)
- addr = omap_dma_chan_read(c, CSAC);
+ } else {
+ addr = omap_dma_chan_read_3_3(c, CSAC);
+ cdac = omap_dma_chan_read_3_3(c, CDAC);
- if (!__dma_omap15xx(od->plat->dma_attr)) {
/*
* CDAC == 0 indicates that the DMA transfer on the channel has
* not been started (no data has been transferred so far).
* Return the programmed source start address in this case.
*/
- if (omap_dma_chan_read(c, CDAC))
- addr = omap_dma_chan_read(c, CSAC);
- else
+ if (cdac == 0)
addr = omap_dma_chan_read(c, CSSA);
}
@@ -487,21 +498,16 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c)
struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
dma_addr_t addr;
- if (__dma_omap15xx(od->plat->dma_attr))
+ if (__dma_omap15xx(od->plat->dma_attr)) {
addr = omap_dma_chan_read(c, CPC);
- else
- addr = omap_dma_chan_read(c, CDAC);
+ } else {
+ addr = omap_dma_chan_read_3_3(c, CDAC);
- /*
- * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
- * read before the DMA controller finished disabling the channel.
- */
- if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) {
- addr = omap_dma_chan_read(c, CDAC);
/*
- * CDAC == 0 indicates that the DMA transfer on the channel has
- * not been started (no data has been transferred so far).
- * Return the programmed destination start address in this case.
+ * CDAC == 0 indicates that the DMA transfer on the channel
+ * has not been started (no data has been transferred so
+ * far). Return the programmed destination start address in
+ * this case.
*/
if (addr == 0)
addr = omap_dma_chan_read(c, CDSA);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 16/26] dmaengine: omap-dma: provide register read/write functions
From: Russell King @ 2014-02-10 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Provide a pair of channel register accessors, and a pair of global
accessors for non-channel specific registers.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 102 +++++++++++++++++++++++++++++--------------------
1 file changed, 61 insertions(+), 41 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index b270aedf1d15..a1baada7dcd4 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -170,12 +170,32 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)
kfree(container_of(vd, struct omap_desc, vd));
}
+static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val)
+{
+ od->plat->dma_write(val, reg, 0);
+}
+
+static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg)
+{
+ return od->plat->dma_read(reg, 0);
+}
+
+static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val)
+{
+ c->plat->dma_write(val, reg, c->dma_ch);
+}
+
+static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg)
+{
+ return c->plat->dma_read(reg, c->dma_ch);
+}
+
static void omap_dma_clear_csr(struct omap_chan *c)
{
if (dma_omap1())
- c->plat->dma_read(CSR, c->dma_ch);
+ omap_dma_chan_read(c, CSR);
else
- c->plat->dma_write(~0, CSR, c->dma_ch);
+ omap_dma_chan_write(c, CSR, ~0);
}
static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
@@ -183,17 +203,17 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
if (__dma_omap15xx(od->plat->dma_attr))
- c->plat->dma_write(0, CPC, c->dma_ch);
+ omap_dma_chan_write(c, CPC, 0);
else
- c->plat->dma_write(0, CDAC, c->dma_ch);
+ omap_dma_chan_write(c, CDAC, 0);
omap_dma_clear_csr(c);
/* Enable interrupts */
- c->plat->dma_write(d->cicr, CICR, c->dma_ch);
+ omap_dma_chan_write(c, CICR, d->cicr);
/* Enable channel */
- c->plat->dma_write(d->ccr | CCR_ENABLE, CCR, c->dma_ch);
+ omap_dma_chan_write(c, CCR, d->ccr | CCR_ENABLE);
}
static void omap_dma_stop(struct omap_chan *c)
@@ -202,27 +222,27 @@ static void omap_dma_stop(struct omap_chan *c)
uint32_t val;
/* disable irq */
- c->plat->dma_write(0, CICR, c->dma_ch);
+ omap_dma_chan_write(c, CICR, 0);
omap_dma_clear_csr(c);
- val = c->plat->dma_read(CCR, c->dma_ch);
+ val = omap_dma_chan_read(c, CCR);
if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) {
uint32_t sysconfig;
unsigned i;
- sysconfig = c->plat->dma_read(OCP_SYSCONFIG, c->dma_ch);
+ sysconfig = omap_dma_glbl_read(od, OCP_SYSCONFIG);
val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK;
val |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
- c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch);
+ omap_dma_glbl_write(od, OCP_SYSCONFIG, val);
- val = c->plat->dma_read(CCR, c->dma_ch);
+ val = omap_dma_chan_read(c, CCR);
val &= ~CCR_ENABLE;
- c->plat->dma_write(val, CCR, c->dma_ch);
+ omap_dma_chan_write(c, CCR, val);
/* Wait for sDMA FIFO to drain */
for (i = 0; ; i++) {
- val = c->plat->dma_read(CCR, c->dma_ch);
+ val = omap_dma_chan_read(c, CCR);
if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)))
break;
@@ -237,23 +257,23 @@ static void omap_dma_stop(struct omap_chan *c)
"DMA drain did not complete on lch %d\n",
c->dma_ch);
- c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch);
+ omap_dma_glbl_write(od, OCP_SYSCONFIG, sysconfig);
} else {
val &= ~CCR_ENABLE;
- c->plat->dma_write(val, CCR, c->dma_ch);
+ omap_dma_chan_write(c, CCR, val);
}
mb();
if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) {
- val = c->plat->dma_read(CLNK_CTRL, c->dma_ch);
+ val = omap_dma_chan_read(c, CLNK_CTRL);
if (dma_omap1())
val |= 1 << 14; /* set the STOP_LNK bit */
else
val &= ~CLNK_CTRL_ENABLE_LNK;
- c->plat->dma_write(val, CLNK_CTRL, c->dma_ch);
+ omap_dma_chan_write(c, CLNK_CTRL, val);
}
}
@@ -273,11 +293,11 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
cxfi = CSFI;
}
- c->plat->dma_write(sg->addr, cxsa, c->dma_ch);
- c->plat->dma_write(0, cxei, c->dma_ch);
- c->plat->dma_write(0, cxfi, c->dma_ch);
- c->plat->dma_write(sg->en, CEN, c->dma_ch);
- c->plat->dma_write(sg->fn, CFN, c->dma_ch);
+ omap_dma_chan_write(c, cxsa, sg->addr);
+ omap_dma_chan_write(c, cxei, 0);
+ omap_dma_chan_write(c, cxfi, 0);
+ omap_dma_chan_write(c, CEN, sg->en);
+ omap_dma_chan_write(c, CFN, sg->fn);
omap_dma_start(c, d);
}
@@ -305,9 +325,9 @@ static void omap_dma_start_desc(struct omap_chan *c)
*/
mb();
- c->plat->dma_write(d->ccr, CCR, c->dma_ch);
+ omap_dma_chan_write(c, CCR, d->ccr);
if (dma_omap1())
- c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch);
+ omap_dma_chan_write(c, CCR2, d->ccr >> 16);
if (d->dir == DMA_DEV_TO_MEM) {
cxsa = CSSA;
@@ -319,11 +339,11 @@ static void omap_dma_start_desc(struct omap_chan *c)
cxfi = CDFI;
}
- c->plat->dma_write(d->dev_addr, cxsa, c->dma_ch);
- c->plat->dma_write(0, cxei, c->dma_ch);
- c->plat->dma_write(d->fi, cxfi, c->dma_ch);
- c->plat->dma_write(d->csdp, CSDP, c->dma_ch);
- c->plat->dma_write(d->clnk_ctrl, CLNK_CTRL, c->dma_ch);
+ omap_dma_chan_write(c, cxsa, d->dev_addr);
+ omap_dma_chan_write(c, cxei, 0);
+ omap_dma_chan_write(c, cxfi, d->fi);
+ omap_dma_chan_write(c, CSDP, d->csdp);
+ omap_dma_chan_write(c, CLNK_CTRL, d->clnk_ctrl);
omap_dma_start_sg(c, d, 0);
}
@@ -437,12 +457,12 @@ static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c)
dma_addr_t addr;
if (__dma_omap15xx(od->plat->dma_attr))
- addr = c->plat->dma_read(CPC, c->dma_ch);
+ addr = omap_dma_chan_read(c, CPC);
else
- addr = c->plat->dma_read(CSAC, c->dma_ch);
+ addr = omap_dma_chan_read(c, CSAC);
if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0)
- addr = c->plat->dma_read(CSAC, c->dma_ch);
+ addr = omap_dma_chan_read(c, CSAC);
if (!__dma_omap15xx(od->plat->dma_attr)) {
/*
@@ -450,14 +470,14 @@ static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c)
* not been started (no data has been transferred so far).
* Return the programmed source start address in this case.
*/
- if (c->plat->dma_read(CDAC, c->dma_ch))
- addr = c->plat->dma_read(CSAC, c->dma_ch);
+ if (omap_dma_chan_read(c, CDAC))
+ addr = omap_dma_chan_read(c, CSAC);
else
- addr = c->plat->dma_read(CSSA, c->dma_ch);
+ addr = omap_dma_chan_read(c, CSSA);
}
if (dma_omap1())
- addr |= c->plat->dma_read(CSSA, c->dma_ch) & 0xffff0000;
+ addr |= omap_dma_chan_read(c, CSSA) & 0xffff0000;
return addr;
}
@@ -468,27 +488,27 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c)
dma_addr_t addr;
if (__dma_omap15xx(od->plat->dma_attr))
- addr = c->plat->dma_read(CPC, c->dma_ch);
+ addr = omap_dma_chan_read(c, CPC);
else
- addr = c->plat->dma_read(CDAC, c->dma_ch);
+ addr = omap_dma_chan_read(c, CDAC);
/*
* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
* read before the DMA controller finished disabling the channel.
*/
if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) {
- addr = c->plat->dma_read(CDAC, c->dma_ch);
+ addr = omap_dma_chan_read(c, CDAC);
/*
* CDAC == 0 indicates that the DMA transfer on the channel has
* not been started (no data has been transferred so far).
* Return the programmed destination start address in this case.
*/
if (addr == 0)
- addr = c->plat->dma_read(CDSA, c->dma_ch);
+ addr = omap_dma_chan_read(c, CDSA);
}
if (dma_omap1())
- addr |= c->plat->dma_read(CDSA, c->dma_ch) & 0xffff0000;
+ addr |= omap_dma_chan_read(c, CDSA) & 0xffff0000;
return addr;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH 15/26] dmaengine: omap-dma: use cached CCR value when enabling DMA
From: Russell King @ 2014-02-10 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
We don't need to read-modify-write the CCR register; we already know
what value it should contain at this point. Use the cached CCR value
when setting the enable bit.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 49b303296d75..b270aedf1d15 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -181,7 +181,6 @@ static void omap_dma_clear_csr(struct omap_chan *c)
static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
{
struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
- uint32_t val;
if (__dma_omap15xx(od->plat->dma_attr))
c->plat->dma_write(0, CPC, c->dma_ch);
@@ -193,9 +192,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
/* Enable interrupts */
c->plat->dma_write(d->cicr, CICR, c->dma_ch);
- val = c->plat->dma_read(CCR, c->dma_ch);
- val |= CCR_ENABLE;
- c->plat->dma_write(val, CCR, c->dma_ch);
+ /* Enable channel */
+ c->plat->dma_write(d->ccr | CCR_ENABLE, CCR, c->dma_ch);
}
static void omap_dma_stop(struct omap_chan *c)
--
1.8.3.1
^ permalink raw reply related
* [PATCH 14/26] dmaengine: omap-dma: move barrier to omap_dma_start_desc()
From: Russell King @ 2014-02-10 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
We don't need to issue a barrier for every segment of a DMA transfer;
doing this just once per descriptor will do.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 49609275b2e7..49b303296d75 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -195,7 +195,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
val = c->plat->dma_read(CCR, c->dma_ch);
val |= CCR_ENABLE;
- mb();
c->plat->dma_write(val, CCR, c->dma_ch);
}
@@ -301,6 +300,13 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->desc = d = to_omap_dma_desc(&vd->tx);
c->sgidx = 0;
+ /*
+ * This provides the necessary barrier to ensure data held in
+ * DMA coherent memory is visible to the DMA engine prior to
+ * the transfer starting.
+ */
+ mb();
+
c->plat->dma_write(d->ccr, CCR, c->dma_ch);
if (dma_omap1())
c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 13/26] dmaengine: omap-dma: move clnk_ctrl setting to preparation functions
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Move the clnk_ctrl setup to the preparation functions, saving its
value in the omap_desc. This only needs to be set once per descriptor,
not for each segment, so set it in omap_dma_start_desc() rather than
omap_dma_start().
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 06727a78e883..49609275b2e7 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -59,6 +59,7 @@ struct omap_desc {
int16_t fi; /* for OMAP_DMA_SYNC_PACKET */
uint8_t es; /* CSDP_DATA_TYPE_xxx */
uint32_t ccr; /* CCR value */
+ uint16_t clnk_ctrl; /* CLNK_CTRL value */
uint16_t cicr; /* CICR value */
uint32_t csdp; /* CSDP value */
@@ -187,18 +188,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
else
c->plat->dma_write(0, CDAC, c->dma_ch);
- if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) {
- val = c->plat->dma_read(CLNK_CTRL, c->dma_ch);
-
- if (dma_omap1())
- val &= ~(1 << 14);
-
- val |= c->dma_ch | CLNK_CTRL_ENABLE_LNK;
-
- c->plat->dma_write(val, CLNK_CTRL, c->dma_ch);
- } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS)
- c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch);
-
omap_dma_clear_csr(c);
/* Enable interrupts */
@@ -330,6 +319,7 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->plat->dma_write(0, cxei, c->dma_ch);
c->plat->dma_write(d->fi, cxfi, c->dma_ch);
c->plat->dma_write(d->csdp, CSDP, c->dma_ch);
+ c->plat->dma_write(d->clnk_ctrl, CLNK_CTRL, c->dma_ch);
omap_dma_start_sg(c, d, 0);
}
@@ -645,6 +635,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
}
if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
d->ccr |= CCR_BUFFERING_DISABLE;
+ if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS)
+ d->clnk_ctrl = c->dma_ch;
/*
* Build our scatterlist entries: each contains the address,
@@ -725,8 +717,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
d->sglen = 1;
d->ccr = 0;
- if (__dma_omap15xx(od->plat->dma_attr))
- d->ccr = CCR_AUTO_INIT | CCR_REPEAT;
if (dir == DMA_DEV_TO_MEM)
d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT;
else
@@ -772,6 +762,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
d->ccr |= CCR_BUFFERING_DISABLE;
+ if (__dma_omap15xx(od->plat->dma_attr))
+ d->ccr |= CCR_AUTO_INIT | CCR_REPEAT;
+ else
+ d->clnk_ctrl = c->dma_ch | CLNK_CTRL_ENABLE_LNK;
+
c->cyclic = true;
return vchan_tx_prep(&c->vc, &d->vd, flags);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 12/26] dmaengine: omap-dma: improve efficiency loading C.SA/C.EI/C.FI registers
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index d1641aa9d113..06727a78e883 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -275,17 +275,21 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
unsigned idx)
{
struct omap_sg *sg = d->sg + idx;
+ unsigned cxsa, cxei, cxfi;
if (d->dir == DMA_DEV_TO_MEM) {
- c->plat->dma_write(sg->addr, CDSA, c->dma_ch);
- c->plat->dma_write(0, CDEI, c->dma_ch);
- c->plat->dma_write(0, CDFI, c->dma_ch);
+ cxsa = CDSA;
+ cxei = CDEI;
+ cxfi = CDFI;
} else {
- c->plat->dma_write(sg->addr, CSSA, c->dma_ch);
- c->plat->dma_write(0, CSEI, c->dma_ch);
- c->plat->dma_write(0, CSFI, c->dma_ch);
+ cxsa = CSSA;
+ cxei = CSEI;
+ cxfi = CSFI;
}
+ c->plat->dma_write(sg->addr, cxsa, c->dma_ch);
+ c->plat->dma_write(0, cxei, c->dma_ch);
+ c->plat->dma_write(0, cxfi, c->dma_ch);
c->plat->dma_write(sg->en, CEN, c->dma_ch);
c->plat->dma_write(sg->fn, CFN, c->dma_ch);
@@ -296,6 +300,7 @@ static void omap_dma_start_desc(struct omap_chan *c)
{
struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
struct omap_desc *d;
+ unsigned cxsa, cxei, cxfi;
if (!vd) {
c->desc = NULL;
@@ -312,15 +317,18 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch);
if (d->dir == DMA_DEV_TO_MEM) {
- c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch);
- c->plat->dma_write(0, CSEI, c->dma_ch);
- c->plat->dma_write(d->fi, CSFI, c->dma_ch);
+ cxsa = CSSA;
+ cxei = CSEI;
+ cxfi = CSFI;
} else {
- c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch);
- c->plat->dma_write(0, CDEI, c->dma_ch);
- c->plat->dma_write(d->fi, CDFI, c->dma_ch);
+ cxsa = CDSA;
+ cxei = CDEI;
+ cxfi = CDFI;
}
+ c->plat->dma_write(d->dev_addr, cxsa, c->dma_ch);
+ c->plat->dma_write(0, cxei, c->dma_ch);
+ c->plat->dma_write(d->fi, cxfi, c->dma_ch);
c->plat->dma_write(d->csdp, CSDP, c->dma_ch);
omap_dma_start_sg(c, d, 0);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 11/26] dmaengine: omap-dma: consolidate clearing channel status register
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 324f4c7c5dd0..d1641aa9d113 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -169,6 +169,14 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)
kfree(container_of(vd, struct omap_desc, vd));
}
+static void omap_dma_clear_csr(struct omap_chan *c)
+{
+ if (dma_omap1())
+ c->plat->dma_read(CSR, c->dma_ch);
+ else
+ c->plat->dma_write(~0, CSR, c->dma_ch);
+}
+
static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
{
struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
@@ -191,11 +199,7 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
} else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS)
c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch);
- /* Clear CSR */
- if (dma_omap1())
- c->plat->dma_read(CSR, c->dma_ch);
- else
- c->plat->dma_write(~0, CSR, c->dma_ch);
+ omap_dma_clear_csr(c);
/* Enable interrupts */
c->plat->dma_write(d->cicr, CICR, c->dma_ch);
@@ -214,11 +218,7 @@ static void omap_dma_stop(struct omap_chan *c)
/* disable irq */
c->plat->dma_write(0, CICR, c->dma_ch);
- /* Clear CSR */
- if (dma_omap1())
- c->plat->dma_read(CSR, c->dma_ch);
- else
- c->plat->dma_write(~0, CSR, c->dma_ch);
+ omap_dma_clear_csr(c);
val = c->plat->dma_read(CCR, c->dma_ch);
if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) {
--
1.8.3.1
^ permalink raw reply related
* [PATCH 10/26] dmaengine: omap-dma: move CCR buffering disable errata out of the fast path
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Since we record the CCR register in the dma transaction, we can move the
processing of the iframe buffering errata out of the omap_dma_start().
Move it to the preparation functions.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 6cf66e608338..324f4c7c5dd0 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -201,8 +201,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
c->plat->dma_write(d->cicr, CICR, c->dma_ch);
val = c->plat->dma_read(CCR, c->dma_ch);
- if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
- val |= CCR_BUFFERING_DISABLE;
val |= CCR_ENABLE;
mb();
c->plat->dma_write(val, CCR, c->dma_ch);
@@ -558,6 +556,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl, unsigned sglen,
enum dma_transfer_direction dir, unsigned long tx_flags, void *context)
{
+ struct omap_dmadev *od = to_omap_dma_dev(chan->device);
struct omap_chan *c = to_omap_dma_chan(chan);
enum dma_slave_buswidth dev_width;
struct scatterlist *sgent;
@@ -636,6 +635,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
}
+ if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
+ d->ccr |= CCR_BUFFERING_DISABLE;
/*
* Build our scatterlist entries: each contains the address,
@@ -760,6 +761,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64;
}
+ if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
+ d->ccr |= CCR_BUFFERING_DISABLE;
c->cyclic = true;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 09/26] dmaengine: omap-dma: provide register definitions
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Provide our own set of more complete register definitions; this allows
us to get rid of the meaningless 1 << n constants scattered throughout
this code.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 171 +++++++++++++++++++++++++++++++++----------------
1 file changed, 117 insertions(+), 54 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 9a9e81907475..6cf66e608338 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -57,7 +57,7 @@ struct omap_desc {
dma_addr_t dev_addr;
int16_t fi; /* for OMAP_DMA_SYNC_PACKET */
- uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */
+ uint8_t es; /* CSDP_DATA_TYPE_xxx */
uint32_t ccr; /* CCR value */
uint16_t cicr; /* CICR value */
uint32_t csdp; /* CSDP value */
@@ -66,10 +66,83 @@ struct omap_desc {
struct omap_sg sg[0];
};
+enum {
+ CCR_FS = BIT(5),
+ CCR_READ_PRIORITY = BIT(6),
+ CCR_ENABLE = BIT(7),
+ CCR_AUTO_INIT = BIT(8), /* OMAP1 only */
+ CCR_REPEAT = BIT(9), /* OMAP1 only */
+ CCR_OMAP31_DISABLE = BIT(10), /* OMAP1 only */
+ CCR_SUSPEND_SENSITIVE = BIT(8), /* OMAP2+ only */
+ CCR_RD_ACTIVE = BIT(9), /* OMAP2+ only */
+ CCR_WR_ACTIVE = BIT(10), /* OMAP2+ only */
+ CCR_SRC_AMODE_CONSTANT = 0 << 12,
+ CCR_SRC_AMODE_POSTINC = 1 << 12,
+ CCR_SRC_AMODE_SGLIDX = 2 << 12,
+ CCR_SRC_AMODE_DBLIDX = 3 << 12,
+ CCR_DST_AMODE_CONSTANT = 0 << 14,
+ CCR_DST_AMODE_POSTINC = 1 << 14,
+ CCR_DST_AMODE_SGLIDX = 2 << 14,
+ CCR_DST_AMODE_DBLIDX = 3 << 14,
+ CCR_CONSTANT_FILL = BIT(16),
+ CCR_TRANSPARENT_COPY = BIT(17),
+ CCR_BS = BIT(18),
+ CCR_SUPERVISOR = BIT(22),
+ CCR_PREFETCH = BIT(23),
+ CCR_TRIGGER_SRC = BIT(24),
+ CCR_BUFFERING_DISABLE = BIT(25),
+ CCR_WRITE_PRIORITY = BIT(26),
+ CCR_SYNC_ELEMENT = 0,
+ CCR_SYNC_FRAME = CCR_FS,
+ CCR_SYNC_BLOCK = CCR_BS,
+ CCR_SYNC_PACKET = CCR_BS | CCR_FS,
+
+ CSDP_DATA_TYPE_8 = 0,
+ CSDP_DATA_TYPE_16 = 1,
+ CSDP_DATA_TYPE_32 = 2,
+ CSDP_SRC_PORT_EMIFF = 0 << 2, /* OMAP1 only */
+ CSDP_SRC_PORT_EMIFS = 1 << 2, /* OMAP1 only */
+ CSDP_SRC_PORT_OCP_T1 = 2 << 2, /* OMAP1 only */
+ CSDP_SRC_PORT_TIPB = 3 << 2, /* OMAP1 only */
+ CSDP_SRC_PORT_OCP_T2 = 4 << 2, /* OMAP1 only */
+ CSDP_SRC_PORT_MPUI = 5 << 2, /* OMAP1 only */
+ CSDP_SRC_PACKED = BIT(6),
+ CSDP_SRC_BURST_1 = 0 << 7,
+ CSDP_SRC_BURST_16 = 1 << 7,
+ CSDP_SRC_BURST_32 = 2 << 7,
+ CSDP_SRC_BURST_64 = 3 << 7,
+ CSDP_DST_PORT_EMIFF = 0 << 9, /* OMAP1 only */
+ CSDP_DST_PORT_EMIFS = 1 << 9, /* OMAP1 only */
+ CSDP_DST_PORT_OCP_T1 = 2 << 9, /* OMAP1 only */
+ CSDP_DST_PORT_TIPB = 3 << 9, /* OMAP1 only */
+ CSDP_DST_PORT_OCP_T2 = 4 << 9, /* OMAP1 only */
+ CSDP_DST_PORT_MPUI = 5 << 9, /* OMAP1 only */
+ CSDP_DST_PACKED = BIT(13),
+ CSDP_DST_BURST_1 = 0 << 14,
+ CSDP_DST_BURST_16 = 1 << 14,
+ CSDP_DST_BURST_32 = 2 << 14,
+ CSDP_DST_BURST_64 = 3 << 14,
+
+ CICR_TOUT_IE = BIT(0), /* OMAP1 only */
+ CICR_DROP_IE = BIT(1),
+ CICR_HALF_IE = BIT(2),
+ CICR_FRAME_IE = BIT(3),
+ CICR_LAST_IE = BIT(4),
+ CICR_BLOCK_IE = BIT(5),
+ CICR_PKT_IE = BIT(7), /* OMAP2+ only */
+ CICR_TRANS_ERR_IE = BIT(8), /* OMAP2+ only */
+ CICR_SUPERVISOR_ERR_IE = BIT(10), /* OMAP2+ only */
+ CICR_MISALIGNED_ERR_IE = BIT(11), /* OMAP2+ only */
+ CICR_DRAIN_IE = BIT(12), /* OMAP2+ only */
+ CICR_SUPER_BLOCK_IE = BIT(14), /* OMAP2+ only */
+
+ CLNK_CTRL_ENABLE_LNK = BIT(15),
+};
+
static const unsigned es_bytes[] = {
- [OMAP_DMA_DATA_TYPE_S8] = 1,
- [OMAP_DMA_DATA_TYPE_S16] = 2,
- [OMAP_DMA_DATA_TYPE_S32] = 4,
+ [CSDP_DATA_TYPE_8] = 1,
+ [CSDP_DATA_TYPE_16] = 2,
+ [CSDP_DATA_TYPE_32] = 4,
};
static struct of_dma_filter_info omap_dma_info = {
@@ -112,7 +185,7 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
if (dma_omap1())
val &= ~(1 << 14);
- val |= c->dma_ch | 1 << 15;
+ val |= c->dma_ch | CLNK_CTRL_ENABLE_LNK;
c->plat->dma_write(val, CLNK_CTRL, c->dma_ch);
} else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS)
@@ -129,8 +202,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
val = c->plat->dma_read(CCR, c->dma_ch);
if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
- val |= OMAP_DMA_CCR_BUFFERING_DISABLE;
- val |= OMAP_DMA_CCR_EN;
+ val |= CCR_BUFFERING_DISABLE;
+ val |= CCR_ENABLE;
mb();
c->plat->dma_write(val, CCR, c->dma_ch);
}
@@ -150,8 +223,7 @@ static void omap_dma_stop(struct omap_chan *c)
c->plat->dma_write(~0, CSR, c->dma_ch);
val = c->plat->dma_read(CCR, c->dma_ch);
- if (od->plat->errata & DMA_ERRATA_i541 &&
- val & OMAP_DMA_CCR_SEL_SRC_DST_SYNC) {
+ if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) {
uint32_t sysconfig;
unsigned i;
@@ -161,13 +233,13 @@ static void omap_dma_stop(struct omap_chan *c)
c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch);
val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~OMAP_DMA_CCR_EN;
+ val &= ~CCR_ENABLE;
c->plat->dma_write(val, CCR, c->dma_ch);
/* Wait for sDMA FIFO to drain */
for (i = 0; ; i++) {
val = c->plat->dma_read(CCR, c->dma_ch);
- if (!(val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE)))
+ if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)))
break;
if (i > 100)
@@ -176,14 +248,14 @@ static void omap_dma_stop(struct omap_chan *c)
udelay(5);
}
- if (val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))
+ if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))
dev_err(c->vc.chan.device->dev,
"DMA drain did not complete on lch %d\n",
c->dma_ch);
c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch);
} else {
- val &= ~OMAP_DMA_CCR_EN;
+ val &= ~CCR_ENABLE;
c->plat->dma_write(val, CCR, c->dma_ch);
}
@@ -195,7 +267,7 @@ static void omap_dma_stop(struct omap_chan *c)
if (dma_omap1())
val |= 1 << 14; /* set the STOP_LNK bit */
else
- val &= ~(1 << 15); /* Clear the ENABLE_LNK bit */
+ val &= ~CLNK_CTRL_ENABLE_LNK;
c->plat->dma_write(val, CLNK_CTRL, c->dma_ch);
}
@@ -510,13 +582,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
/* Bus width translates to the element size (ES) */
switch (dev_width) {
case DMA_SLAVE_BUSWIDTH_1_BYTE:
- es = OMAP_DMA_DATA_TYPE_S8;
+ es = CSDP_DATA_TYPE_8;
break;
case DMA_SLAVE_BUSWIDTH_2_BYTES:
- es = OMAP_DMA_DATA_TYPE_S16;
+ es = CSDP_DATA_TYPE_16;
break;
case DMA_SLAVE_BUSWIDTH_4_BYTES:
- es = OMAP_DMA_DATA_TYPE_S32;
+ es = CSDP_DATA_TYPE_32;
break;
default: /* not reached */
return NULL;
@@ -531,44 +603,38 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->dev_addr = dev_addr;
d->es = es;
- d->ccr = 0;
+ d->ccr = CCR_SYNC_FRAME;
if (dir == DMA_DEV_TO_MEM)
- d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 |
- OMAP_DMA_AMODE_CONSTANT << 12;
+ d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT;
else
- d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 |
- OMAP_DMA_AMODE_POST_INC << 12;
+ d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC;
- d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
+ d->cicr = CICR_DROP_IE | CICR_BLOCK_IE;
d->csdp = es;
if (dma_omap1()) {
- d->ccr |= 1 << 5; /* frame sync */
if (__dma_omap16xx(od->plat->dma_attr)) {
- d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */
+ d->ccr |= CCR_OMAP31_DISABLE;
/* Duplicate what plat-omap/dma.c does */
d->ccr |= c->dma_ch + 1;
} else {
d->ccr |= c->dma_sig & 0x1f;
}
- d->cicr |= OMAP1_DMA_TOUT_IRQ;
+ d->cicr |= CICR_TOUT_IE;
if (dir == DMA_DEV_TO_MEM)
- d->csdp |= OMAP_DMA_PORT_EMIFF << 9 |
- OMAP_DMA_PORT_TIPB << 2;
+ d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_TIPB;
else
- d->csdp |= OMAP_DMA_PORT_TIPB << 9 |
- OMAP_DMA_PORT_EMIFF << 2;
+ d->csdp |= CSDP_DST_PORT_TIPB | CSDP_SRC_PORT_EMIFF;
} else {
d->ccr |= (c->dma_sig & ~0x1f) << 14;
d->ccr |= c->dma_sig & 0x1f;
- d->ccr |= 1 << 5; /* frame sync */
if (dir == DMA_DEV_TO_MEM)
- d->ccr |= 1 << 24; /* source synch */
+ d->ccr |= CCR_TRIGGER_SRC;
- d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ;
+ d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
}
/*
@@ -623,13 +689,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
/* Bus width translates to the element size (ES) */
switch (dev_width) {
case DMA_SLAVE_BUSWIDTH_1_BYTE:
- es = OMAP_DMA_DATA_TYPE_S8;
+ es = CSDP_DATA_TYPE_8;
break;
case DMA_SLAVE_BUSWIDTH_2_BYTES:
- es = OMAP_DMA_DATA_TYPE_S16;
+ es = CSDP_DATA_TYPE_16;
break;
case DMA_SLAVE_BUSWIDTH_4_BYTES:
- es = OMAP_DMA_DATA_TYPE_S32;
+ es = CSDP_DATA_TYPE_32;
break;
default: /* not reached */
return NULL;
@@ -651,51 +717,48 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
d->ccr = 0;
if (__dma_omap15xx(od->plat->dma_attr))
- d->ccr = 3 << 8;
+ d->ccr = CCR_AUTO_INIT | CCR_REPEAT;
if (dir == DMA_DEV_TO_MEM)
- d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 |
- OMAP_DMA_AMODE_CONSTANT << 12;
+ d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT;
else
- d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 |
- OMAP_DMA_AMODE_POST_INC << 12;
+ d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC;
- d->cicr = OMAP_DMA_DROP_IRQ;
+ d->cicr = CICR_DROP_IE;
if (flags & DMA_PREP_INTERRUPT)
- d->cicr |= OMAP_DMA_FRAME_IRQ;
+ d->cicr |= CICR_FRAME_IE;
d->csdp = es;
if (dma_omap1()) {
if (__dma_omap16xx(od->plat->dma_attr)) {
- d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */
+ d->ccr |= CCR_OMAP31_DISABLE;
/* Duplicate what plat-omap/dma.c does */
d->ccr |= c->dma_ch + 1;
} else {
d->ccr |= c->dma_sig & 0x1f;
}
- d->cicr |= OMAP1_DMA_TOUT_IRQ;
+ d->cicr |= CICR_TOUT_IE;
if (dir == DMA_DEV_TO_MEM)
- d->csdp |= OMAP_DMA_PORT_EMIFF << 9 |
- OMAP_DMA_PORT_MPUI << 2;
+ d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_MPUI;
else
- d->csdp |= OMAP_DMA_PORT_MPUI << 9 |
- OMAP_DMA_PORT_EMIFF << 2;
+ d->csdp |= CSDP_DST_PORT_MPUI | CSDP_SRC_PORT_EMIFF;
} else {
d->ccr |= (c->dma_sig & ~0x1f) << 14;
d->ccr |= c->dma_sig & 0x1f;
if (burst)
- d->ccr |= 1 << 18 | 1 << 5; /* packet */
+ d->ccr |= CCR_SYNC_PACKET;
+ else
+ d->ccr |= CCR_SYNC_ELEMENT;
if (dir == DMA_DEV_TO_MEM)
- d->ccr |= 1 << 24; /* source synch */
+ d->ccr |= CCR_TRIGGER_SRC;
- d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ;
+ d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
- /* src and dst burst mode 16 */
- d->csdp |= 3 << 14 | 3 << 7;
+ d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64;
}
c->cyclic = true;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 08/26] dmaengine: omap-dma: consolidate setup of CCR
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Consolidate the setup of the channel control register. Prepare the
basic value in the preparation of the DMA descriptor, and write it into
the register upon descriptor execution.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 147 ++++++++++++++++++++-----------------------------
1 file changed, 61 insertions(+), 86 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index ec7cc10d4594..9a9e81907475 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -58,8 +58,7 @@ struct omap_desc {
int16_t fi; /* for OMAP_DMA_SYNC_PACKET */
uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */
- uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */
- uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */
+ uint32_t ccr; /* CCR value */
uint16_t cicr; /* CICR value */
uint32_t csdp; /* CSDP value */
@@ -227,7 +226,6 @@ static void omap_dma_start_desc(struct omap_chan *c)
{
struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
struct omap_desc *d;
- uint32_t val;
if (!vd) {
c->desc = NULL;
@@ -239,23 +237,15 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->desc = d = to_omap_dma_desc(&vd->tx);
c->sgidx = 0;
- if (d->dir == DMA_DEV_TO_MEM) {
- val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~(0x03 << 14 | 0x03 << 12);
- val |= OMAP_DMA_AMODE_POST_INC << 14;
- val |= OMAP_DMA_AMODE_CONSTANT << 12;
- c->plat->dma_write(val, CCR, c->dma_ch);
+ c->plat->dma_write(d->ccr, CCR, c->dma_ch);
+ if (dma_omap1())
+ c->plat->dma_write(d->ccr >> 16, CCR2, c->dma_ch);
+ if (d->dir == DMA_DEV_TO_MEM) {
c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch);
c->plat->dma_write(0, CSEI, c->dma_ch);
c->plat->dma_write(d->fi, CSFI, c->dma_ch);
} else {
- val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~(0x03 << 12 | 0x03 << 14);
- val |= OMAP_DMA_AMODE_CONSTANT << 14;
- val |= OMAP_DMA_AMODE_POST_INC << 12;
- c->plat->dma_write(val, CCR, c->dma_ch);
-
c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch);
c->plat->dma_write(0, CDEI, c->dma_ch);
c->plat->dma_write(d->fi, CDFI, c->dma_ch);
@@ -263,45 +253,6 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->plat->dma_write(d->csdp, CSDP, c->dma_ch);
- if (dma_omap1()) {
- val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~(1 << 5);
- if (d->sync_mode == OMAP_DMA_SYNC_FRAME)
- val |= 1 << 5;
- c->plat->dma_write(val, CCR, c->dma_ch);
-
- val = c->plat->dma_read(CCR2, c->dma_ch);
- val &= ~(1 << 2);
- if (d->sync_mode == OMAP_DMA_SYNC_BLOCK)
- val |= 1 << 2;
- c->plat->dma_write(val, CCR2, c->dma_ch);
- } else if (c->dma_sig) {
- val = c->plat->dma_read(CCR, c->dma_ch);
-
- /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
- val &= ~(1 << 24 | 1 << 23 | 3 << 19 | 1 << 18 | 1 << 5 | 0x1f);
- val |= (c->dma_sig & ~0x1f) << 14;
- val |= c->dma_sig & 0x1f;
-
- if (d->sync_mode & OMAP_DMA_SYNC_FRAME)
- val |= 1 << 5;
-
- if (d->sync_mode & OMAP_DMA_SYNC_BLOCK)
- val |= 1 << 18;
-
- switch (d->sync_type) {
- case OMAP_DMA_DST_SYNC_PREFETCH:/* dest synch */
- val |= 1 << 23; /* Prefetch */
- break;
- case 0:
- break;
- default:
- val |= 1 << 24; /* source synch */
- break;
- }
- c->plat->dma_write(val, CCR, c->dma_ch);
- }
-
omap_dma_start_sg(c, d, 0);
}
@@ -540,19 +491,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
struct scatterlist *sgent;
struct omap_desc *d;
dma_addr_t dev_addr;
- unsigned i, j = 0, es, en, frame_bytes, sync_type;
+ unsigned i, j = 0, es, en, frame_bytes;
u32 burst;
if (dir == DMA_DEV_TO_MEM) {
dev_addr = c->cfg.src_addr;
dev_width = c->cfg.src_addr_width;
burst = c->cfg.src_maxburst;
- sync_type = OMAP_DMA_SRC_SYNC;
} else if (dir == DMA_MEM_TO_DEV) {
dev_addr = c->cfg.dst_addr;
dev_width = c->cfg.dst_addr_width;
burst = c->cfg.dst_maxburst;
- sync_type = OMAP_DMA_DST_SYNC;
} else {
dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
return NULL;
@@ -581,12 +530,28 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->dir = dir;
d->dev_addr = dev_addr;
d->es = es;
- d->sync_mode = OMAP_DMA_SYNC_FRAME;
- d->sync_type = sync_type;
+
+ d->ccr = 0;
+ if (dir == DMA_DEV_TO_MEM)
+ d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 |
+ OMAP_DMA_AMODE_CONSTANT << 12;
+ else
+ d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 |
+ OMAP_DMA_AMODE_POST_INC << 12;
+
d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
d->csdp = es;
if (dma_omap1()) {
+ d->ccr |= 1 << 5; /* frame sync */
+ if (__dma_omap16xx(od->plat->dma_attr)) {
+ d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */
+ /* Duplicate what plat-omap/dma.c does */
+ d->ccr |= c->dma_ch + 1;
+ } else {
+ d->ccr |= c->dma_sig & 0x1f;
+ }
+
d->cicr |= OMAP1_DMA_TOUT_IRQ;
if (dir == DMA_DEV_TO_MEM)
@@ -596,6 +561,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->csdp |= OMAP_DMA_PORT_TIPB << 9 |
OMAP_DMA_PORT_EMIFF << 2;
} else {
+ d->ccr |= (c->dma_sig & ~0x1f) << 14;
+ d->ccr |= c->dma_sig & 0x1f;
+ d->ccr |= 1 << 5; /* frame sync */
+
+ if (dir == DMA_DEV_TO_MEM)
+ d->ccr |= 1 << 24; /* source synch */
+
d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ;
}
@@ -632,19 +604,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
enum dma_slave_buswidth dev_width;
struct omap_desc *d;
dma_addr_t dev_addr;
- unsigned es, sync_type;
+ unsigned es;
u32 burst;
if (dir == DMA_DEV_TO_MEM) {
dev_addr = c->cfg.src_addr;
dev_width = c->cfg.src_addr_width;
burst = c->cfg.src_maxburst;
- sync_type = OMAP_DMA_SRC_SYNC;
} else if (dir == DMA_MEM_TO_DEV) {
dev_addr = c->cfg.dst_addr;
dev_width = c->cfg.dst_addr_width;
burst = c->cfg.dst_maxburst;
- sync_type = OMAP_DMA_DST_SYNC;
} else {
dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
return NULL;
@@ -674,15 +644,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
d->dev_addr = dev_addr;
d->fi = burst;
d->es = es;
- if (burst)
- d->sync_mode = OMAP_DMA_SYNC_PACKET;
- else
- d->sync_mode = OMAP_DMA_SYNC_ELEMENT;
- d->sync_type = sync_type;
d->sg[0].addr = buf_addr;
d->sg[0].en = period_len / es_bytes[es];
d->sg[0].fn = buf_len / period_len;
d->sglen = 1;
+
+ d->ccr = 0;
+ if (__dma_omap15xx(od->plat->dma_attr))
+ d->ccr = 3 << 8;
+ if (dir == DMA_DEV_TO_MEM)
+ d->ccr |= OMAP_DMA_AMODE_POST_INC << 14 |
+ OMAP_DMA_AMODE_CONSTANT << 12;
+ else
+ d->ccr |= OMAP_DMA_AMODE_CONSTANT << 14 |
+ OMAP_DMA_AMODE_POST_INC << 12;
+
d->cicr = OMAP_DMA_DROP_IRQ;
if (flags & DMA_PREP_INTERRUPT)
d->cicr |= OMAP_DMA_FRAME_IRQ;
@@ -690,6 +666,14 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
d->csdp = es;
if (dma_omap1()) {
+ if (__dma_omap16xx(od->plat->dma_attr)) {
+ d->ccr |= 1 << 10; /* disable 3.0/3.1 compatibility mode */
+ /* Duplicate what plat-omap/dma.c does */
+ d->ccr |= c->dma_ch + 1;
+ } else {
+ d->ccr |= c->dma_sig & 0x1f;
+ }
+
d->cicr |= OMAP1_DMA_TOUT_IRQ;
if (dir == DMA_DEV_TO_MEM)
@@ -699,23 +683,22 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
d->csdp |= OMAP_DMA_PORT_MPUI << 9 |
OMAP_DMA_PORT_EMIFF << 2;
} else {
+ d->ccr |= (c->dma_sig & ~0x1f) << 14;
+ d->ccr |= c->dma_sig & 0x1f;
+
+ if (burst)
+ d->ccr |= 1 << 18 | 1 << 5; /* packet */
+
+ if (dir == DMA_DEV_TO_MEM)
+ d->ccr |= 1 << 24; /* source synch */
+
d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ;
/* src and dst burst mode 16 */
d->csdp |= 3 << 14 | 3 << 7;
}
- if (!c->cyclic) {
- c->cyclic = true;
-
- if (__dma_omap15xx(od->plat->dma_attr)) {
- uint32_t val;
-
- val = c->plat->dma_read(CCR, c->dma_ch);
- val |= 3 << 8;
- c->plat->dma_write(val, CCR, c->dma_ch);
- }
- }
+ c->cyclic = true;
return vchan_tx_prep(&c->vc, &d->vd, flags);
}
@@ -759,14 +742,6 @@ static int omap_dma_terminate_all(struct omap_chan *c)
if (c->cyclic) {
c->cyclic = false;
c->paused = false;
-
- if (__dma_omap15xx(od->plat->dma_attr)) {
- uint32_t val;
-
- val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~(3 << 8);
- c->plat->dma_write(val, CCR, c->dma_ch);
- }
}
vchan_get_all_descriptors(&c->vc, &head);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 07/26] dmaengine: omap-dma: consolidate setup of CSDP
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Consolidate the setup of the channel source destination parameters
register. This way, we calculate the required CSDP value when we setup
a transfer descriptor, and only write it to the device registers once
when we start the descriptor.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 64 ++++++++++++++++++++++----------------------------
1 file changed, 28 insertions(+), 36 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 323eae2c9d08..ec7cc10d4594 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -60,8 +60,8 @@ struct omap_desc {
uint8_t es; /* OMAP_DMA_DATA_TYPE_xxx */
uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */
uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */
- uint8_t periph_port; /* Peripheral port */
uint16_t cicr; /* CICR value */
+ uint32_t csdp; /* CSDP value */
unsigned sglen;
struct omap_sg sg[0];
@@ -240,14 +240,6 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->sgidx = 0;
if (d->dir == DMA_DEV_TO_MEM) {
- if (dma_omap1()) {
- val = c->plat->dma_read(CSDP, c->dma_ch);
- val &= ~(0x1f << 9 | 0x1f << 2);
- val |= OMAP_DMA_PORT_EMIFF << 9;
- val |= d->periph_port << 2;
- c->plat->dma_write(val, CSDP, c->dma_ch);
- }
-
val = c->plat->dma_read(CCR, c->dma_ch);
val &= ~(0x03 << 14 | 0x03 << 12);
val |= OMAP_DMA_AMODE_POST_INC << 14;
@@ -258,14 +250,6 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->plat->dma_write(0, CSEI, c->dma_ch);
c->plat->dma_write(d->fi, CSFI, c->dma_ch);
} else {
- if (dma_omap1()) {
- val = c->plat->dma_read(CSDP, c->dma_ch);
- val &= ~(0x1f << 9 | 0x1f << 2);
- val |= d->periph_port << 9;
- val |= OMAP_DMA_PORT_EMIFF << 2;
- c->plat->dma_write(val, CSDP, c->dma_ch);
- }
-
val = c->plat->dma_read(CCR, c->dma_ch);
val &= ~(0x03 << 12 | 0x03 << 14);
val |= OMAP_DMA_AMODE_CONSTANT << 14;
@@ -277,10 +261,7 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->plat->dma_write(d->fi, CDFI, c->dma_ch);
}
- val = c->plat->dma_read(CSDP, c->dma_ch);
- val &= ~0x03;
- val |= d->es;
- c->plat->dma_write(val, CSDP, c->dma_ch);
+ c->plat->dma_write(d->csdp, CSDP, c->dma_ch);
if (dma_omap1()) {
val = c->plat->dma_read(CCR, c->dma_ch);
@@ -602,13 +583,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->es = es;
d->sync_mode = OMAP_DMA_SYNC_FRAME;
d->sync_type = sync_type;
- d->periph_port = OMAP_DMA_PORT_TIPB;
d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
+ d->csdp = es;
- if (dma_omap1())
+ if (dma_omap1()) {
d->cicr |= OMAP1_DMA_TOUT_IRQ;
- else
+
+ if (dir == DMA_DEV_TO_MEM)
+ d->csdp |= OMAP_DMA_PORT_EMIFF << 9 |
+ OMAP_DMA_PORT_TIPB << 2;
+ else
+ d->csdp |= OMAP_DMA_PORT_TIPB << 9 |
+ OMAP_DMA_PORT_EMIFF << 2;
+ } else {
d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ;
+ }
/*
* Build our scatterlist entries: each contains the address,
@@ -690,7 +679,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
else
d->sync_mode = OMAP_DMA_SYNC_ELEMENT;
d->sync_type = sync_type;
- d->periph_port = OMAP_DMA_PORT_MPUI;
d->sg[0].addr = buf_addr;
d->sg[0].en = period_len / es_bytes[es];
d->sg[0].fn = buf_len / period_len;
@@ -699,11 +687,24 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
if (flags & DMA_PREP_INTERRUPT)
d->cicr |= OMAP_DMA_FRAME_IRQ;
- if (dma_omap1())
+ d->csdp = es;
+
+ if (dma_omap1()) {
d->cicr |= OMAP1_DMA_TOUT_IRQ;
- else
+
+ if (dir == DMA_DEV_TO_MEM)
+ d->csdp |= OMAP_DMA_PORT_EMIFF << 9 |
+ OMAP_DMA_PORT_MPUI << 2;
+ else
+ d->csdp |= OMAP_DMA_PORT_MPUI << 9 |
+ OMAP_DMA_PORT_EMIFF << 2;
+ } else {
d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ;
+ /* src and dst burst mode 16 */
+ d->csdp |= 3 << 14 | 3 << 7;
+ }
+
if (!c->cyclic) {
c->cyclic = true;
@@ -716,15 +717,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
}
}
- if (dma_omap2plus()) {
- uint32_t val;
-
- val = c->plat->dma_read(CSDP, c->dma_ch);
- val |= 0x03 << 7; /* src burst mode 16 */
- val |= 0x03 << 14; /* dst burst mode 16 */
- c->plat->dma_write(val, CSDP, c->dma_ch);
- }
-
return vchan_tx_prep(&c->vc, &d->vd, flags);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH 06/26] dmaengine: omap-dma: move reading of dma position to omap-dma.c
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Read the current DMA position from the hardware directly rather than via
arch/arm/plat-omap/dma.c.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 64 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 7aa5ff7ab935..323eae2c9d08 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -427,6 +427,68 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr)
return size;
}
+static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c)
+{
+ struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+ dma_addr_t addr;
+
+ if (__dma_omap15xx(od->plat->dma_attr))
+ addr = c->plat->dma_read(CPC, c->dma_ch);
+ else
+ addr = c->plat->dma_read(CSAC, c->dma_ch);
+
+ if (od->plat->errata & DMA_ERRATA_3_3 && addr == 0)
+ addr = c->plat->dma_read(CSAC, c->dma_ch);
+
+ if (!__dma_omap15xx(od->plat->dma_attr)) {
+ /*
+ * CDAC == 0 indicates that the DMA transfer on the channel has
+ * not been started (no data has been transferred so far).
+ * Return the programmed source start address in this case.
+ */
+ if (c->plat->dma_read(CDAC, c->dma_ch))
+ addr = c->plat->dma_read(CSAC, c->dma_ch);
+ else
+ addr = c->plat->dma_read(CSSA, c->dma_ch);
+ }
+
+ if (dma_omap1())
+ addr |= c->plat->dma_read(CSSA, c->dma_ch) & 0xffff0000;
+
+ return addr;
+}
+
+static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c)
+{
+ struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+ dma_addr_t addr;
+
+ if (__dma_omap15xx(od->plat->dma_attr))
+ addr = c->plat->dma_read(CPC, c->dma_ch);
+ else
+ addr = c->plat->dma_read(CDAC, c->dma_ch);
+
+ /*
+ * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
+ * read before the DMA controller finished disabling the channel.
+ */
+ if (!__dma_omap15xx(od->plat->dma_attr) && addr == 0) {
+ addr = c->plat->dma_read(CDAC, c->dma_ch);
+ /*
+ * CDAC == 0 indicates that the DMA transfer on the channel has
+ * not been started (no data has been transferred so far).
+ * Return the programmed destination start address in this case.
+ */
+ if (addr == 0)
+ addr = c->plat->dma_read(CDSA, c->dma_ch);
+ }
+
+ if (dma_omap1())
+ addr |= c->plat->dma_read(CDSA, c->dma_ch) & 0xffff0000;
+
+ return addr;
+}
+
static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *txstate)
{
@@ -448,9 +510,9 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
dma_addr_t pos;
if (d->dir == DMA_MEM_TO_DEV)
- pos = omap_get_dma_src_pos(c->dma_ch);
+ pos = omap_dma_get_src_pos(c);
else if (d->dir == DMA_DEV_TO_MEM)
- pos = omap_get_dma_dst_pos(c->dma_ch);
+ pos = omap_dma_get_dst_pos(c);
else
pos = 0;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 05/26] dmaengine: omap-dma: control start/stop directly
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Program the non-cyclic mode DMA start/stop directly, rather than via
arch/arm/plat-omap/dma.c.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 151 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 141 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 8c5c862f01ed..7aa5ff7ab935 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -5,6 +5,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
@@ -60,6 +61,7 @@ struct omap_desc {
uint8_t sync_mode; /* OMAP_DMA_SYNC_xxx */
uint8_t sync_type; /* OMAP_DMA_xxx_SYNC* */
uint8_t periph_port; /* Peripheral port */
+ uint16_t cicr; /* CICR value */
unsigned sglen;
struct omap_sg sg[0];
@@ -95,6 +97,111 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)
kfree(container_of(vd, struct omap_desc, vd));
}
+static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
+{
+ struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+ uint32_t val;
+
+ if (__dma_omap15xx(od->plat->dma_attr))
+ c->plat->dma_write(0, CPC, c->dma_ch);
+ else
+ c->plat->dma_write(0, CDAC, c->dma_ch);
+
+ if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) {
+ val = c->plat->dma_read(CLNK_CTRL, c->dma_ch);
+
+ if (dma_omap1())
+ val &= ~(1 << 14);
+
+ val |= c->dma_ch | 1 << 15;
+
+ c->plat->dma_write(val, CLNK_CTRL, c->dma_ch);
+ } else if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS)
+ c->plat->dma_write(c->dma_ch, CLNK_CTRL, c->dma_ch);
+
+ /* Clear CSR */
+ if (dma_omap1())
+ c->plat->dma_read(CSR, c->dma_ch);
+ else
+ c->plat->dma_write(~0, CSR, c->dma_ch);
+
+ /* Enable interrupts */
+ c->plat->dma_write(d->cicr, CICR, c->dma_ch);
+
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
+ val |= OMAP_DMA_CCR_BUFFERING_DISABLE;
+ val |= OMAP_DMA_CCR_EN;
+ mb();
+ c->plat->dma_write(val, CCR, c->dma_ch);
+}
+
+static void omap_dma_stop(struct omap_chan *c)
+{
+ struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
+ uint32_t val;
+
+ /* disable irq */
+ c->plat->dma_write(0, CICR, c->dma_ch);
+
+ /* Clear CSR */
+ if (dma_omap1())
+ c->plat->dma_read(CSR, c->dma_ch);
+ else
+ c->plat->dma_write(~0, CSR, c->dma_ch);
+
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ if (od->plat->errata & DMA_ERRATA_i541 &&
+ val & OMAP_DMA_CCR_SEL_SRC_DST_SYNC) {
+ uint32_t sysconfig;
+ unsigned i;
+
+ sysconfig = c->plat->dma_read(OCP_SYSCONFIG, c->dma_ch);
+ val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+ val |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
+ c->plat->dma_write(val, OCP_SYSCONFIG, c->dma_ch);
+
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ val &= ~OMAP_DMA_CCR_EN;
+ c->plat->dma_write(val, CCR, c->dma_ch);
+
+ /* Wait for sDMA FIFO to drain */
+ for (i = 0; ; i++) {
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ if (!(val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE)))
+ break;
+
+ if (i > 100)
+ break;
+
+ udelay(5);
+ }
+
+ if (val & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))
+ dev_err(c->vc.chan.device->dev,
+ "DMA drain did not complete on lch %d\n",
+ c->dma_ch);
+
+ c->plat->dma_write(sysconfig, OCP_SYSCONFIG, c->dma_ch);
+ } else {
+ val &= ~OMAP_DMA_CCR_EN;
+ c->plat->dma_write(val, CCR, c->dma_ch);
+ }
+
+ mb();
+
+ if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) {
+ val = c->plat->dma_read(CLNK_CTRL, c->dma_ch);
+
+ if (dma_omap1())
+ val |= 1 << 14; /* set the STOP_LNK bit */
+ else
+ val &= ~(1 << 15); /* Clear the ENABLE_LNK bit */
+
+ c->plat->dma_write(val, CLNK_CTRL, c->dma_ch);
+ }
+}
+
static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
unsigned idx)
{
@@ -113,7 +220,7 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
c->plat->dma_write(sg->en, CEN, c->dma_ch);
c->plat->dma_write(sg->fn, CFN, c->dma_ch);
- omap_start_dma(c->dma_ch);
+ omap_dma_start(c, d);
}
static void omap_dma_start_desc(struct omap_chan *c)
@@ -434,6 +541,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
d->sync_mode = OMAP_DMA_SYNC_FRAME;
d->sync_type = sync_type;
d->periph_port = OMAP_DMA_PORT_TIPB;
+ d->cicr = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
+
+ if (dma_omap1())
+ d->cicr |= OMAP1_DMA_TOUT_IRQ;
+ else
+ d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ;
/*
* Build our scatterlist entries: each contains the address,
@@ -463,6 +576,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
size_t period_len, enum dma_transfer_direction dir, unsigned long flags,
void *context)
{
+ struct omap_dmadev *od = to_omap_dma_dev(chan->device);
struct omap_chan *c = to_omap_dma_chan(chan);
enum dma_slave_buswidth dev_width;
struct omap_desc *d;
@@ -519,15 +633,25 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
d->sg[0].en = period_len / es_bytes[es];
d->sg[0].fn = buf_len / period_len;
d->sglen = 1;
+ d->cicr = OMAP_DMA_DROP_IRQ;
+ if (flags & DMA_PREP_INTERRUPT)
+ d->cicr |= OMAP_DMA_FRAME_IRQ;
+
+ if (dma_omap1())
+ d->cicr |= OMAP1_DMA_TOUT_IRQ;
+ else
+ d->cicr |= OMAP2_DMA_MISALIGNED_ERR_IRQ | OMAP2_DMA_TRANS_ERR_IRQ;
if (!c->cyclic) {
c->cyclic = true;
- omap_dma_link_lch(c->dma_ch, c->dma_ch);
- if (flags & DMA_PREP_INTERRUPT)
- omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ);
+ if (__dma_omap15xx(od->plat->dma_attr)) {
+ uint32_t val;
- omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ);
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ val |= 3 << 8;
+ c->plat->dma_write(val, CCR, c->dma_ch);
+ }
}
if (dma_omap2plus()) {
@@ -568,20 +692,27 @@ static int omap_dma_terminate_all(struct omap_chan *c)
/*
* Stop DMA activity: we assume the callback will not be called
- * after omap_stop_dma() returns (even if it does, it will see
+ * after omap_dma_stop() returns (even if it does, it will see
* c->desc is NULL and exit.)
*/
if (c->desc) {
c->desc = NULL;
/* Avoid stopping the dma twice */
if (!c->paused)
- omap_stop_dma(c->dma_ch);
+ omap_dma_stop(c);
}
if (c->cyclic) {
c->cyclic = false;
c->paused = false;
- omap_dma_unlink_lch(c->dma_ch, c->dma_ch);
+
+ if (__dma_omap15xx(od->plat->dma_attr)) {
+ uint32_t val;
+
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ val &= ~(3 << 8);
+ c->plat->dma_write(val, CCR, c->dma_ch);
+ }
}
vchan_get_all_descriptors(&c->vc, &head);
@@ -598,7 +729,7 @@ static int omap_dma_pause(struct omap_chan *c)
return -EINVAL;
if (!c->paused) {
- omap_stop_dma(c->dma_ch);
+ omap_dma_stop(c);
c->paused = true;
}
@@ -612,7 +743,7 @@ static int omap_dma_resume(struct omap_chan *c)
return -EINVAL;
if (c->paused) {
- omap_start_dma(c->dma_ch);
+ omap_dma_start(c, c->desc);
c->paused = false;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH 04/26] dmaengine: omap-dma: consolidate writes to DMA registers
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
There's no need to keep writing registers which don't change value in
omap_dma_start_sg(). Move this into omap_dma_start_desc() and merge
the register updates together.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 123 +++++++++++++++++++------------------------------
1 file changed, 48 insertions(+), 75 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 47a3fa5bc38e..8c5c862f01ed 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -99,40 +99,75 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
unsigned idx)
{
struct omap_sg *sg = d->sg + idx;
+
+ if (d->dir == DMA_DEV_TO_MEM) {
+ c->plat->dma_write(sg->addr, CDSA, c->dma_ch);
+ c->plat->dma_write(0, CDEI, c->dma_ch);
+ c->plat->dma_write(0, CDFI, c->dma_ch);
+ } else {
+ c->plat->dma_write(sg->addr, CSSA, c->dma_ch);
+ c->plat->dma_write(0, CSEI, c->dma_ch);
+ c->plat->dma_write(0, CSFI, c->dma_ch);
+ }
+
+ c->plat->dma_write(sg->en, CEN, c->dma_ch);
+ c->plat->dma_write(sg->fn, CFN, c->dma_ch);
+
+ omap_start_dma(c->dma_ch);
+}
+
+static void omap_dma_start_desc(struct omap_chan *c)
+{
+ struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
+ struct omap_desc *d;
uint32_t val;
+ if (!vd) {
+ c->desc = NULL;
+ return;
+ }
+
+ list_del(&vd->node);
+
+ c->desc = d = to_omap_dma_desc(&vd->tx);
+ c->sgidx = 0;
+
if (d->dir == DMA_DEV_TO_MEM) {
if (dma_omap1()) {
val = c->plat->dma_read(CSDP, c->dma_ch);
- val &= ~(0x1f << 9);
+ val &= ~(0x1f << 9 | 0x1f << 2);
val |= OMAP_DMA_PORT_EMIFF << 9;
+ val |= d->periph_port << 2;
c->plat->dma_write(val, CSDP, c->dma_ch);
}
val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~(0x03 << 14);
+ val &= ~(0x03 << 14 | 0x03 << 12);
val |= OMAP_DMA_AMODE_POST_INC << 14;
+ val |= OMAP_DMA_AMODE_CONSTANT << 12;
c->plat->dma_write(val, CCR, c->dma_ch);
- c->plat->dma_write(sg->addr, CDSA, c->dma_ch);
- c->plat->dma_write(0, CDEI, c->dma_ch);
- c->plat->dma_write(0, CDFI, c->dma_ch);
+ c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch);
+ c->plat->dma_write(0, CSEI, c->dma_ch);
+ c->plat->dma_write(d->fi, CSFI, c->dma_ch);
} else {
if (dma_omap1()) {
val = c->plat->dma_read(CSDP, c->dma_ch);
- val &= ~(0x1f << 2);
+ val &= ~(0x1f << 9 | 0x1f << 2);
+ val |= d->periph_port << 9;
val |= OMAP_DMA_PORT_EMIFF << 2;
c->plat->dma_write(val, CSDP, c->dma_ch);
}
val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~(0x03 << 12);
+ val &= ~(0x03 << 12 | 0x03 << 14);
+ val |= OMAP_DMA_AMODE_CONSTANT << 14;
val |= OMAP_DMA_AMODE_POST_INC << 12;
c->plat->dma_write(val, CCR, c->dma_ch);
- c->plat->dma_write(sg->addr, CSSA, c->dma_ch);
- c->plat->dma_write(0, CSEI, c->dma_ch);
- c->plat->dma_write(0, CSFI, c->dma_ch);
+ c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch);
+ c->plat->dma_write(0, CDEI, c->dma_ch);
+ c->plat->dma_write(d->fi, CDFI, c->dma_ch);
}
val = c->plat->dma_read(CSDP, c->dma_ch);
@@ -156,91 +191,29 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
val = c->plat->dma_read(CCR, c->dma_ch);
/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
- val &= ~((1 << 23) | (3 << 19) | 0x1f);
+ val &= ~(1 << 24 | 1 << 23 | 3 << 19 | 1 << 18 | 1 << 5 | 0x1f);
val |= (c->dma_sig & ~0x1f) << 14;
val |= c->dma_sig & 0x1f;
if (d->sync_mode & OMAP_DMA_SYNC_FRAME)
val |= 1 << 5;
- else
- val &= ~(1 << 5);
if (d->sync_mode & OMAP_DMA_SYNC_BLOCK)
val |= 1 << 18;
- else
- val &= ~(1 << 18);
switch (d->sync_type) {
- case OMAP_DMA_DST_SYNC_PREFETCH:
- val &= ~(1 << 24); /* dest synch */
+ case OMAP_DMA_DST_SYNC_PREFETCH:/* dest synch */
val |= 1 << 23; /* Prefetch */
break;
case 0:
- val &= ~(1 << 24); /* dest synch */
break;
default:
- val |= 1 << 24; /* source synch */
+ val |= 1 << 24; /* source synch */
break;
}
c->plat->dma_write(val, CCR, c->dma_ch);
}
- c->plat->dma_write(sg->en, CEN, c->dma_ch);
- c->plat->dma_write(sg->fn, CFN, c->dma_ch);
-
- omap_start_dma(c->dma_ch);
-}
-
-static void omap_dma_start_desc(struct omap_chan *c)
-{
- struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
- struct omap_desc *d;
- uint32_t val;
-
- if (!vd) {
- c->desc = NULL;
- return;
- }
-
- list_del(&vd->node);
-
- c->desc = d = to_omap_dma_desc(&vd->tx);
- c->sgidx = 0;
-
- if (d->dir == DMA_DEV_TO_MEM) {
- if (dma_omap1()) {
- val = c->plat->dma_read(CSDP, c->dma_ch);
- val &= ~(0x1f << 2);
- val |= d->periph_port << 2;
- c->plat->dma_write(val, CSDP, c->dma_ch);
- }
-
- val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~(0x03 << 12);
- val |= OMAP_DMA_AMODE_CONSTANT << 12;
- c->plat->dma_write(val, CCR, c->dma_ch);
-
- c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch);
- c->plat->dma_write(0, CSEI, c->dma_ch);
- c->plat->dma_write(d->fi, CSFI, c->dma_ch);
- } else {
- if (dma_omap1()) {
- val = c->plat->dma_read(CSDP, c->dma_ch);
- val &= ~(0x1f << 9);
- val |= d->periph_port << 9;
- c->plat->dma_write(val, CSDP, c->dma_ch);
- }
-
- val = c->plat->dma_read(CCR, c->dma_ch);
- val &= ~(0x03 << 14);
- val |= OMAP_DMA_AMODE_CONSTANT << 14;
- c->plat->dma_write(val, CCR, c->dma_ch);
-
- c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch);
- c->plat->dma_write(0, CDEI, c->dma_ch);
- c->plat->dma_write(d->fi, CDFI, c->dma_ch);
- }
-
omap_dma_start_sg(c, d, 0);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH 03/26] dmaengine: omap-dma: program hardware directly
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Program the transfer parameters directly into the hardware, rather
than using the functions in arch/arm/plat-omap/dma.c.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 142 +++++++++++++++++++++++++++++++++++++++++------
include/linux/omap-dma.h | 6 +-
2 files changed, 130 insertions(+), 18 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 4ac26bf0ad30..47a3fa5bc38e 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -99,16 +99,94 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d,
unsigned idx)
{
struct omap_sg *sg = d->sg + idx;
+ uint32_t val;
+
+ if (d->dir == DMA_DEV_TO_MEM) {
+ if (dma_omap1()) {
+ val = c->plat->dma_read(CSDP, c->dma_ch);
+ val &= ~(0x1f << 9);
+ val |= OMAP_DMA_PORT_EMIFF << 9;
+ c->plat->dma_write(val, CSDP, c->dma_ch);
+ }
- if (d->dir == DMA_DEV_TO_MEM)
- omap_set_dma_dest_params(c->dma_ch, OMAP_DMA_PORT_EMIFF,
- OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0);
- else
- omap_set_dma_src_params(c->dma_ch, OMAP_DMA_PORT_EMIFF,
- OMAP_DMA_AMODE_POST_INC, sg->addr, 0, 0);
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ val &= ~(0x03 << 14);
+ val |= OMAP_DMA_AMODE_POST_INC << 14;
+ c->plat->dma_write(val, CCR, c->dma_ch);
+
+ c->plat->dma_write(sg->addr, CDSA, c->dma_ch);
+ c->plat->dma_write(0, CDEI, c->dma_ch);
+ c->plat->dma_write(0, CDFI, c->dma_ch);
+ } else {
+ if (dma_omap1()) {
+ val = c->plat->dma_read(CSDP, c->dma_ch);
+ val &= ~(0x1f << 2);
+ val |= OMAP_DMA_PORT_EMIFF << 2;
+ c->plat->dma_write(val, CSDP, c->dma_ch);
+ }
+
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ val &= ~(0x03 << 12);
+ val |= OMAP_DMA_AMODE_POST_INC << 12;
+ c->plat->dma_write(val, CCR, c->dma_ch);
+
+ c->plat->dma_write(sg->addr, CSSA, c->dma_ch);
+ c->plat->dma_write(0, CSEI, c->dma_ch);
+ c->plat->dma_write(0, CSFI, c->dma_ch);
+ }
+
+ val = c->plat->dma_read(CSDP, c->dma_ch);
+ val &= ~0x03;
+ val |= d->es;
+ c->plat->dma_write(val, CSDP, c->dma_ch);
+
+ if (dma_omap1()) {
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ val &= ~(1 << 5);
+ if (d->sync_mode == OMAP_DMA_SYNC_FRAME)
+ val |= 1 << 5;
+ c->plat->dma_write(val, CCR, c->dma_ch);
+
+ val = c->plat->dma_read(CCR2, c->dma_ch);
+ val &= ~(1 << 2);
+ if (d->sync_mode == OMAP_DMA_SYNC_BLOCK)
+ val |= 1 << 2;
+ c->plat->dma_write(val, CCR2, c->dma_ch);
+ } else if (c->dma_sig) {
+ val = c->plat->dma_read(CCR, c->dma_ch);
+
+ /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
+ val &= ~((1 << 23) | (3 << 19) | 0x1f);
+ val |= (c->dma_sig & ~0x1f) << 14;
+ val |= c->dma_sig & 0x1f;
+
+ if (d->sync_mode & OMAP_DMA_SYNC_FRAME)
+ val |= 1 << 5;
+ else
+ val &= ~(1 << 5);
+
+ if (d->sync_mode & OMAP_DMA_SYNC_BLOCK)
+ val |= 1 << 18;
+ else
+ val &= ~(1 << 18);
+
+ switch (d->sync_type) {
+ case OMAP_DMA_DST_SYNC_PREFETCH:
+ val &= ~(1 << 24); /* dest synch */
+ val |= 1 << 23; /* Prefetch */
+ break;
+ case 0:
+ val &= ~(1 << 24); /* dest synch */
+ break;
+ default:
+ val |= 1 << 24; /* source synch */
+ break;
+ }
+ c->plat->dma_write(val, CCR, c->dma_ch);
+ }
- omap_set_dma_transfer_params(c->dma_ch, d->es, sg->en, sg->fn,
- d->sync_mode, c->dma_sig, d->sync_type);
+ c->plat->dma_write(sg->en, CEN, c->dma_ch);
+ c->plat->dma_write(sg->fn, CFN, c->dma_ch);
omap_start_dma(c->dma_ch);
}
@@ -117,6 +195,7 @@ static void omap_dma_start_desc(struct omap_chan *c)
{
struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
struct omap_desc *d;
+ uint32_t val;
if (!vd) {
c->desc = NULL;
@@ -128,12 +207,39 @@ static void omap_dma_start_desc(struct omap_chan *c)
c->desc = d = to_omap_dma_desc(&vd->tx);
c->sgidx = 0;
- if (d->dir == DMA_DEV_TO_MEM)
- omap_set_dma_src_params(c->dma_ch, d->periph_port,
- OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi);
- else
- omap_set_dma_dest_params(c->dma_ch, d->periph_port,
- OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi);
+ if (d->dir == DMA_DEV_TO_MEM) {
+ if (dma_omap1()) {
+ val = c->plat->dma_read(CSDP, c->dma_ch);
+ val &= ~(0x1f << 2);
+ val |= d->periph_port << 2;
+ c->plat->dma_write(val, CSDP, c->dma_ch);
+ }
+
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ val &= ~(0x03 << 12);
+ val |= OMAP_DMA_AMODE_CONSTANT << 12;
+ c->plat->dma_write(val, CCR, c->dma_ch);
+
+ c->plat->dma_write(d->dev_addr, CSSA, c->dma_ch);
+ c->plat->dma_write(0, CSEI, c->dma_ch);
+ c->plat->dma_write(d->fi, CSFI, c->dma_ch);
+ } else {
+ if (dma_omap1()) {
+ val = c->plat->dma_read(CSDP, c->dma_ch);
+ val &= ~(0x1f << 9);
+ val |= d->periph_port << 9;
+ c->plat->dma_write(val, CSDP, c->dma_ch);
+ }
+
+ val = c->plat->dma_read(CCR, c->dma_ch);
+ val &= ~(0x03 << 14);
+ val |= OMAP_DMA_AMODE_CONSTANT << 14;
+ c->plat->dma_write(val, CCR, c->dma_ch);
+
+ c->plat->dma_write(d->dev_addr, CDSA, c->dma_ch);
+ c->plat->dma_write(0, CDEI, c->dma_ch);
+ c->plat->dma_write(d->fi, CDFI, c->dma_ch);
+ }
omap_dma_start_sg(c, d, 0);
}
@@ -452,8 +558,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
}
if (dma_omap2plus()) {
- omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
- omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
+ uint32_t val;
+
+ val = c->plat->dma_read(CSDP, c->dma_ch);
+ val |= 0x03 << 7; /* src burst mode 16 */
+ val |= 0x03 << 14; /* dst burst mode 16 */
+ c->plat->dma_write(val, CSDP, c->dma_ch);
}
return vchan_tx_prep(&c->vc, &d->vd, flags);
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index 14742fc2aefe..d631658e2237 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -289,8 +289,10 @@ struct omap_system_dma_plat_info {
#define dma_omap2plus() 0
#endif
#define dma_omap1() (!dma_omap2plus())
-#define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE)))
-#define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE)))
+#define __dma_omap15xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_1510_MODE)
+#define __dma_omap16xx(d) (dma_omap1() && (d)->dev_caps & ENABLE_16XX_MODE)
+#define dma_omap15xx() __dma_omap15xx(d)
+#define dma_omap16xx() __dma_omap16xx(d)
extern struct omap_system_dma_plat_info *omap_get_plat_info(void);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 02/26] dmaengine: omap-dma: provide a hook to get the underlying DMA platform ops
From: Russell King @ 2014-02-10 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Provide and use a hook to obtain the underlying DMA platform operations
so that omap-dma.c can access the hardware more directly without
involving the legacy DMA driver.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/plat-omap/dma.c | 6 ++++++
drivers/dma/omap-dma.c | 7 +++++++
include/linux/omap-dma.h | 2 ++
3 files changed, 15 insertions(+)
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 01619c2910e3..d4d9a5e62152 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -2000,6 +2000,12 @@ void omap_dma_global_context_restore(void)
omap_clear_dma(ch);
}
+struct omap_system_dma_plat_info *omap_get_plat_info(void)
+{
+ return p;
+}
+EXPORT_SYMBOL_GPL(omap_get_plat_info);
+
static int omap_system_dma_probe(struct platform_device *pdev)
{
int ch, ret = 0;
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 98034e8c558f..4ac26bf0ad30 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -26,11 +26,13 @@ struct omap_dmadev {
spinlock_t lock;
struct tasklet_struct task;
struct list_head pending;
+ struct omap_system_dma_plat_info *plat;
};
struct omap_chan {
struct virt_dma_chan vc;
struct list_head node;
+ struct omap_system_dma_plat_info *plat;
struct dma_slave_config cfg;
unsigned dma_sig;
@@ -573,6 +575,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig)
if (!c)
return -ENOMEM;
+ c->plat = od->plat;
c->dma_sig = dma_sig;
c->vc.desc_free = omap_dma_desc_free;
vchan_init(&c->vc, &od->ddev);
@@ -605,6 +608,10 @@ static int omap_dma_probe(struct platform_device *pdev)
if (!od)
return -ENOMEM;
+ od->plat = omap_get_plat_info();
+ if (!od->plat)
+ return -EPROBE_DEFER;
+
dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources;
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index 7af25a9c9c51..14742fc2aefe 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -292,6 +292,8 @@ struct omap_system_dma_plat_info {
#define dma_omap15xx() ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE)))
#define dma_omap16xx() ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE)))
+extern struct omap_system_dma_plat_info *omap_get_plat_info(void);
+
extern void omap_set_dma_priority(int lch, int dst_port, int priority);
extern int omap_request_dma(int dev_id, const char *dev_name,
void (*callback)(int lch, u16 ch_status, void *data),
--
1.8.3.1
^ permalink raw reply related
* [PATCH 01/26] dmaengine: omap-dma: use devm_kzalloc() to allocate omap_dmadev.
From: Russell King @ 2014-02-10 15:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>
Use devm_kzalloc() to allocate omap_dmadev() so that we don't need
complex error cleanup paths.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/dma/omap-dma.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 362e7c49f2e1..98034e8c558f 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -594,7 +594,6 @@ static void omap_dma_free(struct omap_dmadev *od)
tasklet_kill(&c->vc.task);
kfree(c);
}
- kfree(od);
}
static int omap_dma_probe(struct platform_device *pdev)
@@ -602,7 +601,7 @@ static int omap_dma_probe(struct platform_device *pdev)
struct omap_dmadev *od;
int rc, i;
- od = kzalloc(sizeof(*od), GFP_KERNEL);
+ od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
if (!od)
return -ENOMEM;
--
1.8.3.1
^ permalink raw reply related
* [PATCH 00/26] OMAP dma engine rework
From: Russell King - ARM Linux @ 2014-02-10 15:55 UTC (permalink / raw)
To: linux-arm-kernel
This is the current set of patches for the OMAP DMA engine rework,
which should now work correctly on OMAP1 platforms thanks to Tony's
testing.
It would be good to get this validated by others across a range of
OMAP platforms, and queued up for the next merge window, so it can
be built upon.
Acks appreciated, and once sufficient have been added, I'll send a
pull request for this to Vinod.
arch/arm/mach-omap1/dma.c | 191 ++++++--------
arch/arm/mach-omap2/dma.c | 183 ++++++-------
arch/arm/plat-omap/dma.c | 17 +-
drivers/dma/omap-dma.c | 659 +++++++++++++++++++++++++++++++++++++++++-----
include/linux/omap-dma.h | 25 +-
5 files changed, 784 insertions(+), 291 deletions(-)
--
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
^ permalink raw reply
* [PATCH V5 4/8] phy: st-miphy-40lp: Add skeleton driver
From: Arnd Bergmann @ 2014-02-10 15:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <fb505abd332645671d9ad125003d8253b6346715.1391871170.git.pratyush.anand@st.com>
On Monday 10 February 2014, Mohit Kumar wrote:
> diff --git a/Documentation/devicetree/bindings/phy/st-miphy40lp.txt b/Documentation/devicetree/bindings/phy/st-miphy40lp.txt
> new file mode 100644
> index 0000000..d0c7096
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/st-miphy40lp.txt
> @@ -0,0 +1,12 @@
> +Required properties:
> +- compatible : should be "st,miphy40lp-phy"
> + Other supported soc specific compatible:
> + "st,spear1310-miphy"
> + "st,spear1340-miphy"
> +- reg : offset and length of the PHY register set.
> +- misc: phandle for the syscon node to access misc registers
> +- phy-id: Instance id of the phy.
> +- #phy-cells : from the generic PHY bindings, must be 1.
> + - 1st cell: phandle to the phy node.
> + - 2nd cell: 0 if phy (in 1st cell) is to be used for SATA, 1 for PCIe
> + and 2 for Super Speed USB.
It's common to start this file with a small header explaining what this
hardware is.
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index afa2354..2f58993 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -64,4 +64,10 @@ config BCM_KONA_USB2_PHY
> help
> Enable this to support the Broadcom Kona USB 2.0 PHY.
>
> +config PHY_ST_MIPHY40LP
> + tristate "ST MIPHY 40LP driver"
> + help
> + Support for ST MIPHY 40LP which can be used for PCIe, SATA and Super Speed USB.
> + select GENERIC_PHY
> +
> endmenu
The 'select' statement should come before 'help', for consistency with the
rest of the kernel. Maybe mention that this phy is used inside the
spear13xx SoC here rather than a standalone phy.
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv) {
> + dev_err(dev, "can't alloc miphy40lp private date memory\n");
> + return -ENOMEM;
> + }
> +
> + priv->plat_ops = (struct miphy40lp_plat_ops *)of_id->data;
The cast would incorrectly remove the 'const' attribute of the pointer.
Better remove the cast and make priv->plat_ops const.
> +static int __init miphy40lp_phy_init(void)
> +{
> +
> + return platform_driver_probe(&miphy40lp_driver,
> + miphy40lp_probe);
> +}
> +module_init(miphy40lp_phy_init);
There should certainly be a module_exit() function here so you can unload the
driver.
Arnd
^ permalink raw reply
* [PATCH v3 0/4] ARM: keystone: enable gpio support
From: Santosh Shilimkar @ 2014-02-10 15:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392050481-19086-1-git-send-email-grygorii.strashko@ti.com>
On Monday 10 February 2014 11:41 AM, Grygorii Strashko wrote:
> This series adds Keystone GPIO IP definition in DT and enable GPIO support in
> Keystone configuration file.
>
> Also, it enables LEDs support for Keystone 2 K2H EVM as specified in board
> schematic. For more information see:
> - http://www.advantech.com/Support/TI-EVM/EVMK2HX.aspx
>
> Changes in v3:
> - rebased on top 3.14 + "[PATCH v2] arm: dts: keystone: add watchdog entry"
> http://www.spinics.net/lists/devicetree/msg20211.html
>
> [v1-v2] http://www.spinics.net/lists/arm-kernel/msg294655.html
>
> Grygorii Strashko (4):
> ARM: dts: keystone: add gpio device entry
> ARM: dts: keystone-evm: add leds supports
> ARM: keystone_defconfig: enable gpio support
> ARM: keystone_defconfig: enable led support
>
Thanks for reposting the patchset Grygorii. I will
take them for the 3.15.
Would be good to get the blessing from DT folks
on first two patches.
Regards,
Santosh
^ permalink raw reply
* [PATCH v6 0/3] Introduce clocksource driver for Keystone platform
From: Santosh Shilimkar @ 2014-02-10 15:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392027058-11680-1-git-send-email-ivan.khoronzhuk@ti.com>
Daniel,
On Monday 10 February 2014 05:10 AM, Ivan Khoronzhuk wrote:
> Add a broadcast timer64 based clockevent driver for keystone arch.
> This driver uses timer in 64-bit general purpose mode as clock event
> device.
>
> Documentation:
> http://www.ti.com/lit/ug/sprugv5a/sprugv5a.pdf
>
> Based on
> git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
> keystone/master
>
> v5..v6:
> added function to encapsulate __iowmb().
>
> v4..v5:
> used __iowmb() insted of wmb()
>
> v3..v4:
> rebased on latest of linux-keystone.git keystone/master
>
> v2..v3:
> - clocksource: timer-keystone: introduce clocksource driver for
> changed "u64" type to "unsigned long" for hz_period as more appropriate
> hz_period rounded up by DIV_ROUND_UP(rate, HZ)
> corrected comments
>
> v1..v2:
> - clocksource: timer-keystone: introduce clocksource driver for
> renamed timer on "timer-keystone"
> in keystone_timer_interrupt() evet pointer is passed via "dev_id"
> used __relaxed variants of writel/readl and added explicit barriers
> added "keystone_timer_disable()" for using in keystone_set_mode()
> keystone_timer_config() is not used for disabling the timer any more
> in case of an unsupported mode the keystone_timer_config() returns -1.
> used request_irq() instead of setup_irq()
> assigned irq for event_device in event_dev->irq
> calculated timer.hz_period for CLOCK_EVT_MODE_PERIODIC at init
> deleted spare call of keystone_timer_config() in keystone_timer_init()
>
> Ivan Khoronzhuk (3):
> clocksource: timer-keystone: introduce clocksource driver for Keystone
> clocksource: keystone: add bindings for keystone timer
> arm: dts: keystone: add keystone timer entry
>
Can you queue the first two patches from the series ?
I will queue the dts patch via my tree.
Regards,
Santosh
^ permalink raw reply
* [RFC PATCH 2/3] mfd: syscon: Support early initialization
From: Michal Simek @ 2014-02-10 15:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1785585d090175da81b561b17eeef95d991ff0de.1392045742.git.michal.simek@xilinx.com>
On 02/10/2014 04:22 PM, Michal Simek wrote:
> Some platforms need to get system controller
> ready as soon as possible.
> The patch provides early_syscon_initialization
> which create early mapping for all syscon compatible
> devices in early_syscon_probe.
> Regmap is get via syscon_early_regmap_lookup_by_phandle()
>
> Regular device probes attach device to regmap
> via regmap_attach_dev().
>
> For early syscon initialization is necessary to extend
> struct syscon and provide remove function
> which unmap all early init structures.
>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> ---
>
> drivers/mfd/syscon.c | 126 +++++++++++++++++++++++++++++++++++++++------
> include/linux/mfd/syscon.h | 11 ++++
> 2 files changed, 120 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
> index 71841f9..5935f02 100644
> --- a/drivers/mfd/syscon.c
> +++ b/drivers/mfd/syscon.c
> @@ -20,12 +20,15 @@
> #include <linux/of_platform.h>
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> +#include <linux/slab.h>
> #include <linux/mfd/syscon.h>
>
> static struct platform_driver syscon_driver;
>
> struct syscon {
> + void __iomem *base;
> struct regmap *regmap;
> + struct resource res;
> };
>
> static int syscon_match_node(struct device *dev, void *data)
> @@ -95,6 +98,24 @@ struct regmap *syscon_regmap_lookup_by_pdevname(const char *s)
> }
> EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_pdevname);
>
> +struct regmap *syscon_early_regmap_lookup_by_phandle(struct device_node *np,
> + const char *property)
> +{
> + struct device_node *syscon_np;
> + struct syscon *syscon;
> +
> + syscon_np = of_parse_phandle(np, property, 0);
> + if (!syscon_np)
> + return ERR_PTR(-ENODEV);
> +
> + syscon = syscon_np->data;
> +
> + of_node_put(syscon_np);
> +
> + return syscon->regmap;
> +}
> +EXPORT_SYMBOL_GPL(syscon_early_regmap_lookup_by_phandle);
> +
> struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
> const char *property)
> {
> @@ -128,40 +149,110 @@ static int syscon_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> struct syscon *syscon;
> struct resource *res;
> - void __iomem *base;
>
> - syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
> + /* Early syscon init */
> + if (pdev->dev.of_node && pdev->dev.of_node->data) {
> + syscon = pdev->dev.of_node->data;
> + res = &syscon->res;
> + regmap_attach_dev(dev, syscon->regmap, &syscon_regmap_config);
> + } else {
> +
> + syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
> + if (!syscon)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res)
> + return -ENOENT;
> +
> + syscon->base = devm_ioremap(dev, res->start,
> + resource_size(res));
> + if (!syscon->base)
> + return -ENOMEM;
> +
> + syscon_regmap_config.max_register = res->end - res->start - 3;
> + syscon->regmap = devm_regmap_init_mmio(dev, syscon->base,
> + &syscon_regmap_config);
> + if (IS_ERR(syscon->regmap)) {
> + dev_err(dev, "regmap init failed\n");
> + return PTR_ERR(syscon->regmap);
> + }
> + }
> +
> + platform_set_drvdata(pdev, syscon);
> +
> + dev_info(dev, "regmap %pR registered\n", res);
> +
> + return 0;
> +}
> +
> +static const struct platform_device_id syscon_ids[] = {
> + { "syscon", },
> + { }
> +};
> +
> +static int syscon_remove(struct platform_device *pdev)
> +{
> + struct syscon *syscon = platform_get_drvdata(pdev);
> +
> + if (pdev->dev.of_node && pdev->dev.of_node->data) {
> + iounmap(syscon->base);
> + kfree(syscon);
> + }
> +
> + return 0;
> +}
> +
> +static int early_syscon_probe(struct device_node *np)
> +{
> + struct syscon *syscon;
> +
> + syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
> if (!syscon)
> return -ENOMEM;
>
> - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> - if (!res)
> - return -ENOENT;
> + if (of_address_to_resource(np, 0, &syscon->res))
> + return -EINVAL;
>
> - base = devm_ioremap(dev, res->start, resource_size(res));
> - if (!base)
> - return -ENOMEM;
> + syscon->base = ioremap(syscon->res.start, resource_size(&syscon->res));
> + if (!syscon->base) {
> + pr_err("%s: Unable to map I/O memory\n", __func__);
> + return PTR_ERR(syscon->base);
> + }
>
> - syscon_regmap_config.max_register = res->end - res->start - 3;
> - syscon->regmap = devm_regmap_init_mmio(dev, base,
> - &syscon_regmap_config);
> + syscon_regmap_config.max_register = syscon->res.end -
> + syscon->res.start - 3;
> + syscon->regmap = regmap_init_mmio(NULL, syscon->base,
> + &syscon_regmap_config);
> if (IS_ERR(syscon->regmap)) {
> - dev_err(dev, "regmap init failed\n");
> + pr_err("regmap init failed\n");
> return PTR_ERR(syscon->regmap);
> }
>
> - platform_set_drvdata(pdev, syscon);
> + np->data = syscon;
>
> - dev_info(dev, "regmap %pR registered\n", res);
> + of_node_put(np);
> +
> + pr_info("%s: regmap %pR registered\n", np->full_name, &syscon->res);
>
> return 0;
> }
>
> -static const struct platform_device_id syscon_ids[] = {
> - { "syscon", },
> - { }
> +static struct of_device_id of_syscon_ids[] = {
> + { .compatible = "syscon" },
> + {},
> };
>
> +void __init early_syscon_init(void)
> +{
> + struct device_node *np;
> +
> + for_each_matching_node_and_match(np, of_syscon_ids, NULL) {
> + if (!early_syscon_probe(np))
just
if (early_syscon_probe(np))
BUG();
here.
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 263 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140210/2a67d56a/attachment-0001.sig>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox