Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [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 21/26] ARM: omap: dma: get rid of errata global
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>

There's no need for this to be a global variable; move it into the
errata configuration function instead.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-omap1/dma.c | 4 ++--
 arch/arm/mach-omap2/dma.c | 5 ++---
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index b680db7a35d4..c979e3f88bbb 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -33,7 +33,6 @@
 #define OMAP1_DMA_BASE			(0xfffed800)
 #define OMAP1_LOGICAL_DMA_CH_COUNT	17
 
-static u32 errata;
 static u32 enable_1510_mode;
 
 static const struct omap_dma_reg reg_map[] = {
@@ -244,8 +243,9 @@ static void omap1_show_dma_caps(void)
 	return;
 }
 
-static u32 configure_dma_errata(void)
+static unsigned configure_dma_errata(void)
 {
+	unsigned errata = 0;
 
 	/*
 	 * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index e633b48a3fcb..244ff5012aed 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -35,8 +35,6 @@
 #include "omap_hwmod.h"
 #include "omap_device.h"
 
-static u32 errata;
-
 static struct omap_dma_dev_attr *d;
 
 static enum omap_reg_offsets dma_common_ch_end;
@@ -124,8 +122,9 @@ static void omap2_show_dma_caps(void)
 	return;
 }
 
-static u32 configure_dma_errata(void)
+static unsigned configure_dma_errata(void)
 {
+	unsigned errata = 0;
 
 	/*
 	 * Errata applicable for OMAP2430ES1.0 and all omap2420
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 22/26] ARM: omap: move dma channel allocation into plat-omap code
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>

This really needs to be there, because otherwise the plat-omap code can
kfree() this data structure, and then re-use the pointer later.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-omap1/dma.c | 17 ++---------------
 arch/arm/mach-omap2/dma.c |  7 -------
 arch/arm/plat-omap/dma.c  | 11 ++++++++---
 include/linux/omap-dma.h  |  1 -
 4 files changed, 10 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index c979e3f88bbb..d170f7d0a6ac 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -325,17 +325,6 @@ static int __init omap1_system_dma_init(void)
 	d->dev_caps		|= CLEAR_CSR_ON_READ;
 	d->dev_caps		|= IS_WORD_16;
 
-
-	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
-					(d->lch_count), GFP_KERNEL);
-	if (!d->chan) {
-		dev_err(&pdev->dev,
-			"%s: Memory allocation failed for d->chan!\n",
-			__func__);
-		ret = -ENOMEM;
-		goto exit_release_d;
-	}
-
 	if (cpu_is_omap15xx())
 		d->chan_count = 9;
 	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
@@ -359,14 +348,14 @@ static int __init omap1_system_dma_init(void)
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
-		goto exit_release_chan;
+		goto exit_release_d;
 	}
 
 	ret = platform_device_add(pdev);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
-		goto exit_release_chan;
+		goto exit_release_d;
 	}
 
 	dma_pdev = platform_device_register_full(&omap_dma_dev_info);
@@ -379,8 +368,6 @@ static int __init omap1_system_dma_init(void)
 
 exit_release_pdev:
 	platform_device_del(pdev);
-exit_release_chan:
-	kfree(d->chan);
 exit_release_d:
 	kfree(d);
 exit_release_p:
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 244ff5012aed..9f210d637354 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -251,13 +251,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 	}
 
 	d = oh->dev_attr;
-	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
-					(d->lch_count), GFP_KERNEL);
-
-	if (!d->chan) {
-		dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__);
-		return -ENOMEM;
-	}
 
 	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
 		d->dev_caps |= HS_CHANNELS_RESERVED;
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index d4d9a5e62152..5f5b975887fc 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -2030,9 +2030,16 @@ static int omap_system_dma_probe(struct platform_device *pdev)
 
 	dma_lch_count		= d->lch_count;
 	dma_chan_count		= dma_lch_count;
-	dma_chan		= d->chan;
 	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;
 
+	dma_chan = devm_kcalloc(&pdev->dev, dma_lch_count,
+				sizeof(struct omap_dma_lch), GFP_KERNEL);
+	if (!dma_chan) {
+		dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__);
+		return -ENOMEM;
+	}
+
+
 	if (dma_omap2plus()) {
 		dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
 						dma_lch_count, GFP_KERNEL);
@@ -2117,7 +2124,6 @@ static int omap_system_dma_probe(struct platform_device *pdev)
 	}
 
 exit_dma_lch_fail:
-	kfree(dma_chan);
 	return ret;
 }
 
@@ -2137,7 +2143,6 @@ static int omap_system_dma_remove(struct platform_device *pdev)
 			free_irq(dma_irq, (void *)(irq_rel + 1));
 		}
 	}
-	kfree(dma_chan);
 	return 0;
 }
 
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index 41328725721a..7813636a193d 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -268,7 +268,6 @@ struct omap_dma_dev_attr {
 	u32 dev_caps;
 	u16 lch_count;
 	u16 chan_count;
-	struct omap_dma_lch *chan;
 };
 
 enum {
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 23/26] ARM: omap: dma: get rid of 'p' allocation and clean up
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 omap_system_dma_plat_info structure is only seven words, it's not
worth the expense of kmalloc()'ing backing store for this only to
release it later.  Note that platform_device_add_data() copies the
data anyway.  Clean up the initialisation of this structure - we don't
even need code to initialise most of this structure.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-omap1/dma.c | 36 ++++++++++++++----------------------
 arch/arm/mach-omap2/dma.c | 34 +++++++++++++---------------------
 2 files changed, 27 insertions(+), 43 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index d170f7d0a6ac..a8c83ccc36fb 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -263,9 +263,17 @@ static const struct platform_device_info omap_dma_dev_info = {
 	.dma_mask = DMA_BIT_MASK(32),
 };
 
+static struct omap_system_dma_plat_info dma_plat_info __initdata = {
+	.show_dma_caps	= omap1_show_dma_caps,
+	.clear_lch_regs	= omap1_clear_lch_regs,
+	.clear_dma	= omap1_clear_dma,
+	.dma_write	= dma_write,
+	.dma_read	= dma_read,
+};
+
 static int __init omap1_system_dma_init(void)
 {
-	struct omap_system_dma_plat_info	*p;
+	struct omap_system_dma_plat_info	p;
 	struct omap_dma_dev_attr		*d;
 	struct platform_device			*pdev, *dma_pdev;
 	int ret;
@@ -291,20 +299,12 @@ static int __init omap1_system_dma_init(void)
 		goto exit_iounmap;
 	}
 
-	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
-	if (!p) {
-		dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
-			__func__, pdev->name);
-		ret = -ENOMEM;
-		goto exit_iounmap;
-	}
-
 	d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
 	if (!d) {
 		dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
 			__func__, pdev->name);
 		ret = -ENOMEM;
-		goto exit_release_p;
+		goto exit_iounmap;
 	}
 
 	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
@@ -334,17 +334,11 @@ static int __init omap1_system_dma_init(void)
 			d->chan_count = 9;
 	}
 
-	p->dma_attr = d;
-
-	p->show_dma_caps	= omap1_show_dma_caps;
-	p->clear_lch_regs	= omap1_clear_lch_regs;
-	p->clear_dma		= omap1_clear_dma;
-	p->dma_write		= dma_write;
-	p->dma_read		= dma_read;
-
-	p->errata = configure_dma_errata();
+	p = dma_plat_info;
+	p.dma_attr = d;
+	p.errata = configure_dma_errata();
 
-	ret = platform_device_add_data(pdev, p, sizeof(*p));
+	ret = platform_device_add_data(pdev, &p, sizeof(p));
 	if (ret) {
 		dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
 			__func__, pdev->name, pdev->id);
@@ -370,8 +364,6 @@ static int __init omap1_system_dma_init(void)
 	platform_device_del(pdev);
 exit_release_d:
 	kfree(d);
-exit_release_p:
-	kfree(p);
 exit_iounmap:
 	iounmap(dma_base);
 exit_device_put:
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 9f210d637354..6331fc4b4054 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -35,8 +35,6 @@
 #include "omap_hwmod.h"
 #include "omap_device.h"
 
-static struct omap_dma_dev_attr *d;
-
 static enum omap_reg_offsets dma_common_ch_end;
 
 static const struct omap_dma_reg reg_map[] = {
@@ -206,33 +204,27 @@ static unsigned configure_dma_errata(void)
 	return errata;
 }
 
+static struct omap_system_dma_plat_info dma_plat_info __initdata = {
+	.show_dma_caps	= omap2_show_dma_caps,
+	.clear_dma	= omap2_clear_dma,
+	.dma_write	= dma_write,
+	.dma_read	= dma_read,
+};
+
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
 	struct platform_device			*pdev;
-	struct omap_system_dma_plat_info	*p;
+	struct omap_system_dma_plat_info	p;
+	struct omap_dma_dev_attr		*d;
 	struct resource				*mem;
 	char					*name = "omap_dma_system";
 
-	p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
-	if (!p) {
-		pr_err("%s: Unable to allocate pdata for %s:%s\n",
-			__func__, name, oh->name);
-		return -ENOMEM;
-	}
-
-	p->dma_attr		= (struct omap_dma_dev_attr *)oh->dev_attr;
-	p->show_dma_caps	= omap2_show_dma_caps;
-	p->clear_dma		= omap2_clear_dma;
-	p->dma_write		= dma_write;
-	p->dma_read		= dma_read;
-
-	p->clear_lch_regs	= NULL;
-
-	p->errata		= configure_dma_errata();
+	p = dma_plat_info;
+	p.dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr;
+	p.errata = configure_dma_errata();
 
-	pdev = omap_device_build(name, 0, oh, p, sizeof(*p));
-	kfree(p);
+	pdev = omap_device_build(name, 0, oh, &p, sizeof(p));
 	if (IS_ERR(pdev)) {
 		pr_err("%s: Can't build omap_device for %s:%s.\n",
 			__func__, name, oh->name);
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 24/26] dmaengine: omap-dma: move register read/writes into omap-dma.c
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>

Export the DMA register information from the SoC specific data, such
that we can access the registers directly in omap-dma.c, mapping the
register region ourselves as well.

Rather than calculating the DMA channel register in its entirety for
each access, we pre-calculate an offset base address for the allocated
DMA channel and then just use the appropriate register offset.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mach-omap1/dma.c |  4 ++
 arch/arm/mach-omap2/dma.c | 18 ++++++---
 drivers/dma/omap-dma.c    | 96 ++++++++++++++++++++++++++++++++++++++++++-----
 include/linux/omap-dma.h  |  2 +
 4 files changed, 105 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index a8c83ccc36fb..4be601b638d7 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -261,9 +261,13 @@ static const struct platform_device_info omap_dma_dev_info = {
 	.name = "omap-dma-engine",
 	.id = -1,
 	.dma_mask = DMA_BIT_MASK(32),
+	.res = res,
+	.num_res = 1,
 };
 
 static struct omap_system_dma_plat_info dma_plat_info __initdata = {
+	.reg_map	= reg_map,
+	.channel_stride	= 0x40,
 	.show_dma_caps	= omap1_show_dma_caps,
 	.clear_lch_regs	= omap1_clear_lch_regs,
 	.clear_dma	= omap1_clear_dma,
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 6331fc4b4054..5689c88d986d 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -205,12 +205,20 @@ static unsigned configure_dma_errata(void)
 }
 
 static struct omap_system_dma_plat_info dma_plat_info __initdata = {
+	.reg_map	= reg_map,
+	.channel_stride	= 0x60,
 	.show_dma_caps	= omap2_show_dma_caps,
 	.clear_dma	= omap2_clear_dma,
 	.dma_write	= dma_write,
 	.dma_read	= dma_read,
 };
 
+static struct platform_device_info omap_dma_dev_info = {
+	.name = "omap-dma-engine",
+	.id = -1,
+	.dma_mask = DMA_BIT_MASK(32),
+};
+
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
@@ -231,11 +239,15 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 		return PTR_ERR(pdev);
 	}
 
+	omap_dma_dev_info.res = pdev->resource;
+	omap_dma_dev_info.num_res = pdev->num_resources;
+
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
 		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
 		return -EINVAL;
 	}
+
 	dma_base = ioremap(mem->start, resource_size(mem));
 	if (!dma_base) {
 		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
@@ -256,12 +268,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 	return 0;
 }
 
-static const struct platform_device_info omap_dma_dev_info = {
-	.name = "omap-dma-engine",
-	.id = -1,
-	.dma_mask = DMA_BIT_MASK(32),
-};
-
 static int __init omap2_system_dma_init(void)
 {
 	struct platform_device *pdev;
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 1e0018f36384..00f8e566cf12 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -27,13 +27,16 @@ struct omap_dmadev {
 	spinlock_t lock;
 	struct tasklet_struct task;
 	struct list_head pending;
+	void __iomem *base;
+	const struct omap_dma_reg *reg_map;
 	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;
+	void __iomem *channel_base;
+	const struct omap_dma_reg *reg_map;
 
 	struct dma_slave_config	cfg;
 	unsigned dma_sig;
@@ -170,24 +173,77 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)
 	kfree(container_of(vd, struct omap_desc, vd));
 }
 
+static void omap_dma_write(uint32_t val, unsigned type, void __iomem *addr)
+{
+	switch (type) {
+	case OMAP_DMA_REG_16BIT:
+		writew_relaxed(val, addr);
+		break;
+	case OMAP_DMA_REG_2X16BIT:
+		writew_relaxed(val, addr);
+		writew_relaxed(val >> 16, addr + 2);
+		break;
+	case OMAP_DMA_REG_32BIT:
+		writel_relaxed(val, addr);
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
+
+static unsigned omap_dma_read(unsigned type, void __iomem *addr)
+{
+	unsigned val;
+
+	switch (type) {
+	case OMAP_DMA_REG_16BIT:
+		val = readw_relaxed(addr);
+		break;
+	case OMAP_DMA_REG_2X16BIT:
+		val = readw_relaxed(addr);
+		val |= readw_relaxed(addr + 2) << 16;
+		break;
+	case OMAP_DMA_REG_32BIT:
+		val = readl_relaxed(addr);
+		break;
+	default:
+		WARN_ON(1);
+		val = 0;
+	}
+
+	return val;
+}
+
 static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val)
 {
-	od->plat->dma_write(val, reg, 0);
+	const struct omap_dma_reg *r = od->reg_map + reg;
+
+	WARN_ON(r->stride);
+
+	omap_dma_write(val, r->type, od->base + r->offset);
 }
 
 static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg)
 {
-	return od->plat->dma_read(reg, 0);
+	const struct omap_dma_reg *r = od->reg_map + reg;
+
+	WARN_ON(r->stride);
+
+	return omap_dma_read(r->type, od->base + r->offset);
 }
 
 static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val)
 {
-	c->plat->dma_write(val, reg, c->dma_ch);
+	const struct omap_dma_reg *r = c->reg_map + reg;
+
+	omap_dma_write(val, r->type, c->channel_base + r->offset);
 }
 
 static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg)
 {
-	return c->plat->dma_read(reg, c->dma_ch);
+	const struct omap_dma_reg *r = c->reg_map + reg;
+
+	return omap_dma_read(r->type, c->channel_base + r->offset);
 }
 
 static void omap_dma_clear_csr(struct omap_chan *c)
@@ -198,6 +254,12 @@ static void omap_dma_clear_csr(struct omap_chan *c)
 		omap_dma_chan_write(c, CSR, ~0);
 }
 
+static void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c,
+	unsigned lch)
+{
+	c->channel_base = od->base + od->plat->channel_stride * lch;
+}
+
 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);
@@ -400,18 +462,26 @@ static void omap_dma_sched(unsigned long data)
 
 static int omap_dma_alloc_chan_resources(struct dma_chan *chan)
 {
+	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
 	struct omap_chan *c = to_omap_dma_chan(chan);
+	int ret;
+
+	dev_dbg(od->ddev.dev, "allocating channel for %u\n", c->dma_sig);
 
-	dev_dbg(c->vc.chan.device->dev, "allocating channel for %u\n", c->dma_sig);
+	ret = omap_request_dma(c->dma_sig, "DMA engine", omap_dma_callback,
+			       c, &c->dma_ch);
 
-	return omap_request_dma(c->dma_sig, "DMA engine",
-		omap_dma_callback, c, &c->dma_ch);
+	if (ret >= 0)
+		omap_dma_assign(od, c, c->dma_ch);
+
+	return ret;
 }
 
 static void omap_dma_free_chan_resources(struct dma_chan *chan)
 {
 	struct omap_chan *c = to_omap_dma_chan(chan);
 
+	c->channel_base = NULL;
 	vchan_free_chan_resources(&c->vc);
 	omap_free_dma(c->dma_ch);
 
@@ -917,7 +987,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig)
 	if (!c)
 		return -ENOMEM;
 
-	c->plat = od->plat;
+	c->reg_map = od->reg_map;
 	c->dma_sig = dma_sig;
 	c->vc.desc_free = omap_dma_desc_free;
 	vchan_init(&c->vc, &od->ddev);
@@ -944,16 +1014,24 @@ static void omap_dma_free(struct omap_dmadev *od)
 static int omap_dma_probe(struct platform_device *pdev)
 {
 	struct omap_dmadev *od;
+	struct resource *res;
 	int rc, i;
 
 	od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
 	if (!od)
 		return -ENOMEM;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	od->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(od->base))
+		return PTR_ERR(od->base);
+
 	od->plat = omap_get_plat_info();
 	if (!od->plat)
 		return -EPROBE_DEFER;
 
+	od->reg_map = od->plat->reg_map;
+
 	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 7813636a193d..41a13e70f41f 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -285,6 +285,8 @@ struct omap_dma_reg {
 
 /* System DMA platform data structure */
 struct omap_system_dma_plat_info {
+	const struct omap_dma_reg *reg_map;
+	unsigned channel_stride;
 	struct omap_dma_dev_attr *dma_attr;
 	u32 errata;
 	void (*show_dma_caps)(void);
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 25/26] dmaengine: omap-dma: move IRQ handling to omap-dma
From: Russell King @ 2014-02-10 15:58 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 | 121 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 115 insertions(+), 6 deletions(-)

diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 00f8e566cf12..ec98e718de70 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -30,6 +30,10 @@ struct omap_dmadev {
 	void __iomem *base;
 	const struct omap_dma_reg *reg_map;
 	struct omap_system_dma_plat_info *plat;
+	bool legacy;
+	spinlock_t irq_lock;
+	uint32_t irq_enable_mask;
+	struct omap_chan *lch_map[32];
 };
 
 struct omap_chan {
@@ -254,10 +258,22 @@ static void omap_dma_clear_csr(struct omap_chan *c)
 		omap_dma_chan_write(c, CSR, ~0);
 }
 
+static unsigned omap_dma_get_csr(struct omap_chan *c)
+{
+	unsigned val = omap_dma_chan_read(c, CSR);
+
+	if (!dma_omap1())
+		omap_dma_chan_write(c, CSR, val);
+
+	return val;
+}
+
 static void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c,
 	unsigned lch)
 {
 	c->channel_base = od->base + od->plat->channel_stride * lch;
+
+	od->lch_map[lch] = c;
 }
 
 static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
@@ -460,32 +476,103 @@ static void omap_dma_sched(unsigned long data)
 	}
 }
 
+static irqreturn_t omap_dma_irq(int irq, void *devid)
+{
+	struct omap_dmadev *od = devid;
+	unsigned status, channel;
+
+	spin_lock(&od->irq_lock);
+
+	status = omap_dma_glbl_read(od, IRQSTATUS_L1);
+	status &= od->irq_enable_mask;
+	if (status == 0) {
+		spin_unlock(&od->irq_lock);
+		return IRQ_NONE;
+	}
+
+	while ((channel = ffs(status)) != 0) {
+		unsigned mask, csr;
+		struct omap_chan *c;
+
+		channel -= 1;
+		mask = BIT(channel);
+		status &= ~mask;
+
+		c = od->lch_map[channel];
+		if (c == NULL) {
+			/* This should never happen */
+			dev_err(od->ddev.dev, "invalid channel %u\n", channel);
+			continue;
+		}
+
+		csr = omap_dma_get_csr(c);
+		omap_dma_glbl_write(od, IRQSTATUS_L1, mask);
+
+		omap_dma_callback(channel, csr, c);
+	}
+
+	spin_unlock(&od->irq_lock);
+
+	return IRQ_HANDLED;
+}
+
 static int omap_dma_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
 	struct omap_chan *c = to_omap_dma_chan(chan);
 	int ret;
 
-	dev_dbg(od->ddev.dev, "allocating channel for %u\n", c->dma_sig);
+	if (od->legacy) {
+		ret = omap_request_dma(c->dma_sig, "DMA engine",
+				       omap_dma_callback, c, &c->dma_ch);
+	} else {
+		ret = omap_request_dma(c->dma_sig, "DMA engine", NULL, NULL,
+				       &c->dma_ch);
+	}
 
-	ret = omap_request_dma(c->dma_sig, "DMA engine", omap_dma_callback,
-			       c, &c->dma_ch);
+	dev_dbg(od->ddev.dev, "allocating channel %u for %u\n",
+		c->dma_ch, c->dma_sig);
 
-	if (ret >= 0)
+	if (ret >= 0) {
 		omap_dma_assign(od, c, c->dma_ch);
 
+		if (!od->legacy) {
+			unsigned val;
+
+			spin_lock_irq(&od->irq_lock);
+			val = BIT(c->dma_ch);
+			omap_dma_glbl_write(od, IRQSTATUS_L1, val);
+			od->irq_enable_mask |= val;
+			omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask);
+
+			val = omap_dma_glbl_read(od, IRQENABLE_L0);
+			val &= ~BIT(c->dma_ch);
+			omap_dma_glbl_write(od, IRQENABLE_L0, val);
+			spin_unlock_irq(&od->irq_lock);
+		}
+	}
+
 	return ret;
 }
 
 static void omap_dma_free_chan_resources(struct dma_chan *chan)
 {
+	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
 	struct omap_chan *c = to_omap_dma_chan(chan);
 
+	if (!od->legacy) {
+		spin_lock_irq(&od->irq_lock);
+		od->irq_enable_mask &= ~BIT(c->dma_ch);
+		omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask);
+		spin_unlock_irq(&od->irq_lock);
+	}
+
 	c->channel_base = NULL;
+	od->lch_map[c->dma_ch] = NULL;
 	vchan_free_chan_resources(&c->vc);
 	omap_free_dma(c->dma_ch);
 
-	dev_dbg(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig);
+	dev_dbg(od->ddev.dev, "freeing channel for %u\n", c->dma_sig);
 }
 
 static size_t omap_dma_sg_size(struct omap_sg *sg)
@@ -1015,7 +1102,7 @@ static int omap_dma_probe(struct platform_device *pdev)
 {
 	struct omap_dmadev *od;
 	struct resource *res;
-	int rc, i;
+	int rc, i, irq;
 
 	od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
 	if (!od)
@@ -1045,6 +1132,7 @@ static int omap_dma_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&od->ddev.channels);
 	INIT_LIST_HEAD(&od->pending);
 	spin_lock_init(&od->lock);
+	spin_lock_init(&od->irq_lock);
 
 	tasklet_init(&od->task, omap_dma_sched, (unsigned long)od);
 
@@ -1056,6 +1144,21 @@ static int omap_dma_probe(struct platform_device *pdev)
 		}
 	}
 
+	irq = platform_get_irq(pdev, 1);
+	if (irq <= 0) {
+		dev_info(&pdev->dev, "failed to get L1 IRQ: %d\n", irq);
+		od->legacy = true;
+	} else {
+		/* Disable all interrupts */
+		od->irq_enable_mask = 0;
+		omap_dma_glbl_write(od, IRQENABLE_L1, 0);
+
+		rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq,
+				      IRQF_SHARED, "omap-dma-engine", od);
+		if (rc)
+			return rc;
+	}
+
 	rc = dma_async_device_register(&od->ddev);
 	if (rc) {
 		pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n",
@@ -1092,6 +1195,12 @@ static int omap_dma_remove(struct platform_device *pdev)
 		of_dma_controller_free(pdev->dev.of_node);
 
 	dma_async_device_unregister(&od->ddev);
+
+	if (!od->legacy) {
+		/* Disable all interrupts */
+		omap_dma_glbl_write(od, IRQENABLE_L0, 0);
+	}
+
 	omap_dma_free(od);
 
 	return 0;
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 26/26] dmaengine: omap-dma: more consolidation of CCR register setup
From: Russell King @ 2014-02-10 15:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140210155531.GB26684@n2100.arm.linux.org.uk>

We can move the handling of the DMA synchronisation control out of the
prepare functions; this can be pre-calculated when the DMA channel has
been allocated, so we don't need to duplicate this in both prepare
functions.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/dma/omap-dma.c | 46 ++++++++++++++++++----------------------------
 1 file changed, 18 insertions(+), 28 deletions(-)

diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index ec98e718de70..64ceca2920b8 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -41,6 +41,7 @@ struct omap_chan {
 	struct list_head node;
 	void __iomem *channel_base;
 	const struct omap_dma_reg *reg_map;
+	uint32_t ccr;
 
 	struct dma_slave_config	cfg;
 	unsigned dma_sig;
@@ -552,6 +553,21 @@ static int omap_dma_alloc_chan_resources(struct dma_chan *chan)
 		}
 	}
 
+	if (dma_omap1()) {
+		if (__dma_omap16xx(od->plat->dma_attr)) {
+			c->ccr = CCR_OMAP31_DISABLE;
+			/* Duplicate what plat-omap/dma.c does */
+			c->ccr |= c->dma_ch + 1;
+		} else {
+			c->ccr = c->dma_sig & 0x1f;
+		}
+	} else {
+		c->ccr = c->dma_sig & 0x1f;
+		c->ccr |= (c->dma_sig & ~0x1f) << 14;
+	}
+	if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING)
+		c->ccr |= CCR_BUFFERING_DISABLE;
+
 	return ret;
 }
 
@@ -787,7 +803,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
 	d->dev_addr = dev_addr;
 	d->es = es;
 
-	d->ccr = CCR_SYNC_FRAME;
+	d->ccr = c->ccr | CCR_SYNC_FRAME;
 	if (dir == DMA_DEV_TO_MEM)
 		d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT;
 	else
@@ -797,14 +813,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
 	d->csdp = es;
 
 	if (dma_omap1()) {
-		if (__dma_omap16xx(od->plat->dma_attr)) {
-			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 |= CICR_TOUT_IE;
 
 		if (dir == DMA_DEV_TO_MEM)
@@ -812,16 +820,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
 		else
 			d->csdp |= CSDP_DST_PORT_TIPB | CSDP_SRC_PORT_EMIFF;
 	} else {
-		d->ccr |= (c->dma_sig & ~0x1f) << 14;
-		d->ccr |= c->dma_sig & 0x1f;
-
 		if (dir == DMA_DEV_TO_MEM)
 			d->ccr |= CCR_TRIGGER_SRC;
 
 		d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
 	}
-	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;
 
@@ -903,7 +906,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	d->sg[0].fn = buf_len / period_len;
 	d->sglen = 1;
 
-	d->ccr = 0;
+	d->ccr = c->ccr;
 	if (dir == DMA_DEV_TO_MEM)
 		d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT;
 	else
@@ -916,14 +919,6 @@ 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 |= 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 |= CICR_TOUT_IE;
 
 		if (dir == DMA_DEV_TO_MEM)
@@ -931,9 +926,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 		else
 			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 |= CCR_SYNC_PACKET;
 		else
@@ -946,8 +938,6 @@ 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;
 
 	if (__dma_omap15xx(od->plat->dma_attr))
 		d->ccr |= CCR_AUTO_INIT | CCR_REPEAT;
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH RFC v2 00/35] Second preview of imx-drm cleanup series
From: Jean-Francois Moine @ 2014-02-10 16:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140210151821.GY26684@n2100.arm.linux.org.uk>

On Mon, 10 Feb 2014 15:18:21 +0000
Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:

> Now, mind explaining what "v4l2 style device tree bindings" means?  I've
> no idea since I'm relatively new to DT.

Documentation/devicetree/bindings/media/video-interfaces.txt

For the Cubox, I have:

	tda998x: hdmi-encoder {
		compatible = "nxp,tda998x";
		...
		port {
			tda998x_0: endpoint at 0 {
				remote-endpoint = <&lcd0_0>;
			};
		};
	};

&lcd0 {
	status = "okay";
	...
	port {
		lcd0_0: endpoint at 0 {
			remote-endpoint = <&tda998x_0>;
		};
	};
};


-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

^ permalink raw reply

* [RFT][PATCH 00/12] change drivers power management to use dev_pm_ops
From: Shuah Khan @ 2014-02-10 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

Change drivers to register pm ops using dev_pm_ops instead of legacy pm_ops.
.pm hooks call existing legacy suspend and resume interfaces by passing in
the right pm state. Bus drivers suspend and resume routines call .pm driver
hooks if found.

Shuah Khan (12):
  arm: change locomo platform and bus power management to use
    dev_pm_ops
  arm: change sa1111 platform and bus power management to use
    dev_pm_ops
  arm: change scoop platform power management to use dev_pm_ops
  drivers/macintosh/adb: change platform power managemnet to use
    dev_pm_ops
  mmc: change au1xmmc platform power management to use dev_pm_ops
  mmc: change bfin_sdh platform power management to use dev_pm_ops
  isa: change isa bus power managemnet to use dev_pm_ops
  mmc: change cb710-mmc platform power management to use dev_pm_ops
  mmc: change msm_sdcc platform power management to use dev_pm_ops
  mmc: change tmio_mmc platform power management to use dev_pm_ops
  drivers/pcmcia: change ds driver power management to use dev_pm_ops
  drivers/s390/crypto: change ap_bus driver power management to use
    dev_pm_ops

 arch/arm/common/locomo.c     |   93 +++++++++++++++++++++++++++++++++++-------
 arch/arm/common/sa1111.c     |   88 +++++++++++++++++++++++++++++++--------
 arch/arm/common/scoop.c      |   44 ++++++++++++++++----
 drivers/base/isa.c           |   30 ++++++++++++--
 drivers/macintosh/adb.c      |   41 ++++++++++++++++---
 drivers/mmc/host/au1xmmc.c   |   43 +++++++++++++++----
 drivers/mmc/host/bfin_sdh.c  |   40 +++++++++++++++---
 drivers/mmc/host/cb710-mmc.c |   37 +++++++++++++++--
 drivers/mmc/host/msm_sdcc.c  |   42 +++++++++++++++----
 drivers/mmc/host/tmio_mmc.c  |   42 +++++++++++++++----
 drivers/pcmcia/ds.c          |   36 +++++++++++++---
 drivers/s390/crypto/ap_bus.c |   30 ++++++++++++--
 12 files changed, 481 insertions(+), 85 deletions(-)

-- 
1.7.10.4

^ permalink raw reply

* [RFT][PATCH 01/12] arm: change locomo platform and bus power management to use dev_pm_ops
From: Shuah Khan @ 2014-02-10 16:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1392040064.git.shuah.kh@samsung.com>

Change locomo platform and bus drivers to register pm ops using dev_pm_ops
instead of legacy pm_ops. .pm hooks call existing legacy suspend and resume
interfaces by passing in the right pm state.

Signed-off-by: Shuah Khan <shuah.kh@samsung.com>
---
 arch/arm/common/locomo.c |   93 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 78 insertions(+), 15 deletions(-)

diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index b55c362..a48effb 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -272,7 +272,7 @@ struct locomo_save_data {
 	u16	LCM_SPIMD;
 };
 
-static int locomo_suspend(struct platform_device *dev, pm_message_t state)
+static int __locomo_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct locomo *lchip = platform_get_drvdata(dev);
 	struct locomo_save_data *save;
@@ -316,7 +316,22 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state)
 	return 0;
 }
 
-static int locomo_resume(struct platform_device *dev)
+static int locomo_suspend(struct device *dev)
+{
+	 return __locomo_suspend(to_platform_device(dev), PMSG_SUSPEND);
+}
+
+static int locomo_freeze(struct device *dev)
+{
+	 return __locomo_suspend(to_platform_device(dev), PMSG_FREEZE);
+}
+
+static int locomo_poweroff(struct device *dev)
+{
+	 return __locomo_suspend(to_platform_device(dev), PMSG_HIBERNATE);
+}
+
+static int __locomo_resume(struct platform_device *dev)
 {
 	struct locomo *lchip = platform_get_drvdata(dev);
 	struct locomo_save_data *save;
@@ -351,6 +366,11 @@ static int locomo_resume(struct platform_device *dev)
 
 	return 0;
 }
+
+static int locomo_resume(struct device *dev)
+{
+	 return __locomo_resume(to_platform_device(dev));
+}
 #endif
 
 
@@ -510,6 +530,18 @@ static int locomo_remove(struct platform_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static const struct dev_pm_ops locomo_dev_pm_ops = {
+	.suspend = locomo_suspend,
+	.resume = locomo_resume,
+	/* Hibernate hooks */
+	.freeze = locomo_freeze,
+	.thaw = locomo_resume,
+	.poweroff = locomo_poweroff,
+	.restore = locomo_resume,
+};
+#endif
+
 /*
  *	Not sure if this should be on the system bus or not yet.
  *	We really want some way to register a system device at
@@ -519,12 +551,11 @@ static int locomo_remove(struct platform_device *dev)
 static struct platform_driver locomo_device_driver = {
 	.probe		= locomo_probe,
 	.remove		= locomo_remove,
-#ifdef CONFIG_PM
-	.suspend	= locomo_suspend,
-	.resume		= locomo_resume,
-#endif
 	.driver		= {
 		.name	= "locomo",
+#ifdef CONFIG_PM
+		.pm	= &locomo_dev_pm_ops,
+#endif
 	},
 };
 
@@ -826,26 +857,45 @@ static int locomo_match(struct device *_dev, struct device_driver *_drv)
 	return dev->devid == drv->devid;
 }
 
-static int locomo_bus_suspend(struct device *dev, pm_message_t state)
+static int __locomo_bus_suspend(struct device *dev, pm_message_t state)
 {
 	struct locomo_dev *ldev = LOCOMO_DEV(dev);
 	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
-	int ret = 0;
+
+	if (drv && drv->drv.pm && drv->drv.pm->suspend)
+		return  drv->drv.pm->suspend(dev);
 
 	if (drv && drv->suspend)
-		ret = drv->suspend(ldev, state);
-	return ret;
+		return	drv->suspend(ldev, state);
+	return 0;
+}
+
+static int locomo_bus_suspend(struct device *dev)
+{
+	return	__locomo_bus_suspend(dev, PMSG_SUSPEND);
+}
+
+static int locomo_bus_freeze(struct device *dev)
+{
+	return	__locomo_bus_suspend(dev, PMSG_FREEZE);
+}
+
+static int locomo_bus_poweroff(struct device *dev)
+{
+	return	__locomo_bus_suspend(dev, PMSG_HIBERNATE);
 }
 
 static int locomo_bus_resume(struct device *dev)
 {
 	struct locomo_dev *ldev = LOCOMO_DEV(dev);
 	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
-	int ret = 0;
+
+	if (drv && drv->drv.pm && drv->drv.pm->resume)
+		return	drv->drv.pm->resume(dev);
 
 	if (drv && drv->resume)
-		ret = drv->resume(ldev);
-	return ret;
+		return	drv->resume(ldev);
+	return 0;
 }
 
 static int locomo_bus_probe(struct device *dev)
@@ -870,13 +920,26 @@ static int locomo_bus_remove(struct device *dev)
 	return ret;
 }
 
+#ifdef CONFIG_PM
+static const struct dev_pm_ops locomo_bus_dev_pm_ops = {
+	.suspend = locomo_bus_suspend,
+	.resume = locomo_bus_resume,
+	/* Hibernate hooks */
+	.freeze = locomo_bus_freeze,
+	.thaw = locomo_bus_resume,
+	.poweroff = locomo_bus_poweroff,
+	.restore = locomo_bus_resume,
+};
+#endif
+
 struct bus_type locomo_bus_type = {
 	.name		= "locomo-bus",
 	.match		= locomo_match,
 	.probe		= locomo_bus_probe,
 	.remove		= locomo_bus_remove,
-	.suspend	= locomo_bus_suspend,
-	.resume		= locomo_bus_resume,
+#ifdef CONFIG_PM
+	.pm		= &locomo_bus_dev_pm_ops,
+#endif
 };
 
 int locomo_driver_register(struct locomo_driver *driver)
-- 
1.7.10.4

^ permalink raw reply related

* [RFT][PATCH 02/12] arm: change sa1111 platform and bus power management to use dev_pm_ops
From: Shuah Khan @ 2014-02-10 16:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1392040064.git.shuah.kh@samsung.com>

Change sa1111 platform and bus drivers to register pm ops using dev_pm_ops
instead of legacy pm_ops. .pm hooks call existing legacy suspend and resume
interfaces by passing in the right pm state.

Signed-off-by: Shuah Khan <shuah.kh@samsung.com>
---
 arch/arm/common/sa1111.c |   88 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 72 insertions(+), 16 deletions(-)

diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index e57d7e5..db017b2 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -872,7 +872,7 @@ struct sa1111_save_data {
 
 #ifdef CONFIG_PM
 
-static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
+static int __sa1111_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct sa1111 *sachip = platform_get_drvdata(dev);
 	struct sa1111_save_data *save;
@@ -928,6 +928,21 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
 	return 0;
 }
 
+static int sa1111_suspend(struct device *dev)
+{
+	return __sa1111_suspend(to_platform_device(dev), PMSG_SUSPEND);
+}
+
+static int sa1111_freeze(struct device *dev)
+{
+	return __sa1111_suspend(to_platform_device(dev), PMSG_FREEZE);
+}
+
+static int sa1111_poweroff(struct device *dev)
+{
+	return __sa1111_suspend(to_platform_device(dev), PMSG_HIBERNATE);
+}
+
 /*
  *	sa1111_resume - Restore the SA1111 device state.
  *	@dev: device to restore
@@ -937,7 +952,7 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
  *	restored by their respective drivers, and must be called
  *	via LDM after this function.
  */
-static int sa1111_resume(struct platform_device *dev)
+static int __sa1111_resume(struct platform_device *dev)
 {
 	struct sa1111 *sachip = platform_get_drvdata(dev);
 	struct sa1111_save_data *save;
@@ -1005,9 +1020,10 @@ static int sa1111_resume(struct platform_device *dev)
 	return 0;
 }
 
-#else
-#define sa1111_suspend NULL
-#define sa1111_resume  NULL
+static int sa1111_resume(struct device *dev)
+{
+	return __sa1111_resume(to_platform_device(dev));
+}
 #endif
 
 static int sa1111_probe(struct platform_device *pdev)
@@ -1041,6 +1057,18 @@ static int sa1111_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static const struct dev_pm_ops sa1111_dev_pm_ops = {
+	.suspend = sa1111_suspend,
+	.resume = sa1111_resume,
+	/* Hibernate hooks */
+	.freeze = sa1111_freeze,
+	.thaw = sa1111_resume,
+	.poweroff = sa1111_poweroff,
+	.restore = sa1111_resume,
+};
+#endif
+
 /*
  *	Not sure if this should be on the system bus or not yet.
  *	We really want some way to register a system device at
@@ -1053,11 +1081,12 @@ static int sa1111_remove(struct platform_device *pdev)
 static struct platform_driver sa1111_device_driver = {
 	.probe		= sa1111_probe,
 	.remove		= sa1111_remove,
-	.suspend	= sa1111_suspend,
-	.resume		= sa1111_resume,
 	.driver		= {
 		.name	= "sa1111",
 		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &sa1111_dev_pm_ops,
+#endif
 	},
 };
 
@@ -1297,26 +1326,44 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv)
 	return dev->devid & drv->devid;
 }
 
-static int sa1111_bus_suspend(struct device *dev, pm_message_t state)
+static int __sa1111_bus_suspend(struct device *dev, pm_message_t state)
 {
 	struct sa1111_dev *sadev = SA1111_DEV(dev);
 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
-	int ret = 0;
+
+	if (drv && drv->drv.pm && drv->drv.pm->suspend)
+		return  drv->drv.pm->suspend(dev);
 
 	if (drv && drv->suspend)
-		ret = drv->suspend(sadev, state);
-	return ret;
+		return drv->suspend(sadev, state);
+	return 0;
+}
+
+static int sa1111_bus_suspend(struct device *dev)
+{
+	return __sa1111_bus_suspend(dev, PMSG_SUSPEND);
+}
+
+static int sa1111_bus_freeze(struct device *dev)
+{
+	return __sa1111_bus_suspend(dev, PMSG_FREEZE);
+}
+
+static int sa1111_bus_poweroff(struct device *dev)
+{
+	return __sa1111_bus_suspend(dev, PMSG_HIBERNATE);
 }
 
 static int sa1111_bus_resume(struct device *dev)
 {
 	struct sa1111_dev *sadev = SA1111_DEV(dev);
 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
-	int ret = 0;
 
+	if (drv && drv->drv.pm && drv->drv.pm->resume)
+		return  drv->drv.pm->resume(dev);
 	if (drv && drv->resume)
-		ret = drv->resume(sadev);
-	return ret;
+		return drv->resume(sadev);
+	return 0;
 }
 
 static void sa1111_bus_shutdown(struct device *dev)
@@ -1349,14 +1396,23 @@ static int sa1111_bus_remove(struct device *dev)
 	return ret;
 }
 
+static const struct dev_pm_ops sa1111_bus_dev_pm_ops = {
+	.suspend = sa1111_bus_suspend,
+	.resume = sa1111_bus_resume,
+	/* Hibernate hooks */
+	.freeze = sa1111_bus_freeze,
+	.thaw = sa1111_bus_resume,
+	.poweroff = sa1111_bus_poweroff,
+	.restore = sa1111_bus_resume,
+};
+
 struct bus_type sa1111_bus_type = {
 	.name		= "sa1111-rab",
 	.match		= sa1111_match,
 	.probe		= sa1111_bus_probe,
 	.remove		= sa1111_bus_remove,
-	.suspend	= sa1111_bus_suspend,
-	.resume		= sa1111_bus_resume,
 	.shutdown	= sa1111_bus_shutdown,
+	.pm		= &sa1111_bus_dev_pm_ops,
 };
 EXPORT_SYMBOL(sa1111_bus_type);
 
-- 
1.7.10.4

^ permalink raw reply related

* [RFT][PATCH 03/12] arm: change scoop platform power management to use dev_pm_ops
From: Shuah Khan @ 2014-02-10 16:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1392040064.git.shuah.kh@samsung.com>

Change scoop platform driver to register pm ops using dev_pm_ops instead of
legacy pm_ops. .pm hooks call existing legacy suspend and resume interfaces
by passing in the right pm state.

Signed-off-by: Shuah Khan <shuah.kh@samsung.com>
---
 arch/arm/common/scoop.c |   44 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 37 insertions(+), 7 deletions(-)

diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index a5c3dc3..260a60b 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -151,7 +151,7 @@ static void check_scoop_reg(struct scoop_dev *sdev)
 		iowrite16(0x0101, sdev->base + SCOOP_MCR);
 }
 
-static int scoop_suspend(struct platform_device *dev, pm_message_t state)
+static int __scoop_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct scoop_dev *sdev = platform_get_drvdata(dev);
 
@@ -162,7 +162,22 @@ static int scoop_suspend(struct platform_device *dev, pm_message_t state)
 	return 0;
 }
 
-static int scoop_resume(struct platform_device *dev)
+static int scoop_suspend(struct device *dev)
+{
+	return __scoop_suspend(to_platform_device(dev), PMSG_SUSPEND);
+}
+
+static int scoop_freeze(struct device *dev)
+{
+	return __scoop_suspend(to_platform_device(dev), PMSG_FREEZE);
+}
+
+static int scoop_poweroff(struct device *dev)
+{
+	return __scoop_suspend(to_platform_device(dev), PMSG_HIBERNATE);
+}
+
+static int __scoop_resume(struct platform_device *dev)
 {
 	struct scoop_dev *sdev = platform_get_drvdata(dev);
 
@@ -171,9 +186,11 @@ static int scoop_resume(struct platform_device *dev)
 
 	return 0;
 }
-#else
-#define scoop_suspend	NULL
-#define scoop_resume	NULL
+
+static int scoop_resume(struct device *dev)
+{
+	return __scoop_resume(to_platform_device(dev));
+}
 #endif
 
 static int scoop_probe(struct platform_device *pdev)
@@ -266,13 +283,26 @@ static int scoop_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static const struct dev_pm_ops scoop_dev_pm_ops = {
+	.suspend = scoop_suspend,
+	.resume = scoop_resume,
+	/* Hibernate hooks */
+	.freeze = scoop_freeze,
+	.thaw = scoop_resume,
+	.poweroff = scoop_poweroff,
+	.restore = scoop_resume,
+};
+#endif
+
 static struct platform_driver scoop_driver = {
 	.probe		= scoop_probe,
 	.remove		= scoop_remove,
-	.suspend	= scoop_suspend,
-	.resume		= scoop_resume,
 	.driver		= {
 		.name	= "sharp-scoop",
+#ifdef CONFIG_PM
+		.pm	= &scoop_dev_pm_ops,
+#endif
 	},
 };
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v4 2/2] memory: ti-aemif: add bindings for AEMIF driver
From: Santosh Shilimkar @ 2014-02-10 16:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391629574-18955-3-git-send-email-ivan.khoronzhuk@ti.com>

Kumar,

On Wednesday 05 February 2014 02:46 PM, Ivan Khoronzhuk wrote:
> Add bindings for TI Async External Memory Interface (AEMIF) controller.
> 
> The Async External Memory Interface (EMIF16/AEMIF) controller is intended to
> provide a glue-less interface to a variety of asynchronous memory devices like
> ASRA M, NOR and NAND memory. A total of 256M bytes of any of these memories
> can be accessed via 4 chip selects with 64M byte access per chip select.
> 
> We are not encoding CS number in reg property, it's memory partition number.
> The CS number is encoded for Davinci NAND node using standalone property
> "ti,davinci-chipselect" and we need to provide two memory ranges to it,
> as result we can't encode CS number in "reg" for AEMIF child devices
> (NAND/NOR/etc), as it will break bindings compatibility.
> 
> In this patch, NAND node is used just as an example of child node.
> 
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
> ---
Can you please have a look at the binding which we discussed in previous
versions ? I want to queue these for 3.15 via Greg's tree but need
your ack on DT part at least.

>  .../bindings/memory-controllers/ti-aemif.txt       | 210 +++++++++++++++++++++
>  1 file changed, 210 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
> 
> diff --git a/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt b/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
> new file mode 100644
> index 0000000..d1466dc
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
> @@ -0,0 +1,210 @@
> +* Device tree bindings for Texas instruments AEMIF controller
> +
> +The Async External Memory Interface (EMIF16/AEMIF) controller is intended to
> +provide a glue-less interface to a variety of asynchronous memory devices like
> +ASRA M, NOR and NAND memory. A total of 256M bytes of any of these memories
> +can be accessed at any given time via four chip selects with 64M byte access
> +per chip select. Synchronous memories such as DDR1 SD RAM, SDR SDRAM
> +and Mobile SDR are not supported.
> +
> +Documentation:
> +Davinci DM646x - http://www.ti.com/lit/ug/sprueq7c/sprueq7c.pdf
> +OMAP-L138 (DA850) - http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf
> +Kestone - http://www.ti.com/lit/ug/sprugz3a/sprugz3a.pdf
> +
> +Required properties:
> +
> +- compatible:		"ti,davinci-aemif"
> +			"ti,keystone-aemif"
> +			"ti,da850-aemif"
> +
> +- reg:			contains offset/length value for AEMIF control registers
> +			space.
> +
> +- #address-cells:	Must be 2. The partition number has to be encoded in the
> +			first address cell and it may accept values 0..N-1
> +			(N - total number of partitions). It's recommended to
> +			assign N-1 number for the control partition. The second
> +			cell is the offset into the partition.
> +
> +- #size-cells:		Must be set to 1.
> +
> +- ranges:		Contains memory regions. There are two types of
> +			ranges/partitions:
> +			- CS-specific partition/range. If continuous, must be
> +			set up to reflect the memory layout for 4 chipselects,
> +			if not then additional range/partition can be added and
> +			child device can select the proper one.
> +			- control partition which is common for all CS
> +			interfaces.
> +
> +- clocks:		the clock feeding the controller clock. Required only
> +			if clock tree data present in device tree.
> +			See clock-bindings.txt
> +
> +- clock-names:		clock name. It has to be "aemif". Required only if clock
> +			tree data present in device tree, in another case don't
> +			use it.
> +			See clock-bindings.txt
> +
> +- clock-ranges:		Empty property indicating that child nodes can inherit
> +			named clocks. Required only if clock tree data present
> +			in device tree.
> +			See clock-bindings.txt
> +
> +
> +Child chip-select (cs) nodes contain the memory devices nodes connected to
> +such as NOR (e.g. cfi-flash) and NAND (ti,davinci-nand, see davinci-nand.txt).
> +There might be board specific devices like FPGAs.
> +
> +Required child cs node properties:
> +
> +- #address-cells:	Must be 2.
> +
> +- #size-cells:		Must be 1.
> +
> +- ranges:		Empty property indicating that child nodes can inherit
> +			memory layout.
> +
> +- clock-ranges:		Empty property indicating that child nodes can inherit
> +			named clocks. Required only if clock tree data present
> +			in device tree.
> +
> +- ti,cs-chipselect:	number of chipselect. Indicates on the aemif driver
> +			which chipselect is used for accessing the memory. For
> +			compatibles "ti,davinci-aemif" and "ti,keystone-aemif"
> +			it can be in range [0-3]. For compatible
> +			"ti,da850-aemif" range is [2-5].
> +
> +Optional child cs node properties:
> +
> +- ti,bus-width:			width of the asynchronous device's data bus
> +				8 or 16 if not preset 8
> +
> +- ti,cs-ss:		enable/disable select strobe mode
> +				In select strobe mode chip select behaves as
> +				the strobe and is active only during the strobe
> +				period. If present then enable.
> +
> +- ti,cs-ew:		enable/disable extended wait mode
> +				if set, the controller monitors the EMIFWAIT pin
> +				mapped to that chip select to determine if the
> +				device wants to extend the strobe period. If
> +				present then enable.
> +
> +- ti,cs-ta:		minimum turn around time, ns
> +				Time between the end of one asynchronous memory
> +				access and the start of another asynchronous
> +				memory access. This delay is not incurred
> +				between a read followed by read or a write
> +				followed by a write to same chip select.
> +
> +- ti,cs-rsetup:		read setup width, ns
> +				Time between the beginning of a memory cycle
> +				and the activation of read strobe.
> +				Minimum value is 1 (0 treated as 1).
> +
> +- ti,cs-rstobe:		read strobe width, ns
> +				Time between the activation and deactivation of
> +				the read strobe.
> +				Minimum value is 1 (0 treated as 1).
> +
> +- ti,cs-rhold:		read hold width, ns
> +				Time between the deactivation of the read
> +				strobe and the end of the cycle (which may be
> +				either an address change or the deactivation of
> +				the chip select signal.
> +				Minimum value is 1 (0 treated as 1).
> +
> +- ti,cs-wsetup:		write setup width, ns
> +				Time between the beginning of a memory cycle
> +				and the activation of write strobe.
> +				Minimum value is 1 (0 treated as 1).
> +
> +- ti,cs-wstrobe:	write strobe width, ns
> +				Time between the activation and deactivation of
> +				the write strobe.
> +				Minimum value is 1 (0 treated as 1).
> +
> +- ti,cs-whold:		write hold width, ns
> +				Time between the deactivation of the write
> +				strobe and the end of the cycle (which may be
> +				either an address change or the deactivation of
> +				the chip select signal.
> +				Minimum value is 1 (0 treated as 1).
> +
> +If any of the above parameters are absent, current parameter value will be taken
> +from the corresponding HW reg.
> +
> +Example for aemif, davinci nand and nor flash chip select shown below.
> +
> +memory-controller at 21000A00 {
> +	compatible = "ti,davinci-aemif";
> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	clocks = <&clkaemif 0>;
> +	clock-names = "aemif";
> +	clock-ranges;
> +	reg = <0x2100A00 0x00000100>;
> +	ranges = <0 0 0x70000000 0x10000000
> +		  1 0 0x21000A00 0x0000100>;
> +		  /*
> +		   * Partition0: CS-specific memory range which is
> +		   * implemented as continuous physical memory region
> +		   * Partition1: control memory range
> +		   */
> +
> +	nand:cs2 {
> +		#address-cells = <2>;
> +		#size-cells = <1>;
> +		clock-ranges;
> +		ranges;
> +
> +		ti,cs-chipselect = <2>;
> +		/* all timings in nanoseconds */
> +		ti,cs-ta = <0>;
> +		ti,cs-rhold = <7>;
> +		ti,cs-rstrobe = <42>;
> +		ti,cs-rsetup = <14>;
> +		ti,cs-whold = <7>;
> +		ti,cs-wstrobe = <42>;
> +		ti,cs-wsetup = <14>;
> +
> +		nand at 0,0x8000000 {
> +			compatible = "ti,davinci-nand";
> +			reg = <0 0x8000000 0x4000000
> +			       1 0x0000000 0x0000100>;
> +			/*
> +			 * Partition0, offset 0x8000000, size 0x4000000
> +			 * Partition1, offset 0x0000000, size 0x0000100
> +			 */
> +
> +			.. see davinci-nand.txt
> +		};
> +	};
> +
> +	nor:cs0 {
> +		#address-cells = <2>;
> +		#size-cells = <1>;
> +		clock-ranges;
> +		ranges;
> +
> +		ti,cs-chipselect = <0>;
> +		/* all timings in nanoseconds */
> +		ti,cs-ta = <0>;
> +		ti,cs-rhold = <8>;
> +		ti,cs-rstrobe = <40>;
> +		ti,cs-rsetup = <14>;
> +		ti,cs-whold = <7>;
> +		ti,cs-wstrobe = <40>;
> +		ti,cs-wsetup = <14>;
> +		ti,cs-asize = <1>;
> +
> +		flash at 0,0x0000000 {
> +			compatible = "cfi-flash";
> +			reg = <0 0x0000000 0x4000000>;
> +
> +			...
> +		};
> +	};
> +};
> 

^ permalink raw reply

* [PATCH v2 2/5] irqchip: gic: use writel instead of dsb + writel_relaxed
From: Catalin Marinas @ 2014-02-10 16:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392042159-11603-2-git-send-email-will.deacon@arm.com>

On Mon, Feb 10, 2014 at 02:22:36PM +0000, Will Deacon wrote:
> When sending an SGI to another CPU, we require a DSB to ensure that
> any pending stores to normal memory are made visible to the recipient
> before the interrupt arrives.
> 
> Rather than use a vanilla dsb() (which will soon cause an assembly error
> on arm64) before the writel_relaxed, we can instead use dsb(ishst),
> since we just need to ensure that any pending normal writes are visible
> within the inner-shareable domain before we poke the GIC.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
> 
> v1 => v2: Use dsb ishst instead of writel (which requires an L2 sync)
>           since the sync should already have been executed by the caller
> 	  if required. We *might* be able to relax this further to a dmb
> 	  but Catalin and I haven't got to the bottom of that yet.

In the meantime,

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH v2 1/5] arm64: barriers: make use of barrier options with explicit barriers
From: Catalin Marinas @ 2014-02-10 16:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392042159-11603-1-git-send-email-will.deacon@arm.com>

On Mon, Feb 10, 2014 at 02:22:35PM +0000, Will Deacon wrote:
> When calling our low-level barrier macros directly, we can often suffice
> with more relaxed behaviour than the default "all accesses, full system"
> option.
> 
> This patch updates the users of dsb() to specify the option which they
> actually require.
> 
> Signed-off-by: Will Deacon <will.deacon@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH 1/4] arm64: topology: Implement basic CPU topology support
From: Catalin Marinas @ 2014-02-10 16:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392037324-5069-1-git-send-email-broonie@kernel.org>

On Mon, Feb 10, 2014 at 01:02:01PM +0000, Mark Brown wrote:
> +static void update_siblings_masks(unsigned int cpuid)
> +{
> +	struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
> +	int cpu;
> +
> +	/* update core and thread sibling masks */
> +	for_each_possible_cpu(cpu) {
> +		cpu_topo = &cpu_topology[cpu];
> +
> +		if (cpuid_topo->cluster_id != cpu_topo->cluster_id)
> +			continue;
> +
> +		cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
> +		if (cpu != cpuid)
> +			cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
> +
> +		if (cpuid_topo->core_id != cpu_topo->core_id)
> +			continue;
> +
> +		cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
> +		if (cpu != cpuid)
> +			cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
> +	}
> +	smp_wmb();

I now noticed there are a couple of smp_wmb() calls in this patch. What
are they for?

-- 
Catalin

^ permalink raw reply

* [PATCH] pinctrl: sunxi: use chained_irq_{enter, exit} for GIC compatibility
From: Chen-Yu Tsai @ 2014-02-10 16:22 UTC (permalink / raw)
  To: linux-arm-kernel

On tha Allwinner A20 SoC, the external interrupts on the pin controller
device are connected to the GIC. Without chained_irq_{enter, exit},
external GPIO interrupts, such as used by mmc core card detect, cause
the system to hang.

Cc: stable at vger.kernel.org
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---

This issue was first encountered during my attempt to get out-of-band
interrupts for WiFi on the Cubietruck working. With David's new series
of sunci-mci using mmc slot-gpio for (GPIO interrupt based) card
detection, removing the SD card also causes my Cubietruck to hang. This
problem should extend to all Allwinner A20 based boards.

With this fix, the system no longer hangs when I remove or insert the
SD card. /proc/interrupts show that the interrupt has correctly fired.
However the system still does not detect card removal/insertion. I
believe this is another unrelated issue.

 drivers/pinctrl/pinctrl-sunxi.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 9ccf681..787f352 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -665,6 +666,7 @@ static struct irq_chip sunxi_pinctrl_irq_chip = {
 
 static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_get_chip(irq);
 	struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
 	const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
 
@@ -674,10 +676,12 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
 	if (reg) {
 		int irqoffset;
 
+		chained_irq_enter(chip, desc);
 		for_each_set_bit(irqoffset, &reg, SUNXI_IRQ_NUMBER) {
 			int pin_irq = irq_find_mapping(pctl->domain, irqoffset);
 			generic_handle_irq(pin_irq);
 		}
+		chained_irq_exit(chip, desc);
 	}
 }
 
-- 
1.9.rc1

^ permalink raw reply related

* [RFC PATCH 2/3] staging: imx-drm-core: Use graph to find connection between crtc and encoder
From: Russell King - ARM Linux @ 2014-02-10 16:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389019922-31992-3-git-send-email-p.zabel@pengutronix.de>

On Mon, Jan 06, 2014 at 03:52:01PM +0100, Philipp Zabel wrote:
> @@ -438,24 +453,21 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
>  	struct drm_encoder *encoder, struct device_node *np)
>  {
>  	struct imx_drm_device *imxdrm = drm->dev_private;
> +	struct device_node *ep, *last_ep = NULL;
>  	uint32_t crtc_mask = 0;
>  	int i, ret = 0;
>  
>  	for (i = 0; !ret; i++) {
> -		struct of_phandle_args args;
>  		uint32_t mask;
> -		int id;
>  
> -		ret = of_parse_phandle_with_args(np, "crtcs", "#crtc-cells", i,
> -						 &args);
> -		if (ret == -ENOENT)
> +		ep = v4l2_of_get_next_endpoint(np, last_ep);
> +		if (last_ep)
> +			of_node_put(last_ep);
> +		if (!ep)
>  			break;
> -		if (ret < 0)
> -			return ret;
>  
> -		id = args.args_count > 0 ? args.args[0] : 0;
> -		mask = imx_drm_find_crtc_mask(imxdrm, args.np, id);
> -		of_node_put(args.np);
> +		/* CSI */
> +		mask = imx_drm_find_crtc_mask(imxdrm, ep);
>  
>  		/*
>  		 * If we failed to find the CRTC(s) which this encoder is
> @@ -463,12 +475,20 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
>  		 * not been registered yet.  Defer probing, and hope that
>  		 * the required CRTC is added later.
>  		 */
> -		if (mask == 0)
> +		if (mask == 0) {
> +			of_node_put(ep);
>  			return -EPROBE_DEFER;
> +		}
>  
>  		crtc_mask |= mask;
> +		last_ep = ep;
>  	}
>  
> +	if (ep)
> +		of_node_put(ep);

Why is this loop soo complicated?  Why do you need to mess around with
this "last_ep" stuff - you don't actually end up using it.

The loop reduces down to this without comments:

 	for (i = 0; !ret; i++) {
 		uint32_t mask;

		ep = v4l2_of_get_next_endpoint(np, last_ep);
		if (!ep)
			break;

		/* CSI */
		mask = imx_drm_find_crtc_mask(imxdrm, ep);
		of_node_put(ep);

		if (mask == 0)
			return -EPROBE_DEFER;

		crtc_mask |= mask;
	}

Now, here's the big question: why do we want to use v4l2_* here?  We
may want to use this functionality, but if this functionality is going
to be used outside of v4l2, it needs to become something generic, not
v4l2 specific.

Let's think about this for a moment... if we want to build imx-drm into
the kernel, can we do it with modular videodev, or with videodev
completely unconfigured.  We may wish to do this because we have no
videodev requirement on a platform.  Should the build fail because the
v4l2 function isn't there?

So, before we can change this, I think we first need to get agreement
from Mauro to move this function out of V4L2, so that it can be
available independently of V4L2.

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

* [RFC PATCH] ARM: Add imprecise abort enable/disable macro
From: Dave Martin @ 2014-02-10 16:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140210151934.GZ26684@n2100.arm.linux.org.uk>

On Mon, Feb 10, 2014 at 03:19:34PM +0000, Russell King - ARM Linux wrote:
> On Mon, Feb 10, 2014 at 02:42:28PM +0000, Dave Martin wrote:
> > Should we require CPSR.A to me masked in Booting, for all CPUs that have
> > it?
> 
> If it's not masked at boot, then there can't be an imprecise exception
> pending.

Couldn't there still be a dangling abort condition triggered by the
bootloader, which which doesn't raise the abort pin until after we
entered the kernel?

> That's unlike interrupts, where a device could trigger an interrupt at
> any moment (eg, a timer expiring.)


List as with interrupts, there's no way to drain or cancel pending aborts
that aren't asserted yet, but whose cause conditions are already
established.

It's possible that Strongly-Ordered memory is sufficient to
guarantee that any D-side abort becomes synchronous in some
implementations but I don't think the arhitecture guarantees it.

It certainly won't be guaranteed for any other memory type.


For these reasons, imprecise aborts seem a lot like interrupts:
you can mask them or handle them; but controlling when and whether
they occur involves platform-specific assumptions, at least in
theory.

Cheers
---Dave

^ permalink raw reply

* [RFC PATCH] ARM: Add imprecise abort enable/disable macro
From: Fabrice Gasnier @ 2014-02-10 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140210152452.GA26684@n2100.arm.linux.org.uk>


On 02/10/2014 04:24 PM, Russell King - ARM Linux wrote:
> On Mon, Feb 10, 2014 at 03:12:47PM +0000, Dave Martin wrote:
>> Firstly, blindly adding 4 to PC is obviouly not right, partly because we
>> might be running an unrelated thread by the time the abort fires, and
>> also because the affected instruction might not be 4 bytes in size in a
>> Thumb kernel.
> Exactly.  We ended up on some platforms having special accessors for PCI
> where we included a number of 'mov r0, r0' instructions after the accessor
> so we could properly cope with them - but this required knowledge that
> we were going to only receive an imprecise abort from these accessors
> and only for a few cycles after the instruction.
>
> However, that's not true with modern architectures.  The point they're
> received will _not_ be the load/store which resulted in the abort, and
> in the case of a write, they could be many hundreds of cycles later,
> especially if the write has been buffered.
What about putting a memory barrier after a load/store ?
CPU should wait for the operation to complete right ?
>
> So adding four to the PC is definitely a very /bad/ thing to do.
>

^ permalink raw reply

* [PATCH 14/28] Remove MACH_SMDKC210
From: Mark Brown @ 2014-02-10 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392046242.3585.41.camel@x220>

On Mon, Feb 10, 2014 at 04:30:42PM +0100, Paul Bolle wrote:
> On Mon, 2014-02-10 at 14:12 +0000, Mark Brown wrote:

> > Yes, that's correct.  Now, like I say think about what the symbol was
> > there for in the first place.

> So, next step: the Kconfig symbols MACH_SMDKV310 and MACH_SMDKC210 were
> removed in commit 383ffda2fa ("ARM: EXYNOS: no more support non-DT for
> EXYNOS SoCs"). That commit was part of v3.11. Correct?

Indeed, so we can see that these platforms were converted to use DT and
the symbols were removed as a result.  This means that a good fix here
is to ensure that the driver can be used with DT platforms.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140210/68f0308e/attachment.sig>

^ permalink raw reply

* [RFC PATCH] ARM: Add imprecise abort enable/disable macro
From: Russell King - ARM Linux @ 2014-02-10 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140210162822.GF2794@e103592.cambridge.arm.com>

On Mon, Feb 10, 2014 at 04:28:22PM +0000, Dave Martin wrote:
> On Mon, Feb 10, 2014 at 03:19:34PM +0000, Russell King - ARM Linux wrote:
> > On Mon, Feb 10, 2014 at 02:42:28PM +0000, Dave Martin wrote:
> > > Should we require CPSR.A to me masked in Booting, for all CPUs that have
> > > it?
> > 
> > If it's not masked at boot, then there can't be an imprecise exception
> > pending.
> 
> Couldn't there still be a dangling abort condition triggered by the
> bootloader, which which doesn't raise the abort pin until after we
> entered the kernel?

True, but the decompressor does disable them (see safe_svcmode_maskall),
so any raised abort is likely to hit the boot loader's vectors at that
time.  They remain masked into the kernel from that point.

If you're not using the decompressor then the A bit will be left as-is.

Given that we've not yet had any failures, I'm inclined to just let the
status-quo be for the kernel entry - if it does cause problems then it's
clear that the right solution is that the A bit must be disabled.

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

* [RFC PATCH] ARM: Add imprecise abort enable/disable macro
From: Ben Dooks @ 2014-02-10 16:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140210152147.GE2794@e103592.cambridge.arm.com>

On 10/02/14 15:21, Dave Martin wrote:
> On Mon, Feb 10, 2014 at 02:54:22PM +0000, Ben Dooks wrote:
>> On 10/02/14 14:16, Dave Martin wrote:
>>> On Fri, Feb 07, 2014 at 05:19:15PM +0100, Fabrice GASNIER wrote:
>>>> This patch adds imprecise abort enable/disable macros.
>>>> It also enables imprecise aborts when starting kernel.
>>>
>>> Relying on imprecise aborts for hardware probing would be considered bad
>>> hardware and/or software design for ARM-specific stuff.
>>>
>>> PCI is more generic though, so we may have to put up with this to some
>>> extent.  Can you point me to the affected probing code?  I'm not very
>>> familiar with that stuff...
>>
>> The marvell pcie always had the option of delivering any bus
>> errors as imprecise aborts. However it was /annoying/ and therefore
>
> You don't say ;)
>
>> easier just to turn it off and rely on the hardware returning 0xffff
>> for any configuration area it couldn't get to.
>
> Does PCI have any way of finding out which parts of the configuration
> space are there before you are forced to go poking around in invalid
> address space?
>
> I'm guessing there may not be, otherwise this convsersation might not
> be happening ... but I don't know too much about PCI.

IIRC for configuration accesses you have to wait for the PCIe core
to get a response from the other end. The systems I've seen either
poll for completion or hold the transaction until the pcie core has
finished working.


-- 
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius

^ permalink raw reply

* [PATCH v3 0/4] ARM: keystone: enable gpio support
From: Grygorii Strashko @ 2014-02-10 16:41 UTC (permalink / raw)
  To: linux-arm-kernel

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

 arch/arm/boot/dts/k2hk-evm.dts      |   23 ++++++++++++++++++
 arch/arm/boot/dts/keystone.dtsi     |   45 +++++++++++++++++++++++++++++++++++
 arch/arm/configs/keystone_defconfig |   11 +++++++++
 3 files changed, 79 insertions(+)

-- 
1.7.9.5

^ permalink raw reply

* [PATCH v3 1/4] ARM: dts: keystone: add gpio device entry
From: Grygorii Strashko @ 2014-02-10 16:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392050481-19086-1-git-send-email-grygorii.strashko@ti.com>

This patch adds Keystone GPIO IP device definitions in DT which supports
up to 32 GPIO lines and each GPIO line can be configured as separate
interrupt source (so called "unbanked" IRQ).

For more information see:
 http://www.ti.com/lit/ug/sprugv1/sprugv1.pdf

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 arch/arm/boot/dts/keystone.dtsi |   45 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index 3a83ffe..0f82bb9 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -7,6 +7,7 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/gpio.h>
 
 #include "skeleton.dtsi"
 
@@ -214,5 +215,49 @@
 			reg = <0x022f0080 0x80>;
 			clocks = <&clkwdtimer0>;
 		};
+
+		gpio0: gpio at 260bf00 {
+			compatible = "ti,keystone-gpio";
+			reg = <0x0260bf00 0x100>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			/* HW Interrupts mapped to GPIO pins */
+			interrupts = <GIC_SPI 120 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 121 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 122 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 123 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 124 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 125 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 126 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 127 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 128 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 129 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 130 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 131 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 132 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 133 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 134 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 135 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 136 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 137 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 138 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 139 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 140 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 141 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 142 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 143 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 144 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 145 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 146 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 147 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 148 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 149 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 150 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkgpio>;
+			clock-names = "gpio";
+			ti,ngpio = <32>;
+			ti,davinci-gpio-unbanked = <32>;
+		};
 	};
 };
-- 
1.7.9.5

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox