build: cleanup src/flash/nand directory
Change-Id: I21bb466a35168cf04743f5baafac9fef50d01707 Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-on: http://openocd.zylin.com/419 Tested-by: jenkins
This commit is contained in:
parent
1e9f8836a1
commit
fab0dcd7e6
|
@ -30,7 +30,6 @@
|
|||
#include <target/arm.h>
|
||||
#include <target/algorithm.h>
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -44,8 +43,8 @@
|
|||
* @return Success or failure of the operation
|
||||
*/
|
||||
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];
|
||||
unsigned i;
|
||||
|
@ -61,7 +60,7 @@ static int arm_code_to_working_area(struct target *target,
|
|||
if (NULL == *area) {
|
||||
retval = target_alloc_working_area(target, size, area);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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:
|
||||
* 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) {
|
||||
retval = arm_code_to_working_area(target, code, sizeof(code),
|
||||
nand->chunk_size, &nand->copy_area);
|
||||
if (retval != ERROR_OK) {
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
retval = arm_code_to_working_area(target, code, sizeof(code),
|
||||
nand->chunk_size, &nand->copy_area);
|
||||
if (retval != ERROR_OK) {
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
* Available operational states the arm_nand_data struct can be in.
|
||||
*/
|
||||
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;
|
||||
|
||||
/** 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. */
|
||||
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_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.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
@ -26,13 +27,13 @@
|
|||
#include "imp.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.
|
||||
|
@ -97,9 +98,8 @@ static int at91sam9_init(struct nand_device *nand)
|
|||
{
|
||||
struct target *target = nand->target;
|
||||
|
||||
if (!at91sam9_halted(target, "init")) {
|
||||
if (!at91sam9_halted(target, "init"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
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 target *target = nand->target;
|
||||
|
||||
if (!at91sam9_halted(target, "command")) {
|
||||
if (!at91sam9_halted(target, "command"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!at91sam9_halted(nand->target, "reset")) {
|
||||
if (!at91sam9_halted(nand->target, "reset"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
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 target *target = nand->target;
|
||||
|
||||
if (!at91sam9_halted(nand->target, "address")) {
|
||||
if (!at91sam9_halted(nand->target, "address"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
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 target *target = nand->target;
|
||||
|
||||
if (!at91sam9_halted(nand->target, "read data")) {
|
||||
if (!at91sam9_halted(nand->target, "read data"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
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 target *target = nand->target;
|
||||
|
||||
if (!at91sam9_halted(target, "write data")) {
|
||||
if (!at91sam9_halted(target, "write data"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
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;
|
||||
uint32_t status;
|
||||
|
||||
if (!at91sam9_halted(target, "nand ready")) {
|
||||
if (!at91sam9_halted(target, "nand ready"))
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
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;
|
||||
}
|
||||
|
||||
alive_sleep(1);
|
||||
} 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;
|
||||
int status;
|
||||
|
||||
if (!at91sam9_halted(nand->target, "read block")) {
|
||||
if (!at91sam9_halted(nand->target, "read block"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
io->chunk_size = nand->page_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;
|
||||
int status;
|
||||
|
||||
if (!at91sam9_halted(nand->target, "write block")) {
|
||||
if (!at91sam9_halted(nand->target, "write block"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
io->chunk_size = nand->page_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;
|
||||
}
|
||||
|
||||
// reset ECC parity registers
|
||||
/* reset ECC parity registers */
|
||||
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.
|
||||
* @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) {
|
||||
// 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;
|
||||
} else if (nand->page_size == 2048) {
|
||||
else if (nand->page_size == 2048)
|
||||
*size = 64;
|
||||
}
|
||||
|
||||
oob = malloc(*size);
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
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;
|
||||
|
||||
retval = at91sam9_ecc_init(target, info);
|
||||
if (ERROR_OK != retval) {
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = nand_page_command(nand, page, NAND_CMD_READ0, !data);
|
||||
if (ERROR_OK != retval) {
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
retval = nand_read_data_page(nand, data, data_size);
|
||||
if (ERROR_OK != retval) {
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (status & 1) {
|
||||
LOG_ERROR("Error detected!");
|
||||
if (status & 4) {
|
||||
if (status & 4)
|
||||
LOG_ERROR("Multiple errors encountered; unrecoverable!");
|
||||
} else {
|
||||
// attempt recovery
|
||||
else {
|
||||
/* attempt recovery */
|
||||
uint32_t parity;
|
||||
|
||||
target_read_u32(target,
|
||||
info->ecc + AT91C_ECCx_PR,
|
||||
&parity);
|
||||
info->ecc + AT91C_ECCx_PR,
|
||||
&parity);
|
||||
uint32_t word = (parity & 0x0000FFF0) >> 4;
|
||||
uint32_t bit = parity & 0x0F;
|
||||
|
||||
data[word] ^= (0x1) << bit;
|
||||
LOG_INFO("Data word %d, bit %d corrected.",
|
||||
(unsigned) word,
|
||||
(unsigned) bit);
|
||||
(unsigned) word,
|
||||
(unsigned) bit);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & 2) {
|
||||
// we could write back correct ECC data
|
||||
/* we could write back correct ECC data */
|
||||
LOG_ERROR("Error in ECC bytes detected");
|
||||
}
|
||||
}
|
||||
|
||||
if (!oob) {
|
||||
// if it wasn't asked for, free it
|
||||
/* if it wasn't asked for, free it */
|
||||
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.
|
||||
*/
|
||||
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 target *target = nand->target;
|
||||
|
@ -458,14 +445,12 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
|
|||
uint32_t parity, nparity;
|
||||
|
||||
retval = at91sam9_ecc_init(target, info);
|
||||
if (ERROR_OK != retval) {
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
|
||||
if (ERROR_OK != retval) {
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
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);
|
||||
|
||||
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_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);
|
||||
|
||||
if (!oob) {
|
||||
if (!oob)
|
||||
free(oob_data);
|
||||
}
|
||||
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Unable to write OOB data to NAND");
|
||||
|
@ -594,9 +578,8 @@ COMMAND_HANDLER(handle_at91sam9_ale_command)
|
|||
struct at91sam9_nand *info = NULL;
|
||||
unsigned num, address_line;
|
||||
|
||||
if (CMD_ARGC != 2) {
|
||||
if (CMD_ARGC != 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
|
||||
nand = get_nand_device_by_num(num);
|
||||
|
@ -623,9 +606,8 @@ COMMAND_HANDLER(handle_at91sam9_rdy_busy_command)
|
|||
struct at91sam9_nand *info = NULL;
|
||||
unsigned num, base_pioc, pin_num;
|
||||
|
||||
if (CMD_ARGC != 3) {
|
||||
if (CMD_ARGC != 3)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
|
||||
nand = get_nand_device_by_num(num);
|
||||
|
@ -655,9 +637,8 @@ COMMAND_HANDLER(handle_at91sam9_ce_command)
|
|||
struct at91sam9_nand *info = NULL;
|
||||
unsigned num, base_pioc, pin_num;
|
||||
|
||||
if (CMD_ARGC != 3) {
|
||||
if (CMD_ARGC != 3)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
|
||||
nand = get_nand_device_by_num(num);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
@ -27,13 +28,14 @@
|
|||
#include "imp.h"
|
||||
|
||||
/* 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)
|
||||
{
|
||||
if (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;
|
||||
} else
|
||||
nand_devices = c;
|
||||
|
@ -50,94 +52,94 @@ void nand_device_add(struct nand_device *c)
|
|||
* 256 256 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 */
|
||||
{ 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 */
|
||||
{ 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, 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, 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 */
|
||||
|
||||
{ 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
/* Manufacturer ID list
|
||||
*/
|
||||
static struct nand_manufacturer nand_manuf_ids[] =
|
||||
{
|
||||
static struct nand_manufacturer nand_manuf_ids[] = {
|
||||
{0x0, "unknown"},
|
||||
{NAND_MFR_TOSHIBA, "Toshiba"},
|
||||
{NAND_MFR_SAMSUNG, "Samsung"},
|
||||
|
@ -162,7 +164,8 @@ static struct nand_ecclayout nand_oob_8 = {
|
|||
{.offset = 3,
|
||||
.length = 2},
|
||||
{.offset = 6,
|
||||
.length = 2}}
|
||||
.length = 2}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -179,8 +182,7 @@ static struct nand_device *get_nand_device_by_name(const char *name)
|
|||
unsigned found = 0;
|
||||
|
||||
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)
|
||||
return nand;
|
||||
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;
|
||||
int i = 0;
|
||||
|
||||
for (p = nand_devices; p; p = p->next)
|
||||
{
|
||||
for (p = nand_devices; p; p = p->next) {
|
||||
if (i++ == num)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
COMMAND_HELPER(nand_command_get_device, unsigned name_index,
|
||||
struct nand_device **nand)
|
||||
struct nand_device **nand)
|
||||
{
|
||||
const char *str = CMD_ARGV[name_index];
|
||||
*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;
|
||||
|
||||
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);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
nand->blocks[i].is_bad = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else
|
||||
nand->blocks[i].is_bad = 0;
|
||||
}
|
||||
|
||||
page += pages_per_block;
|
||||
}
|
||||
|
@ -276,16 +270,12 @@ int nand_read_status(struct nand_device *nand, uint8_t *status)
|
|||
alive_sleep(1);
|
||||
|
||||
/* read status */
|
||||
if (nand->device->options & NAND_BUSWIDTH_16)
|
||||
{
|
||||
if (nand->device->options & NAND_BUSWIDTH_16) {
|
||||
uint16_t data;
|
||||
nand->controller->read_data(nand, &data);
|
||||
*status = data & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else
|
||||
nand->controller->read_data(nand, status);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -300,9 +290,8 @@ static int nand_poll_ready(struct nand_device *nand, int timeout)
|
|||
uint16_t data;
|
||||
nand->controller->read_data(nand, &data);
|
||||
status = data & 0xff;
|
||||
} else {
|
||||
} else
|
||||
nand->controller->read_data(nand, &status);
|
||||
}
|
||||
if (status & NAND_STATUS_READY)
|
||||
break;
|
||||
alive_sleep(1);
|
||||
|
@ -329,15 +318,15 @@ int nand_probe(struct nand_device *nand)
|
|||
nand->erase_size = 0;
|
||||
|
||||
/* 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:
|
||||
LOG_DEBUG("controller initialization failed");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
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;
|
||||
default:
|
||||
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->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, &device_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
uint16_t data_buf;
|
||||
nand->controller->read_data(nand, &data_buf);
|
||||
manufacturer_id = data_buf & 0xff;
|
||||
|
@ -365,36 +351,32 @@ int nand_probe(struct nand_device *nand)
|
|||
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 &&
|
||||
(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];
|
||||
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];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nand->manufacturer)
|
||||
{
|
||||
if (!nand->manufacturer) {
|
||||
nand->manufacturer = &nand_manuf_ids[0];
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -410,16 +392,12 @@ int nand_probe(struct nand_device *nand)
|
|||
|
||||
/* Do we need extended device probe information? */
|
||||
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 + 4);
|
||||
nand->controller->read_data(nand, id_buff + 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
uint16_t data_buf;
|
||||
|
||||
nand->controller->read_data(nand, &data_buf);
|
||||
|
@ -435,81 +413,68 @@ int nand_probe(struct nand_device *nand)
|
|||
|
||||
/* page size */
|
||||
if (nand->device->page_size == 0)
|
||||
{
|
||||
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");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else
|
||||
nand->page_size = nand->device->page_size;
|
||||
}
|
||||
|
||||
/* number of address cycles */
|
||||
if (nand->page_size <= 512)
|
||||
{
|
||||
if (nand->page_size <= 512) {
|
||||
/* small page devices */
|
||||
if (nand->device->chip_size <= 32)
|
||||
nand->address_cycles = 3;
|
||||
else if (nand->device->chip_size <= 8*1024)
|
||||
nand->address_cycles = 4;
|
||||
else
|
||||
{
|
||||
else {
|
||||
LOG_ERROR("BUG: small page NAND device with more than 8 GiB encountered");
|
||||
nand->address_cycles = 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* large page devices */
|
||||
if (nand->device->chip_size <= 128)
|
||||
nand->address_cycles = 4;
|
||||
else if (nand->device->chip_size <= 32*1024)
|
||||
nand->address_cycles = 5;
|
||||
else
|
||||
{
|
||||
else {
|
||||
LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered");
|
||||
nand->address_cycles = 6;
|
||||
}
|
||||
}
|
||||
|
||||
/* erase size */
|
||||
if (nand->device->erase_size == 0)
|
||||
{
|
||||
if (nand->device->erase_size == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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:
|
||||
LOG_DEBUG("controller initialization failed");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
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;
|
||||
default:
|
||||
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->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].offset = i * nand->erase_size;
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = first_block; i <= last_block; i++)
|
||||
{
|
||||
for (i = first_block; i <= last_block; i++) {
|
||||
/* Send erase setup command */
|
||||
nand->controller->command(nand, NAND_CMD_ERASE1);
|
||||
|
||||
page = i * (nand->erase_size / nand->page_size);
|
||||
|
||||
/* Send page address */
|
||||
if (nand->page_size <= 512)
|
||||
{
|
||||
if (nand->page_size <= 512) {
|
||||
/* row */
|
||||
nand->controller->address(nand, page & 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 */
|
||||
if (nand->address_cycles >= 5)
|
||||
nand->controller->address(nand, (page >> 24) & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* row */
|
||||
nand->controller->address(nand, page & 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);
|
||||
|
||||
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) {
|
||||
LOG_ERROR("timeout waiting for NAND flash block erase to complete");
|
||||
return ERROR_NAND_OPERATION_TIMEOUT;
|
||||
}
|
||||
|
||||
retval = nand_read_status(nand, &status);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("couldn't read status");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if (status & 0x1)
|
||||
{
|
||||
if (status & 0x1) {
|
||||
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 */
|
||||
}
|
||||
|
||||
|
@ -621,23 +577,24 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
|
|||
}
|
||||
|
||||
#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;
|
||||
|
||||
if (!nand->device)
|
||||
return ERROR_NAND_DEVICE_NOT_PROBED;
|
||||
|
||||
if (address % nand->page_size)
|
||||
{
|
||||
if (address % nand->page_size) {
|
||||
LOG_ERROR("reads need to be page aligned");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
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 page_address;
|
||||
|
||||
|
@ -658,23 +615,24 @@ static int nand_read_plain(struct nand_device *nand, uint32_t address, uint8_t *
|
|||
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;
|
||||
|
||||
if (!nand->device)
|
||||
return ERROR_NAND_DEVICE_NOT_PROBED;
|
||||
|
||||
if (address % nand->page_size)
|
||||
{
|
||||
if (address % nand->page_size) {
|
||||
LOG_ERROR("writes need to be page aligned");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
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 page_address;
|
||||
|
||||
|
@ -697,8 +655,8 @@ static int nand_write_plain(struct nand_device *nand, uint32_t address, uint8_t
|
|||
#endif
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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,
|
||||
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)
|
||||
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,
|
||||
uint8_t cmd, bool oob_only)
|
||||
uint8_t cmd, bool oob_only)
|
||||
{
|
||||
if (!nand->device)
|
||||
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,
|
||||
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;
|
||||
|
||||
|
@ -870,8 +828,8 @@ int nand_write_finish(struct nand_device *nand)
|
|||
nand->controller->command(nand, NAND_CMD_PAGEPROG);
|
||||
|
||||
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)
|
||||
return ERROR_NAND_OPERATION_TIMEOUT;
|
||||
|
||||
|
@ -883,7 +841,7 @@ int nand_write_finish(struct nand_device *nand)
|
|||
|
||||
if (status & NAND_STATUS_FAIL) {
|
||||
LOG_ERROR("write operation didn't pass, status: 0x%2.2x",
|
||||
status);
|
||||
status);
|
||||
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,
|
||||
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;
|
||||
|
||||
|
@ -918,4 +876,3 @@ int nand_write_page_raw(struct nand_device *nand, uint32_t page,
|
|||
|
||||
return nand_write_finish(nand);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef FLASH_NAND_CORE_H
|
||||
#define FLASH_NAND_CORE_H
|
||||
|
||||
|
@ -30,8 +31,7 @@
|
|||
/**
|
||||
* Representation of a single NAND block in a NAND device.
|
||||
*/
|
||||
struct nand_block
|
||||
{
|
||||
struct nand_block {
|
||||
/** Offset to the block. */
|
||||
uint32_t offset;
|
||||
|
||||
|
@ -57,8 +57,7 @@ struct nand_ecclayout {
|
|||
struct nand_oobfree oobfree[2];
|
||||
};
|
||||
|
||||
struct nand_device
|
||||
{
|
||||
struct nand_device {
|
||||
const char *name;
|
||||
struct target *target;
|
||||
struct nand_flash_controller *controller;
|
||||
|
@ -77,8 +76,7 @@ struct nand_device
|
|||
|
||||
/* NAND Flash Manufacturer ID Codes
|
||||
*/
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
NAND_MFR_TOSHIBA = 0x98,
|
||||
NAND_MFR_SAMSUNG = 0xec,
|
||||
NAND_MFR_FUJITSU = 0x04,
|
||||
|
@ -89,14 +87,12 @@ enum
|
|||
NAND_MFR_MICRON = 0x2c,
|
||||
};
|
||||
|
||||
struct nand_manufacturer
|
||||
{
|
||||
struct nand_manufacturer {
|
||||
int id;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct nand_info
|
||||
{
|
||||
struct nand_info {
|
||||
int mfr_id;
|
||||
int id;
|
||||
int page_size;
|
||||
|
@ -152,8 +148,7 @@ enum {
|
|||
LP_OPTIONS16 = (LP_OPTIONS | NAND_BUSWIDTH_16),
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
/* Standard NAND flash commands */
|
||||
NAND_CMD_READ0 = 0x0,
|
||||
NAND_CMD_READ1 = 0x1,
|
||||
|
@ -161,7 +156,7 @@ enum
|
|||
NAND_CMD_PAGEPROG = 0x10,
|
||||
NAND_CMD_READOOB = 0x50,
|
||||
NAND_CMD_ERASE1 = 0x60,
|
||||
NAND_CMD_STATUS = 0x70,
|
||||
NAND_CMD_STATUS = 0x70,
|
||||
NAND_CMD_STATUS_MULTI = 0x71,
|
||||
NAND_CMD_SEQIN = 0x80,
|
||||
NAND_CMD_RNDIN = 0x85,
|
||||
|
@ -176,8 +171,7 @@ enum
|
|||
};
|
||||
|
||||
/* Status bits */
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
NAND_STATUS_FAIL = 0x01,
|
||||
NAND_STATUS_FAIL_N1 = 0x02,
|
||||
NAND_STATUS_TRUE_READY = 0x20,
|
||||
|
@ -186,14 +180,14 @@ enum
|
|||
};
|
||||
|
||||
/* OOB (spare) data formats */
|
||||
enum oob_formats
|
||||
{
|
||||
enum oob_formats {
|
||||
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_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_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);
|
||||
|
||||
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_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_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,
|
||||
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_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,
|
||||
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);
|
||||
|
||||
/// 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,
|
||||
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 {
|
||||
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 */
|
||||
uint32_t aemif;
|
||||
uint32_t aemif;
|
||||
|
||||
/* 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 */
|
||||
struct arm_nand_data io;
|
||||
struct arm_nand_data io;
|
||||
|
||||
/* page i/o for the relevant flavor of hardware ECC */
|
||||
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,
|
||||
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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
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 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,
|
||||
uint8_t *data, int data_size)
|
||||
uint8_t *data, int data_size)
|
||||
{
|
||||
struct davinci_nand *info = nand->controller_priv;
|
||||
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,
|
||||
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;
|
||||
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. */
|
||||
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) {
|
||||
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,
|
||||
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;
|
||||
|
||||
|
@ -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,
|
||||
uint8_t *oob, uint32_t oob_size)
|
||||
uint8_t *oob, uint32_t oob_size)
|
||||
{
|
||||
struct davinci_nand *info = nand->controller_priv;
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
|
@ -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.
|
||||
*/
|
||||
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[] = {
|
||||
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,
|
||||
};
|
||||
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,
|
||||
};
|
||||
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,
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
|
@ -533,11 +533,11 @@ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
|
|||
raw_ecc[i] &= 0x03ff03ff;
|
||||
}
|
||||
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] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
|
||||
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);
|
||||
|
@ -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.
|
||||
*/
|
||||
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 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 */
|
||||
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] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
|
||||
*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 */
|
||||
|
@ -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,
|
||||
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 want_col, at_col;
|
||||
|
@ -688,9 +688,8 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
|
|||
* - aemif address
|
||||
* Plus someday, optionally, ALE and CLE masks.
|
||||
*/
|
||||
if (CMD_ARGC < 5) {
|
||||
if (CMD_ARGC < 5)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
|
||||
if (chip == 0) {
|
||||
|
@ -720,9 +719,9 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
|
|||
* AEMIF controller address.
|
||||
*/
|
||||
if (aemif == 0x01e00000 /* dm6446, dm357 */
|
||||
|| aemif == 0x01e10000 /* dm335, dm355 */
|
||||
|| aemif == 0x01d10000 /* dm365 */
|
||||
) {
|
||||
|| aemif == 0x01e10000 /* dm335, dm355 */
|
||||
|| aemif == 0x01d10000 /* dm365 */
|
||||
) {
|
||||
if (chip < 0x02000000 || chip >= 0x0a000000) {
|
||||
LOG_ERROR("NAND address %08lx out of range?", chip);
|
||||
goto fail;
|
||||
|
@ -757,19 +756,19 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
|
|||
info->read_page = nand_read_page_raw;
|
||||
|
||||
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;
|
||||
|
@ -779,18 +778,18 @@ fail:
|
|||
}
|
||||
|
||||
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; */
|
||||
|
||||
static struct nand_flash_controller *nand_flash_controllers[] =
|
||||
{
|
||||
static struct nand_flash_controller *nand_flash_controllers[] = {
|
||||
&nonce_nand_controller,
|
||||
&davinci_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)
|
||||
{
|
||||
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];
|
||||
if (strcmp(name, controller->name) == 0)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,28 +19,28 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef FLASH_NAND_DRIVER_H
|
||||
#define FLASH_NAND_DRIVER_H
|
||||
|
||||
struct nand_device;
|
||||
|
||||
#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
|
||||
* required for full functionality of the NAND driver, but better performance
|
||||
* 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. */
|
||||
const char *name;
|
||||
|
||||
/** Usage of flash command registration. */
|
||||
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((*nand_device_command));
|
||||
|
@ -70,10 +70,12 @@ struct nand_flash_controller
|
|||
int (*read_block_data)(struct nand_device *nand, uint8_t *data, int size);
|
||||
|
||||
/** 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. */
|
||||
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. */
|
||||
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);
|
||||
|
||||
/// 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.
|
||||
* 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);
|
||||
|
||||
#endif // FLASH_NAND_DRIVER_H
|
||||
#endif /* FLASH_NAND_DRIVER_H */
|
||||
|
|
|
@ -125,7 +125,7 @@ static inline int countbits(uint32_t b)
|
|||
{
|
||||
int res = 0;
|
||||
|
||||
for (;b; b >>= 1)
|
||||
for (; b; b >>= 1)
|
||||
res += b & 0x01;
|
||||
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
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -151,9 +151,9 @@ int nand_correct_data(struct nand_device *nand, u_char *dat,
|
|||
return 0;
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@ -176,7 +176,7 @@ int nand_correct_data(struct nand_device *nand, u_char *dat,
|
|||
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;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* For multiplication, a discrete log/exponent table is used, with
|
||||
* 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
|
||||
|
@ -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;
|
||||
int i;
|
||||
static int tables_initialized = 0;
|
||||
static int tables_initialized;
|
||||
|
||||
if (!tables_initialized) {
|
||||
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];
|
||||
r7 = data[511];
|
||||
|
||||
|
||||
/*
|
||||
* Shift bytes 503..0 (in that order) into r0, followed
|
||||
* by eight zero bytes, while reducing the polynomial by the
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
@ -32,18 +33,21 @@ static struct nand_ecclayout nand_oob_16 = {
|
|||
.eccpos = {0, 1, 2, 3, 6, 7},
|
||||
.oobfree = {
|
||||
{.offset = 8,
|
||||
. length = 8}}
|
||||
.length = 8}
|
||||
}
|
||||
};
|
||||
|
||||
static struct nand_ecclayout nand_oob_64 = {
|
||||
.eccbytes = 24,
|
||||
.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 = {
|
||||
{.offset = 2,
|
||||
.length = 38}}
|
||||
.length = 38}
|
||||
}
|
||||
};
|
||||
|
||||
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,
|
||||
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");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
duration_start(&state->bench);
|
||||
|
||||
if (NULL != filename)
|
||||
{
|
||||
if (NULL != filename) {
|
||||
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";
|
||||
command_print(cmd_ctx, "failed to open '%s' for %s access",
|
||||
filename, msg);
|
||||
filename, msg);
|
||||
return retval;
|
||||
}
|
||||
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 = 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->eccpos = nand_oob_16.eccpos;
|
||||
}
|
||||
else if (nand->page_size == 2048)
|
||||
{
|
||||
} else if (nand->page_size == 2048) {
|
||||
state->oob_size = 64;
|
||||
state->eccpos = nand_oob_64.eccpos;
|
||||
}
|
||||
|
@ -105,13 +101,11 @@ int nand_fileio_cleanup(struct nand_fileio_state *state)
|
|||
if (state->file_opened)
|
||||
fileio_close(&state->fileio);
|
||||
|
||||
if (state->oob)
|
||||
{
|
||||
if (state->oob) {
|
||||
free(state->oob);
|
||||
state->oob = NULL;
|
||||
}
|
||||
if (state->page)
|
||||
{
|
||||
if (state->page) {
|
||||
free(state->page);
|
||||
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,
|
||||
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);
|
||||
|
||||
|
@ -138,27 +132,22 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
|
|||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
if (NULL == nand->device)
|
||||
{
|
||||
if (NULL == nand->device) {
|
||||
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
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"))
|
||||
state->oob_format |= NAND_OOB_RAW;
|
||||
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;
|
||||
else if (sw_ecc && !strcmp(CMD_ARGV[i], "oob_softecc_kw"))
|
||||
state->oob_format |= NAND_OOB_SW_ECC_KW;
|
||||
else
|
||||
{
|
||||
else {
|
||||
command_print(CMD_CTX, "unknown option: %s", CMD_ARGV[i]);
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
@ -179,8 +167,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
|
|||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
if (!need_size)
|
||||
{
|
||||
if (!need_size) {
|
||||
int filesize;
|
||||
retval = fileio_size(&state->fileio, &filesize);
|
||||
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 one_read;
|
||||
|
||||
if (NULL != s->page)
|
||||
{
|
||||
if (NULL != s->page) {
|
||||
fileio_read(&s->fileio, s->page_size, s->page, &one_read);
|
||||
if (one_read < s->page_size)
|
||||
memset(s->page + one_read, 0xff, s->page_size - 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];
|
||||
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);
|
||||
s->oob[s->eccpos[j++]] = ecc[0];
|
||||
s->oob[s->eccpos[j++]] = ecc[1];
|
||||
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
|
||||
* 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;
|
||||
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);
|
||||
ecc += 10;
|
||||
}
|
||||
}
|
||||
else if (NULL != s->oob)
|
||||
{
|
||||
} else if (NULL != s->oob) {
|
||||
fileio_read(&s->fileio, s->oob_size, s->oob, &one_read);
|
||||
if (one_read < s->oob_size)
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef 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);
|
||||
|
||||
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);
|
||||
|
||||
#endif // FLASH_NAND_FILEIO_H
|
||||
#endif /* FLASH_NAND_FILEIO_H */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef 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_build_bbt(struct nand_device *nand, int first, int last);
|
||||
|
||||
#endif // FLASH_NAND_IMP_H
|
||||
#endif /* FLASH_NAND_IMP_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,18 +17,17 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef LPC3180_NAND_CONTROLLER_H
|
||||
#define LPC3180_NAND_CONTROLLER_H
|
||||
|
||||
enum lpc3180_selected_controller
|
||||
{
|
||||
enum lpc3180_selected_controller {
|
||||
LPC3180_NO_CONTROLLER,
|
||||
LPC3180_MLC_CONTROLLER,
|
||||
LPC3180_SLC_CONTROLLER,
|
||||
};
|
||||
|
||||
struct lpc3180_nand_controller
|
||||
{
|
||||
struct lpc3180_nand_controller {
|
||||
int osc_freq;
|
||||
enum lpc3180_selected_controller selected_controller;
|
||||
int is_bulk;
|
||||
|
@ -37,4 +36,4 @@ struct lpc3180_nand_controller
|
|||
uint32_t sw_wp_upper_bound;
|
||||
};
|
||||
|
||||
#endif /*LPC3180_NAND_CONTROLLER_H */
|
||||
#endif /*LPC3180_NAND_CONTROLLER_H */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
@ -37,7 +38,7 @@ static int lpc32xx_reset(struct nand_device *nand);
|
|||
static int lpc32xx_controller_ready(struct nand_device *nand, int timeout);
|
||||
static int lpc32xx_tc_ready(struct nand_device *nand, int timeout);
|
||||
extern int nand_correct_data(struct nand_device *nand, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc);
|
||||
u_char *read_ecc, u_char *calc_ecc);
|
||||
|
||||
/* These are offset with the working area in IRAM when using DMA to
|
||||
* read/write data to the SLC controller.
|
||||
|
@ -74,9 +75,8 @@ static dmac_ll_t dmalist[(2048/256) * 2 + 1];
|
|||
*/
|
||||
NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command)
|
||||
{
|
||||
if (CMD_ARGC < 3) {
|
||||
if (CMD_ARGC < 3)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
uint32_t osc_freq;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
|
||||
|
@ -89,8 +89,8 @@ NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command)
|
|||
|
||||
if ((lpc32xx_info->osc_freq < 1000) || (lpc32xx_info->osc_freq > 20000))
|
||||
LOG_WARNING("LPC32xx oscillator frequency should be between "
|
||||
"1000 and 20000 kHz, was %i",
|
||||
lpc32xx_info->osc_freq);
|
||||
"1000 and 20000 kHz, was %i",
|
||||
lpc32xx_info->osc_freq);
|
||||
|
||||
lpc32xx_info->selected_controller = LPC32xx_NO_CONTROLLER;
|
||||
lpc32xx_info->sw_write_protection = 0;
|
||||
|
@ -113,18 +113,18 @@ static int lpc32xx_pll(int fclkin, uint32_t pll_ctrl)
|
|||
if (!lock)
|
||||
LOG_WARNING("PLL is not locked");
|
||||
|
||||
if (!bypass && direct) /* direct mode */
|
||||
if (!bypass && direct) /* direct mode */
|
||||
return (m * fclkin) / n;
|
||||
|
||||
if (bypass && !direct) /* bypass mode */
|
||||
if (bypass && !direct) /* bypass mode */
|
||||
return fclkin / (2 * p);
|
||||
|
||||
if (bypass & direct) /* direct bypass mode */
|
||||
if (bypass & direct) /* direct bypass mode */
|
||||
return fclkin;
|
||||
|
||||
if (feedback) /* integer mode */
|
||||
if (feedback) /* integer mode */
|
||||
return m * (fclkin / n);
|
||||
else /* non-integer mode */
|
||||
else /* non-integer mode */
|
||||
return (m / (2 * p)) * (fclkin / n);
|
||||
}
|
||||
|
||||
|
@ -160,9 +160,9 @@ static float lpc32xx_cycle_time(struct nand_device *nand)
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if ((pwr_ctrl & (1 << 2)) == 0) { /* DIRECT RUN mode */
|
||||
if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
|
||||
hclk = sysclk;
|
||||
} else {
|
||||
else {
|
||||
retval = target_read_u32(target, 0x40004058, &hclkpll_ctrl);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not read HCLKPLL_CTRL");
|
||||
|
@ -176,9 +176,9 @@ static float lpc32xx_cycle_time(struct nand_device *nand)
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
|
||||
if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
|
||||
hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1);
|
||||
else /* HCLK uses HCLK_PLL */
|
||||
else /* HCLK uses HCLK_PLL */
|
||||
hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3));
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ static int lpc32xx_init(struct nand_device *nand)
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use LPC32xx "
|
||||
"NAND flash controller");
|
||||
"NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ static int lpc32xx_init(struct nand_device *nand)
|
|||
/* select MLC controller if none is currently selected */
|
||||
if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
|
||||
LOG_DEBUG("no LPC32xx NAND flash controller selected, "
|
||||
"using default 'slc'");
|
||||
"using default 'slc'");
|
||||
lpc32xx_info->selected_controller = LPC32xx_SLC_CONTROLLER;
|
||||
}
|
||||
|
||||
|
@ -291,13 +291,13 @@ static int lpc32xx_init(struct nand_device *nand)
|
|||
|
||||
/* MLC_TIME_REG */
|
||||
retval = target_write_u32(target, 0x200b8034,
|
||||
(twp & 0xf)
|
||||
| ((twh & 0xf) << 4)
|
||||
| ((trp & 0xf) << 8)
|
||||
| ((treh & 0xf) << 12)
|
||||
| ((trhz & 0x7) << 16)
|
||||
| ((trbwb & 0x1f) << 19)
|
||||
| ((tcea & 0x3) << 24));
|
||||
(twp & 0xf)
|
||||
| ((twh & 0xf) << 4)
|
||||
| ((trp & 0xf) << 8)
|
||||
| ((treh & 0xf) << 12)
|
||||
| ((trhz & 0x7) << 16)
|
||||
| ((trbwb & 0x1f) << 19)
|
||||
| ((tcea & 0x3) << 24));
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_TIME_REG");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -334,7 +334,7 @@ static int lpc32xx_init(struct nand_device *nand)
|
|||
WIDTH = bus_width)
|
||||
*/
|
||||
retval = target_write_u32(target, 0x20020014,
|
||||
0x3e | (bus_width == 16) ? 1 : 0);
|
||||
0x3e | (bus_width == 16) ? 1 : 0);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set SLC_CFG");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -374,14 +374,14 @@ static int lpc32xx_init(struct nand_device *nand)
|
|||
|
||||
/* SLC_TAC: SLC timing arcs register */
|
||||
retval = target_write_u32(target, 0x2002002c,
|
||||
(r_setup & 0xf)
|
||||
| ((r_hold & 0xf) << 4)
|
||||
| ((r_width & 0xf) << 8)
|
||||
| ((r_rdy & 0xf) << 12)
|
||||
| ((w_setup & 0xf) << 16)
|
||||
| ((w_hold & 0xf) << 20)
|
||||
| ((w_width & 0xf) << 24)
|
||||
| ((w_rdy & 0xf) << 28));
|
||||
(r_setup & 0xf)
|
||||
| ((r_hold & 0xf) << 4)
|
||||
| ((r_width & 0xf) << 8)
|
||||
| ((r_rdy & 0xf) << 12)
|
||||
| ((w_setup & 0xf) << 16)
|
||||
| ((w_hold & 0xf) << 20)
|
||||
| ((w_width & 0xf) << 24)
|
||||
| ((w_rdy & 0xf) << 28));
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set SLC_TAC");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -399,7 +399,7 @@ static int lpc32xx_reset(struct nand_device *nand)
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use "
|
||||
"LPC32xx NAND flash controller");
|
||||
"LPC32xx NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -416,7 +416,7 @@ static int lpc32xx_reset(struct nand_device *nand)
|
|||
|
||||
if (!lpc32xx_controller_ready(nand, 100)) {
|
||||
LOG_ERROR("LPC32xx MLC NAND controller timed out "
|
||||
"after reset");
|
||||
"after reset");
|
||||
return ERROR_NAND_OPERATION_TIMEOUT;
|
||||
}
|
||||
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
|
||||
|
@ -427,10 +427,9 @@ static int lpc32xx_reset(struct nand_device *nand)
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if (!lpc32xx_controller_ready(nand, 100))
|
||||
{
|
||||
if (!lpc32xx_controller_ready(nand, 100)) {
|
||||
LOG_ERROR("LPC32xx SLC NAND controller timed out "
|
||||
"after reset");
|
||||
"after reset");
|
||||
return ERROR_NAND_OPERATION_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +445,7 @@ static int lpc32xx_command(struct nand_device *nand, uint8_t command)
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use "
|
||||
"LPC32xx NAND flash controller");
|
||||
"LPC32xx NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -480,7 +479,7 @@ static int lpc32xx_address(struct nand_device *nand, uint8_t address)
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use "
|
||||
"LPC32xx NAND flash controller");
|
||||
"LPC32xx NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -514,7 +513,7 @@ static int lpc32xx_write_data(struct nand_device *nand, uint16_t data)
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use "
|
||||
"LPC32xx NAND flash controller");
|
||||
"LPC32xx NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -548,7 +547,7 @@ static int lpc32xx_read_data(struct nand_device *nand, void *data)
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use LPC32xx "
|
||||
"NAND flash controller");
|
||||
"NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -591,8 +590,8 @@ static int lpc32xx_read_data(struct nand_device *nand, void *data)
|
|||
}
|
||||
|
||||
static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
|
||||
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 target *target = nand->target;
|
||||
int retval;
|
||||
|
@ -623,7 +622,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
retval = target_write_u32(target, 0x200b8004,
|
||||
(page >> 8) & 0xff);
|
||||
(page >> 8) & 0xff);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_ADDR");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -631,7 +630,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
|
||||
if (nand->address_cycles == 4) {
|
||||
retval = target_write_u32(target, 0x200b8004,
|
||||
(page >> 16) & 0xff);
|
||||
(page >> 16) & 0xff);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_ADDR");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -657,7 +656,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
retval = target_write_u32(target, 0x200b8004,
|
||||
(page >> 8) & 0xff);
|
||||
(page >> 8) & 0xff);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_ADDR");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -717,7 +716,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
|
||||
if (!lpc32xx_controller_ready(nand, 1000)) {
|
||||
LOG_ERROR("timeout while waiting for "
|
||||
"completion of auto encode cycle");
|
||||
"completion of auto encode cycle");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
}
|
||||
|
@ -729,14 +728,15 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if ((retval = nand_read_status(nand, &status)) != ERROR_OK) {
|
||||
retval = nand_read_status(nand, &status);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("couldn't read status");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if (status & NAND_STATUS_FAIL) {
|
||||
LOG_ERROR("write operation didn't pass, status: 0x%2.2x",
|
||||
status);
|
||||
status);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -749,7 +749,7 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
* target.
|
||||
*/
|
||||
static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
|
||||
int do_read)
|
||||
int do_read)
|
||||
{
|
||||
uint32_t i, dmasrc, ctrl, ecc_ctrl, oob_ctrl, dmadst;
|
||||
|
||||
|
@ -794,7 +794,7 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
|
|||
*/
|
||||
|
||||
ctrl = (0x40 | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
|
||||
| 0 << 25 | 0 << 26 | 0 << 27 | 0 << 31);
|
||||
| 0 << 25 | 0 << 26 | 0 << 27 | 0 << 31);
|
||||
|
||||
/* DMACCxControl =
|
||||
TransferSize =1,
|
||||
|
@ -809,7 +809,7 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
|
|||
Terminal count interrupt enable bit = 0
|
||||
*/
|
||||
ecc_ctrl = 0x01 | 1 << 12 | 1 << 15 | 2 << 18 | 2 << 21 | 0 << 24
|
||||
| 0 << 25 | 0 << 26 | 1 << 27 | 0 << 31;
|
||||
| 0 << 25 | 0 << 26 | 1 << 27 | 0 << 31;
|
||||
|
||||
/* DMACCxControl =
|
||||
TransferSize =16 for lp or 4 for sp,
|
||||
|
@ -824,18 +824,18 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
|
|||
Terminal count interrupt enable bit = 1 // set on last
|
||||
*/
|
||||
oob_ctrl = (page_size == 2048 ? 0x10 : 0x04)
|
||||
| 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
|
||||
| 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31;
|
||||
| 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
|
||||
| 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31;
|
||||
if (do_read) {
|
||||
ctrl |= 1 << 27; /* Destination increment = 1 */
|
||||
oob_ctrl |= 1 << 27; /* Destination increment = 1 */
|
||||
dmasrc = 0x20020038; /* SLC_DMA_DATA */
|
||||
ctrl |= 1 << 27;/* Destination increment = 1 */
|
||||
oob_ctrl |= 1 << 27; /* Destination increment = 1 */
|
||||
dmasrc = 0x20020038; /* SLC_DMA_DATA */
|
||||
dmadst = target_mem_base + DATA_OFFS;
|
||||
} else {
|
||||
ctrl |= 1 << 26; /* Source increment = 1 */
|
||||
oob_ctrl |= 1 << 26; /* Source increment = 1 */
|
||||
ctrl |= 1 << 26;/* Source increment = 1 */
|
||||
oob_ctrl |= 1 << 26; /* Source increment = 1 */
|
||||
dmasrc = target_mem_base + DATA_OFFS;
|
||||
dmadst = 0x20020038; /* SLC_DMA_DATA */
|
||||
dmadst = 0x20020038; /* SLC_DMA_DATA */
|
||||
}
|
||||
/*
|
||||
* Write Operation Sequence for Small Block NAND
|
||||
|
@ -865,40 +865,38 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
|
|||
* data & 32 bytes of ECC data.
|
||||
* 2. X'fer 64 bytes of Spare area from Flash to Memory.
|
||||
*/
|
||||
for (i = 0; i < page_size/0x100; i++)
|
||||
{
|
||||
for (i = 0; i < page_size/0x100; i++) {
|
||||
dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256));
|
||||
dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst);
|
||||
dmalist[i*2].next_lli =
|
||||
target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t);
|
||||
dmalist[i*2].next_ctrl = ctrl;
|
||||
|
||||
dmalist[(i*2) + 1].dma_src = 0x20020034; /* SLC_ECC */
|
||||
dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */
|
||||
dmalist[(i*2) + 1].dma_dest =
|
||||
target_mem_base + ECC_OFFS + i * 4;
|
||||
dmalist[(i*2) + 1].next_lli =
|
||||
target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t);
|
||||
target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t);
|
||||
dmalist[(i*2) + 1].next_ctrl = ecc_ctrl;
|
||||
|
||||
}
|
||||
if (do_read)
|
||||
{
|
||||
dmadst = target_mem_base + SPARE_OFFS;
|
||||
} else {
|
||||
else {
|
||||
dmasrc = target_mem_base + SPARE_OFFS;
|
||||
dmalist[(i*2) - 1].next_lli = 0; /* last link = null on write */
|
||||
dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */
|
||||
dmalist[(i*2) - 1].next_lli = 0;/* last link = null on write */
|
||||
dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */
|
||||
}
|
||||
dmalist[i*2].dma_src = dmasrc;
|
||||
dmalist[i*2].dma_dest = dmadst;
|
||||
dmalist[i*2].next_lli = 0;
|
||||
dmalist[i*2].next_ctrl = oob_ctrl;
|
||||
|
||||
return (i*2 + 1); /* Number of descriptors */
|
||||
return i * 2 + 1; /* Number of descriptors */
|
||||
}
|
||||
|
||||
static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count,
|
||||
int do_wait)
|
||||
int do_wait)
|
||||
{
|
||||
struct target *target = nand->target;
|
||||
int retval;
|
||||
|
@ -928,8 +926,8 @@ static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count,
|
|||
H=0
|
||||
*/
|
||||
retval = target_write_u32(target, 0x31000110,
|
||||
1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
|
||||
| 0<<15 | 0<<16 | 0<<18);
|
||||
1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
|
||||
| 0<<15 | 0<<16 | 0<<18);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not set DMACC0Config");
|
||||
return retval;
|
||||
|
@ -990,14 +988,13 @@ static int lpc32xx_dma_ready(struct nand_device *nand, int timeout)
|
|||
}
|
||||
if ((tc_stat | err_stat) & 1) {
|
||||
LOG_DEBUG("lpc32xx_dma_ready count=%d",
|
||||
timeout);
|
||||
timeout);
|
||||
if (err_stat & 1) {
|
||||
LOG_ERROR("lpc32xx_dma_ready "
|
||||
"DMA error, aborted");
|
||||
"DMA error, aborted");
|
||||
return 0;
|
||||
} else {
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
alive_sleep(1);
|
||||
|
@ -1006,8 +1003,8 @@ static int lpc32xx_dma_ready(struct nand_device *nand, int timeout)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t slc_ecc_copy_to_buffer(uint8_t * spare,
|
||||
const uint32_t * ecc, int count)
|
||||
static uint32_t slc_ecc_copy_to_buffer(uint8_t *spare,
|
||||
const uint32_t *ecc, int count)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (count * 3); i += 3) {
|
||||
|
@ -1025,8 +1022,8 @@ static void lpc32xx_dump_oob(uint8_t *oob, uint32_t oob_size)
|
|||
int addr = 0;
|
||||
while (oob_size > 0) {
|
||||
LOG_DEBUG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", addr,
|
||||
oob[0], oob[1], oob[2], oob[3],
|
||||
oob[4], oob[5], oob[6], oob[7]);
|
||||
oob[0], oob[1], oob[2], oob[3],
|
||||
oob[4], oob[5], oob[6], oob[7]);
|
||||
oob += 8;
|
||||
addr += 8;
|
||||
oob_size -= 8;
|
||||
|
@ -1034,18 +1031,18 @@ static void lpc32xx_dump_oob(uint8_t *oob, uint32_t oob_size)
|
|||
}
|
||||
|
||||
static int lpc32xx_write_page_slc(struct nand_device *nand,
|
||||
struct working_area *pworking_area,
|
||||
uint32_t page, uint8_t *data,
|
||||
uint32_t data_size, uint8_t *oob,
|
||||
uint32_t oob_size)
|
||||
struct working_area *pworking_area,
|
||||
uint32_t page, uint8_t *data,
|
||||
uint32_t data_size, uint8_t *oob,
|
||||
uint32_t oob_size)
|
||||
{
|
||||
struct target *target = nand->target;
|
||||
int retval;
|
||||
uint32_t target_mem_base;
|
||||
|
||||
LOG_DEBUG("SLC write page %x data=%d, oob=%d, "
|
||||
"data_size=%d, oob_size=%d",
|
||||
page, data != 0, oob != 0, data_size, oob_size);
|
||||
"data_size=%d, oob_size=%d",
|
||||
page, data != 0, oob != 0, data_size, oob_size);
|
||||
|
||||
target_mem_base = pworking_area->address;
|
||||
/*
|
||||
|
@ -1060,7 +1057,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
break;
|
||||
}
|
||||
if (all_ff)
|
||||
return ERROR_OK;
|
||||
return ERROR_OK;
|
||||
}
|
||||
/* Make the dma descriptors in local memory */
|
||||
int nll = lpc32xx_make_dma_list(target_mem_base, nand->page_size, 0);
|
||||
|
@ -1068,8 +1065,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
XXX: Assumes host and target have same byte sex.
|
||||
*/
|
||||
retval = target_write_memory(target, target_mem_base, 4,
|
||||
nll * sizeof(dmac_ll_t) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
nll * sizeof(dmac_ll_t) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write DMA descriptors to IRAM");
|
||||
return retval;
|
||||
|
@ -1081,13 +1078,13 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* SLC_CFG =
|
||||
Force nCE assert,
|
||||
DMA ECC enabled,
|
||||
ECC enabled,
|
||||
DMA burst enabled,
|
||||
DMA write to SLC,
|
||||
WIDTH = bus_width
|
||||
/* SLC_CFG =
|
||||
Force nCE assert,
|
||||
DMA ECC enabled,
|
||||
ECC enabled,
|
||||
DMA burst enabled,
|
||||
DMA write to SLC,
|
||||
WIDTH = bus_width
|
||||
*/
|
||||
retval = target_write_u32(target, 0x20020014, 0x3c);
|
||||
if (ERROR_OK != retval) {
|
||||
|
@ -1100,8 +1097,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
memset(fdata, 0xFF, nand->page_size);
|
||||
memcpy(fdata, data, data_size);
|
||||
retval = target_write_memory(target,
|
||||
target_mem_base + DATA_OFFS,
|
||||
4, nand->page_size/4, fdata);
|
||||
target_mem_base + DATA_OFFS,
|
||||
4, nand->page_size/4, fdata);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write data to IRAM");
|
||||
return retval;
|
||||
|
@ -1109,8 +1106,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
|
||||
/* Write first decriptor to DMA controller */
|
||||
retval = target_write_memory(target, 0x31000100, 4,
|
||||
sizeof(dmac_ll_t) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
sizeof(dmac_ll_t) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write DMA descriptor to DMAC");
|
||||
return retval;
|
||||
|
@ -1130,20 +1127,20 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
LOG_ERROR("Data DMA failed during write");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
} /* data xfer */
|
||||
} /* data xfer */
|
||||
|
||||
/* Copy OOB to iram */
|
||||
static uint8_t foob[64];
|
||||
int foob_size = nand->page_size == 2048 ? 64 : 16;
|
||||
memset(foob, 0xFF, foob_size);
|
||||
if (oob) { /* Raw mode */
|
||||
if (oob) /* Raw mode */
|
||||
memcpy(foob, oob, oob_size);
|
||||
} else {
|
||||
else {
|
||||
/* Get HW generated ECC, made while writing data */
|
||||
int ecc_count = nand->page_size == 2048 ? 8 : 2;
|
||||
static uint32_t hw_ecc[8];
|
||||
retval = target_read_memory(target, target_mem_base + ECC_OFFS,
|
||||
4, ecc_count, (uint8_t *)hw_ecc);
|
||||
4, ecc_count, (uint8_t *)hw_ecc);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Reading hw generated ECC from IRAM failed");
|
||||
return retval;
|
||||
|
@ -1158,7 +1155,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
lpc32xx_dump_oob(foob, foob_size);
|
||||
}
|
||||
retval = target_write_memory(target, target_mem_base + SPARE_OFFS, 4,
|
||||
foob_size / 4, foob);
|
||||
foob_size / 4, foob);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Writing OOB to IRAM failed");
|
||||
return retval;
|
||||
|
@ -1166,8 +1163,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
|
||||
/* Write OOB decriptor to DMA controller */
|
||||
retval = target_write_memory(target, 0x31000100, 4,
|
||||
sizeof(dmac_ll_t) / 4,
|
||||
(uint8_t *)(&dmalist[nll-1]));
|
||||
sizeof(dmac_ll_t) / 4,
|
||||
(uint8_t *)(&dmalist[nll-1]));
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write OOB DMA descriptor to DMAC");
|
||||
return retval;
|
||||
|
@ -1183,18 +1180,18 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
return retval;
|
||||
}
|
||||
/* DMACCxConfig=
|
||||
E=1,
|
||||
SrcPeripheral = 1 (SLC),
|
||||
DestPeripheral = 1 (SLC),
|
||||
FlowCntrl = 2 (Pher -> Mem, DMA),
|
||||
IE = 0,
|
||||
ITC = 0,
|
||||
L= 0,
|
||||
H=0
|
||||
* E=1,
|
||||
* SrcPeripheral = 1 (SLC),
|
||||
* DestPeripheral = 1 (SLC),
|
||||
* FlowCntrl = 2 (Pher -> Mem, DMA),
|
||||
* IE = 0,
|
||||
* ITC = 0,
|
||||
* L= 0,
|
||||
* H=0
|
||||
*/
|
||||
retval = target_write_u32(target, 0x31000110,
|
||||
1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
|
||||
| 0<<15 | 0<<16 | 0<<18);
|
||||
1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
|
||||
| 0<<15 | 0<<16 | 0<<18);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not set DMACC0Config");
|
||||
return retval;
|
||||
|
@ -1202,7 +1199,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
/* Wait finish */
|
||||
if (!lpc32xx_tc_ready(nand, 100)) {
|
||||
LOG_ERROR("timeout while waiting for "
|
||||
"completion of DMA");
|
||||
"completion of DMA");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
} else {
|
||||
|
@ -1225,8 +1222,8 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
}
|
||||
|
||||
static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
|
||||
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 lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
|
||||
struct target *target = nand->target;
|
||||
|
@ -1234,7 +1231,7 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use LPC32xx "
|
||||
"NAND flash controller");
|
||||
"NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1244,13 +1241,13 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
|
|||
} else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
|
||||
if (!data && oob) {
|
||||
LOG_ERROR("LPC32xx MLC controller can't write "
|
||||
"OOB data only");
|
||||
"OOB data only");
|
||||
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (oob && (oob_size > 24)) {
|
||||
LOG_ERROR("LPC32xx MLC controller can't write more "
|
||||
"than 6 bytes for each quarter's OOB data");
|
||||
"than 6 bytes for each quarter's OOB data");
|
||||
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -1260,7 +1257,7 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
|
|||
}
|
||||
|
||||
retval = lpc32xx_write_page_mlc(nand, page, data, data_size,
|
||||
oob, oob_size);
|
||||
oob, oob_size);
|
||||
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
|
||||
struct working_area *pworking_area;
|
||||
if (!data && oob) {
|
||||
|
@ -1270,18 +1267,18 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
|
|||
* Anyway the code supports the oob only mode below.
|
||||
*/
|
||||
return nand_write_page_raw(nand, page, data,
|
||||
data_size, oob, oob_size);
|
||||
data_size, oob, oob_size);
|
||||
}
|
||||
retval = target_alloc_working_area(target,
|
||||
nand->page_size + DATA_OFFS,
|
||||
&pworking_area);
|
||||
nand->page_size + DATA_OFFS,
|
||||
&pworking_area);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("Can't allocate working area in "
|
||||
"LPC internal RAM");
|
||||
"LPC internal RAM");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
retval = lpc32xx_write_page_slc(nand, pworking_area, page,
|
||||
data, data_size, oob, oob_size);
|
||||
data, data_size, oob, oob_size);
|
||||
target_free_working_area(target, pworking_area);
|
||||
}
|
||||
|
||||
|
@ -1289,8 +1286,8 @@ static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
|
|||
}
|
||||
|
||||
static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
||||
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 target *target = nand->target;
|
||||
static uint8_t page_buffer[2048];
|
||||
|
@ -1317,8 +1314,8 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
if (nand->page_size == 512) {
|
||||
/* small page device */
|
||||
/* MLC_ADDR = 0x0 (one column cycle) */
|
||||
/* small page device
|
||||
* MLC_ADDR = 0x0 (one column cycle) */
|
||||
retval = target_write_u32(target, 0x200b8004, 0x0);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_ADDR");
|
||||
|
@ -1332,7 +1329,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
retval = target_write_u32(target, 0x200b8004,
|
||||
(page >> 8) & 0xff);
|
||||
(page >> 8) & 0xff);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_ADDR");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -1340,15 +1337,15 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
|
||||
if (nand->address_cycles == 4) {
|
||||
retval = target_write_u32(target, 0x200b8004,
|
||||
(page >> 16) & 0xff);
|
||||
(page >> 16) & 0xff);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_ADDR");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* large page device */
|
||||
/* MLC_ADDR = 0x0 (two column cycles) */
|
||||
/* large page device
|
||||
* MLC_ADDR = 0x0 (two column cycles) */
|
||||
retval = target_write_u32(target, 0x200b8004, 0x0);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_ADDR");
|
||||
|
@ -1367,7 +1364,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
retval = target_write_u32(target, 0x200b8004,
|
||||
(page >> 8) & 0xff);
|
||||
(page >> 8) & 0xff);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_ADDR");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -1375,7 +1372,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
|
||||
/* MLC_CMD = Read Start */
|
||||
retval = target_write_u32(target, 0x200b8000,
|
||||
NAND_CMD_READSTART);
|
||||
NAND_CMD_READSTART);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not set MLC_CMD");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -1392,7 +1389,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
|
||||
if (!lpc32xx_controller_ready(nand, 1000)) {
|
||||
LOG_ERROR("timeout while waiting for "
|
||||
"completion of auto decode cycle");
|
||||
"completion of auto decode cycle");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1405,17 +1402,17 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
if (mlc_isr & 0x8) {
|
||||
if (mlc_isr & 0x40) {
|
||||
LOG_ERROR("uncorrectable error detected: "
|
||||
"0x%2.2x", (unsigned)mlc_isr);
|
||||
"0x%2.2x", (unsigned)mlc_isr);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
LOG_WARNING("%i symbol error detected and corrected",
|
||||
((int)(((mlc_isr & 0x30) >> 4) + 1)));
|
||||
((int)(((mlc_isr & 0x30) >> 4) + 1)));
|
||||
}
|
||||
|
||||
if (data) {
|
||||
retval = target_read_memory(target, 0x200a8000, 4, 128,
|
||||
page_buffer + page_bytes_done);
|
||||
page_buffer + page_bytes_done);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not read MLC_BUF (data)");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -1424,7 +1421,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
|
||||
if (oob) {
|
||||
retval = target_read_memory(target, 0x200a8000, 4, 4,
|
||||
oob_buffer + oob_bytes_done);
|
||||
oob_buffer + oob_bytes_done);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("could not read MLC_BUF (oob)");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
@ -1445,17 +1442,17 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
|
|||
}
|
||||
|
||||
static int lpc32xx_read_page_slc(struct nand_device *nand,
|
||||
struct working_area *pworking_area,
|
||||
uint32_t page, uint8_t *data,
|
||||
uint32_t data_size, uint8_t *oob,
|
||||
uint32_t oob_size)
|
||||
struct working_area *pworking_area,
|
||||
uint32_t page, uint8_t *data,
|
||||
uint32_t data_size, uint8_t *oob,
|
||||
uint32_t oob_size)
|
||||
{
|
||||
struct target *target = nand->target;
|
||||
int retval;
|
||||
uint32_t target_mem_base;
|
||||
|
||||
LOG_DEBUG("SLC read page %x data=%d, oob=%d",
|
||||
page, data_size, oob_size);
|
||||
page, data_size, oob_size);
|
||||
|
||||
target_mem_base = pworking_area->address;
|
||||
|
||||
|
@ -1465,8 +1462,8 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
XXX: Assumes host and target have same byte sex.
|
||||
*/
|
||||
retval = target_write_memory(target, target_mem_base, 4,
|
||||
nll * sizeof(dmac_ll_t) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
nll * sizeof(dmac_ll_t) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write DMA descriptors to IRAM");
|
||||
return retval;
|
||||
|
@ -1478,13 +1475,13 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* SLC_CFG =
|
||||
Force nCE assert,
|
||||
DMA ECC enabled,
|
||||
ECC enabled,
|
||||
DMA burst enabled,
|
||||
DMA read from SLC,
|
||||
WIDTH = bus_width
|
||||
/* SLC_CFG =
|
||||
Force nCE assert,
|
||||
DMA ECC enabled,
|
||||
ECC enabled,
|
||||
DMA burst enabled,
|
||||
DMA read from SLC,
|
||||
WIDTH = bus_width
|
||||
*/
|
||||
retval = target_write_u32(target, 0x20020014, 0x3e);
|
||||
if (ERROR_OK != retval) {
|
||||
|
@ -1494,7 +1491,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
|
||||
/* Write first decriptor to DMA controller */
|
||||
retval = target_write_memory(target, 0x31000100, 4,
|
||||
sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist);
|
||||
sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write DMA descriptor to DMAC");
|
||||
return retval;
|
||||
|
@ -1512,7 +1509,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
/* Copy data from iram */
|
||||
if (data) {
|
||||
retval = target_read_memory(target, target_mem_base + DATA_OFFS,
|
||||
4, data_size/4, data);
|
||||
4, data_size/4, data);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not read data from IRAM");
|
||||
return retval;
|
||||
|
@ -1521,8 +1518,8 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
if (oob) {
|
||||
/* No error correction, just return data as read from flash */
|
||||
retval = target_read_memory(target,
|
||||
target_mem_base + SPARE_OFFS, 4,
|
||||
oob_size/4, oob);
|
||||
target_mem_base + SPARE_OFFS, 4,
|
||||
oob_size/4, oob);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not read OOB from IRAM");
|
||||
return retval;
|
||||
|
@ -1533,7 +1530,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
/* Copy OOB from flash, stored in IRAM */
|
||||
static uint8_t foob[64];
|
||||
retval = target_read_memory(target, target_mem_base + SPARE_OFFS,
|
||||
4, nand->page_size == 2048 ? 16 : 4, foob);
|
||||
4, nand->page_size == 2048 ? 16 : 4, foob);
|
||||
lpc32xx_dump_oob(foob, nand->page_size == 2048 ? 64 : 16);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not read OOB from IRAM");
|
||||
|
@ -1541,9 +1538,9 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
}
|
||||
/* Copy ECC from HW, generated while reading */
|
||||
int ecc_count = nand->page_size == 2048 ? 8 : 2;
|
||||
static uint32_t hw_ecc[8]; /* max size */
|
||||
static uint32_t hw_ecc[8]; /* max size */
|
||||
retval = target_read_memory(target, target_mem_base + ECC_OFFS, 4,
|
||||
ecc_count, (uint8_t *)hw_ecc);
|
||||
ecc_count, (uint8_t *)hw_ecc);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not read hw generated ECC from IRAM");
|
||||
return retval;
|
||||
|
@ -1551,7 +1548,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
static uint8_t ecc[24];
|
||||
slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count);
|
||||
/* Copy ECC from flash using correct layout */
|
||||
static uint8_t fecc[24]; /* max size */
|
||||
static uint8_t fecc[24];/* max size */
|
||||
int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout;
|
||||
int i;
|
||||
for (i = 0; i < ecc_count * 3; i++)
|
||||
|
@ -1559,10 +1556,10 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
/* Compare ECC and possibly correct data */
|
||||
for (i = 0; i < ecc_count; i++) {
|
||||
retval = nand_correct_data(nand, data + 256*i, &fecc[i * 3],
|
||||
&ecc[i * 3]);
|
||||
&ecc[i * 3]);
|
||||
if (retval > 0)
|
||||
LOG_WARNING("error detected and corrected: %d/%d",
|
||||
page, i);
|
||||
page, i);
|
||||
if (retval < 0)
|
||||
break;
|
||||
}
|
||||
|
@ -1576,8 +1573,8 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
}
|
||||
|
||||
static int lpc32xx_read_page(struct nand_device *nand, uint32_t page,
|
||||
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 lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
|
||||
struct target *target = nand->target;
|
||||
|
@ -1585,7 +1582,7 @@ static int lpc32xx_read_page(struct nand_device *nand, uint32_t page,
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use LPC32xx "
|
||||
"NAND flash controller");
|
||||
"NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1598,21 +1595,21 @@ static int lpc32xx_read_page(struct nand_device *nand, uint32_t page,
|
|||
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
|
||||
}
|
||||
retval = lpc32xx_read_page_mlc(nand, page, data, data_size,
|
||||
oob, oob_size);
|
||||
oob, oob_size);
|
||||
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
|
||||
struct working_area *pworking_area;
|
||||
|
||||
retval = target_alloc_working_area(target,
|
||||
nand->page_size + 0x200,
|
||||
&pworking_area);
|
||||
retval = target_alloc_working_area(target,
|
||||
nand->page_size + 0x200,
|
||||
&pworking_area);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("Can't allocate working area in "
|
||||
"LPC internal RAM");
|
||||
"LPC internal RAM");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
retval = lpc32xx_read_page_slc(nand, pworking_area, page,
|
||||
data, data_size, oob, oob_size);
|
||||
target_free_working_area(target, pworking_area);
|
||||
data, data_size, oob, oob_size);
|
||||
target_free_working_area(target, pworking_area);
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -1626,7 +1623,7 @@ static int lpc32xx_controller_ready(struct nand_device *nand, int timeout)
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use LPC32xx "
|
||||
"NAND flash controller");
|
||||
"NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1645,7 +1642,7 @@ static int lpc32xx_controller_ready(struct nand_device *nand, int timeout)
|
|||
|
||||
if (status & 2) {
|
||||
LOG_DEBUG("lpc32xx_controller_ready count=%d",
|
||||
timeout);
|
||||
timeout);
|
||||
return 1;
|
||||
}
|
||||
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
|
||||
|
@ -1660,7 +1657,7 @@ static int lpc32xx_controller_ready(struct nand_device *nand, int timeout)
|
|||
|
||||
if (status & 1) {
|
||||
LOG_DEBUG("lpc32xx_controller_ready count=%d",
|
||||
timeout);
|
||||
timeout);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -1679,7 +1676,7 @@ static int lpc32xx_nand_ready(struct nand_device *nand, int timeout)
|
|||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("target must be halted to use LPC32xx "
|
||||
"NAND flash controller");
|
||||
"NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1699,7 +1696,7 @@ static int lpc32xx_nand_ready(struct nand_device *nand, int timeout)
|
|||
|
||||
if (status & 1) {
|
||||
LOG_DEBUG("lpc32xx_nand_ready count end=%d",
|
||||
timeout);
|
||||
timeout);
|
||||
return 1;
|
||||
}
|
||||
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
|
||||
|
@ -1714,7 +1711,7 @@ static int lpc32xx_nand_ready(struct nand_device *nand, int timeout)
|
|||
|
||||
if (status & 1) {
|
||||
LOG_DEBUG("lpc32xx_nand_ready count end=%d",
|
||||
timeout);
|
||||
timeout);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -1740,7 +1737,7 @@ static int lpc32xx_tc_ready(struct nand_device *nand, int timeout)
|
|||
LOG_ERROR("Could not read SLC_INT_STAT");
|
||||
return 0;
|
||||
}
|
||||
if (status & 2){
|
||||
if (status & 2) {
|
||||
LOG_DEBUG("lpc32xx_tc_ready count=%d", timeout);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1758,16 +1755,15 @@ COMMAND_HANDLER(handle_lpc32xx_select_command)
|
|||
"no", "mlc", "slc"
|
||||
};
|
||||
|
||||
if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) {
|
||||
if ((CMD_ARGC < 1) || (CMD_ARGC > 3))
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
unsigned num;
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
|
||||
struct nand_device *nand = get_nand_device_by_num(num);
|
||||
if (!nand) {
|
||||
command_print(CMD_CTX, "nand device '#%s' is out of bounds",
|
||||
CMD_ARGV[0]);
|
||||
CMD_ARGV[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -1780,13 +1776,12 @@ COMMAND_HANDLER(handle_lpc32xx_select_command)
|
|||
} else if (strcmp(CMD_ARGV[1], "slc") == 0) {
|
||||
lpc32xx_info->selected_controller =
|
||||
LPC32xx_SLC_CONTROLLER;
|
||||
} else {
|
||||
} else
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
command_print(CMD_CTX, "%s controller selected",
|
||||
selected[lpc32xx_info->selected_controller]);
|
||||
selected[lpc32xx_info->selected_controller]);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -17,18 +17,17 @@
|
|||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef LPC32xx_NAND_CONTROLLER_H
|
||||
#define LPC32xx_NAND_CONTROLLER_H
|
||||
|
||||
enum lpc32xx_selected_controller
|
||||
{
|
||||
enum lpc32xx_selected_controller {
|
||||
LPC32xx_NO_CONTROLLER,
|
||||
LPC32xx_MLC_CONTROLLER,
|
||||
LPC32xx_SLC_CONTROLLER,
|
||||
};
|
||||
|
||||
struct lpc32xx_nand_controller
|
||||
{
|
||||
struct lpc32xx_nand_controller {
|
||||
int osc_freq;
|
||||
enum lpc32xx_selected_controller selected_controller;
|
||||
int sw_write_protection;
|
||||
|
@ -36,4 +35,4 @@ struct lpc32xx_nand_controller
|
|||
uint32_t sw_wp_upper_bound;
|
||||
};
|
||||
|
||||
#endif /*LPC32xx_NAND_CONTROLLER_H */
|
||||
#endif /*LPC32xx_NAND_CONTROLLER_H */
|
||||
|
|
1052
src/flash/nand/mx3.c
1052
src/flash/nand/mx3.c
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,3 @@
|
|||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Alexei Babich *
|
||||
* Rezonans plc., Chelyabinsk, Russia *
|
||||
|
@ -26,80 +25,77 @@
|
|||
* 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 */
|
||||
#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 */
|
||||
|
||||
/*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 */
|
||||
#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_NANDID = 2,
|
||||
MX3_NF_DATAOUT_NANDSTATUS = 4,
|
||||
};
|
||||
enum mx_nf_finalize_action
|
||||
{
|
||||
enum mx_nf_finalize_action {
|
||||
MX3_NF_FIN_NONE,
|
||||
MX3_NF_FIN_DATAOUT,
|
||||
};
|
||||
|
||||
struct mx3_nf_flags
|
||||
{
|
||||
struct mx3_nf_flags {
|
||||
unsigned host_little_endian:1;
|
||||
unsigned target_little_endian:1;
|
||||
unsigned nand_readonly:1;
|
||||
|
@ -107,8 +103,7 @@ struct mx3_nf_flags
|
|||
unsigned hw_ecc_enabled:1;
|
||||
};
|
||||
|
||||
struct mx3_nf_controller
|
||||
{
|
||||
struct mx3_nf_controller {
|
||||
enum mx_dataout_type optype;
|
||||
enum mx_nf_finalize_action fin;
|
||||
struct mx3_nf_flags flags;
|
||||
|
|
|
@ -49,12 +49,12 @@
|
|||
#include "mxc.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 || \
|
||||
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 || \
|
||||
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
|
||||
* 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->fin = MXC_NF_FIN_NONE;
|
||||
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
|
||||
|
@ -190,9 +190,9 @@ COMMAND_HANDLER(handle_mxc_biswap_command)
|
|||
static const struct command_registration mxc_sub_command_handlers[] = {
|
||||
{
|
||||
.name = "biswap",
|
||||
.handler = handle_mxc_biswap_command ,
|
||||
.handler = handle_mxc_biswap_command,
|
||||
.help = "Turns on/off bad block information swaping from main area, "
|
||||
"without parameter query status.",
|
||||
"without parameter query status.",
|
||||
.usage = "bank_id ['enable'|'disable']",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
|
@ -262,18 +262,17 @@ static int mxc_init(struct nand_device *nand)
|
|||
else
|
||||
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;
|
||||
} else {
|
||||
else {
|
||||
sreg_content |= ((nand->page_size == 2048) ? SEL_FMS : 0x00000000);
|
||||
target_write_u32(target, SREG, sreg_content);
|
||||
}
|
||||
if (mxc_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) {
|
||||
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");
|
||||
}
|
||||
|
||||
if (nfc_is_v2() && sreg_content & MX35_RCSR_NF_4K)
|
||||
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)) {
|
||||
LOG_INFO("NAND read-only");
|
||||
mxc_nf_info->flags.nand_readonly = 1;
|
||||
} else {
|
||||
} else
|
||||
mxc_nf_info->flags.nand_readonly = 0;
|
||||
}
|
||||
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);
|
||||
if (try_data_output_from_nand_chip != ERROR_OK) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -360,26 +358,26 @@ static int mxc_command(struct nand_device *nand, uint8_t command)
|
|||
return validate_target_result;
|
||||
|
||||
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);
|
||||
|
@ -396,24 +394,24 @@ static int mxc_command(struct nand_device *nand, uint8_t command)
|
|||
sign_of_sequental_byte_read = 0;
|
||||
/* Handle special read command and adjust NF_CFG2(FDO) */
|
||||
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;
|
||||
}
|
||||
|
@ -463,14 +461,13 @@ static int mxc_nand_ready(struct nand_device *nand, int tout)
|
|||
return tout;
|
||||
|
||||
alive_sleep(1);
|
||||
}
|
||||
while (tout-- > 0);
|
||||
} while (tout-- > 0);
|
||||
return tout;
|
||||
}
|
||||
|
||||
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 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;
|
||||
retval = ERROR_OK;
|
||||
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);
|
||||
if (oob) {
|
||||
|
@ -518,7 +515,7 @@ static int mxc_write_page(struct nand_device *nand, uint32_t page,
|
|||
* ECC generator
|
||||
*/
|
||||
LOG_DEBUG("part of spare block will be overrided "
|
||||
"by hardware ECC generator");
|
||||
"by hardware ECC generator");
|
||||
}
|
||||
if (nfc_is_v1())
|
||||
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");
|
||||
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);
|
||||
swap2 = (swap1 << 8) | (swap2 & 0xFF);
|
||||
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
|
||||
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_CFG2, MXC_NF_BIT_OP_FDI);
|
||||
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,
|
||||
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 target *target = nand->target;
|
||||
|
@ -620,31 +617,37 @@ static int mxc_read_page(struct nand_device *nand, uint32_t page,
|
|||
* validate target state
|
||||
*/
|
||||
retval = validate_target_state(nand);
|
||||
if (retval != ERROR_OK) {
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
/* Reset address_cycles before mxc_command ?? */
|
||||
/* Reset address_cycles before mxc_command ?? */
|
||||
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);
|
||||
if (retval != ERROR_OK) return retval;
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if (nfc_is_v1() && nand->page_size > 512)
|
||||
bufs = 4;
|
||||
else
|
||||
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);
|
||||
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
|
||||
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;
|
||||
uint32_t ret = addr;
|
||||
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;
|
||||
} 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;
|
||||
return ret;
|
||||
}
|
||||
|
@ -725,15 +728,13 @@ static int initialize_nf_controller(struct nand_device *nand)
|
|||
if (target->endianness == TARGET_BIG_ENDIAN) {
|
||||
LOG_DEBUG("MXC_NF : work in Big Endian mode");
|
||||
work_mode |= MXC_NF_BIT_BE_EN;
|
||||
} else {
|
||||
} else
|
||||
LOG_DEBUG("MXC_NF : work in Little Endian mode");
|
||||
}
|
||||
if (mxc_nf_info->flags.hw_ecc_enabled) {
|
||||
LOG_DEBUG("MXC_NF : work with ECC mode");
|
||||
work_mode |= MXC_NF_BIT_ECC_EN;
|
||||
} else {
|
||||
} else
|
||||
LOG_DEBUG("MXC_NF : work without ECC mode");
|
||||
}
|
||||
if (nfc_is_v2()) {
|
||||
target_write_u16(target, MXC_NF_V2_SPAS, OOB_SIZE / 2);
|
||||
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 target *target = nand->target;
|
||||
static uint8_t even_byte = 0;
|
||||
static uint8_t even_byte;
|
||||
uint16_t temp;
|
||||
/*
|
||||
* 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)
|
||||
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);
|
||||
*value = 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 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);
|
||||
*value = 0;
|
||||
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 !=
|
||||
(target->endianness == TARGET_LITTLE_ENDIAN)) {
|
||||
(target->endianness == TARGET_LITTLE_ENDIAN)) {
|
||||
/*
|
||||
* 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);
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
@ -927,47 +926,46 @@ static int do_data_output(struct nand_device *nand)
|
|||
struct target *target = nand->target;
|
||||
int poll_result;
|
||||
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;
|
||||
}
|
||||
|
||||
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 "hello.h"
|
||||
|
||||
|
||||
static int nonce_nand_command(struct nand_device *nand, uint8_t command)
|
||||
{
|
||||
return ERROR_OK;
|
||||
|
@ -62,16 +61,15 @@ static int nonce_nand_init(struct nand_device *nand)
|
|||
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 <target/arm.h>
|
||||
|
||||
struct nuc910_nand_controller
|
||||
{
|
||||
struct nuc910_nand_controller {
|
||||
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;
|
||||
int result;
|
||||
|
||||
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||
result = validate_target_state(nand);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
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;
|
||||
int result;
|
||||
|
||||
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||
result = validate_target_state(nand);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
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;
|
||||
int result;
|
||||
|
||||
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||
result = validate_target_state(nand);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
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;
|
||||
int result;
|
||||
|
||||
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||
result = validate_target_state(nand);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
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;
|
||||
int result;
|
||||
|
||||
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||
result = validate_target_state(nand);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
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;
|
||||
int result;
|
||||
|
||||
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||
result = validate_target_state(nand);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
nuc910_nand->io.chunk_size = nand->page_size;
|
||||
|
@ -154,9 +159,8 @@ static int nuc910_nand_ready(struct nand_device *nand, int timeout)
|
|||
|
||||
do {
|
||||
target_read_u32(target, NUC910_SMISR, &status);
|
||||
if (status & NUC910_SMISR_RB_) {
|
||||
if (status & NUC910_SMISR_RB_)
|
||||
return 1;
|
||||
}
|
||||
alive_sleep(1);
|
||||
} while (timeout-- > 0);
|
||||
|
||||
|
@ -184,12 +188,12 @@ static int nuc910_nand_init(struct nand_device *nand)
|
|||
int bus_width = nand->bus_width ? : 8;
|
||||
int result;
|
||||
|
||||
if ((result = validate_target_state(nand)) != ERROR_OK)
|
||||
result = validate_target_state(nand);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
/* 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);
|
||||
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
|
||||
}
|
||||
|
@ -210,8 +214,7 @@ static int nuc910_nand_init(struct nand_device *nand)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
struct nand_flash_controller nuc910_nand_controller =
|
||||
{
|
||||
struct nand_flash_controller nuc910_nand_controller = {
|
||||
.name = "nuc910",
|
||||
.command = nuc910_nand_command,
|
||||
.address = nuc910_nand_address,
|
||||
|
|
|
@ -30,9 +30,7 @@
|
|||
#include "arm_io.h"
|
||||
#include <target/arm.h>
|
||||
|
||||
|
||||
struct orion_nand_controller
|
||||
{
|
||||
struct orion_nand_controller {
|
||||
struct arm_nand_data io;
|
||||
|
||||
uint32_t cmd;
|
||||
|
@ -120,9 +118,8 @@ NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
|
|||
uint32_t base;
|
||||
uint8_t ale, cle;
|
||||
|
||||
if (CMD_ARGC != 3) {
|
||||
if (CMD_ARGC != 3)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
hw = calloc(1, sizeof(*hw));
|
||||
if (!hw) {
|
||||
|
@ -152,17 +149,15 @@ static int orion_nand_init(struct nand_device *nand)
|
|||
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 = {
|
||||
.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 = {
|
||||
.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"
|
||||
|
||||
|
||||
NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
|
||||
{
|
||||
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 = {
|
||||
.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"
|
||||
|
||||
|
||||
NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command)
|
||||
{
|
||||
struct s3c24xx_nand_controller *info;
|
||||
|
@ -62,17 +61,17 @@ static int s3c2443_init(struct nand_device *nand)
|
|||
}
|
||||
|
||||
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"
|
||||
|
||||
|
||||
S3C24XX_DEVICE_COMMAND()
|
||||
{
|
||||
*info = NULL;
|
||||
|
@ -77,7 +76,6 @@ int s3c24xx_command(struct nand_device *nand, uint8_t command)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
int s3c24xx_address(struct nand_device *nand, uint8_t address)
|
||||
{
|
||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||
|
|
|
@ -31,8 +31,7 @@
|
|||
#include "s3c24xx_regs.h"
|
||||
#include <target/target.h>
|
||||
|
||||
struct s3c24xx_nand_controller
|
||||
{
|
||||
struct s3c24xx_nand_controller {
|
||||
/* register addresses */
|
||||
uint32_t cmd;
|
||||
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,
|
||||
uint8_t *data, int data_size);
|
||||
|
||||
#endif // S3C24xx_NAND_H
|
||||
#endif /* S3C24xx_NAND_H */
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
#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)
|
||||
|
||||
|
|
|
@ -58,17 +58,17 @@ static int s3c6400_init(struct nand_device *nand)
|
|||
}
|
||||
|
||||
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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
@ -29,7 +30,7 @@
|
|||
#include "fileio.h"
|
||||
#include <target/target.h>
|
||||
|
||||
// to be removed
|
||||
/* to be removed */
|
||||
extern struct nand_device *nand_devices;
|
||||
|
||||
COMMAND_HANDLER(handle_nand_list_command)
|
||||
|
@ -37,14 +38,12 @@ COMMAND_HANDLER(handle_nand_list_command)
|
|||
struct nand_device *p;
|
||||
int i;
|
||||
|
||||
if (!nand_devices)
|
||||
{
|
||||
if (!nand_devices) {
|
||||
command_print(CMD_CTX, "no NAND flash devices configured");
|
||||
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)
|
||||
command_print(CMD_CTX, "#%i: %s (%s) "
|
||||
"pagesize: %i, buswidth: %i,\n\t"
|
||||
|
@ -67,21 +66,21 @@ COMMAND_HANDLER(handle_nand_info_command)
|
|||
int last = -1;
|
||||
|
||||
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;
|
||||
|
@ -89,8 +88,7 @@ COMMAND_HANDLER(handle_nand_info_command)
|
|||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
if (NULL == p->device)
|
||||
{
|
||||
if (NULL == p->device) {
|
||||
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -101,11 +99,16 @@ COMMAND_HANDLER(handle_nand_info_command)
|
|||
if (last >= p->num_blocks)
|
||||
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;
|
||||
|
||||
if (p->blocks[j].is_erased == 0)
|
||||
|
@ -123,12 +126,12 @@ COMMAND_HANDLER(handle_nand_info_command)
|
|||
bad_state = " (block condition unknown)";
|
||||
|
||||
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;
|
||||
|
@ -137,19 +140,17 @@ COMMAND_HANDLER(handle_nand_info_command)
|
|||
COMMAND_HANDLER(handle_nand_probe_command)
|
||||
{
|
||||
if (CMD_ARGC != 1)
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
struct nand_device *p;
|
||||
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
|
||||
if (ERROR_OK != 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",
|
||||
p->device->name, p->manufacturer->name);
|
||||
p->device->name, p->manufacturer->name);
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -158,11 +159,8 @@ COMMAND_HANDLER(handle_nand_probe_command)
|
|||
COMMAND_HANDLER(handle_nand_erase_command)
|
||||
{
|
||||
if (CMD_ARGC != 1 && CMD_ARGC != 3)
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
}
|
||||
|
||||
struct nand_device *p;
|
||||
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
|
||||
if (ERROR_OK != retval)
|
||||
|
@ -181,7 +179,7 @@ COMMAND_HANDLER(handle_nand_erase_command)
|
|||
|
||||
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
|
||||
if ((length == 0) || (length % p->erase_size) != 0
|
||||
|| (length + offset) > size)
|
||||
|| (length + offset) > size)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
offset /= p->erase_size;
|
||||
|
@ -192,12 +190,11 @@ COMMAND_HANDLER(handle_nand_erase_command)
|
|||
}
|
||||
|
||||
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 "
|
||||
"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;
|
||||
|
@ -209,18 +206,14 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
|
|||
int last = -1;
|
||||
|
||||
if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2))
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
}
|
||||
|
||||
struct nand_device *p;
|
||||
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
if (CMD_ARGC == 3)
|
||||
{
|
||||
if (CMD_ARGC == 3) {
|
||||
unsigned long offset;
|
||||
unsigned long length;
|
||||
|
||||
|
@ -241,10 +234,9 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
|
|||
}
|
||||
|
||||
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, "
|
||||
"use \"nand info\" command to list blocks");
|
||||
"use \"nand info\" command to list blocks");
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -260,11 +252,9 @@ COMMAND_HANDLER(handle_nand_write_command)
|
|||
return retval;
|
||||
|
||||
uint32_t total_bytes = s.size;
|
||||
while (s.size > 0)
|
||||
{
|
||||
while (s.size > 0) {
|
||||
int bytes_read = nand_fileio_read(nand, &s);
|
||||
if (bytes_read <= 0)
|
||||
{
|
||||
if (bytes_read <= 0) {
|
||||
command_print(CMD_CTX, "error while reading file");
|
||||
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,
|
||||
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 "
|
||||
"to NAND flash %s at offset 0x%8.8" PRIx32,
|
||||
CMD_ARGV[1], CMD_ARGV[0], s.address);
|
||||
|
@ -282,12 +271,11 @@ COMMAND_HANDLER(handle_nand_write_command)
|
|||
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 "
|
||||
"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;
|
||||
}
|
||||
|
@ -310,12 +298,10 @@ COMMAND_HANDLER(handle_nand_verify_command)
|
|||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
while (file.size > 0)
|
||||
{
|
||||
while (file.size > 0) {
|
||||
retval = nand_read_page(nand, dev.address / dev.page_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");
|
||||
nand_fileio_cleanup(&dev);
|
||||
nand_fileio_cleanup(&file);
|
||||
|
@ -323,8 +309,7 @@ COMMAND_HANDLER(handle_nand_verify_command)
|
|||
}
|
||||
|
||||
int bytes_read = nand_fileio_read(nand, &file);
|
||||
if (bytes_read <= 0)
|
||||
{
|
||||
if (bytes_read <= 0) {
|
||||
command_print(CMD_CTX, "error while reading file");
|
||||
nand_fileio_cleanup(&dev);
|
||||
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)) ||
|
||||
(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 "
|
||||
"at 0x%8.8" PRIx32, dev.address);
|
||||
"at 0x%8.8" PRIx32, dev.address);
|
||||
nand_fileio_cleanup(&dev);
|
||||
nand_fileio_cleanup(&file);
|
||||
return ERROR_FAIL;
|
||||
|
@ -345,12 +329,11 @@ COMMAND_HANDLER(handle_nand_verify_command)
|
|||
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 "
|
||||
"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);
|
||||
|
@ -366,13 +349,11 @@ COMMAND_HANDLER(handle_nand_dump_command)
|
|||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
while (s.size > 0)
|
||||
{
|
||||
while (s.size > 0) {
|
||||
size_t size_written;
|
||||
retval = nand_read_page(nand, s.address / nand->page_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");
|
||||
nand_fileio_cleanup(&s);
|
||||
return retval;
|
||||
|
@ -392,11 +373,10 @@ COMMAND_HANDLER(handle_nand_dump_command)
|
|||
if (retval != ERROR_OK)
|
||||
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)",
|
||||
(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;
|
||||
}
|
||||
|
@ -404,17 +384,14 @@ COMMAND_HANDLER(handle_nand_dump_command)
|
|||
COMMAND_HANDLER(handle_nand_raw_access_command)
|
||||
{
|
||||
if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
struct nand_device *p;
|
||||
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
if (NULL == p->device)
|
||||
{
|
||||
if (NULL == p->device) {
|
||||
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -510,9 +487,8 @@ COMMAND_HANDLER(handle_nand_init_command)
|
|||
if (CMD_ARGC != 0)
|
||||
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");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -536,32 +512,28 @@ COMMAND_HANDLER(handle_nand_list_drivers)
|
|||
}
|
||||
|
||||
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 target *target;
|
||||
int retval;
|
||||
|
||||
if (CMD_ARGC < 2)
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
target = get_target(CMD_ARGV[1]);
|
||||
if (!target) {
|
||||
LOG_ERROR("invalid target %s", CMD_ARGV[1]);
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
||||
if (NULL != controller->commands)
|
||||
{
|
||||
if (NULL != controller->commands) {
|
||||
retval = register_commands(CMD_CTX, NULL,
|
||||
controller->commands);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
}
|
||||
c = malloc(sizeof(struct nand_device));
|
||||
if (c == NULL)
|
||||
{
|
||||
if (c == NULL) {
|
||||
LOG_ERROR("End of memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -579,8 +551,7 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
|
|||
c->next = NULL;
|
||||
|
||||
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",
|
||||
controller->name,
|
||||
controller->usage);
|
||||
|
@ -599,19 +570,16 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
|
|||
COMMAND_HANDLER(handle_nand_device_command)
|
||||
{
|
||||
if (CMD_ARGC < 2)
|
||||
{
|
||||
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++;
|
||||
CMD_ARGC--;
|
||||
|
||||
const char *driver_name = CMD_ARGV[0];
|
||||
struct nand_flash_controller *controller;
|
||||
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);
|
||||
return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
|
||||
}
|
||||
|
@ -642,6 +610,7 @@ static const struct command_registration nand_config_command_handlers[] = {
|
|||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
static const struct command_registration nand_command_handlers[] = {
|
||||
{
|
||||
.name = "nand",
|
||||
|
@ -657,5 +626,3 @@ int nand_register_commands(struct command_context *cmd_ctx)
|
|||
{
|
||||
return register_commands(cmd_ctx, NULL, nand_command_handlers);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue