X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fflash%2Fnand%2Fcore.c;h=44b13ce1de85b09124528dca083b7019b133cc95;hb=34f70956ed31c2739d34bae23fa6ca620e5299f8;hp=1056696d9336cad5d739f2dfa9ea25a1499e1ba4;hpb=b8b4bb0745b63e03eec745ce0eb97bfa6e0792a1;p=openocd diff --git a/src/flash/nand/core.c b/src/flash/nand/core.c index 1056696d..44b13ce1 100644 --- a/src/flash/nand/core.c +++ b/src/flash/nand/core.c @@ -160,7 +160,14 @@ static struct nand_ecclayout nand_oob_8 = { }; #endif -struct nand_device *get_nand_device_by_name(const char *name) +/** + * Returns the flash bank specified by @a name, which matches the + * driver name and a suffix (option) specify the driver-specific + * bank number. The suffix consists of the '.' and the driver-specific + * bank number: when two davinci banks are defined, then 'davinci.1' refers + * to the second (e.g. DM355EVM). + */ +static struct nand_device *get_nand_device_by_name(const char *name) { unsigned requested = get_flash_name_index(name); unsigned found = 0; @@ -215,8 +222,9 @@ COMMAND_HELPER(nand_command_get_device, unsigned name_index, int nand_build_bbt(struct nand_device *nand, int first, int last) { - uint32_t page = 0x0; + uint32_t page; int i; + int pages_per_block = (nand->erase_size / nand->page_size); uint8_t oob[6]; if ((first < 0) || (first >= nand->num_blocks)) @@ -225,7 +233,8 @@ int nand_build_bbt(struct nand_device *nand, int first, int last) if ((last >= nand->num_blocks) || (last == -1)) last = nand->num_blocks - 1; - for (i = first; i < last; i++) + page = first * pages_per_block; + for (i = first; i <= last; i++) { nand_read_page(nand, page, NULL, 0, oob, 6); @@ -241,7 +250,7 @@ int nand_build_bbt(struct nand_device *nand, int first, int last) nand->blocks[i].is_bad = 0; } - page += (nand->erase_size / nand->page_size); + page += pages_per_block; } return ERROR_OK; @@ -521,7 +530,7 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block) if (!nand->device) return ERROR_NAND_DEVICE_NOT_PROBED; - if ((first_block < 0) || (last_block > nand->num_blocks)) + if ((first_block < 0) || (last_block >= nand->num_blocks)) return ERROR_INVALID_ARGUMENTS; /* make sure we know if a block is bad before erasing it */ @@ -675,7 +684,9 @@ static int nand_write_plain(struct nand_device *nand, uint32_t address, uint8_t } #endif -int nand_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) +int nand_write_page(struct nand_device *nand, uint32_t page, + uint8_t *data, uint32_t data_size, + uint8_t *oob, uint32_t oob_size) { uint32_t block; @@ -808,66 +819,41 @@ int nand_read_page_raw(struct nand_device *nand, uint32_t page, return ERROR_OK; } -int nand_write_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) +int nand_write_data_page(struct nand_device *nand, uint8_t *data, uint32_t size) { - uint32_t i; - int retval; - uint8_t status; + int retval = ERROR_NAND_NO_BUFFER; - retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data); - if (ERROR_OK != retval) - return retval; + if (nand->controller->write_block_data != NULL) + retval = (nand->controller->write_block_data)(nand, data, size); - if (data) - { - if (nand->controller->write_block_data != NULL) - (nand->controller->write_block_data)(nand, data, data_size); - else - { - for (i = 0; i < data_size;) - { - if (nand->device->options & NAND_BUSWIDTH_16) - { - uint16_t data_buf = le_to_h_u16(data); - nand->controller->write_data(nand, data_buf); - data += 2; - i += 2; - } - else - { - nand->controller->write_data(nand, *data); - data += 1; - i += 1; - } - } - } - } + if (ERROR_NAND_NO_BUFFER == retval) { + bool is16bit = nand->device->options & NAND_BUSWIDTH_16; + uint32_t incr = is16bit ? 2 : 1; + uint16_t write_data; + uint32_t i; - if (oob) - { - if (nand->controller->write_block_data != NULL) - (nand->controller->write_block_data)(nand, oob, oob_size); - else - { - for (i = 0; i < oob_size;) - { - if (nand->device->options & NAND_BUSWIDTH_16) - { - uint16_t oob_buf = le_to_h_u16(data); - nand->controller->write_data(nand, oob_buf); - oob += 2; - i += 2; - } - else - { - nand->controller->write_data(nand, *oob); - oob += 1; - i += 1; - } - } + for (i = 0; i < size; i += incr) { + if (is16bit) + write_data = le_to_h_u16(data); + else + write_data = *data; + + retval = nand->controller->write_data(nand, write_data); + if (ERROR_OK != retval) + break; + + data += incr; } } + return retval; +} + +int nand_write_finish(struct nand_device *nand) +{ + int retval; + uint8_t status; + nand->controller->command(nand, NAND_CMD_PAGEPROG); retval = nand->controller->nand_ready ? @@ -876,18 +862,47 @@ int nand_write_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, if (!retval) return ERROR_NAND_OPERATION_TIMEOUT; - if ((retval = nand_read_status(nand, &status)) != ERROR_OK) - { + retval = nand_read_status(nand, &status); + if (ERROR_OK != retval) { LOG_ERROR("couldn't read status"); return ERROR_NAND_OPERATION_FAILED; } - if (status & NAND_STATUS_FAIL) - { - LOG_ERROR("write operation didn't pass, status: 0x%2.2x", status); + if (status & NAND_STATUS_FAIL) { + LOG_ERROR("write operation didn't pass, status: 0x%2.2x", + status); return ERROR_NAND_OPERATION_FAILED; } return ERROR_OK; } +int nand_write_page_raw(struct nand_device *nand, uint32_t page, + uint8_t *data, uint32_t data_size, + uint8_t *oob, uint32_t oob_size) +{ + int retval; + + retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data); + if (ERROR_OK != retval) + return retval; + + if (data) { + retval = nand_write_data_page(nand, data, data_size); + if (ERROR_OK != retval) { + LOG_ERROR("Unable to write data to NAND device"); + return retval; + } + } + + if (oob) { + retval = nand_write_data_page(nand, oob, oob_size); + if (ERROR_OK != retval) { + LOG_ERROR("Unable to write OOB data to NAND device"); + return retval; + } + } + + return nand_write_finish(nand); +} +