From patchwork Wed Nov 14 10:24:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bob Liu X-Patchwork-Id: 198861 X-Patchwork-Delegate: sonic.adi@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id D3E542C009F for ; Wed, 14 Nov 2012 21:40:46 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2C8FE4A026; Wed, 14 Nov 2012 11:40:44 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id AG7ItXXFjosY; Wed, 14 Nov 2012 11:40:43 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 47E5B4A03F; Wed, 14 Nov 2012 11:40:40 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6E6884A03E for ; Wed, 14 Nov 2012 11:40:37 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id mxSYtDhuZhn7 for ; Wed, 14 Nov 2012 11:40:36 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from va3outboundpool.messaging.microsoft.com (va3ehsobe006.messaging.microsoft.com [216.32.180.16]) by theia.denx.de (Postfix) with ESMTPS id ACFCE4A026 for ; Wed, 14 Nov 2012 11:40:33 +0100 (CET) Received: from mail85-va3-R.bigfish.com (10.7.14.236) by VA3EHSOBE005.bigfish.com (10.7.40.25) with Microsoft SMTP Server id 14.1.225.23; Wed, 14 Nov 2012 10:25:29 +0000 Received: from mail85-va3 (localhost [127.0.0.1]) by mail85-va3-R.bigfish.com (Postfix) with ESMTP id 800C23200E5; Wed, 14 Nov 2012 10:25:29 +0000 (UTC) X-Forefront-Antispam-Report: CIP:137.71.25.57; KIP:(null); UIP:(null); IPV:NLI; H:nwd2mta2.analog.com; RD:nwd2mail11.analog.com; EFVD:NLI X-SpamScore: 17 X-BigFish: VS17(zzzz1ce5h1202h1d1ah1cabh1d2ahzz8275bhz2ei87h2a8h668h839hd24he5bh1288h12a5h12a9h12bdh12e5h137ah139eh13b6h13eah1441h14ddh1504h1537h15a8hff4m129fs1155h) Received-SPF: neutral (mail85-va3: 137.71.25.57 is neither permitted nor denied by domain of gmail.com) client-ip=137.71.25.57; envelope-from=lliubbo@gmail.com; helo=nwd2mta2.analog.com ; 2.analog.com ; X-FB-DOMAIN-IP-MATCH: fail Received: from mail85-va3 (localhost.localdomain [127.0.0.1]) by mail85-va3 (MessageSwitch) id 1352888727447813_21507; Wed, 14 Nov 2012 10:25:27 +0000 (UTC) Received: from VA3EHSMHS023.bigfish.com (unknown [10.7.14.254]) by mail85-va3.bigfish.com (Postfix) with ESMTP id 6958B220053; Wed, 14 Nov 2012 10:25:27 +0000 (UTC) Received: from nwd2mta2.analog.com (137.71.25.57) by VA3EHSMHS023.bigfish.com (10.7.99.33) with Microsoft SMTP Server (TLS) id 14.1.225.23; Wed, 14 Nov 2012 10:25:27 +0000 Received: from NWD2HUBCAS1.ad.analog.com (nwd2hubcas1.ad.analog.com [10.64.73.29]) by nwd2mta2.analog.com (8.13.8/8.13.8) with ESMTP id qAEBYAHq016160 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL); Wed, 14 Nov 2012 06:34:10 -0500 Received: from zeus.spd.analog.com (10.64.82.11) by NWD2HUBCAS1.ad.analog.com (10.64.73.29) with Microsoft SMTP Server id 8.3.83.0; Wed, 14 Nov 2012 05:25:26 -0500 Received: from linux.site ([10.99.22.20]) by zeus.spd.analog.com (8.14.5/8.14.5) with ESMTP id qAEAPO5W032315; Wed, 14 Nov 2012 05:25:24 -0500 Received: from bob-OptiPlex-760.analog.com (unknown [10.99.24.84]) by linux.site (Postfix) with ESMTP id 1157542CC14A; Tue, 13 Nov 2012 19:54:05 -0700 (MST) From: Bob Liu To: Date: Wed, 14 Nov 2012 18:24:37 +0800 Message-ID: <1352888686-9868-4-git-send-email-lliubbo@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1352888686-9868-1-git-send-email-lliubbo@gmail.com> References: <1352888686-9868-1-git-send-email-lliubbo@gmail.com> MIME-Version: 1.0 Cc: u-boot-devel@blackfin.uclinux.org, trini@ti.com, sonic.zhang@analog.com Subject: [U-Boot] [PATCH V3 03/12] Blackfin: bf60x: add dma support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Add dma support for bf60x. Signed-off-by: Bob Liu --- arch/blackfin/include/asm/dma.h | 113 ++++++++++++---------- arch/blackfin/include/asm/mach-common/bits/dma.h | 48 ++++++++- arch/blackfin/lib/string.c | 97 ++++++++++--------- 3 files changed, 159 insertions(+), 99 deletions(-) diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h index 21ff1cf..211719a 100644 --- a/arch/blackfin/include/asm/dma.h +++ b/arch/blackfin/include/asm/dma.h @@ -8,68 +8,77 @@ #ifndef _BLACKFIN_DMA_H_ #define _BLACKFIN_DMA_H_ +#include +#ifdef __ADSPBF60x__ +#include +#else #include +#endif struct dmasg_large { void *next_desc_addr; - unsigned long start_addr; - unsigned short cfg; - unsigned short x_count; - short x_modify; - unsigned short y_count; - short y_modify; + u32 start_addr; + u16 cfg; + u16 x_count; + s16 x_modify; + u16 y_count; + s16 y_modify; } __attribute__((packed)); struct dmasg { - unsigned long start_addr; - unsigned short cfg; - unsigned short x_count; - short x_modify; - unsigned short y_count; - short y_modify; + u32 start_addr; + u16 cfg; + u16 x_count; + s16 x_modify; + u16 y_count; + s16 y_modify; } __attribute__((packed)); +/* + * All Blackfin system MMRs are padded to 32bits even if the register + * itself is only 16bits. So use a helper macro to streamline this. + */ +#define __BFP(m) m; u16 __pad_##m struct dma_register { - void *next_desc_ptr; /* DMA Next Descriptor Pointer register */ - unsigned long start_addr; /* DMA Start address register */ - - unsigned short cfg; /* DMA Configuration register */ - unsigned short dummy1; /* DMA Configuration register */ - - unsigned long reserved; - - unsigned short x_count; /* DMA x_count register */ - unsigned short dummy2; - - short x_modify; /* DMA x_modify register */ - unsigned short dummy3; - - unsigned short y_count; /* DMA y_count register */ - unsigned short dummy4; - - short y_modify; /* DMA y_modify register */ - unsigned short 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; - - unsigned short peripheral_map; /* DMA peripheral map register */ - unsigned short dummy7; - - unsigned short curr_x_count; /* DMA Current x-count register */ - unsigned short dummy8; - - unsigned long reserved2; - - unsigned short curr_y_count; /* DMA Current y-count register */ - unsigned short dummy9; - - unsigned long reserved3; - +#ifdef __ADSPBF60x__ + void *next_desc_ptr; + u32 start_addr; + u32 config; + u32 x_count; + s32 x_modify; + u32 y_count; + s32 y_modify; + u32 __pad0[2]; + void *curr_desc_ptr; + void *prev_desc_ptr; + void *curr_addr; + u32 status; + u32 curr_x_count; + u32 curr_y_count; + u32 __pad1[2]; + u32 bw_limit; + u32 curr_bw_limit; + u32 bw_monitor; + u32 curr_bw_monitor; +#else + void *next_desc_ptr; + u32 start_addr; + u16 __BFP(config); + u32 __pad0; + u16 __BFP(x_count); + s16 __BFP(x_modify); + u16 __BFP(y_count); + s16 __BFP(y_modify); + void *curr_desc_ptr; + u32 curr_addr_ptr; + u16 __BFP(status); + u16 __BFP(peripheral_map); + u16 __BFP(curr_x_count); + u32 __pad1; + u16 __BFP(curr_y_count); + u32 __pad2; +#endif }; +#undef __BFP #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..1126c44 100644 --- a/arch/blackfin/include/asm/mach-common/bits/dma.h +++ b/arch/blackfin/include/asm/mach-common/bits/dma.h @@ -9,8 +9,48 @@ #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 Interrupt Enable in X count */ +#define DI_EN_Y 0x00200000 /* Data Interrupt Enable in Y count */ +#define DI_EN_P 0x00300000 /* Data Interrupt Enable in Peripheral */ +#define DI_EN DI_EN_X /* Data Interrupt Enable */ +#define NDSIZE_0 0x00000000 /* Next Descriptor Size = 0 (Stop/Autobuffer) */ +#define NDSIZE_1 0x00010000 /* Next Descriptor Size = 1 */ +#define NDSIZE_2 0x00020000 /* Next Descriptor Size = 2 */ +#define NDSIZE_3 0x00030000 /* Next Descriptor Size = 3 */ +#define NDSIZE_4 0x00040000 /* Next Descriptor Size = 4 */ +#define NDSIZE_5 0x00050000 /* Next Descriptor Size = 5 */ +#define NDSIZE_6 0x00060000 /* Next Descriptor Size = 6 */ +#define NDSIZE 0x00070000 /* Next Descriptor Size */ +#define NDSIZE_OFFSET 16 /* Next Descriptor Size Offset */ +#define DMAFLOW_LIST 0x00004000 /* Descriptor List Mode */ +#define DMAFLOW_ARRAY 0x00005000 /* Descriptor Array Mode */ +#define DMAFLOW_LIST_DEMAND 0x00006000 /* Descriptor Demand List Mode */ +#define DMAFLOW_ARRAY_DEMAND 0x00007000 /* Descriptor Demand Array Mode */ +#define DMA_RUN_DFETCH 0x00000100 /* DMA Channel Running Indicator (DFETCH) */ +#define DMA_RUN 0x00000200 /* DMA Channel Running Indicator */ +#define DMA_RUN_WAIT_TRIG 0x00000300 /* DMA Channel Running Indicator (WAIT TRIG) */ +#define DMA_RUN_WAIT_ACK 0x00000400 /* DMA Channel Running Indicator (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 */ @@ -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,6 +84,11 @@ #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 */ 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 #include #include -#include +#include 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