Change-Id: I21bb466a35168cf04743f5baafac9fef50d01707 Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-on: http://openocd.zylin.com/419 Tested-by: jenkinstags/v0.6.0-rc1
@@ -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, | |||||
unsigned additional, struct working_area **area) | |||||
const uint32_t *code, unsigned code_size, | |||||
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 arm_algorithm algo; | |||||
struct arm *arm = target->arch_info; | |||||
struct reg_param reg_params[3]; | |||||
uint32_t target_buf; | |||||
uint32_t exit_var = 0; | |||||
int retval; | |||||
struct target *target = nand->target; | |||||
struct arm_algorithm algo; | |||||
struct arm *arm = target->arch_info; | |||||
struct reg_param reg_params[3]; | |||||
uint32_t target_buf; | |||||
uint32_t exit_var = 0; | |||||
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; | ||||
} | } | ||||
@@ -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_READ, /**< Read operation performed. */ | |||||
ARM_NAND_WRITE, /**< Write operation performed. */ | |||||
ARM_NAND_NONE, /**< No operation performed. */ | |||||
ARM_NAND_READ, /**< Read 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 */ |
@@ -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_CODR (0x34) /**< Offset to PIO CODR. */ | |||||
#define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */ | |||||
#define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */ | |||||
#define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */ | |||||
#define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */ | |||||
#define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */ | |||||
#define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */ | |||||
#define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */ | |||||
#define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */ | |||||
#define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */ | |||||
#define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */ | |||||
#define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */ | |||||
#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 | |||||
if (nand->page_size == 512) { | |||||
/* user doesn't want OOB, allocate it */ | |||||
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 { | |||||
// attempt recovery | |||||
else { | |||||
/* attempt recovery */ | |||||
uint32_t parity; | uint32_t parity; | ||||
target_read_u32(target, | target_read_u32(target, | ||||
info->ecc + AT91C_ECCx_PR, | |||||
&parity); | |||||
info->ecc + AT91C_ECCx_PR, | |||||
&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) bit); | |||||
(unsigned) word, | |||||
(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); | ||||
@@ -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, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS, "K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"}, | |||||
{ NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS, | |||||
"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, 0x64, 256, 2, 0x1000, 0, "NAND 2MiB 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, 0xec, 256, 1, 0x1000, 0, "NAND 1MiB 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, 0xe3, 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, 0x39, 512, 8, 0x2000, 0, "NAND 8MiB 1.8V 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, 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 3.3V 16-bit"}, | |||||
{ 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 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, 0xe8, 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, 0xd5, 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, 0xd6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 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, 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"}, | |||||
/* end "museum" IDs */ | /* end "museum" IDs */ | ||||
{ 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, 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, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 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, 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, 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, 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, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 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, 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, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 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, 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, 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, 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, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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 == 2048) && (oob[0] != 0xff)))) | |||||
{ | |||||
|| (((nand->page_size == 512) && (oob[5] != 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)) | |||||
{ | |||||
switch (retval) | |||||
{ | |||||
retval = nand->controller->init(nand); | |||||
if (retval != ERROR_OK) { | |||||
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 == 0 )) | |||||
{ | |||||
(nand_flash_ids[i].mfr_id == manufacturer_id || | |||||
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++) | |||||
{ | |||||
if (nand_manuf_ids[i].id == manufacturer_id) | |||||
{ | |||||
for (i = 0; nand_manuf_ids[i].name; i++) { | |||||
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) | |||||
{ | |||||
LOG_ERROR("unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x", | |||||
manufacturer_id, device_id); | |||||
if (!nand->device) { | |||||
LOG_ERROR( | |||||
"unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x", | |||||
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) | |||||
{ | |||||
if (nand->bus_width == 8) | |||||
{ | |||||
nand->device->erase_size == 0) { | |||||
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: | |||||
nand->erase_size = 64 << 10; | |||||
break; | |||||
case 1: | |||||
nand->erase_size = 128 << 10; | |||||
break; | |||||
case 2: | |||||
nand->erase_size = 256 << 10; | |||||
break; | |||||
case 3: | |||||
nand->erase_size =512 << 10; | |||||
break; | |||||
case 0: | |||||
nand->erase_size = 64 << 10; | |||||
break; | |||||
case 1: | |||||
nand->erase_size = 128 << 10; | |||||
break; | |||||
case 2: | |||||
nand->erase_size = 256 << 10; | |||||
break; | |||||
case 3: | |||||
nand->erase_size = 512 << 10; | |||||
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)) | |||||
{ | |||||
switch (retval) | |||||
{ | |||||
retval = nand->controller->init(nand); | |||||
if (retval != ERROR_OK) { | |||||
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)", | |||||
nand->bus_width, nand->address_cycles, nand->page_size); | |||||
LOG_ERROR( | |||||
"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++) | |||||
{ | |||||
if (nand->blocks[i].is_bad == -1) | |||||
{ | |||||
for (i = first_block; i <= last_block; i++) { | |||||
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_poll_ready(nand, 1000); | |||||
nand->controller->nand_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) | |||||
? "bad " : "", | |||||
i, status); | |||||
(nand->blocks[i].is_bad == 1) | |||||
? "bad " : "", | |||||
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 *oob, uint32_t oob_size) | |||||
uint8_t *data, uint32_t data_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 *oob, uint32_t oob_size) | |||||
uint8_t *data, uint32_t data_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 *oob, uint32_t oob_size) | |||||
uint8_t *data, uint32_t data_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_poll_ready(nand, 100); | |||||
nand->controller->nand_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 *oob, uint32_t oob_size) | |||||
uint8_t *data, uint32_t data_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); | ||||
} | } | ||||
@@ -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_SW_ECC_KW = 0x40, /* when writing, use Marvell's Kirkwood bootrom format */ | |||||
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_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_OPERATION_FAILED (-1101) | |||||
#define ERROR_NAND_OPERATION_TIMEOUT (-1102) | |||||
#define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103) | |||||
#define ERROR_NAND_DEVICE_NOT_PROBED (-1104) | |||||
#define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105) | |||||
#define ERROR_NAND_NO_BUFFER (-1106) | |||||
#endif // FLASH_NAND_CORE_H | |||||
#define ERROR_NAND_DEVICE_INVALID (-1100) | |||||
#define ERROR_NAND_OPERATION_FAILED (-1101) | |||||
#define ERROR_NAND_OPERATION_TIMEOUT (-1102) | |||||
#define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103) | |||||
#define ERROR_NAND_DEVICE_NOT_PROBED (-1104) | |||||
#define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105) | |||||
#define ERROR_NAND_NO_BUFFER (-1106) | |||||
#endif /* FLASH_NAND_CORE_H */ |
@@ -39,34 +39,34 @@ enum ecc { | |||||
}; | }; | ||||
struct davinci_nand { | struct davinci_nand { | ||||
uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */ | |||||
uint8_t eccmode; | |||||
uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */ | |||||
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 cmd; /* with CLE */ | |||||
uint32_t addr; /* with ALE */ | |||||
uint32_t data; /* without CLE or ALE */ | |||||
uint32_t cmd; /* with CLE */ | |||||
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 NANDFSR 0x64 /* flash status register */ | |||||
#define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */ | |||||
#define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */ | |||||
#define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */ | |||||
#define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */ | |||||
#define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */ | |||||
#define NANDFCR 0x60 /* flash control register */ | |||||
#define NANDFSR 0x64 /* flash status register */ | |||||
#define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */ | |||||
#define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */ | |||||
#define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */ | |||||
#define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 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: | |||||
oob_size = 16; | |||||
break; | |||||
case 2048: | |||||
oob_size = 64; | |||||
break; | |||||
case 4096: | |||||
oob_size = 128; | |||||
break; | |||||
default: | |||||
return ERROR_NAND_OPERATION_FAILED; | |||||
case 512: | |||||
oob_size = 16; | |||||
break; | |||||
case 2048: | |||||
oob_size = 64; | |||||
break; | |||||
case 4096: | |||||
oob_size = 128; | |||||
break; | |||||
default: | |||||
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: | |||||
oob_offset = 0; | |||||
break; | |||||
case 2048: | |||||
oob_offset = 40; | |||||
break; | |||||
default: | |||||
oob_offset = 80; | |||||
break; | |||||
case 512: | |||||
oob_offset = 0; | |||||
break; | |||||
case 2048: | |||||
oob_offset = 40; | |||||
break; | |||||
default: | |||||
oob_offset = 80; | |||||
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, | |||||
58, 59, 60, 61, 62, 63, 64, 65, 66, 67, | |||||
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, | |||||
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, | |||||
88, 89, 90, 91, 92, 93, 94, 95, 96, 97, | |||||
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, | |||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, | |||||
58, 59, 60, 61, 62, 63, 64, 65, 66, 67, | |||||
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, | |||||
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, | |||||
88, 89, 90, 91, 92, 93, 94, 95, 96, 97, | |||||
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: | |||||
l = ecc512; | |||||
break; | |||||
case 2048: | |||||
l = ecc2048; | |||||
break; | |||||
default: | |||||
l = ecc4096; | |||||
break; | |||||
case 512: | |||||
l = ecc512; | |||||
break; | |||||
case 2048: | |||||
l = ecc2048; | |||||
break; | |||||
default: | |||||
l = ecc4096; | |||||
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 == 0x01d10000 /* dm365 */ | |||||
) { | |||||
|| aemif == 0x01e10000 /* dm335, dm355 */ | |||||
|| 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: | |||||
/* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */ | |||||
info->write_page = davinci_write_page_ecc1; | |||||
break; | |||||
case HWECC4: | |||||
/* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */ | |||||
info->write_page = davinci_write_page_ecc4; | |||||
break; | |||||
case HWECC4_INFIX: | |||||
/* Same 4-bit ECC HW, with problematic page/ecc layout */ | |||||
info->read_page = davinci_read_page_ecc4infix; | |||||
info->write_page = davinci_write_page_ecc4infix; | |||||
break; | |||||
case HWECC1: | |||||
/* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */ | |||||
info->write_page = davinci_write_page_ecc1; | |||||
break; | |||||
case HWECC4: | |||||
/* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */ | |||||
info->write_page = davinci_write_page_ecc4; | |||||
break; | |||||
case HWECC4_INFIX: | |||||
/* Same 4-bit ECC HW, with problematic page/ecc layout */ | |||||
info->read_page = davinci_read_page_ecc4infix; | |||||
info->write_page = davinci_write_page_ecc4infix; | |||||
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", | |||||
.usage = "chip_addr hwecc_mode aemif_addr", | |||||
.nand_device_command = davinci_nand_device_command, | |||||
.init = davinci_init, | |||||
.reset = davinci_reset, | |||||
.command = davinci_command, | |||||
.address = davinci_address, | |||||
.write_data = davinci_write_data, | |||||
.read_data = davinci_read_data, | |||||
.write_page = davinci_write_page, | |||||
.read_page = davinci_read_page, | |||||
.write_block_data = davinci_write_block_data, | |||||
.read_block_data = davinci_read_block_data, | |||||
.nand_ready = davinci_nand_ready, | |||||
.name = "davinci", | |||||
.usage = "chip_addr hwecc_mode aemif_addr", | |||||
.nand_device_command = davinci_nand_device_command, | |||||
.init = davinci_init, | |||||
.reset = davinci_reset, | |||||
.command = davinci_command, | |||||
.address = davinci_address, | |||||
.write_data = davinci_write_data, | |||||
.read_data = davinci_read_data, | |||||
.write_page = davinci_write_page, | |||||
.read_page = davinci_read_page, | |||||
.write_block_data = davinci_write_block_data, | |||||
.read_block_data = davinci_read_block_data, | |||||
.nand_ready = davinci_nand_ready, | |||||
}; | }; |
@@ -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; | ||||
} | } | ||||
@@ -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 | |||||
typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void*); | |||||
/* / Signature for callback functions passed to nand_driver_walk */ | |||||
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 */ |
@@ -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 && | |||||
((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && | |||||
((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { | |||||
if (((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && | |||||
((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && | |||||
((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; | ||||
@@ -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 | ||||
@@ -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, | |||||
48, 49, 50, 51, 52, 53, 54, 55, | |||||
56, 57, 58, 59, 60, 61, 62, 63}, | |||||
40, 41, 42, 43, 44, 45, 46, 47, | |||||
48, 49, 50, 51, 52, 53, 54, 55, | |||||
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_fileio_state *state) | |||||
struct nand_device *nand, const char *filename, int filemode, | |||||
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 (nand->page_size == 512) | |||||
{ | |||||
if (state->oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW)) { | |||||
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, | |||||
bool need_size, bool sw_ecc) | |||||
struct nand_device **dev, enum fileio_access filemode, | |||||
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) | |||||
{ | |||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], state->size); | |||||
if (state->size % nand->page_size) | |||||
{ | |||||
command_print(CMD_CTX, "only page-aligned sizes are supported"); | |||||
return ERROR_COMMAND_SYNTAX_ERROR; | |||||
} | |||||
if (need_size) { | |||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], state->size); | |||||
if (state->size % nand->page_size) { | |||||
command_print(CMD_CTX, "only page-aligned sizes are supported"); | |||||
return ERROR_COMMAND_SYNTAX_ERROR; | |||||
} | |||||
} | } | ||||
if (CMD_ARGC > minargs) | |||||
{ | |||||
for (unsigned i = minargs; i < CMD_ARGC; i++) | |||||
{ | |||||
if (CMD_ARGC > minargs) { | |||||
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; | ||||
} | } | ||||
@@ -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, | |||||
bool need_size, bool sw_ecc); | |||||
struct nand_device **dev, enum fileio_access filemode, | |||||
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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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 */ |
@@ -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_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00) | |||||
#define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04) | |||||
#define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06) | |||||
#define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08) | |||||
#define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a) | |||||
#define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c) | |||||
#define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e) | |||||
#define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10) | |||||
#define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12) | |||||
#define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14) | |||||
#define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16) | |||||
#define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18) | |||||
/* | |||||
* all bits not marked as self-clearing bit | |||||
*/ | |||||
#define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a) | |||||
#define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c) | |||||
#define MX3_NF_BASE_ADDR 0xb8000000 | |||||
#define MX3_NF_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00) | |||||
#define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04) | |||||
#define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06) | |||||
#define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08) | |||||
#define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a) | |||||
#define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c) | |||||
#define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e) | |||||
#define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10) | |||||
#define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12) | |||||
#define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14) | |||||
#define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16) | |||||
#define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18) | |||||
/* | |||||
* all bits not marked as self-clearing bit | |||||
*/ | |||||
#define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a) | |||||
#define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c) | |||||
#define MX3_NF_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000) | |||||
#define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200) | |||||
#define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400) | |||||
#define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600) | |||||
#define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800) | |||||
#define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810) | |||||
#define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820) | |||||
#define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830) | |||||
#define MX3_NF_MAIN_BUFFER_LEN 512 | |||||
#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_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000) | |||||
#define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200) | |||||
#define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400) | |||||
#define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600) | |||||
#define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800) | |||||
#define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810) | |||||
#define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820) | |||||
#define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830) | |||||
#define MX3_NF_MAIN_BUFFER_LEN 512 | |||||
#define MX3_NF_SPARE_BUFFER_LEN 16 | |||||
#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_ECC_EN (1<<3) | |||||
#define MX3_NF_BIT_INT_DIS (1<<4) | |||||
#define MX3_NF_BIT_BE_EN (1<<5) | |||||
#define MX3_NF_BIT_RESET_EN (1<<6) | |||||
#define MX3_NF_BIT_FORCE_CE (1<<7) | |||||
#define MX3_NF_BIT_SPARE_ONLY_EN (1<<2) | |||||
#define MX3_NF_BIT_ECC_EN (1<<3) | |||||
#define MX3_NF_BIT_INT_DIS (1<<4) | |||||
#define MX3_NF_BIT_BE_EN (1<<5) | |||||
#define MX3_NF_BIT_RESET_EN (1<<6) | |||||
#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) | |||||
/* | |||||
* Flash Address Input | |||||
*/ | |||||
#define MX3_NF_BIT_OP_FAI (1<<1) | |||||
/* | |||||
* Flash Data Input | |||||
*/ | |||||
#define MX3_NF_BIT_OP_FDI (1<<2) | |||||
#define MX3_NF_BIT_OP_FCI (1<<0) | |||||
/* | |||||
* Flash Address Input | |||||
*/ | |||||
#define MX3_NF_BIT_OP_FAI (1<<1) | |||||
/* | |||||
* Flash Data Input | |||||
*/ | |||||
#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_OP_DONE (1<<15) | |||||
#define MX3_NF_BIT_DATAOUT_TYPE(x) ((x)<<3) | |||||
#define MX3_NF_BIT_OP_DONE (1<<15) | |||||
#define MX3_CCM_CGR2 0x53f80028 | |||||
#define MX3_GPR 0x43fac008 | |||||
#define MX3_PCSR 0x53f8000c | |||||
#define MX3_CCM_CGR2 0x53f80028 | |||||
#define MX3_GPR 0x43fac008 | |||||
#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; | ||||
@@ -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"); | |||||
} else { | |||||
"pagesize 2048 is incompatible with it"); | |||||
} 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: | |||||
command = NAND_CMD_READ0; | |||||
/* set read point for data_read() and read_block_data() to | |||||
* spare area in SRAM buffer | |||||
*/ | |||||
if (nfc_is_v1()) | |||||
in_sram_address = MXC_NF_V1_SPARE_BUFFER0; | |||||
else | |||||
in_sram_address = MXC_NF_V2_SPARE_BUFFER0; | |||||
break; | |||||
case NAND_CMD_READ1: | |||||
command = NAND_CMD_READ0; | |||||
/* | |||||
* offset == one half of page size | |||||
*/ | |||||
in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1); | |||||
break; | |||||
default: | |||||
in_sram_address = MXC_NF_MAIN_BUFFER0; | |||||
break; | |||||
case NAND_CMD_READOOB: | |||||
command = NAND_CMD_READ0; | |||||
/* set read point for data_read() and read_block_data() to | |||||
* spare area in SRAM buffer | |||||
*/ | |||||
if (nfc_is_v1()) | |||||
in_sram_address = MXC_NF_V1_SPARE_BUFFER0; | |||||
else | |||||
in_sram_address = MXC_NF_V2_SPARE_BUFFER0; | |||||
break; | |||||
case NAND_CMD_READ1: | |||||
command = NAND_CMD_READ0; | |||||
/* | |||||
* offset == one half of page size | |||||
*/ | |||||
in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1); | |||||
break; | |||||
default: | |||||
in_sram_address = MXC_NF_MAIN_BUFFER0; | |||||
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: | |||||
mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID; | |||||
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; | |||||
break; | |||||
case NAND_CMD_STATUS: | |||||
mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS; | |||||
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; | |||||
target_write_u16 (target, MXC_NF_BUFADDR, 0); | |||||
in_sram_address = 0; | |||||
break; | |||||
case NAND_CMD_READ0: | |||||
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; | |||||
mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; | |||||
break; | |||||
default: | |||||
/* Ohter command use the default 'One page data out' FDO */ | |||||
mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; | |||||
break; | |||||
case NAND_CMD_READID: | |||||
mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID; | |||||
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; | |||||
break; | |||||
case NAND_CMD_STATUS: | |||||
mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS; | |||||
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; | |||||
target_write_u16 (target, MXC_NF_BUFADDR, 0); | |||||
in_sram_address = 0; | |||||
break; | |||||
case NAND_CMD_READ0: | |||||
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; | |||||
mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; | |||||
break; | |||||
default: | |||||
/* Ohter command use the default 'One page data out' FDO */ | |||||
mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE; | |||||
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 *oob, uint32_t oob_size) | |||||
uint8_t *data, uint32_t data_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, page & 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, 0); /* col */ | |||||
retval |= mxc_address(nand, 0); /* col */ | |||||
retval |= mxc_address(nand, page & 0xff); /* page address */ | |||||
retval |= mxc_address(nand, (page >> 8) & 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 *oob, uint32_t oob_size) | |||||
uint8_t *data, uint32_t data_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; | |||||
retval = mxc_address(nand, 0); /* col */ | |||||
if (retval != ERROR_OK) return retval; | |||||
retval = mxc_address(nand, 0); /* col */ | |||||
if (retval != ERROR_OK) return retval; | |||||
retval = mxc_address(nand, page & 0xff); /* page address */ | |||||
if (retval != ERROR_OK) 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; | |||||
if (retval != ERROR_OK) | |||||
return retval; | |||||
retval = mxc_address(nand, 0); /* col */ | |||||
if (retval != ERROR_OK) | |||||
return retval; | |||||
retval = mxc_address(nand, 0); /* col */ | |||||
if (retval != ERROR_OK) | |||||
return retval; | |||||
retval = mxc_address(nand, page & 0xff);/* page address */ | |||||
if (retval != ERROR_OK) | |||||
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 > | |||||
(nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) { | |||||
if (in_sram_address > (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 > | |||||
(nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) { | |||||
if (in_sram_address > (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: | |||||
LOG_INFO("main area read with 1 (correctable) error"); | |||||
break; | |||||
case 2 << 2: | |||||
LOG_INFO("main area read with more than 1 (incorrectable) error"); | |||||
return ERROR_NAND_OPERATION_FAILED; | |||||
break; | |||||
case 1 << 2: | |||||
LOG_INFO("main area read with 1 (correctable) error"); | |||||
break; | |||||
case 2 << 2: | |||||
LOG_INFO("main area read with more than 1 (incorrectable) error"); | |||||
return ERROR_NAND_OPERATION_FAILED; | |||||
break; | |||||
} | } | ||||
switch (ecc_status & 0x0003) { | switch (ecc_status & 0x0003) { | ||||
case 1: | |||||
LOG_INFO("spare area read with 1 (correctable) error"); | |||||
break; | |||||
case 2: | |||||
LOG_INFO("main area read with more than 1 (incorrectable) error"); | |||||
return ERROR_NAND_OPERATION_FAILED; | |||||
break; | |||||
case 1: | |||||
LOG_INFO("spare area read with 1 (correctable) error"); | |||||
break; | |||||
case 2: | |||||
LOG_INFO("main area read with more than 1 (incorrectable) error"); | |||||
return ERROR_NAND_OPERATION_FAILED; | |||||
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: | |||||
/* | |||||
* 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)); | |||||
poll_result = poll_for_complete_op(nand, "data output"); | |||||
if (poll_result != ERROR_OK) | |||||
return poll_result; | |||||
case MXC_NF_FIN_DATAOUT: | |||||
/* | |||||
* 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)); | |||||
poll_result = poll_for_complete_op(nand, "data output"); | |||||
if (poll_result != ERROR_OK) | |||||
return poll_result; | |||||
mxc_nf_info->fin = MXC_NF_FIN_NONE; | |||||
/* | |||||
* ECC stuff | |||||
*/ | |||||
if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && | |||||
mxc_nf_info->flags.hw_ecc_enabled) { | |||||
int ecc_status; | |||||
if (nfc_is_v1()) | |||||
ecc_status = ecc_status_v1(nand); | |||||
else | |||||
ecc_status = ecc_status_v2(nand); | |||||
if (ecc_status != ERROR_OK) | |||||
return ecc_status; | |||||
} | |||||
break; | |||||
case MXC_NF_FIN_NONE: | |||||
break; | |||||
mxc_nf_info->fin = MXC_NF_FIN_NONE; | |||||
/* | |||||
* ECC stuff | |||||
*/ | |||||
if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && mxc_nf_info->flags.hw_ecc_enabled) { | |||||
int ecc_status; | |||||
if (nfc_is_v1()) | |||||
ecc_status = ecc_status_v1(nand); | |||||
else | |||||
ecc_status = ecc_status_v2(nand); | |||||
if (ecc_status != ERROR_OK) | |||||
return ecc_status; | |||||
} | |||||
break; | |||||
case MXC_NF_FIN_NONE: | |||||
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", | |||||
.nand_device_command = &mxc_nand_device_command, | |||||
.commands = mxc_nand_command_handler, | |||||
.init = &mxc_init, | |||||
.reset = &mxc_reset, | |||||
.command = &mxc_command, | |||||
.address = &mxc_address, | |||||
.write_data = &mxc_write_data, | |||||
.read_data = &mxc_read_data, | |||||
.write_page = &mxc_write_page, | |||||
.read_page = &mxc_read_page, | |||||
.nand_ready = &mxc_nand_ready, | |||||
.name = "mxc", | |||||
.nand_device_command = &mxc_nand_device_command, | |||||
.commands = mxc_nand_command_handler, | |||||
.init = &mxc_init, | |||||
.reset = &mxc_reset, | |||||
.command = &mxc_command, | |||||
.address = &mxc_address, | |||||
.write_data = &mxc_write_data, | |||||
.read_data = &mxc_read_data, | |||||
.write_page = &mxc_write_page, | |||||
.read_page = &mxc_read_page, | |||||
.nand_ready = &mxc_nand_ready, | |||||
}; | }; |
@@ -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 = | |||||
{ | |||||
.name = "nonce", | |||||
.commands = hello_command_handlers, | |||||
.nand_device_command = &nonce_nand_device_command, | |||||
.init = &nonce_nand_init, | |||||
.reset = &nonce_nand_reset, | |||||
.command = &nonce_nand_command, | |||||
.address = &nonce_nand_address, | |||||
.read_data = &nonce_nand_read, | |||||
.write_data = &nonce_nand_write, | |||||
.write_block_data = &nonce_nand_fast_block_write, | |||||
struct nand_flash_controller nonce_nand_controller = { | |||||
.name = "nonce", | |||||
.commands = hello_command_handlers, | |||||
.nand_device_command = &nonce_nand_device_command, | |||||
.init = &nonce_nand_init, | |||||
.reset = &nonce_nand_reset, | |||||
.command = &nonce_nand_command, | |||||
.address = &nonce_nand_address, | |||||
.read_data = &nonce_nand_read, | |||||
.write_data = &nonce_nand_write, | |||||
.write_block_data = &nonce_nand_fast_block_write, | |||||
}; | }; |
@@ -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, | ||||
@@ -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 = | |||||
{ | |||||
.name = "orion", | |||||
.usage = "<target_id> <NAND_address>", | |||||
.command = orion_nand_command, | |||||
.address = orion_nand_address, | |||||
.read_data = orion_nand_read, | |||||
.write_data = orion_nand_write, | |||||
.write_block_data = orion_nand_fast_block_write, | |||||
.reset = orion_nand_reset, | |||||
.nand_device_command = orion_nand_device_command, | |||||
.init = orion_nand_init, | |||||
struct nand_flash_controller orion_nand_controller = { | |||||
.name = "orion", | |||||
.usage = "<target_id> <NAND_address>", | |||||
.command = orion_nand_command, | |||||
.address = orion_nand_address, | |||||
.read_data = orion_nand_read, | |||||
.write_data = orion_nand_write, | |||||
.write_block_data = orion_nand_fast_block_write, | |||||
.reset = orion_nand_reset, | |||||
.nand_device_command = orion_nand_device_command, | |||||
.init = orion_nand_init, | |||||
}; | }; | ||||
@@ -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", | |||||
.nand_device_command = &s3c2410_nand_device_command, | |||||
.init = &s3c2410_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c2410_write_data, | |||||
.read_data = &s3c2410_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.nand_ready = &s3c2410_nand_ready, | |||||
}; | |||||
.name = "s3c2410", | |||||
.nand_device_command = &s3c2410_nand_device_command, | |||||
.init = &s3c2410_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c2410_write_data, | |||||
.read_data = &s3c2410_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.nand_ready = &s3c2410_nand_ready, | |||||
}; |
@@ -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", | |||||
.nand_device_command = &s3c2412_nand_device_command, | |||||
.init = &s3c2412_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c24xx_write_data, | |||||
.read_data = &s3c24xx_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.write_block_data = &s3c2440_write_block_data, | |||||
.read_block_data = &s3c2440_read_block_data, | |||||
.nand_ready = &s3c2440_nand_ready, | |||||
}; | |||||
.name = "s3c2412", | |||||
.nand_device_command = &s3c2412_nand_device_command, | |||||
.init = &s3c2412_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c24xx_write_data, | |||||
.read_data = &s3c24xx_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.write_block_data = &s3c2440_write_block_data, | |||||
.read_block_data = &s3c2440_read_block_data, | |||||
.nand_ready = &s3c2440_nand_ready, | |||||
}; |
@@ -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", | |||||
.nand_device_command = &s3c2440_nand_device_command, | |||||
.init = &s3c2440_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c24xx_write_data, | |||||
.read_data = &s3c24xx_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.write_block_data = &s3c2440_write_block_data, | |||||
.read_block_data = &s3c2440_read_block_data, | |||||
.nand_ready = &s3c2440_nand_ready, | |||||
}; | |||||
.name = "s3c2440", | |||||
.nand_device_command = &s3c2440_nand_device_command, | |||||
.init = &s3c2440_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c24xx_write_data, | |||||
.read_data = &s3c24xx_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.write_block_data = &s3c2440_write_block_data, | |||||
.read_block_data = &s3c2440_read_block_data, | |||||
.nand_ready = &s3c2440_nand_ready, | |||||
}; |
@@ -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", | |||||
.nand_device_command = &s3c2443_nand_device_command, | |||||
.init = &s3c2443_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c24xx_write_data, | |||||
.read_data = &s3c24xx_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.write_block_data = &s3c2440_write_block_data, | |||||
.read_block_data = &s3c2440_read_block_data, | |||||
.nand_ready = &s3c2440_nand_ready, | |||||
}; | |||||
.name = "s3c2443", | |||||
.nand_device_command = &s3c2443_nand_device_command, | |||||
.init = &s3c2443_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c24xx_write_data, | |||||
.read_data = &s3c24xx_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.write_block_data = &s3c2440_write_block_data, | |||||
.read_block_data = &s3c2440_read_block_data, | |||||
.nand_ready = &s3c2440_nand_ready, | |||||
}; |
@@ -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; | ||||
@@ -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 */ |
@@ -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) | ||||
@@ -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", | |||||
.nand_device_command = &s3c6400_nand_device_command, | |||||
.init = &s3c6400_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c24xx_write_data, | |||||
.read_data = &s3c24xx_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.write_block_data = &s3c2440_write_block_data, | |||||
.read_block_data = &s3c2440_read_block_data, | |||||
.nand_ready = &s3c2440_nand_ready, | |||||
}; | |||||
.name = "s3c6400", | |||||
.nand_device_command = &s3c6400_nand_device_command, | |||||
.init = &s3c6400_init, | |||||
.reset = &s3c24xx_reset, | |||||
.command = &s3c24xx_command, | |||||
.address = &s3c24xx_address, | |||||
.write_data = &s3c24xx_write_data, | |||||
.read_data = &s3c24xx_read_data, | |||||
.write_page = s3c24xx_write_page, | |||||
.read_page = s3c24xx_read_page, | |||||
.write_block_data = &s3c2440_write_block_data, | |||||
.read_block_data = &s3c2440_read_block_data, | |||||
.nand_ready = &s3c2440_nand_ready, | |||||
}; |
@@ -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: | |||||
return ERROR_COMMAND_SYNTAX_ERROR; | |||||
case 1: | |||||
first = 0; | |||||
last = INT32_MAX; | |||||
break; | |||||
case 2: | |||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i); | |||||
first = last = i; | |||||
i = 0; | |||||
break; | |||||
case 3: | |||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first); | |||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last); | |||||
break; | |||||
default: | |||||
return ERROR_COMMAND_SYNTAX_ERROR; | |||||
case 1: | |||||
first = 0; | |||||
last = INT32_MAX; | |||||
break; | |||||
case 2: | |||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i); | |||||
first = last = i; | |||||
i = 0; | |||||
break; | |||||
case 3: | |||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first); | |||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last); | |||||
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", | |||||
i++, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size); | |||||
command_print(CMD_CTX, | |||||
"#%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", | |||||
j, | |||||
p->blocks[j].offset, | |||||
p->blocks[j].size / 1024, | |||||
erase_state, | |||||
bad_state); | |||||
"\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s", | |||||
j, | |||||
p->blocks[j].offset, | |||||
p->blocks[j].size / 1024, | |||||
erase_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'", | |||||
offset, offset + length - 1, | |||||
CMD_ARGV[0], p->device->name); | |||||
"on NAND flash device #%s '%s'", | |||||
offset, offset + length - 1, | |||||
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)", | |||||
CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench), | |||||
duration_kbps(&s.bench, total_bytes)); | |||||
"offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", | |||||
CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench), | |||||
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)", | |||||
CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench), | |||||
duration_kbps(&file.bench, dev.size)); | |||||
"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), | |||||
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), | |||||
duration_kbps(&s.bench, filesize)); | |||||
(long)filesize, duration_elapsed(&s.bench), | |||||
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; | |||||
if (nand_initialized) | |||||
{ | |||||
static bool 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); | ||||
} | } | ||||