Patchwork [U-Boot,v3,04/11] Blackfin: bf60x: add dma support

login
register
mail settings
Submitter Sonic Zhang
Date Feb. 20, 2013, 8:50 a.m.
Message ID <1361350217-7592-5-git-send-email-sonic.adi@gmail.com>
Download mbox | patch
Permalink /patch/222004/
State Superseded
Delegated to: Tom Rini
Headers show

Comments

Sonic Zhang - Feb. 20, 2013, 8:50 a.m.
From: Bob Liu <lliubbo@gmail.com>

Add dma support for bf60x.

Fix review issues from Wolfgang:
1) Fix all checkpatch issues.
2) Remove unrelated dma structure change to separate patch.
3) The DMA config MMR on BF60x is 32 bits while it is 16 bits on BF5xx.
The different type of config MMR is correct.
4) Replace unreable macro in dma structures with normal types.

Signed-off-by: Bob Liu <lliubbo@gmail.com>
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---
 arch/blackfin/include/asm/dma.h                  |   81 ++++++++++++------
 arch/blackfin/include/asm/mach-common/bits/dma.h |   54 +++++++++++-
 arch/blackfin/lib/string.c                       |   97 ++++++++++++----------
 3 files changed, 156 insertions(+), 76 deletions(-)

Patch

diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h
index 21ff1cf..ef1db6e 100644
--- a/arch/blackfin/include/asm/dma.h
+++ b/arch/blackfin/include/asm/dma.h
@@ -8,7 +8,12 @@ 
 #ifndef _BLACKFIN_DMA_H_
 #define _BLACKFIN_DMA_H_
 
+#include <linux/types.h>
+#ifdef __ADSPBF60x__
+#include <asm/mach-common/bits/dde.h>
+#else
 #include <asm/mach-common/bits/dma.h>
+#endif
 
 struct dmasg_large {
 	void *next_desc_addr;
@@ -30,46 +35,70 @@  struct dmasg {
 } __attribute__((packed));
 
 struct dma_register {
+#ifdef __ADSPBF60x__
+	void *next_desc_ptr;	/* DMA Next Descriptor Pointer register */
+	u32 start_addr;		/* DMA Start address  register */
+	u32 config;		/* DMA Configuration register */
+
+	u32 x_count;		/* DMA x_count register */
+	s32 x_modify;		/* DMA x_modify register */
+	u32 y_count;		/* DMA y_count register */
+	s32 y_modify;		/* DMA y_modify register */
+	u32 __pad0[2];
+
+	void *curr_desc_ptr;	/* DMA Curr Descriptor Pointer register */
+	void *prev_desc_ptr;	/* DMA Prev Descriptor Pointer register */
+	void *curr_addr;	/* DMA Current Address Pointer register */
+	u32 status;		/* DMA irq status register */
+	u32 curr_x_count;	/* DMA Current x-count register */
+	u32 curr_y_count;	/* DMA Current y-count register */
+	u32 __pad1[2];
+
+	u32 bw_limit;		/* DMA Bandwidth Limit Count */
+	u32 curr_bw_limit;	/* DMA curr Bandwidth Limit Count */
+	u32 bw_monitor;		/* DMA Bandwidth Monitor Count */
+	u32 curr_bw_monitor;	/* DMA curr Bandwidth Monitor Count */
+#else
 	void *next_desc_ptr;	/* DMA Next Descriptor Pointer register */
-	unsigned long start_addr;	/* DMA Start address  register */
+	u32 start_addr;		/* DMA Start address  register */
 
-	unsigned short cfg;	/* DMA Configuration register */
-	unsigned short dummy1;	/* DMA Configuration register */
+	u16 config;		/* DMA Configuration register */
+	u16 dummy1;		/* DMA Configuration register */
 
-	unsigned long reserved;
+	u32 reserved;
 
-	unsigned short x_count;	/* DMA x_count register */
-	unsigned short dummy2;
+	u16 x_count;		/* DMA x_count register */
+	u16 dummy2;
 
-	short x_modify;	/* DMA x_modify register */
-	unsigned short dummy3;
+	s16 x_modify;		/* DMA x_modify register */
+	u16 dummy3;
 
-	unsigned short y_count;	/* DMA y_count register */
-	unsigned short dummy4;
+	u16 y_count;		/* DMA y_count register */
+	u16 dummy4;
 
-	short y_modify;	/* DMA y_modify register */
-	unsigned short dummy5;
+	s16 y_modify;		/* DMA y_modify register */
+	u16 dummy5;
 
-	void *curr_desc_ptr;	/* DMA Current Descriptor Pointer
-					   register */
-	unsigned long curr_addr_ptr;	/* DMA Current Address Pointer
-						   register */
-	unsigned short irq_status;	/* DMA irq status register */
-	unsigned short dummy6;
+	void *curr_desc_ptr;	/* DMA Current Descriptor Pointer register */
 
-	unsigned short peripheral_map;	/* DMA peripheral map register */
-	unsigned short dummy7;
+	u32 curr_addr_ptr;	/* DMA Current Address Pointer register */
 
-	unsigned short curr_x_count;	/* DMA Current x-count register */
-	unsigned short dummy8;
+	u16 status;		/* DMA irq status register */
+	u16 dummy6;
 
-	unsigned long reserved2;
+	u16 peripheral_map;	/* DMA peripheral map register */
+	u16 dummy7;
 
-	unsigned short curr_y_count;	/* DMA Current y-count register */
-	unsigned short dummy9;
+	u16 curr_x_count;	/* DMA Current x-count register */
+	u16 dummy8;
 
-	unsigned long reserved3;
+	u32 reserved2;
 
+	u16 curr_y_count;	/* DMA Current y-count register */
+	u16 dummy9;
+
+	u32 reserved3;
+#endif
 };
 
 #endif
diff --git a/arch/blackfin/include/asm/mach-common/bits/dma.h b/arch/blackfin/include/asm/mach-common/bits/dma.h
index 136313e..ac426ad 100644
--- a/arch/blackfin/include/asm/mach-common/bits/dma.h
+++ b/arch/blackfin/include/asm/mach-common/bits/dma.h
@@ -9,14 +9,54 @@ 
 #define DMAEN			0x0001	/* DMA Channel Enable */
 #define WNR			0x0002	/* Channel Direction (W/R*) */
 #define WDSIZE_8		0x0000	/* Transfer Word Size = 8 */
+
+#ifdef CONFIG_BF60x
+
+#define PSIZE_8			0x00000000	/* Transfer Word Size = 16 */
+#define PSIZE_16		0x00000010	/* Transfer Word Size = 16 */
+#define PSIZE_32		0x00000020	/* Transfer Word Size = 32 */
+#define PSIZE_64		0x00000030	/* Transfer Word Size = 32 */
+#define WDSIZE_16		0x00000100	/* Transfer Word Size = 16 */
+#define WDSIZE_32		0x00000200	/* Transfer Word Size = 32 */
+#define WDSIZE_64		0x00000300	/* Transfer Word Size = 32 */
+#define WDSIZE_128		0x00000400	/* Transfer Word Size = 32 */
+#define WDSIZE_256		0x00000500	/* Transfer Word Size = 32 */
+#define DMA2D			0x04000000	/* DMA Mode (2D/1D*) */
+#define RESTART			0x00000004	/* DMA Buffer Clear SYNC */
+#define DI_EN_X			0x00100000	/* Data Int Enable in X count */
+#define DI_EN_Y			0x00200000	/* Data Int Enable in Y count */
+#define DI_EN_P			0x00300000	/* Data Int Enable in Peri */
+#define DI_EN			DI_EN_X		/* Data Int Enable */
+#define NDSIZE_0		0x00000000	/* Next Desc Size = 0 */
+#define NDSIZE_1		0x00010000	/* Next Desc Size = 1 */
+#define NDSIZE_2		0x00020000	/* Next Desc Size = 2 */
+#define NDSIZE_3		0x00030000	/* Next Desc Size = 3 */
+#define NDSIZE_4		0x00040000	/* Next Desc Size = 4 */
+#define NDSIZE_5		0x00050000	/* Next Desc Size = 5 */
+#define NDSIZE_6		0x00060000	/* Next Desc Size = 6 */
+#define NDSIZE			0x00070000	/* Next Desc Size */
+#define NDSIZE_OFFSET		16		/* Next Desc Size Offset */
+#define DMAFLOW_LIST		0x00004000	/* Desc List Mode */
+#define DMAFLOW_ARRAY		0x00005000	/* Desc Array Mode */
+#define DMAFLOW_LIST_DEMAND	0x00006000	/* Desc Demand List Mode */
+#define DMAFLOW_ARRAY_DEMAND	0x00007000	/* Desc Demand Array Mode */
+#define DMA_RUN_DFETCH		0x00000100	/* DMA Channel Run (DFETCH) */
+#define DMA_RUN			0x00000200	/* DMA Channel Run */
+#define DMA_RUN_WAIT_TRIG	0x00000300	/* DMA Channel Run (WAIT TRIG)*/
+#define DMA_RUN_WAIT_ACK	0x00000400	/* DMA Channel Run (WAIT ACK) */
+
+#else
+
 #define WDSIZE_16		0x0004	/* Transfer Word Size = 16 */
 #define WDSIZE_32		0x0008	/* Transfer Word Size = 32 */
+#define PSIZE_16		WDSIZE_16
+#define PSIZE_32		WDSIZE_32
 #define DMA2D			0x0010	/* DMA Mode (2D/1D*) */
 #define RESTART			0x0020	/* DMA Buffer Clear */
 #define DI_SEL			0x0040	/* Data Interrupt Timing Select */
 #define DI_EN			0x0080	/* Data Interrupt Enable */
 #define NDSIZE			0x0F00	/* Next Descriptor bitmask */
-#define NDSIZE_0		0x0000	/* Next Descriptor Size = 0 (Stop/Autobuffer) */
+#define NDSIZE_0		0x0000	/* Next Descriptor Size = 0 */
 #define NDSIZE_1		0x0100	/* Next Descriptor Size = 1 */
 #define NDSIZE_2		0x0200	/* Next Descriptor Size = 2 */
 #define NDSIZE_3		0x0300	/* Next Descriptor Size = 3 */
@@ -26,14 +66,13 @@ 
 #define NDSIZE_7		0x0700	/* Next Descriptor Size = 7 */
 #define NDSIZE_8		0x0800	/* Next Descriptor Size = 8 */
 #define NDSIZE_9		0x0900	/* Next Descriptor Size = 9 */
-#define FLOW_STOP		0x0000	/* Stop Mode */
-#define FLOW_AUTO		0x1000	/* Autobuffer Mode */
 #define FLOW_ARRAY		0x4000	/* Descriptor Array Mode */
 #define FLOW_SMALL		0x6000	/* Small Model Descriptor List Mode */
 #define FLOW_LARGE		0x7000	/* Large Model Descriptor List Mode */
 
 #define DMAEN_P			0	/* Channel Enable */
 #define WNR_P			1	/* Channel Direction (W/R*) */
+#define WDSIZE_P		2	/* Transfer Word Size */
 #define DMA2D_P			4	/* 2D/1D* Mode */
 #define RESTART_P		5	/* Restart */
 #define DI_SEL_P		6	/* Data Interrupt Select */
@@ -45,14 +84,19 @@ 
 #define DFETCH			0x0004	/* DMA Descriptor Fetch Indicator */
 #define DMA_RUN			0x0008	/* DMA Channel Running Indicator */
 
+#endif
+#define DMAFLOW			0x7000	/* Flow Control */
+#define FLOW_STOP		0x0000	/* Stop Mode */
+#define FLOW_AUTO		0x1000	/* Autobuffer Mode */
+
 #define DMA_DONE_P		0	/* DMA Done Indicator */
 #define DMA_ERR_P		1	/* DMA Error Indicator */
 #define DFETCH_P		2	/* Descriptor Fetch Indicator */
 #define DMA_RUN_P		3	/* DMA Running Indicator */
 
 /* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks */
-#define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*) */
-#define CTYPE_P			6	/* DMA Channel Type Indicator BIT POSITION */
+#define CTYPE			0x0040	/* DMA Channel Type (Mem/Peri) */
+#define CTYPE_P			6	/* DMA Channel Type BIT POSITION */
 #define PMAP			0xF000	/* Peripheral Mapped To This Channel */
 
 #endif
diff --git a/arch/blackfin/lib/string.c b/arch/blackfin/lib/string.c
index e344d3b..44d8c6d 100644
--- a/arch/blackfin/lib/string.c
+++ b/arch/blackfin/lib/string.c
@@ -29,7 +29,7 @@ 
 #include <config.h>
 #include <asm/blackfin.h>
 #include <asm/io.h>
-#include <asm/mach-common/bits/dma.h>
+#include <asm/dma.h>
 
 char *strcpy(char *dest, const char *src)
 {
@@ -117,81 +117,88 @@  int strncmp(const char *cs, const char *ct, size_t count)
 	return __res1;
 }
 
-#ifdef bfin_write_MDMA1_D0_IRQ_STATUS
-# define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA1_D0_IRQ_STATUS
-# define bfin_write_MDMA_D0_START_ADDR bfin_write_MDMA1_D0_START_ADDR
-# define bfin_write_MDMA_D0_X_COUNT    bfin_write_MDMA1_D0_X_COUNT
-# define bfin_write_MDMA_D0_X_MODIFY   bfin_write_MDMA1_D0_X_MODIFY
-# define bfin_write_MDMA_D0_CONFIG     bfin_write_MDMA1_D0_CONFIG
-# define bfin_write_MDMA_S0_START_ADDR bfin_write_MDMA1_S0_START_ADDR
-# define bfin_write_MDMA_S0_X_COUNT    bfin_write_MDMA1_S0_X_COUNT
-# define bfin_write_MDMA_S0_X_MODIFY   bfin_write_MDMA1_S0_X_MODIFY
-# define bfin_write_MDMA_S0_CONFIG     bfin_write_MDMA1_S0_CONFIG
-# define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA1_D0_IRQ_STATUS
-# define bfin_read_MDMA_D0_IRQ_STATUS  bfin_read_MDMA1_D0_IRQ_STATUS
+#ifdef MDMA1_D0_NEXT_DESC_PTR
+# define MDMA_D0_NEXT_DESC_PTR MDMA1_D0_NEXT_DESC_PTR
+# define MDMA_S0_NEXT_DESC_PTR MDMA1_S0_NEXT_DESC_PTR
 #endif
+
+static void dma_calc_size(unsigned long ldst, unsigned long lsrc, size_t count,
+			unsigned long *dshift, unsigned long *bpos)
+{
+	unsigned long limit;
+
+#ifdef MSIZE
+	limit = 6;
+	*dshift = MSIZE_P;
+#else
+	limit = 3;
+	*dshift = WDSIZE_P;
+#endif
+
+	*bpos = min(limit, ffs(ldst | lsrc | count)) - 1;
+}
+
 /* This version misbehaves for count values of 0 and 2^16+.
  * Perhaps we should detect that ?  Nowhere do we actually
  * use dma memcpy for those types of lengths though ...
  */
 void dma_memcpy_nocache(void *dst, const void *src, size_t count)
 {
-	uint16_t wdsize, mod;
+	struct dma_register *mdma_d0 = (void *)MDMA_D0_NEXT_DESC_PTR;
+	struct dma_register *mdma_s0 = (void *)MDMA_S0_NEXT_DESC_PTR;
+	unsigned long ldst = (unsigned long)dst;
+	unsigned long lsrc = (unsigned long)src;
+	unsigned long dshift, bpos;
+	uint32_t dsize, mod;
 
 	/* Disable DMA in case it's still running (older u-boot's did not
 	 * always turn them off).  Do it before the if statement below so
 	 * we can be cheap and not do a SSYNC() due to the forced abort.
 	 */
-	bfin_write_MDMA_D0_CONFIG(0);
-	bfin_write_MDMA_S0_CONFIG(0);
-	bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
+	bfin_write(&mdma_d0->config, 0);
+	bfin_write(&mdma_s0->config, 0);
+	bfin_write(&mdma_d0->status, DMA_RUN | DMA_DONE | DMA_ERR);
 
 	/* Scratchpad cannot be a DMA source or destination */
-	if (((unsigned long)src >= L1_SRAM_SCRATCH &&
-	     (unsigned long)src < L1_SRAM_SCRATCH_END) ||
-	    ((unsigned long)dst >= L1_SRAM_SCRATCH &&
-	     (unsigned long)dst < L1_SRAM_SCRATCH_END))
+	if ((lsrc >= L1_SRAM_SCRATCH && lsrc < L1_SRAM_SCRATCH_END) ||
+	    (ldst >= L1_SRAM_SCRATCH && ldst < L1_SRAM_SCRATCH_END))
 		hang();
 
-	if (((unsigned long)dst | (unsigned long)src | count) & 0x1) {
-		wdsize = WDSIZE_8;
-		mod = 1;
-	} else if (((unsigned long)dst | (unsigned long)src | count) & 0x2) {
-		wdsize = WDSIZE_16;
-		count >>= 1;
-		mod = 2;
-	} else {
-		wdsize = WDSIZE_32;
-		count >>= 2;
-		mod = 4;
-	}
+	dma_calc_size(ldst, lsrc, count, &dshift, &bpos);
+	dsize = bpos << dshift;
+	count >>= bpos;
+	mod = 1 << bpos;
+
+#ifdef PSIZE
+	dsize |= min(3, bpos) << PSIZE_P;
+#endif
 
 	/* Copy sram functions from sdram to sram */
 	/* Setup destination start address */
-	bfin_write_MDMA_D0_START_ADDR(dst);
+	bfin_write(&mdma_d0->start_addr, ldst);
 	/* Setup destination xcount */
-	bfin_write_MDMA_D0_X_COUNT(count);
+	bfin_write(&mdma_d0->x_count, count);
 	/* Setup destination xmodify */
-	bfin_write_MDMA_D0_X_MODIFY(mod);
+	bfin_write(&mdma_d0->x_modify, mod);
 
 	/* Setup Source start address */
-	bfin_write_MDMA_S0_START_ADDR(src);
+	bfin_write(&mdma_s0->start_addr, lsrc);
 	/* Setup Source xcount */
-	bfin_write_MDMA_S0_X_COUNT(count);
+	bfin_write(&mdma_s0->x_count, count);
 	/* Setup Source xmodify */
-	bfin_write_MDMA_S0_X_MODIFY(mod);
+	bfin_write(&mdma_s0->x_modify, mod);
 
 	/* Enable source DMA */
-	bfin_write_MDMA_S0_CONFIG(wdsize | DMAEN);
-	bfin_write_MDMA_D0_CONFIG(wdsize | DMAEN | WNR | DI_EN);
+	bfin_write(&mdma_s0->config, dsize | DMAEN);
+	bfin_write(&mdma_d0->config, dsize | DMAEN | WNR | DI_EN);
 	SSYNC();
 
-	while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
+	while (!(bfin_read(&mdma_d0->status) & DMA_DONE))
 		continue;
 
-	bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
-	bfin_write_MDMA_D0_CONFIG(0);
-	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write(&mdma_d0->status, DMA_RUN | DMA_DONE | DMA_ERR);
+	bfin_write(&mdma_d0->config, 0);
+	bfin_write(&mdma_s0->config, 0);
 }
 /* We should do a dcache invalidate on the destination after the dma, but since
  * we lack such hardware capability, we'll flush/invalidate the destination