build: cleanup src/flash/nand directory

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

View File

@ -30,7 +30,6 @@
#include <target/arm.h> #include <target/arm.h>
#include <target/algorithm.h> #include <target/algorithm.h>
/** /**
* Copies code to a working area. This will allocate room for the code plus the * Copies code to a working area. This will allocate room for the code plus the
* additional amount requested if the working area pointer is null. * additional amount requested if the working area pointer is null.
@ -61,7 +60,7 @@ static int arm_code_to_working_area(struct target *target,
if (NULL == *area) { if (NULL == *area) {
retval = target_alloc_working_area(target, size, area); retval = target_alloc_working_area(target, size, area);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_DEBUG("%s: no %d byte buffer", __FUNCTION__, (int) size); LOG_DEBUG("%s: no %d byte buffer", __func__, (int) size);
return ERROR_NAND_NO_BUFFER; return ERROR_NAND_NO_BUFFER;
} }
} }
@ -121,10 +120,9 @@ int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
if (nand->op != ARM_NAND_WRITE || !nand->copy_area) { if (nand->op != ARM_NAND_WRITE || !nand->copy_area) {
retval = arm_code_to_working_area(target, code, sizeof(code), retval = arm_code_to_working_area(target, code, sizeof(code),
nand->chunk_size, &nand->copy_area); nand->chunk_size, &nand->copy_area);
if (retval != ERROR_OK) { if (retval != ERROR_OK)
return retval; return retval;
} }
}
nand->op = ARM_NAND_WRITE; nand->op = ARM_NAND_WRITE;
@ -206,10 +204,9 @@ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size)
if (nand->op != ARM_NAND_READ || !nand->copy_area) { if (nand->op != ARM_NAND_READ || !nand->copy_area) {
retval = arm_code_to_working_area(target, code, sizeof(code), retval = arm_code_to_working_area(target, code, sizeof(code),
nand->chunk_size, &nand->copy_area); nand->chunk_size, &nand->copy_area);
if (retval != ERROR_OK) { if (retval != ERROR_OK)
return retval; return retval;
} }
}
nand->op = ARM_NAND_READ; nand->op = ARM_NAND_READ;
target_buf = nand->copy_area->address + sizeof(code); target_buf = nand->copy_area->address + sizeof(code);
@ -246,4 +243,3 @@ int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size)
return retval; return retval;
} }

View File

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

View File

@ -20,6 +20,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -27,13 +28,14 @@
#include "imp.h" #include "imp.h"
/* configured NAND devices and NAND Flash command handler */ /* configured NAND devices and NAND Flash command handler */
struct nand_device *nand_devices = NULL; struct nand_device *nand_devices;
void nand_device_add(struct nand_device *c) void nand_device_add(struct nand_device *c)
{ {
if (nand_devices) { if (nand_devices) {
struct nand_device *p = nand_devices; struct nand_device *p = nand_devices;
while (p && p->next) p = p->next; while (p && p->next)
p = p->next;
p->next = c; p->next = c;
} else } else
nand_devices = c; nand_devices = c;
@ -50,11 +52,12 @@ void nand_device_add(struct nand_device *c)
* 256 256 Byte page size * 256 256 Byte page size
* 512 512 Byte page size * 512 512 Byte page size
*/ */
static struct nand_info nand_flash_ids[] = static struct nand_info nand_flash_ids[] = {
{
/* Vendor Specific Entries */ /* Vendor Specific Entries */
{ NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS, "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"}, { NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS,
{ NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS, "K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"}, "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"},
{ NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS,
"K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"},
/* start "museum" IDs */ /* start "museum" IDs */
{ 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"}, { 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"},
@ -76,26 +79,26 @@ static struct nand_info nand_flash_ids[] =
{ 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"}, { 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"},
{ 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"}, { 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"},
{ 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16,"NAND 16MiB 1.8V 16-bit"}, { 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 1.8V 16-bit"},
{ 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16,"NAND 16MiB 3.3V 16-bit"}, { 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 3.3V 16-bit"},
{ 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"}, { 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"},
{ 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"}, { 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"},
{ 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16,"NAND 32MiB 1.8V 16-bit"}, { 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 1.8V 16-bit"},
{ 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16,"NAND 32MiB 3.3V 16-bit"}, { 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 3.3V 16-bit"},
{ 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"}, { 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"},
{ 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"}, { 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"},
{ 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16,"NAND 64MiB 1.8V 16-bit"}, { 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 1.8V 16-bit"},
{ 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16,"NAND 64MiB 3.3V 16-bit"}, { 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 3.3V 16-bit"},
{ 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"}, { 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
{ 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"}, { 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
{ 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"}, { 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"},
{ 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 1.8V 16-bit"}, { 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"},
{ 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 1.8V 16-bit"}, { 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"},
{ 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3.3V 16-bit"}, { 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"},
{ 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3.3V 16-bit"}, { 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"},
{ 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"}, { 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"},
@ -136,8 +139,7 @@ static struct nand_info nand_flash_ids[] =
/* Manufacturer ID list /* Manufacturer ID list
*/ */
static struct nand_manufacturer nand_manuf_ids[] = static struct nand_manufacturer nand_manuf_ids[] = {
{
{0x0, "unknown"}, {0x0, "unknown"},
{NAND_MFR_TOSHIBA, "Toshiba"}, {NAND_MFR_TOSHIBA, "Toshiba"},
{NAND_MFR_SAMSUNG, "Samsung"}, {NAND_MFR_SAMSUNG, "Samsung"},
@ -162,7 +164,8 @@ static struct nand_ecclayout nand_oob_8 = {
{.offset = 3, {.offset = 3,
.length = 2}, .length = 2},
{.offset = 6, {.offset = 6,
.length = 2}} .length = 2}
}
}; };
#endif #endif
@ -179,8 +182,7 @@ static struct nand_device *get_nand_device_by_name(const char *name)
unsigned found = 0; unsigned found = 0;
struct nand_device *nand; struct nand_device *nand;
for (nand = nand_devices; NULL != nand; nand = nand->next) for (nand = nand_devices; NULL != nand; nand = nand->next) {
{
if (strcmp(nand->name, name) == 0) if (strcmp(nand->name, name) == 0)
return nand; return nand;
if (!flash_driver_name_matches(nand->controller->name, name)) if (!flash_driver_name_matches(nand->controller->name, name))
@ -197,13 +199,10 @@ struct nand_device *get_nand_device_by_num(int num)
struct nand_device *p; struct nand_device *p;
int i = 0; int i = 0;
for (p = nand_devices; p; p = p->next) for (p = nand_devices; p; p = p->next) {
{
if (i++ == num) if (i++ == num)
{
return p; return p;
} }
}
return NULL; return NULL;
} }
@ -241,23 +240,18 @@ int nand_build_bbt(struct nand_device *nand, int first, int last)
last = nand->num_blocks - 1; last = nand->num_blocks - 1;
page = first * pages_per_block; page = first * pages_per_block;
for (i = first; i <= last; i++) for (i = first; i <= last; i++) {
{
ret = nand_read_page(nand, page, NULL, 0, oob, 6); ret = nand_read_page(nand, page, NULL, 0, oob, 6);
if (ret != ERROR_OK) if (ret != ERROR_OK)
return ret; return ret;
if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff)) if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff))
|| (((nand->page_size == 512) && (oob[5] != 0xff)) || || (((nand->page_size == 512) && (oob[5] != 0xff)) ||
((nand->page_size == 2048) && (oob[0] != 0xff)))) ((nand->page_size == 2048) && (oob[0] != 0xff)))) {
{
LOG_WARNING("bad block: %i", i); LOG_WARNING("bad block: %i", i);
nand->blocks[i].is_bad = 1; nand->blocks[i].is_bad = 1;
} } else
else
{
nand->blocks[i].is_bad = 0; nand->blocks[i].is_bad = 0;
}
page += pages_per_block; page += pages_per_block;
} }
@ -276,16 +270,12 @@ int nand_read_status(struct nand_device *nand, uint8_t *status)
alive_sleep(1); alive_sleep(1);
/* read status */ /* read status */
if (nand->device->options & NAND_BUSWIDTH_16) if (nand->device->options & NAND_BUSWIDTH_16) {
{
uint16_t data; uint16_t data;
nand->controller->read_data(nand, &data); nand->controller->read_data(nand, &data);
*status = data & 0xff; *status = data & 0xff;
} } else
else
{
nand->controller->read_data(nand, status); nand->controller->read_data(nand, status);
}
return ERROR_OK; return ERROR_OK;
} }
@ -300,9 +290,8 @@ static int nand_poll_ready(struct nand_device *nand, int timeout)
uint16_t data; uint16_t data;
nand->controller->read_data(nand, &data); nand->controller->read_data(nand, &data);
status = data & 0xff; status = data & 0xff;
} else { } else
nand->controller->read_data(nand, &status); nand->controller->read_data(nand, &status);
}
if (status & NAND_STATUS_READY) if (status & NAND_STATUS_READY)
break; break;
alive_sleep(1); alive_sleep(1);
@ -329,15 +318,15 @@ int nand_probe(struct nand_device *nand)
nand->erase_size = 0; nand->erase_size = 0;
/* initialize controller (device parameters are zero, use controller default) */ /* initialize controller (device parameters are zero, use controller default) */
if ((retval = nand->controller->init(nand) != ERROR_OK)) retval = nand->controller->init(nand);
{ if (retval != ERROR_OK) {
switch (retval) switch (retval) {
{
case ERROR_NAND_OPERATION_FAILED: case ERROR_NAND_OPERATION_FAILED:
LOG_DEBUG("controller initialization failed"); LOG_DEBUG("controller initialization failed");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
case ERROR_NAND_OPERATION_NOT_SUPPORTED: case ERROR_NAND_OPERATION_NOT_SUPPORTED:
LOG_ERROR("BUG: controller reported that it doesn't support default parameters"); LOG_ERROR(
"BUG: controller reported that it doesn't support default parameters");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
default: default:
LOG_ERROR("BUG: unknown controller initialization failure"); LOG_ERROR("BUG: unknown controller initialization failure");
@ -351,13 +340,10 @@ int nand_probe(struct nand_device *nand)
nand->controller->command(nand, NAND_CMD_READID); nand->controller->command(nand, NAND_CMD_READID);
nand->controller->address(nand, 0x0); nand->controller->address(nand, 0x0);
if (nand->bus_width == 8) if (nand->bus_width == 8) {
{
nand->controller->read_data(nand, &manufacturer_id); nand->controller->read_data(nand, &manufacturer_id);
nand->controller->read_data(nand, &device_id); nand->controller->read_data(nand, &device_id);
} } else {
else
{
uint16_t data_buf; uint16_t data_buf;
nand->controller->read_data(nand, &data_buf); nand->controller->read_data(nand, &data_buf);
manufacturer_id = data_buf & 0xff; manufacturer_id = data_buf & 0xff;
@ -365,36 +351,32 @@ int nand_probe(struct nand_device *nand)
device_id = data_buf & 0xff; device_id = data_buf & 0xff;
} }
for (i = 0; nand_flash_ids[i].name; i++) for (i = 0; nand_flash_ids[i].name; i++) {
{
if (nand_flash_ids[i].id == device_id && if (nand_flash_ids[i].id == device_id &&
(nand_flash_ids[i].mfr_id == manufacturer_id || (nand_flash_ids[i].mfr_id == manufacturer_id ||
nand_flash_ids[i].mfr_id == 0 )) nand_flash_ids[i].mfr_id == 0)) {
{
nand->device = &nand_flash_ids[i]; nand->device = &nand_flash_ids[i];
break; break;
} }
} }
for (i = 0; nand_manuf_ids[i].name; i++) for (i = 0; nand_manuf_ids[i].name; i++) {
{ if (nand_manuf_ids[i].id == manufacturer_id) {
if (nand_manuf_ids[i].id == manufacturer_id)
{
nand->manufacturer = &nand_manuf_ids[i]; nand->manufacturer = &nand_manuf_ids[i];
break; break;
} }
} }
if (!nand->manufacturer) if (!nand->manufacturer) {
{
nand->manufacturer = &nand_manuf_ids[0]; nand->manufacturer = &nand_manuf_ids[0];
nand->manufacturer->id = manufacturer_id; nand->manufacturer->id = manufacturer_id;
} }
if (!nand->device) if (!nand->device) {
{ LOG_ERROR(
LOG_ERROR("unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x", "unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x",
manufacturer_id, device_id); manufacturer_id,
device_id);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -410,16 +392,12 @@ int nand_probe(struct nand_device *nand)
/* Do we need extended device probe information? */ /* Do we need extended device probe information? */
if (nand->device->page_size == 0 || if (nand->device->page_size == 0 ||
nand->device->erase_size == 0) nand->device->erase_size == 0) {
{ if (nand->bus_width == 8) {
if (nand->bus_width == 8)
{
nand->controller->read_data(nand, id_buff + 3); nand->controller->read_data(nand, id_buff + 3);
nand->controller->read_data(nand, id_buff + 4); nand->controller->read_data(nand, id_buff + 4);
nand->controller->read_data(nand, id_buff + 5); nand->controller->read_data(nand, id_buff + 5);
} } else {
else
{
uint16_t data_buf; uint16_t data_buf;
nand->controller->read_data(nand, &data_buf); nand->controller->read_data(nand, &data_buf);
@ -435,50 +413,38 @@ int nand_probe(struct nand_device *nand)
/* page size */ /* page size */
if (nand->device->page_size == 0) if (nand->device->page_size == 0)
{
nand->page_size = 1 << (10 + (id_buff[4] & 3)); nand->page_size = 1 << (10 + (id_buff[4] & 3));
} else if (nand->device->page_size == 256) {
else if (nand->device->page_size == 256)
{
LOG_ERROR("NAND flashes with 256 byte pagesize are not supported"); LOG_ERROR("NAND flashes with 256 byte pagesize are not supported");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} } else
else
{
nand->page_size = nand->device->page_size; nand->page_size = nand->device->page_size;
}
/* number of address cycles */ /* number of address cycles */
if (nand->page_size <= 512) if (nand->page_size <= 512) {
{
/* small page devices */ /* small page devices */
if (nand->device->chip_size <= 32) if (nand->device->chip_size <= 32)
nand->address_cycles = 3; nand->address_cycles = 3;
else if (nand->device->chip_size <= 8*1024) else if (nand->device->chip_size <= 8*1024)
nand->address_cycles = 4; nand->address_cycles = 4;
else else {
{
LOG_ERROR("BUG: small page NAND device with more than 8 GiB encountered"); LOG_ERROR("BUG: small page NAND device with more than 8 GiB encountered");
nand->address_cycles = 5; nand->address_cycles = 5;
} }
} } else {
else
{
/* large page devices */ /* large page devices */
if (nand->device->chip_size <= 128) if (nand->device->chip_size <= 128)
nand->address_cycles = 4; nand->address_cycles = 4;
else if (nand->device->chip_size <= 32*1024) else if (nand->device->chip_size <= 32*1024)
nand->address_cycles = 5; nand->address_cycles = 5;
else else {
{
LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered"); LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered");
nand->address_cycles = 6; nand->address_cycles = 6;
} }
} }
/* erase size */ /* erase size */
if (nand->device->erase_size == 0) if (nand->device->erase_size == 0) {
{
switch ((id_buff[4] >> 4) & 3) { switch ((id_buff[4] >> 4) & 3) {
case 0: case 0:
nand->erase_size = 64 << 10; nand->erase_size = 64 << 10;
@ -490,26 +456,25 @@ int nand_probe(struct nand_device *nand)
nand->erase_size = 256 << 10; nand->erase_size = 256 << 10;
break; break;
case 3: case 3:
nand->erase_size =512 << 10; nand->erase_size = 512 << 10;
break; break;
} }
} } else
else
{
nand->erase_size = nand->device->erase_size; nand->erase_size = nand->device->erase_size;
}
/* initialize controller, but leave parameters at the controllers default */ /* initialize controller, but leave parameters at the controllers default */
if ((retval = nand->controller->init(nand) != ERROR_OK)) retval = nand->controller->init(nand);
{ if (retval != ERROR_OK) {
switch (retval) switch (retval) {
{
case ERROR_NAND_OPERATION_FAILED: case ERROR_NAND_OPERATION_FAILED:
LOG_DEBUG("controller initialization failed"); LOG_DEBUG("controller initialization failed");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
case ERROR_NAND_OPERATION_NOT_SUPPORTED: case ERROR_NAND_OPERATION_NOT_SUPPORTED:
LOG_ERROR("controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)", LOG_ERROR(
nand->bus_width, nand->address_cycles, nand->page_size); "controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)",
nand->bus_width,
nand->address_cycles,
nand->page_size);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
default: default:
LOG_ERROR("BUG: unknown controller initialization failure"); LOG_ERROR("BUG: unknown controller initialization failure");
@ -520,8 +485,7 @@ int nand_probe(struct nand_device *nand)
nand->num_blocks = (nand->device->chip_size * 1024) / (nand->erase_size / 1024); nand->num_blocks = (nand->device->chip_size * 1024) / (nand->erase_size / 1024);
nand->blocks = malloc(sizeof(struct nand_block) * nand->num_blocks); nand->blocks = malloc(sizeof(struct nand_block) * nand->num_blocks);
for (i = 0; i < nand->num_blocks; i++) for (i = 0; i < nand->num_blocks; i++) {
{
nand->blocks[i].size = nand->erase_size; nand->blocks[i].size = nand->erase_size;
nand->blocks[i].offset = i * nand->erase_size; nand->blocks[i].offset = i * nand->erase_size;
nand->blocks[i].is_erased = -1; nand->blocks[i].is_erased = -1;
@ -545,25 +509,21 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
/* make sure we know if a block is bad before erasing it */ /* make sure we know if a block is bad before erasing it */
for (i = first_block; i <= last_block; i++) for (i = first_block; i <= last_block; i++) {
{ if (nand->blocks[i].is_bad == -1) {
if (nand->blocks[i].is_bad == -1)
{
nand_build_bbt(nand, i, last_block); nand_build_bbt(nand, i, last_block);
break; break;
} }
} }
for (i = first_block; i <= last_block; i++) for (i = first_block; i <= last_block; i++) {
{
/* Send erase setup command */ /* Send erase setup command */
nand->controller->command(nand, NAND_CMD_ERASE1); nand->controller->command(nand, NAND_CMD_ERASE1);
page = i * (nand->erase_size / nand->page_size); page = i * (nand->erase_size / nand->page_size);
/* Send page address */ /* Send page address */
if (nand->page_size <= 512) if (nand->page_size <= 512) {
{
/* row */ /* row */
nand->controller->address(nand, page & 0xff); nand->controller->address(nand, page & 0xff);
nand->controller->address(nand, (page >> 8) & 0xff); nand->controller->address(nand, (page >> 8) & 0xff);
@ -575,9 +535,7 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
/* 4th cycle only on devices with more than 8 GiB */ /* 4th cycle only on devices with more than 8 GiB */
if (nand->address_cycles >= 5) if (nand->address_cycles >= 5)
nand->controller->address(nand, (page >> 24) & 0xff); nand->controller->address(nand, (page >> 24) & 0xff);
} } else {
else
{
/* row */ /* row */
nand->controller->address(nand, page & 0xff); nand->controller->address(nand, page & 0xff);
nand->controller->address(nand, (page >> 8) & 0xff); nand->controller->address(nand, (page >> 8) & 0xff);
@ -599,14 +557,12 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
} }
retval = nand_read_status(nand, &status); retval = nand_read_status(nand, &status);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{
LOG_ERROR("couldn't read status"); LOG_ERROR("couldn't read status");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (status & 0x1) if (status & 0x1) {
{
LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x", LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x",
(nand->blocks[i].is_bad == 1) (nand->blocks[i].is_bad == 1)
? "bad " : "", ? "bad " : "",
@ -621,23 +577,24 @@ int nand_erase(struct nand_device *nand, int first_block, int last_block)
} }
#if 0 #if 0
static int nand_read_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size) static int nand_read_plain(struct nand_device *nand,
uint32_t address,
uint8_t *data,
uint32_t data_size)
{ {
uint8_t *page; uint8_t *page;
if (!nand->device) if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED; return ERROR_NAND_DEVICE_NOT_PROBED;
if (address % nand->page_size) if (address % nand->page_size) {
{
LOG_ERROR("reads need to be page aligned"); LOG_ERROR("reads need to be page aligned");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
page = malloc(nand->page_size); page = malloc(nand->page_size);
while (data_size > 0) while (data_size > 0) {
{
uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size; uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size;
uint32_t page_address; uint32_t page_address;
@ -658,23 +615,24 @@ static int nand_read_plain(struct nand_device *nand, uint32_t address, uint8_t *
return ERROR_OK; return ERROR_OK;
} }
static int nand_write_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size) static int nand_write_plain(struct nand_device *nand,
uint32_t address,
uint8_t *data,
uint32_t data_size)
{ {
uint8_t *page; uint8_t *page;
if (!nand->device) if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED; return ERROR_NAND_DEVICE_NOT_PROBED;
if (address % nand->page_size) if (address % nand->page_size) {
{
LOG_ERROR("writes need to be page aligned"); LOG_ERROR("writes need to be page aligned");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
page = malloc(nand->page_size); page = malloc(nand->page_size);
while (data_size > 0) while (data_size > 0) {
{
uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size; uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size;
uint32_t page_address; uint32_t page_address;
@ -918,4 +876,3 @@ int nand_write_page_raw(struct nand_device *nand, uint32_t page,
return nand_write_finish(nand); return nand_write_finish(nand);
} }

View File

@ -22,6 +22,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NAND_CORE_H #ifndef FLASH_NAND_CORE_H
#define FLASH_NAND_CORE_H #define FLASH_NAND_CORE_H
@ -30,8 +31,7 @@
/** /**
* Representation of a single NAND block in a NAND device. * Representation of a single NAND block in a NAND device.
*/ */
struct nand_block struct nand_block {
{
/** Offset to the block. */ /** Offset to the block. */
uint32_t offset; uint32_t offset;
@ -57,8 +57,7 @@ struct nand_ecclayout {
struct nand_oobfree oobfree[2]; struct nand_oobfree oobfree[2];
}; };
struct nand_device struct nand_device {
{
const char *name; const char *name;
struct target *target; struct target *target;
struct nand_flash_controller *controller; struct nand_flash_controller *controller;
@ -77,8 +76,7 @@ struct nand_device
/* NAND Flash Manufacturer ID Codes /* NAND Flash Manufacturer ID Codes
*/ */
enum enum {
{
NAND_MFR_TOSHIBA = 0x98, NAND_MFR_TOSHIBA = 0x98,
NAND_MFR_SAMSUNG = 0xec, NAND_MFR_SAMSUNG = 0xec,
NAND_MFR_FUJITSU = 0x04, NAND_MFR_FUJITSU = 0x04,
@ -89,14 +87,12 @@ enum
NAND_MFR_MICRON = 0x2c, NAND_MFR_MICRON = 0x2c,
}; };
struct nand_manufacturer struct nand_manufacturer {
{
int id; int id;
const char *name; const char *name;
}; };
struct nand_info struct nand_info {
{
int mfr_id; int mfr_id;
int id; int id;
int page_size; int page_size;
@ -152,8 +148,7 @@ enum {
LP_OPTIONS16 = (LP_OPTIONS | NAND_BUSWIDTH_16), LP_OPTIONS16 = (LP_OPTIONS | NAND_BUSWIDTH_16),
}; };
enum enum {
{
/* Standard NAND flash commands */ /* Standard NAND flash commands */
NAND_CMD_READ0 = 0x0, NAND_CMD_READ0 = 0x0,
NAND_CMD_READ1 = 0x1, NAND_CMD_READ1 = 0x1,
@ -176,8 +171,7 @@ enum
}; };
/* Status bits */ /* Status bits */
enum enum {
{
NAND_STATUS_FAIL = 0x01, NAND_STATUS_FAIL = 0x01,
NAND_STATUS_FAIL_N1 = 0x02, NAND_STATUS_FAIL_N1 = 0x02,
NAND_STATUS_TRUE_READY = 0x20, NAND_STATUS_TRUE_READY = 0x20,
@ -186,10 +180,10 @@ enum
}; };
/* OOB (spare) data formats */ /* OOB (spare) data formats */
enum oob_formats enum oob_formats {
{
NAND_OOB_NONE = 0x0, /* no OOB data at all */ NAND_OOB_NONE = 0x0, /* no OOB data at all */
NAND_OOB_RAW = 0x1, /* raw OOB data (16 bytes for 512b page sizes, 64 bytes for 2048b page sizes) */ NAND_OOB_RAW = 0x1, /* raw OOB data (16 bytes for 512b page sizes, 64 bytes for
*2048b page sizes) */
NAND_OOB_ONLY = 0x2, /* only OOB data */ NAND_OOB_ONLY = 0x2, /* only OOB data */
NAND_OOB_SW_ECC = 0x10, /* when writing, use SW ECC (as opposed to no ECC) */ NAND_OOB_SW_ECC = 0x10, /* when writing, use SW ECC (as opposed to no ECC) */
NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no ECC) */ NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no ECC) */
@ -224,7 +218,7 @@ int nand_calculate_ecc_kw(struct nand_device *nand,
int nand_register_commands(struct command_context *cmd_ctx); int nand_register_commands(struct command_context *cmd_ctx);
/// helper for parsing a nand device command argument string /* / helper for parsing a nand device command argument string */
COMMAND_HELPER(nand_command_get_device, unsigned name_index, COMMAND_HELPER(nand_command_get_device, unsigned name_index,
struct nand_device **nand); struct nand_device **nand);
@ -237,5 +231,4 @@ COMMAND_HELPER(nand_command_get_device, unsigned name_index,
#define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105) #define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105)
#define ERROR_NAND_NO_BUFFER (-1106) #define ERROR_NAND_NO_BUFFER (-1106)
#endif // FLASH_NAND_CORE_H #endif /* FLASH_NAND_CORE_H */

View File

@ -688,9 +688,8 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
* - aemif address * - aemif address
* Plus someday, optionally, ALE and CLE masks. * Plus someday, optionally, ALE and CLE masks.
*/ */
if (CMD_ARGC < 5) { if (CMD_ARGC < 5)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip); COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
if (chip == 0) { if (chip == 0) {

View File

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

View File

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

View File

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

View File

@ -102,7 +102,7 @@ int nand_calculate_ecc_kw(struct nand_device *nand, const uint8_t *data, uint8_t
{ {
unsigned int r7, r6, r5, r4, r3, r2, r1, r0; unsigned int r7, r6, r5, r4, r3, r2, r1, r0;
int i; int i;
static int tables_initialized = 0; static int tables_initialized;
if (!tables_initialized) { if (!tables_initialized) {
gf_build_log_exp_table(); gf_build_log_exp_table();
@ -121,7 +121,6 @@ int nand_calculate_ecc_kw(struct nand_device *nand, const uint8_t *data, uint8_t
r6 = data[510]; r6 = data[510];
r7 = data[511]; r7 = data[511];
/* /*
* Shift bytes 503..0 (in that order) into r0, followed * Shift bytes 503..0 (in that order) into r0, followed
* by eight zero bytes, while reducing the polynomial by the * by eight zero bytes, while reducing the polynomial by the

View File

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

View File

@ -16,6 +16,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef FLASH_NAND_FILEIO_H #ifndef FLASH_NAND_FILEIO_H
#define FLASH_NAND_FILEIO_H #define FLASH_NAND_FILEIO_H
@ -54,4 +55,4 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s); int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s);
#endif // FLASH_NAND_FILEIO_H #endif /* FLASH_NAND_FILEIO_H */

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -25,6 +25,7 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -74,9 +75,8 @@ static dmac_ll_t dmalist[(2048/256) * 2 + 1];
*/ */
NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command) NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command)
{ {
if (CMD_ARGC < 3) { if (CMD_ARGC < 3)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
uint32_t osc_freq; uint32_t osc_freq;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
@ -160,9 +160,9 @@ static float lpc32xx_cycle_time(struct nand_device *nand)
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if ((pwr_ctrl & (1 << 2)) == 0) { /* DIRECT RUN mode */ if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
hclk = sysclk; hclk = sysclk;
} else { else {
retval = target_read_u32(target, 0x40004058, &hclkpll_ctrl); retval = target_read_u32(target, 0x40004058, &hclkpll_ctrl);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not read HCLKPLL_CTRL"); LOG_ERROR("could not read HCLKPLL_CTRL");
@ -427,8 +427,7 @@ static int lpc32xx_reset(struct nand_device *nand)
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (!lpc32xx_controller_ready(nand, 100)) if (!lpc32xx_controller_ready(nand, 100)) {
{
LOG_ERROR("LPC32xx SLC NAND controller timed out " LOG_ERROR("LPC32xx SLC NAND controller timed out "
"after reset"); "after reset");
return ERROR_NAND_OPERATION_TIMEOUT; return ERROR_NAND_OPERATION_TIMEOUT;
@ -729,7 +728,8 @@ static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if ((retval = nand_read_status(nand, &status)) != ERROR_OK) { retval = nand_read_status(nand, &status);
if (retval != ERROR_OK) {
LOG_ERROR("couldn't read status"); LOG_ERROR("couldn't read status");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -827,12 +827,12 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
| 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24 | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
| 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31; | 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31;
if (do_read) { if (do_read) {
ctrl |= 1 << 27; /* Destination increment = 1 */ ctrl |= 1 << 27;/* Destination increment = 1 */
oob_ctrl |= 1 << 27; /* Destination increment = 1 */ oob_ctrl |= 1 << 27; /* Destination increment = 1 */
dmasrc = 0x20020038; /* SLC_DMA_DATA */ dmasrc = 0x20020038; /* SLC_DMA_DATA */
dmadst = target_mem_base + DATA_OFFS; dmadst = target_mem_base + DATA_OFFS;
} else { } else {
ctrl |= 1 << 26; /* Source increment = 1 */ ctrl |= 1 << 26;/* Source increment = 1 */
oob_ctrl |= 1 << 26; /* Source increment = 1 */ oob_ctrl |= 1 << 26; /* Source increment = 1 */
dmasrc = target_mem_base + DATA_OFFS; dmasrc = target_mem_base + DATA_OFFS;
dmadst = 0x20020038; /* SLC_DMA_DATA */ dmadst = 0x20020038; /* SLC_DMA_DATA */
@ -865,15 +865,14 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
* data & 32 bytes of ECC data. * data & 32 bytes of ECC data.
* 2. X'fer 64 bytes of Spare area from Flash to Memory. * 2. X'fer 64 bytes of Spare area from Flash to Memory.
*/ */
for (i = 0; i < page_size/0x100; i++) for (i = 0; i < page_size/0x100; i++) {
{
dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256)); dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256));
dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst); dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst);
dmalist[i*2].next_lli = dmalist[i*2].next_lli =
target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t); target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t);
dmalist[i*2].next_ctrl = ctrl; dmalist[i*2].next_ctrl = ctrl;
dmalist[(i*2) + 1].dma_src = 0x20020034; /* SLC_ECC */ dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */
dmalist[(i*2) + 1].dma_dest = dmalist[(i*2) + 1].dma_dest =
target_mem_base + ECC_OFFS + i * 4; target_mem_base + ECC_OFFS + i * 4;
dmalist[(i*2) + 1].next_lli = dmalist[(i*2) + 1].next_lli =
@ -882,11 +881,10 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
} }
if (do_read) if (do_read)
{
dmadst = target_mem_base + SPARE_OFFS; dmadst = target_mem_base + SPARE_OFFS;
} else { else {
dmasrc = target_mem_base + SPARE_OFFS; dmasrc = target_mem_base + SPARE_OFFS;
dmalist[(i*2) - 1].next_lli = 0; /* last link = null on write */ dmalist[(i*2) - 1].next_lli = 0;/* last link = null on write */
dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */ dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */
} }
dmalist[i*2].dma_src = dmasrc; dmalist[i*2].dma_src = dmasrc;
@ -894,7 +892,7 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
dmalist[i*2].next_lli = 0; dmalist[i*2].next_lli = 0;
dmalist[i*2].next_ctrl = oob_ctrl; dmalist[i*2].next_ctrl = oob_ctrl;
return (i*2 + 1); /* Number of descriptors */ return i * 2 + 1; /* Number of descriptors */
} }
static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count, static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count,
@ -995,10 +993,9 @@ static int lpc32xx_dma_ready(struct nand_device *nand, int timeout)
LOG_ERROR("lpc32xx_dma_ready " LOG_ERROR("lpc32xx_dma_ready "
"DMA error, aborted"); "DMA error, aborted");
return 0; return 0;
} else { } else
return 1; return 1;
} }
}
alive_sleep(1); alive_sleep(1);
} while (timeout-- > 0); } while (timeout-- > 0);
@ -1006,8 +1003,8 @@ static int lpc32xx_dma_ready(struct nand_device *nand, int timeout)
return 0; return 0;
} }
static uint32_t slc_ecc_copy_to_buffer(uint8_t * spare, static uint32_t slc_ecc_copy_to_buffer(uint8_t *spare,
const uint32_t * ecc, int count) const uint32_t *ecc, int count)
{ {
int i; int i;
for (i = 0; i < (count * 3); i += 3) { for (i = 0; i < (count * 3); i += 3) {
@ -1136,9 +1133,9 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
static uint8_t foob[64]; static uint8_t foob[64];
int foob_size = nand->page_size == 2048 ? 64 : 16; int foob_size = nand->page_size == 2048 ? 64 : 16;
memset(foob, 0xFF, foob_size); memset(foob, 0xFF, foob_size);
if (oob) { /* Raw mode */ if (oob) /* Raw mode */
memcpy(foob, oob, oob_size); memcpy(foob, oob, oob_size);
} else { else {
/* Get HW generated ECC, made while writing data */ /* Get HW generated ECC, made while writing data */
int ecc_count = nand->page_size == 2048 ? 8 : 2; int ecc_count = nand->page_size == 2048 ? 8 : 2;
static uint32_t hw_ecc[8]; static uint32_t hw_ecc[8];
@ -1183,14 +1180,14 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
return retval; return retval;
} }
/* DMACCxConfig= /* DMACCxConfig=
E=1, * E=1,
SrcPeripheral = 1 (SLC), * SrcPeripheral = 1 (SLC),
DestPeripheral = 1 (SLC), * DestPeripheral = 1 (SLC),
FlowCntrl = 2 (Pher -> Mem, DMA), * FlowCntrl = 2 (Pher -> Mem, DMA),
IE = 0, * IE = 0,
ITC = 0, * ITC = 0,
L= 0, * L= 0,
H=0 * H=0
*/ */
retval = target_write_u32(target, 0x31000110, retval = target_write_u32(target, 0x31000110,
1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
@ -1317,8 +1314,8 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (nand->page_size == 512) { if (nand->page_size == 512) {
/* small page device */ /* small page device
/* MLC_ADDR = 0x0 (one column cycle) */ * MLC_ADDR = 0x0 (one column cycle) */
retval = target_write_u32(target, 0x200b8004, 0x0); retval = target_write_u32(target, 0x200b8004, 0x0);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
@ -1347,8 +1344,8 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
} }
} }
} else { } else {
/* large page device */ /* large page device
/* MLC_ADDR = 0x0 (two column cycles) */ * MLC_ADDR = 0x0 (two column cycles) */
retval = target_write_u32(target, 0x200b8004, 0x0); retval = target_write_u32(target, 0x200b8004, 0x0);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR"); LOG_ERROR("could not set MLC_ADDR");
@ -1551,7 +1548,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
static uint8_t ecc[24]; static uint8_t ecc[24];
slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count); slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count);
/* Copy ECC from flash using correct layout */ /* Copy ECC from flash using correct layout */
static uint8_t fecc[24]; /* max size */ static uint8_t fecc[24];/* max size */
int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout; int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout;
int i; int i;
for (i = 0; i < ecc_count * 3; i++) for (i = 0; i < ecc_count * 3; i++)
@ -1740,7 +1737,7 @@ static int lpc32xx_tc_ready(struct nand_device *nand, int timeout)
LOG_ERROR("Could not read SLC_INT_STAT"); LOG_ERROR("Could not read SLC_INT_STAT");
return 0; return 0;
} }
if (status & 2){ if (status & 2) {
LOG_DEBUG("lpc32xx_tc_ready count=%d", timeout); LOG_DEBUG("lpc32xx_tc_ready count=%d", timeout);
return 1; return 1;
} }
@ -1758,9 +1755,8 @@ COMMAND_HANDLER(handle_lpc32xx_select_command)
"no", "mlc", "slc" "no", "mlc", "slc"
}; };
if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) { if ((CMD_ARGC < 1) || (CMD_ARGC > 3))
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
unsigned num; unsigned num;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
@ -1780,10 +1776,9 @@ COMMAND_HANDLER(handle_lpc32xx_select_command)
} else if (strcmp(CMD_ARGV[1], "slc") == 0) { } else if (strcmp(CMD_ARGV[1], "slc") == 0) {
lpc32xx_info->selected_controller = lpc32xx_info->selected_controller =
LPC32xx_SLC_CONTROLLER; LPC32xx_SLC_CONTROLLER;
} else { } else
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
}
command_print(CMD_CTX, "%s controller selected", command_print(CMD_CTX, "%s controller selected",
selected[lpc32xx_info->selected_controller]); selected[lpc32xx_info->selected_controller]);

View File

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

View File

@ -49,50 +49,43 @@ static const char get_status_register_err_msg[] = "can't get NAND status";
static uint32_t in_sram_address; static uint32_t in_sram_address;
static unsigned char sign_of_sequental_byte_read; static unsigned char sign_of_sequental_byte_read;
static int test_iomux_settings (struct target * target, uint32_t value, static int test_iomux_settings(struct target *target, uint32_t value,
uint32_t mask, const char *text); uint32_t mask, const char *text);
static int initialize_nf_controller (struct nand_device *nand); static int initialize_nf_controller(struct nand_device *nand);
static int get_next_byte_from_sram_buffer (struct target * target, uint8_t * value); static int get_next_byte_from_sram_buffer(struct target *target, uint8_t *value);
static int get_next_halfword_from_sram_buffer (struct target * target, static int get_next_halfword_from_sram_buffer(struct target *target,
uint16_t * value); uint16_t *value);
static int poll_for_complete_op (struct target * target, const char *text); static int poll_for_complete_op(struct target *target, const char *text);
static int validate_target_state (struct nand_device *nand); static int validate_target_state(struct nand_device *nand);
static int do_data_output (struct nand_device *nand); static int do_data_output(struct nand_device *nand);
static int imx31_command (struct nand_device *nand, uint8_t command); static int imx31_command(struct nand_device *nand, uint8_t command);
static int imx31_address (struct nand_device *nand, uint8_t address); static int imx31_address(struct nand_device *nand, uint8_t address);
NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command) NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
{ {
struct mx3_nf_controller *mx3_nf_info; struct mx3_nf_controller *mx3_nf_info;
mx3_nf_info = malloc (sizeof (struct mx3_nf_controller)); mx3_nf_info = malloc(sizeof(struct mx3_nf_controller));
if (mx3_nf_info == NULL) if (mx3_nf_info == NULL) {
{ LOG_ERROR("no memory for nand controller");
LOG_ERROR ("no memory for nand controller");
return ERROR_FAIL; return ERROR_FAIL;
} }
nand->controller_priv = mx3_nf_info; nand->controller_priv = mx3_nf_info;
if (CMD_ARGC < 3) if (CMD_ARGC < 3)
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
/* /*
* check hwecc requirements * check hwecc requirements
*/ */
{ {
int hwecc_needed; int hwecc_needed;
hwecc_needed = strcmp (CMD_ARGV[2], "hwecc"); hwecc_needed = strcmp(CMD_ARGV[2], "hwecc");
if (hwecc_needed == 0) if (hwecc_needed == 0)
{
mx3_nf_info->flags.hw_ecc_enabled = 1; mx3_nf_info->flags.hw_ecc_enabled = 1;
}
else else
{
mx3_nf_info->flags.hw_ecc_enabled = 0; mx3_nf_info->flags.hw_ecc_enabled = 0;
} }
}
mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE; mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
mx3_nf_info->fin = MX3_NF_FIN_NONE; mx3_nf_info->fin = MX3_NF_FIN_NONE;
@ -104,18 +97,14 @@ NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
{ {
int x = 1; int x = 1;
if (*(char *) &x == 1) if (*(char *) &x == 1)
{
mx3_nf_info->flags.host_little_endian = 1; mx3_nf_info->flags.host_little_endian = 1;
}
else else
{
mx3_nf_info->flags.host_little_endian = 0; mx3_nf_info->flags.host_little_endian = 0;
} }
}
return ERROR_OK; return ERROR_OK;
} }
static int imx31_init (struct nand_device *nand) static int imx31_init(struct nand_device *nand)
{ {
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -127,66 +116,51 @@ static int imx31_init (struct nand_device *nand)
int validate_target_result; int validate_target_result;
validate_target_result = validate_target_state(nand); validate_target_result = validate_target_state(nand);
if (validate_target_result != ERROR_OK) if (validate_target_result != ERROR_OK)
{
return validate_target_result; return validate_target_result;
} }
}
{ {
uint16_t buffsize_register_content; uint16_t buffsize_register_content;
target_read_u16 (target, MX3_NF_BUFSIZ, &buffsize_register_content); target_read_u16(target, MX3_NF_BUFSIZ, &buffsize_register_content);
mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f); mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
} }
{ {
uint32_t pcsr_register_content; uint32_t pcsr_register_content;
target_read_u32 (target, MX3_PCSR, &pcsr_register_content); target_read_u32(target, MX3_PCSR, &pcsr_register_content);
if (!nand->bus_width) if (!nand->bus_width) {
{ nand->bus_width = (pcsr_register_content & 0x80000000) ? 16 : 8;
nand->bus_width = } else {
(pcsr_register_content & 0x80000000) ? 16 : 8; pcsr_register_content |= ((nand->bus_width == 16) ? 0x80000000 : 0x00000000);
} target_write_u32(target, MX3_PCSR, pcsr_register_content);
else
{
pcsr_register_content |=
((nand->bus_width == 16) ? 0x80000000 : 0x00000000);
target_write_u32 (target, MX3_PCSR, pcsr_register_content);
} }
if (!nand->page_size) if (!nand->page_size) {
{ nand->page_size = (pcsr_register_content & 0x40000000) ? 2048 : 512;
nand->page_size = } else {
(pcsr_register_content & 0x40000000) ? 2048 : 512; pcsr_register_content |= ((nand->page_size == 2048) ? 0x40000000 : 0x00000000);
target_write_u32(target, MX3_PCSR, pcsr_register_content);
} }
else if (mx3_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) {
{ LOG_ERROR("NAND controller have only 1 kb SRAM, "
pcsr_register_content |= "so pagesize 2048 is incompatible with it");
((nand->page_size == 2048) ? 0x40000000 : 0x00000000);
target_write_u32 (target, MX3_PCSR, pcsr_register_content);
}
if (mx3_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");
} }
} }
{ {
uint32_t cgr_register_content; uint32_t cgr_register_content;
target_read_u32 (target, MX3_CCM_CGR2, &cgr_register_content); target_read_u32(target, MX3_CCM_CGR2, &cgr_register_content);
if (!(cgr_register_content & 0x00000300)) if (!(cgr_register_content & 0x00000300)) {
{ LOG_ERROR("clock gating to EMI disabled");
LOG_ERROR ("clock gating to EMI disabled");
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
{ {
uint32_t gpr_register_content; uint32_t gpr_register_content;
target_read_u32 (target, MX3_GPR, &gpr_register_content); target_read_u32(target, MX3_GPR, &gpr_register_content);
if (gpr_register_content & 0x00000060) if (gpr_register_content & 0x00000060) {
{ LOG_ERROR("pins mode overrided by GPR");
LOG_ERROR ("pins mode overrided by GPR");
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
@ -198,67 +172,48 @@ static int imx31_init (struct nand_device *nand)
*/ */
int test_iomux; int test_iomux;
test_iomux = ERROR_OK; test_iomux = ERROR_OK;
test_iomux |= test_iomux |= test_iomux_settings(target, 0x43fac0c0, 0x7f7f7f00, "d0,d1,d2");
test_iomux_settings (target, 0x43fac0c0, 0x7f7f7f00, "d0,d1,d2"); test_iomux |= test_iomux_settings(target, 0x43fac0c4, 0x7f7f7f7f, "d3,d4,d5,d6");
test_iomux |= test_iomux |= test_iomux_settings(target, 0x43fac0c8, 0x0000007f, "d7");
test_iomux_settings (target, 0x43fac0c4, 0x7f7f7f7f, "d3,d4,d5,d6"); if (nand->bus_width == 16) {
test_iomux |= test_iomux |= test_iomux_settings(target, 0x43fac0c8, 0x7f7f7f00, "d8,d9,d10");
test_iomux_settings (target, 0x43fac0c8, 0x0000007f, "d7"); test_iomux |= test_iomux_settings(target, 0x43fac0cc, 0x7f7f7f7f, "d11,d12,d13,d14");
if (nand->bus_width == 16) test_iomux |= test_iomux_settings(target, 0x43fac0d0, 0x0000007f, "d15");
{
test_iomux |=
test_iomux_settings (target, 0x43fac0c8, 0x7f7f7f00,
"d8,d9,d10");
test_iomux |=
test_iomux_settings (target, 0x43fac0cc, 0x7f7f7f7f,
"d11,d12,d13,d14");
test_iomux |=
test_iomux_settings (target, 0x43fac0d0, 0x0000007f, "d15");
} }
test_iomux |= test_iomux |= test_iomux_settings(target, 0x43fac0d0, 0x7f7f7f00, "nfwp,nfce,nfrb");
test_iomux_settings (target, 0x43fac0d0, 0x7f7f7f00, test_iomux |= test_iomux_settings(target, 0x43fac0d4, 0x7f7f7f7f,
"nfwp,nfce,nfrb");
test_iomux |=
test_iomux_settings (target, 0x43fac0d4, 0x7f7f7f7f,
"nfwe,nfre,nfale,nfcle"); "nfwe,nfre,nfale,nfcle");
if (test_iomux != ERROR_OK) if (test_iomux != ERROR_OK)
{
return ERROR_FAIL; return ERROR_FAIL;
} }
}
initialize_nf_controller (nand); initialize_nf_controller(nand);
{ {
int retval; int retval;
uint16_t nand_status_content; uint16_t nand_status_content;
retval = ERROR_OK; retval = ERROR_OK;
retval |= imx31_command (nand, NAND_CMD_STATUS); retval |= imx31_command(nand, NAND_CMD_STATUS);
retval |= imx31_address (nand, 0x00); retval |= imx31_address(nand, 0x00);
retval |= do_data_output (nand); retval |= do_data_output(nand);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{ LOG_ERROR(get_status_register_err_msg);
LOG_ERROR (get_status_register_err_msg);
return ERROR_FAIL; return ERROR_FAIL;
} }
target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content); target_read_u16(target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
if (!(nand_status_content & 0x0080)) if (!(nand_status_content & 0x0080)) {
{
/* /*
* is host-big-endian correctly ?? * is host-big-endian correctly ??
*/ */
LOG_INFO ("NAND read-only"); LOG_INFO("NAND read-only");
mx3_nf_info->flags.nand_readonly = 1; mx3_nf_info->flags.nand_readonly = 1;
} } else
else
{
mx3_nf_info->flags.nand_readonly = 0; mx3_nf_info->flags.nand_readonly = 0;
} }
}
return ERROR_OK; return ERROR_OK;
} }
static int imx31_read_data (struct nand_device *nand, void *data) static int imx31_read_data(struct nand_device *nand, void *data)
{ {
struct target *target = nand->target; struct target *target = nand->target;
{ {
@ -266,59 +221,49 @@ static int imx31_read_data (struct nand_device *nand, void *data)
* validate target state * validate target state
*/ */
int validate_target_result; int validate_target_result;
validate_target_result = validate_target_state (nand); validate_target_result = validate_target_state(nand);
if (validate_target_result != ERROR_OK) if (validate_target_result != ERROR_OK)
{
return validate_target_result; return validate_target_result;
} }
}
{ {
/* /*
* get data from nand chip * get data from nand chip
*/ */
int try_data_output_from_nand_chip; int try_data_output_from_nand_chip;
try_data_output_from_nand_chip = do_data_output (nand); try_data_output_from_nand_chip = do_data_output(nand);
if (try_data_output_from_nand_chip != ERROR_OK) if (try_data_output_from_nand_chip != ERROR_OK)
{
return try_data_output_from_nand_chip; return try_data_output_from_nand_chip;
} }
}
if (nand->bus_width == 16) if (nand->bus_width == 16)
{ get_next_halfword_from_sram_buffer(target, data);
get_next_halfword_from_sram_buffer (target, data);
}
else else
{ get_next_byte_from_sram_buffer(target, data);
get_next_byte_from_sram_buffer (target, data);
}
return ERROR_OK; return ERROR_OK;
} }
static int imx31_write_data (struct nand_device *nand, uint16_t data) static int imx31_write_data(struct nand_device *nand, uint16_t data)
{ {
LOG_ERROR ("write_data() not implemented"); LOG_ERROR("write_data() not implemented");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
static int imx31_reset (struct nand_device *nand) static int imx31_reset(struct nand_device *nand)
{ {
/* /*
* validate target state * validate target state
*/ */
int validate_target_result; int validate_target_result;
validate_target_result = validate_target_state (nand); validate_target_result = validate_target_state(nand);
if (validate_target_result != ERROR_OK) if (validate_target_result != ERROR_OK)
{
return validate_target_result; return validate_target_result;
} initialize_nf_controller(nand);
initialize_nf_controller (nand);
return ERROR_OK; return ERROR_OK;
} }
static int imx31_command (struct nand_device *nand, uint8_t command) static int imx31_command(struct nand_device *nand, uint8_t command)
{ {
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
@ -327,15 +272,12 @@ static int imx31_command (struct nand_device *nand, uint8_t command)
* validate target state * validate target state
*/ */
int validate_target_result; int validate_target_result;
validate_target_result = validate_target_state (nand); validate_target_result = validate_target_state(nand);
if (validate_target_result != ERROR_OK) if (validate_target_result != ERROR_OK)
{
return validate_target_result; return validate_target_result;
} }
}
switch (command) switch (command) {
{
case NAND_CMD_READOOB: case NAND_CMD_READOOB:
command = NAND_CMD_READ0; command = NAND_CMD_READ0;
in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
@ -349,31 +291,27 @@ static int imx31_command (struct nand_device *nand, uint8_t command)
/* /*
* offset == one half of page size * offset == one half of page size
*/ */
in_sram_address = in_sram_address = MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
default: default:
in_sram_address = MX3_NF_MAIN_BUFFER0; in_sram_address = MX3_NF_MAIN_BUFFER0;
} }
target_write_u16 (target, MX3_NF_FCMD, command); target_write_u16(target, MX3_NF_FCMD, command);
/* /*
* start command input operation (set MX3_NF_BIT_OP_DONE==0) * start command input operation (set MX3_NF_BIT_OP_DONE==0)
*/ */
target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FCI); target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FCI);
{ {
int poll_result; int poll_result;
poll_result = poll_for_complete_op (target, "command"); poll_result = poll_for_complete_op(target, "command");
if (poll_result != ERROR_OK) if (poll_result != ERROR_OK)
{
return poll_result; return poll_result;
} }
}
/* /*
* reset cursor to begin of the buffer * reset cursor to begin of the buffer
*/ */
sign_of_sequental_byte_read = 0; sign_of_sequental_byte_read = 0;
switch (command) switch (command) {
{
case NAND_CMD_READID: case NAND_CMD_READID:
mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID; mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
mx3_nf_info->fin = MX3_NF_FIN_DATAOUT; mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
@ -392,7 +330,7 @@ static int imx31_command (struct nand_device *nand, uint8_t command)
return ERROR_OK; return ERROR_OK;
} }
static int imx31_address (struct nand_device *nand, uint8_t address) static int imx31_address(struct nand_device *nand, uint8_t address)
{ {
struct target *target = nand->target; struct target *target = nand->target;
{ {
@ -400,30 +338,26 @@ static int imx31_address (struct nand_device *nand, uint8_t address)
* validate target state * validate target state
*/ */
int validate_target_result; int validate_target_result;
validate_target_result = validate_target_state (nand); validate_target_result = validate_target_state(nand);
if (validate_target_result != ERROR_OK) if (validate_target_result != ERROR_OK)
{
return validate_target_result; return validate_target_result;
} }
}
target_write_u16 (target, MX3_NF_FADDR, address); target_write_u16(target, MX3_NF_FADDR, address);
/* /*
* start address input operation (set MX3_NF_BIT_OP_DONE==0) * start address input operation (set MX3_NF_BIT_OP_DONE==0)
*/ */
target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FAI); target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FAI);
{ {
int poll_result; int poll_result;
poll_result = poll_for_complete_op (target, "address"); poll_result = poll_for_complete_op(target, "address");
if (poll_result != ERROR_OK) if (poll_result != ERROR_OK)
{
return poll_result; return poll_result;
} }
}
return ERROR_OK; return ERROR_OK;
} }
static int imx31_nand_ready (struct nand_device *nand, int tout) static int imx31_nand_ready(struct nand_device *nand, int tout)
{ {
uint16_t poll_complete_status; uint16_t poll_complete_status;
struct target *target = nand->target; struct target *target = nand->target;
@ -433,46 +367,37 @@ static int imx31_nand_ready (struct nand_device *nand, int tout)
* validate target state * validate target state
*/ */
int validate_target_result; int validate_target_result;
validate_target_result = validate_target_state (nand); validate_target_result = validate_target_state(nand);
if (validate_target_result != ERROR_OK) if (validate_target_result != ERROR_OK)
{
return validate_target_result; return validate_target_result;
} }
}
do do {
{ target_read_u16(target, MX3_NF_CFG2, &poll_complete_status);
target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
if (poll_complete_status & MX3_NF_BIT_OP_DONE) if (poll_complete_status & MX3_NF_BIT_OP_DONE)
{
return tout; return tout;
} alive_sleep(1);
alive_sleep (1); } while (tout-- > 0);
}
while (tout-- > 0);
return tout; return tout;
} }
static int imx31_write_page (struct nand_device *nand, uint32_t page, static int imx31_write_page(struct nand_device *nand, uint32_t page,
uint8_t * data, uint32_t data_size, uint8_t * oob, uint8_t *data, uint32_t data_size, uint8_t *oob,
uint32_t oob_size) uint32_t oob_size)
{ {
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
if (data_size % 2) if (data_size % 2) {
{ LOG_ERROR(data_block_size_err_msg, data_size);
LOG_ERROR (data_block_size_err_msg, data_size);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (oob_size % 2) if (oob_size % 2) {
{ LOG_ERROR(data_block_size_err_msg, oob_size);
LOG_ERROR (data_block_size_err_msg, oob_size);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (!data) if (!data) {
{ LOG_ERROR("nothing to program");
LOG_ERROR ("nothing to program");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
{ {
@ -480,58 +405,45 @@ static int imx31_write_page (struct nand_device *nand, uint32_t page,
* validate target state * validate target state
*/ */
int retval; int retval;
retval = validate_target_state (nand); retval = validate_target_state(nand);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
} }
}
{ {
int retval = ERROR_OK; int retval = ERROR_OK;
retval |= imx31_command(nand, NAND_CMD_SEQIN); retval |= imx31_command(nand, NAND_CMD_SEQIN);
retval |= imx31_address(nand, 0x00); retval |= imx31_address(nand, 0x00);
retval |= imx31_address(nand, page & 0xff); retval |= imx31_address(nand, page & 0xff);
retval |= imx31_address(nand, (page >> 8) & 0xff); retval |= imx31_address(nand, (page >> 8) & 0xff);
if (nand->address_cycles >= 4) if (nand->address_cycles >= 4) {
{ retval |= imx31_address(nand, (page >> 16) & 0xff);
retval |= imx31_address (nand, (page >> 16) & 0xff);
if (nand->address_cycles >= 5) if (nand->address_cycles >= 5)
{ retval |= imx31_address(nand, (page >> 24) & 0xff);
retval |= imx31_address (nand, (page >> 24) & 0xff);
} }
} target_write_buffer(target, MX3_NF_MAIN_BUFFER0, data_size, data);
target_write_buffer (target, MX3_NF_MAIN_BUFFER0, data_size, data); if (oob) {
if (oob) if (mx3_nf_info->flags.hw_ecc_enabled) {
{
if (mx3_nf_info->flags.hw_ecc_enabled)
{
/* /*
* part of spare block will be overrided by hardware * part of spare block will be overrided by hardware
* ECC generator * ECC generator
*/ */
LOG_DEBUG LOG_DEBUG("part of spare block will be overrided by hardware ECC generator");
("part of spare block will be overrided by hardware ECC generator");
} }
target_write_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size, target_write_buffer(target, MX3_NF_SPARE_BUFFER0, oob_size, oob);
oob);
} }
/* /*
* start data input operation (set MX3_NF_BIT_OP_DONE==0) * start data input operation (set MX3_NF_BIT_OP_DONE==0)
*/ */
target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI); target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI);
{ {
int poll_result; int poll_result;
poll_result = poll_for_complete_op (target, "data input"); poll_result = poll_for_complete_op(target, "data input");
if (poll_result != ERROR_OK) if (poll_result != ERROR_OK)
{
return poll_result; return poll_result;
} }
} retval |= imx31_command(nand, NAND_CMD_PAGEPROG);
retval |= imx31_command (nand, NAND_CMD_PAGEPROG);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
}
/* /*
* check status register * check status register
@ -542,14 +454,12 @@ static int imx31_write_page (struct nand_device *nand, uint32_t page,
retval |= imx31_command(nand, NAND_CMD_STATUS); retval |= imx31_command(nand, NAND_CMD_STATUS);
retval |= imx31_address(nand, 0x00); retval |= imx31_address(nand, 0x00);
retval |= do_data_output(nand); retval |= do_data_output(nand);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
{ LOG_ERROR(get_status_register_err_msg);
LOG_ERROR (get_status_register_err_msg);
return retval; return retval;
} }
target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content); target_read_u16(target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
if (nand_status_content & 0x0001) if (nand_status_content & 0x0001) {
{
/* /*
* is host-big-endian correctly ?? * is host-big-endian correctly ??
*/ */
@ -560,20 +470,18 @@ static int imx31_write_page (struct nand_device *nand, uint32_t page,
return ERROR_OK; return ERROR_OK;
} }
static int imx31_read_page (struct nand_device *nand, uint32_t page, static int imx31_read_page(struct nand_device *nand, uint32_t page,
uint8_t * data, uint32_t data_size, uint8_t * oob, uint8_t *data, uint32_t data_size, uint8_t *oob,
uint32_t oob_size) uint32_t oob_size)
{ {
struct target *target = nand->target; struct target *target = nand->target;
if (data_size % 2) if (data_size % 2) {
{ LOG_ERROR(data_block_size_err_msg, data_size);
LOG_ERROR (data_block_size_err_msg, data_size);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (oob_size % 2) if (oob_size % 2) {
{ LOG_ERROR(data_block_size_err_msg, oob_size);
LOG_ERROR (data_block_size_err_msg, oob_size);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
@ -584,89 +492,75 @@ static int imx31_read_page (struct nand_device *nand, uint32_t page,
int retval; int retval;
retval = validate_target_state(nand); retval = validate_target_state(nand);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
} }
}
{ {
int retval = ERROR_OK; int retval = ERROR_OK;
retval |= imx31_command(nand, NAND_CMD_READ0); retval |= imx31_command(nand, NAND_CMD_READ0);
retval |= imx31_address(nand, 0x00); retval |= imx31_address(nand, 0x00);
retval |= imx31_address(nand, page & 0xff); retval |= imx31_address(nand, page & 0xff);
retval |= imx31_address(nand, (page >> 8) & 0xff); retval |= imx31_address(nand, (page >> 8) & 0xff);
if (nand->address_cycles >= 4) if (nand->address_cycles >= 4) {
{
retval |= imx31_address(nand, (page >> 16) & 0xff); retval |= imx31_address(nand, (page >> 16) & 0xff);
if (nand->address_cycles >= 5) if (nand->address_cycles >= 5) {
{
retval |= imx31_address(nand, (page >> 24) & 0xff); retval |= imx31_address(nand, (page >> 24) & 0xff);
retval |= imx31_command(nand, NAND_CMD_READSTART); retval |= imx31_command(nand, NAND_CMD_READSTART);
} }
} }
retval |= do_data_output (nand); retval |= do_data_output(nand);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{
return retval; return retval;
}
if (data) if (data) {
{ target_read_buffer(target, MX3_NF_MAIN_BUFFER0, data_size,
target_read_buffer (target, MX3_NF_MAIN_BUFFER0, data_size,
data); data);
} }
if (oob) if (oob) {
{ target_read_buffer(target, MX3_NF_SPARE_BUFFER0, oob_size,
target_read_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
oob); oob);
} }
} }
return ERROR_OK; return ERROR_OK;
} }
static int test_iomux_settings (struct target * target, uint32_t address, static int test_iomux_settings(struct target *target, uint32_t address,
uint32_t mask, const char *text) uint32_t mask, const char *text)
{ {
uint32_t register_content; uint32_t register_content;
target_read_u32 (target, address, &register_content); target_read_u32(target, address, &register_content);
if ((register_content & mask) != (0x12121212 & mask)) if ((register_content & mask) != (0x12121212 & mask)) {
{ LOG_ERROR("IOMUX for {%s} is bad", text);
LOG_ERROR ("IOMUX for {%s} is bad", text);
return ERROR_FAIL; return ERROR_FAIL;
} }
return ERROR_OK; return ERROR_OK;
} }
static int initialize_nf_controller (struct nand_device *nand) static int initialize_nf_controller(struct nand_device *nand)
{ {
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
/* /*
* resets NAND flash controller in zero time ? I dont know. * resets NAND flash controller in zero time ? I dont know.
*/ */
target_write_u16 (target, MX3_NF_CFG1, MX3_NF_BIT_RESET_EN); target_write_u16(target, MX3_NF_CFG1, MX3_NF_BIT_RESET_EN);
{ {
uint16_t work_mode; uint16_t work_mode;
work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */ work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */
if (target->endianness == TARGET_BIG_ENDIAN) if (target->endianness == TARGET_BIG_ENDIAN)
{
work_mode |= MX3_NF_BIT_BE_EN; work_mode |= MX3_NF_BIT_BE_EN;
}
if (mx3_nf_info->flags.hw_ecc_enabled) if (mx3_nf_info->flags.hw_ecc_enabled)
{
work_mode |= MX3_NF_BIT_ECC_EN; work_mode |= MX3_NF_BIT_ECC_EN;
} target_write_u16(target, MX3_NF_CFG1, work_mode);
target_write_u16 (target, MX3_NF_CFG1, work_mode);
} }
/* /*
* unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock" * unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock"
*/ */
target_write_u16 (target, MX3_NF_BUFCFG, 2); target_write_u16(target, MX3_NF_BUFCFG, 2);
{ {
uint16_t temp; uint16_t temp;
target_read_u16 (target, MX3_NF_FWP, &temp); target_read_u16(target, MX3_NF_FWP, &temp);
if ((temp & 0x0007) == 1) if ((temp & 0x0007) == 1) {
{ LOG_ERROR("NAND flash is tight-locked, reset needed");
LOG_ERROR ("NAND flash is tight-locked, reset needed");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -674,13 +568,13 @@ static int initialize_nf_controller (struct nand_device *nand)
/* /*
* unlock NAND flash for write * unlock NAND flash for write
*/ */
target_write_u16 (target, MX3_NF_FWP, 4); target_write_u16(target, MX3_NF_FWP, 4);
target_write_u16 (target, MX3_NF_LOCKSTART, 0x0000); target_write_u16(target, MX3_NF_LOCKSTART, 0x0000);
target_write_u16 (target, MX3_NF_LOCKEND, 0xFFFF); target_write_u16(target, MX3_NF_LOCKEND, 0xFFFF);
/* /*
* 0x0000 means that first SRAM buffer @0xB800_0000 will be used * 0x0000 means that first SRAM buffer @0xB800_0000 will be used
*/ */
target_write_u16 (target, MX3_NF_BUFADDR, 0x0000); target_write_u16(target, MX3_NF_BUFADDR, 0x0000);
/* /*
* address of SRAM buffer * address of SRAM buffer
*/ */
@ -689,36 +583,28 @@ static int initialize_nf_controller (struct nand_device *nand)
return ERROR_OK; return ERROR_OK;
} }
static int get_next_byte_from_sram_buffer (struct target * target, uint8_t * value) static int get_next_byte_from_sram_buffer(struct target *target, uint8_t *value)
{ {
static uint8_t even_byte = 0; static uint8_t even_byte;
/* /*
* host-big_endian ?? * host-big_endian ??
*/ */
if (sign_of_sequental_byte_read == 0) if (sign_of_sequental_byte_read == 0)
{
even_byte = 0; even_byte = 0;
} if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) {
if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
{
LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
*value = 0; *value = 0;
sign_of_sequental_byte_read = 0; sign_of_sequental_byte_read = 0;
even_byte = 0; even_byte = 0;
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} } else {
else
{
uint16_t temp; uint16_t temp;
target_read_u16 (target, in_sram_address, &temp); target_read_u16(target, in_sram_address, &temp);
if (even_byte) if (even_byte) {
{
*value = temp >> 8; *value = temp >> 8;
even_byte = 0; even_byte = 0;
in_sram_address += 2; in_sram_address += 2;
} } else {
else
{
*value = temp & 0xff; *value = temp & 0xff;
even_byte = 1; even_byte = 1;
} }
@ -727,57 +613,48 @@ static int get_next_byte_from_sram_buffer (struct target * target, uint8_t * val
return ERROR_OK; return ERROR_OK;
} }
static int get_next_halfword_from_sram_buffer (struct target * target, static int get_next_halfword_from_sram_buffer(struct target *target,
uint16_t * value) uint16_t *value)
{ {
if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) {
{ LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
*value = 0; *value = 0;
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} } else {
else target_read_u16(target, in_sram_address, value);
{
target_read_u16 (target, in_sram_address, value);
in_sram_address += 2; in_sram_address += 2;
} }
return ERROR_OK; return ERROR_OK;
} }
static int poll_for_complete_op (struct target * target, const char *text) static int poll_for_complete_op(struct target *target, const char *text)
{ {
uint16_t poll_complete_status; uint16_t poll_complete_status;
for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++) for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++) {
{ usleep(25);
usleep (25); target_read_u16(target, MX3_NF_CFG2, &poll_complete_status);
target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
if (poll_complete_status & MX3_NF_BIT_OP_DONE) if (poll_complete_status & MX3_NF_BIT_OP_DONE)
{
break; break;
} }
} if (!(poll_complete_status & MX3_NF_BIT_OP_DONE)) {
if (!(poll_complete_status & MX3_NF_BIT_OP_DONE)) LOG_ERROR("%s sending timeout", text);
{
LOG_ERROR ("%s sending timeout", text);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
return ERROR_OK; return ERROR_OK;
} }
static int validate_target_state (struct nand_device *nand) static int validate_target_state(struct nand_device *nand)
{ {
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED) {
{ LOG_ERROR(target_not_halted_err_msg);
LOG_ERROR (target_not_halted_err_msg);
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
if (mx3_nf_info->flags.target_little_endian != if (mx3_nf_info->flags.target_little_endian !=
(target->endianness == TARGET_LITTLE_ENDIAN)) (target->endianness == TARGET_LITTLE_ENDIAN)) {
{
/* /*
* endianness changed after NAND controller probed * endianness changed after NAND controller probed
*/ */
@ -786,57 +663,46 @@ static int validate_target_state (struct nand_device *nand)
return ERROR_OK; return ERROR_OK;
} }
static int do_data_output (struct nand_device *nand) static int do_data_output(struct nand_device *nand)
{ {
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv; struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
switch (mx3_nf_info->fin) switch (mx3_nf_info->fin) {
{
case MX3_NF_FIN_DATAOUT: case MX3_NF_FIN_DATAOUT:
/* /*
* start data output operation (set MX3_NF_BIT_OP_DONE==0) * start data output operation (set MX3_NF_BIT_OP_DONE==0)
*/ */
target_write_u16 (target, MX3_NF_CFG2, target_write_u16 (target, MX3_NF_CFG2,
MX3_NF_BIT_DATAOUT_TYPE (mx3_nf_info-> MX3_NF_BIT_DATAOUT_TYPE(mx3_nf_info->optype));
optype));
{ {
int poll_result; int poll_result;
poll_result = poll_for_complete_op (target, "data output"); poll_result = poll_for_complete_op(target, "data output");
if (poll_result != ERROR_OK) if (poll_result != ERROR_OK)
{
return poll_result; return poll_result;
} }
}
mx3_nf_info->fin = MX3_NF_FIN_NONE; mx3_nf_info->fin = MX3_NF_FIN_NONE;
/* /*
* ECC stuff * ECC stuff
*/ */
if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE) if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE)
&& mx3_nf_info->flags.hw_ecc_enabled) && mx3_nf_info->flags.hw_ecc_enabled) {
{
uint16_t ecc_status; uint16_t ecc_status;
target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status); target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
switch (ecc_status & 0x000c) switch (ecc_status & 0x000c) {
{
case 1 << 2: case 1 << 2:
LOG_DEBUG LOG_DEBUG("main area readed with 1 (correctable) error");
("main area readed with 1 (correctable) error");
break; break;
case 2 << 2: case 2 << 2:
LOG_DEBUG LOG_DEBUG("main area readed with more than 1 (incorrectable) error");
("main area readed with more than 1 (incorrectable) error");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
break; break;
} }
switch (ecc_status & 0x0003) switch (ecc_status & 0x0003) {
{
case 1: case 1:
LOG_DEBUG LOG_DEBUG("spare area readed with 1 (correctable) error");
("spare area readed with 1 (correctable) error");
break; break;
case 2: case 2:
LOG_DEBUG LOG_DEBUG("main area readed with more than 1 (incorrectable) error");
("main area readed with more than 1 (incorrectable) error");
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
break; break;
} }
@ -861,4 +727,4 @@ struct nand_flash_controller imx31_nand_flash_controller = {
.write_page = &imx31_write_page, .write_page = &imx31_write_page,
.read_page = &imx31_read_page, .read_page = &imx31_read_page,
.nand_ready = &imx31_nand_ready, .nand_ready = &imx31_nand_ready,
}; };

View File

@ -1,4 +1,3 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2009 by Alexei Babich * * Copyright (C) 2009 by Alexei Babich *
* Rezonans plc., Chelyabinsk, Russia * * Rezonans plc., Chelyabinsk, Russia *
@ -39,7 +38,7 @@
#define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14) #define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14)
#define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16) #define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16)
#define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18) #define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18)
/* /*
* all bits not marked as self-clearing bit * all bits not marked as self-clearing bit
*/ */
#define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a) #define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a)
@ -69,11 +68,11 @@
/*Flash Command Input*/ /*Flash Command Input*/
#define MX3_NF_BIT_OP_FCI (1<<0) #define MX3_NF_BIT_OP_FCI (1<<0)
/* /*
* Flash Address Input * Flash Address Input
*/ */
#define MX3_NF_BIT_OP_FAI (1<<1) #define MX3_NF_BIT_OP_FAI (1<<1)
/* /*
* Flash Data Input * Flash Data Input
*/ */
#define MX3_NF_BIT_OP_FDI (1<<2) #define MX3_NF_BIT_OP_FDI (1<<2)
@ -86,20 +85,17 @@
#define MX3_GPR 0x43fac008 #define MX3_GPR 0x43fac008
#define MX3_PCSR 0x53f8000c #define MX3_PCSR 0x53f8000c
enum mx_dataout_type enum mx_dataout_type {
{
MX3_NF_DATAOUT_PAGE = 1, MX3_NF_DATAOUT_PAGE = 1,
MX3_NF_DATAOUT_NANDID = 2, MX3_NF_DATAOUT_NANDID = 2,
MX3_NF_DATAOUT_NANDSTATUS = 4, MX3_NF_DATAOUT_NANDSTATUS = 4,
}; };
enum mx_nf_finalize_action enum mx_nf_finalize_action {
{
MX3_NF_FIN_NONE, MX3_NF_FIN_NONE,
MX3_NF_FIN_DATAOUT, MX3_NF_FIN_DATAOUT,
}; };
struct mx3_nf_flags struct mx3_nf_flags {
{
unsigned host_little_endian:1; unsigned host_little_endian:1;
unsigned target_little_endian:1; unsigned target_little_endian:1;
unsigned nand_readonly:1; unsigned nand_readonly:1;
@ -107,8 +103,7 @@ struct mx3_nf_flags
unsigned hw_ecc_enabled:1; unsigned hw_ecc_enabled:1;
}; };
struct mx3_nf_controller struct mx3_nf_controller {
{
enum mx_dataout_type optype; enum mx_dataout_type optype;
enum mx_nf_finalize_action fin; enum mx_nf_finalize_action fin;
struct mx3_nf_flags flags; struct mx3_nf_flags flags;

View File

@ -190,7 +190,7 @@ COMMAND_HANDLER(handle_mxc_biswap_command)
static const struct command_registration mxc_sub_command_handlers[] = { static const struct command_registration mxc_sub_command_handlers[] = {
{ {
.name = "biswap", .name = "biswap",
.handler = handle_mxc_biswap_command , .handler = handle_mxc_biswap_command,
.help = "Turns on/off bad block information swaping from main area, " .help = "Turns on/off bad block information swaping from main area, "
"without parameter query status.", "without parameter query status.",
.usage = "bank_id ['enable'|'disable']", .usage = "bank_id ['enable'|'disable']",
@ -262,18 +262,17 @@ static int mxc_init(struct nand_device *nand)
else else
LOG_DEBUG("MXC_NF : bus is 8-bit width"); LOG_DEBUG("MXC_NF : bus is 8-bit width");
if (!nand->page_size) { if (!nand->page_size)
nand->page_size = (sreg_content & SEL_FMS) ? 2048 : 512; nand->page_size = (sreg_content & SEL_FMS) ? 2048 : 512;
} else { else {
sreg_content |= ((nand->page_size == 2048) ? SEL_FMS : 0x00000000); sreg_content |= ((nand->page_size == 2048) ? SEL_FMS : 0x00000000);
target_write_u32(target, SREG, sreg_content); target_write_u32(target, SREG, sreg_content);
} }
if (mxc_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) { if (mxc_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) {
LOG_ERROR("NAND controller have only 1 kb SRAM, so " LOG_ERROR("NAND controller have only 1 kb SRAM, so "
"pagesize 2048 is incompatible with it"); "pagesize 2048 is incompatible with it");
} else { } else
LOG_DEBUG("MXC_NF : NAND controller can handle pagesize of 2048"); LOG_DEBUG("MXC_NF : NAND controller can handle pagesize of 2048");
}
if (nfc_is_v2() && sreg_content & MX35_RCSR_NF_4K) if (nfc_is_v2() && sreg_content & MX35_RCSR_NF_4K)
LOG_ERROR("MXC driver does not have support for 4k pagesize."); LOG_ERROR("MXC driver does not have support for 4k pagesize.");
@ -292,9 +291,8 @@ static int mxc_init(struct nand_device *nand)
if (!(nand_status_content & 0x0080)) { if (!(nand_status_content & 0x0080)) {
LOG_INFO("NAND read-only"); LOG_INFO("NAND read-only");
mxc_nf_info->flags.nand_readonly = 1; mxc_nf_info->flags.nand_readonly = 1;
} else { } else
mxc_nf_info->flags.nand_readonly = 0; mxc_nf_info->flags.nand_readonly = 0;
}
return ERROR_OK; return ERROR_OK;
} }
@ -463,8 +461,7 @@ static int mxc_nand_ready(struct nand_device *nand, int tout)
return tout; return tout;
alive_sleep(1); alive_sleep(1);
} } while (tout-- > 0);
while (tout-- > 0);
return tout; return tout;
} }
@ -507,7 +504,7 @@ static int mxc_write_page(struct nand_device *nand, uint32_t page,
retval |= mxc_address(nand, 0); /* col */ retval |= mxc_address(nand, 0); /* col */
retval |= mxc_address(nand, 0); /* col */ retval |= mxc_address(nand, 0); /* col */
retval |= mxc_address(nand, page & 0xff); /* page address */ retval |= mxc_address(nand, page & 0xff); /* page address */
retval |= mxc_address(nand, (page >> 8) & 0xff); /* page address */ retval |= mxc_address(nand, (page >> 8) & 0xff);/* page address */
retval |= mxc_address(nand, (page >> 16) & 0xff); /* page address */ retval |= mxc_address(nand, (page >> 16) & 0xff); /* page address */
target_write_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data); target_write_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data);
@ -559,7 +556,7 @@ static int mxc_write_page(struct nand_device *nand, uint32_t page,
else else
bufs = 1; bufs = 1;
for (uint8_t i = 0 ; i < bufs ; ++i) { for (uint8_t i = 0; i < bufs; ++i) {
target_write_u16(target, MXC_NF_BUFADDR, i); target_write_u16(target, MXC_NF_BUFADDR, i);
target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FDI); target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FDI);
poll_result = poll_for_complete_op(nand, "data input"); poll_result = poll_for_complete_op(nand, "data input");
@ -620,31 +617,37 @@ static int mxc_read_page(struct nand_device *nand, uint32_t page,
* validate target state * validate target state
*/ */
retval = validate_target_state(nand); retval = validate_target_state(nand);
if (retval != ERROR_OK) { if (retval != ERROR_OK)
return retval; return retval;
}
/* Reset address_cycles before mxc_command ?? */ /* Reset address_cycles before mxc_command ?? */
retval = mxc_command(nand, NAND_CMD_READ0); retval = mxc_command(nand, NAND_CMD_READ0);
if (retval != ERROR_OK) return retval; if (retval != ERROR_OK)
return retval;
retval = mxc_address(nand, 0); /* col */ retval = mxc_address(nand, 0); /* col */
if (retval != ERROR_OK) return retval; if (retval != ERROR_OK)
return retval;
retval = mxc_address(nand, 0); /* col */ retval = mxc_address(nand, 0); /* col */
if (retval != ERROR_OK) return retval; if (retval != ERROR_OK)
retval = mxc_address(nand, page & 0xff); /* page address */ return retval;
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 */ retval = mxc_address(nand, (page >> 8) & 0xff); /* page address */
if (retval != ERROR_OK) return retval; if (retval != ERROR_OK)
retval = mxc_address(nand, (page >> 16) & 0xff); /* page address */ return retval;
if (retval != ERROR_OK) return retval; retval = mxc_address(nand, (page >> 16) & 0xff);/* page address */
if (retval != ERROR_OK)
return retval;
retval = mxc_command(nand, NAND_CMD_READSTART); retval = mxc_command(nand, NAND_CMD_READSTART);
if (retval != ERROR_OK) return retval; if (retval != ERROR_OK)
return retval;
if (nfc_is_v1() && nand->page_size > 512) if (nfc_is_v1() && nand->page_size > 512)
bufs = 4; bufs = 4;
else else
bufs = 1; bufs = 1;
for (uint8_t i = 0 ; i < bufs ; ++i) { for (uint8_t i = 0; i < bufs; ++i) {
target_write_u16(target, MXC_NF_BUFADDR, i); target_write_u16(target, MXC_NF_BUFADDR, i);
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT; mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
retval = do_data_output(nand); retval = do_data_output(nand);
@ -702,9 +705,9 @@ static uint32_t align_address_v2(struct nand_device *nand, uint32_t addr)
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
uint32_t ret = addr; uint32_t ret = addr;
if (addr > MXC_NF_V2_SPARE_BUFFER0 && if (addr > MXC_NF_V2_SPARE_BUFFER0 &&
(addr & 0x1F) == MXC_NF_SPARE_BUFFER_LEN) { (addr & 0x1F) == MXC_NF_SPARE_BUFFER_LEN)
ret += MXC_NF_SPARE_BUFFER_MAX - MXC_NF_SPARE_BUFFER_LEN; ret += MXC_NF_SPARE_BUFFER_MAX - MXC_NF_SPARE_BUFFER_LEN;
} else if (addr >= (mxc_nf_info->mxc_base_addr + (uint32_t)nand->page_size)) else if (addr >= (mxc_nf_info->mxc_base_addr + (uint32_t)nand->page_size))
ret = MXC_NF_V2_SPARE_BUFFER0; ret = MXC_NF_V2_SPARE_BUFFER0;
return ret; return ret;
} }
@ -725,15 +728,13 @@ static int initialize_nf_controller(struct nand_device *nand)
if (target->endianness == TARGET_BIG_ENDIAN) { if (target->endianness == TARGET_BIG_ENDIAN) {
LOG_DEBUG("MXC_NF : work in Big Endian mode"); LOG_DEBUG("MXC_NF : work in Big Endian mode");
work_mode |= MXC_NF_BIT_BE_EN; work_mode |= MXC_NF_BIT_BE_EN;
} else { } else
LOG_DEBUG("MXC_NF : work in Little Endian mode"); LOG_DEBUG("MXC_NF : work in Little Endian mode");
}
if (mxc_nf_info->flags.hw_ecc_enabled) { if (mxc_nf_info->flags.hw_ecc_enabled) {
LOG_DEBUG("MXC_NF : work with ECC mode"); LOG_DEBUG("MXC_NF : work with ECC mode");
work_mode |= MXC_NF_BIT_ECC_EN; work_mode |= MXC_NF_BIT_ECC_EN;
} else { } else
LOG_DEBUG("MXC_NF : work without ECC mode"); LOG_DEBUG("MXC_NF : work without ECC mode");
}
if (nfc_is_v2()) { if (nfc_is_v2()) {
target_write_u16(target, MXC_NF_V2_SPAS, OOB_SIZE / 2); target_write_u16(target, MXC_NF_V2_SPAS, OOB_SIZE / 2);
if (nand->page_size) { if (nand->page_size) {
@ -788,7 +789,7 @@ static int get_next_byte_from_sram_buffer(struct nand_device *nand, uint8_t *val
{ {
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
static uint8_t even_byte = 0; static uint8_t even_byte;
uint16_t temp; uint16_t temp;
/* /*
* host-big_endian ?? * host-big_endian ??
@ -796,8 +797,7 @@ static int get_next_byte_from_sram_buffer(struct nand_device *nand, uint8_t *val
if (sign_of_sequental_byte_read == 0) if (sign_of_sequental_byte_read == 0)
even_byte = 0; even_byte = 0;
if (in_sram_address > if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
(nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address); LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
*value = 0; *value = 0;
sign_of_sequental_byte_read = 0; sign_of_sequental_byte_read = 0;
@ -826,8 +826,7 @@ static int get_next_halfword_from_sram_buffer(struct nand_device *nand, uint16_t
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv; struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target; struct target *target = nand->target;
if (in_sram_address > if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
(nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address); LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
*value = 0; *value = 0;
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
@ -940,8 +939,7 @@ static int do_data_output(struct nand_device *nand)
/* /*
* ECC stuff * ECC stuff
*/ */
if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && mxc_nf_info->flags.hw_ecc_enabled) {
mxc_nf_info->flags.hw_ecc_enabled) {
int ecc_status; int ecc_status;
if (nfc_is_v1()) if (nfc_is_v1())
ecc_status = ecc_status_v1(nand); ecc_status = ecc_status_v1(nand);

View File

@ -24,7 +24,6 @@
#include "imp.h" #include "imp.h"
#include "hello.h" #include "hello.h"
static int nonce_nand_command(struct nand_device *nand, uint8_t command) static int nonce_nand_command(struct nand_device *nand, uint8_t command)
{ {
return ERROR_OK; return ERROR_OK;
@ -62,8 +61,7 @@ static int nonce_nand_init(struct nand_device *nand)
return ERROR_OK; return ERROR_OK;
} }
struct nand_flash_controller nonce_nand_controller = struct nand_flash_controller nonce_nand_controller = {
{
.name = "nonce", .name = "nonce",
.commands = hello_command_handlers, .commands = hello_command_handlers,
.nand_device_command = &nonce_nand_device_command, .nand_device_command = &nonce_nand_device_command,

View File

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

View File

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

View File

@ -115,4 +115,4 @@ struct nand_flash_controller s3c2410_nand_controller = {
.write_page = s3c24xx_write_page, .write_page = s3c24xx_write_page,
.read_page = s3c24xx_read_page, .read_page = s3c24xx_read_page,
.nand_ready = &s3c2410_nand_ready, .nand_ready = &s3c2410_nand_ready,
}; };

View File

@ -74,4 +74,4 @@ struct nand_flash_controller s3c2412_nand_controller = {
.write_block_data = &s3c2440_write_block_data, .write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data, .read_block_data = &s3c2440_read_block_data,
.nand_ready = &s3c2440_nand_ready, .nand_ready = &s3c2440_nand_ready,
}; };

View File

@ -30,7 +30,6 @@
#include "s3c24xx.h" #include "s3c24xx.h"
NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command) NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
{ {
struct s3c24xx_nand_controller *info; struct s3c24xx_nand_controller *info;
@ -166,4 +165,4 @@ struct nand_flash_controller s3c2440_nand_controller = {
.write_block_data = &s3c2440_write_block_data, .write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data, .read_block_data = &s3c2440_read_block_data,
.nand_ready = &s3c2440_nand_ready, .nand_ready = &s3c2440_nand_ready,
}; };

View File

@ -30,7 +30,6 @@
#include "s3c24xx.h" #include "s3c24xx.h"
NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command) NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command)
{ {
struct s3c24xx_nand_controller *info; struct s3c24xx_nand_controller *info;
@ -75,4 +74,4 @@ struct nand_flash_controller s3c2443_nand_controller = {
.write_block_data = &s3c2440_write_block_data, .write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data, .read_block_data = &s3c2440_read_block_data,
.nand_ready = &s3c2440_nand_ready, .nand_ready = &s3c2440_nand_ready,
}; };

View File

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

View File

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

View File

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

View File

@ -71,4 +71,4 @@ struct nand_flash_controller s3c6400_nand_controller = {
.write_block_data = &s3c2440_write_block_data, .write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data, .read_block_data = &s3c2440_read_block_data,
.nand_ready = &s3c2440_nand_ready, .nand_ready = &s3c2440_nand_ready,
}; };

View File

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