From a89dd2ca6542d157890656d918d6ae2f933ab401 Mon Sep 17 00:00:00 2001 From: oharboe Date: Thu, 3 Sep 2009 08:23:39 +0000 Subject: David Brownell Abstract the orion_nand_fast_block_write() routine into a separate routine -- arm_nandwrite() -- so that other ARM cores can reuse it. Have davinci_nand do so. This faster than byte-at-a-time ops by a factor of three (!), even given the slowish interactions to support hardware ECC (1-bit flavor in that test) each 512 bytes; those could be read more efficiently by on-chip code. NOTE that until there's a generic "ARM algorithm" structure, this can't work on newer ARMv6 (like ARM1136) or ARMv7A (like Cortex-A8) cores, though the downloaded code itself would work just fine there. git-svn-id: svn://svn.berlios.de/openocd/trunk@2663 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/flash/davinci_nand.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/flash/davinci_nand.c') diff --git a/src/flash/davinci_nand.c b/src/flash/davinci_nand.c index 29c96300..41c2b20a 100644 --- a/src/flash/davinci_nand.c +++ b/src/flash/davinci_nand.c @@ -28,7 +28,7 @@ #include "config.h" #endif -#include "nand.h" +#include "arm_nandio.h" enum ecc { @@ -51,6 +51,9 @@ struct davinci_nand { uint32_t cmd; /* with CLE */ uint32_t addr; /* with ALE */ + /* write acceleration */ + struct arm_nand_data io; + /* page i/o for the relevant flavor of hardware ECC */ int (*read_page)(struct nand_device_s *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); @@ -181,7 +184,7 @@ static int davinci_read_data(struct nand_device_s *nand, void *data) return ERROR_OK; } -/* REVISIT a bit of native code should let block I/O be MUCH faster */ +/* REVISIT a bit of native code should let block reads be MUCH faster */ static int davinci_read_block_data(struct nand_device_s *nand, uint8_t *data, int data_size) @@ -223,10 +226,17 @@ static int davinci_write_block_data(struct nand_device_s *nand, target_t *target = info->target; uint32_t nfdata = info->data; uint32_t tmp; + int status; if (!halted(target, "write_block")) return ERROR_NAND_OPERATION_FAILED; + /* try the fast way first */ + status = arm_nandwrite(&info->io, data, data_size); + if (status != ERROR_NAND_NO_BUFFER) + return status; + + /* else do it slowly */ while (data_size >= 4) { tmp = le_to_h_u32(data); target_write_u32(target, nfdata, tmp); @@ -285,6 +295,12 @@ static int davinci_write_page(struct nand_device_s *nand, uint32_t page, memset(oob, 0x0ff, oob_size); } + /* REVISIT avoid wasting SRAM: unless nand->use_raw is set, + * use 512 byte chunks. Read side support will often want + * to include oob_size ... + */ + info->io.chunk_size = nand->page_size; + status = info->write_page(nand, page, data, data_size, oob, oob_size); free(ooballoc); return status; @@ -700,6 +716,9 @@ static int davinci_nand_device_command(struct command_context_s *cmd_ctx, nand->controller_priv = info; + info->io.target = target; + info->io.data = info->data; + /* NOTE: for now we don't do any error correction on read. * Nothing else in OpenOCD currently corrects read errors, * and in any case it's *writing* that we care most about. -- cgit v1.2.3