/* NAND flash controller
*/
extern nand_flash_controller_t lpc3180_nand_controller;
+extern nand_flash_controller_t orion_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;
nand_flash_controller_t *nand_flash_controllers[] =
{
&lpc3180_nand_controller,
+ &orion_nand_controller,
&s3c2410_nand_controller,
&s3c2412_nand_controller,
&s3c2440_nand_controller,
if (strcmp(args[0], nand_flash_controllers[i]->name) == 0)
{
/* register flash specific commands */
- if (nand_flash_controllers[i]->register_commands(cmd_ctx) != ERROR_OK)
+ if ((retval = nand_flash_controllers[i]->register_commands(cmd_ctx)) != ERROR_OK)
{
LOG_ERROR("couldn't register '%s' commands", args[0]);
- exit(-1);
+ return retval;
}
c = malloc(sizeof(nand_device_t));
register_command(cmd_ctx, nand_cmd, "dump", handle_nand_dump_command, COMMAND_EXEC,
"dump from NAND flash device <num> <filename> <offset> <size> [options]");
register_command(cmd_ctx, nand_cmd, "write", handle_nand_write_command, COMMAND_EXEC,
- "write to NAND flash device <num> <filename> <offset> [options]");
+ "write to NAND flash device <num> <filename> <offset> [oob_raw|oob_only]");
register_command(cmd_ctx, nand_cmd, "raw_access", handle_nand_raw_access_command, COMMAND_EXEC,
"raw access to NAND flash device <num> ['enable'|'disable']");
}
/* Send read status command */
device->controller->command(device, NAND_CMD_STATUS);
- usleep(1000);
+ alive_sleep(1);
/* read status */
if (device->device->options & NAND_BUSWIDTH_16)
return ERROR_OK;
}
+int nand_poll_ready(struct nand_device_s *device, int timeout)
+{
+ u8 status;
+
+ device->controller->command(device, NAND_CMD_STATUS);
+ do {
+ if (device->device->options & NAND_BUSWIDTH_16) {
+ u16 data;
+ device->controller->read_data(device, &data);
+ status = data & 0xff;
+ } else {
+ device->controller->read_data(device, &status);
+ }
+ if (status & NAND_STATUS_READY)
+ break;
+ alive_sleep(1);
+ } while (timeout--);
+
+ return (status & NAND_STATUS_READY) != 0;
+}
+
int nand_probe(struct nand_device_s *device)
{
u8 manufacturer_id, device_id;
- u8 id_buff[5];
+ u8 id_buff[6];
int retval;
int i;
device->address_cycles = 5;
else
{
- LOG_ERROR("BUG: small page NAND device with more than 32 GiB encountered");
+ LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered");
device->address_cycles = 6;
}
}
/* Send erase confirm command */
device->controller->command(device, NAND_CMD_ERASE2);
-
- if (!device->controller->nand_ready(device, 1000))
- {
+
+ retval = device->controller->nand_ready ?
+ device->controller->nand_ready(device, 1000) :
+ nand_poll_ready(device, 1000);
+ if (!retval) {
LOG_ERROR("timeout waiting for NAND flash block erase to complete");
return ERROR_NAND_OPERATION_TIMEOUT;
}
device->controller->command(device, NAND_CMD_READSTART);
}
- if (!device->controller->nand_ready(device, 100))
- return ERROR_NAND_OPERATION_TIMEOUT;
+ if (device->controller->nand_ready) {
+ if (!device->controller->nand_ready(device, 100))
+ return ERROR_NAND_OPERATION_TIMEOUT;
+ } else {
+ alive_sleep(1);
+ }
if (data)
{
* or 2048 for the beginning of OOB area)
*/
device->controller->address(device, 0x0);
- device->controller->address(device, 0x8);
+ if (data)
+ device->controller->address(device, 0x0);
+ else
+ device->controller->address(device, 0x8);
/* row */
device->controller->address(device, page & 0xff);
device->controller->command(device, NAND_CMD_PAGEPROG);
- if (!device->controller->nand_ready(device, 100))
+ retval = device->controller->nand_ready ?
+ device->controller->nand_ready(device, 100) :
+ nand_poll_ready(device, 100);
+ if (!retval)
return ERROR_NAND_OPERATION_TIMEOUT;
if ((retval = nand_read_status(device, &status)) != ERROR_OK)
u8 *oob = NULL;
u32 oob_size = 0;
- duration_start_measure(&duration);
offset = strtoul(args[2], NULL, 0);
if (argc > 3)
else
{
command_print(cmd_ctx, "unknown option: %s", args[i]);
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
}
}
+ duration_start_measure(&duration);
+
if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
{
return ERROR_OK;
oob = NULL;
page = NULL;
duration_stop_measure(&duration, &duration_text);
- command_print(cmd_ctx, "wrote file %s to NAND flash %s at offset 0x%8.8x in %s",
+ command_print(cmd_ctx, "wrote file %s to NAND flash %s up to offset 0x%8.8x in %s",
args[1], args[0], offset, duration_text);
free(duration_text);
duration_text = NULL;
return ERROR_OK;
}
-