Nicolas Pitre nico at cam.org support for NAND flash used with Marvell Orion and...
[fw/openocd] / src / flash / nand.c
index c42291ba000c5e897bb0cb3b8e2fc39c8b046d6c..51755aa0015e124668911e247a62345810ed42a3 100644 (file)
@@ -61,6 +61,7 @@ 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 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;
@@ -71,6 +72,7 @@ extern nand_flash_controller_t s3c2443_nand_controller;
 nand_flash_controller_t *nand_flash_controllers[] =
 {
        &lpc3180_nand_controller,
+       &orion_nand_controller,
        &s3c2410_nand_controller,
        &s3c2412_nand_controller,
        &s3c2440_nand_controller,
@@ -287,7 +289,7 @@ int nand_init(struct command_context_s *cmd_ctx)
                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']");
        }
@@ -372,6 +374,27 @@ int nand_read_status(struct nand_device_s *device, u8 *status)
        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;
@@ -648,9 +671,11 @@ int nand_erase(struct nand_device_s *device, int first_block, int last_block)
                
                /* 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;
                }
@@ -823,8 +848,12 @@ int nand_read_page_raw(struct nand_device_s *device, u32 page, u8 *data, u32 dat
                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)
        {
@@ -977,7 +1006,10 @@ int nand_write_page_raw(struct nand_device_s *device, u32 page, u8 *data, u32 da
        
        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)
@@ -1254,7 +1286,6 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
                u8 *oob = NULL;
                u32 oob_size = 0;
                        
-               duration_start_measure(&duration);
                offset = strtoul(args[2], NULL, 0);
                
                if (argc > 3)
@@ -1269,10 +1300,13 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
                                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;