#include "nand.h"
#include "common.h"
-#include "time_support.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_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
-/* 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;
-extern struct nand_flash_controller s3c2410_nand_controller;
-extern struct nand_flash_controller s3c2412_nand_controller;
-extern struct nand_flash_controller s3c2440_nand_controller;
-extern struct nand_flash_controller s3c2443_nand_controller;
-extern struct nand_flash_controller imx31_nand_flash_controller;
-
-/* extern struct nand_flash_controller boundary_scan_nand_controller; */
-
-static struct nand_flash_controller *nand_flash_controllers[] =
-{
- &nonce_nand_controller,
- &davinci_nand_controller,
- &lpc3180_nand_controller,
- &orion_nand_controller,
- &s3c2410_nand_controller,
- &s3c2412_nand_controller,
- &s3c2440_nand_controller,
- &s3c2443_nand_controller,
- &imx31_nand_flash_controller,
-/* &boundary_scan_nand_controller, */
- NULL
-};
-
/* configured NAND devices and NAND Flash command handler */
static struct nand_device *nand_devices = NULL;
.length = 38}}
};
+int nand_list_walker(struct nand_flash_controller *c, void *x)
+{
+ struct command_context *cmd_ctx = (struct command_context *)x;
+ command_print(cmd_ctx, " %s", c->name);
+ return ERROR_OK;
+}
COMMAND_HANDLER(handle_nand_list_drivers)
{
command_print(CMD_CTX, "Available NAND flash controller drivers:");
- for (unsigned i = 0; nand_flash_controllers[i]; i++)
- command_print(CMD_CTX, " %s", nand_flash_controllers[i]->name);
- return ERROR_OK;
+ return nand_driver_walk(&nand_list_walker, CMD_CTX);
}
static COMMAND_HELPER(create_nand_device, const char *bank_name,
CMD_ARGC--;
const char *driver_name = CMD_ARGV[0];
- for (unsigned i = 0; nand_flash_controllers[i]; i++)
+ struct nand_flash_controller *controller;
+ controller = nand_driver_find_by_name(CMD_ARGV[0]);
+ if (NULL == controller)
{
- struct nand_flash_controller *controller = nand_flash_controllers[i];
- if (strcmp(driver_name, controller->name) != 0)
- continue;
-
- return CALL_COMMAND_HANDLER(create_nand_device,
- bank_name, controller);
+ LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
+ return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
}
-
- LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
- return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
+ return CALL_COMMAND_HANDLER(create_nand_device, bank_name, controller);
}
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);
/* 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);
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) {
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)
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)
{