X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnand.c;h=92c7bc7ae52f199bbb768bb26e265441334668e2;hb=958f845f4b64448d72688c31f0c299de569961e6;hp=38a70749a4f2553662df8a352cdcc53b30e04026;hpb=237e894805dd757cc24029af1b4b1e824c51712b;p=openocd.git diff --git a/src/flash/nand.c b/src/flash/nand.c index 38a70749a4..92c7bc7ae5 100644 --- a/src/flash/nand.c +++ b/src/flash/nand.c @@ -3,7 +3,7 @@ * Dominic.Rath@gmx.de * * * * partially based on * - * drivers/mtd/nand_ids.c * + * drivers/mtd/nand_ids.c * * * * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) * * * @@ -31,6 +31,7 @@ #include #include +#include #include @@ -62,13 +63,20 @@ int nand_write_page(struct nand_device_s *device, u32 page, u8 *data, u32 data_s /* NAND flash controller */ extern nand_flash_controller_t lpc3180_nand_controller; -/* extern nand_flash_controller_t s3c2410_nand_controller; */ +extern nand_flash_controller_t s3c2410_nand_controller; +extern nand_flash_controller_t s3c2412_nand_controller; +extern nand_flash_controller_t s3c2440_nand_controller; +extern nand_flash_controller_t s3c2443_nand_controller; + /* extern nand_flash_controller_t boundary_scan_nand_controller; */ nand_flash_controller_t *nand_flash_controllers[] = { &lpc3180_nand_controller, -/* &s3c2410_nand_controller, */ + &s3c2410_nand_controller, + &s3c2412_nand_controller, + &s3c2440_nand_controller, + &s3c2443_nand_controller, /* &boundary_scan_nand_controller, */ NULL }; @@ -255,7 +263,7 @@ int handle_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, cha int nand_register_commands(struct command_context_s *cmd_ctx) { - nand_cmd = register_command(cmd_ctx, NULL, "nand", NULL, COMMAND_ANY, NULL); + nand_cmd = register_command(cmd_ctx, NULL, "nand", NULL, COMMAND_ANY, "NAND specific commands"); register_command(cmd_ctx, nand_cmd, "device", handle_nand_device_command, COMMAND_CONFIG, NULL); @@ -369,6 +377,7 @@ int nand_read_status(struct nand_device_s *device, u8 *status) int nand_probe(struct nand_device_s *device) { u8 manufacturer_id, device_id; + u8 id_buff[5]; int retval; int i; @@ -459,12 +468,36 @@ int nand_probe(struct nand_device_s *device) device->bus_width = 16; else device->bus_width = 8; + + /* Do we need extended device probe information? */ + if (device->device->page_size == 0 || + device->device->erase_size == 0) + { + if (device->bus_width == 8) + { + device->controller->read_data(device, id_buff+3); + device->controller->read_data(device, id_buff+4); + device->controller->read_data(device, id_buff+5); + } + else + { + u16 data_buf; + + device->controller->read_data(device, &data_buf); + id_buff[3] = data_buf; + + device->controller->read_data(device, &data_buf); + id_buff[4] = data_buf; + + device->controller->read_data(device, &data_buf); + id_buff[5] = data_buf >> 8; + } + } /* page size */ if (device->device->page_size == 0) { - /* TODO: support reading extended chip id to determine page size */ - return ERROR_NAND_OPERATION_FAILED; + device->page_size = 1 << (10 + (id_buff[4] & 3)); } else if (device->device->page_size == 256) { @@ -507,7 +540,20 @@ int nand_probe(struct nand_device_s *device) /* erase size */ if (device->device->erase_size == 0) { - /* TODO: support reading extended chip id to determine erase size */ + switch ((id_buff[4] >> 4) & 3) { + case 0: + device->erase_size = 64 << 10; + break; + case 1: + device->erase_size = 128 << 10; + break; + case 2: + device->erase_size = 256 << 10; + break; + case 3: + device->erase_size =512 << 10; + break; + } } else { @@ -706,7 +752,7 @@ int nand_write_page(struct nand_device_s *device, u32 page, u8 *data, u32 data_s if (!device->device) return ERROR_NAND_DEVICE_NOT_PROBED; - if (device->use_raw) + if (device->use_raw || device->controller->write_page == NULL) return nand_write_page_raw(device, page, data, data_size, oob, oob_size); else return device->controller->write_page(device, page, data, data_size, oob, oob_size); @@ -717,7 +763,7 @@ int nand_read_page(struct nand_device_s *device, u32 page, u8 *data, u32 data_si if (!device->device) return ERROR_NAND_DEVICE_NOT_PROBED; - if (device->use_raw) + if (device->use_raw || device->controller->read_page == NULL) return nand_read_page_raw(device, page, data, data_size, oob, oob_size); else return device->controller->read_page(device, page, data, data_size, oob, oob_size); @@ -781,38 +827,48 @@ int nand_read_page_raw(struct nand_device_s *device, u32 page, u8 *data, u32 dat if (data) { - for (i = 0; i < data_size;) + if (device->controller->read_block_data != NULL) + (device->controller->read_block_data)(device, data, data_size); + else { - if (device->device->options & NAND_BUSWIDTH_16) - { - device->controller->read_data(device, data); - data += 2; - i += 2; - } - else + for (i = 0; i < data_size;) { - device->controller->read_data(device, data); - data += 1; - i += 1; + if (device->device->options & NAND_BUSWIDTH_16) + { + device->controller->read_data(device, data); + data += 2; + i += 2; + } + else + { + device->controller->read_data(device, data); + data += 1; + i += 1; + } } } } if (oob) { - for (i = 0; i < oob_size;) + if (device->controller->read_block_data != NULL) + (device->controller->read_block_data)(device, oob, oob_size); + else { - if (device->device->options & NAND_BUSWIDTH_16) - { - device->controller->read_data(device, oob); - oob += 2; - i += 2; - } - else + for (i = 0; i < oob_size;) { - device->controller->read_data(device, oob); - oob += 1; - i += 1; + if (device->device->options & NAND_BUSWIDTH_16) + { + device->controller->read_data(device, oob); + oob += 2; + i += 2; + } + else + { + device->controller->read_data(device, oob); + oob += 1; + i += 1; + } } } } @@ -867,40 +923,50 @@ int nand_write_page_raw(struct nand_device_s *device, u32 page, u8 *data, u32 da if (data) { - for (i = 0; i < data_size;) + if (device->controller->write_block_data != NULL) + (device->controller->write_block_data)(device, data, data_size); + else { - if (device->device->options & NAND_BUSWIDTH_16) - { - u16 data_buf = le_to_h_u16(data); - device->controller->write_data(device, data_buf); - data += 2; - i += 2; - } - else + for (i = 0; i < data_size;) { - device->controller->write_data(device, *data); - data += 1; - i += 1; + if (device->device->options & NAND_BUSWIDTH_16) + { + u16 data_buf = le_to_h_u16(data); + device->controller->write_data(device, data_buf); + data += 2; + i += 2; + } + else + { + device->controller->write_data(device, *data); + data += 1; + i += 1; + } } } } if (oob) { - for (i = 0; i < oob_size;) + if (device->controller->write_block_data != NULL) + (device->controller->write_block_data)(device, oob, oob_size); + else { - if (device->device->options & NAND_BUSWIDTH_16) + for (i = 0; i < oob_size;) { - u16 oob_buf = le_to_h_u16(data); - device->controller->write_data(device, oob_buf); - oob += 2; - i += 2; - } - else - { - device->controller->write_data(device, *oob); - oob += 1; - i += 1; + if (device->device->options & NAND_BUSWIDTH_16) + { + u16 oob_buf = le_to_h_u16(data); + device->controller->write_data(device, oob_buf); + oob += 2; + i += 2; + } + else + { + device->controller->write_data(device, *oob); + oob += 1; + i += 1; + } } } } @@ -1164,8 +1230,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char u32 buf_cnt; enum oob_formats oob_format = NAND_OOB_NONE; - image_t image; - int image_type_identified = 0; + fileio_t fileio; duration_t duration; char *duration_text; @@ -1187,7 +1252,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char u32 oob_size = 0; duration_start_measure(&duration); - strtoul(args[2], NULL, 0); + offset = strtoul(args[2], NULL, 0); if (argc > 3) { @@ -1200,40 +1265,18 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY; else { - if (identify_image_type(&image.type, args[i]) == ERROR_OK) - { - image_type_identified = 1; - } - else - { - command_print(cmd_ctx, "unknown option: %s", args[i]); - } + command_print(cmd_ctx, "unknown option: %s", args[i]); } } } - /* if no image type option was encountered, set the default */ - if (!image_type_identified) + if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) { - - identify_image_type(&image.type, NULL); - image_type_identified = 1; - } - - image.base_address_set = 1; - image.base_address = strtoul(args[2], NULL, 0); - image.start_address_set = 0; - - if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK) - { - command_print(cmd_ctx, "flash write error: %s", image.error_str); + command_print(cmd_ctx, "file open error: %s", fileio.error_str); return ERROR_OK; } - /* the offset might have been overwritten by the image base address */ - offset = image.base_address; - - buf_cnt = binary_size = image.size; + buf_cnt = binary_size = fileio.size; if (!(oob_format & NAND_OOB_ONLY)) { @@ -1262,7 +1305,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char if (page) { - image_read(&image, page_size, page, &size_read); + fileio_read(&fileio, page_size, page, &size_read); buf_cnt -= size_read; if (size_read < page_size) { @@ -1272,7 +1315,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char if (oob) { - image_read(&image, oob_size, oob, &size_read); + fileio_read(&fileio, oob_size, oob, &size_read); buf_cnt -= size_read; if (size_read < oob_size) { @@ -1289,9 +1332,11 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char offset += page_size; } + fileio_close(&fileio); + duration_stop_measure(&duration, &duration_text); command_print(cmd_ctx, "wrote file %s to NAND flash %s at offset 0x%8.8x in %s", - args[1], args[0], image.base_address, duration_text); + args[1], args[0], offset, duration_text); free(duration_text); } else @@ -1408,7 +1453,7 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char fileio_close(&fileio); duration_stop_measure(&duration, &duration_text); - command_print(cmd_ctx, "dumped %lli byte in %s", fileio.size, duration_text); + command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text); free(duration_text); } else