X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnand%2Fdavinci.c;h=e12fc46104692063c59aa70a1d150bb9f1a28a17;hp=72cd378a4da7fbd1b9bf331d77bc923a4a586d0c;hb=16b6b5e7a86353dbc0c4823fe3d772c0faca7c1c;hpb=e1ec02bb055fa356b058dddc0a15710e0fdc9870 diff --git a/src/flash/nand/davinci.c b/src/flash/nand/davinci.c index 72cd378a4d..e12fc46104 100644 --- a/src/flash/nand/davinci.c +++ b/src/flash/nand/davinci.c @@ -28,8 +28,9 @@ #include "config.h" #endif -#include "arm_nandio.h" - +#include "imp.h" +#include "arm_io.h" +#include enum ecc { HWECC1, /* all controllers support 1-bit ECC */ @@ -38,8 +39,6 @@ enum ecc { }; struct davinci_nand { - struct target *target; - uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */ uint8_t eccmode; @@ -81,7 +80,7 @@ static int halted(struct target *target, const char *label) static int davinci_init(struct nand_device *nand) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; uint32_t nandfcr; if (!halted(target, "init")) @@ -111,7 +110,7 @@ static int davinci_reset(struct nand_device *nand) static int davinci_nand_ready(struct nand_device *nand, int timeout) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; uint32_t nandfsr; /* NOTE: return code is zero/error, else success; not ERROR_* */ @@ -134,7 +133,7 @@ static int davinci_nand_ready(struct nand_device *nand, int timeout) static int davinci_command(struct nand_device *nand, uint8_t command) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; if (!halted(target, "command")) return ERROR_NAND_OPERATION_FAILED; @@ -146,7 +145,7 @@ static int davinci_command(struct nand_device *nand, uint8_t command) static int davinci_address(struct nand_device *nand, uint8_t address) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; if (!halted(target, "address")) return ERROR_NAND_OPERATION_FAILED; @@ -158,7 +157,7 @@ static int davinci_address(struct nand_device *nand, uint8_t address) static int davinci_write_data(struct nand_device *nand, uint16_t data) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; if (!halted(target, "write_data")) return ERROR_NAND_OPERATION_FAILED; @@ -170,7 +169,7 @@ static int davinci_write_data(struct nand_device *nand, uint16_t data) static int davinci_read_data(struct nand_device *nand, void *data) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; if (!halted(target, "read_data")) return ERROR_NAND_OPERATION_FAILED; @@ -185,7 +184,7 @@ static int davinci_read_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; uint32_t nfdata = info->data; uint32_t tmp; @@ -218,7 +217,7 @@ static int davinci_write_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; uint32_t nfdata = info->data; uint32_t tmp; int status; @@ -259,12 +258,12 @@ static int davinci_write_page(struct nand_device *nand, uint32_t page, if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; - if (!halted(info->target, "write_page")) + if (!halted(nand->target, "write_page")) return ERROR_NAND_OPERATION_FAILED; /* Always write both data and OOB ... we are not "raw" I/O! */ if (!data) { - LOG_ERROR("Missing NAND data; try 'nand raw_access enable'\n"); + LOG_ERROR("Missing NAND data; try 'nand raw_access enable'"); return ERROR_NAND_OPERATION_FAILED; } @@ -308,7 +307,7 @@ static int davinci_read_page(struct nand_device *nand, uint32_t page, if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; - if (!halted(info->target, "read_page")) + if (!halted(nand->target, "read_page")) return ERROR_NAND_OPERATION_FAILED; return info->read_page(nand, page, data, data_size, oob, oob_size); @@ -317,7 +316,7 @@ static int davinci_read_page(struct nand_device *nand, uint32_t page, static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_t page) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; int page3 = nand->address_cycles - (nand->page_size == 512); /* write command ({page,otp}x{read,program} */ @@ -337,11 +336,32 @@ static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_ target_write_u8(target, info->addr, page >> 24); } +static int davinci_seek_column(struct nand_device *nand, uint16_t column) +{ + struct davinci_nand *info = nand->controller_priv; + struct target *target = nand->target; + + /* Random read, we must have issued a page read already */ + target_write_u8(target, info->cmd, NAND_CMD_RNDOUT); + + target_write_u8(target, info->addr, column); + + if (nand->page_size > 512) { + target_write_u8(target, info->addr, column >> 8); + target_write_u8(target, info->cmd, NAND_CMD_RNDOUTSTART); + } + + if (!davinci_nand_ready(nand, 100)) + return ERROR_NAND_OPERATION_TIMEOUT; + + return ERROR_OK; +} + static int davinci_writepage_tail(struct nand_device *nand, uint8_t *oob, uint32_t oob_size) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; uint8_t status; if (oob_size) @@ -374,7 +394,7 @@ static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page, { unsigned oob_offset; struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; const uint32_t fcr_addr = info->aemif + NANDFCR; const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel); uint32_t fcr, ecc1; @@ -462,7 +482,7 @@ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page, struct davinci_nand *info = nand->controller_priv; const uint8_t *l; - struct target *target = info->target; + struct target *target = nand->target; const uint32_t fcr_addr = info->aemif + NANDFCR; const uint32_t ecc4_addr = info->aemif + NAND4BITECC; uint32_t fcr, ecc4; @@ -542,7 +562,7 @@ static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct davinci_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; const uint32_t fcr_addr = info->aemif + NANDFCR; const uint32_t ecc4_addr = info->aemif + NAND4BITECC; uint32_t fcr, ecc4; @@ -598,6 +618,10 @@ static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page, static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { + int read_size; + int want_col, at_col; + int ret; + davinci_write_pagecmd(nand, NAND_CMD_READ0, page); /* large page devices need a start command */ @@ -609,25 +633,49 @@ static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page, /* NOTE: not bothering to compute and use ECC data for now */ - do { - /* write 512 bytes */ - davinci_read_block_data(nand, data, 512); - data += 512; - data_size -= 512; - - /* read this "out-of-band" data -- infix */ - davinci_read_block_data(nand, oob, 16); - oob += 16; - oob_size -= 16; - } while (data_size); - + want_col = 0; + at_col = 0; + while ((data && data_size) || (oob && oob_size)) { + + if (data && data_size) { + if (want_col != at_col) { + /* Reads are slow, so seek past them when we can */ + ret = davinci_seek_column(nand, want_col); + if (ret != ERROR_OK) + return ret; + at_col = want_col; + } + /* read 512 bytes or data_size, whichever is smaller*/ + read_size = data_size > 512 ? 512 : data_size; + davinci_read_block_data(nand, data, read_size); + data += read_size; + data_size -= read_size; + at_col += read_size; + } + want_col += 512; + + if (oob && oob_size) { + if (want_col != at_col) { + ret = davinci_seek_column(nand, want_col); + if (ret != ERROR_OK) + return ret; + at_col = want_col; + } + /* read this "out-of-band" data -- infix */ + read_size = oob_size > 16 ? 16 : oob_size; + davinci_read_block_data(nand, oob, read_size); + oob += read_size; + oob_size -= read_size; + at_col += read_size; + } + want_col += 16; + } return ERROR_OK; } NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command) { struct davinci_nand *info; - struct target *target; unsigned long chip, aemif; enum ecc eccmode; int chipsel; @@ -641,16 +689,7 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command) * Plus someday, optionally, ALE and CLE masks. */ if (CMD_ARGC < 5) { - LOG_ERROR("parameters: %s target " - "chip_addr hwecc_mode aemif_addr", - CMD_ARGV[0]); - goto fail; - } - - target = get_target(CMD_ARGV[1]); - if (!target) { - LOG_ERROR("invalid target %s", CMD_ARGV[1]); - goto fail; + return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip); @@ -698,7 +737,6 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command) if (info == NULL) goto fail; - info->target = target; info->eccmode = eccmode; info->chipsel = chipsel; info->aemif = aemif; @@ -708,8 +746,9 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command) nand->controller_priv = info; - info->io.target = target; + info->io.target = nand->target; info->io.data = info->data; + info->io.op = ARM_NAND_NONE; /* NOTE: for now we don't do any error correction on read. * Nothing else in OpenOCD currently corrects read errors, @@ -741,6 +780,7 @@ fail: struct nand_flash_controller davinci_nand_controller = { .name = "davinci", + .usage = "chip_addr hwecc_mode aemif_addr", .nand_device_command = davinci_nand_device_command, .init = davinci_init, .reset = davinci_reset,