build: cleanup src/flash/nand directory

Change-Id: I21bb466a35168cf04743f5baafac9fef50d01707
Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk>
Reviewed-on: http://openocd.zylin.com/419
Tested-by: jenkins
This commit is contained in:
Spencer Oliver 2012-01-31 11:07:53 +00:00
parent 1e9f8836a1
commit fab0dcd7e6
32 changed files with 2066 additions and 2361 deletions

View File

@ -30,7 +30,6 @@
#include <target/arm.h> #include <target/arm.h>
#include <target/algorithm.h> #include <target/algorithm.h>
/** /**
* Copies code to a working area. This will allocate room for the code plus the * Copies code to a working area. This will allocate room for the code plus the
* additional amount requested if the working area pointer is null. * additional amount requested if the working area pointer is null.
@ -44,8 +43,8 @@
* @return Success or failure of the operation * @return Success or failure of the operation
*/ */
static int arm_code_to_working_area(struct target *target, static int arm_code_to_working_area(struct target *target,
const uint32_t *code, unsigned code_size, const uint32_t *code, unsigned code_size,
unsigned additional, struct working_area **area) unsigned additional, struct working_area **area)
{ {
uint8_t code_buf[code_size]; uint8_t code_buf[code_size];
unsigned i; unsigned i;
@ -61,7 +60,7 @@ static int arm_code_to_working_area(struct target *target,
if (NULL == *area) { if (NULL == *area) {
retval = target_alloc_working_area(target, size, area); retval = target_alloc_working_area(target, size, area);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_DEBUG("%s: no %d byte buffer", __FUNCTION__, (int) size); LOG_DEBUG("%s: no %d byte buffer", __func__, (int) size);
return ERROR_NAND_NO_BUFFER; return ERROR_NAND_NO_BUFFER;
} }
} }
@ -95,13 +94,13 @@ static int arm_code_to_working_area(struct target *target,
*/ */
int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size) int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
{ {
struct target *target = nand->target; struct target *target = nand->target;
struct arm_algorithm algo; struct arm_algorithm algo;
struct arm *arm = target->arch_info; struct arm *arm = target->arch_info;
struct reg_param reg_params[3]; struct reg_param reg_params[3];
uint32_t target_buf; uint32_t target_buf;
uint32_t exit_var = 0; uint32_t exit_var = 0;
int retval; int retval;
/* Inputs: /* Inputs:
* r0 NAND data address (byte wide) * r0 NAND data address (byte wide)
@ -121,9 +120,8 @@ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
if (nand->op != ARM_NAND_WRITE || !nand->copy_area) { if (nand->op != ARM_NAND_WRITE || !nand->copy_area) {
retval = arm_code_to_working_area(target, code, sizeof(code), retval = arm_code_to_working_area(target, code, sizeof(code),
nand->chunk_size, &nand->copy_area); nand->chunk_size, &nand->copy_area);
if (retval != ERROR_OK) { if (retval != ERROR_OK)
return retval; return retval;
}
} }
nand->op = ARM_NAND_WRITE; nand->op = ARM_NAND_WRITE;
@ -206,9 +204,8 @@ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size)
if (nand->op != ARM_NAND_READ || !nand->copy_area) { if (nand->op != ARM_NAND_READ || !nand->copy_area) {
retval = arm_code_to_working_area(target, code, sizeof(code), retval = arm_code_to_working_area(target, code, sizeof(code),
nand->chunk_size, &nand->copy_area); nand->chunk_size, &nand->copy_area);
if (retval != ERROR_OK) { if (retval != ERROR_OK)
return retval; return retval;
}
} }
nand->op = ARM_NAND_READ; nand->op = ARM_NAND_READ;
@ -246,4 +243,3 @@ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size)
return retval; return retval;
} }

View File

@ -23,9 +23,9 @@
* Available operational states the arm_nand_data struct can be in. * Available operational states the arm_nand_data struct can be in.
*/ */
enum arm_nand_op { enum arm_nand_op {
ARM_NAND_NONE, /**< No operation performed. */ ARM_NAND_NONE, /**< No operation performed. */
ARM_NAND_READ, /**< Read operation performed. */ ARM_NAND_READ, /**< Read operation performed. */
ARM_NAND_WRITE, /**< Write operation performed. */ ARM_NAND_WRITE, /**< Write operation performed. */
}; };
/** /**
@ -37,7 +37,7 @@ struct arm_nand_data {
struct target *target; struct target *target;
/** The copy area holds code loop and data for I/O operations. */ /** The copy area holds code loop and data for I/O operations. */
struct working_area *copy_area; struct working_area *copy_area;
/** The chunk size is the page size or ECC chunk. */ /** The chunk size is the page size or ECC chunk. */
unsigned chunk_size; unsigned chunk_size;
@ -54,4 +54,4 @@ struct arm_nand_data {
int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size); int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size);
int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size); int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size);
#endif /* __ARM_NANDIO_H */ #endif /* __ARM_NANDIO_H */

View File

@ -17,6 +17,7 @@
* Free Software Foundation, Inc., * Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -26,13 +27,13 @@
#include "imp.h" #include "imp.h"
#include "arm_io.h" #include "arm_io.h"
#define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */ #define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */
#define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */ #define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */
#define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */ #define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */
#define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */ #define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */
#define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */ #define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */
#define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */ #define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */
#define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */ #define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */
/** /**
* Representation of a pin on an AT91SAM9 chip. * Representation of a pin on an AT91SAM9 chip.
@ -97,9 +98,8 @@ static int at91sam9_init(struct nand_device *nand)
{ {
struct target *target = nand->target; struct target *target = nand->target;
if (!at91sam9_halted(target, "init")) { if (!at91sam9_halted(target, "init"))
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
}
return ERROR_OK; return ERROR_OK;
} }
@ -144,9 +144,8 @@ static int at91sam9_command(struct nand_device *nand, uint8_t command)
struct at91sam9_nand *info = nand->controller_priv; struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
if (!at91sam9_halted(target, "command")) { if (!at91sam9_halted(target, "command"))
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
}
at91sam9_enable(nand); at91sam9_enable(nand);
@ -161,9 +160,8 @@ static int at91sam9_command(struct nand_device *nand, uint8_t command)
*/ */
static int at91sam9_reset(struct nand_device *nand) static int at91sam9_reset(struct nand_device *nand)
{ {
if (!at91sam9_halted(nand->target, "reset")) { if (!at91sam9_halted(nand->target, "reset"))
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
}
return at91sam9_disable(nand); return at91sam9_disable(nand);
} }
@ -180,9 +178,8 @@ static int at91sam9_address(struct nand_device *nand, uint8_t address)
struct at91sam9_nand *info = nand->controller_priv; struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
if (!at91sam9_halted(nand->target, "address")) { if (!at91sam9_halted(nand->target, "address"))
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
}
return target_write_u8(target, info->addr, address); return target_write_u8(target, info->addr, address);
} }
@ -200,9 +197,8 @@ static int at91sam9_read_data(struct nand_device *nand, void *data)
struct at91sam9_nand *info = nand->controller_priv; struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
if (!at91sam9_halted(nand->target, "read data")) { if (!at91sam9_halted(nand->target, "read data"))
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
}
return target_read_u8(target, info->data, data); return target_read_u8(target, info->data, data);
} }
@ -220,9 +216,8 @@ static int at91sam9_write_data(struct nand_device *nand, uint16_t data)
struct at91sam9_nand *info = nand->controller_priv; struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
if (!at91sam9_halted(target, "write data")) { if (!at91sam9_halted(target, "write data"))
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
}
return target_write_u8(target, info->data, data); return target_write_u8(target, info->data, data);
} }
@ -240,16 +235,14 @@ static int at91sam9_nand_ready(struct nand_device *nand, int timeout)
struct target *target = nand->target; struct target *target = nand->target;
uint32_t status; uint32_t status;
if (!at91sam9_halted(target, "nand ready")) { if (!at91sam9_halted(target, "nand ready"))
return 0; return 0;
}
do { do {
target_read_u32(target, info->busy.pioc + AT91C_PIOx_PDSR, &status); target_read_u32(target, info->busy.pioc + AT91C_PIOx_PDSR, &status);
if (status & (1 << info->busy.num)) { if (status & (1 << info->busy.num))
return 1; return 1;
}
alive_sleep(1); alive_sleep(1);
} while (timeout-- > 0); } while (timeout-- > 0);
@ -272,9 +265,8 @@ static int at91sam9_read_block_data(struct nand_device *nand, uint8_t *data, int
struct arm_nand_data *io = &info->io; struct arm_nand_data *io = &info->io;
int status; int status;
if (!at91sam9_halted(nand->target, "read block")) { if (!at91sam9_halted(nand->target, "read block"))
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
}
io->chunk_size = nand->page_size; io->chunk_size = nand->page_size;
status = arm_nandread(io, data, size); status = arm_nandread(io, data, size);
@ -297,9 +289,8 @@ static int at91sam9_write_block_data(struct nand_device *nand, uint8_t *data, in
struct arm_nand_data *io = &info->io; struct arm_nand_data *io = &info->io;
int status; int status;
if (!at91sam9_halted(nand->target, "write block")) { if (!at91sam9_halted(nand->target, "write block"))
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
}
io->chunk_size = nand->page_size; io->chunk_size = nand->page_size;
status = arm_nandwrite(io, data, size); status = arm_nandwrite(io, data, size);
@ -321,7 +312,7 @@ static int at91sam9_ecc_init(struct target *target, struct at91sam9_nand *info)
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
// reset ECC parity registers /* reset ECC parity registers */
return target_write_u32(target, info->ecc + AT91C_ECCx_CR, 1); return target_write_u32(target, info->ecc + AT91C_ECCx_CR, 1);
} }
@ -335,15 +326,14 @@ static int at91sam9_ecc_init(struct target *target, struct at91sam9_nand *info)
* @param size Size of the OOB. * @param size Size of the OOB.
* @return Pointer to an area to store OOB data. * @return Pointer to an area to store OOB data.
*/ */
static uint8_t * at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint32_t *size) static uint8_t *at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint32_t *size)
{ {
if (!oob) { if (!oob) {
// user doesn't want OOB, allocate it /* user doesn't want OOB, allocate it */
if (nand->page_size == 512) { if (nand->page_size == 512)
*size = 16; *size = 16;
} else if (nand->page_size == 2048) { else if (nand->page_size == 2048)
*size = 64; *size = 64;
}
oob = malloc(*size); oob = malloc(*size);
if (!oob) { if (!oob) {
@ -371,7 +361,7 @@ static uint8_t * at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint3
* @return Success or failure of reading the NAND page. * @return Success or failure of reading the NAND page.
*/ */
static int at91sam9_read_page(struct nand_device *nand, uint32_t page, static int at91sam9_read_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{ {
int retval; int retval;
struct at91sam9_nand *info = nand->controller_priv; struct at91sam9_nand *info = nand->controller_priv;
@ -380,20 +370,17 @@ static int at91sam9_read_page(struct nand_device *nand, uint32_t page,
uint32_t status; uint32_t status;
retval = at91sam9_ecc_init(target, info); retval = at91sam9_ecc_init(target, info);
if (ERROR_OK != retval) { if (ERROR_OK != retval)
return retval; return retval;
}
retval = nand_page_command(nand, page, NAND_CMD_READ0, !data); retval = nand_page_command(nand, page, NAND_CMD_READ0, !data);
if (ERROR_OK != retval) { if (ERROR_OK != retval)
return retval; return retval;
}
if (data) { if (data) {
retval = nand_read_data_page(nand, data, data_size); retval = nand_read_data_page(nand, data, data_size);
if (ERROR_OK != retval) { if (ERROR_OK != retval)
return retval; return retval;
}
} }
oob_data = at91sam9_oob_init(nand, oob, &oob_size); oob_data = at91sam9_oob_init(nand, oob, &oob_size);
@ -402,33 +389,33 @@ static int at91sam9_read_page(struct nand_device *nand, uint32_t page,
target_read_u32(target, info->ecc + AT91C_ECCx_SR, &status); target_read_u32(target, info->ecc + AT91C_ECCx_SR, &status);
if (status & 1) { if (status & 1) {
LOG_ERROR("Error detected!"); LOG_ERROR("Error detected!");
if (status & 4) { if (status & 4)
LOG_ERROR("Multiple errors encountered; unrecoverable!"); LOG_ERROR("Multiple errors encountered; unrecoverable!");
} else { else {
// attempt recovery /* attempt recovery */
uint32_t parity; uint32_t parity;
target_read_u32(target, target_read_u32(target,
info->ecc + AT91C_ECCx_PR, info->ecc + AT91C_ECCx_PR,
&parity); &parity);
uint32_t word = (parity & 0x0000FFF0) >> 4; uint32_t word = (parity & 0x0000FFF0) >> 4;
uint32_t bit = parity & 0x0F; uint32_t bit = parity & 0x0F;
data[word] ^= (0x1) << bit; data[word] ^= (0x1) << bit;
LOG_INFO("Data word %d, bit %d corrected.", LOG_INFO("Data word %d, bit %d corrected.",
(unsigned) word, (unsigned) word,
(unsigned) bit); (unsigned) bit);
} }
} }
if (status & 2) { if (status & 2) {
// we could write back correct ECC data /* we could write back correct ECC data */
LOG_ERROR("Error in ECC bytes detected"); LOG_ERROR("Error in ECC bytes detected");
} }
} }
if (!oob) { if (!oob) {
// if it wasn't asked for, free it /* if it wasn't asked for, free it */
free(oob_data); free(oob_data);
} }
@ -449,7 +436,7 @@ static int at91sam9_read_page(struct nand_device *nand, uint32_t page,
* @return Success or failure of the page write. * @return Success or failure of the page write.
*/ */
static int at91sam9_write_page(struct nand_device *nand, uint32_t page, static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{ {
struct at91sam9_nand *info = nand->controller_priv; struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -458,14 +445,12 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
uint32_t parity, nparity; uint32_t parity, nparity;
retval = at91sam9_ecc_init(target, info); retval = at91sam9_ecc_init(target, info);
if (ERROR_OK != retval) { if (ERROR_OK != retval)
return retval; return retval;
}
retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data); retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
if (ERROR_OK != retval) { if (ERROR_OK != retval)
return retval; return retval;
}
if (data) { if (data) {
retval = nand_write_data_page(nand, data, data_size); retval = nand_write_data_page(nand, data, data_size);
@ -478,7 +463,7 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
oob_data = at91sam9_oob_init(nand, oob, &oob_size); oob_data = at91sam9_oob_init(nand, oob, &oob_size);
if (!oob) { if (!oob) {
// no OOB given, so read in the ECC parity from the ECC controller /* no OOB given, so read in the ECC parity from the ECC controller */
target_read_u32(target, info->ecc + AT91C_ECCx_PR, &parity); target_read_u32(target, info->ecc + AT91C_ECCx_PR, &parity);
target_read_u32(target, info->ecc + AT91C_ECCx_NPR, &nparity); target_read_u32(target, info->ecc + AT91C_ECCx_NPR, &nparity);
@ -490,9 +475,8 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
retval = nand_write_data_page(nand, oob_data, oob_size); retval = nand_write_data_page(nand, oob_data, oob_size);
if (!oob) { if (!oob)
free(oob_data); free(oob_data);
}
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Unable to write OOB data to NAND"); LOG_ERROR("Unable to write OOB data to NAND");
@ -594,9 +578,8 @@ COMMAND_HANDLER(handle_at91sam9_ale_command)
struct at91sam9_nand *info = NULL; struct at91sam9_nand *info = NULL;
unsigned num, address_line; unsigned num, address_line;
if (CMD_ARGC != 2) { if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
nand = get_nand_device_by_num(num); nand = get_nand_device_by_num(num);
@ -623,9 +606,8 @@ COMMAND_HANDLER(handle_at91sam9_rdy_busy_command)
struct at91sam9_nand *info = NULL; struct at91sam9_nand *info = NULL;
unsigned num, base_pioc, pin_num; unsigned num, base_pioc, pin_num;
if (CMD_ARGC != 3) { if (CMD_ARGC != 3)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
nand = get_nand_device_by_num(num); nand = get_nand_device_by_num(num);
@ -655,9 +637,8 @@ COMMAND_HANDLER(handle_at91sam9_ce_command)
struct at91sam9_nand *info = NULL; struct at91sam9_nand *info = NULL;
unsigned num, base_pioc, pin_num; unsigned num, base_pioc, pin_num;
if (CMD_ARGC != 3) { if (CMD_ARGC != 3)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
nand = get_nand_device_by_num(num); nand = get_nand_device_by_num(num);

View File

@ -20,6 +20,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -27,13 +28,14 @@
#include "imp.h" #include "imp.h"
/* configured NAND devices and NAND Flash command handler */ /* configured NAND devices and NAND Flash command handler */
struct nand_device *nand_devices = NULL; struct nand_device *nand_devices;
void nand_device_add(struct nand_device *c) void nand_device_add(struct nand_device *c)
{ {
if (nand_devices) { if (nand_devices) {
struct nand_device *p = nand_devices; struct nand_device *p = nand_devices;
while (p && p->next) p = p->next; while (p && p->next)
p = p->next;
p->next = c; p->next = c;
} else } else
nand_devices = c; nand_devices = c;
@ -50,94 +52,94 @@ void nand_device_add(struct nand_device *c)
* 256 256 Byte page size * 256 256 Byte page size
* 512 512 Byte page size * 512 512 Byte page size
*/ */
static struct nand_info nand_flash_ids[] = static struct nand_info nand_flash_ids[] = {
{
/* Vendor Specific Entries */ /* Vendor Specific Entries */
{ NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS, "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"}, { NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS,
{ NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS, "K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"}, "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"},
{ NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS,
"K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"},
/* start "museum" IDs */ /* start "museum" IDs */
{ 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"}, { 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"},
{ 0x0, 0x64, 256, 2, 0x1000, 0, "NAND 2MiB 5V 8-bit"}, { 0x0, 0x64, 256, 2, 0x1000, 0, "NAND 2MiB 5V 8-bit"},
{ 0x0, 0x6b, 512, 4, 0x2000, 0, "NAND 4MiB 5V 8-bit"}, { 0x0, 0x6b, 512, 4, 0x2000, 0, "NAND 4MiB 5V 8-bit"},
{ 0x0, 0xe8, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"}, { 0x0, 0xe8, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
{ 0x0, 0xec, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"}, { 0x0, 0xec, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
{ 0x0, 0xea, 256, 2, 0x1000, 0, "NAND 2MiB 3.3V 8-bit"}, { 0x0, 0xea, 256, 2, 0x1000, 0, "NAND 2MiB 3.3V 8-bit"},
{ 0x0, 0xd5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"}, { 0x0, 0xd5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
{ 0x0, 0xe3, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"}, { 0x0, 0xe3, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
{ 0x0, 0xe5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"}, { 0x0, 0xe5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
{ 0x0, 0xd6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"}, { 0x0, 0xd6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
{ 0x0, 0x39, 512, 8, 0x2000, 0, "NAND 8MiB 1.8V 8-bit"}, { 0x0, 0x39, 512, 8, 0x2000, 0, "NAND 8MiB 1.8V 8-bit"},
{ 0x0, 0xe6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"}, { 0x0, 0xe6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
{ 0x0, 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 1.8V 16-bit"}, { 0x0, 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 1.8V 16-bit"},
{ 0x0, 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 3.3V 16-bit"}, { 0x0, 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 3.3V 16-bit"},
/* end "museum" IDs */ /* end "museum" IDs */
{ 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"}, { 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"},
{ 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"}, { 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"},
{ 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16,"NAND 16MiB 1.8V 16-bit"}, { 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 1.8V 16-bit"},
{ 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16,"NAND 16MiB 3.3V 16-bit"}, { 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 3.3V 16-bit"},
{ 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"}, { 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"},
{ 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"}, { 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"},
{ 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16,"NAND 32MiB 1.8V 16-bit"}, { 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 1.8V 16-bit"},
{ 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16,"NAND 32MiB 3.3V 16-bit"}, { 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 3.3V 16-bit"},
{ 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"}, { 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"},
{ 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"}, { 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"},
{ 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16,"NAND 64MiB 1.8V 16-bit"}, { 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 1.8V 16-bit"},
{ 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16,"NAND 64MiB 3.3V 16-bit"}, { 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 3.3V 16-bit"},
{ 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"}, { 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
{ 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"}, { 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
{ 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"}, { 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"},
{ 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 1.8V 16-bit"}, { 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"},
{ 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 1.8V 16-bit"}, { 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"},
{ 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3.3V 16-bit"}, { 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"},
{ 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3.3V 16-bit"}, { 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"},
{ 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"}, { 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"},
{ 0x0, 0xA2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 1.8V 8-bit"}, { 0x0, 0xA2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 1.8V 8-bit"},
{ 0x0, 0xF2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 3.3V 8-bit"}, { 0x0, 0xF2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 3.3V 8-bit"},
{ 0x0, 0xB2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 1.8V 16-bit"}, { 0x0, 0xB2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 1.8V 16-bit"},
{ 0x0, 0xC2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 3.3V 16-bit"}, { 0x0, 0xC2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 3.3V 16-bit"},
{ 0x0, 0xA1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 1.8V 8-bit"}, { 0x0, 0xA1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 1.8V 8-bit"},
{ 0x0, 0xF1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 3.3V 8-bit"}, { 0x0, 0xF1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 3.3V 8-bit"},
{ 0x0, 0xB1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 1.8V 16-bit"}, { 0x0, 0xB1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 1.8V 16-bit"},
{ 0x0, 0xC1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 3.3V 16-bit"}, { 0x0, 0xC1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 3.3V 16-bit"},
{ 0x0, 0xAA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 1.8V 8-bit"}, { 0x0, 0xAA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 1.8V 8-bit"},
{ 0x0, 0xDA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 3.3V 8-bit"}, { 0x0, 0xDA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 3.3V 8-bit"},
{ 0x0, 0xBA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 1.8V 16-bit"}, { 0x0, 0xBA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 1.8V 16-bit"},
{ 0x0, 0xCA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 3.3V 16-bit"}, { 0x0, 0xCA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 3.3V 16-bit"},
{ 0x0, 0xAC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 1.8V 8-bit"}, { 0x0, 0xAC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 1.8V 8-bit"},
{ 0x0, 0xDC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 3.3V 8-bit"}, { 0x0, 0xDC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 3.3V 8-bit"},
{ 0x0, 0xBC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 1.8V 16-bit"}, { 0x0, 0xBC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 1.8V 16-bit"},
{ 0x0, 0xCC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 3.3V 16-bit"}, { 0x0, 0xCC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 3.3V 16-bit"},
{ 0x0, 0xA3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 1.8V 8-bit"}, { 0x0, 0xA3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 1.8V 8-bit"},
{ 0x0, 0xD3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 3.3V 8-bit"}, { 0x0, 0xD3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 3.3V 8-bit"},
{ 0x0, 0xB3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 1.8V 16-bit"}, { 0x0, 0xB3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 1.8V 16-bit"},
{ 0x0, 0xC3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 3.3V 16-bit"}, { 0x0, 0xC3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 3.3V 16-bit"},
{ 0x0, 0xA5, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 1.8V 8-bit"}, { 0x0, 0xA5, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 1.8V 8-bit"},
{ 0x0, 0xD5, 0, 8192, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"}, { 0x0, 0xD5, 0, 8192, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
{ 0x0, 0xB5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 1.8V 16-bit"}, { 0x0, 0xB5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 1.8V 16-bit"},
{ 0x0, 0xC5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 3.3V 16-bit"}, { 0x0, 0xC5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 3.3V 16-bit"},
{ 0x0, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"}, { 0x0, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
{0, 0, 0, 0, 0, 0, NULL} {0, 0, 0, 0, 0, 0, NULL}
}; };
/* Manufacturer ID list /* Manufacturer ID list
*/ */
static struct nand_manufacturer nand_manuf_ids[] = static struct nand_manufacturer nand_manuf_ids[] = {
{
{0x0, "unknown"}, {0x0, "unknown"},
{NAND_MFR_TOSHIBA, "Toshiba"}, {NAND_MFR_TOSHIBA, "Toshiba"},
{NAND_MFR_SAMSUNG, "Samsung"}, {NAND_MFR_SAMSUNG, "Samsung"},
@ -162,7 +164,8 @@ static struct nand_ecclayout nand_oob_8 = {
{.offset = 3, {.offset = 3,
.length = 2}, .length = 2},
{.offset = 6, {.offset = 6,
.length = 2}} .length = 2}
}
}; };
#endif #endif
@ -179,8 +182,7 @@ static struct nand_device *get_nand_device_by_name(const char *name)
unsigned found = 0; unsigned found = 0;
struct nand_device *nand; struct nand_device *nand;
for (nand = nand_devices; NULL != nand; nand = nand->next) for (nand = nand_devices; NULL != nand; nand = nand->next) {
{
if (strcmp(nand->name, name) == 0) if (strcmp(nand->name, name) == 0)
return nand; return nand;
if (!flash_driver_name_matches(nand->controller->name, name)) if (!flash_driver_name_matches(nand->controller->name, name))
@ -197,19 +199,16 @@ struct nand_device *get_nand_device_by_num(int num)
struct nand_device *p; struct nand_device *p;
int i = 0; int i = 0;
for (p = nand_devices; p; p = p->next) for (p = nand_devices; p; p = p->next) {
{
if (i++ == num) if (i++ == num)
{
return p; return p;
}
} }
return NULL; return NULL;
} }
COMMAND_HELPER(nand_command_get_device, unsigned name_index, COMMAND_HELPER(nand_command_get_device, unsigned name_index,
struct nand_device **nand) struct nand_device **nand)
{ {
const char *str = CMD_ARGV[name_index]; const char *str = CMD_ARGV[name_index];
*nand = get_nand_device_by_name(str); *nand = get_nand_device_by_name(str);
@ -241,23 +240,18 @@ int nand_build_bbt(struct nand_device *nand, int first, int last)
last = nand->num_blocks - 1; last = nand->num_blocks - 1;
page = first * pages_per_block; page = first * pages_per_block;
for (i = first; i <= last; i++) for (i = first; i <= last; i++) {
{
ret = nand_read_page(nand, page, NULL, 0, oob, 6); ret = nand_read_page(nand, page, NULL, 0, oob, 6);
if (ret != ERROR_OK) if (ret != ERROR_OK)
return ret; return ret;
if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff)) if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff))
|| (((nand->page_size == 512) && (oob[5] != 0xff)) || || (((nand->page_size == 512) && (oob[5] != 0xff)) ||
((nand->page_size == 2048) && (oob[0] != 0xff)))) ((nand->page_size == 2048) && (oob[0] != 0xff)))) {
{
LOG_WARNING("bad block: %i", i); LOG_WARNING("bad block: %i", i);
nand->blocks[i].is_bad = 1; nand->blocks[i].is_bad = 1;
} } else
else
{
nand->blocks[i].is_bad = 0; nand->blocks[i].is_bad = 0;
}
page += pages_per_block; page += pages_per_block;
} }
@ -276,16 +270,12 @@ int nand_read_status(struct nand_device *nand, uint8_t *status)
alive_sleep(1); alive_sleep(1);
/* read status */ /* read status */
if (nand->device->options & NAND_BUSWIDTH_16) if (nand->device->options & NAND_BUSWIDTH_16) {
{
uint16_t data; uint16_t data;
nand->controller->read_data(nand, &data); nand->controller->read_data(nand, &data);
*status = data & 0xff; *status = data & 0xff;
} } else
else
{
nand->controller->read_data(nand, status); nand->controller->read_data(nand, status);
}
return ERROR_OK; return ERROR_OK;
} }
@ -300,9 +290,8 @@ static int nand_poll_ready(struct nand_device *nand, int timeout)
uint16_t data; uint16_t data;
nand->controller->read_data(nand, &data); nand->controller->read_data(nand, &data);
status = data & 0xff; status = data & 0xff;
} else { } else
nand->controller->read_data(nand, &status); nand->controller->read_data(nand, &status);
}
if (status & NAND_STATUS_READY) if (status & NAND_STATUS_READY)
break; break;
alive_sleep(1); alive_sleep(1);
@ -329,15 +318,15 @@ int nand_probe(struct nand_device *nand)
nand->erase_size = 0; nand->erase_size = 0;
/* initialize controller (device parameters are zero, use controller default) */ /* initialize controller (device parameters are zero, use controller default) */
if ((retval = nand->controller->init(nand) != ERROR_OK)) retval = nand->controller->init(nand);
{ if (retval != ERROR_OK) {
switch (retval) switch (retval) {
{
case ERROR_NAND_OPERATION_FAILED: case ERROR_NAND_OPERATION_FAILED:
LOG_DEBUG("controller initialization failed"); LOG_DEBUG("controller initialization failed");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
case ERROR_NAND_OPERATION_NOT_SUPPORTED: case ERROR_NAND_OPERATION_NOT_SUPPORTED:
LOG_ERROR("BUG: controller reported that it doesn't support default parameters"); LOG_ERROR(
"BUG: controller reported that it doesn't support default parameters");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
default: default:
LOG_ERROR("BUG: unknown controller initialization failure"); LOG_ERROR("BUG: unknown controller initialization failure");
@ -351,13 +340,10 @@ int nand_probe(struct nand_device *nand)
nand->controller->command(nand, NAND_CMD_READID); nand->controller->command(nand, NAND_CMD_READID);
nand->controller->address(nand, 0x0); nand->controller->address(nand, 0x0);
if (nand->bus_width == 8) if (nand->bus_width == 8) {
{
nand->controller->read_data(nand, &manufacturer_id); nand->controller->read_data(nand, &manufacturer_id);
nand->controller->read_data(nand, &device_id); nand->controller->read_data(nand, &device_id);
} } else {
else
{
uint16_t data_buf; uint16_t data_buf;
nand->controller->read_data(nand, &data_buf); nand->controller->read_data(nand, &data_buf);
manufacturer_id = data_buf & 0xff; manufacturer_id = data_buf & 0xff;
@ -365,36 +351,32 @@ int nand_probe(struct nand_device *nand)
device_id = data_buf & 0xff; device_id = data_buf & 0xff;
} }
for (i = 0; nand_flash_ids[i].name; i++) for (i = 0; nand_flash_ids[i].name; i++) {
{
if (nand_flash_ids[i].id == device_id && if (nand_flash_ids[i].id == device_id &&
(nand_flash_ids[i].mfr_id == manufacturer_id || (nand_flash_ids[i].mfr_id == manufacturer_id ||
nand_flash_ids[i].mfr_id == 0 )) nand_flash_ids[i].mfr_id == 0)) {
{
nand->device = &nand_flash_ids[i]; nand->device = &nand_flash_ids[i];
break; break;
} }
} }
for (i = 0; nand_manuf_ids[i].name; i++) for (i = 0; nand_manuf_ids[i].name; i++) {
{ if (nand_manuf_ids[i].id == manufacturer_id) {
if (nand_manuf_ids[i].id == manufacturer_id)
{
nand->manufacturer = &nand_manuf_ids[i]; nand->manufacturer = &nand_manuf_ids[i];
break; break;
} }
} }
if (!nand->manufacturer) if (!nand->manufacturer) {
{
nand->manufacturer = &nand_manuf_ids[0]; nand->manufacturer = &nand_manuf_ids[0];
nand->manufacturer->id = manufacturer_id; nand->manufacturer->id = manufacturer_id;
} }
if (!nand->device) if (!nand->device) {
{ LOG_ERROR(
LOG_ERROR("unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x", "unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x",
manufacturer_id, device_id); manufacturer_id,
device_id);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -410,16 +392,12 @@ int nand_probe(struct nand_device *nand)
/* Do we need extended device probe information? */ /* Do we need extended device probe information? */
if (nand->device->page_size == 0 || if (nand->device->page_size == 0 ||
nand->device->erase_size == 0) nand->device->erase_size == 0) {
{ if (nand->bus_width == 8) {
if (nand->bus_width == 8)
{
nand->controller->read_data(nand, id_buff + 3); nand->controller->read_data(nand, id_buff + 3);
nand->controller->read_data(nand, id_buff + 4); nand->controller->read_data(nand, id_buff + 4);
nand->controller->read_data(nand, id_buff + 5); nand->controller->read_data(nand, id_buff + 5);
} } else {
else
{
uint16_t data_buf; uint16_t data_buf;
nand->controller->read_data(nand, &data_buf); nand->controller->read_data(nand, &data_buf);
@ -435,81 +413,68 @@ int nand_probe(struct nand_device *nand)
/* page size */ /* page size */
if (nand->device->page_size == 0) if (nand->device->page_size == 0)
{
nand->page_size = 1 << (10 + (id_buff[4] & 3)); nand->page_size = 1 << (10 + (id_buff[4] & 3));
} else if (nand->device->page_size == 256) {
else if (nand->device->page_size == 256)
{
LOG_ERROR("NAND flashes with 256 byte pagesize are not supported"); LOG_ERROR("NAND flashes with 256 byte pagesize are not supported");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} } else
else
{
nand->page_size = nand->device->page_size; nand->page_size = nand->device->page_size;
}
/* number of address cycles */ /* number of address cycles */
if (nand->page_size <= 512) if (nand->page_size <= 512) {
{
/* small page devices */ /* small page devices */
if (nand->device->chip_size <= 32) if (nand->device->chip_size <= 32)
nand->address_cycles = 3; nand->address_cycles = 3;
else if (nand->device->chip_size <= 8*1024) else if (nand->device->chip_size <= 8*1024)
nand->address_cycles = 4; nand->address_cycles = 4;
else else {
{
LOG_ERROR("BUG: small page NAND device with more than 8 GiB encountered"); LOG_ERROR("BUG: small page NAND device with more than 8 GiB encountered");
nand->address_cycles = 5; nand->address_cycles = 5;
} }
} } else {
else
{
/* large page devices */ /* large page devices */
if (nand->device->chip_size <= 128) if (nand->device->chip_size <= 128)
nand->address_cycles = 4; nand->address_cycles = 4;
else if (nand->device->chip_size <= 32*1024) else if (nand->device->chip_size <= 32*1024)
nand->address_cycles = 5; nand->address_cycles = 5;
else else {
{
LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered"); LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered");
nand->address_cycles = 6; nand->address_cycles = 6;
} }
} }
/* erase size */ /* erase size */
if (nand->device->erase_size == 0) if (nand->device->erase_size == 0) {
{
switch ((id_buff[4] >> 4) & 3) { switch ((id_buff[4] >> 4) & 3) {
case 0: case 0:
nand->erase_size = 64 << 10; nand->erase_size = 64 << 10;
break; break;
case 1: case 1:
nand->erase_size = 128 << 10; nand->erase_size = 128 << 10;
break; break;
case 2: case 2:
nand->erase_size = 256 << 10; nand->erase_size = 256 << 10;
break; break;
case 3: case 3:
nand->erase_size =512 << 10; nand->erase_size = 512 << 10;
break; break;
} }
} } else
else
{
nand->erase_size = nand->device->erase_size; nand->erase_size = nand->device->erase_size;
}
/* initialize controller, but leave parameters at the controllers default */ /* initialize controller, but leave parameters at the controllers default */
if ((retval = nand->controller->init(nand) != ERROR_OK)) retval = nand->controller->init(nand);
{ if (retval != ERROR_OK) {
switch (retval) switch (retval) {
{
case ERROR_NAND_OPERATION_FAILED: case ERROR_NAND_OPERATION_FAILED:
LOG_DEBUG("controller initialization failed"); LOG_DEBUG("controller initialization failed");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
case ERROR_NAND_OPERATION_NOT_SUPPORTED: case ERROR_NAND_OPERATION_NOT_SUPPORTED:
LOG_ERROR("controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)", LOG_ERROR(
nand->bus_width, nand->address_cycles, nand->page_size); "controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)",
nand->bus_width,
nand->address_cycles,
nand->page_size);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
default: default:
LOG_ERROR("BUG: unknown controller initialization failure"); LOG_ERROR("BUG: unknown controller initialization failure");
@ -520,8 +485,7 @@ int nand_probe(struct nand_device *nand)
nand->num_blocks = (nand->device->chip_size * 1024) / (nand->erase_size / 1024); nand->num_blocks = (nand->device->chip_size * 1024) / (nand->erase_size / 1024);
nand->blocks = malloc(sizeof(struct nand_block) * nand->num_blocks); nand->blocks = malloc(sizeof(struct nand_block) * nand->num_blocks);
for (i = 0; i < nand->num_blocks; i++) for (i = 0; i < nand->num_blocks; i++) {
{
nand->blocks[i].size = nand->erase_size; nand->blocks[i].size = nand->erase_size;
nand->blocks[i].offset = i * nand->erase_size; nand->blocks[i].offset = i * nand->erase_size;
nand->blocks[i].is_erased = -1; nand->blocks[i].is_erased = -1;
@ -545,25 +509,21 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
/* make sure we know if a block is bad before erasing it */ /* make sure we know if a block is bad before erasing it */
for (i = first_block; i <= last_block; i++) for (i = first_block; i <= last_block; i++) {
{ if (nand->blocks[i].is_bad == -1) {
if (nand->blocks[i].is_bad == -1)
{
nand_build_bbt(nand, i, last_block); nand_build_bbt(nand, i, last_block);
break; break;
} }
} }
for (i = first_block; i <= last_block; i++) for (i = first_block; i <= last_block; i++) {
{
/* Send erase setup command */ /* Send erase setup command */
nand->controller->command(nand, NAND_CMD_ERASE1); nand->controller->command(nand, NAND_CMD_ERASE1);
page = i * (nand->erase_size / nand->page_size); page = i * (nand->erase_size / nand->page_size);
/* Send page address */ /* Send page address */
if (nand->page_size <= 512) if (nand->page_size <= 512) {
{
/* row */ /* row */
nand->controller->address(nand, page & 0xff); nand->controller->address(nand, page & 0xff);
nand->controller->address(nand, (page >> 8) & 0xff); nand->controller->address(nand, (page >> 8) & 0xff);
@ -575,9 +535,7 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
/* 4th cycle only on devices with more than 8 GiB */ /* 4th cycle only on devices with more than 8 GiB */
if (nand->address_cycles >= 5) if (nand->address_cycles >= 5)
nand->controller->address(nand, (page >> 24) & 0xff); nand->controller->address(nand, (page >> 24) & 0xff);
} } else {
else
{
/* row */ /* row */
nand->controller->address(nand, page & 0xff); nand->controller->address(nand, page & 0xff);
nand->controller->address(nand, (page >> 8) & 0xff); nand->controller->address(nand, (page >> 8) & 0xff);
@ -591,26 +549,24 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
nand->controller->command(nand, NAND_CMD_ERASE2); nand->controller->command(nand, NAND_CMD_ERASE2);
retval = nand->controller->nand_ready ? retval = nand->controller->nand_ready ?
nand->controller->nand_ready(nand, 1000) : nand->controller->nand_ready(nand, 1000) :
nand_poll_ready(nand, 1000); nand_poll_ready(nand, 1000);
if (!retval) { if (!retval) {
LOG_ERROR("timeout waiting for NAND flash block erase to complete"); LOG_ERROR("timeout waiting for NAND flash block erase to complete");
return ERROR_NAND_OPERATION_TIMEOUT; return ERROR_NAND_OPERATION_TIMEOUT;
} }
retval = nand_read_status(nand, &status); retval = nand_read_status(nand, &status);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
LOG_ERROR("couldn't read status"); LOG_ERROR("couldn't read status");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (status & 0x1) if (status & 0x1) {
{
LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x", LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x",
(nand->blocks[i].is_bad == 1) (nand->blocks[i].is_bad == 1)
? "bad " : "", ? "bad " : "",
i, status); i, status);
/* continue; other blocks might still be erasable */ /* continue; other blocks might still be erasable */
} }
@ -621,23 +577,24 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
} }
#if 0 #if 0
static int nand_read_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size) static int nand_read_plain(struct nand_device *nand,
uint32_t address,
uint8_t *data,
uint32_t data_size)
{ {
uint8_t *page; uint8_t *page;
if (!nand->device) if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED; return ERROR_NAND_DEVICE_NOT_PROBED;
if (address % nand->page_size) if (address % nand->page_size) {
{
LOG_ERROR("reads need to be page aligned"); LOG_ERROR("reads need to be page aligned");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
page = malloc(nand->page_size); page = malloc(nand->page_size);
while (data_size > 0) while (data_size > 0) {
{
uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size; uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size;
uint32_t page_address; uint32_t page_address;
@ -658,23 +615,24 @@ static int nand_read_plain(struct nand_device *nand, uint32_t address, uint8_t *
return ERROR_OK; return ERROR_OK;
} }
static int nand_write_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size) static int nand_write_plain(struct nand_device *nand,
uint32_t address,
uint8_t *data,
uint32_t data_size)
{ {
uint8_t *page; uint8_t *page;
if (!nand->device) if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED; return ERROR_NAND_DEVICE_NOT_PROBED;
if (address % nand->page_size) if (address % nand->page_size) {
{
LOG_ERROR("writes need to be page aligned"); LOG_ERROR("writes need to be page aligned");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
page = malloc(nand->page_size); page = malloc(nand->page_size);
while (data_size > 0) while (data_size > 0) {
{
uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size; uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size;
uint32_t page_address; uint32_t page_address;
@ -697,8 +655,8 @@ static int nand_write_plain(struct nand_device *nand, uint32_t address, uint8_t
#endif #endif
int nand_write_page(struct nand_device *nand, uint32_t page, int nand_write_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
uint32_t block; uint32_t block;
@ -716,8 +674,8 @@ int nand_write_page(struct nand_device *nand, uint32_t page,
} }
int nand_read_page(struct nand_device *nand, uint32_t page, int nand_read_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
if (!nand->device) if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED; return ERROR_NAND_DEVICE_NOT_PROBED;
@ -729,7 +687,7 @@ int nand_read_page(struct nand_device *nand, uint32_t page,
} }
int nand_page_command(struct nand_device *nand, uint32_t page, int nand_page_command(struct nand_device *nand, uint32_t page,
uint8_t cmd, bool oob_only) uint8_t cmd, bool oob_only)
{ {
if (!nand->device) if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED; return ERROR_NAND_DEVICE_NOT_PROBED;
@ -814,8 +772,8 @@ int nand_read_data_page(struct nand_device *nand, uint8_t *data, uint32_t size)
} }
int nand_read_page_raw(struct nand_device *nand, uint32_t page, int nand_read_page_raw(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
int retval; int retval;
@ -870,8 +828,8 @@ int nand_write_finish(struct nand_device *nand)
nand->controller->command(nand, NAND_CMD_PAGEPROG); nand->controller->command(nand, NAND_CMD_PAGEPROG);
retval = nand->controller->nand_ready ? retval = nand->controller->nand_ready ?
nand->controller->nand_ready(nand, 100) : nand->controller->nand_ready(nand, 100) :
nand_poll_ready(nand, 100); nand_poll_ready(nand, 100);
if (!retval) if (!retval)
return ERROR_NAND_OPERATION_TIMEOUT; return ERROR_NAND_OPERATION_TIMEOUT;
@ -883,7 +841,7 @@ int nand_write_finish(struct nand_device *nand)
if (status & NAND_STATUS_FAIL) { if (status & NAND_STATUS_FAIL) {
LOG_ERROR("write operation didn't pass, status: 0x%2.2x", LOG_ERROR("write operation didn't pass, status: 0x%2.2x",
status); status);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -891,8 +849,8 @@ int nand_write_finish(struct nand_device *nand)
} }
int nand_write_page_raw(struct nand_device *nand, uint32_t page, int nand_write_page_raw(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
int retval; int retval;
@ -918,4 +876,3 @@ int nand_write_page_raw(struct nand_device *nand, uint32_t page,
return nand_write_finish(nand); return nand_write_finish(nand);
} }

View File

@ -22,6 +22,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NAND_CORE_H #ifndef FLASH_NAND_CORE_H
#define FLASH_NAND_CORE_H #define FLASH_NAND_CORE_H
@ -30,8 +31,7 @@
/** /**
* Representation of a single NAND block in a NAND device. * Representation of a single NAND block in a NAND device.
*/ */
struct nand_block struct nand_block {
{
/** Offset to the block. */ /** Offset to the block. */
uint32_t offset; uint32_t offset;
@ -57,8 +57,7 @@ struct nand_ecclayout {
struct nand_oobfree oobfree[2]; struct nand_oobfree oobfree[2];
}; };
struct nand_device struct nand_device {
{
const char *name; const char *name;
struct target *target; struct target *target;
struct nand_flash_controller *controller; struct nand_flash_controller *controller;
@ -77,8 +76,7 @@ struct nand_device
/* NAND Flash Manufacturer ID Codes /* NAND Flash Manufacturer ID Codes
*/ */
enum enum {
{
NAND_MFR_TOSHIBA = 0x98, NAND_MFR_TOSHIBA = 0x98,
NAND_MFR_SAMSUNG = 0xec, NAND_MFR_SAMSUNG = 0xec,
NAND_MFR_FUJITSU = 0x04, NAND_MFR_FUJITSU = 0x04,
@ -89,14 +87,12 @@ enum
NAND_MFR_MICRON = 0x2c, NAND_MFR_MICRON = 0x2c,
}; };
struct nand_manufacturer struct nand_manufacturer {
{
int id; int id;
const char *name; const char *name;
}; };
struct nand_info struct nand_info {
{
int mfr_id; int mfr_id;
int id; int id;
int page_size; int page_size;
@ -152,8 +148,7 @@ enum {
LP_OPTIONS16 = (LP_OPTIONS | NAND_BUSWIDTH_16), LP_OPTIONS16 = (LP_OPTIONS | NAND_BUSWIDTH_16),
}; };
enum enum {
{
/* Standard NAND flash commands */ /* Standard NAND flash commands */
NAND_CMD_READ0 = 0x0, NAND_CMD_READ0 = 0x0,
NAND_CMD_READ1 = 0x1, NAND_CMD_READ1 = 0x1,
@ -161,7 +156,7 @@ enum
NAND_CMD_PAGEPROG = 0x10, NAND_CMD_PAGEPROG = 0x10,
NAND_CMD_READOOB = 0x50, NAND_CMD_READOOB = 0x50,
NAND_CMD_ERASE1 = 0x60, NAND_CMD_ERASE1 = 0x60,
NAND_CMD_STATUS = 0x70, NAND_CMD_STATUS = 0x70,
NAND_CMD_STATUS_MULTI = 0x71, NAND_CMD_STATUS_MULTI = 0x71,
NAND_CMD_SEQIN = 0x80, NAND_CMD_SEQIN = 0x80,
NAND_CMD_RNDIN = 0x85, NAND_CMD_RNDIN = 0x85,
@ -176,8 +171,7 @@ enum
}; };
/* Status bits */ /* Status bits */
enum enum {
{
NAND_STATUS_FAIL = 0x01, NAND_STATUS_FAIL = 0x01,
NAND_STATUS_FAIL_N1 = 0x02, NAND_STATUS_FAIL_N1 = 0x02,
NAND_STATUS_TRUE_READY = 0x20, NAND_STATUS_TRUE_READY = 0x20,
@ -186,14 +180,14 @@ enum
}; };
/* OOB (spare) data formats */ /* OOB (spare) data formats */
enum oob_formats enum oob_formats {
{
NAND_OOB_NONE = 0x0, /* no OOB data at all */ NAND_OOB_NONE = 0x0, /* no OOB data at all */
NAND_OOB_RAW = 0x1, /* raw OOB data (16 bytes for 512b page sizes, 64 bytes for 2048b page sizes) */ NAND_OOB_RAW = 0x1, /* raw OOB data (16 bytes for 512b page sizes, 64 bytes for
*2048b page sizes) */
NAND_OOB_ONLY = 0x2, /* only OOB data */ NAND_OOB_ONLY = 0x2, /* only OOB data */
NAND_OOB_SW_ECC = 0x10, /* when writing, use SW ECC (as opposed to no ECC) */ NAND_OOB_SW_ECC = 0x10, /* when writing, use SW ECC (as opposed to no ECC) */
NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no ECC) */ NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no ECC) */
NAND_OOB_SW_ECC_KW = 0x40, /* when writing, use Marvell's Kirkwood bootrom format */ NAND_OOB_SW_ECC_KW = 0x40, /* when writing, use Marvell's Kirkwood bootrom format */
NAND_OOB_JFFS2 = 0x100, /* when writing, use JFFS2 OOB layout */ NAND_OOB_JFFS2 = 0x100, /* when writing, use JFFS2 OOB layout */
NAND_OOB_YAFFS2 = 0x100,/* when writing, use YAFFS2 OOB layout */ NAND_OOB_YAFFS2 = 0x100,/* when writing, use YAFFS2 OOB layout */
}; };
@ -202,40 +196,39 @@ enum oob_formats
struct nand_device *get_nand_device_by_num(int num); struct nand_device *get_nand_device_by_num(int num);
int nand_page_command(struct nand_device *nand, uint32_t page, int nand_page_command(struct nand_device *nand, uint32_t page,
uint8_t cmd, bool oob_only); uint8_t cmd, bool oob_only);
int nand_read_data_page(struct nand_device *nand, uint8_t *data, uint32_t size); int nand_read_data_page(struct nand_device *nand, uint8_t *data, uint32_t size);
int nand_write_data_page(struct nand_device *nand, int nand_write_data_page(struct nand_device *nand,
uint8_t *data, uint32_t size); uint8_t *data, uint32_t size);
int nand_write_finish(struct nand_device *nand); int nand_write_finish(struct nand_device *nand);
int nand_read_page_raw(struct nand_device *nand, uint32_t page, 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); uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
int nand_write_page_raw(struct nand_device *nand, uint32_t page, int nand_write_page_raw(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
int nand_read_status(struct nand_device *nand, uint8_t *status); int nand_read_status(struct nand_device *nand, uint8_t *status);
int nand_calculate_ecc(struct nand_device *nand, int nand_calculate_ecc(struct nand_device *nand,
const uint8_t *dat, uint8_t *ecc_code); const uint8_t *dat, uint8_t *ecc_code);
int nand_calculate_ecc_kw(struct nand_device *nand, int nand_calculate_ecc_kw(struct nand_device *nand,
const uint8_t *dat, uint8_t *ecc_code); const uint8_t *dat, uint8_t *ecc_code);
int nand_register_commands(struct command_context *cmd_ctx); int nand_register_commands(struct command_context *cmd_ctx);
/// helper for parsing a nand device command argument string /* / helper for parsing a nand device command argument string */
COMMAND_HELPER(nand_command_get_device, unsigned name_index, COMMAND_HELPER(nand_command_get_device, unsigned name_index,
struct nand_device **nand); struct nand_device **nand);
#define ERROR_NAND_DEVICE_INVALID (-1100) #define ERROR_NAND_DEVICE_INVALID (-1100)
#define ERROR_NAND_OPERATION_FAILED (-1101) #define ERROR_NAND_OPERATION_FAILED (-1101)
#define ERROR_NAND_OPERATION_TIMEOUT (-1102) #define ERROR_NAND_OPERATION_TIMEOUT (-1102)
#define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103) #define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103)
#define ERROR_NAND_DEVICE_NOT_PROBED (-1104) #define ERROR_NAND_DEVICE_NOT_PROBED (-1104)
#define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105) #define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105)
#define ERROR_NAND_NO_BUFFER (-1106) #define ERROR_NAND_NO_BUFFER (-1106)
#endif // FLASH_NAND_CORE_H
#endif /* FLASH_NAND_CORE_H */

View File

@ -39,34 +39,34 @@ enum ecc {
}; };
struct davinci_nand { struct davinci_nand {
uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */ uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */
uint8_t eccmode; uint8_t eccmode;
/* Async EMIF controller base */ /* Async EMIF controller base */
uint32_t aemif; uint32_t aemif;
/* NAND chip addresses */ /* NAND chip addresses */
uint32_t data; /* without CLE or ALE */ uint32_t data; /* without CLE or ALE */
uint32_t cmd; /* with CLE */ uint32_t cmd; /* with CLE */
uint32_t addr; /* with ALE */ uint32_t addr; /* with ALE */
/* write acceleration */ /* write acceleration */
struct arm_nand_data io; struct arm_nand_data io;
/* page i/o for the relevant flavor of hardware ECC */ /* page i/o for the relevant flavor of hardware ECC */
int (*read_page)(struct nand_device *nand, uint32_t page, int (*read_page)(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
int (*write_page)(struct nand_device *nand, uint32_t page, int (*write_page)(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
}; };
#define NANDFCR 0x60 /* flash control register */ #define NANDFCR 0x60 /* flash control register */
#define NANDFSR 0x64 /* flash status register */ #define NANDFSR 0x64 /* flash status register */
#define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */ #define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */
#define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */ #define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */
#define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */ #define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */
#define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */ #define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */
#define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */ #define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */
static int halted(struct target *target, const char *label) static int halted(struct target *target, const char *label)
{ {
@ -181,7 +181,7 @@ static int davinci_read_data(struct nand_device *nand, void *data)
/* REVISIT a bit of native code should let block reads be MUCH faster */ /* REVISIT a bit of native code should let block reads be MUCH faster */
static int davinci_read_block_data(struct nand_device *nand, static int davinci_read_block_data(struct nand_device *nand,
uint8_t *data, int data_size) uint8_t *data, int data_size)
{ {
struct davinci_nand *info = nand->controller_priv; struct davinci_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -214,7 +214,7 @@ static int davinci_read_block_data(struct nand_device *nand,
} }
static int davinci_write_block_data(struct nand_device *nand, static int davinci_write_block_data(struct nand_device *nand,
uint8_t *data, int data_size) uint8_t *data, int data_size)
{ {
struct davinci_nand *info = nand->controller_priv; struct davinci_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -250,7 +250,7 @@ static int davinci_write_block_data(struct nand_device *nand,
} }
static int davinci_write_page(struct nand_device *nand, uint32_t page, static int davinci_write_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{ {
struct davinci_nand *info = nand->controller_priv; struct davinci_nand *info = nand->controller_priv;
uint8_t *ooballoc = NULL; uint8_t *ooballoc = NULL;
@ -269,17 +269,17 @@ static int davinci_write_page(struct nand_device *nand, uint32_t page,
/* If we're not given OOB, write 0xff where we don't write ECC codes. */ /* If we're not given OOB, write 0xff where we don't write ECC codes. */
switch (nand->page_size) { switch (nand->page_size) {
case 512: case 512:
oob_size = 16; oob_size = 16;
break; break;
case 2048: case 2048:
oob_size = 64; oob_size = 64;
break; break;
case 4096: case 4096:
oob_size = 128; oob_size = 128;
break; break;
default: default:
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (!oob) { if (!oob) {
ooballoc = malloc(oob_size); ooballoc = malloc(oob_size);
@ -301,7 +301,7 @@ static int davinci_write_page(struct nand_device *nand, uint32_t page,
} }
static int davinci_read_page(struct nand_device *nand, uint32_t page, static int davinci_read_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{ {
struct davinci_nand *info = nand->controller_priv; struct davinci_nand *info = nand->controller_priv;
@ -358,7 +358,7 @@ static int davinci_seek_column(struct nand_device *nand, uint16_t column)
} }
static int davinci_writepage_tail(struct nand_device *nand, static int davinci_writepage_tail(struct nand_device *nand,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
struct davinci_nand *info = nand->controller_priv; struct davinci_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -390,7 +390,7 @@ static int davinci_writepage_tail(struct nand_device *nand,
* All DaVinci family chips support 1-bit ECC on a per-chipselect basis. * All DaVinci family chips support 1-bit ECC on a per-chipselect basis.
*/ */
static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page, static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{ {
unsigned oob_offset; unsigned oob_offset;
struct davinci_nand *info = nand->controller_priv; struct davinci_nand *info = nand->controller_priv;
@ -404,15 +404,15 @@ static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
* for 16-bit OOB, those extra bytes are discontiguous. * for 16-bit OOB, those extra bytes are discontiguous.
*/ */
switch (nand->page_size) { switch (nand->page_size) {
case 512: case 512:
oob_offset = 0; oob_offset = 0;
break; break;
case 2048: case 2048:
oob_offset = 40; oob_offset = 40;
break; break;
default: default:
oob_offset = 80; oob_offset = 80;
break; break;
} }
davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page); davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
@ -457,10 +457,10 @@ static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
* manufacturer bad block markers are safe. Contrast: old "infix" style. * manufacturer bad block markers are safe. Contrast: old "infix" style.
*/ */
static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page, static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{ {
static const uint8_t ecc512[] = { static const uint8_t ecc512[] = {
0, 1, 2, 3, 4, /* 5== mfr badblock */ 0, 1, 2, 3, 4, /* 5== mfr badblock */
6, 7, /* 8..12 for BBT or JFFS2 */ 13, 14, 15, 6, 7, /* 8..12 for BBT or JFFS2 */ 13, 14, 15,
}; };
static const uint8_t ecc2048[] = { static const uint8_t ecc2048[] = {
@ -470,12 +470,12 @@ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
}; };
static const uint8_t ecc4096[] = { static const uint8_t ecc4096[] = {
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
}; };
@ -495,15 +495,15 @@ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
* the standard ECC logic can't handle. * the standard ECC logic can't handle.
*/ */
switch (nand->page_size) { switch (nand->page_size) {
case 512: case 512:
l = ecc512; l = ecc512;
break; break;
case 2048: case 2048:
l = ecc2048; l = ecc2048;
break; break;
default: default:
l = ecc4096; l = ecc4096;
break; break;
} }
davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page); davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
@ -533,11 +533,11 @@ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
raw_ecc[i] &= 0x03ff03ff; raw_ecc[i] &= 0x03ff03ff;
} }
for (i = 0, p = raw_ecc; i < 2; i++, p += 2) { for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
oob[*l++] = p[0] & 0xff; oob[*l++] = p[0] & 0xff;
oob[*l++] = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc); oob[*l++] = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc);
oob[*l++] = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0); oob[*l++] = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
oob[*l++] = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0); oob[*l++] = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0);
oob[*l++] = (p[1] >> 18) & 0xff; oob[*l++] = (p[1] >> 18) & 0xff;
} }
} while (data_size); } while (data_size);
@ -559,7 +559,7 @@ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
* (MVL 4.x/5.x kernels, filesystems, etc) may need it more generally. * (MVL 4.x/5.x kernels, filesystems, etc) may need it more generally.
*/ */
static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page, static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{ {
struct davinci_nand *info = nand->controller_priv; struct davinci_nand *info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -597,11 +597,11 @@ static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
/* skip 6 bytes of prepad, then pack 10 packed ecc bytes */ /* skip 6 bytes of prepad, then pack 10 packed ecc bytes */
for (i = 0, l = oob + 6, p = raw_ecc; i < 2; i++, p += 2) { for (i = 0, l = oob + 6, p = raw_ecc; i < 2; i++, p += 2) {
*l++ = p[0] & 0xff; *l++ = p[0] & 0xff;
*l++ = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc); *l++ = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc);
*l++ = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0); *l++ = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
*l++ = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0); *l++ = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0);
*l++ = (p[1] >> 18) & 0xff; *l++ = (p[1] >> 18) & 0xff;
} }
/* write this "out-of-band" data -- infix */ /* write this "out-of-band" data -- infix */
@ -616,7 +616,7 @@ static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
} }
static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page, static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{ {
int read_size; int read_size;
int want_col, at_col; int want_col, at_col;
@ -688,9 +688,8 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
* - aemif address * - aemif address
* Plus someday, optionally, ALE and CLE masks. * Plus someday, optionally, ALE and CLE masks.
*/ */
if (CMD_ARGC < 5) { if (CMD_ARGC < 5)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip); COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
if (chip == 0) { if (chip == 0) {
@ -720,9 +719,9 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
* AEMIF controller address. * AEMIF controller address.
*/ */
if (aemif == 0x01e00000 /* dm6446, dm357 */ if (aemif == 0x01e00000 /* dm6446, dm357 */
|| aemif == 0x01e10000 /* dm335, dm355 */ || aemif == 0x01e10000 /* dm335, dm355 */
|| aemif == 0x01d10000 /* dm365 */ || aemif == 0x01d10000 /* dm365 */
) { ) {
if (chip < 0x02000000 || chip >= 0x0a000000) { if (chip < 0x02000000 || chip >= 0x0a000000) {
LOG_ERROR("NAND address %08lx out of range?", chip); LOG_ERROR("NAND address %08lx out of range?", chip);
goto fail; goto fail;
@ -757,19 +756,19 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
info->read_page = nand_read_page_raw; info->read_page = nand_read_page_raw;
switch (eccmode) { switch (eccmode) {
case HWECC1: case HWECC1:
/* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */ /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
info->write_page = davinci_write_page_ecc1; info->write_page = davinci_write_page_ecc1;
break; break;
case HWECC4: case HWECC4:
/* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */ /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
info->write_page = davinci_write_page_ecc4; info->write_page = davinci_write_page_ecc4;
break; break;
case HWECC4_INFIX: case HWECC4_INFIX:
/* Same 4-bit ECC HW, with problematic page/ecc layout */ /* Same 4-bit ECC HW, with problematic page/ecc layout */
info->read_page = davinci_read_page_ecc4infix; info->read_page = davinci_read_page_ecc4infix;
info->write_page = davinci_write_page_ecc4infix; info->write_page = davinci_write_page_ecc4infix;
break; break;
} }
return ERROR_OK; return ERROR_OK;
@ -779,18 +778,18 @@ fail:
} }
struct nand_flash_controller davinci_nand_controller = { struct nand_flash_controller davinci_nand_controller = {
.name = "davinci", .name = "davinci",
.usage = "chip_addr hwecc_mode aemif_addr", .usage = "chip_addr hwecc_mode aemif_addr",
.nand_device_command = davinci_nand_device_command, .nand_device_command = davinci_nand_device_command,
.init = davinci_init, .init = davinci_init,
.reset = davinci_reset, .reset = davinci_reset,
.command = davinci_command, .command = davinci_command,
.address = davinci_address, .address = davinci_address,
.write_data = davinci_write_data, .write_data = davinci_write_data,
.read_data = davinci_read_data, .read_data = davinci_read_data,
.write_page = davinci_write_page, .write_page = davinci_write_page,
.read_page = davinci_read_page, .read_page = davinci_read_page,
.write_block_data = davinci_write_block_data, .write_block_data = davinci_write_block_data,
.read_block_data = davinci_read_block_data, .read_block_data = davinci_read_block_data,
.nand_ready = davinci_nand_ready, .nand_ready = davinci_nand_ready,
}; };

View File

@ -45,8 +45,7 @@ extern struct nand_flash_controller nuc910_nand_controller;
/* extern struct nand_flash_controller boundary_scan_nand_controller; */ /* extern struct nand_flash_controller boundary_scan_nand_controller; */
static struct nand_flash_controller *nand_flash_controllers[] = static struct nand_flash_controller *nand_flash_controllers[] = {
{
&nonce_nand_controller, &nonce_nand_controller,
&davinci_nand_controller, &davinci_nand_controller,
&lpc3180_nand_controller, &lpc3180_nand_controller,
@ -67,8 +66,7 @@ static struct nand_flash_controller *nand_flash_controllers[] =
struct nand_flash_controller *nand_driver_find_by_name(const char *name) struct nand_flash_controller *nand_driver_find_by_name(const char *name)
{ {
for (unsigned i = 0; nand_flash_controllers[i]; i++) for (unsigned i = 0; nand_flash_controllers[i]; i++) {
{
struct nand_flash_controller *controller = nand_flash_controllers[i]; struct nand_flash_controller *controller = nand_flash_controllers[i];
if (strcmp(name, controller->name) == 0) if (strcmp(name, controller->name) == 0)
return controller; return controller;
@ -77,13 +75,10 @@ struct nand_flash_controller *nand_driver_find_by_name(const char *name)
} }
int nand_driver_walk(nand_driver_walker_t f, void *x) int nand_driver_walk(nand_driver_walker_t f, void *x)
{ {
for (unsigned i = 0; nand_flash_controllers[i]; i++) for (unsigned i = 0; nand_flash_controllers[i]; i++) {
{
int retval = (*f)(nand_flash_controllers[i], x); int retval = (*f)(nand_flash_controllers[i], x);
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
} }
return ERROR_OK; return ERROR_OK;
} }

View File

@ -19,28 +19,28 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NAND_DRIVER_H #ifndef FLASH_NAND_DRIVER_H
#define FLASH_NAND_DRIVER_H #define FLASH_NAND_DRIVER_H
struct nand_device; struct nand_device;
#define __NAND_DEVICE_COMMAND(name) \ #define __NAND_DEVICE_COMMAND(name) \
COMMAND_HELPER(name, struct nand_device *nand) COMMAND_HELPER(name, struct nand_device *nand)
/** /**
* Interface for NAND flash controllers. Not all of these functions are * Interface for NAND flash controllers. Not all of these functions are
* required for full functionality of the NAND driver, but better performance * required for full functionality of the NAND driver, but better performance
* can be achieved by implementing each function. * can be achieved by implementing each function.
*/ */
struct nand_flash_controller struct nand_flash_controller {
{
/** Driver name that is used to select it from configuration files. */ /** Driver name that is used to select it from configuration files. */
const char *name; const char *name;
/** Usage of flash command registration. */ /** Usage of flash command registration. */
const char *usage; const char *usage;
const struct command_registration *commands; const struct command_registration *commands;
/** NAND device command called when driver is instantiated during configuration. */ /** NAND device command called when driver is instantiated during configuration. */
__NAND_DEVICE_COMMAND((*nand_device_command)); __NAND_DEVICE_COMMAND((*nand_device_command));
@ -70,10 +70,12 @@ struct nand_flash_controller
int (*read_block_data)(struct nand_device *nand, uint8_t *data, int size); int (*read_block_data)(struct nand_device *nand, uint8_t *data, int size);
/** Write a page to the NAND device. */ /** Write a page to the NAND device. */
int (*write_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); int (*write_page)(struct nand_device *nand, uint32_t page, uint8_t *data,
uint32_t data_size, uint8_t *oob, uint32_t oob_size);
/** Read a page from the NAND device. */ /** Read a page from the NAND device. */
int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size); int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size);
/** Check if the NAND device is ready for more instructions with timeout. */ /** Check if the NAND device is ready for more instructions with timeout. */
int (*nand_ready)(struct nand_device *nand, int timeout); int (*nand_ready)(struct nand_device *nand, int timeout);
@ -88,8 +90,8 @@ struct nand_flash_controller
*/ */
struct nand_flash_controller *nand_driver_find_by_name(const char *name); struct nand_flash_controller *nand_driver_find_by_name(const char *name);
/// Signature for callback functions passed to nand_driver_walk /* / Signature for callback functions passed to nand_driver_walk */
typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void*); typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void *);
/** /**
* Walk the list of drivers, encapsulating the data structure type. * Walk the list of drivers, encapsulating the data structure type.
* Application state/context can be passed through the @c x pointer. * Application state/context can be passed through the @c x pointer.
@ -100,4 +102,4 @@ typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void*);
*/ */
int nand_driver_walk(nand_driver_walker_t f, void *x); int nand_driver_walk(nand_driver_walker_t f, void *x);
#endif // FLASH_NAND_DRIVER_H #endif /* FLASH_NAND_DRIVER_H */

View File

@ -125,7 +125,7 @@ static inline int countbits(uint32_t b)
{ {
int res = 0; int res = 0;
for (;b; b >>= 1) for (; b; b >>= 1)
res += b & 0x01; res += b & 0x01;
return res; return res;
} }
@ -134,7 +134,7 @@ static inline int countbits(uint32_t b)
* nand_correct_data - Detect and correct a 1 bit error for 256 byte block * nand_correct_data - Detect and correct a 1 bit error for 256 byte block
*/ */
int nand_correct_data(struct nand_device *nand, u_char *dat, int nand_correct_data(struct nand_device *nand, u_char *dat,
u_char *read_ecc, u_char *calc_ecc) u_char *read_ecc, u_char *calc_ecc)
{ {
uint8_t s0, s1, s2; uint8_t s0, s1, s2;
@ -151,9 +151,9 @@ int nand_correct_data(struct nand_device *nand, u_char *dat,
return 0; return 0;
/* Check for a single bit error */ /* Check for a single bit error */
if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && if (((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
uint32_t byteoffs, bitnum; uint32_t byteoffs, bitnum;
@ -176,7 +176,7 @@ int nand_correct_data(struct nand_device *nand, u_char *dat,
return 1; return 1;
} }
if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1) if (countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 << 16)) == 1)
return 1; return 1;
return -1; return -1;

View File

@ -28,7 +28,7 @@
* For multiplication, a discrete log/exponent table is used, with * For multiplication, a discrete log/exponent table is used, with
* primitive element x (F is a primitive field, so x is primitive). * primitive element x (F is a primitive field, so x is primitive).
*/ */
#define MODPOLY 0x409 /* x^10 + x^3 + 1 in binary */ #define MODPOLY 0x409 /* x^10 + x^3 + 1 in binary */
/* /*
* Maps an integer a [0..1022] to a polynomial b = gf_exp[a] in * Maps an integer a [0..1022] to a polynomial b = gf_exp[a] in
@ -102,7 +102,7 @@ int nand_calculate_ecc_kw(struct nand_device *nand, const uint8_t *data, uint8_t
{ {
unsigned int r7, r6, r5, r4, r3, r2, r1, r0; unsigned int r7, r6, r5, r4, r3, r2, r1, r0;
int i; int i;
static int tables_initialized = 0; static int tables_initialized;
if (!tables_initialized) { if (!tables_initialized) {
gf_build_log_exp_table(); gf_build_log_exp_table();
@ -121,7 +121,6 @@ int nand_calculate_ecc_kw(struct nand_device *nand, const uint8_t *data, uint8_t
r6 = data[510]; r6 = data[510];
r7 = data[511]; r7 = data[511];
/* /*
* Shift bytes 503..0 (in that order) into r0, followed * Shift bytes 503..0 (in that order) into r0, followed
* by eight zero bytes, while reducing the polynomial by the * by eight zero bytes, while reducing the polynomial by the

View File

@ -20,6 +20,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -32,18 +33,21 @@ static struct nand_ecclayout nand_oob_16 = {
.eccpos = {0, 1, 2, 3, 6, 7}, .eccpos = {0, 1, 2, 3, 6, 7},
.oobfree = { .oobfree = {
{.offset = 8, {.offset = 8,
. length = 8}} .length = 8}
}
}; };
static struct nand_ecclayout nand_oob_64 = { static struct nand_ecclayout nand_oob_64 = {
.eccbytes = 24, .eccbytes = 24,
.eccpos = { .eccpos = {
40, 41, 42, 43, 44, 45, 46, 47, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63}, 56, 57, 58, 59, 60, 61, 62, 63
},
.oobfree = { .oobfree = {
{.offset = 2, {.offset = 2,
.length = 38}} .length = 38}
}
}; };
void nand_fileio_init(struct nand_fileio_state *state) void nand_fileio_init(struct nand_fileio_state *state)
@ -53,45 +57,37 @@ void nand_fileio_init(struct nand_fileio_state *state)
} }
int nand_fileio_start(struct command_context *cmd_ctx, int nand_fileio_start(struct command_context *cmd_ctx,
struct nand_device *nand, const char *filename, int filemode, struct nand_device *nand, const char *filename, int filemode,
struct nand_fileio_state *state) struct nand_fileio_state *state)
{ {
if (state->address % nand->page_size) if (state->address % nand->page_size) {
{
command_print(cmd_ctx, "only page-aligned addresses are supported"); command_print(cmd_ctx, "only page-aligned addresses are supported");
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
duration_start(&state->bench); duration_start(&state->bench);
if (NULL != filename) if (NULL != filename) {
{
int retval = fileio_open(&state->fileio, filename, filemode, FILEIO_BINARY); int retval = fileio_open(&state->fileio, filename, filemode, FILEIO_BINARY);
if (ERROR_OK != retval) if (ERROR_OK != retval) {
{
const char *msg = (FILEIO_READ == filemode) ? "read" : "write"; const char *msg = (FILEIO_READ == filemode) ? "read" : "write";
command_print(cmd_ctx, "failed to open '%s' for %s access", command_print(cmd_ctx, "failed to open '%s' for %s access",
filename, msg); filename, msg);
return retval; return retval;
} }
state->file_opened = true; state->file_opened = true;
} }
if (!(state->oob_format & NAND_OOB_ONLY)) if (!(state->oob_format & NAND_OOB_ONLY)) {
{
state->page_size = nand->page_size; state->page_size = nand->page_size;
state->page = malloc(nand->page_size); state->page = malloc(nand->page_size);
} }
if (state->oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW)) if (state->oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW)) {
{ if (nand->page_size == 512) {
if (nand->page_size == 512)
{
state->oob_size = 16; state->oob_size = 16;
state->eccpos = nand_oob_16.eccpos; state->eccpos = nand_oob_16.eccpos;
} } else if (nand->page_size == 2048) {
else if (nand->page_size == 2048)
{
state->oob_size = 64; state->oob_size = 64;
state->eccpos = nand_oob_64.eccpos; state->eccpos = nand_oob_64.eccpos;
} }
@ -105,13 +101,11 @@ int nand_fileio_cleanup(struct nand_fileio_state *state)
if (state->file_opened) if (state->file_opened)
fileio_close(&state->fileio); fileio_close(&state->fileio);
if (state->oob) if (state->oob) {
{
free(state->oob); free(state->oob);
state->oob = NULL; state->oob = NULL;
} }
if (state->page) if (state->page) {
{
free(state->page); free(state->page);
state->page = NULL; state->page = NULL;
} }
@ -124,8 +118,8 @@ int nand_fileio_finish(struct nand_fileio_state *state)
} }
COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
struct nand_device **dev, enum fileio_access filemode, struct nand_device **dev, enum fileio_access filemode,
bool need_size, bool sw_ecc) bool need_size, bool sw_ecc)
{ {
nand_fileio_init(state); nand_fileio_init(state);
@ -138,27 +132,22 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if (NULL == nand->device) if (NULL == nand->device) {
{
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]); command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
return ERROR_OK; return ERROR_OK;
} }
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], state->address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], state->address);
if (need_size) if (need_size) {
{ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], state->size);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], state->size); if (state->size % nand->page_size) {
if (state->size % nand->page_size) command_print(CMD_CTX, "only page-aligned sizes are supported");
{ return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX, "only page-aligned sizes are supported"); }
return ERROR_COMMAND_SYNTAX_ERROR;
}
} }
if (CMD_ARGC > minargs) if (CMD_ARGC > minargs) {
{ for (unsigned i = minargs; i < CMD_ARGC; i++) {
for (unsigned i = minargs; i < CMD_ARGC; i++)
{
if (!strcmp(CMD_ARGV[i], "oob_raw")) if (!strcmp(CMD_ARGV[i], "oob_raw"))
state->oob_format |= NAND_OOB_RAW; state->oob_format |= NAND_OOB_RAW;
else if (!strcmp(CMD_ARGV[i], "oob_only")) else if (!strcmp(CMD_ARGV[i], "oob_only"))
@ -167,8 +156,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
state->oob_format |= NAND_OOB_SW_ECC; state->oob_format |= NAND_OOB_SW_ECC;
else if (sw_ecc && !strcmp(CMD_ARGV[i], "oob_softecc_kw")) else if (sw_ecc && !strcmp(CMD_ARGV[i], "oob_softecc_kw"))
state->oob_format |= NAND_OOB_SW_ECC_KW; state->oob_format |= NAND_OOB_SW_ECC_KW;
else else {
{
command_print(CMD_CTX, "unknown option: %s", CMD_ARGV[i]); command_print(CMD_CTX, "unknown option: %s", CMD_ARGV[i]);
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
@ -179,8 +167,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if (!need_size) if (!need_size) {
{
int filesize; int filesize;
retval = fileio_size(&state->fileio, &filesize); retval = fileio_size(&state->fileio, &filesize);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -202,28 +189,23 @@ int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s)
size_t total_read = 0; size_t total_read = 0;
size_t one_read; size_t one_read;
if (NULL != s->page) if (NULL != s->page) {
{
fileio_read(&s->fileio, s->page_size, s->page, &one_read); fileio_read(&s->fileio, s->page_size, s->page, &one_read);
if (one_read < s->page_size) if (one_read < s->page_size)
memset(s->page + one_read, 0xff, s->page_size - one_read); memset(s->page + one_read, 0xff, s->page_size - one_read);
total_read += one_read; total_read += one_read;
} }
if (s->oob_format & NAND_OOB_SW_ECC) if (s->oob_format & NAND_OOB_SW_ECC) {
{
uint8_t ecc[3]; uint8_t ecc[3];
memset(s->oob, 0xff, s->oob_size); memset(s->oob, 0xff, s->oob_size);
for (uint32_t i = 0, j = 0; i < s->page_size; i += 256) for (uint32_t i = 0, j = 0; i < s->page_size; i += 256) {
{
nand_calculate_ecc(nand, s->page + i, ecc); nand_calculate_ecc(nand, s->page + i, ecc);
s->oob[s->eccpos[j++]] = ecc[0]; s->oob[s->eccpos[j++]] = ecc[0];
s->oob[s->eccpos[j++]] = ecc[1]; s->oob[s->eccpos[j++]] = ecc[1];
s->oob[s->eccpos[j++]] = ecc[2]; s->oob[s->eccpos[j++]] = ecc[2];
} }
} } else if (s->oob_format & NAND_OOB_SW_ECC_KW) {
else if (s->oob_format & NAND_OOB_SW_ECC_KW)
{
/* /*
* In this case eccpos is not used as * In this case eccpos is not used as
* the ECC data is always stored contigously * the ECC data is always stored contigously
@ -232,14 +214,11 @@ int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s)
*/ */
uint8_t *ecc = s->oob + s->oob_size - s->page_size / 512 * 10; uint8_t *ecc = s->oob + s->oob_size - s->page_size / 512 * 10;
memset(s->oob, 0xff, s->oob_size); memset(s->oob, 0xff, s->oob_size);
for (uint32_t i = 0; i < s->page_size; i += 512) for (uint32_t i = 0; i < s->page_size; i += 512) {
{
nand_calculate_ecc_kw(nand, s->page + i, ecc); nand_calculate_ecc_kw(nand, s->page + i, ecc);
ecc += 10; ecc += 10;
} }
} } else if (NULL != s->oob) {
else if (NULL != s->oob)
{
fileio_read(&s->fileio, s->oob_size, s->oob, &one_read); fileio_read(&s->fileio, s->oob_size, s->oob, &one_read);
if (one_read < s->oob_size) if (one_read < s->oob_size)
memset(s->oob + one_read, 0xff, s->oob_size - one_read); memset(s->oob + one_read, 0xff, s->oob_size - one_read);
@ -247,4 +226,3 @@ int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s)
} }
return total_read; return total_read;
} }

View File

@ -16,6 +16,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NAND_FILEIO_H #ifndef FLASH_NAND_FILEIO_H
#define FLASH_NAND_FILEIO_H #define FLASH_NAND_FILEIO_H
@ -49,9 +50,9 @@ int nand_fileio_cleanup(struct nand_fileio_state *state);
int nand_fileio_finish(struct nand_fileio_state *state); int nand_fileio_finish(struct nand_fileio_state *state);
COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
struct nand_device **dev, enum fileio_access filemode, struct nand_device **dev, enum fileio_access filemode,
bool need_size, bool sw_ecc); bool need_size, bool sw_ecc);
int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s); int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s);
#endif // FLASH_NAND_FILEIO_H #endif /* FLASH_NAND_FILEIO_H */

View File

@ -16,6 +16,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NAND_IMP_H #ifndef FLASH_NAND_IMP_H
#define FLASH_NAND_IMP_H #define FLASH_NAND_IMP_H
@ -36,4 +37,4 @@ int nand_probe(struct nand_device *nand);
int nand_erase(struct nand_device *nand, int first_block, int last_block); int nand_erase(struct nand_device *nand, int first_block, int last_block);
int nand_build_bbt(struct nand_device *nand, int first, int last); int nand_build_bbt(struct nand_device *nand, int first, int last);
#endif // FLASH_NAND_IMP_H #endif /* FLASH_NAND_IMP_H */

File diff suppressed because it is too large Load Diff

View File

@ -17,18 +17,17 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef LPC3180_NAND_CONTROLLER_H #ifndef LPC3180_NAND_CONTROLLER_H
#define LPC3180_NAND_CONTROLLER_H #define LPC3180_NAND_CONTROLLER_H
enum lpc3180_selected_controller enum lpc3180_selected_controller {
{
LPC3180_NO_CONTROLLER, LPC3180_NO_CONTROLLER,
LPC3180_MLC_CONTROLLER, LPC3180_MLC_CONTROLLER,
LPC3180_SLC_CONTROLLER, LPC3180_SLC_CONTROLLER,
}; };
struct lpc3180_nand_controller struct lpc3180_nand_controller {
{
int osc_freq; int osc_freq;
enum lpc3180_selected_controller selected_controller; enum lpc3180_selected_controller selected_controller;
int is_bulk; int is_bulk;
@ -37,4 +36,4 @@ struct lpc3180_nand_controller
uint32_t sw_wp_upper_bound; uint32_t sw_wp_upper_bound;
}; };
#endif /*LPC3180_NAND_CONTROLLER_H */ #endif /*LPC3180_NAND_CONTROLLER_H */

View File

@ -25,6 +25,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -37,7 +38,7 @@ static int lpc32xx_reset(struct nand_device *nand);
static int lpc32xx_controller_ready(struct nand_device *nand, int timeout); static int lpc32xx_controller_ready(struct nand_device *nand, int timeout);
static int lpc32xx_tc_ready(struct nand_device *nand, int timeout); static int lpc32xx_tc_ready(struct nand_device *nand, int timeout);
extern int nand_correct_data(struct nand_device *nand, u_char *dat, extern int nand_correct_data(struct nand_device *nand, u_char *dat,
u_char *read_ecc, u_char *calc_ecc); u_char *read_ecc, u_char *calc_ecc);
/* These are offset with the working area in IRAM when using DMA to /* These are offset with the working area in IRAM when using DMA to
* read/write data to the SLC controller. * read/write data to the SLC controller.
@ -74,9 +75,8 @@ static dmac_ll_t dmalist[(2048/256) * 2 + 1];
*/ */
NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command) NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command)
{ {
if (CMD_ARGC < 3) { if (CMD_ARGC < 3)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
uint32_t osc_freq; uint32_t osc_freq;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
@ -89,8 +89,8 @@ NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command)
if ((lpc32xx_info->osc_freq < 1000) || (lpc32xx_info->osc_freq > 20000)) if ((lpc32xx_info->osc_freq < 1000) || (lpc32xx_info->osc_freq > 20000))
LOG_WARNING("LPC32xx oscillator frequency should be between " LOG_WARNING("LPC32xx oscillator frequency should be between "
"1000 and 20000 kHz, was %i", "1000 and 20000 kHz, was %i",
lpc32xx_info->osc_freq); lpc32xx_info->osc_freq);
lpc32xx_info->selected_controller = LPC32xx_NO_CONTROLLER; lpc32xx_info->selected_controller = LPC32xx_NO_CONTROLLER;
lpc32xx_info->sw_write_protection = 0; lpc32xx_info->sw_write_protection = 0;
@ -113,18 +113,18 @@ static int lpc32xx_pll(int fclkin, uint32_t pll_ctrl)
if (!lock) if (!lock)
LOG_WARNING("PLL is not locked"); LOG_WARNING("PLL is not locked");
if (!bypass && direct) /* direct mode */ if (!bypass && direct) /* direct mode */
return (m * fclkin) / n; return (m * fclkin) / n;
if (bypass && !direct) /* bypass mode */ if (bypass && !direct) /* bypass mode */
return fclkin / (2 * p); return fclkin / (2 * p);
if (bypass & direct) /* direct bypass mode */ if (bypass & direct) /* direct bypass mode */
return fclkin; return fclkin;
if (feedback) /* integer mode */ if (feedback) /* integer mode */
return m * (fclkin / n); return m * (fclkin / n);
else /* non-integer mode */ else /* non-integer mode */
return (m / (2 * p)) * (fclkin / n); return (m / (2 * p)) * (fclkin / n);
} }
@ -160,9 +160,9 @@ static float lpc32xx_cycle_time(struct nand_device *nand)
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if ((pwr_ctrl & (1 << 2)) == 0) { /* DIRECT RUN mode */ if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
hclk = sysclk; hclk = sysclk;
} else { else {
retval = target_read_u32(target, 0x40004058, &hclkpll_ctrl); retval = target_read_u32(target, 0x40004058, &hclkpll_ctrl);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not read HCLKPLL_CTRL"); LOG_ERROR("could not read HCLKPLL_CTRL");
@ -176,9 +176,9 @@ static float lpc32xx_cycle_time(struct nand_device *nand)
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */ if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1); hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1);
else /* HCLK uses HCLK_PLL */ else /* HCLK uses HCLK_PLL */
hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3)); hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3));
} }
@ -200,7 +200,7 @@ static int lpc32xx_init(struct nand_device *nand)
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx " LOG_ERROR("target must be halted to use LPC32xx "
"NAND flash controller"); "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -226,7 +226,7 @@ static int lpc32xx_init(struct nand_device *nand)
/* select MLC controller if none is currently selected */ /* select MLC controller if none is currently selected */
if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) { if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
LOG_DEBUG("no LPC32xx NAND flash controller selected, " LOG_DEBUG("no LPC32xx NAND flash controller selected, "
"using default 'slc'"); "using default 'slc'");
lpc32xx_info->selected_controller = LPC32xx_SLC_CONTROLLER; lpc32xx_info->selected_controller = LPC32xx_SLC_CONTROLLER;
} }
@ -291,13 +291,13 @@ static int lpc32xx_init(struct nand_device *nand)
/* MLC_TIME_REG */ /* MLC_TIME_REG */
retval = target_write_u32(target, 0x200b8034, retval = target_write_u32(target, 0x200b8034,
(twp & 0xf) (twp & 0xf)
| ((twh & 0xf) << 4) | ((twh & 0xf) << 4)
| ((trp & 0xf) << 8) | ((trp & 0xf) << 8)
| ((treh & 0xf) << 12) | ((treh & 0xf) << 12)
| ((trhz & 0x7) << 16) | ((trhz & 0x7) << 16)
| ((trbwb & 0x1f) << 19) | ((trbwb & 0x1f) << 19)
| ((tcea & 0x3) << 24)); | ((tcea & 0x3) << 24));
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_TIME_REG"); LOG_ERROR("could not set MLC_TIME_REG");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -334,7 +334,7 @@ static int lpc32xx_init(struct nand_device *nand)
WIDTH = bus_width) WIDTH = bus_width)
*/ */
retval = target_write_u32(target, 0x20020014, retval = target_write_u32(target, 0x20020014,
0x3e | (bus_width == 16) ? 1 : 0); 0x3e | (bus_width == 16) ? 1 : 0);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set SLC_CFG"); LOG_ERROR("could not set SLC_CFG");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -374,14 +374,14 @@ static int lpc32xx_init(struct nand_device *nand)
/* SLC_TAC: SLC timing arcs register */ /* SLC_TAC: SLC timing arcs register */
retval = target_write_u32(target, 0x2002002c, retval = target_write_u32(target, 0x2002002c,
(r_setup & 0xf) (r_setup & 0xf)
| ((r_hold & 0xf) << 4) | ((r_hold & 0xf) << 4)
| ((r_width & 0xf) << 8) | ((r_width & 0xf) << 8)
| ((r_rdy & 0xf) << 12) | ((r_rdy & 0xf) << 12)
| ((w_setup & 0xf) << 16) | ((w_setup & 0xf) << 16)
| ((w_hold & 0xf) << 20) | ((w_hold & 0xf) << 20)
| ((w_width & 0xf) << 24) | ((w_width & 0xf) << 24)
| ((w_rdy & 0xf) << 28)); | ((w_rdy & 0xf) << 28));
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set SLC_TAC"); LOG_ERROR("could not set SLC_TAC");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -399,7 +399,7 @@ static int lpc32xx_reset(struct nand_device *nand)
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use " LOG_ERROR("target must be halted to use "
"LPC32xx NAND flash controller"); "LPC32xx NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -416,7 +416,7 @@ static int lpc32xx_reset(struct nand_device *nand)
if (!lpc32xx_controller_ready(nand, 100)) { if (!lpc32xx_controller_ready(nand, 100)) {
LOG_ERROR("LPC32xx MLC NAND controller timed out " LOG_ERROR("LPC32xx MLC NAND controller timed out "
"after reset"); "after reset");
return ERROR_NAND_OPERATION_TIMEOUT; return ERROR_NAND_OPERATION_TIMEOUT;
} }
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
@ -427,10 +427,9 @@ static int lpc32xx_reset(struct nand_device *nand)
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (!lpc32xx_controller_ready(nand, 100)) if (!lpc32xx_controller_ready(nand, 100)) {
{
LOG_ERROR("LPC32xx SLC NAND controller timed out " LOG_ERROR("LPC32xx SLC NAND controller timed out "
"after reset"); "after reset");
return ERROR_NAND_OPERATION_TIMEOUT; return ERROR_NAND_OPERATION_TIMEOUT;
} }
} }
@ -446,7 +445,7 @@ static int lpc32xx_command(struct nand_device *nand, uint8_t command)
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use " LOG_ERROR("target must be halted to use "
"LPC32xx NAND flash controller"); "LPC32xx NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -480,7 +479,7 @@ static int lpc32xx_address(struct nand_device *nand, uint8_t address)
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use " LOG_ERROR("target must be halted to use "
"LPC32xx NAND flash controller"); "LPC32xx NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -514,7 +513,7 @@ static int lpc32xx_write_data(struct nand_device *nand, uint16_t data)
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use " LOG_ERROR("target must be halted to use "
"LPC32xx NAND flash controller"); "LPC32xx NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -548,7 +547,7 @@ static int lpc32xx_read_data(struct nand_device *nand, void *data)
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx " LOG_ERROR("target must be halted to use LPC32xx "
"NAND flash controller"); "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -591,8 +590,8 @@ static int lpc32xx_read_data(struct nand_device *nand, void *data)
} }
static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page, static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
struct target *target = nand->target; struct target *target = nand->target;
int retval; int retval;
@ -623,7 +622,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
retval = target_write_u32(target, 0x200b8004, retval = target_write_u32(target, 0x200b8004,
(page >> 8) & 0xff); (page >> 8) & 0xff);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -631,7 +630,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
if (nand->address_cycles == 4) { if (nand->address_cycles == 4) {
retval = target_write_u32(target, 0x200b8004, retval = target_write_u32(target, 0x200b8004,
(page >> 16) & 0xff); (page >> 16) & 0xff);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -657,7 +656,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
retval = target_write_u32(target, 0x200b8004, retval = target_write_u32(target, 0x200b8004,
(page >> 8) & 0xff); (page >> 8) & 0xff);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -717,7 +716,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
if (!lpc32xx_controller_ready(nand, 1000)) { if (!lpc32xx_controller_ready(nand, 1000)) {
LOG_ERROR("timeout while waiting for " LOG_ERROR("timeout while waiting for "
"completion of auto encode cycle"); "completion of auto encode cycle");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
} }
@ -729,14 +728,15 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if ((retval = nand_read_status(nand, &status)) != ERROR_OK) { retval = nand_read_status(nand, &status);
if (retval != ERROR_OK) {
LOG_ERROR("couldn't read status"); LOG_ERROR("couldn't read status");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (status & NAND_STATUS_FAIL) { if (status & NAND_STATUS_FAIL) {
LOG_ERROR("write operation didn't pass, status: 0x%2.2x", LOG_ERROR("write operation didn't pass, status: 0x%2.2x",
status); status);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -749,7 +749,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
* target. * target.
*/ */
static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size, static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
int do_read) int do_read)
{ {
uint32_t i, dmasrc, ctrl, ecc_ctrl, oob_ctrl, dmadst; uint32_t i, dmasrc, ctrl, ecc_ctrl, oob_ctrl, dmadst;
@ -794,7 +794,7 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
*/ */
ctrl = (0x40 | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24 ctrl = (0x40 | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
| 0 << 25 | 0 << 26 | 0 << 27 | 0 << 31); | 0 << 25 | 0 << 26 | 0 << 27 | 0 << 31);
/* DMACCxControl = /* DMACCxControl =
TransferSize =1, TransferSize =1,
@ -809,7 +809,7 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
Terminal count interrupt enable bit = 0 Terminal count interrupt enable bit = 0
*/ */
ecc_ctrl = 0x01 | 1 << 12 | 1 << 15 | 2 << 18 | 2 << 21 | 0 << 24 ecc_ctrl = 0x01 | 1 << 12 | 1 << 15 | 2 << 18 | 2 << 21 | 0 << 24
| 0 << 25 | 0 << 26 | 1 << 27 | 0 << 31; | 0 << 25 | 0 << 26 | 1 << 27 | 0 << 31;
/* DMACCxControl = /* DMACCxControl =
TransferSize =16 for lp or 4 for sp, TransferSize =16 for lp or 4 for sp,
@ -824,18 +824,18 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
Terminal count interrupt enable bit = 1 // set on last Terminal count interrupt enable bit = 1 // set on last
*/ */
oob_ctrl = (page_size == 2048 ? 0x10 : 0x04) oob_ctrl = (page_size == 2048 ? 0x10 : 0x04)
| 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24 | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
| 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31; | 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31;
if (do_read) { if (do_read) {
ctrl |= 1 << 27; /* Destination increment = 1 */ ctrl |= 1 << 27;/* Destination increment = 1 */
oob_ctrl |= 1 << 27; /* Destination increment = 1 */ oob_ctrl |= 1 << 27; /* Destination increment = 1 */
dmasrc = 0x20020038; /* SLC_DMA_DATA */ dmasrc = 0x20020038; /* SLC_DMA_DATA */
dmadst = target_mem_base + DATA_OFFS; dmadst = target_mem_base + DATA_OFFS;
} else { } else {
ctrl |= 1 << 26; /* Source increment = 1 */ ctrl |= 1 << 26;/* Source increment = 1 */
oob_ctrl |= 1 << 26; /* Source increment = 1 */ oob_ctrl |= 1 << 26; /* Source increment = 1 */
dmasrc = target_mem_base + DATA_OFFS; dmasrc = target_mem_base + DATA_OFFS;
dmadst = 0x20020038; /* SLC_DMA_DATA */ dmadst = 0x20020038; /* SLC_DMA_DATA */
} }
/* /*
* Write Operation Sequence for Small Block NAND * Write Operation Sequence for Small Block NAND
@ -865,40 +865,38 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
* data & 32 bytes of ECC data. * data & 32 bytes of ECC data.
* 2. X'fer 64 bytes of Spare area from Flash to Memory. * 2. X'fer 64 bytes of Spare area from Flash to Memory.
*/ */
for (i = 0; i < page_size/0x100; i++) for (i = 0; i < page_size/0x100; i++) {
{
dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256)); dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256));
dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst); dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst);
dmalist[i*2].next_lli = dmalist[i*2].next_lli =
target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t); target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t);
dmalist[i*2].next_ctrl = ctrl; dmalist[i*2].next_ctrl = ctrl;
dmalist[(i*2) + 1].dma_src = 0x20020034; /* SLC_ECC */ dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */
dmalist[(i*2) + 1].dma_dest = dmalist[(i*2) + 1].dma_dest =
target_mem_base + ECC_OFFS + i * 4; target_mem_base + ECC_OFFS + i * 4;
dmalist[(i*2) + 1].next_lli = dmalist[(i*2) + 1].next_lli =
target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t); target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t);
dmalist[(i*2) + 1].next_ctrl = ecc_ctrl; dmalist[(i*2) + 1].next_ctrl = ecc_ctrl;
} }
if (do_read) if (do_read)
{
dmadst = target_mem_base + SPARE_OFFS; dmadst = target_mem_base + SPARE_OFFS;
} else { else {
dmasrc = target_mem_base + SPARE_OFFS; dmasrc = target_mem_base + SPARE_OFFS;
dmalist[(i*2) - 1].next_lli = 0; /* last link = null on write */ dmalist[(i*2) - 1].next_lli = 0;/* last link = null on write */
dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */ dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */
} }
dmalist[i*2].dma_src = dmasrc; dmalist[i*2].dma_src = dmasrc;
dmalist[i*2].dma_dest = dmadst; dmalist[i*2].dma_dest = dmadst;
dmalist[i*2].next_lli = 0; dmalist[i*2].next_lli = 0;
dmalist[i*2].next_ctrl = oob_ctrl; dmalist[i*2].next_ctrl = oob_ctrl;
return (i*2 + 1); /* Number of descriptors */ return i * 2 + 1; /* Number of descriptors */
} }
static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count, static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count,
int do_wait) int do_wait)
{ {
struct target *target = nand->target; struct target *target = nand->target;
int retval; int retval;
@ -928,8 +926,8 @@ static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count,
H=0 H=0
*/ */
retval = target_write_u32(target, 0x31000110, retval = target_write_u32(target, 0x31000110,
1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
| 0<<15 | 0<<16 | 0<<18); | 0<<15 | 0<<16 | 0<<18);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not set DMACC0Config"); LOG_ERROR("Could not set DMACC0Config");
return retval; return retval;
@ -990,14 +988,13 @@ static int lpc32xx_dma_ready(struct nand_device *nand, int timeout)
} }
if ((tc_stat | err_stat) & 1) { if ((tc_stat | err_stat) & 1) {
LOG_DEBUG("lpc32xx_dma_ready count=%d", LOG_DEBUG("lpc32xx_dma_ready count=%d",
timeout); timeout);
if (err_stat & 1) { if (err_stat & 1) {
LOG_ERROR("lpc32xx_dma_ready " LOG_ERROR("lpc32xx_dma_ready "
"DMA error, aborted"); "DMA error, aborted");
return 0; return 0;
} else { } else
return 1; return 1;
}
} }
alive_sleep(1); alive_sleep(1);
@ -1006,8 +1003,8 @@ static int lpc32xx_dma_ready(struct nand_device *nand, int timeout)
return 0; return 0;
} }
static uint32_t slc_ecc_copy_to_buffer(uint8_t * spare, static uint32_t slc_ecc_copy_to_buffer(uint8_t *spare,
const uint32_t * ecc, int count) const uint32_t *ecc, int count)
{ {
int i; int i;
for (i = 0; i < (count * 3); i += 3) { for (i = 0; i < (count * 3); i += 3) {
@ -1025,8 +1022,8 @@ static void lpc32xx_dump_oob(uint8_t *oob, uint32_t oob_size)
int addr = 0; int addr = 0;
while (oob_size > 0) { while (oob_size > 0) {
LOG_DEBUG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", addr, LOG_DEBUG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", addr,
oob[0], oob[1], oob[2], oob[3], oob[0], oob[1], oob[2], oob[3],
oob[4], oob[5], oob[6], oob[7]); oob[4], oob[5], oob[6], oob[7]);
oob += 8; oob += 8;
addr += 8; addr += 8;
oob_size -= 8; oob_size -= 8;
@ -1034,18 +1031,18 @@ static void lpc32xx_dump_oob(uint8_t *oob, uint32_t oob_size)
} }
static int lpc32xx_write_page_slc(struct nand_device *nand, static int lpc32xx_write_page_slc(struct nand_device *nand,
struct working_area *pworking_area, struct working_area *pworking_area,
uint32_t page, uint8_t *data, uint32_t page, uint8_t *data,
uint32_t data_size, uint8_t *oob, uint32_t data_size, uint8_t *oob,
uint32_t oob_size) uint32_t oob_size)
{ {
struct target *target = nand->target; struct target *target = nand->target;
int retval; int retval;
uint32_t target_mem_base; uint32_t target_mem_base;
LOG_DEBUG("SLC write page %x data=%d, oob=%d, " LOG_DEBUG("SLC write page %x data=%d, oob=%d, "
"data_size=%d, oob_size=%d", "data_size=%d, oob_size=%d",
page, data != 0, oob != 0, data_size, oob_size); page, data != 0, oob != 0, data_size, oob_size);
target_mem_base = pworking_area->address; target_mem_base = pworking_area->address;
/* /*
@ -1060,7 +1057,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
break; break;
} }
if (all_ff) if (all_ff)
return ERROR_OK; return ERROR_OK;
} }
/* Make the dma descriptors in local memory */ /* Make the dma descriptors in local memory */
int nll = lpc32xx_make_dma_list(target_mem_base, nand->page_size, 0); int nll = lpc32xx_make_dma_list(target_mem_base, nand->page_size, 0);
@ -1068,8 +1065,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
XXX: Assumes host and target have same byte sex. XXX: Assumes host and target have same byte sex.
*/ */
retval = target_write_memory(target, target_mem_base, 4, retval = target_write_memory(target, target_mem_base, 4,
nll * sizeof(dmac_ll_t) / 4, nll * sizeof(dmac_ll_t) / 4,
(uint8_t *)dmalist); (uint8_t *)dmalist);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptors to IRAM"); LOG_ERROR("Could not write DMA descriptors to IRAM");
return retval; return retval;
@ -1081,13 +1078,13 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
return retval; return retval;
} }
/* SLC_CFG = /* SLC_CFG =
Force nCE assert, Force nCE assert,
DMA ECC enabled, DMA ECC enabled,
ECC enabled, ECC enabled,
DMA burst enabled, DMA burst enabled,
DMA write to SLC, DMA write to SLC,
WIDTH = bus_width WIDTH = bus_width
*/ */
retval = target_write_u32(target, 0x20020014, 0x3c); retval = target_write_u32(target, 0x20020014, 0x3c);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
@ -1100,8 +1097,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
memset(fdata, 0xFF, nand->page_size); memset(fdata, 0xFF, nand->page_size);
memcpy(fdata, data, data_size); memcpy(fdata, data, data_size);
retval = target_write_memory(target, retval = target_write_memory(target,
target_mem_base + DATA_OFFS, target_mem_base + DATA_OFFS,
4, nand->page_size/4, fdata); 4, nand->page_size/4, fdata);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write data to IRAM"); LOG_ERROR("Could not write data to IRAM");
return retval; return retval;
@ -1109,8 +1106,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
/* Write first decriptor to DMA controller */ /* Write first decriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4, retval = target_write_memory(target, 0x31000100, 4,
sizeof(dmac_ll_t) / 4, sizeof(dmac_ll_t) / 4,
(uint8_t *)dmalist); (uint8_t *)dmalist);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptor to DMAC"); LOG_ERROR("Could not write DMA descriptor to DMAC");
return retval; return retval;
@ -1130,20 +1127,20 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
LOG_ERROR("Data DMA failed during write"); LOG_ERROR("Data DMA failed during write");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
} /* data xfer */ } /* data xfer */
/* Copy OOB to iram */ /* Copy OOB to iram */
static uint8_t foob[64]; static uint8_t foob[64];
int foob_size = nand->page_size == 2048 ? 64 : 16; int foob_size = nand->page_size == 2048 ? 64 : 16;
memset(foob, 0xFF, foob_size); memset(foob, 0xFF, foob_size);
if (oob) { /* Raw mode */ if (oob) /* Raw mode */
memcpy(foob, oob, oob_size); memcpy(foob, oob, oob_size);
} else { else {
/* Get HW generated ECC, made while writing data */ /* Get HW generated ECC, made while writing data */
int ecc_count = nand->page_size == 2048 ? 8 : 2; int ecc_count = nand->page_size == 2048 ? 8 : 2;
static uint32_t hw_ecc[8]; static uint32_t hw_ecc[8];
retval = target_read_memory(target, target_mem_base + ECC_OFFS, retval = target_read_memory(target, target_mem_base + ECC_OFFS,
4, ecc_count, (uint8_t *)hw_ecc); 4, ecc_count, (uint8_t *)hw_ecc);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Reading hw generated ECC from IRAM failed"); LOG_ERROR("Reading hw generated ECC from IRAM failed");
return retval; return retval;
@ -1158,7 +1155,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
lpc32xx_dump_oob(foob, foob_size); lpc32xx_dump_oob(foob, foob_size);
} }
retval = target_write_memory(target, target_mem_base + SPARE_OFFS, 4, retval = target_write_memory(target, target_mem_base + SPARE_OFFS, 4,
foob_size / 4, foob); foob_size / 4, foob);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Writing OOB to IRAM failed"); LOG_ERROR("Writing OOB to IRAM failed");
return retval; return retval;
@ -1166,8 +1163,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
/* Write OOB decriptor to DMA controller */ /* Write OOB decriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4, retval = target_write_memory(target, 0x31000100, 4,
sizeof(dmac_ll_t) / 4, sizeof(dmac_ll_t) / 4,
(uint8_t *)(&dmalist[nll-1])); (uint8_t *)(&dmalist[nll-1]));
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write OOB DMA descriptor to DMAC"); LOG_ERROR("Could not write OOB DMA descriptor to DMAC");
return retval; return retval;
@ -1183,18 +1180,18 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
return retval; return retval;
} }
/* DMACCxConfig= /* DMACCxConfig=
E=1, * E=1,
SrcPeripheral = 1 (SLC), * SrcPeripheral = 1 (SLC),
DestPeripheral = 1 (SLC), * DestPeripheral = 1 (SLC),
FlowCntrl = 2 (Pher -> Mem, DMA), * FlowCntrl = 2 (Pher -> Mem, DMA),
IE = 0, * IE = 0,
ITC = 0, * ITC = 0,
L= 0, * L= 0,
H=0 * H=0
*/ */
retval = target_write_u32(target, 0x31000110, retval = target_write_u32(target, 0x31000110,
1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
| 0<<15 | 0<<16 | 0<<18); | 0<<15 | 0<<16 | 0<<18);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not set DMACC0Config"); LOG_ERROR("Could not set DMACC0Config");
return retval; return retval;
@ -1202,7 +1199,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
/* Wait finish */ /* Wait finish */
if (!lpc32xx_tc_ready(nand, 100)) { if (!lpc32xx_tc_ready(nand, 100)) {
LOG_ERROR("timeout while waiting for " LOG_ERROR("timeout while waiting for "
"completion of DMA"); "completion of DMA");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
} else { } else {
@ -1225,8 +1222,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
} }
static int lpc32xx_write_page(struct nand_device *nand, uint32_t page, static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -1234,7 +1231,7 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx " LOG_ERROR("target must be halted to use LPC32xx "
"NAND flash controller"); "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -1244,13 +1241,13 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
} else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) { } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
if (!data && oob) { if (!data && oob) {
LOG_ERROR("LPC32xx MLC controller can't write " LOG_ERROR("LPC32xx MLC controller can't write "
"OOB data only"); "OOB data only");
return ERROR_NAND_OPERATION_NOT_SUPPORTED; return ERROR_NAND_OPERATION_NOT_SUPPORTED;
} }
if (oob && (oob_size > 24)) { if (oob && (oob_size > 24)) {
LOG_ERROR("LPC32xx MLC controller can't write more " LOG_ERROR("LPC32xx MLC controller can't write more "
"than 6 bytes for each quarter's OOB data"); "than 6 bytes for each quarter's OOB data");
return ERROR_NAND_OPERATION_NOT_SUPPORTED; return ERROR_NAND_OPERATION_NOT_SUPPORTED;
} }
@ -1260,7 +1257,7 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
} }
retval = lpc32xx_write_page_mlc(nand, page, data, data_size, retval = lpc32xx_write_page_mlc(nand, page, data, data_size,
oob, oob_size); oob, oob_size);
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
struct working_area *pworking_area; struct working_area *pworking_area;
if (!data && oob) { if (!data && oob) {
@ -1270,18 +1267,18 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
* Anyway the code supports the oob only mode below. * Anyway the code supports the oob only mode below.
*/ */
return nand_write_page_raw(nand, page, data, return nand_write_page_raw(nand, page, data,
data_size, oob, oob_size); data_size, oob, oob_size);
} }
retval = target_alloc_working_area(target, retval = target_alloc_working_area(target,
nand->page_size + DATA_OFFS, nand->page_size + DATA_OFFS,
&pworking_area); &pworking_area);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Can't allocate working area in " LOG_ERROR("Can't allocate working area in "
"LPC internal RAM"); "LPC internal RAM");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
retval = lpc32xx_write_page_slc(nand, pworking_area, page, retval = lpc32xx_write_page_slc(nand, pworking_area, page,
data, data_size, oob, oob_size); data, data_size, oob, oob_size);
target_free_working_area(target, pworking_area); target_free_working_area(target, pworking_area);
} }
@ -1289,8 +1286,8 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
} }
static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page, static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
struct target *target = nand->target; struct target *target = nand->target;
static uint8_t page_buffer[2048]; static uint8_t page_buffer[2048];
@ -1317,8 +1314,8 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (nand->page_size == 512) { if (nand->page_size == 512) {
/* small page device */ /* small page device
/* MLC_ADDR = 0x0 (one column cycle) */ * MLC_ADDR = 0x0 (one column cycle) */
retval = target_write_u32(target, 0x200b8004, 0x0); retval = target_write_u32(target, 0x200b8004, 0x0);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
@ -1332,7 +1329,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
retval = target_write_u32(target, 0x200b8004, retval = target_write_u32(target, 0x200b8004,
(page >> 8) & 0xff); (page >> 8) & 0xff);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -1340,15 +1337,15 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
if (nand->address_cycles == 4) { if (nand->address_cycles == 4) {
retval = target_write_u32(target, 0x200b8004, retval = target_write_u32(target, 0x200b8004,
(page >> 16) & 0xff); (page >> 16) & 0xff);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
} }
} else { } else {
/* large page device */ /* large page device
/* MLC_ADDR = 0x0 (two column cycles) */ * MLC_ADDR = 0x0 (two column cycles) */
retval = target_write_u32(target, 0x200b8004, 0x0); retval = target_write_u32(target, 0x200b8004, 0x0);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
@ -1367,7 +1364,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
retval = target_write_u32(target, 0x200b8004, retval = target_write_u32(target, 0x200b8004,
(page >> 8) & 0xff); (page >> 8) & 0xff);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -1375,7 +1372,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
/* MLC_CMD = Read Start */ /* MLC_CMD = Read Start */
retval = target_write_u32(target, 0x200b8000, retval = target_write_u32(target, 0x200b8000,
NAND_CMD_READSTART); NAND_CMD_READSTART);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_CMD"); LOG_ERROR("could not set MLC_CMD");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -1392,7 +1389,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
if (!lpc32xx_controller_ready(nand, 1000)) { if (!lpc32xx_controller_ready(nand, 1000)) {
LOG_ERROR("timeout while waiting for " LOG_ERROR("timeout while waiting for "
"completion of auto decode cycle"); "completion of auto decode cycle");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -1405,17 +1402,17 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
if (mlc_isr & 0x8) { if (mlc_isr & 0x8) {
if (mlc_isr & 0x40) { if (mlc_isr & 0x40) {
LOG_ERROR("uncorrectable error detected: " LOG_ERROR("uncorrectable error detected: "
"0x%2.2x", (unsigned)mlc_isr); "0x%2.2x", (unsigned)mlc_isr);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
LOG_WARNING("%i symbol error detected and corrected", LOG_WARNING("%i symbol error detected and corrected",
((int)(((mlc_isr & 0x30) >> 4) + 1))); ((int)(((mlc_isr & 0x30) >> 4) + 1)));
} }
if (data) { if (data) {
retval = target_read_memory(target, 0x200a8000, 4, 128, retval = target_read_memory(target, 0x200a8000, 4, 128,
page_buffer + page_bytes_done); page_buffer + page_bytes_done);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not read MLC_BUF (data)"); LOG_ERROR("could not read MLC_BUF (data)");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -1424,7 +1421,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
if (oob) { if (oob) {
retval = target_read_memory(target, 0x200a8000, 4, 4, retval = target_read_memory(target, 0x200a8000, 4, 4,
oob_buffer + oob_bytes_done); oob_buffer + oob_bytes_done);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not read MLC_BUF (oob)"); LOG_ERROR("could not read MLC_BUF (oob)");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -1445,17 +1442,17 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
} }
static int lpc32xx_read_page_slc(struct nand_device *nand, static int lpc32xx_read_page_slc(struct nand_device *nand,
struct working_area *pworking_area, struct working_area *pworking_area,
uint32_t page, uint8_t *data, uint32_t page, uint8_t *data,
uint32_t data_size, uint8_t *oob, uint32_t data_size, uint8_t *oob,
uint32_t oob_size) uint32_t oob_size)
{ {
struct target *target = nand->target; struct target *target = nand->target;
int retval; int retval;
uint32_t target_mem_base; uint32_t target_mem_base;
LOG_DEBUG("SLC read page %x data=%d, oob=%d", LOG_DEBUG("SLC read page %x data=%d, oob=%d",
page, data_size, oob_size); page, data_size, oob_size);
target_mem_base = pworking_area->address; target_mem_base = pworking_area->address;
@ -1465,8 +1462,8 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
XXX: Assumes host and target have same byte sex. XXX: Assumes host and target have same byte sex.
*/ */
retval = target_write_memory(target, target_mem_base, 4, retval = target_write_memory(target, target_mem_base, 4,
nll * sizeof(dmac_ll_t) / 4, nll * sizeof(dmac_ll_t) / 4,
(uint8_t *)dmalist); (uint8_t *)dmalist);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptors to IRAM"); LOG_ERROR("Could not write DMA descriptors to IRAM");
return retval; return retval;
@ -1478,13 +1475,13 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
return retval; return retval;
} }
/* SLC_CFG = /* SLC_CFG =
Force nCE assert, Force nCE assert,
DMA ECC enabled, DMA ECC enabled,
ECC enabled, ECC enabled,
DMA burst enabled, DMA burst enabled,
DMA read from SLC, DMA read from SLC,
WIDTH = bus_width WIDTH = bus_width
*/ */
retval = target_write_u32(target, 0x20020014, 0x3e); retval = target_write_u32(target, 0x20020014, 0x3e);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
@ -1494,7 +1491,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
/* Write first decriptor to DMA controller */ /* Write first decriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4, retval = target_write_memory(target, 0x31000100, 4,
sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist); sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptor to DMAC"); LOG_ERROR("Could not write DMA descriptor to DMAC");
return retval; return retval;
@ -1512,7 +1509,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
/* Copy data from iram */ /* Copy data from iram */
if (data) { if (data) {
retval = target_read_memory(target, target_mem_base + DATA_OFFS, retval = target_read_memory(target, target_mem_base + DATA_OFFS,
4, data_size/4, data); 4, data_size/4, data);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not read data from IRAM"); LOG_ERROR("Could not read data from IRAM");
return retval; return retval;
@ -1521,8 +1518,8 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
if (oob) { if (oob) {
/* No error correction, just return data as read from flash */ /* No error correction, just return data as read from flash */
retval = target_read_memory(target, retval = target_read_memory(target,
target_mem_base + SPARE_OFFS, 4, target_mem_base + SPARE_OFFS, 4,
oob_size/4, oob); oob_size/4, oob);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not read OOB from IRAM"); LOG_ERROR("Could not read OOB from IRAM");
return retval; return retval;
@ -1533,7 +1530,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
/* Copy OOB from flash, stored in IRAM */ /* Copy OOB from flash, stored in IRAM */
static uint8_t foob[64]; static uint8_t foob[64];
retval = target_read_memory(target, target_mem_base + SPARE_OFFS, retval = target_read_memory(target, target_mem_base + SPARE_OFFS,
4, nand->page_size == 2048 ? 16 : 4, foob); 4, nand->page_size == 2048 ? 16 : 4, foob);
lpc32xx_dump_oob(foob, nand->page_size == 2048 ? 64 : 16); lpc32xx_dump_oob(foob, nand->page_size == 2048 ? 64 : 16);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not read OOB from IRAM"); LOG_ERROR("Could not read OOB from IRAM");
@ -1541,9 +1538,9 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
} }
/* Copy ECC from HW, generated while reading */ /* Copy ECC from HW, generated while reading */
int ecc_count = nand->page_size == 2048 ? 8 : 2; int ecc_count = nand->page_size == 2048 ? 8 : 2;
static uint32_t hw_ecc[8]; /* max size */ static uint32_t hw_ecc[8]; /* max size */
retval = target_read_memory(target, target_mem_base + ECC_OFFS, 4, retval = target_read_memory(target, target_mem_base + ECC_OFFS, 4,
ecc_count, (uint8_t *)hw_ecc); ecc_count, (uint8_t *)hw_ecc);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not read hw generated ECC from IRAM"); LOG_ERROR("Could not read hw generated ECC from IRAM");
return retval; return retval;
@ -1551,7 +1548,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
static uint8_t ecc[24]; static uint8_t ecc[24];
slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count); slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count);
/* Copy ECC from flash using correct layout */ /* Copy ECC from flash using correct layout */
static uint8_t fecc[24]; /* max size */ static uint8_t fecc[24];/* max size */
int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout; int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout;
int i; int i;
for (i = 0; i < ecc_count * 3; i++) for (i = 0; i < ecc_count * 3; i++)
@ -1559,10 +1556,10 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
/* Compare ECC and possibly correct data */ /* Compare ECC and possibly correct data */
for (i = 0; i < ecc_count; i++) { for (i = 0; i < ecc_count; i++) {
retval = nand_correct_data(nand, data + 256*i, &fecc[i * 3], retval = nand_correct_data(nand, data + 256*i, &fecc[i * 3],
&ecc[i * 3]); &ecc[i * 3]);
if (retval > 0) if (retval > 0)
LOG_WARNING("error detected and corrected: %d/%d", LOG_WARNING("error detected and corrected: %d/%d",
page, i); page, i);
if (retval < 0) if (retval < 0)
break; break;
} }
@ -1576,8 +1573,8 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
} }
static int lpc32xx_read_page(struct nand_device *nand, uint32_t page, static int lpc32xx_read_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv; struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -1585,7 +1582,7 @@ static int lpc32xx_read_page(struct nand_device *nand, uint32_t page,
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx " LOG_ERROR("target must be halted to use LPC32xx "
"NAND flash controller"); "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -1598,21 +1595,21 @@ static int lpc32xx_read_page(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_NOT_SUPPORTED; return ERROR_NAND_OPERATION_NOT_SUPPORTED;
} }
retval = lpc32xx_read_page_mlc(nand, page, data, data_size, retval = lpc32xx_read_page_mlc(nand, page, data, data_size,
oob, oob_size); oob, oob_size);
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
struct working_area *pworking_area; struct working_area *pworking_area;
retval = target_alloc_working_area(target, retval = target_alloc_working_area(target,
nand->page_size + 0x200, nand->page_size + 0x200,
&pworking_area); &pworking_area);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Can't allocate working area in " LOG_ERROR("Can't allocate working area in "
"LPC internal RAM"); "LPC internal RAM");
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
retval = lpc32xx_read_page_slc(nand, pworking_area, page, retval = lpc32xx_read_page_slc(nand, pworking_area, page,
data, data_size, oob, oob_size); data, data_size, oob, oob_size);
target_free_working_area(target, pworking_area); target_free_working_area(target, pworking_area);
} }
return retval; return retval;
@ -1626,7 +1623,7 @@ static int lpc32xx_controller_ready(struct nand_device *nand, int timeout)
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx " LOG_ERROR("target must be halted to use LPC32xx "
"NAND flash controller"); "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -1645,7 +1642,7 @@ static int lpc32xx_controller_ready(struct nand_device *nand, int timeout)
if (status & 2) { if (status & 2) {
LOG_DEBUG("lpc32xx_controller_ready count=%d", LOG_DEBUG("lpc32xx_controller_ready count=%d",
timeout); timeout);
return 1; return 1;
} }
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
@ -1660,7 +1657,7 @@ static int lpc32xx_controller_ready(struct nand_device *nand, int timeout)
if (status & 1) { if (status & 1) {
LOG_DEBUG("lpc32xx_controller_ready count=%d", LOG_DEBUG("lpc32xx_controller_ready count=%d",
timeout); timeout);
return 1; return 1;
} }
} }
@ -1679,7 +1676,7 @@ static int lpc32xx_nand_ready(struct nand_device *nand, int timeout)
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx " LOG_ERROR("target must be halted to use LPC32xx "
"NAND flash controller"); "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -1699,7 +1696,7 @@ static int lpc32xx_nand_ready(struct nand_device *nand, int timeout)
if (status & 1) { if (status & 1) {
LOG_DEBUG("lpc32xx_nand_ready count end=%d", LOG_DEBUG("lpc32xx_nand_ready count end=%d",
timeout); timeout);
return 1; return 1;
} }
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) { } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
@ -1714,7 +1711,7 @@ static int lpc32xx_nand_ready(struct nand_device *nand, int timeout)
if (status & 1) { if (status & 1) {
LOG_DEBUG("lpc32xx_nand_ready count end=%d", LOG_DEBUG("lpc32xx_nand_ready count end=%d",
timeout); timeout);
return 1; return 1;
} }
} }
@ -1740,7 +1737,7 @@ static int lpc32xx_tc_ready(struct nand_device *nand, int timeout)
LOG_ERROR("Could not read SLC_INT_STAT"); LOG_ERROR("Could not read SLC_INT_STAT");
return 0; return 0;
} }
if (status & 2){ if (status & 2) {
LOG_DEBUG("lpc32xx_tc_ready count=%d", timeout); LOG_DEBUG("lpc32xx_tc_ready count=%d", timeout);
return 1; return 1;
} }
@ -1758,16 +1755,15 @@ COMMAND_HANDLER(handle_lpc32xx_select_command)
"no", "mlc", "slc" "no", "mlc", "slc"
}; };
if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) { if ((CMD_ARGC < 1) || (CMD_ARGC > 3))
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
unsigned num; unsigned num;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
struct nand_device *nand = get_nand_device_by_num(num); struct nand_device *nand = get_nand_device_by_num(num);
if (!nand) { if (!nand) {
command_print(CMD_CTX, "nand device '#%s' is out of bounds", command_print(CMD_CTX, "nand device '#%s' is out of bounds",
CMD_ARGV[0]); CMD_ARGV[0]);
return ERROR_OK; return ERROR_OK;
} }
@ -1780,13 +1776,12 @@ COMMAND_HANDLER(handle_lpc32xx_select_command)
} else if (strcmp(CMD_ARGV[1], "slc") == 0) { } else if (strcmp(CMD_ARGV[1], "slc") == 0) {
lpc32xx_info->selected_controller = lpc32xx_info->selected_controller =
LPC32xx_SLC_CONTROLLER; LPC32xx_SLC_CONTROLLER;
} else { } else
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
} }
command_print(CMD_CTX, "%s controller selected", command_print(CMD_CTX, "%s controller selected",
selected[lpc32xx_info->selected_controller]); selected[lpc32xx_info->selected_controller]);
return ERROR_OK; return ERROR_OK;
} }

View File

@ -17,18 +17,17 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef LPC32xx_NAND_CONTROLLER_H #ifndef LPC32xx_NAND_CONTROLLER_H
#define LPC32xx_NAND_CONTROLLER_H #define LPC32xx_NAND_CONTROLLER_H
enum lpc32xx_selected_controller enum lpc32xx_selected_controller {
{
LPC32xx_NO_CONTROLLER, LPC32xx_NO_CONTROLLER,
LPC32xx_MLC_CONTROLLER, LPC32xx_MLC_CONTROLLER,
LPC32xx_SLC_CONTROLLER, LPC32xx_SLC_CONTROLLER,
}; };
struct lpc32xx_nand_controller struct lpc32xx_nand_controller {
{
int osc_freq; int osc_freq;
enum lpc32xx_selected_controller selected_controller; enum lpc32xx_selected_controller selected_controller;
int sw_write_protection; int sw_write_protection;
@ -36,4 +35,4 @@ struct lpc32xx_nand_controller
uint32_t sw_wp_upper_bound; uint32_t sw_wp_upper_bound;
}; };
#endif /*LPC32xx_NAND_CONTROLLER_H */ #endif /*LPC32xx_NAND_CONTROLLER_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2009 by Alexei Babich * * Copyright (C) 2009 by Alexei Babich *
* Rezonans plc., Chelyabinsk, Russia * * Rezonans plc., Chelyabinsk, Russia *
@ -26,80 +25,77 @@
* Many thanks to Ben Dooks for writing s3c24xx driver. * Many thanks to Ben Dooks for writing s3c24xx driver.
*/ */
#define MX3_NF_BASE_ADDR 0xb8000000 #define MX3_NF_BASE_ADDR 0xb8000000
#define MX3_NF_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00) #define MX3_NF_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00)
#define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04) #define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04)
#define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06) #define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06)
#define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08) #define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08)
#define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a) #define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a)
#define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c) #define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c)
#define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e) #define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e)
#define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10) #define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10)
#define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12) #define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12)
#define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14) #define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14)
#define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16) #define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16)
#define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18) #define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18)
/* /*
* all bits not marked as self-clearing bit * all bits not marked as self-clearing bit
*/ */
#define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a) #define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a)
#define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c) #define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c)
#define MX3_NF_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000) #define MX3_NF_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000)
#define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200) #define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200)
#define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400) #define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400)
#define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600) #define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600)
#define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800) #define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800)
#define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810) #define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810)
#define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820) #define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820)
#define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830) #define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830)
#define MX3_NF_MAIN_BUFFER_LEN 512 #define MX3_NF_MAIN_BUFFER_LEN 512
#define MX3_NF_SPARE_BUFFER_LEN 16 #define MX3_NF_SPARE_BUFFER_LEN 16
#define MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2) #define MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2)
/* bits in MX3_NF_CFG1 register */ /* bits in MX3_NF_CFG1 register */
#define MX3_NF_BIT_SPARE_ONLY_EN (1<<2) #define MX3_NF_BIT_SPARE_ONLY_EN (1<<2)
#define MX3_NF_BIT_ECC_EN (1<<3) #define MX3_NF_BIT_ECC_EN (1<<3)
#define MX3_NF_BIT_INT_DIS (1<<4) #define MX3_NF_BIT_INT_DIS (1<<4)
#define MX3_NF_BIT_BE_EN (1<<5) #define MX3_NF_BIT_BE_EN (1<<5)
#define MX3_NF_BIT_RESET_EN (1<<6) #define MX3_NF_BIT_RESET_EN (1<<6)
#define MX3_NF_BIT_FORCE_CE (1<<7) #define MX3_NF_BIT_FORCE_CE (1<<7)
/* bits in MX3_NF_CFG2 register */ /* bits in MX3_NF_CFG2 register */
/*Flash Command Input*/ /*Flash Command Input*/
#define MX3_NF_BIT_OP_FCI (1<<0) #define MX3_NF_BIT_OP_FCI (1<<0)
/* /*
* Flash Address Input * Flash Address Input
*/ */
#define MX3_NF_BIT_OP_FAI (1<<1) #define MX3_NF_BIT_OP_FAI (1<<1)
/* /*
* Flash Data Input * Flash Data Input
*/ */
#define MX3_NF_BIT_OP_FDI (1<<2) #define MX3_NF_BIT_OP_FDI (1<<2)
/* see "enum mx_dataout_type" below */ /* see "enum mx_dataout_type" below */
#define MX3_NF_BIT_DATAOUT_TYPE(x) ((x)<<3) #define MX3_NF_BIT_DATAOUT_TYPE(x) ((x)<<3)
#define MX3_NF_BIT_OP_DONE (1<<15) #define MX3_NF_BIT_OP_DONE (1<<15)
#define MX3_CCM_CGR2 0x53f80028 #define MX3_CCM_CGR2 0x53f80028
#define MX3_GPR 0x43fac008 #define MX3_GPR 0x43fac008
#define MX3_PCSR 0x53f8000c #define MX3_PCSR 0x53f8000c
enum mx_dataout_type enum mx_dataout_type {
{
MX3_NF_DATAOUT_PAGE = 1, MX3_NF_DATAOUT_PAGE = 1,
MX3_NF_DATAOUT_NANDID = 2, MX3_NF_DATAOUT_NANDID = 2,
MX3_NF_DATAOUT_NANDSTATUS = 4, MX3_NF_DATAOUT_NANDSTATUS = 4,
}; };
enum mx_nf_finalize_action enum mx_nf_finalize_action {
{
MX3_NF_FIN_NONE, MX3_NF_FIN_NONE,
MX3_NF_FIN_DATAOUT, MX3_NF_FIN_DATAOUT,
}; };
struct mx3_nf_flags struct mx3_nf_flags {
{
unsigned host_little_endian:1; unsigned host_little_endian:1;
unsigned target_little_endian:1; unsigned target_little_endian:1;
unsigned nand_readonly:1; unsigned nand_readonly:1;
@ -107,8 +103,7 @@ struct mx3_nf_flags
unsigned hw_ecc_enabled:1; unsigned hw_ecc_enabled:1;
}; };
struct mx3_nf_controller struct mx3_nf_controller {
{
enum mx_dataout_type optype; enum mx_dataout_type optype;
enum mx_nf_finalize_action fin; enum mx_nf_finalize_action fin;
struct mx3_nf_flags flags; struct mx3_nf_flags flags;

View File

@ -49,12 +49,12 @@
#include "mxc.h" #include "mxc.h"
#include <target/target.h> #include <target/target.h>
#define OOB_SIZE 64 #define OOB_SIZE 64
#define nfc_is_v1() (mxc_nf_info->mxc_version == MXC_VERSION_MX27 || \ #define nfc_is_v1() (mxc_nf_info->mxc_version == MXC_VERSION_MX27 || \
mxc_nf_info->mxc_version == MXC_VERSION_MX31) mxc_nf_info->mxc_version == MXC_VERSION_MX31)
#define nfc_is_v2() (mxc_nf_info->mxc_version == MXC_VERSION_MX25 || \ #define nfc_is_v2() (mxc_nf_info->mxc_version == MXC_VERSION_MX25 || \
mxc_nf_info->mxc_version == MXC_VERSION_MX35) mxc_nf_info->mxc_version == MXC_VERSION_MX35)
/* This permits to print (in LOG_INFO) how much bytes /* This permits to print (in LOG_INFO) how much bytes
* has been written after a page read or write. * has been written after a page read or write.
@ -136,7 +136,7 @@ NAND_DEVICE_COMMAND_HANDLER(mxc_nand_device_command)
mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
mxc_nf_info->fin = MXC_NF_FIN_NONE; mxc_nf_info->fin = MXC_NF_FIN_NONE;
mxc_nf_info->flags.target_little_endian = mxc_nf_info->flags.target_little_endian =
(nand->target->endianness == TARGET_LITTLE_ENDIAN); (nand->target->endianness == TARGET_LITTLE_ENDIAN);
/* /*
* should factory bad block indicator be swaped * should factory bad block indicator be swaped
@ -190,9 +190,9 @@ COMMAND_HANDLER(handle_mxc_biswap_command)
static const struct command_registration mxc_sub_command_handlers[] = { static const struct command_registration mxc_sub_command_handlers[] = {
{ {
.name = "biswap", .name = "biswap",
.handler = handle_mxc_biswap_command , .handler = handle_mxc_biswap_command,
.help = "Turns on/off bad block information swaping from main area, " .help = "Turns on/off bad block information swaping from main area, "
"without parameter query status.", "without parameter query status.",
.usage = "bank_id ['enable'|'disable']", .usage = "bank_id ['enable'|'disable']",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
@ -262,18 +262,17 @@ static int mxc_init(struct nand_device *nand)
else else
LOG_DEBUG("MXC_NF : bus is 8-bit width"); LOG_DEBUG("MXC_NF : bus is 8-bit width");
if (!nand->page_size) { if (!nand->page_size)
nand->page_size = (sreg_content & SEL_FMS) ? 2048 : 512; nand->page_size = (sreg_content & SEL_FMS) ? 2048 : 512;
} else { else {
sreg_content |= ((nand->page_size == 2048) ? SEL_FMS : 0x00000000); sreg_content |= ((nand->page_size == 2048) ? SEL_FMS : 0x00000000);
target_write_u32(target, SREG, sreg_content); target_write_u32(target, SREG, sreg_content);
} }
if (mxc_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) { if (mxc_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) {
LOG_ERROR("NAND controller have only 1 kb SRAM, so " LOG_ERROR("NAND controller have only 1 kb SRAM, so "
"pagesize 2048 is incompatible with it"); "pagesize 2048 is incompatible with it");
} else { } else
LOG_DEBUG("MXC_NF : NAND controller can handle pagesize of 2048"); LOG_DEBUG("MXC_NF : NAND controller can handle pagesize of 2048");
}
if (nfc_is_v2() && sreg_content & MX35_RCSR_NF_4K) if (nfc_is_v2() && sreg_content & MX35_RCSR_NF_4K)
LOG_ERROR("MXC driver does not have support for 4k pagesize."); LOG_ERROR("MXC driver does not have support for 4k pagesize.");
@ -292,9 +291,8 @@ static int mxc_init(struct nand_device *nand)
if (!(nand_status_content & 0x0080)) { if (!(nand_status_content & 0x0080)) {
LOG_INFO("NAND read-only"); LOG_INFO("NAND read-only");
mxc_nf_info->flags.nand_readonly = 1; mxc_nf_info->flags.nand_readonly = 1;
} else { } else
mxc_nf_info->flags.nand_readonly = 0; mxc_nf_info->flags.nand_readonly = 0;
}
return ERROR_OK; return ERROR_OK;
} }
@ -315,7 +313,7 @@ static int mxc_read_data(struct nand_device *nand, void *data)
try_data_output_from_nand_chip = do_data_output(nand); try_data_output_from_nand_chip = do_data_output(nand);
if (try_data_output_from_nand_chip != ERROR_OK) { if (try_data_output_from_nand_chip != ERROR_OK) {
LOG_ERROR("mxc_read_data : read data failed : '%x'", LOG_ERROR("mxc_read_data : read data failed : '%x'",
try_data_output_from_nand_chip); try_data_output_from_nand_chip);
return try_data_output_from_nand_chip; return try_data_output_from_nand_chip;
} }
@ -360,26 +358,26 @@ static int mxc_command(struct nand_device *nand, uint8_t command)
return validate_target_result; return validate_target_result;
switch (command) { switch (command) {
case NAND_CMD_READOOB: case NAND_CMD_READOOB:
command = NAND_CMD_READ0; command = NAND_CMD_READ0;
/* set read point for data_read() and read_block_data() to /* set read point for data_read() and read_block_data() to
* spare area in SRAM buffer * spare area in SRAM buffer
*/ */
if (nfc_is_v1()) if (nfc_is_v1())
in_sram_address = MXC_NF_V1_SPARE_BUFFER0; in_sram_address = MXC_NF_V1_SPARE_BUFFER0;
else else
in_sram_address = MXC_NF_V2_SPARE_BUFFER0; in_sram_address = MXC_NF_V2_SPARE_BUFFER0;
break; break;
case NAND_CMD_READ1: case NAND_CMD_READ1:
command = NAND_CMD_READ0; command = NAND_CMD_READ0;
/* /*
* offset == one half of page size * offset == one half of page size
*/ */
in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1); in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
break; break;
default: default:
in_sram_address = MXC_NF_MAIN_BUFFER0; in_sram_address = MXC_NF_MAIN_BUFFER0;
break; break;
} }
target_write_u16(target, MXC_NF_FCMD, command); target_write_u16(target, MXC_NF_FCMD, command);
@ -396,24 +394,24 @@ static int mxc_command(struct nand_device *nand, uint8_t command)
sign_of_sequental_byte_read = 0; sign_of_sequental_byte_read = 0;
/* Handle special read command and adjust NF_CFG2(FDO) */ /* Handle special read command and adjust NF_CFG2(FDO) */
switch (command) { switch (command) {
case NAND_CMD_READID: case NAND_CMD_READID:
mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID; mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID;
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
break; break;
case NAND_CMD_STATUS: case NAND_CMD_STATUS:
mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS; mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS;
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
target_write_u16 (target, MXC_NF_BUFADDR, 0); target_write_u16 (target, MXC_NF_BUFADDR, 0);
in_sram_address = 0; in_sram_address = 0;
break; break;
case NAND_CMD_READ0: case NAND_CMD_READ0:
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
break; break;
default: default:
/* Ohter command use the default 'One page data out' FDO */ /* Ohter command use the default 'One page data out' FDO */
mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
break; break;
} }
return ERROR_OK; return ERROR_OK;
} }
@ -463,14 +461,13 @@ static int mxc_nand_ready(struct nand_device *nand, int tout)
return tout; return tout;
alive_sleep(1); alive_sleep(1);
} } while (tout-- > 0);
while (tout-- > 0);
return tout; return tout;
} }
static int mxc_write_page(struct nand_device *nand, uint32_t page, static int mxc_write_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -504,11 +501,11 @@ static int mxc_write_page(struct nand_device *nand, uint32_t page,
sign_of_sequental_byte_read = 0; sign_of_sequental_byte_read = 0;
retval = ERROR_OK; retval = ERROR_OK;
retval |= mxc_command(nand, NAND_CMD_SEQIN); retval |= mxc_command(nand, NAND_CMD_SEQIN);
retval |= mxc_address(nand, 0); /* col */ retval |= mxc_address(nand, 0); /* col */
retval |= mxc_address(nand, 0); /* col */ retval |= mxc_address(nand, 0); /* col */
retval |= mxc_address(nand, page & 0xff); /* page address */ retval |= mxc_address(nand, page & 0xff); /* page address */
retval |= mxc_address(nand, (page >> 8) & 0xff); /* page address */ retval |= mxc_address(nand, (page >> 8) & 0xff);/* page address */
retval |= mxc_address(nand, (page >> 16) & 0xff); /* page address */ retval |= mxc_address(nand, (page >> 16) & 0xff); /* page address */
target_write_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data); target_write_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data);
if (oob) { if (oob) {
@ -518,7 +515,7 @@ static int mxc_write_page(struct nand_device *nand, uint32_t page,
* ECC generator * ECC generator
*/ */
LOG_DEBUG("part of spare block will be overrided " LOG_DEBUG("part of spare block will be overrided "
"by hardware ECC generator"); "by hardware ECC generator");
} }
if (nfc_is_v1()) if (nfc_is_v1())
target_write_buffer(target, MXC_NF_V1_SPARE_BUFFER0, oob_size, oob); target_write_buffer(target, MXC_NF_V1_SPARE_BUFFER0, oob_size, oob);
@ -541,7 +538,7 @@ static int mxc_write_page(struct nand_device *nand, uint32_t page,
LOG_ERROR("Due to NFC Bug, oob is not correctly implemented in mxc driver"); LOG_ERROR("Due to NFC Bug, oob is not correctly implemented in mxc driver");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
swap2 = 0xffff; /* Spare buffer unused forced to 0xffff */ swap2 = 0xffff; /* Spare buffer unused forced to 0xffff */
new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8); new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8);
swap2 = (swap1 << 8) | (swap2 & 0xFF); swap2 = (swap1 << 8) | (swap2 & 0xFF);
target_write_u16(target, MXC_NF_MAIN_BUFFER3 + 464, new_swap1); target_write_u16(target, MXC_NF_MAIN_BUFFER3 + 464, new_swap1);
@ -559,7 +556,7 @@ static int mxc_write_page(struct nand_device *nand, uint32_t page,
else else
bufs = 1; bufs = 1;
for (uint8_t i = 0 ; i < bufs ; ++i) { for (uint8_t i = 0; i < bufs; ++i) {
target_write_u16(target, MXC_NF_BUFADDR, i); target_write_u16(target, MXC_NF_BUFADDR, i);
target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FDI); target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FDI);
poll_result = poll_for_complete_op(nand, "data input"); poll_result = poll_for_complete_op(nand, "data input");
@ -598,8 +595,8 @@ static int mxc_write_page(struct nand_device *nand, uint32_t page,
} }
static int mxc_read_page(struct nand_device *nand, uint32_t page, static int mxc_read_page(struct nand_device *nand, uint32_t page,
uint8_t *data, uint32_t data_size, uint8_t *data, uint32_t data_size,
uint8_t *oob, uint32_t oob_size) uint8_t *oob, uint32_t oob_size)
{ {
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -620,31 +617,37 @@ static int mxc_read_page(struct nand_device *nand, uint32_t page,
* validate target state * validate target state
*/ */
retval = validate_target_state(nand); retval = validate_target_state(nand);
if (retval != ERROR_OK) { if (retval != ERROR_OK)
return retval; return retval;
} /* Reset address_cycles before mxc_command ?? */
/* Reset address_cycles before mxc_command ?? */
retval = mxc_command(nand, NAND_CMD_READ0); retval = mxc_command(nand, NAND_CMD_READ0);
if (retval != ERROR_OK) return retval; if (retval != ERROR_OK)
retval = mxc_address(nand, 0); /* col */ return retval;
if (retval != ERROR_OK) return retval; retval = mxc_address(nand, 0); /* col */
retval = mxc_address(nand, 0); /* col */ if (retval != ERROR_OK)
if (retval != ERROR_OK) return retval; return retval;
retval = mxc_address(nand, page & 0xff); /* page address */ retval = mxc_address(nand, 0); /* col */
if (retval != ERROR_OK) return retval; if (retval != ERROR_OK)
retval = mxc_address(nand, (page >> 8) & 0xff); /* page address */ return retval;
if (retval != ERROR_OK) return retval; retval = mxc_address(nand, page & 0xff);/* page address */
retval = mxc_address(nand, (page >> 16) & 0xff); /* page address */ if (retval != ERROR_OK)
if (retval != ERROR_OK) return retval; return retval;
retval = mxc_address(nand, (page >> 8) & 0xff); /* page address */
if (retval != ERROR_OK)
return retval;
retval = mxc_address(nand, (page >> 16) & 0xff);/* page address */
if (retval != ERROR_OK)
return retval;
retval = mxc_command(nand, NAND_CMD_READSTART); retval = mxc_command(nand, NAND_CMD_READSTART);
if (retval != ERROR_OK) return retval; if (retval != ERROR_OK)
return retval;
if (nfc_is_v1() && nand->page_size > 512) if (nfc_is_v1() && nand->page_size > 512)
bufs = 4; bufs = 4;
else else
bufs = 1; bufs = 1;
for (uint8_t i = 0 ; i < bufs ; ++i) { for (uint8_t i = 0; i < bufs; ++i) {
target_write_u16(target, MXC_NF_BUFADDR, i); target_write_u16(target, MXC_NF_BUFADDR, i);
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
retval = do_data_output(nand); retval = do_data_output(nand);
@ -702,9 +705,9 @@ static uint32_t align_address_v2(struct nand_device *nand, uint32_t addr)
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
uint32_t ret = addr; uint32_t ret = addr;
if (addr > MXC_NF_V2_SPARE_BUFFER0 && if (addr > MXC_NF_V2_SPARE_BUFFER0 &&
(addr & 0x1F) == MXC_NF_SPARE_BUFFER_LEN) { (addr & 0x1F) == MXC_NF_SPARE_BUFFER_LEN)
ret += MXC_NF_SPARE_BUFFER_MAX - MXC_NF_SPARE_BUFFER_LEN; ret += MXC_NF_SPARE_BUFFER_MAX - MXC_NF_SPARE_BUFFER_LEN;
} else if (addr >= (mxc_nf_info->mxc_base_addr + (uint32_t)nand->page_size)) else if (addr >= (mxc_nf_info->mxc_base_addr + (uint32_t)nand->page_size))
ret = MXC_NF_V2_SPARE_BUFFER0; ret = MXC_NF_V2_SPARE_BUFFER0;
return ret; return ret;
} }
@ -725,15 +728,13 @@ static int initialize_nf_controller(struct nand_device *nand)
if (target->endianness == TARGET_BIG_ENDIAN) { if (target->endianness == TARGET_BIG_ENDIAN) {
LOG_DEBUG("MXC_NF : work in Big Endian mode"); LOG_DEBUG("MXC_NF : work in Big Endian mode");
work_mode |= MXC_NF_BIT_BE_EN; work_mode |= MXC_NF_BIT_BE_EN;
} else { } else
LOG_DEBUG("MXC_NF : work in Little Endian mode"); LOG_DEBUG("MXC_NF : work in Little Endian mode");
}
if (mxc_nf_info->flags.hw_ecc_enabled) { if (mxc_nf_info->flags.hw_ecc_enabled) {
LOG_DEBUG("MXC_NF : work with ECC mode"); LOG_DEBUG("MXC_NF : work with ECC mode");
work_mode |= MXC_NF_BIT_ECC_EN; work_mode |= MXC_NF_BIT_ECC_EN;
} else { } else
LOG_DEBUG("MXC_NF : work without ECC mode"); LOG_DEBUG("MXC_NF : work without ECC mode");
}
if (nfc_is_v2()) { if (nfc_is_v2()) {
target_write_u16(target, MXC_NF_V2_SPAS, OOB_SIZE / 2); target_write_u16(target, MXC_NF_V2_SPAS, OOB_SIZE / 2);
if (nand->page_size) { if (nand->page_size) {
@ -788,7 +789,7 @@ static int get_next_byte_from_sram_buffer(struct nand_device *nand, uint8_t *val
{ {
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
static uint8_t even_byte = 0; static uint8_t even_byte;
uint16_t temp; uint16_t temp;
/* /*
* host-big_endian ?? * host-big_endian ??
@ -796,8 +797,7 @@ static int get_next_byte_from_sram_buffer(struct nand_device *nand, uint8_t *val
if (sign_of_sequental_byte_read == 0) if (sign_of_sequental_byte_read == 0)
even_byte = 0; even_byte = 0;
if (in_sram_address > if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
(nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address); LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
*value = 0; *value = 0;
sign_of_sequental_byte_read = 0; sign_of_sequental_byte_read = 0;
@ -826,8 +826,7 @@ static int get_next_halfword_from_sram_buffer(struct nand_device *nand, uint16_t
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
if (in_sram_address > if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
(nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address); LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
*value = 0; *value = 0;
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -861,7 +860,7 @@ static int validate_target_state(struct nand_device *nand)
} }
if (mxc_nf_info->flags.target_little_endian != if (mxc_nf_info->flags.target_little_endian !=
(target->endianness == TARGET_LITTLE_ENDIAN)) { (target->endianness == TARGET_LITTLE_ENDIAN)) {
/* /*
* endianness changed after NAND controller probed * endianness changed after NAND controller probed
*/ */
@ -878,22 +877,22 @@ int ecc_status_v1(struct nand_device *nand)
target_read_u16(target, MXC_NF_ECCSTATUS, &ecc_status); target_read_u16(target, MXC_NF_ECCSTATUS, &ecc_status);
switch (ecc_status & 0x000c) { switch (ecc_status & 0x000c) {
case 1 << 2: case 1 << 2:
LOG_INFO("main area read with 1 (correctable) error"); LOG_INFO("main area read with 1 (correctable) error");
break; break;
case 2 << 2: case 2 << 2:
LOG_INFO("main area read with more than 1 (incorrectable) error"); LOG_INFO("main area read with more than 1 (incorrectable) error");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
break; break;
} }
switch (ecc_status & 0x0003) { switch (ecc_status & 0x0003) {
case 1: case 1:
LOG_INFO("spare area read with 1 (correctable) error"); LOG_INFO("spare area read with 1 (correctable) error");
break; break;
case 2: case 2:
LOG_INFO("main area read with more than 1 (incorrectable) error"); LOG_INFO("main area read with more than 1 (incorrectable) error");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
break; break;
} }
return ERROR_OK; return ERROR_OK;
} }
@ -927,47 +926,46 @@ static int do_data_output(struct nand_device *nand)
struct target *target = nand->target; struct target *target = nand->target;
int poll_result; int poll_result;
switch (mxc_nf_info->fin) { switch (mxc_nf_info->fin) {
case MXC_NF_FIN_DATAOUT: case MXC_NF_FIN_DATAOUT:
/* /*
* start data output operation (set MXC_NF_BIT_OP_DONE==0) * start data output operation (set MXC_NF_BIT_OP_DONE==0)
*/ */
target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_DATAOUT_TYPE(mxc_nf_info->optype)); target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_DATAOUT_TYPE(mxc_nf_info->optype));
poll_result = poll_for_complete_op(nand, "data output"); poll_result = poll_for_complete_op(nand, "data output");
if (poll_result != ERROR_OK) if (poll_result != ERROR_OK)
return poll_result; return poll_result;
mxc_nf_info->fin = MXC_NF_FIN_NONE; mxc_nf_info->fin = MXC_NF_FIN_NONE;
/* /*
* ECC stuff * ECC stuff
*/ */
if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && mxc_nf_info->flags.hw_ecc_enabled) {
mxc_nf_info->flags.hw_ecc_enabled) { int ecc_status;
int ecc_status; if (nfc_is_v1())
if (nfc_is_v1()) ecc_status = ecc_status_v1(nand);
ecc_status = ecc_status_v1(nand); else
else ecc_status = ecc_status_v2(nand);
ecc_status = ecc_status_v2(nand); if (ecc_status != ERROR_OK)
if (ecc_status != ERROR_OK) return ecc_status;
return ecc_status; }
} break;
break; case MXC_NF_FIN_NONE:
case MXC_NF_FIN_NONE: break;
break;
} }
return ERROR_OK; return ERROR_OK;
} }
struct nand_flash_controller mxc_nand_flash_controller = { struct nand_flash_controller mxc_nand_flash_controller = {
.name = "mxc", .name = "mxc",
.nand_device_command = &mxc_nand_device_command, .nand_device_command = &mxc_nand_device_command,
.commands = mxc_nand_command_handler, .commands = mxc_nand_command_handler,
.init = &mxc_init, .init = &mxc_init,
.reset = &mxc_reset, .reset = &mxc_reset,
.command = &mxc_command, .command = &mxc_command,
.address = &mxc_address, .address = &mxc_address,
.write_data = &mxc_write_data, .write_data = &mxc_write_data,
.read_data = &mxc_read_data, .read_data = &mxc_read_data,
.write_page = &mxc_write_page, .write_page = &mxc_write_page,
.read_page = &mxc_read_page, .read_page = &mxc_read_page,
.nand_ready = &mxc_nand_ready, .nand_ready = &mxc_nand_ready,
}; };

View File

@ -24,7 +24,6 @@
#include "imp.h" #include "imp.h"
#include "hello.h" #include "hello.h"
static int nonce_nand_command(struct nand_device *nand, uint8_t command) static int nonce_nand_command(struct nand_device *nand, uint8_t command)
{ {
return ERROR_OK; return ERROR_OK;
@ -62,16 +61,15 @@ static int nonce_nand_init(struct nand_device *nand)
return ERROR_OK; return ERROR_OK;
} }
struct nand_flash_controller nonce_nand_controller = struct nand_flash_controller nonce_nand_controller = {
{ .name = "nonce",
.name = "nonce", .commands = hello_command_handlers,
.commands = hello_command_handlers, .nand_device_command = &nonce_nand_device_command,
.nand_device_command = &nonce_nand_device_command, .init = &nonce_nand_init,
.init = &nonce_nand_init, .reset = &nonce_nand_reset,
.reset = &nonce_nand_reset, .command = &nonce_nand_command,
.command = &nonce_nand_command, .address = &nonce_nand_address,
.address = &nonce_nand_address, .read_data = &nonce_nand_read,
.read_data = &nonce_nand_read, .write_data = &nonce_nand_write,
.write_data = &nonce_nand_write, .write_block_data = &nonce_nand_fast_block_write,
.write_block_data = &nonce_nand_fast_block_write,
}; };

View File

@ -31,8 +31,7 @@
#include "arm_io.h" #include "arm_io.h"
#include <target/arm.h> #include <target/arm.h>
struct nuc910_nand_controller struct nuc910_nand_controller {
{
struct arm_nand_data io; struct arm_nand_data io;
}; };
@ -53,7 +52,8 @@ static int nuc910_nand_command(struct nand_device *nand, uint8_t command)
struct target *target = nand->target; struct target *target = nand->target;
int result; int result;
if ((result = validate_target_state(nand)) != ERROR_OK) result = validate_target_state(nand);
if (result != ERROR_OK)
return result; return result;
target_write_u8(target, NUC910_SMCMD, command); target_write_u8(target, NUC910_SMCMD, command);
@ -65,7 +65,8 @@ static int nuc910_nand_address(struct nand_device *nand, uint8_t address)
struct target *target = nand->target; struct target *target = nand->target;
int result; int result;
if ((result = validate_target_state(nand)) != ERROR_OK) result = validate_target_state(nand);
if (result != ERROR_OK)
return result; return result;
target_write_u32(target, NUC910_SMADDR, ((address & 0xff) | NUC910_SMADDR_EOA)); target_write_u32(target, NUC910_SMADDR, ((address & 0xff) | NUC910_SMADDR_EOA));
@ -77,7 +78,8 @@ static int nuc910_nand_read(struct nand_device *nand, void *data)
struct target *target = nand->target; struct target *target = nand->target;
int result; int result;
if ((result = validate_target_state(nand)) != ERROR_OK) result = validate_target_state(nand);
if (result != ERROR_OK)
return result; return result;
target_read_u8(target, NUC910_SMDATA, data); target_read_u8(target, NUC910_SMDATA, data);
@ -89,7 +91,8 @@ static int nuc910_nand_write(struct nand_device *nand, uint16_t data)
struct target *target = nand->target; struct target *target = nand->target;
int result; int result;
if ((result = validate_target_state(nand)) != ERROR_OK) result = validate_target_state(nand);
if (result != ERROR_OK)
return result; return result;
target_write_u8(target, NUC910_SMDATA, data); target_write_u8(target, NUC910_SMDATA, data);
@ -102,7 +105,8 @@ static int nuc910_nand_read_block_data(struct nand_device *nand,
struct nuc910_nand_controller *nuc910_nand = nand->controller_priv; struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
int result; int result;
if ((result = validate_target_state(nand)) != ERROR_OK) result = validate_target_state(nand);
if (result != ERROR_OK)
return result; return result;
nuc910_nand->io.chunk_size = nand->page_size; nuc910_nand->io.chunk_size = nand->page_size;
@ -125,7 +129,8 @@ static int nuc910_nand_write_block_data(struct nand_device *nand,
struct nuc910_nand_controller *nuc910_nand = nand->controller_priv; struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
int result; int result;
if ((result = validate_target_state(nand)) != ERROR_OK) result = validate_target_state(nand);
if (result != ERROR_OK)
return result; return result;
nuc910_nand->io.chunk_size = nand->page_size; nuc910_nand->io.chunk_size = nand->page_size;
@ -154,9 +159,8 @@ static int nuc910_nand_ready(struct nand_device *nand, int timeout)
do { do {
target_read_u32(target, NUC910_SMISR, &status); target_read_u32(target, NUC910_SMISR, &status);
if (status & NUC910_SMISR_RB_) { if (status & NUC910_SMISR_RB_)
return 1; return 1;
}
alive_sleep(1); alive_sleep(1);
} while (timeout-- > 0); } while (timeout-- > 0);
@ -184,12 +188,12 @@ static int nuc910_nand_init(struct nand_device *nand)
int bus_width = nand->bus_width ? : 8; int bus_width = nand->bus_width ? : 8;
int result; int result;
if ((result = validate_target_state(nand)) != ERROR_OK) result = validate_target_state(nand);
if (result != ERROR_OK)
return result; return result;
/* nuc910 only supports 8bit */ /* nuc910 only supports 8bit */
if (bus_width != 8) if (bus_width != 8) {
{
LOG_ERROR("nuc910 only supports 8 bit bus width, not %i", bus_width); LOG_ERROR("nuc910 only supports 8 bit bus width, not %i", bus_width);
return ERROR_NAND_OPERATION_NOT_SUPPORTED; return ERROR_NAND_OPERATION_NOT_SUPPORTED;
} }
@ -210,8 +214,7 @@ static int nuc910_nand_init(struct nand_device *nand)
return ERROR_OK; return ERROR_OK;
} }
struct nand_flash_controller nuc910_nand_controller = struct nand_flash_controller nuc910_nand_controller = {
{
.name = "nuc910", .name = "nuc910",
.command = nuc910_nand_command, .command = nuc910_nand_command,
.address = nuc910_nand_address, .address = nuc910_nand_address,

View File

@ -30,9 +30,7 @@
#include "arm_io.h" #include "arm_io.h"
#include <target/arm.h> #include <target/arm.h>
struct orion_nand_controller {
struct orion_nand_controller
{
struct arm_nand_data io; struct arm_nand_data io;
uint32_t cmd; uint32_t cmd;
@ -120,9 +118,8 @@ NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
uint32_t base; uint32_t base;
uint8_t ale, cle; uint8_t ale, cle;
if (CMD_ARGC != 3) { if (CMD_ARGC != 3)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
hw = calloc(1, sizeof(*hw)); hw = calloc(1, sizeof(*hw));
if (!hw) { if (!hw) {
@ -152,17 +149,15 @@ static int orion_nand_init(struct nand_device *nand)
return ERROR_OK; return ERROR_OK;
} }
struct nand_flash_controller orion_nand_controller = struct nand_flash_controller orion_nand_controller = {
{ .name = "orion",
.name = "orion", .usage = "<target_id> <NAND_address>",
.usage = "<target_id> <NAND_address>", .command = orion_nand_command,
.command = orion_nand_command, .address = orion_nand_address,
.address = orion_nand_address, .read_data = orion_nand_read,
.read_data = orion_nand_read, .write_data = orion_nand_write,
.write_data = orion_nand_write, .write_block_data = orion_nand_fast_block_write,
.write_block_data = orion_nand_fast_block_write, .reset = orion_nand_reset,
.reset = orion_nand_reset, .nand_device_command = orion_nand_device_command,
.nand_device_command = orion_nand_device_command, .init = orion_nand_init,
.init = orion_nand_init,
}; };

View File

@ -104,15 +104,15 @@ static int s3c2410_nand_ready(struct nand_device *nand, int timeout)
} }
struct nand_flash_controller s3c2410_nand_controller = { struct nand_flash_controller s3c2410_nand_controller = {
.name = "s3c2410", .name = "s3c2410",
.nand_device_command = &s3c2410_nand_device_command, .nand_device_command = &s3c2410_nand_device_command,
.init = &s3c2410_init, .init = &s3c2410_init,
.reset = &s3c24xx_reset, .reset = &s3c24xx_reset,
.command = &s3c24xx_command, .command = &s3c24xx_command,
.address = &s3c24xx_address, .address = &s3c24xx_address,
.write_data = &s3c2410_write_data, .write_data = &s3c2410_write_data,
.read_data = &s3c2410_read_data, .read_data = &s3c2410_read_data,
.write_page = s3c24xx_write_page, .write_page = s3c24xx_write_page,
.read_page = s3c24xx_read_page, .read_page = s3c24xx_read_page,
.nand_ready = &s3c2410_nand_ready, .nand_ready = &s3c2410_nand_ready,
}; };

View File

@ -61,17 +61,17 @@ static int s3c2412_init(struct nand_device *nand)
} }
struct nand_flash_controller s3c2412_nand_controller = { struct nand_flash_controller s3c2412_nand_controller = {
.name = "s3c2412", .name = "s3c2412",
.nand_device_command = &s3c2412_nand_device_command, .nand_device_command = &s3c2412_nand_device_command,
.init = &s3c2412_init, .init = &s3c2412_init,
.reset = &s3c24xx_reset, .reset = &s3c24xx_reset,
.command = &s3c24xx_command, .command = &s3c24xx_command,
.address = &s3c24xx_address, .address = &s3c24xx_address,
.write_data = &s3c24xx_write_data, .write_data = &s3c24xx_write_data,
.read_data = &s3c24xx_read_data, .read_data = &s3c24xx_read_data,
.write_page = s3c24xx_write_page, .write_page = s3c24xx_write_page,
.read_page = s3c24xx_read_page, .read_page = s3c24xx_read_page,
.write_block_data = &s3c2440_write_block_data, .write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data, .read_block_data = &s3c2440_read_block_data,
.nand_ready = &s3c2440_nand_ready, .nand_ready = &s3c2440_nand_ready,
}; };

View File

@ -30,7 +30,6 @@
#include "s3c24xx.h" #include "s3c24xx.h"
NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command) NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
{ {
struct s3c24xx_nand_controller *info; struct s3c24xx_nand_controller *info;
@ -153,17 +152,17 @@ int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_s
} }
struct nand_flash_controller s3c2440_nand_controller = { struct nand_flash_controller s3c2440_nand_controller = {
.name = "s3c2440", .name = "s3c2440",
.nand_device_command = &s3c2440_nand_device_command, .nand_device_command = &s3c2440_nand_device_command,
.init = &s3c2440_init, .init = &s3c2440_init,
.reset = &s3c24xx_reset, .reset = &s3c24xx_reset,
.command = &s3c24xx_command, .command = &s3c24xx_command,
.address = &s3c24xx_address, .address = &s3c24xx_address,
.write_data = &s3c24xx_write_data, .write_data = &s3c24xx_write_data,
.read_data = &s3c24xx_read_data, .read_data = &s3c24xx_read_data,
.write_page = s3c24xx_write_page, .write_page = s3c24xx_write_page,
.read_page = s3c24xx_read_page, .read_page = s3c24xx_read_page,
.write_block_data = &s3c2440_write_block_data, .write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data, .read_block_data = &s3c2440_read_block_data,
.nand_ready = &s3c2440_nand_ready, .nand_ready = &s3c2440_nand_ready,
}; };

View File

@ -30,7 +30,6 @@
#include "s3c24xx.h" #include "s3c24xx.h"
NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command) NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command)
{ {
struct s3c24xx_nand_controller *info; struct s3c24xx_nand_controller *info;
@ -62,17 +61,17 @@ static int s3c2443_init(struct nand_device *nand)
} }
struct nand_flash_controller s3c2443_nand_controller = { struct nand_flash_controller s3c2443_nand_controller = {
.name = "s3c2443", .name = "s3c2443",
.nand_device_command = &s3c2443_nand_device_command, .nand_device_command = &s3c2443_nand_device_command,
.init = &s3c2443_init, .init = &s3c2443_init,
.reset = &s3c24xx_reset, .reset = &s3c24xx_reset,
.command = &s3c24xx_command, .command = &s3c24xx_command,
.address = &s3c24xx_address, .address = &s3c24xx_address,
.write_data = &s3c24xx_write_data, .write_data = &s3c24xx_write_data,
.read_data = &s3c24xx_read_data, .read_data = &s3c24xx_read_data,
.write_page = s3c24xx_write_page, .write_page = s3c24xx_write_page,
.read_page = s3c24xx_read_page, .read_page = s3c24xx_read_page,
.write_block_data = &s3c2440_write_block_data, .write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data, .read_block_data = &s3c2440_read_block_data,
.nand_ready = &s3c2440_nand_ready, .nand_ready = &s3c2440_nand_ready,
}; };

View File

@ -30,7 +30,6 @@
#include "s3c24xx.h" #include "s3c24xx.h"
S3C24XX_DEVICE_COMMAND() S3C24XX_DEVICE_COMMAND()
{ {
*info = NULL; *info = NULL;
@ -77,7 +76,6 @@ int s3c24xx_command(struct nand_device *nand, uint8_t command)
return ERROR_OK; return ERROR_OK;
} }
int s3c24xx_address(struct nand_device *nand, uint8_t address) int s3c24xx_address(struct nand_device *nand, uint8_t address)
{ {
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;

View File

@ -31,8 +31,7 @@
#include "s3c24xx_regs.h" #include "s3c24xx_regs.h"
#include <target/target.h> #include <target/target.h>
struct s3c24xx_nand_controller struct s3c24xx_nand_controller {
{
/* register addresses */ /* register addresses */
uint32_t cmd; uint32_t cmd;
uint32_t addr; uint32_t addr;
@ -78,4 +77,4 @@ int s3c2440_read_block_data(struct nand_device *nand,
int s3c2440_write_block_data(struct nand_device *nand, int s3c2440_write_block_data(struct nand_device *nand,
uint8_t *data, int data_size); uint8_t *data, int data_size);
#endif // S3C24xx_NAND_H #endif /* S3C24xx_NAND_H */

View File

@ -23,7 +23,7 @@
*/ */
#ifndef __ASM_ARM_REGS_NAND #ifndef __ASM_ARM_REGS_NAND
#define __ASM_ARM_REGS_NAND "$Id: nand.h,v 1.3 2003/12/09 11:36:29 ben Exp $" #define __ASM_ARM_REGS_NAND
#define S3C2410_NFREG(x) (x) #define S3C2410_NFREG(x) (x)

View File

@ -58,17 +58,17 @@ static int s3c6400_init(struct nand_device *nand)
} }
struct nand_flash_controller s3c6400_nand_controller = { struct nand_flash_controller s3c6400_nand_controller = {
.name = "s3c6400", .name = "s3c6400",
.nand_device_command = &s3c6400_nand_device_command, .nand_device_command = &s3c6400_nand_device_command,
.init = &s3c6400_init, .init = &s3c6400_init,
.reset = &s3c24xx_reset, .reset = &s3c24xx_reset,
.command = &s3c24xx_command, .command = &s3c24xx_command,
.address = &s3c24xx_address, .address = &s3c24xx_address,
.write_data = &s3c24xx_write_data, .write_data = &s3c24xx_write_data,
.read_data = &s3c24xx_read_data, .read_data = &s3c24xx_read_data,
.write_page = s3c24xx_write_page, .write_page = s3c24xx_write_page,
.read_page = s3c24xx_read_page, .read_page = s3c24xx_read_page,
.write_block_data = &s3c2440_write_block_data, .write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data, .read_block_data = &s3c2440_read_block_data,
.nand_ready = &s3c2440_nand_ready, .nand_ready = &s3c2440_nand_ready,
}; };

View File

@ -20,6 +20,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -29,7 +30,7 @@
#include "fileio.h" #include "fileio.h"
#include <target/target.h> #include <target/target.h>
// to be removed /* to be removed */
extern struct nand_device *nand_devices; extern struct nand_device *nand_devices;
COMMAND_HANDLER(handle_nand_list_command) COMMAND_HANDLER(handle_nand_list_command)
@ -37,14 +38,12 @@ COMMAND_HANDLER(handle_nand_list_command)
struct nand_device *p; struct nand_device *p;
int i; int i;
if (!nand_devices) if (!nand_devices) {
{
command_print(CMD_CTX, "no NAND flash devices configured"); command_print(CMD_CTX, "no NAND flash devices configured");
return ERROR_OK; return ERROR_OK;
} }
for (p = nand_devices, i = 0; p; p = p->next, i++) for (p = nand_devices, i = 0; p; p = p->next, i++) {
{
if (p->device) if (p->device)
command_print(CMD_CTX, "#%i: %s (%s) " command_print(CMD_CTX, "#%i: %s (%s) "
"pagesize: %i, buswidth: %i,\n\t" "pagesize: %i, buswidth: %i,\n\t"
@ -67,21 +66,21 @@ COMMAND_HANDLER(handle_nand_info_command)
int last = -1; int last = -1;
switch (CMD_ARGC) { switch (CMD_ARGC) {
default: default:
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
case 1: case 1:
first = 0; first = 0;
last = INT32_MAX; last = INT32_MAX;
break; break;
case 2: case 2:
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
first = last = i; first = last = i;
i = 0; i = 0;
break; break;
case 3: case 3:
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last); COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
break; break;
} }
struct nand_device *p; struct nand_device *p;
@ -89,8 +88,7 @@ COMMAND_HANDLER(handle_nand_info_command)
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if (NULL == p->device) if (NULL == p->device) {
{
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]); command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
return ERROR_OK; return ERROR_OK;
} }
@ -101,11 +99,16 @@ COMMAND_HANDLER(handle_nand_info_command)
if (last >= p->num_blocks) if (last >= p->num_blocks)
last = p->num_blocks - 1; last = p->num_blocks - 1;
command_print(CMD_CTX, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i", command_print(CMD_CTX,
i++, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size); "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
i++,
p->device->name,
p->manufacturer->name,
p->page_size,
p->bus_width,
p->erase_size);
for (j = first; j <= last; j++) for (j = first; j <= last; j++) {
{
char *erase_state, *bad_state; char *erase_state, *bad_state;
if (p->blocks[j].is_erased == 0) if (p->blocks[j].is_erased == 0)
@ -123,12 +126,12 @@ COMMAND_HANDLER(handle_nand_info_command)
bad_state = " (block condition unknown)"; bad_state = " (block condition unknown)";
command_print(CMD_CTX, command_print(CMD_CTX,
"\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s", "\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s",
j, j,
p->blocks[j].offset, p->blocks[j].offset,
p->blocks[j].size / 1024, p->blocks[j].size / 1024,
erase_state, erase_state,
bad_state); bad_state);
} }
return ERROR_OK; return ERROR_OK;
@ -137,19 +140,17 @@ COMMAND_HANDLER(handle_nand_info_command)
COMMAND_HANDLER(handle_nand_probe_command) COMMAND_HANDLER(handle_nand_probe_command)
{ {
if (CMD_ARGC != 1) if (CMD_ARGC != 1)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct nand_device *p; struct nand_device *p;
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if ((retval = nand_probe(p)) == ERROR_OK) retval = nand_probe(p);
{ if (retval == ERROR_OK) {
command_print(CMD_CTX, "NAND flash device '%s (%s)' found", command_print(CMD_CTX, "NAND flash device '%s (%s)' found",
p->device->name, p->manufacturer->name); p->device->name, p->manufacturer->name);
} }
return retval; return retval;
@ -158,11 +159,8 @@ COMMAND_HANDLER(handle_nand_probe_command)
COMMAND_HANDLER(handle_nand_erase_command) COMMAND_HANDLER(handle_nand_erase_command)
{ {
if (CMD_ARGC != 1 && CMD_ARGC != 3) if (CMD_ARGC != 1 && CMD_ARGC != 3)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct nand_device *p; struct nand_device *p;
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
if (ERROR_OK != retval) if (ERROR_OK != retval)
@ -181,7 +179,7 @@ COMMAND_HANDLER(handle_nand_erase_command)
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length); COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
if ((length == 0) || (length % p->erase_size) != 0 if ((length == 0) || (length % p->erase_size) != 0
|| (length + offset) > size) || (length + offset) > size)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
offset /= p->erase_size; offset /= p->erase_size;
@ -192,12 +190,11 @@ COMMAND_HANDLER(handle_nand_erase_command)
} }
retval = nand_erase(p, offset, offset + length - 1); retval = nand_erase(p, offset, offset + length - 1);
if (retval == ERROR_OK) if (retval == ERROR_OK) {
{
command_print(CMD_CTX, "erased blocks %lu to %lu " command_print(CMD_CTX, "erased blocks %lu to %lu "
"on NAND flash device #%s '%s'", "on NAND flash device #%s '%s'",
offset, offset + length - 1, offset, offset + length - 1,
CMD_ARGV[0], p->device->name); CMD_ARGV[0], p->device->name);
} }
return retval; return retval;
@ -209,18 +206,14 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
int last = -1; int last = -1;
if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2)) if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2))
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct nand_device *p; struct nand_device *p;
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if (CMD_ARGC == 3) if (CMD_ARGC == 3) {
{
unsigned long offset; unsigned long offset;
unsigned long length; unsigned long length;
@ -241,10 +234,9 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
} }
retval = nand_build_bbt(p, first, last); retval = nand_build_bbt(p, first, last);
if (retval == ERROR_OK) if (retval == ERROR_OK) {
{
command_print(CMD_CTX, "checked NAND flash device for bad blocks, " command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
"use \"nand info\" command to list blocks"); "use \"nand info\" command to list blocks");
} }
return retval; return retval;
@ -260,11 +252,9 @@ COMMAND_HANDLER(handle_nand_write_command)
return retval; return retval;
uint32_t total_bytes = s.size; uint32_t total_bytes = s.size;
while (s.size > 0) while (s.size > 0) {
{
int bytes_read = nand_fileio_read(nand, &s); int bytes_read = nand_fileio_read(nand, &s);
if (bytes_read <= 0) if (bytes_read <= 0) {
{
command_print(CMD_CTX, "error while reading file"); command_print(CMD_CTX, "error while reading file");
return nand_fileio_cleanup(&s); return nand_fileio_cleanup(&s);
} }
@ -272,8 +262,7 @@ COMMAND_HANDLER(handle_nand_write_command)
retval = nand_write_page(nand, s.address / nand->page_size, retval = nand_write_page(nand, s.address / nand->page_size,
s.page, s.page_size, s.oob, s.oob_size); s.page, s.page_size, s.oob, s.oob_size);
if (ERROR_OK != retval) if (ERROR_OK != retval) {
{
command_print(CMD_CTX, "failed writing file %s " command_print(CMD_CTX, "failed writing file %s "
"to NAND flash %s at offset 0x%8.8" PRIx32, "to NAND flash %s at offset 0x%8.8" PRIx32,
CMD_ARGV[1], CMD_ARGV[0], s.address); CMD_ARGV[1], CMD_ARGV[0], s.address);
@ -282,12 +271,11 @@ COMMAND_HANDLER(handle_nand_write_command)
s.address += s.page_size; s.address += s.page_size;
} }
if (nand_fileio_finish(&s)) if (nand_fileio_finish(&s)) {
{
command_print(CMD_CTX, "wrote file %s to NAND flash %s up to " command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
"offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench), CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
duration_kbps(&s.bench, total_bytes)); duration_kbps(&s.bench, total_bytes));
} }
return ERROR_OK; return ERROR_OK;
} }
@ -310,12 +298,10 @@ COMMAND_HANDLER(handle_nand_verify_command)
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
while (file.size > 0) while (file.size > 0) {
{
retval = nand_read_page(nand, dev.address / dev.page_size, retval = nand_read_page(nand, dev.address / dev.page_size,
dev.page, dev.page_size, dev.oob, dev.oob_size); dev.page, dev.page_size, dev.oob, dev.oob_size);
if (ERROR_OK != retval) if (ERROR_OK != retval) {
{
command_print(CMD_CTX, "reading NAND flash page failed"); command_print(CMD_CTX, "reading NAND flash page failed");
nand_fileio_cleanup(&dev); nand_fileio_cleanup(&dev);
nand_fileio_cleanup(&file); nand_fileio_cleanup(&file);
@ -323,8 +309,7 @@ COMMAND_HANDLER(handle_nand_verify_command)
} }
int bytes_read = nand_fileio_read(nand, &file); int bytes_read = nand_fileio_read(nand, &file);
if (bytes_read <= 0) if (bytes_read <= 0) {
{
command_print(CMD_CTX, "error while reading file"); command_print(CMD_CTX, "error while reading file");
nand_fileio_cleanup(&dev); nand_fileio_cleanup(&dev);
nand_fileio_cleanup(&file); nand_fileio_cleanup(&file);
@ -332,10 +317,9 @@ COMMAND_HANDLER(handle_nand_verify_command)
} }
if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) || if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
(dev.oob && memcmp(dev.oob, file.oob, dev.oob_size)) ) (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size))) {
{
command_print(CMD_CTX, "NAND flash contents differ " command_print(CMD_CTX, "NAND flash contents differ "
"at 0x%8.8" PRIx32, dev.address); "at 0x%8.8" PRIx32, dev.address);
nand_fileio_cleanup(&dev); nand_fileio_cleanup(&dev);
nand_fileio_cleanup(&file); nand_fileio_cleanup(&file);
return ERROR_FAIL; return ERROR_FAIL;
@ -345,12 +329,11 @@ COMMAND_HANDLER(handle_nand_verify_command)
dev.address += nand->page_size; dev.address += nand->page_size;
} }
if (nand_fileio_finish(&file) == ERROR_OK) if (nand_fileio_finish(&file) == ERROR_OK) {
{
command_print(CMD_CTX, "verified file %s in NAND flash %s " command_print(CMD_CTX, "verified file %s in NAND flash %s "
"up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench), CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
duration_kbps(&file.bench, dev.size)); duration_kbps(&file.bench, dev.size));
} }
return nand_fileio_cleanup(&dev); return nand_fileio_cleanup(&dev);
@ -366,13 +349,11 @@ COMMAND_HANDLER(handle_nand_dump_command)
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
while (s.size > 0) while (s.size > 0) {
{
size_t size_written; size_t size_written;
retval = nand_read_page(nand, s.address / nand->page_size, retval = nand_read_page(nand, s.address / nand->page_size,
s.page, s.page_size, s.oob, s.oob_size); s.page, s.page_size, s.oob, s.oob_size);
if (ERROR_OK != retval) if (ERROR_OK != retval) {
{
command_print(CMD_CTX, "reading NAND flash page failed"); command_print(CMD_CTX, "reading NAND flash page failed");
nand_fileio_cleanup(&s); nand_fileio_cleanup(&s);
return retval; return retval;
@ -392,11 +373,10 @@ COMMAND_HANDLER(handle_nand_dump_command)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (nand_fileio_finish(&s) == ERROR_OK) if (nand_fileio_finish(&s) == ERROR_OK) {
{
command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)", command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)",
(long)filesize, duration_elapsed(&s.bench), (long)filesize, duration_elapsed(&s.bench),
duration_kbps(&s.bench, filesize)); duration_kbps(&s.bench, filesize));
} }
return ERROR_OK; return ERROR_OK;
} }
@ -404,17 +384,14 @@ COMMAND_HANDLER(handle_nand_dump_command)
COMMAND_HANDLER(handle_nand_raw_access_command) COMMAND_HANDLER(handle_nand_raw_access_command)
{ {
if ((CMD_ARGC < 1) || (CMD_ARGC > 2)) if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
struct nand_device *p; struct nand_device *p;
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p); int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
if (NULL == p->device) if (NULL == p->device) {
{
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]); command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
return ERROR_OK; return ERROR_OK;
} }
@ -510,9 +487,8 @@ COMMAND_HANDLER(handle_nand_init_command)
if (CMD_ARGC != 0) if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
static bool nand_initialized = false; static bool nand_initialized;
if (nand_initialized) if (nand_initialized) {
{
LOG_INFO("'nand init' has already been called"); LOG_INFO("'nand init' has already been called");
return ERROR_OK; return ERROR_OK;
} }
@ -536,32 +512,28 @@ COMMAND_HANDLER(handle_nand_list_drivers)
} }
static COMMAND_HELPER(create_nand_device, const char *bank_name, static COMMAND_HELPER(create_nand_device, const char *bank_name,
struct nand_flash_controller *controller) struct nand_flash_controller *controller)
{ {
struct nand_device *c; struct nand_device *c;
struct target *target; struct target *target;
int retval; int retval;
if (CMD_ARGC < 2) if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
target = get_target(CMD_ARGV[1]); target = get_target(CMD_ARGV[1]);
if (!target) { if (!target) {
LOG_ERROR("invalid target %s", CMD_ARGV[1]); LOG_ERROR("invalid target %s", CMD_ARGV[1]);
return ERROR_COMMAND_ARGUMENT_INVALID; return ERROR_COMMAND_ARGUMENT_INVALID;
} }
if (NULL != controller->commands) if (NULL != controller->commands) {
{
retval = register_commands(CMD_CTX, NULL, retval = register_commands(CMD_CTX, NULL,
controller->commands); controller->commands);
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
} }
c = malloc(sizeof(struct nand_device)); c = malloc(sizeof(struct nand_device));
if (c == NULL) if (c == NULL) {
{
LOG_ERROR("End of memory"); LOG_ERROR("End of memory");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -579,8 +551,7 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
c->next = NULL; c->next = NULL;
retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c); retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
if (ERROR_OK != retval) if (ERROR_OK != retval) {
{
LOG_ERROR("'%s' driver rejected nand flash. Usage: %s", LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
controller->name, controller->name,
controller->usage); controller->usage);
@ -599,19 +570,16 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
COMMAND_HANDLER(handle_nand_device_command) COMMAND_HANDLER(handle_nand_device_command)
{ {
if (CMD_ARGC < 2) if (CMD_ARGC < 2)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
// save name and increment (for compatibility) with drivers /* save name and increment (for compatibility) with drivers */
const char *bank_name = *CMD_ARGV++; const char *bank_name = *CMD_ARGV++;
CMD_ARGC--; CMD_ARGC--;
const char *driver_name = CMD_ARGV[0]; const char *driver_name = CMD_ARGV[0];
struct nand_flash_controller *controller; struct nand_flash_controller *controller;
controller = nand_driver_find_by_name(CMD_ARGV[0]); controller = nand_driver_find_by_name(CMD_ARGV[0]);
if (NULL == controller) if (NULL == controller) {
{
LOG_ERROR("No valid NAND flash driver found (%s)", driver_name); LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
return CALL_COMMAND_HANDLER(handle_nand_list_drivers); return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
} }
@ -642,6 +610,7 @@ static const struct command_registration nand_config_command_handlers[] = {
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
static const struct command_registration nand_command_handlers[] = { static const struct command_registration nand_command_handlers[] = {
{ {
.name = "nand", .name = "nand",
@ -657,5 +626,3 @@ int nand_register_commands(struct command_context *cmd_ctx)
{ {
return register_commands(cmd_ctx, NULL, nand_command_handlers); return register_commands(cmd_ctx, NULL, nand_command_handlers);
} }