[PATCH] DMA: PL330: Support MEMTOMEM transmit without barrier operation.

Boojin Kim boojin.kim at samsung.com
Tue Dec 13 02:06:24 EST 2011


PL330 r1p0 version fixed the lockup error being on r0p0.
This patch supports the DMA transmit without barrier operation
if the revision is the next of r0p0.

Signed-off-by: Boojin Kim <boojin.kim at samsung.com>
---
 arch/arm/include/asm/hardware/pl330.h |    5 +++++
 drivers/dma/pl330.c                   |   26 +++++++++++++++++++++-----
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/hardware/pl330.h b/arch/arm/include/asm/hardware/pl330.h
index ed38e32..1f4d7cb 100644
--- a/arch/arm/include/asm/hardware/pl330.h
+++ b/arch/arm/include/asm/hardware/pl330.h
@@ -144,6 +144,11 @@ enum pl330_reqtype {
 #define CRD		0xe14
 
 #define PERIPH_ID	0xfe0
+#define PERIPH_REV_SHIFT	20
+#define PERIPH_REV_MASK		0xf
+#define PERIPH_REV_R0P0		0
+#define PERIPH_REV_R1P0		1
+#define PERIPH_REV_R1P1		2
 #define PCELL_ID	0xff0
 
 #define CR0_PERIPH_REQ_SET	(1 << 0)
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 3214ced..d87d884 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -129,6 +129,7 @@ struct pl330_reqcfg {
 	enum pl330_dstcachectrl dcctl;
 	enum pl330_srccachectrl scctl;
 	enum pl330_byteswap swap;
+	struct pl330_config *pcfg;
 };
 
 /*
@@ -438,6 +439,11 @@ static inline u32 get_id(struct pl330_info *pi, u32 off)
 	return id;
 }
 
+static inline u32 get_revision(u32 periph_id)
+{
+	return (periph_id>>PERIPH_REV_SHIFT)&PERIPH_REV_MASK;
+}
+
 static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
 		enum pl330_dst da, u16 val)
 {
@@ -1026,12 +1032,21 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
 		const struct _xfer_spec *pxs, int cyc)
 {
 	int off = 0;
+	struct pl330_config *pcfg = pxs->r->cfg->pcfg;
 
-	while (cyc--) {
-		off += _emit_LD(dry_run, &buf[off], ALWAYS);
-		off += _emit_RMB(dry_run, &buf[off]);
-		off += _emit_ST(dry_run, &buf[off], ALWAYS);
-		off += _emit_WMB(dry_run, &buf[off]);
+	/* check lock-up free version */
+	if (get_revision(pcfg->periph_id)  >= PERIPH_REV_R1P0) {
+		while (cyc--) {
+			off += _emit_LD(dry_run, &buf[off], ALWAYS);
+			off += _emit_ST(dry_run, &buf[off], ALWAYS);
+		}
+	} else {
+		while (cyc--) {
+			off += _emit_LD(dry_run, &buf[off], ALWAYS);
+			off += _emit_RMB(dry_run, &buf[off]);
+			off += _emit_ST(dry_run, &buf[off], ALWAYS);
+			off += _emit_WMB(dry_run, &buf[off]);
+		}
 	}
 
 	return off;
@@ -2398,6 +2413,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 	async_tx_ack(&desc->txd);
 
 	desc->req.peri = peri_id ? pch->chan.chan_id : 0;
+	desc->rqcfg.pcfg = &pch->dmac->pif.pcfg;
 
 	dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
 
-- 
1.7.1




More information about the linux-arm-kernel mailing list