This is an automated email from Gerrit. Adrien Destugues (pulkoma...@gmail.com) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/3734
-- gerrit commit 3983859853b20d01ceae0a91d7f64d605de83376 Author: Adrien Destugues <pulkoma...@gmail.com> Date: Tue Sep 13 17:14:52 2016 +0200 NAND: add command to get and set ONFI features The ONFI specification has GET_FEATURE and SET_FEATURE commands to get and set various parameters of NAND chips. This commit introduce a new command, "nand feature", to get and set those. This can be used to configure NAND chips in several ways. Some of the features are standardized, and other are manufacturer specific. Change-Id: I288130435f47b0fa6c0ce5f0a460cc4d4e524a48 Signed-off-by: Adrien Destugues <pulkoma...@gmail.com> diff --git a/doc/openocd.texi b/doc/openocd.texi index 8146654..811e3ef 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6413,6 +6413,15 @@ bypassing hardware ECC logic. with the wrong ECC data can cause them to be marked as bad. @end deffn +@deffn Command {nand feature} num address [value] +Manage NAND chip features + +If a value is given, set the feature at address to the given value. + +If no value is given, get the current value of the requested feature. + +@end deffn + @anchor{nanddriverlist} @subsection NAND Driver List As noted above, the @command{nand device} command allows diff --git a/src/flash/nand/core.c b/src/flash/nand/core.c index 7428d22..8471388 100644 --- a/src/flash/nand/core.c +++ b/src/flash/nand/core.c @@ -298,6 +298,83 @@ static int nand_poll_ready(struct nand_device *nand, int timeout) return (status & NAND_STATUS_READY) != 0; } +int nand_get_feature(struct nand_device *nand, uint8_t feature, uint32_t* value) +{ + int retval; + uint8_t byte; + int i; + + if (!nand->device) + return ERROR_NAND_DEVICE_NOT_PROBED; + + + /* Send "get feature" command */ + nand->controller->command(nand, NAND_CMD_GET_FEATURE); + + /* Send feature address */ + nand->controller->address(nand, feature); + + alive_sleep(1); + + retval = nand->controller->nand_ready ? + nand->controller->nand_ready(nand, 1000) : ERROR_OK; + if (!retval) { + LOG_ERROR("timeout waiting for NAND flash feature get to complete"); + return ERROR_NAND_OPERATION_TIMEOUT; + } + + alive_sleep(1); + + retval = ERROR_OK; + for (i = 0; retval == ERROR_OK && i < 4; i++) + { + retval = nand->controller->read_data(nand, &byte); + if (value != NULL) + { + *value = (*value >> 8) | (((uint32_t)byte) << 24); + } + } + + return ERROR_OK; +} + +int nand_set_feature(struct nand_device *nand, uint8_t feature, uint32_t value) +{ + int retval; + int i; + + if (!nand->device) + return ERROR_NAND_DEVICE_NOT_PROBED; + + + /* Send "get feature" command */ + nand->controller->command(nand, NAND_CMD_SET_FEATURE); + + /* Send feature address */ + nand->controller->address(nand, feature); + + alive_sleep(1); + + retval = ERROR_OK; + for (i = 0; retval == ERROR_OK && i < 4; i++) + { + retval = nand->controller->write_data(nand, value & 0xFF); + value >>= 8; + } + + alive_sleep(1); + + retval = nand->controller->nand_ready ? + nand->controller->nand_ready(nand, 1000) : + nand_poll_ready(nand, 1000); + if (!retval) { + LOG_ERROR("timeout waiting for NAND flash feature set to complete"); + return ERROR_NAND_OPERATION_TIMEOUT; + } + + return ERROR_OK; +} + int nand_probe(struct nand_device *nand) { uint8_t manufacturer_id, device_id; diff --git a/src/flash/nand/core.h b/src/flash/nand/core.h index 5bf9fb3..d542e36 100644 --- a/src/flash/nand/core.h +++ b/src/flash/nand/core.h @@ -160,6 +160,8 @@ enum { NAND_CMD_RNDIN = 0x85, NAND_CMD_READID = 0x90, NAND_CMD_ERASE2 = 0xd0, + NAND_CMD_GET_FEATURE = 0xee, + NAND_CMD_SET_FEATURE = 0xef, NAND_CMD_RESET = 0xff, /* Extended commands for large page devices */ @@ -209,6 +211,9 @@ int nand_write_page_raw(struct nand_device *nand, uint32_t page, int nand_read_status(struct nand_device *nand, uint8_t *status); +int nand_get_feature(struct nand_device *nand, uint8_t feature, uint32_t* value); +int nand_set_feature(struct nand_device *nand, uint8_t feature, uint32_t value); + int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ecc_code); int nand_calculate_ecc_kw(struct nand_device *nand, diff --git a/src/flash/nand/tcl.c b/src/flash/nand/tcl.c index cbdeda5..272190e 100644 --- a/src/flash/nand/tcl.c +++ b/src/flash/nand/tcl.c @@ -403,6 +403,39 @@ COMMAND_HANDLER(handle_nand_raw_access_command) return ERROR_OK; } +COMMAND_HANDLER(handle_nand_feature_command) +{ + if ((CMD_ARGC < 2) || (CMD_ARGC > 3)) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct nand_device *p; + int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); + if (ERROR_OK != retval) + return retval; + + if (NULL == p->device) { + command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]); + return ERROR_OK; + } + + uint8_t address; + uint32_t val; + + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], address); + + if (CMD_ARGC == 3) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], val); + retval = nand_set_feature(p, address, val); + } else { + val = 0; + retval = nand_get_feature(p, address, &val); + if (retval == ERROR_OK) + command_print(CMD_CTX, "#%s feature %d: %x", CMD_ARGV[0], address, val); + } + + return retval; +} + static const struct command_registration nand_exec_command_handlers[] = { { .name = "list", @@ -469,6 +502,13 @@ static const struct command_registration nand_exec_command_handlers[] = { .usage = "bank_id ['enable'|'disable']", .help = "raw access to NAND flash device", }, + { + .name = "feature", + .handler = handle_nand_feature_command, + .mode = COMMAND_EXEC, + .usage = "bank_id address [value]", + .help = "manage device features", + }, COMMAND_REGISTRATION_DONE }; -- ------------------------------------------------------------------------------ _______________________________________________ OpenOCD-devel mailing list OpenOCD-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openocd-devel