remove flash.h from tree
[fw/openocd] / src / flash / nand.c
index bc0e350556f9b8a4a6e646a856b7dd0c12292c5d..2f0f503fd431802d5208020f26e332e04f2a2401 100644 (file)
@@ -26,8 +26,8 @@
 
 #include "nand.h"
 #include "common.h"
-#include "time_support.h"
-#include "fileio.h"
+#include <helper/time_support.h>
+#include <helper/fileio.h>
 
 static int nand_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
 //static int nand_read_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size);
@@ -36,6 +36,7 @@ static int nand_write_page(struct nand_device *nand, uint32_t page, uint8_t *dat
 
 /* NAND flash controller
  */
+extern struct nand_flash_controller nonce_nand_controller;
 extern struct nand_flash_controller davinci_nand_controller;
 extern struct nand_flash_controller lpc3180_nand_controller;
 extern struct nand_flash_controller orion_nand_controller;
@@ -49,6 +50,7 @@ extern struct nand_flash_controller imx31_nand_flash_controller;
 
 static struct nand_flash_controller *nand_flash_controllers[] =
 {
+       &nonce_nand_controller,
        &davinci_nand_controller,
        &lpc3180_nand_controller,
        &orion_nand_controller,
@@ -214,11 +216,12 @@ COMMAND_HANDLER(handle_nand_list_drivers)
 static COMMAND_HELPER(create_nand_device, const char *bank_name,
                struct nand_flash_controller *controller)
 {
-       int retval = controller->register_commands(CMD_CTX);
-       if (ERROR_OK != retval)
+       if (NULL != controller->commands)
        {
-               LOG_ERROR("couldn't register '%s' commands", controller->name);
-               return retval;
+               int retval = register_commands(CMD_CTX, NULL,
+                               controller->commands);
+               if (ERROR_OK != retval)
+                       return retval;
        }
        struct nand_device *c = malloc(sizeof(struct nand_device));
 
@@ -233,7 +236,7 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
        c->use_raw = 0;
        c->next = NULL;
 
-       retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
+       int retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
        if (ERROR_OK != retval)
        {
                LOG_ERROR("'%s' driver rejected nand flash", controller->name);
@@ -278,6 +281,9 @@ COMMAND_HANDLER(handle_nand_device_command)
        return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
 }
 
+
+COMMAND_HANDLER(handle_nand_init_command);
+
 static const struct command_registration nand_config_command_handlers[] = {
        {
                .name = "device",
@@ -291,6 +297,12 @@ static const struct command_registration nand_config_command_handlers[] = {
                .mode = COMMAND_ANY,
                .help = "lists available NAND drivers",
        },
+       {
+               .name = "init",
+               .mode = COMMAND_CONFIG,
+               .handler = &handle_nand_init_command,
+               .help = "initialize NAND devices",
+       },
        COMMAND_REGISTRATION_DONE
 };
 static const struct command_registration nand_command_handlers[] = {
@@ -851,20 +863,19 @@ static int nand_read_page(struct nand_device *nand, uint32_t page, uint8_t *data
                return nand->controller->read_page(nand, page, data, data_size, oob, oob_size);
 }
 
-int nand_read_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_page_command(struct nand_device *nand, uint32_t page,
+               uint8_t cmd, bool oob_only)
 {
-       uint32_t i;
-
        if (!nand->device)
                return ERROR_NAND_DEVICE_NOT_PROBED;
 
-       if (nand->page_size <= 512)
-       {
+       if (oob_only && NAND_CMD_READ0 == cmd && nand->page_size <= 512)
+               cmd = NAND_CMD_READOOB;
+
+       nand->controller->command(nand, cmd);
+
+       if (nand->page_size <= 512) {
                /* small page device */
-               if (data)
-                       nand->controller->command(nand, NAND_CMD_READ0);
-               else
-                       nand->controller->command(nand, NAND_CMD_READOOB);
 
                /* column (always 0, we start at the beginning of a page/OOB area) */
                nand->controller->address(nand, 0x0);
@@ -880,20 +891,17 @@ int nand_read_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, u
                /* 5th cycle only on devices with more than 8 GiB */
                if (nand->address_cycles >= 5)
                        nand->controller->address(nand, (page >> 24) & 0xff);
-       }
-       else
-       {
+       } else {
                /* large page device */
-               nand->controller->command(nand, NAND_CMD_READ0);
 
                /* column (0 when we start at the beginning of a page,
                 * or 2048 for the beginning of OOB area)
                 */
                nand->controller->address(nand, 0x0);
-               if (data)
-                       nand->controller->address(nand, 0x0);
-               else
+               if (oob_only)
                        nand->controller->address(nand, 0x8);
+               else
+                       nand->controller->address(nand, 0x0);
 
                /* row */
                nand->controller->address(nand, page & 0xff);
@@ -903,8 +911,9 @@ int nand_read_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, u
                if (nand->address_cycles >= 5)
                        nand->controller->address(nand, (page >> 16) & 0xff);
 
-               /* large page devices need a start command */
-               nand->controller->command(nand, NAND_CMD_READSTART);
+               /* large page devices need a start command if reading */
+               if (NAND_CMD_READ0 == cmd)
+                       nand->controller->command(nand, NAND_CMD_READSTART);
        }
 
        if (nand->controller->nand_ready) {
@@ -914,6 +923,20 @@ int nand_read_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data, u
                alive_sleep(1);
        }
 
+       return ERROR_OK;
+}
+
+int nand_read_page_raw(struct nand_device *nand, uint32_t page,
+               uint8_t *data, uint32_t data_size,
+               uint8_t *oob, uint32_t oob_size)
+{
+       uint32_t i;
+       int retval;
+
+       retval = nand_page_command(nand, page, NAND_CMD_READ0, !data);
+       if (ERROR_OK != retval)
+               return retval;
+
        if (data)
        {
                if (nand->controller->read_block_data != NULL)
@@ -971,47 +994,9 @@ int nand_write_page_raw(struct nand_device *nand, uint32_t page, uint8_t *data,
        int retval;
        uint8_t status;
 
-       if (!nand->device)
-               return ERROR_NAND_DEVICE_NOT_PROBED;
-
-       nand->controller->command(nand, NAND_CMD_SEQIN);
-
-       if (nand->page_size <= 512)
-       {
-               /* column (always 0, we start at the beginning of a page/OOB area) */
-               nand->controller->address(nand, 0x0);
-
-               /* row */
-               nand->controller->address(nand, page & 0xff);
-               nand->controller->address(nand, (page >> 8) & 0xff);
-
-               /* 4th cycle only on devices with more than 32 MiB */
-               if (nand->address_cycles >= 4)
-                       nand->controller->address(nand, (page >> 16) & 0xff);
-
-               /* 5th cycle only on devices with more than 8 GiB */
-               if (nand->address_cycles >= 5)
-                       nand->controller->address(nand, (page >> 24) & 0xff);
-       }
-       else
-       {
-               /* column (0 when we start at the beginning of a page,
-                * or 2048 for the beginning of OOB area)
-                */
-               nand->controller->address(nand, 0x0);
-               if (data)
-                       nand->controller->address(nand, 0x0);
-               else
-                       nand->controller->address(nand, 0x8);
-
-               /* row */
-               nand->controller->address(nand, page & 0xff);
-               nand->controller->address(nand, (page >> 8) & 0xff);
-
-               /* 5th cycle only on devices with more than 128 MiB */
-               if (nand->address_cycles >= 5)
-                       nand->controller->address(nand, (page >> 16) & 0xff);
-       }
+       retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
+       if (ERROR_OK != retval)
+               return retval;
 
        if (data)
        {
@@ -1120,11 +1105,6 @@ COMMAND_HANDLER(handle_nand_info_command)
        int first = -1;
        int last = -1;
 
-       struct nand_device *p;
-       int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
-       if (ERROR_OK != retval)
-               return retval;
-
        switch (CMD_ARGC) {
        default:
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1143,6 +1123,11 @@ COMMAND_HANDLER(handle_nand_info_command)
                break;
        }
 
+       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]);
@@ -1791,3 +1776,20 @@ int nand_init(struct command_context *cmd_ctx)
        struct command *parent = command_find_in_context(cmd_ctx, "nand");
        return register_commands(cmd_ctx, parent, nand_exec_command_handlers);
 }
+
+COMMAND_HANDLER(handle_nand_init_command)
+{
+       if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       static bool nand_initialized = false;
+       if (nand_initialized)
+       {
+               LOG_INFO("'nand init' has already been called");
+               return ERROR_OK;
+       }
+       nand_initialized = true;
+
+       LOG_DEBUG("Initializing NAND devices...");
+       return nand_init(CMD_CTX);
+}