blackfin: bf60x: add dma support
Add dma support for bf60x. Signed-off-by: Bob Liu <lliubbo@gmail.com> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Sonic Zhang <sonic.adi@gmail.com>
This commit is contained in:
parent
a12c51f640
commit
ee8259623e
@ -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 */
|
||||
unsigned long start_addr; /* DMA Start address register */
|
||||
u32 start_addr; /* DMA Start address register */
|
||||
u32 config; /* DMA Configuration register */
|
||||
|
||||
unsigned short cfg; /* DMA Configuration register */
|
||||
unsigned short dummy1; /* 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];
|
||||
|
||||
unsigned long reserved;
|
||||
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];
|
||||
|
||||
unsigned short x_count; /* DMA x_count register */
|
||||
unsigned short dummy2;
|
||||
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 */
|
||||
u32 start_addr; /* DMA Start address register */
|
||||
|
||||
short x_modify; /* DMA x_modify register */
|
||||
unsigned short dummy3;
|
||||
u16 config; /* DMA Configuration register */
|
||||
u16 dummy1; /* DMA Configuration register */
|
||||
|
||||
unsigned short y_count; /* DMA y_count register */
|
||||
unsigned short dummy4;
|
||||
u32 reserved;
|
||||
|
||||
short y_modify; /* DMA y_modify register */
|
||||
unsigned short dummy5;
|
||||
u16 x_count; /* DMA x_count register */
|
||||
u16 dummy2;
|
||||
|
||||
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;
|
||||
s16 x_modify; /* DMA x_modify register */
|
||||
u16 dummy3;
|
||||
|
||||
unsigned short peripheral_map; /* DMA peripheral map register */
|
||||
unsigned short dummy7;
|
||||
u16 y_count; /* DMA y_count register */
|
||||
u16 dummy4;
|
||||
|
||||
unsigned short curr_x_count; /* DMA Current x-count register */
|
||||
unsigned short dummy8;
|
||||
s16 y_modify; /* DMA y_modify register */
|
||||
u16 dummy5;
|
||||
|
||||
unsigned long reserved2;
|
||||
void *curr_desc_ptr; /* DMA Current Descriptor Pointer register */
|
||||
|
||||
unsigned short curr_y_count; /* DMA Current y-count register */
|
||||
unsigned short dummy9;
|
||||
u32 curr_addr_ptr; /* DMA Current Address Pointer register */
|
||||
|
||||
unsigned long reserved3;
|
||||
u16 status; /* DMA irq status register */
|
||||
u16 dummy6;
|
||||
|
||||
u16 peripheral_map; /* DMA peripheral map register */
|
||||
u16 dummy7;
|
||||
|
||||
u16 curr_x_count; /* DMA Current x-count register */
|
||||
u16 dummy8;
|
||||
|
||||
u32 reserved2;
|
||||
|
||||
u16 curr_y_count; /* DMA Current y-count register */
|
||||
u16 dummy9;
|
||||
|
||||
u32 reserved3;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user