#include <target/arm.h>
#include <target/algorithm.h>
-
/**
* Copies code to a working area. This will allocate room for the code plus the
* additional amount requested if the working area pointer is null.
* @return Success or failure of the operation
*/
static int arm_code_to_working_area(struct target *target,
- const uint32_t *code, unsigned code_size,
- unsigned additional, struct working_area **area)
+ const uint32_t *code, unsigned code_size,
+ unsigned additional, struct working_area **area)
{
uint8_t code_buf[code_size];
unsigned i;
if (NULL == *area) {
retval = target_alloc_working_area(target, size, area);
if (retval != ERROR_OK) {
- LOG_DEBUG("%s: no %d byte buffer", __FUNCTION__, (int) size);
+ LOG_DEBUG("%s: no %d byte buffer", __func__, (int) size);
return ERROR_NAND_NO_BUFFER;
}
}
*/
int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
{
- struct target *target = nand->target;
- struct arm_algorithm algo;
- struct arm *arm = target->arch_info;
- struct reg_param reg_params[3];
- uint32_t target_buf;
- uint32_t exit_var = 0;
- int retval;
+ struct target *target = nand->target;
+ struct arm_algorithm algo;
+ struct arm *arm = target->arch_info;
+ struct reg_param reg_params[3];
+ uint32_t target_buf;
+ uint32_t exit_var = 0;
+ int retval;
/* Inputs:
* r0 NAND data address (byte wide)
if (nand->op != ARM_NAND_WRITE || !nand->copy_area) {
retval = arm_code_to_working_area(target, code, sizeof(code),
nand->chunk_size, &nand->copy_area);
- if (retval != ERROR_OK) {
+ if (retval != ERROR_OK)
return retval;
- }
}
nand->op = ARM_NAND_WRITE;
if (nand->op != ARM_NAND_READ || !nand->copy_area) {
retval = arm_code_to_working_area(target, code, sizeof(code),
nand->chunk_size, &nand->copy_area);
- if (retval != ERROR_OK) {
+ if (retval != ERROR_OK)
return retval;
- }
}
nand->op = ARM_NAND_READ;
return retval;
}
-
* Available operational states the arm_nand_data struct can be in.
*/
enum arm_nand_op {
- ARM_NAND_NONE, /**< No operation performed. */
- ARM_NAND_READ, /**< Read operation performed. */
- ARM_NAND_WRITE, /**< Write operation performed. */
+ ARM_NAND_NONE, /**< No operation performed. */
+ ARM_NAND_READ, /**< Read operation performed. */
+ ARM_NAND_WRITE, /**< Write operation performed. */
};
/**
struct target *target;
/** The copy area holds code loop and data for I/O operations. */
- struct working_area *copy_area;
+ struct working_area *copy_area;
/** The chunk size is the page size or ECC chunk. */
unsigned chunk_size;
int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size);
int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size);
-#endif /* __ARM_NANDIO_H */
+#endif /* __ARM_NANDIO_H */
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include "arm_io.h"
-#define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */
-#define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */
-#define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */
-#define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */
-#define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */
-#define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */
-#define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */
+#define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */
+#define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */
+#define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */
+#define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */
+#define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */
+#define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */
+#define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */
/**
* Representation of a pin on an AT91SAM9 chip.
{
struct target *target = nand->target;
- if (!at91sam9_halted(target, "init")) {
+ if (!at91sam9_halted(target, "init"))
return ERROR_NAND_OPERATION_FAILED;
- }
return ERROR_OK;
}
struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target;
- if (!at91sam9_halted(target, "command")) {
+ if (!at91sam9_halted(target, "command"))
return ERROR_NAND_OPERATION_FAILED;
- }
at91sam9_enable(nand);
*/
static int at91sam9_reset(struct nand_device *nand)
{
- if (!at91sam9_halted(nand->target, "reset")) {
+ if (!at91sam9_halted(nand->target, "reset"))
return ERROR_NAND_OPERATION_FAILED;
- }
return at91sam9_disable(nand);
}
struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target;
- if (!at91sam9_halted(nand->target, "address")) {
+ if (!at91sam9_halted(nand->target, "address"))
return ERROR_NAND_OPERATION_FAILED;
- }
return target_write_u8(target, info->addr, address);
}
struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target;
- if (!at91sam9_halted(nand->target, "read data")) {
+ if (!at91sam9_halted(nand->target, "read data"))
return ERROR_NAND_OPERATION_FAILED;
- }
return target_read_u8(target, info->data, data);
}
struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target;
- if (!at91sam9_halted(target, "write data")) {
+ if (!at91sam9_halted(target, "write data"))
return ERROR_NAND_OPERATION_FAILED;
- }
return target_write_u8(target, info->data, data);
}
struct target *target = nand->target;
uint32_t status;
- if (!at91sam9_halted(target, "nand ready")) {
+ if (!at91sam9_halted(target, "nand ready"))
return 0;
- }
do {
target_read_u32(target, info->busy.pioc + AT91C_PIOx_PDSR, &status);
- if (status & (1 << info->busy.num)) {
+ if (status & (1 << info->busy.num))
return 1;
- }
alive_sleep(1);
} while (timeout-- > 0);
struct arm_nand_data *io = &info->io;
int status;
- if (!at91sam9_halted(nand->target, "read block")) {
+ if (!at91sam9_halted(nand->target, "read block"))
return ERROR_NAND_OPERATION_FAILED;
- }
io->chunk_size = nand->page_size;
status = arm_nandread(io, data, size);
struct arm_nand_data *io = &info->io;
int status;
- if (!at91sam9_halted(nand->target, "write block")) {
+ if (!at91sam9_halted(nand->target, "write block"))
return ERROR_NAND_OPERATION_FAILED;
- }
io->chunk_size = nand->page_size;
status = arm_nandwrite(io, data, size);
return ERROR_NAND_OPERATION_FAILED;
}
- // reset ECC parity registers
+ /* reset ECC parity registers */
return target_write_u32(target, info->ecc + AT91C_ECCx_CR, 1);
}
* @param size Size of the OOB.
* @return Pointer to an area to store OOB data.
*/
-static uint8_t * at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint32_t *size)
+static uint8_t *at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint32_t *size)
{
if (!oob) {
- // user doesn't want OOB, allocate it
- if (nand->page_size == 512) {
+ /* user doesn't want OOB, allocate it */
+ if (nand->page_size == 512)
*size = 16;
- } else if (nand->page_size == 2048) {
+ else if (nand->page_size == 2048)
*size = 64;
- }
oob = malloc(*size);
if (!oob) {
* @return Success or failure of reading the NAND page.
*/
static int at91sam9_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
int retval;
struct at91sam9_nand *info = nand->controller_priv;
uint32_t status;
retval = at91sam9_ecc_init(target, info);
- if (ERROR_OK != retval) {
+ if (ERROR_OK != retval)
return retval;
- }
retval = nand_page_command(nand, page, NAND_CMD_READ0, !data);
- if (ERROR_OK != retval) {
+ if (ERROR_OK != retval)
return retval;
- }
if (data) {
retval = nand_read_data_page(nand, data, data_size);
- if (ERROR_OK != retval) {
+ if (ERROR_OK != retval)
return retval;
- }
}
oob_data = at91sam9_oob_init(nand, oob, &oob_size);
target_read_u32(target, info->ecc + AT91C_ECCx_SR, &status);
if (status & 1) {
LOG_ERROR("Error detected!");
- if (status & 4) {
+ if (status & 4)
LOG_ERROR("Multiple errors encountered; unrecoverable!");
- } else {
- // attempt recovery
+ else {
+ /* attempt recovery */
uint32_t parity;
target_read_u32(target,
- info->ecc + AT91C_ECCx_PR,
- &parity);
+ info->ecc + AT91C_ECCx_PR,
+ &parity);
uint32_t word = (parity & 0x0000FFF0) >> 4;
uint32_t bit = parity & 0x0F;
data[word] ^= (0x1) << bit;
LOG_INFO("Data word %d, bit %d corrected.",
- (unsigned) word,
- (unsigned) bit);
+ (unsigned) word,
+ (unsigned) bit);
}
}
if (status & 2) {
- // we could write back correct ECC data
+ /* we could write back correct ECC data */
LOG_ERROR("Error in ECC bytes detected");
}
}
if (!oob) {
- // if it wasn't asked for, free it
+ /* if it wasn't asked for, free it */
free(oob_data);
}
* @return Success or failure of the page write.
*/
static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
struct at91sam9_nand *info = nand->controller_priv;
struct target *target = nand->target;
uint32_t parity, nparity;
retval = at91sam9_ecc_init(target, info);
- if (ERROR_OK != retval) {
+ if (ERROR_OK != retval)
return retval;
- }
retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
- if (ERROR_OK != retval) {
+ if (ERROR_OK != retval)
return retval;
- }
if (data) {
retval = nand_write_data_page(nand, data, data_size);
oob_data = at91sam9_oob_init(nand, oob, &oob_size);
if (!oob) {
- // no OOB given, so read in the ECC parity from the ECC controller
+ /* no OOB given, so read in the ECC parity from the ECC controller */
target_read_u32(target, info->ecc + AT91C_ECCx_PR, &parity);
target_read_u32(target, info->ecc + AT91C_ECCx_NPR, &nparity);
retval = nand_write_data_page(nand, oob_data, oob_size);
- if (!oob) {
+ if (!oob)
free(oob_data);
- }
if (ERROR_OK != retval) {
LOG_ERROR("Unable to write OOB data to NAND");
struct at91sam9_nand *info = NULL;
unsigned num, address_line;
- if (CMD_ARGC != 2) {
+ if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
nand = get_nand_device_by_num(num);
struct at91sam9_nand *info = NULL;
unsigned num, base_pioc, pin_num;
- if (CMD_ARGC != 3) {
+ if (CMD_ARGC != 3)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
nand = get_nand_device_by_num(num);
struct at91sam9_nand *info = NULL;
unsigned num, base_pioc, pin_num;
- if (CMD_ARGC != 3) {
+ if (CMD_ARGC != 3)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
nand = get_nand_device_by_num(num);
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
/* configured NAND devices and NAND Flash command handler */
-struct nand_device *nand_devices = NULL;
+struct nand_device *nand_devices;
void nand_device_add(struct nand_device *c)
{
if (nand_devices) {
struct nand_device *p = nand_devices;
- while (p && p->next) p = p->next;
+ while (p && p->next)
+ p = p->next;
p->next = c;
} else
nand_devices = c;
* 256 256 Byte page size
* 512 512 Byte page size
*/
-static struct nand_info nand_flash_ids[] =
-{
+static struct nand_info nand_flash_ids[] = {
/* Vendor Specific Entries */
- { NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS, "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"},
- { NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS, "K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"},
+ { NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS,
+ "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"},
+ { NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS,
+ "K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"},
/* start "museum" IDs */
- { 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"},
- { 0x0, 0x64, 256, 2, 0x1000, 0, "NAND 2MiB 5V 8-bit"},
- { 0x0, 0x6b, 512, 4, 0x2000, 0, "NAND 4MiB 5V 8-bit"},
- { 0x0, 0xe8, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
- { 0x0, 0xec, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
- { 0x0, 0xea, 256, 2, 0x1000, 0, "NAND 2MiB 3.3V 8-bit"},
- { 0x0, 0xd5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
- { 0x0, 0xe3, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
- { 0x0, 0xe5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
- { 0x0, 0xd6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
-
- { 0x0, 0x39, 512, 8, 0x2000, 0, "NAND 8MiB 1.8V 8-bit"},
- { 0x0, 0xe6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
- { 0x0, 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 1.8V 16-bit"},
- { 0x0, 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 3.3V 16-bit"},
+ { 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"},
+ { 0x0, 0x64, 256, 2, 0x1000, 0, "NAND 2MiB 5V 8-bit"},
+ { 0x0, 0x6b, 512, 4, 0x2000, 0, "NAND 4MiB 5V 8-bit"},
+ { 0x0, 0xe8, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
+ { 0x0, 0xec, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
+ { 0x0, 0xea, 256, 2, 0x1000, 0, "NAND 2MiB 3.3V 8-bit"},
+ { 0x0, 0xd5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
+ { 0x0, 0xe3, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
+ { 0x0, 0xe5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
+ { 0x0, 0xd6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
+
+ { 0x0, 0x39, 512, 8, 0x2000, 0, "NAND 8MiB 1.8V 8-bit"},
+ { 0x0, 0xe6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
+ { 0x0, 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 1.8V 16-bit"},
+ { 0x0, 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 3.3V 16-bit"},
/* end "museum" IDs */
- { 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"},
- { 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"},
- { 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16,"NAND 16MiB 1.8V 16-bit"},
- { 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16,"NAND 16MiB 3.3V 16-bit"},
-
- { 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"},
- { 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"},
- { 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16,"NAND 32MiB 1.8V 16-bit"},
- { 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16,"NAND 32MiB 3.3V 16-bit"},
-
- { 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"},
- { 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"},
- { 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16,"NAND 64MiB 1.8V 16-bit"},
- { 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16,"NAND 64MiB 3.3V 16-bit"},
-
- { 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
- { 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
- { 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"},
- { 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 1.8V 16-bit"},
- { 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 1.8V 16-bit"},
- { 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3.3V 16-bit"},
- { 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3.3V 16-bit"},
-
- { 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"},
-
- { 0x0, 0xA2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 1.8V 8-bit"},
- { 0x0, 0xF2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 3.3V 8-bit"},
- { 0x0, 0xB2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 1.8V 16-bit"},
- { 0x0, 0xC2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 3.3V 16-bit"},
-
- { 0x0, 0xA1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 1.8V 8-bit"},
- { 0x0, 0xF1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 3.3V 8-bit"},
- { 0x0, 0xB1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 1.8V 16-bit"},
- { 0x0, 0xC1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 3.3V 16-bit"},
-
- { 0x0, 0xAA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 1.8V 8-bit"},
- { 0x0, 0xDA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 3.3V 8-bit"},
- { 0x0, 0xBA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 1.8V 16-bit"},
- { 0x0, 0xCA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 3.3V 16-bit"},
-
- { 0x0, 0xAC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 1.8V 8-bit"},
- { 0x0, 0xDC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 3.3V 8-bit"},
- { 0x0, 0xBC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 1.8V 16-bit"},
- { 0x0, 0xCC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 3.3V 16-bit"},
-
- { 0x0, 0xA3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 1.8V 8-bit"},
- { 0x0, 0xD3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 3.3V 8-bit"},
- { 0x0, 0xB3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 1.8V 16-bit"},
- { 0x0, 0xC3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 3.3V 16-bit"},
-
- { 0x0, 0xA5, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 1.8V 8-bit"},
- { 0x0, 0xD5, 0, 8192, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
- { 0x0, 0xB5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 1.8V 16-bit"},
- { 0x0, 0xC5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 3.3V 16-bit"},
-
- { 0x0, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
+ { 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"},
+ { 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"},
+ { 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 1.8V 16-bit"},
+ { 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 3.3V 16-bit"},
+
+ { 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"},
+ { 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"},
+ { 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 1.8V 16-bit"},
+ { 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 3.3V 16-bit"},
+
+ { 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"},
+ { 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"},
+ { 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 1.8V 16-bit"},
+ { 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 3.3V 16-bit"},
+
+ { 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
+ { 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
+ { 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"},
+ { 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"},
+ { 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"},
+ { 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"},
+ { 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"},
+
+ { 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"},
+
+ { 0x0, 0xA2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 1.8V 8-bit"},
+ { 0x0, 0xF2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 3.3V 8-bit"},
+ { 0x0, 0xB2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 1.8V 16-bit"},
+ { 0x0, 0xC2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 3.3V 16-bit"},
+
+ { 0x0, 0xA1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 1.8V 8-bit"},
+ { 0x0, 0xF1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 3.3V 8-bit"},
+ { 0x0, 0xB1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 1.8V 16-bit"},
+ { 0x0, 0xC1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 3.3V 16-bit"},
+
+ { 0x0, 0xAA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 1.8V 8-bit"},
+ { 0x0, 0xDA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 3.3V 8-bit"},
+ { 0x0, 0xBA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 1.8V 16-bit"},
+ { 0x0, 0xCA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 3.3V 16-bit"},
+
+ { 0x0, 0xAC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 1.8V 8-bit"},
+ { 0x0, 0xDC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 3.3V 8-bit"},
+ { 0x0, 0xBC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 1.8V 16-bit"},
+ { 0x0, 0xCC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 3.3V 16-bit"},
+
+ { 0x0, 0xA3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 1.8V 8-bit"},
+ { 0x0, 0xD3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 3.3V 8-bit"},
+ { 0x0, 0xB3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 1.8V 16-bit"},
+ { 0x0, 0xC3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 3.3V 16-bit"},
+
+ { 0x0, 0xA5, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 1.8V 8-bit"},
+ { 0x0, 0xD5, 0, 8192, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
+ { 0x0, 0xB5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 1.8V 16-bit"},
+ { 0x0, 0xC5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 3.3V 16-bit"},
+
+ { 0x0, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
{0, 0, 0, 0, 0, 0, NULL}
};
/* Manufacturer ID list
*/
-static struct nand_manufacturer nand_manuf_ids[] =
-{
+static struct nand_manufacturer nand_manuf_ids[] = {
{0x0, "unknown"},
{NAND_MFR_TOSHIBA, "Toshiba"},
{NAND_MFR_SAMSUNG, "Samsung"},
{.offset = 3,
.length = 2},
{.offset = 6,
- .length = 2}}
+ .length = 2}
+ }
};
#endif
unsigned found = 0;
struct nand_device *nand;
- for (nand = nand_devices; NULL != nand; nand = nand->next)
- {
+ for (nand = nand_devices; NULL != nand; nand = nand->next) {
if (strcmp(nand->name, name) == 0)
return nand;
if (!flash_driver_name_matches(nand->controller->name, name))
struct nand_device *p;
int i = 0;
- for (p = nand_devices; p; p = p->next)
- {
+ for (p = nand_devices; p; p = p->next) {
if (i++ == num)
- {
return p;
- }
}
return NULL;
}
COMMAND_HELPER(nand_command_get_device, unsigned name_index,
- struct nand_device **nand)
+ struct nand_device **nand)
{
const char *str = CMD_ARGV[name_index];
*nand = get_nand_device_by_name(str);
last = nand->num_blocks - 1;
page = first * pages_per_block;
- for (i = first; i <= last; i++)
- {
+ for (i = first; i <= last; i++) {
ret = nand_read_page(nand, page, NULL, 0, oob, 6);
if (ret != ERROR_OK)
return ret;
if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff))
- || (((nand->page_size == 512) && (oob[5] != 0xff)) ||
- ((nand->page_size == 2048) && (oob[0] != 0xff))))
- {
+ || (((nand->page_size == 512) && (oob[5] != 0xff)) ||
+ ((nand->page_size == 2048) && (oob[0] != 0xff)))) {
LOG_WARNING("bad block: %i", i);
nand->blocks[i].is_bad = 1;
- }
- else
- {
+ } else
nand->blocks[i].is_bad = 0;
- }
page += pages_per_block;
}
alive_sleep(1);
/* read status */
- if (nand->device->options & NAND_BUSWIDTH_16)
- {
+ if (nand->device->options & NAND_BUSWIDTH_16) {
uint16_t data;
nand->controller->read_data(nand, &data);
*status = data & 0xff;
- }
- else
- {
+ } else
nand->controller->read_data(nand, status);
- }
return ERROR_OK;
}
uint16_t data;
nand->controller->read_data(nand, &data);
status = data & 0xff;
- } else {
+ } else
nand->controller->read_data(nand, &status);
- }
if (status & NAND_STATUS_READY)
break;
alive_sleep(1);
nand->erase_size = 0;
/* initialize controller (device parameters are zero, use controller default) */
- if ((retval = nand->controller->init(nand) != ERROR_OK))
- {
- switch (retval)
- {
+ retval = nand->controller->init(nand);
+ if (retval != ERROR_OK) {
+ switch (retval) {
case ERROR_NAND_OPERATION_FAILED:
LOG_DEBUG("controller initialization failed");
return ERROR_NAND_OPERATION_FAILED;
case ERROR_NAND_OPERATION_NOT_SUPPORTED:
- LOG_ERROR("BUG: controller reported that it doesn't support default parameters");
+ LOG_ERROR(
+ "BUG: controller reported that it doesn't support default parameters");
return ERROR_NAND_OPERATION_FAILED;
default:
LOG_ERROR("BUG: unknown controller initialization failure");
nand->controller->command(nand, NAND_CMD_READID);
nand->controller->address(nand, 0x0);
- if (nand->bus_width == 8)
- {
+ if (nand->bus_width == 8) {
nand->controller->read_data(nand, &manufacturer_id);
nand->controller->read_data(nand, &device_id);
- }
- else
- {
+ } else {
uint16_t data_buf;
nand->controller->read_data(nand, &data_buf);
manufacturer_id = data_buf & 0xff;
device_id = data_buf & 0xff;
}
- for (i = 0; nand_flash_ids[i].name; i++)
- {
+ for (i = 0; nand_flash_ids[i].name; i++) {
if (nand_flash_ids[i].id == device_id &&
- (nand_flash_ids[i].mfr_id == manufacturer_id ||
- nand_flash_ids[i].mfr_id == 0 ))
- {
+ (nand_flash_ids[i].mfr_id == manufacturer_id ||
+ nand_flash_ids[i].mfr_id == 0)) {
nand->device = &nand_flash_ids[i];
break;
}
}
- for (i = 0; nand_manuf_ids[i].name; i++)
- {
- if (nand_manuf_ids[i].id == manufacturer_id)
- {
+ for (i = 0; nand_manuf_ids[i].name; i++) {
+ if (nand_manuf_ids[i].id == manufacturer_id) {
nand->manufacturer = &nand_manuf_ids[i];
break;
}
}
- if (!nand->manufacturer)
- {
+ if (!nand->manufacturer) {
nand->manufacturer = &nand_manuf_ids[0];
nand->manufacturer->id = manufacturer_id;
}
- if (!nand->device)
- {
- LOG_ERROR("unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x",
- manufacturer_id, device_id);
+ if (!nand->device) {
+ LOG_ERROR(
+ "unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x",
+ manufacturer_id,
+ device_id);
return ERROR_NAND_OPERATION_FAILED;
}
/* Do we need extended device probe information? */
if (nand->device->page_size == 0 ||
- nand->device->erase_size == 0)
- {
- if (nand->bus_width == 8)
- {
+ nand->device->erase_size == 0) {
+ if (nand->bus_width == 8) {
nand->controller->read_data(nand, id_buff + 3);
nand->controller->read_data(nand, id_buff + 4);
nand->controller->read_data(nand, id_buff + 5);
- }
- else
- {
+ } else {
uint16_t data_buf;
nand->controller->read_data(nand, &data_buf);
/* page size */
if (nand->device->page_size == 0)
- {
nand->page_size = 1 << (10 + (id_buff[4] & 3));
- }
- else if (nand->device->page_size == 256)
- {
+ else if (nand->device->page_size == 256) {
LOG_ERROR("NAND flashes with 256 byte pagesize are not supported");
return ERROR_NAND_OPERATION_FAILED;
- }
- else
- {
+ } else
nand->page_size = nand->device->page_size;
- }
/* number of address cycles */
- if (nand->page_size <= 512)
- {
+ if (nand->page_size <= 512) {
/* small page devices */
if (nand->device->chip_size <= 32)
nand->address_cycles = 3;
else if (nand->device->chip_size <= 8*1024)
nand->address_cycles = 4;
- else
- {
+ else {
LOG_ERROR("BUG: small page NAND device with more than 8 GiB encountered");
nand->address_cycles = 5;
}
- }
- else
- {
+ } else {
/* large page devices */
if (nand->device->chip_size <= 128)
nand->address_cycles = 4;
else if (nand->device->chip_size <= 32*1024)
nand->address_cycles = 5;
- else
- {
+ else {
LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered");
nand->address_cycles = 6;
}
}
/* erase size */
- if (nand->device->erase_size == 0)
- {
+ if (nand->device->erase_size == 0) {
switch ((id_buff[4] >> 4) & 3) {
- case 0:
- nand->erase_size = 64 << 10;
- break;
- case 1:
- nand->erase_size = 128 << 10;
- break;
- case 2:
- nand->erase_size = 256 << 10;
- break;
- case 3:
- nand->erase_size =512 << 10;
- break;
+ case 0:
+ nand->erase_size = 64 << 10;
+ break;
+ case 1:
+ nand->erase_size = 128 << 10;
+ break;
+ case 2:
+ nand->erase_size = 256 << 10;
+ break;
+ case 3:
+ nand->erase_size = 512 << 10;
+ break;
}
- }
- else
- {
+ } else
nand->erase_size = nand->device->erase_size;
- }
/* initialize controller, but leave parameters at the controllers default */
- if ((retval = nand->controller->init(nand) != ERROR_OK))
- {
- switch (retval)
- {
+ retval = nand->controller->init(nand);
+ if (retval != ERROR_OK) {
+ switch (retval) {
case ERROR_NAND_OPERATION_FAILED:
LOG_DEBUG("controller initialization failed");
return ERROR_NAND_OPERATION_FAILED;
case ERROR_NAND_OPERATION_NOT_SUPPORTED:
- LOG_ERROR("controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)",
- nand->bus_width, nand->address_cycles, nand->page_size);
+ LOG_ERROR(
+ "controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)",
+ nand->bus_width,
+ nand->address_cycles,
+ nand->page_size);
return ERROR_NAND_OPERATION_FAILED;
default:
LOG_ERROR("BUG: unknown controller initialization failure");
nand->num_blocks = (nand->device->chip_size * 1024) / (nand->erase_size / 1024);
nand->blocks = malloc(sizeof(struct nand_block) * nand->num_blocks);
- for (i = 0; i < nand->num_blocks; i++)
- {
+ for (i = 0; i < nand->num_blocks; i++) {
nand->blocks[i].size = nand->erase_size;
nand->blocks[i].offset = i * nand->erase_size;
nand->blocks[i].is_erased = -1;
return ERROR_COMMAND_SYNTAX_ERROR;
/* make sure we know if a block is bad before erasing it */
- for (i = first_block; i <= last_block; i++)
- {
- if (nand->blocks[i].is_bad == -1)
- {
+ for (i = first_block; i <= last_block; i++) {
+ if (nand->blocks[i].is_bad == -1) {
nand_build_bbt(nand, i, last_block);
break;
}
}
- for (i = first_block; i <= last_block; i++)
- {
+ for (i = first_block; i <= last_block; i++) {
/* Send erase setup command */
nand->controller->command(nand, NAND_CMD_ERASE1);
page = i * (nand->erase_size / nand->page_size);
/* Send page address */
- if (nand->page_size <= 512)
- {
+ if (nand->page_size <= 512) {
/* row */
nand->controller->address(nand, page & 0xff);
nand->controller->address(nand, (page >> 8) & 0xff);
/* 4th cycle only on devices with more than 8 GiB */
if (nand->address_cycles >= 5)
nand->controller->address(nand, (page >> 24) & 0xff);
- }
- else
- {
+ } else {
/* row */
nand->controller->address(nand, page & 0xff);
nand->controller->address(nand, (page >> 8) & 0xff);
nand->controller->command(nand, NAND_CMD_ERASE2);
retval = nand->controller->nand_ready ?
- nand->controller->nand_ready(nand, 1000) :
- nand_poll_ready(nand, 1000);
+ nand->controller->nand_ready(nand, 1000) :
+ nand_poll_ready(nand, 1000);
if (!retval) {
LOG_ERROR("timeout waiting for NAND flash block erase to complete");
return ERROR_NAND_OPERATION_TIMEOUT;
}
retval = nand_read_status(nand, &status);
- if (retval != ERROR_OK)
- {
+ if (retval != ERROR_OK) {
LOG_ERROR("couldn't read status");
return ERROR_NAND_OPERATION_FAILED;
}
- if (status & 0x1)
- {
+ if (status & 0x1) {
LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x",
- (nand->blocks[i].is_bad == 1)
- ? "bad " : "",
- i, status);
+ (nand->blocks[i].is_bad == 1)
+ ? "bad " : "",
+ i, status);
/* continue; other blocks might still be erasable */
}
}
#if 0
-static int nand_read_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size)
+static int nand_read_plain(struct nand_device *nand,
+ uint32_t address,
+ uint8_t *data,
+ uint32_t data_size)
{
uint8_t *page;
if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED;
- if (address % nand->page_size)
- {
+ if (address % nand->page_size) {
LOG_ERROR("reads need to be page aligned");
return ERROR_NAND_OPERATION_FAILED;
}
page = malloc(nand->page_size);
- while (data_size > 0)
- {
+ while (data_size > 0) {
uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size;
uint32_t page_address;
return ERROR_OK;
}
-static int nand_write_plain(struct nand_device *nand, uint32_t address, uint8_t *data, uint32_t data_size)
+static int nand_write_plain(struct nand_device *nand,
+ uint32_t address,
+ uint8_t *data,
+ uint32_t data_size)
{
uint8_t *page;
if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED;
- if (address % nand->page_size)
- {
+ if (address % nand->page_size) {
LOG_ERROR("writes need to be page aligned");
return ERROR_NAND_OPERATION_FAILED;
}
page = malloc(nand->page_size);
- while (data_size > 0)
- {
+ while (data_size > 0) {
uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size;
uint32_t page_address;
#endif
int nand_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
uint32_t block;
}
int nand_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED;
}
int nand_page_command(struct nand_device *nand, uint32_t page,
- uint8_t cmd, bool oob_only)
+ uint8_t cmd, bool oob_only)
{
if (!nand->device)
return ERROR_NAND_DEVICE_NOT_PROBED;
}
int nand_read_page_raw(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
int retval;
nand->controller->command(nand, NAND_CMD_PAGEPROG);
retval = nand->controller->nand_ready ?
- nand->controller->nand_ready(nand, 100) :
- nand_poll_ready(nand, 100);
+ nand->controller->nand_ready(nand, 100) :
+ nand_poll_ready(nand, 100);
if (!retval)
return ERROR_NAND_OPERATION_TIMEOUT;
if (status & NAND_STATUS_FAIL) {
LOG_ERROR("write operation didn't pass, status: 0x%2.2x",
- status);
+ status);
return ERROR_NAND_OPERATION_FAILED;
}
}
int nand_write_page_raw(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
int retval;
return nand_write_finish(nand);
}
-
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifndef FLASH_NAND_CORE_H
#define FLASH_NAND_CORE_H
/**
* Representation of a single NAND block in a NAND device.
*/
-struct nand_block
-{
+struct nand_block {
/** Offset to the block. */
uint32_t offset;
struct nand_oobfree oobfree[2];
};
-struct nand_device
-{
+struct nand_device {
const char *name;
struct target *target;
struct nand_flash_controller *controller;
/* NAND Flash Manufacturer ID Codes
*/
-enum
-{
+enum {
NAND_MFR_TOSHIBA = 0x98,
NAND_MFR_SAMSUNG = 0xec,
NAND_MFR_FUJITSU = 0x04,
NAND_MFR_MICRON = 0x2c,
};
-struct nand_manufacturer
-{
+struct nand_manufacturer {
int id;
const char *name;
};
-struct nand_info
-{
+struct nand_info {
int mfr_id;
int id;
int page_size;
LP_OPTIONS16 = (LP_OPTIONS | NAND_BUSWIDTH_16),
};
-enum
-{
+enum {
/* Standard NAND flash commands */
NAND_CMD_READ0 = 0x0,
NAND_CMD_READ1 = 0x1,
NAND_CMD_PAGEPROG = 0x10,
NAND_CMD_READOOB = 0x50,
NAND_CMD_ERASE1 = 0x60,
- NAND_CMD_STATUS = 0x70,
+ NAND_CMD_STATUS = 0x70,
NAND_CMD_STATUS_MULTI = 0x71,
NAND_CMD_SEQIN = 0x80,
NAND_CMD_RNDIN = 0x85,
};
/* Status bits */
-enum
-{
+enum {
NAND_STATUS_FAIL = 0x01,
NAND_STATUS_FAIL_N1 = 0x02,
NAND_STATUS_TRUE_READY = 0x20,
};
/* OOB (spare) data formats */
-enum oob_formats
-{
+enum oob_formats {
NAND_OOB_NONE = 0x0, /* no OOB data at all */
- NAND_OOB_RAW = 0x1, /* raw OOB data (16 bytes for 512b page sizes, 64 bytes for 2048b page sizes) */
+ NAND_OOB_RAW = 0x1, /* raw OOB data (16 bytes for 512b page sizes, 64 bytes for
+ *2048b page sizes) */
NAND_OOB_ONLY = 0x2, /* only OOB data */
NAND_OOB_SW_ECC = 0x10, /* when writing, use SW ECC (as opposed to no ECC) */
- NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no ECC) */
- NAND_OOB_SW_ECC_KW = 0x40, /* when writing, use Marvell's Kirkwood bootrom format */
+ NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no ECC) */
+ NAND_OOB_SW_ECC_KW = 0x40, /* when writing, use Marvell's Kirkwood bootrom format */
NAND_OOB_JFFS2 = 0x100, /* when writing, use JFFS2 OOB layout */
NAND_OOB_YAFFS2 = 0x100,/* when writing, use YAFFS2 OOB layout */
};
struct nand_device *get_nand_device_by_num(int num);
int nand_page_command(struct nand_device *nand, uint32_t page,
- uint8_t cmd, bool oob_only);
+ uint8_t cmd, bool oob_only);
int nand_read_data_page(struct nand_device *nand, uint8_t *data, uint32_t size);
int nand_write_data_page(struct nand_device *nand,
- uint8_t *data, uint32_t size);
+ uint8_t *data, uint32_t size);
int nand_write_finish(struct nand_device *nand);
int nand_read_page_raw(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
int nand_write_page_raw(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
int nand_read_status(struct nand_device *nand, uint8_t *status);
int nand_calculate_ecc(struct nand_device *nand,
- const uint8_t *dat, uint8_t *ecc_code);
+ const uint8_t *dat, uint8_t *ecc_code);
int nand_calculate_ecc_kw(struct nand_device *nand,
- const uint8_t *dat, uint8_t *ecc_code);
+ const uint8_t *dat, uint8_t *ecc_code);
int nand_register_commands(struct command_context *cmd_ctx);
-/// helper for parsing a nand device command argument string
+/* / helper for parsing a nand device command argument string */
COMMAND_HELPER(nand_command_get_device, unsigned name_index,
- struct nand_device **nand);
-
+ struct nand_device **nand);
-#define ERROR_NAND_DEVICE_INVALID (-1100)
-#define ERROR_NAND_OPERATION_FAILED (-1101)
-#define ERROR_NAND_OPERATION_TIMEOUT (-1102)
-#define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103)
-#define ERROR_NAND_DEVICE_NOT_PROBED (-1104)
-#define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105)
-#define ERROR_NAND_NO_BUFFER (-1106)
-#endif // FLASH_NAND_CORE_H
+#define ERROR_NAND_DEVICE_INVALID (-1100)
+#define ERROR_NAND_OPERATION_FAILED (-1101)
+#define ERROR_NAND_OPERATION_TIMEOUT (-1102)
+#define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103)
+#define ERROR_NAND_DEVICE_NOT_PROBED (-1104)
+#define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105)
+#define ERROR_NAND_NO_BUFFER (-1106)
+#endif /* FLASH_NAND_CORE_H */
};
struct davinci_nand {
- uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */
- uint8_t eccmode;
+ uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */
+ uint8_t eccmode;
/* Async EMIF controller base */
- uint32_t aemif;
+ uint32_t aemif;
/* NAND chip addresses */
- uint32_t data; /* without CLE or ALE */
- uint32_t cmd; /* with CLE */
- uint32_t addr; /* with ALE */
+ uint32_t data; /* without CLE or ALE */
+ uint32_t cmd; /* with CLE */
+ uint32_t addr; /* with ALE */
/* write acceleration */
- struct arm_nand_data io;
+ struct arm_nand_data io;
/* page i/o for the relevant flavor of hardware ECC */
int (*read_page)(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
int (*write_page)(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
};
-#define NANDFCR 0x60 /* flash control register */
-#define NANDFSR 0x64 /* flash status register */
-#define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */
-#define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */
-#define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */
-#define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */
-#define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */
+#define NANDFCR 0x60 /* flash control register */
+#define NANDFSR 0x64 /* flash status register */
+#define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */
+#define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */
+#define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */
+#define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */
+#define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */
static int halted(struct target *target, const char *label)
{
/* REVISIT a bit of native code should let block reads be MUCH faster */
static int davinci_read_block_data(struct nand_device *nand,
- uint8_t *data, int data_size)
+ uint8_t *data, int data_size)
{
struct davinci_nand *info = nand->controller_priv;
struct target *target = nand->target;
}
static int davinci_write_block_data(struct nand_device *nand,
- uint8_t *data, int data_size)
+ uint8_t *data, int data_size)
{
struct davinci_nand *info = nand->controller_priv;
struct target *target = nand->target;
}
static int davinci_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
struct davinci_nand *info = nand->controller_priv;
uint8_t *ooballoc = NULL;
/* If we're not given OOB, write 0xff where we don't write ECC codes. */
switch (nand->page_size) {
- case 512:
- oob_size = 16;
- break;
- case 2048:
- oob_size = 64;
- break;
- case 4096:
- oob_size = 128;
- break;
- default:
- return ERROR_NAND_OPERATION_FAILED;
+ case 512:
+ oob_size = 16;
+ break;
+ case 2048:
+ oob_size = 64;
+ break;
+ case 4096:
+ oob_size = 128;
+ break;
+ default:
+ return ERROR_NAND_OPERATION_FAILED;
}
if (!oob) {
ooballoc = malloc(oob_size);
}
static int davinci_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
struct davinci_nand *info = nand->controller_priv;
}
static int davinci_writepage_tail(struct nand_device *nand,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *oob, uint32_t oob_size)
{
struct davinci_nand *info = nand->controller_priv;
struct target *target = nand->target;
* All DaVinci family chips support 1-bit ECC on a per-chipselect basis.
*/
static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
unsigned oob_offset;
struct davinci_nand *info = nand->controller_priv;
* for 16-bit OOB, those extra bytes are discontiguous.
*/
switch (nand->page_size) {
- case 512:
- oob_offset = 0;
- break;
- case 2048:
- oob_offset = 40;
- break;
- default:
- oob_offset = 80;
- break;
+ case 512:
+ oob_offset = 0;
+ break;
+ case 2048:
+ oob_offset = 40;
+ break;
+ default:
+ oob_offset = 80;
+ break;
}
davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
* manufacturer bad block markers are safe. Contrast: old "infix" style.
*/
static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
static const uint8_t ecc512[] = {
- 0, 1, 2, 3, 4, /* 5== mfr badblock */
+ 0, 1, 2, 3, 4, /* 5== mfr badblock */
6, 7, /* 8..12 for BBT or JFFS2 */ 13, 14, 15,
};
static const uint8_t ecc2048[] = {
54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
};
static const uint8_t ecc4096[] = {
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
};
* the standard ECC logic can't handle.
*/
switch (nand->page_size) {
- case 512:
- l = ecc512;
- break;
- case 2048:
- l = ecc2048;
- break;
- default:
- l = ecc4096;
- break;
+ case 512:
+ l = ecc512;
+ break;
+ case 2048:
+ l = ecc2048;
+ break;
+ default:
+ l = ecc4096;
+ break;
}
davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
raw_ecc[i] &= 0x03ff03ff;
}
for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
- oob[*l++] = p[0] & 0xff;
+ oob[*l++] = p[0] & 0xff;
oob[*l++] = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc);
oob[*l++] = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
oob[*l++] = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0);
- oob[*l++] = (p[1] >> 18) & 0xff;
+ oob[*l++] = (p[1] >> 18) & 0xff;
}
} while (data_size);
* (MVL 4.x/5.x kernels, filesystems, etc) may need it more generally.
*/
static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
struct davinci_nand *info = nand->controller_priv;
struct target *target = nand->target;
/* skip 6 bytes of prepad, then pack 10 packed ecc bytes */
for (i = 0, l = oob + 6, p = raw_ecc; i < 2; i++, p += 2) {
- *l++ = p[0] & 0xff;
+ *l++ = p[0] & 0xff;
*l++ = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc);
*l++ = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
*l++ = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0);
- *l++ = (p[1] >> 18) & 0xff;
+ *l++ = (p[1] >> 18) & 0xff;
}
/* write this "out-of-band" data -- infix */
}
static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
{
int read_size;
int want_col, at_col;
* - aemif address
* Plus someday, optionally, ALE and CLE masks.
*/
- if (CMD_ARGC < 5) {
+ if (CMD_ARGC < 5)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
if (chip == 0) {
* AEMIF controller address.
*/
if (aemif == 0x01e00000 /* dm6446, dm357 */
- || aemif == 0x01e10000 /* dm335, dm355 */
- || aemif == 0x01d10000 /* dm365 */
- ) {
+ || aemif == 0x01e10000 /* dm335, dm355 */
+ || aemif == 0x01d10000 /* dm365 */
+ ) {
if (chip < 0x02000000 || chip >= 0x0a000000) {
LOG_ERROR("NAND address %08lx out of range?", chip);
goto fail;
info->read_page = nand_read_page_raw;
switch (eccmode) {
- case HWECC1:
- /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
- info->write_page = davinci_write_page_ecc1;
- break;
- case HWECC4:
- /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
- info->write_page = davinci_write_page_ecc4;
- break;
- case HWECC4_INFIX:
- /* Same 4-bit ECC HW, with problematic page/ecc layout */
- info->read_page = davinci_read_page_ecc4infix;
- info->write_page = davinci_write_page_ecc4infix;
- break;
+ case HWECC1:
+ /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
+ info->write_page = davinci_write_page_ecc1;
+ break;
+ case HWECC4:
+ /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
+ info->write_page = davinci_write_page_ecc4;
+ break;
+ case HWECC4_INFIX:
+ /* Same 4-bit ECC HW, with problematic page/ecc layout */
+ info->read_page = davinci_read_page_ecc4infix;
+ info->write_page = davinci_write_page_ecc4infix;
+ break;
}
return ERROR_OK;
}
struct nand_flash_controller davinci_nand_controller = {
- .name = "davinci",
- .usage = "chip_addr hwecc_mode aemif_addr",
- .nand_device_command = davinci_nand_device_command,
- .init = davinci_init,
- .reset = davinci_reset,
- .command = davinci_command,
- .address = davinci_address,
- .write_data = davinci_write_data,
- .read_data = davinci_read_data,
- .write_page = davinci_write_page,
- .read_page = davinci_read_page,
- .write_block_data = davinci_write_block_data,
- .read_block_data = davinci_read_block_data,
- .nand_ready = davinci_nand_ready,
+ .name = "davinci",
+ .usage = "chip_addr hwecc_mode aemif_addr",
+ .nand_device_command = davinci_nand_device_command,
+ .init = davinci_init,
+ .reset = davinci_reset,
+ .command = davinci_command,
+ .address = davinci_address,
+ .write_data = davinci_write_data,
+ .read_data = davinci_read_data,
+ .write_page = davinci_write_page,
+ .read_page = davinci_read_page,
+ .write_block_data = davinci_write_block_data,
+ .read_block_data = davinci_read_block_data,
+ .nand_ready = davinci_nand_ready,
};
/* extern struct nand_flash_controller boundary_scan_nand_controller; */
-static struct nand_flash_controller *nand_flash_controllers[] =
-{
+static struct nand_flash_controller *nand_flash_controllers[] = {
&nonce_nand_controller,
&davinci_nand_controller,
&lpc3180_nand_controller,
struct nand_flash_controller *nand_driver_find_by_name(const char *name)
{
- for (unsigned i = 0; nand_flash_controllers[i]; i++)
- {
+ for (unsigned i = 0; nand_flash_controllers[i]; i++) {
struct nand_flash_controller *controller = nand_flash_controllers[i];
if (strcmp(name, controller->name) == 0)
return controller;
}
int nand_driver_walk(nand_driver_walker_t f, void *x)
{
- for (unsigned i = 0; nand_flash_controllers[i]; i++)
- {
+ for (unsigned i = 0; nand_flash_controllers[i]; i++) {
int retval = (*f)(nand_flash_controllers[i], x);
if (ERROR_OK != retval)
return retval;
}
return ERROR_OK;
}
-
-
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifndef FLASH_NAND_DRIVER_H
#define FLASH_NAND_DRIVER_H
struct nand_device;
#define __NAND_DEVICE_COMMAND(name) \
- COMMAND_HELPER(name, struct nand_device *nand)
+ COMMAND_HELPER(name, struct nand_device *nand)
/**
* Interface for NAND flash controllers. Not all of these functions are
* required for full functionality of the NAND driver, but better performance
* can be achieved by implementing each function.
*/
-struct nand_flash_controller
-{
+struct nand_flash_controller {
/** Driver name that is used to select it from configuration files. */
const char *name;
/** Usage of flash command registration. */
const char *usage;
- const struct command_registration *commands;
+ const struct command_registration *commands;
/** NAND device command called when driver is instantiated during configuration. */
__NAND_DEVICE_COMMAND((*nand_device_command));
int (*read_block_data)(struct nand_device *nand, uint8_t *data, int size);
/** Write a page to the NAND device. */
- int (*write_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+ int (*write_page)(struct nand_device *nand, uint32_t page, uint8_t *data,
+ uint32_t data_size, uint8_t *oob, uint32_t oob_size);
/** Read a page from the NAND device. */
- int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
+ int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size);
/** Check if the NAND device is ready for more instructions with timeout. */
int (*nand_ready)(struct nand_device *nand, int timeout);
*/
struct nand_flash_controller *nand_driver_find_by_name(const char *name);
-/// Signature for callback functions passed to nand_driver_walk
-typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void*);
+/* / Signature for callback functions passed to nand_driver_walk */
+typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void *);
/**
* Walk the list of drivers, encapsulating the data structure type.
* Application state/context can be passed through the @c x pointer.
*/
int nand_driver_walk(nand_driver_walker_t f, void *x);
-#endif // FLASH_NAND_DRIVER_H
+#endif /* FLASH_NAND_DRIVER_H */
{
int res = 0;
- for (;b; b >>= 1)
+ for (; b; b >>= 1)
res += b & 0x01;
return res;
}
* nand_correct_data - Detect and correct a 1 bit error for 256 byte block
*/
int nand_correct_data(struct nand_device *nand, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
+ u_char *read_ecc, u_char *calc_ecc)
{
uint8_t s0, s1, s2;
return 0;
/* Check for a single bit error */
- if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
- ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
- ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
+ if (((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
+ ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
+ ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
uint32_t byteoffs, bitnum;
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;
* For multiplication, a discrete log/exponent table is used, with
* primitive element x (F is a primitive field, so x is primitive).
*/
-#define MODPOLY 0x409 /* x^10 + x^3 + 1 in binary */
+#define MODPOLY 0x409 /* x^10 + x^3 + 1 in binary */
/*
* Maps an integer a [0..1022] to a polynomial b = gf_exp[a] in
{
unsigned int r7, r6, r5, r4, r3, r2, r1, r0;
int i;
- static int tables_initialized = 0;
+ static int tables_initialized;
if (!tables_initialized) {
gf_build_log_exp_table();
r6 = data[510];
r7 = data[511];
-
/*
* Shift bytes 503..0 (in that order) into r0, followed
* by eight zero bytes, while reducing the polynomial by the
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
.eccpos = {0, 1, 2, 3, 6, 7},
.oobfree = {
{.offset = 8,
- . length = 8}}
+ .length = 8}
+ }
};
static struct nand_ecclayout nand_oob_64 = {
.eccbytes = 24,
.eccpos = {
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63},
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63
+ },
.oobfree = {
{.offset = 2,
- .length = 38}}
+ .length = 38}
+ }
};
void nand_fileio_init(struct nand_fileio_state *state)
}
int nand_fileio_start(struct command_context *cmd_ctx,
- struct nand_device *nand, const char *filename, int filemode,
- struct nand_fileio_state *state)
+ struct nand_device *nand, const char *filename, int filemode,
+ struct nand_fileio_state *state)
{
- if (state->address % nand->page_size)
- {
+ if (state->address % nand->page_size) {
command_print(cmd_ctx, "only page-aligned addresses are supported");
return ERROR_COMMAND_SYNTAX_ERROR;
}
duration_start(&state->bench);
- if (NULL != filename)
- {
+ if (NULL != filename) {
int retval = fileio_open(&state->fileio, filename, filemode, FILEIO_BINARY);
- if (ERROR_OK != retval)
- {
+ if (ERROR_OK != retval) {
const char *msg = (FILEIO_READ == filemode) ? "read" : "write";
command_print(cmd_ctx, "failed to open '%s' for %s access",
- filename, msg);
+ filename, msg);
return retval;
}
state->file_opened = true;
}
- if (!(state->oob_format & NAND_OOB_ONLY))
- {
+ if (!(state->oob_format & NAND_OOB_ONLY)) {
state->page_size = nand->page_size;
state->page = malloc(nand->page_size);
}
- if (state->oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW))
- {
- if (nand->page_size == 512)
- {
+ if (state->oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW)) {
+ if (nand->page_size == 512) {
state->oob_size = 16;
state->eccpos = nand_oob_16.eccpos;
- }
- else if (nand->page_size == 2048)
- {
+ } else if (nand->page_size == 2048) {
state->oob_size = 64;
state->eccpos = nand_oob_64.eccpos;
}
if (state->file_opened)
fileio_close(&state->fileio);
- if (state->oob)
- {
+ if (state->oob) {
free(state->oob);
state->oob = NULL;
}
- if (state->page)
- {
+ if (state->page) {
free(state->page);
state->page = NULL;
}
}
COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
- struct nand_device **dev, enum fileio_access filemode,
- bool need_size, bool sw_ecc)
+ struct nand_device **dev, enum fileio_access filemode,
+ bool need_size, bool sw_ecc)
{
nand_fileio_init(state);
if (ERROR_OK != retval)
return retval;
- if (NULL == nand->device)
- {
+ if (NULL == nand->device) {
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
return ERROR_OK;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], state->address);
- if (need_size)
- {
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], state->size);
- if (state->size % nand->page_size)
- {
- command_print(CMD_CTX, "only page-aligned sizes are supported");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
+ if (need_size) {
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], state->size);
+ if (state->size % nand->page_size) {
+ command_print(CMD_CTX, "only page-aligned sizes are supported");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
}
- if (CMD_ARGC > minargs)
- {
- for (unsigned i = minargs; i < CMD_ARGC; i++)
- {
+ if (CMD_ARGC > minargs) {
+ for (unsigned i = minargs; i < CMD_ARGC; i++) {
if (!strcmp(CMD_ARGV[i], "oob_raw"))
state->oob_format |= NAND_OOB_RAW;
else if (!strcmp(CMD_ARGV[i], "oob_only"))
state->oob_format |= NAND_OOB_SW_ECC;
else if (sw_ecc && !strcmp(CMD_ARGV[i], "oob_softecc_kw"))
state->oob_format |= NAND_OOB_SW_ECC_KW;
- else
- {
+ else {
command_print(CMD_CTX, "unknown option: %s", CMD_ARGV[i]);
return ERROR_COMMAND_SYNTAX_ERROR;
}
if (ERROR_OK != retval)
return retval;
- if (!need_size)
- {
+ if (!need_size) {
int filesize;
retval = fileio_size(&state->fileio, &filesize);
if (retval != ERROR_OK)
size_t total_read = 0;
size_t one_read;
- if (NULL != s->page)
- {
+ if (NULL != s->page) {
fileio_read(&s->fileio, s->page_size, s->page, &one_read);
if (one_read < s->page_size)
memset(s->page + one_read, 0xff, s->page_size - one_read);
total_read += one_read;
}
- if (s->oob_format & NAND_OOB_SW_ECC)
- {
+ if (s->oob_format & NAND_OOB_SW_ECC) {
uint8_t ecc[3];
memset(s->oob, 0xff, s->oob_size);
- for (uint32_t i = 0, j = 0; i < s->page_size; i += 256)
- {
+ for (uint32_t i = 0, j = 0; i < s->page_size; i += 256) {
nand_calculate_ecc(nand, s->page + i, ecc);
s->oob[s->eccpos[j++]] = ecc[0];
s->oob[s->eccpos[j++]] = ecc[1];
s->oob[s->eccpos[j++]] = ecc[2];
}
- }
- else if (s->oob_format & NAND_OOB_SW_ECC_KW)
- {
+ } else if (s->oob_format & NAND_OOB_SW_ECC_KW) {
/*
* In this case eccpos is not used as
* the ECC data is always stored contigously
*/
uint8_t *ecc = s->oob + s->oob_size - s->page_size / 512 * 10;
memset(s->oob, 0xff, s->oob_size);
- for (uint32_t i = 0; i < s->page_size; i += 512)
- {
+ for (uint32_t i = 0; i < s->page_size; i += 512) {
nand_calculate_ecc_kw(nand, s->page + i, ecc);
ecc += 10;
}
- }
- else if (NULL != s->oob)
- {
+ } else if (NULL != s->oob) {
fileio_read(&s->fileio, s->oob_size, s->oob, &one_read);
if (one_read < s->oob_size)
memset(s->oob + one_read, 0xff, s->oob_size - one_read);
}
return total_read;
}
-
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifndef FLASH_NAND_FILEIO_H
#define FLASH_NAND_FILEIO_H
int nand_fileio_finish(struct nand_fileio_state *state);
COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
- struct nand_device **dev, enum fileio_access filemode,
- bool need_size, bool sw_ecc);
+ struct nand_device **dev, enum fileio_access filemode,
+ bool need_size, bool sw_ecc);
int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s);
-#endif // FLASH_NAND_FILEIO_H
+#endif /* FLASH_NAND_FILEIO_H */
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifndef FLASH_NAND_IMP_H
#define FLASH_NAND_IMP_H
int nand_erase(struct nand_device *nand, int first_block, int last_block);
int nand_build_bbt(struct nand_device *nand, int first, int last);
-#endif // FLASH_NAND_IMP_H
+#endif /* FLASH_NAND_IMP_H */
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "lpc3180.h"
#include <target/target.h>
-
static int lpc3180_reset(struct nand_device *nand);
static int lpc3180_controller_ready(struct nand_device *nand, int timeout);
static int lpc3180_tc_ready(struct nand_device *nand, int timeout);
-
#define ECC_OFFS 0x120
#define SPARE_OFFS 0x140
#define DATA_OFFS 0x200
-
/* nand device lpc3180 <target#> <oscillator_frequency>
*/
NAND_DEVICE_COMMAND_HANDLER(lpc3180_nand_device_command)
{
if (CMD_ARGC < 3)
- {
return ERROR_COMMAND_SYNTAX_ERROR;
- }
uint32_t osc_freq;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
lpc3180_info->osc_freq = osc_freq;
if ((lpc3180_info->osc_freq < 1000) || (lpc3180_info->osc_freq > 20000))
- {
- LOG_WARNING("LPC3180 oscillator frequency should be between 1000 and 20000 kHz, was %i", lpc3180_info->osc_freq);
- }
+ LOG_WARNING(
+ "LPC3180 oscillator frequency should be between 1000 and 20000 kHz, was %i",
+ lpc3180_info->osc_freq);
lpc3180_info->selected_controller = LPC3180_NO_CONTROLLER;
lpc3180_info->sw_write_protection = 0;
lpc3180_info->sw_wp_lower_bound = 0x0;
/* determine selected HCLK source */
target_read_u32(target, 0x40004044, &pwr_ctrl);
- if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
- {
+ if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
hclk = sysclk;
- }
- else
- {
+ else {
target_read_u32(target, 0x40004058, &hclkpll_ctrl);
hclk_pll = lpc3180_pll(sysclk, hclkpll_ctrl);
target_read_u32(target, 0x40004040, &hclkdiv_ctrl);
if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
- {
hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1);
- }
else /* HCLK uses HCLK_PLL */
- {
hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3));
- }
}
LOG_DEBUG("LPC3180 HCLK currently clocked at %i kHz", hclk);
int address_cycles = nand->address_cycles ? : 3;
int page_size = nand->page_size ? : 512;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
/* sanitize arguments */
- if ((bus_width != 8) && (bus_width != 16))
- {
+ if ((bus_width != 8) && (bus_width != 16)) {
LOG_ERROR("LPC3180 only supports 8 or 16 bit bus width, not %i", bus_width);
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
* would support 16 bit, too, so we just warn about this for now
*/
if (bus_width == 16)
- {
LOG_WARNING("LPC3180 only supports 8 bit bus width");
- }
/* inform calling code about selected bus width */
nand->bus_width = bus_width;
- if ((address_cycles != 3) && (address_cycles != 4))
- {
+ if ((address_cycles != 3) && (address_cycles != 4)) {
LOG_ERROR("LPC3180 only supports 3 or 4 address cycles, not %i", address_cycles);
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
- if ((page_size != 512) && (page_size != 2048))
- {
+ if ((page_size != 512) && (page_size != 2048)) {
LOG_ERROR("LPC3180 only supports 512 or 2048 byte pages, not %i", page_size);
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
/* select MLC controller if none is currently selected */
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
LOG_DEBUG("no LPC3180 NAND flash controller selected, using default 'mlc'");
lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER;
}
- if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
uint32_t mlc_icr_value = 0x0;
float cycle;
int twp, twh, trp, treh, trhz, trbwb, tcea;
((trbwb & 0x1f) << 19) | ((tcea & 0x3) << 24));
lpc3180_reset(nand);
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
float cycle;
int r_setup, r_hold, r_width, r_rdy;
int w_setup, w_hold, w_width, w_rdy;
/* after reset set other registers of SLC so reset calling is here at the begining*/
lpc3180_reset(nand);
- /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA read from SLC, WIDTH = bus_width) */
+ /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled,
+ *DMA read from SLC, WIDTH = bus_width) */
target_write_u32(target, 0x20020014, 0x3e | (bus_width == 16) ? 1 : 0);
/* SLC_IEN = 3 (INT_RDY_EN = 1) ,(INT_TC_STAT = 1) */
target_write_u32(target, 0x20020020, 0x03);
- /* DMA configuration */
- /* DMACLK_CTRL = 0x01 (enable clock for DMA controller) */
+ /* DMA configuration
+ * DMACLK_CTRL = 0x01 (enable clock for DMA controller) */
target_write_u32(target, 0x400040e8, 0x01);
/* DMACConfig = DMA enabled*/
target_write_u32(target, 0x31000030, 0x01);
-
+
/* calculate NAND controller timings */
cycle = lpc3180_cycle_time(nand);
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
return ERROR_NAND_OPERATION_FAILED;
- }
- else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
/* MLC_CMD = 0xff (reset controller and NAND device) */
target_write_u32(target, 0x200b8000, 0xff);
- if (!lpc3180_controller_ready(nand, 100))
- {
+ if (!lpc3180_controller_ready(nand, 100)) {
LOG_ERROR("LPC3180 NAND controller timed out after reset");
return ERROR_NAND_OPERATION_TIMEOUT;
}
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
/* SLC_CTRL = 0x6 (ECC_CLEAR, SW_RESET) */
target_write_u32(target, 0x20020010, 0x6);
- if (!lpc3180_controller_ready(nand, 100))
- {
+ if (!lpc3180_controller_ready(nand, 100)) {
LOG_ERROR("LPC3180 NAND controller timed out after reset");
return ERROR_NAND_OPERATION_TIMEOUT;
}
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
return ERROR_NAND_OPERATION_FAILED;
- }
- else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
/* MLC_CMD = command */
target_write_u32(target, 0x200b8000, command);
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
/* SLC_CMD = command */
target_write_u32(target, 0x20020008, command);
}
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
return ERROR_NAND_OPERATION_FAILED;
- }
- else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
/* MLC_ADDR = address */
target_write_u32(target, 0x200b8004, address);
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
/* SLC_ADDR = address */
target_write_u32(target, 0x20020004, address);
}
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
return ERROR_NAND_OPERATION_FAILED;
- }
- else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
/* MLC_DATA = data */
target_write_u32(target, 0x200b0000, data);
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
/* SLC_DATA = data */
target_write_u32(target, 0x20020000, data);
}
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
return ERROR_NAND_OPERATION_FAILED;
- }
- else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
/* data = MLC_DATA, use sized access */
- if (nand->bus_width == 8)
- {
+ if (nand->bus_width == 8) {
uint8_t *data8 = data;
target_read_u8(target, 0x200b0000, data8);
- }
- else if (nand->bus_width == 16)
- {
+ } else if (nand->bus_width == 16) {
uint16_t *data16 = data;
target_read_u16(target, 0x200b0000, data16);
- }
- else
- {
+ } else {
LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
return ERROR_NAND_OPERATION_FAILED;
}
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
uint32_t data32;
/* data = SLC_DATA, must use 32-bit access */
target_read_u32(target, 0x20020000, &data32);
- if (nand->bus_width == 8)
- {
+ if (nand->bus_width == 8) {
uint8_t *data8 = data;
*data8 = data32 & 0xff;
- }
- else if (nand->bus_width == 16)
- {
+ } else if (nand->bus_width == 16) {
uint16_t *data16 = data;
*data16 = data32 & 0xffff;
- }
- else
- {
+ } else {
LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
return ERROR_NAND_OPERATION_FAILED;
}
return ERROR_OK;
}
-static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+static int lpc3180_write_page(struct nand_device *nand,
+ uint32_t page,
+ uint8_t *data,
+ uint32_t data_size,
+ uint8_t *oob,
+ uint32_t oob_size)
{
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
uint8_t status;
uint8_t *page_buffer;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
return ERROR_NAND_OPERATION_FAILED;
- }
- else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
uint8_t *oob_buffer;
int quarter, num_quarters;
- if (!data && oob)
- {
+ if (!data && oob) {
LOG_ERROR("LPC3180 MLC controller can't write OOB data only");
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
- if (oob && (oob_size > 24))
- {
+ if (oob && (oob_size > 24)) {
LOG_ERROR("LPC3180 MLC controller can't write more "
"than 6 bytes for each quarter's OOB data");
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
- if (data_size > (uint32_t)nand->page_size)
- {
+ if (data_size > (uint32_t)nand->page_size) {
LOG_ERROR("data size exceeds page size");
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
page_buffer = malloc(512);
oob_buffer = malloc(6);
- if (nand->page_size == 512)
- {
+ if (nand->page_size == 512) {
/* MLC_ADDR = 0x0 (one column cycle) */
target_write_u32(target, 0x200b8004, 0x0);
if (nand->address_cycles == 4)
target_write_u32(target, 0x200b8004, (page >> 16) & 0xff);
- }
- else
- {
+ } else {
/* MLC_ADDR = 0x0 (two column cycles) */
target_write_u32(target, 0x200b8004, 0x0);
target_write_u32(target, 0x200b8004, 0x0);
*/
num_quarters = (nand->page_size == 2048) ? 4 : 1;
- for (quarter = 0; quarter < num_quarters; quarter++)
- {
+ for (quarter = 0; quarter < num_quarters; quarter++) {
int thisrun_data_size = (data_size > 512) ? 512 : data_size;
int thisrun_oob_size = (oob_size > 6) ? 6 : oob_size;
memset(page_buffer, 0xff, 512);
- if (data)
- {
+ if (data) {
memcpy(page_buffer, data, thisrun_data_size);
data_size -= thisrun_data_size;
data += thisrun_data_size;
}
memset(oob_buffer, 0xff, 6);
- if (oob)
- {
+ if (oob) {
memcpy(oob_buffer, oob, thisrun_oob_size);
oob_size -= thisrun_oob_size;
oob += thisrun_oob_size;
target_write_u32(target, 0x200b8008, 0x0);
target_write_memory(target, 0x200a8000,
- 4, 128, page_buffer);
+ 4, 128, page_buffer);
target_write_memory(target, 0x200a8000,
- 1, 6, oob_buffer);
+ 1, 6, oob_buffer);
/* write MLC_ECC_AUTO_ENC_REG to start auto encode */
target_write_u32(target, 0x200b8010, 0x0);
- if (!lpc3180_controller_ready(nand, 1000))
- {
- LOG_ERROR("timeout while waiting for completion of auto encode cycle");
+ if (!lpc3180_controller_ready(nand, 1000)) {
+ LOG_ERROR(
+ "timeout while waiting for completion of auto encode cycle");
return ERROR_NAND_OPERATION_FAILED;
}
}
/* MLC_CMD = auto program command */
target_write_u32(target, 0x200b8000, NAND_CMD_PAGEPROG);
- if ((retval = nand_read_status(nand, &status)) != ERROR_OK)
- {
+ retval = nand_read_status(nand, &status);
+ if (retval != ERROR_OK) {
LOG_ERROR("couldn't read status");
return ERROR_NAND_OPERATION_FAILED;
}
- if (status & NAND_STATUS_FAIL)
- {
+ if (status & NAND_STATUS_FAIL) {
LOG_ERROR("write operation didn't pass, status: 0x%2.2x", status);
return ERROR_NAND_OPERATION_FAILED;
}
free(page_buffer);
free(oob_buffer);
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
-
- /**********************************************************************
- * Write both SLC NAND flash page main area and spare area.
- * Small page -
- * ------------------------------------------
- * | 512 bytes main | 16 bytes spare |
- * ------------------------------------------
- * Large page -
- * ------------------------------------------
- * | 2048 bytes main | 64 bytes spare |
- * ------------------------------------------
- * If DMA & ECC enabled, then the ECC generated for the 1st 256-byte
- * data is written to the 3rd word of the spare area. The ECC
- * generated for the 2nd 256-byte data is written to the 4th word
- * of the spare area. The ECC generated for the 3rd 256-byte data is
- * written to the 7th word of the spare area. The ECC generated
- * for the 4th 256-byte data is written to the 8th word of the
- * spare area and so on.
- *
- **********************************************************************/
-
- int i=0,target_mem_base;
- uint8_t *ecc_flash_buffer;
- struct working_area *pworking_area;
-
-
- if(lpc3180_info->is_bulk){
-
- if (!data && oob){
- /*if oob only mode is active original method is used as SLC controller hangs during DMA interworking. Anyway the code supports the oob only mode below. */
- return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
- }
- retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
- if (ERROR_OK != retval)
- return retval;
-
- /* allocate a working area */
- if (target->working_area_size < (uint32_t) nand->page_size + 0x200){
- LOG_ERROR("Reserve at least 0x%x physical target working area",nand->page_size + 0x200);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (target->working_area_phys%4){
- LOG_ERROR("Reserve the physical target working area at word boundary");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (target_alloc_working_area(target, target->working_area_size, &pworking_area) != ERROR_OK)
- {
- LOG_ERROR("no working area specified, can't read LPC internal flash");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- target_mem_base = target->working_area_phys;
-
-
- if (nand->page_size == 2048)
- {
- page_buffer = malloc(2048);
- }
- else
- {
- page_buffer = malloc(512);
- }
-
- ecc_flash_buffer = malloc(64);
-
- /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA write to SLC, WIDTH = bus_width) */
- target_write_u32(target, 0x20020014, 0x3c);
-
- if( data && !oob){
- /* set DMA LLI-s in target memory and in DMA*/
- for(i=0;i<nand->page_size/0x100;i++){
-
- int tmp;
- /* -------LLI for 256 byte block---------*/
- /* DMACC0SrcAddr = SRAM */
- target_write_u32(target,target_mem_base+0+i*32,target_mem_base+DATA_OFFS+i*256 );
- if(i==0) target_write_u32(target,0x31000100,target_mem_base+DATA_OFFS );
- /* DMACCxDestAddr = SLC_DMA_DATA */
- target_write_u32(target,target_mem_base+4+i*32,0x20020038 );
- if(i==0) target_write_u32(target,0x31000104,0x20020038 );
- /* DMACCxLLI = next element */
- tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc;
- target_write_u32(target,target_mem_base+8+i*32, tmp );
- if(i==0) target_write_u32(target,0x31000108, tmp );
- /* DMACCxControl = TransferSize =64, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
- Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 1,
- Destination increment = 0, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,target_mem_base+12+i*32,0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
- if(i==0) target_write_u32(target,0x3100010c,0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
-
- /* -------LLI for 3 byte ECC---------*/
- /* DMACC0SrcAddr = SLC_ECC*/
- target_write_u32(target,target_mem_base+16+i*32,0x20020034 );
- /* DMACCxDestAddr = SRAM */
- target_write_u32(target,target_mem_base+20+i*32,target_mem_base+SPARE_OFFS+8+16*(i>>1)+(i%2)*4 );
- /* DMACCxLLI = next element */
- tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc;
- target_write_u32(target,target_mem_base+24+i*32, tmp );
- /* DMACCxControl = TransferSize =1, Source burst size =4, Destination burst size = 4, Source transfer width = 32 bit,
- Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0,
- Destination increment = 1, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,target_mem_base+28+i*32,0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
- }
- }
- else if (data && oob){
- /* -------LLI for 512 or 2048 bytes page---------*/
- /* DMACC0SrcAddr = SRAM */
- target_write_u32(target,target_mem_base,target_mem_base+DATA_OFFS );
- target_write_u32(target,0x31000100,target_mem_base+DATA_OFFS );
- /* DMACCxDestAddr = SLC_DMA_DATA */
- target_write_u32(target,target_mem_base+4,0x20020038 );
- target_write_u32(target,0x31000104,0x20020038 );
- /* DMACCxLLI = next element */
- target_write_u32(target,target_mem_base+8, (target_mem_base+32)&0xfffffffc );
- target_write_u32(target,0x31000108, (target_mem_base+32)&0xfffffffc );
- /* DMACCxControl = TransferSize =512 or 128, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
- Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 1,
- Destination increment = 0, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,target_mem_base+12,(nand->page_size==2048?512:128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
- target_write_u32(target,0x3100010c,(nand->page_size==2048?512:128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
- i = 1;
- }
- else if (!data && oob){
- i = 0;
- }
-
- /* -------LLI for spare area---------*/
- /* DMACC0SrcAddr = SRAM*/
- target_write_u32(target,target_mem_base+0+i*32,target_mem_base+SPARE_OFFS );
- if(i==0) target_write_u32(target,0x31000100,target_mem_base+SPARE_OFFS );
- /* DMACCxDestAddr = SLC_DMA_DATA */
- target_write_u32(target,target_mem_base+4+i*32,0x20020038 );
- if(i==0) target_write_u32(target,0x31000104,0x20020038 );
- /* DMACCxLLI = next element = NULL */
- target_write_u32(target,target_mem_base+8+i*32, 0 );
- if(i==0) target_write_u32(target,0x31000108,0 );
- /* DMACCxControl = TransferSize =16 for large page or 4 for small page, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
- Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 1,
- Destination increment = 0, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,target_mem_base+12+i*32, (nand->page_size==2048?0x10:0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31);
- if(i==0) target_write_u32(target,0x3100010c,(nand->page_size==2048?0x10:0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 | 0<<27| 0<<31 );
-
-
-
- memset(ecc_flash_buffer, 0xff, 64);
- if( oob ){
- memcpy(ecc_flash_buffer,oob, oob_size);
- }
- target_write_memory(target, target_mem_base+SPARE_OFFS, 4, 16, ecc_flash_buffer);
-
- if (data){
- memset(page_buffer, 0xff, nand->page_size == 2048?2048:512);
- memcpy(page_buffer,data, data_size);
- target_write_memory(target, target_mem_base+DATA_OFFS, 4, nand->page_size == 2048?512:128, page_buffer);
- }
-
- free(page_buffer);
- free(ecc_flash_buffer);
-
- /* Enable DMA after channel set up !
- LLI only works when DMA is the flow controller!
- */
- /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC), FlowCntrl = 2 (Pher -> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/
- target_write_u32(target,0x31000110, 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18);
-
-
-
- /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
- target_write_u32(target, 0x20020010, 0x3);
-
- /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
- target_write_u32(target, 0x20020028, 2);
-
- /* SLC_TC */
- if (!data && oob)
- target_write_u32(target, 0x20020030, (nand->page_size==2048?0x10:0x04));
- else
- target_write_u32(target, 0x20020030, (nand->page_size==2048?0x840:0x210));
-
- nand_write_finish(nand);
-
-
- if (!lpc3180_tc_ready(nand, 1000))
- {
- LOG_ERROR("timeout while waiting for completion of DMA");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_free_working_area(target,pworking_area);
-
- LOG_INFO("Page = 0x%" PRIx32 " was written.",page);
-
- }
- else
- return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
- }
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
+
+ /**********************************************************************
+ * Write both SLC NAND flash page main area and spare area.
+ * Small page -
+ * ------------------------------------------
+ * | 512 bytes main | 16 bytes spare |
+ * ------------------------------------------
+ * Large page -
+ * ------------------------------------------
+ * | 2048 bytes main | 64 bytes spare |
+ * ------------------------------------------
+ * If DMA & ECC enabled, then the ECC generated for the 1st 256-byte
+ * data is written to the 3rd word of the spare area. The ECC
+ * generated for the 2nd 256-byte data is written to the 4th word
+ * of the spare area. The ECC generated for the 3rd 256-byte data is
+ * written to the 7th word of the spare area. The ECC generated
+ * for the 4th 256-byte data is written to the 8th word of the
+ * spare area and so on.
+ *
+ **********************************************************************/
+
+ int i = 0, target_mem_base;
+ uint8_t *ecc_flash_buffer;
+ struct working_area *pworking_area;
+
+ if (lpc3180_info->is_bulk) {
+
+ if (!data && oob) {
+ /*if oob only mode is active original method is used as SLC
+ *controller hangs during DMA interworking. Anyway the code supports
+ *the oob only mode below. */
+ return nand_write_page_raw(nand,
+ page,
+ data,
+ data_size,
+ oob,
+ oob_size);
+ }
+ retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
+ if (ERROR_OK != retval)
+ return retval;
+
+ /* allocate a working area */
+ if (target->working_area_size < (uint32_t) nand->page_size + 0x200) {
+ LOG_ERROR("Reserve at least 0x%x physical target working area",
+ nand->page_size + 0x200);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ if (target->working_area_phys%4) {
+ LOG_ERROR(
+ "Reserve the physical target working area at word boundary");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ if (target_alloc_working_area(target, target->working_area_size,
+ &pworking_area) != ERROR_OK) {
+ LOG_ERROR("no working area specified, can't read LPC internal flash");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ target_mem_base = target->working_area_phys;
+
+ if (nand->page_size == 2048)
+ page_buffer = malloc(2048);
+ else
+ page_buffer = malloc(512);
+
+ ecc_flash_buffer = malloc(64);
+
+ /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst
+ *enabled, DMA write to SLC, WIDTH = bus_width) */
+ target_write_u32(target, 0x20020014, 0x3c);
+
+ if (data && !oob) {
+ /* set DMA LLI-s in target memory and in DMA*/
+ for (i = 0; i < nand->page_size/0x100; i++) {
+
+ int tmp;
+ /* -------LLI for 256 byte block---------
+ * DMACC0SrcAddr = SRAM */
+ target_write_u32(target,
+ target_mem_base+0+i*32,
+ target_mem_base+DATA_OFFS+i*256);
+ if (i == 0)
+ target_write_u32(target,
+ 0x31000100,
+ target_mem_base+DATA_OFFS);
+ /* DMACCxDestAddr = SLC_DMA_DATA */
+ target_write_u32(target, target_mem_base+4+i*32, 0x20020038);
+ if (i == 0)
+ target_write_u32(target, 0x31000104, 0x20020038);
+ /* DMACCxLLI = next element */
+ tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc;
+ target_write_u32(target, target_mem_base+8+i*32, tmp);
+ if (i == 0)
+ target_write_u32(target, 0x31000108, tmp);
+ /* DMACCxControl = TransferSize =64, Source burst size =16,
+ * Destination burst size = 16, Source transfer width = 32 bit,
+ * Destination transfer width = 32 bit, Source AHB master select = M0,
+ * Destination AHB master select = M0, Source increment = 1,
+ * Destination increment = 0, Terminal count interrupt enable bit = 0*/
+ target_write_u32(target,
+ target_mem_base+12+i*32,
+ 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 |
+ 0<<27 | 0<<31);
+ if (i == 0)
+ target_write_u32(target,
+ 0x3100010c,
+ 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 |
+ 0<<27 | 0<<31);
+
+ /* -------LLI for 3 byte ECC---------
+ * DMACC0SrcAddr = SLC_ECC*/
+ target_write_u32(target, target_mem_base+16+i*32, 0x20020034);
+ /* DMACCxDestAddr = SRAM */
+ target_write_u32(target,
+ target_mem_base+20+i*32,
+ target_mem_base+SPARE_OFFS+8+16*(i>>1)+(i%2)*4);
+ /* DMACCxLLI = next element */
+ tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc;
+ target_write_u32(target, target_mem_base+24+i*32, tmp);
+ /* DMACCxControl = TransferSize =1, Source burst size =4,
+ * Destination burst size = 4, Source transfer width = 32 bit,
+ * Destination transfer width = 32 bit, Source AHB master select = M0,
+ * Destination AHB master select = M0, Source increment = 0,
+ * Destination increment = 1, Terminal count interrupt enable bit = 0*/
+ target_write_u32(target,
+ target_mem_base+28+i*32,
+ 0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<
+ 31);
+ }
+ } else if (data && oob) {
+ /* -------LLI for 512 or 2048 bytes page---------
+ * DMACC0SrcAddr = SRAM */
+ target_write_u32(target, target_mem_base, target_mem_base+DATA_OFFS);
+ target_write_u32(target, 0x31000100, target_mem_base+DATA_OFFS);
+ /* DMACCxDestAddr = SLC_DMA_DATA */
+ target_write_u32(target, target_mem_base+4, 0x20020038);
+ target_write_u32(target, 0x31000104, 0x20020038);
+ /* DMACCxLLI = next element */
+ target_write_u32(target,
+ target_mem_base+8,
+ (target_mem_base+32)&0xfffffffc);
+ target_write_u32(target, 0x31000108,
+ (target_mem_base+32)&0xfffffffc);
+ /* DMACCxControl = TransferSize =512 or 128, Source burst size =16,
+ * Destination burst size = 16, Source transfer width = 32 bit,
+ * Destination transfer width = 32 bit, Source AHB master select = M0,
+ * Destination AHB master select = M0, Source increment = 1,
+ * Destination increment = 0, Terminal count interrupt enable bit = 0*/
+ target_write_u32(target,
+ target_mem_base+12,
+ (nand->page_size ==
+ 2048 ? 512 : 128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 |
+ 1<<26 | 0<<27 | 0<<31);
+ target_write_u32(target,
+ 0x3100010c,
+ (nand->page_size ==
+ 2048 ? 512 : 128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 |
+ 1<<26 | 0<<27 | 0<<31);
+ i = 1;
+ } else if (!data && oob)
+ i = 0;
+
+ /* -------LLI for spare area---------
+ * DMACC0SrcAddr = SRAM*/
+ target_write_u32(target, target_mem_base+0+i*32, target_mem_base+SPARE_OFFS);
+ if (i == 0)
+ target_write_u32(target, 0x31000100, target_mem_base+SPARE_OFFS);
+ /* DMACCxDestAddr = SLC_DMA_DATA */
+ target_write_u32(target, target_mem_base+4+i*32, 0x20020038);
+ if (i == 0)
+ target_write_u32(target, 0x31000104, 0x20020038);
+ /* DMACCxLLI = next element = NULL */
+ target_write_u32(target, target_mem_base+8+i*32, 0);
+ if (i == 0)
+ target_write_u32(target, 0x31000108, 0);
+ /* DMACCxControl = TransferSize =16 for large page or 4 for small page,
+ * Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
+ * Destination transfer width = 32 bit, Source AHB master select = M0,
+ * Destination AHB master select = M0, Source increment = 1,
+ * Destination increment = 0, Terminal count interrupt enable bit = 0*/
+ target_write_u32(target,
+ target_mem_base+12+i*32,
+ (nand->page_size ==
+ 2048 ? 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 |
+ 0<<27 | 0<<31);
+ if (i == 0)
+ target_write_u32(target, 0x3100010c,
+ (nand->page_size == 2048 ?
+ 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 |
+ 0<<25 | 1<<26 | 0<<27 | 0<<31);
+
+ memset(ecc_flash_buffer, 0xff, 64);
+ if (oob)
+ memcpy(ecc_flash_buffer, oob, oob_size);
+ target_write_memory(target,
+ target_mem_base+SPARE_OFFS,
+ 4,
+ 16,
+ ecc_flash_buffer);
+
+ if (data) {
+ memset(page_buffer, 0xff, nand->page_size == 2048 ? 2048 : 512);
+ memcpy(page_buffer, data, data_size);
+ target_write_memory(target,
+ target_mem_base+DATA_OFFS,
+ 4,
+ nand->page_size == 2048 ? 512 : 128,
+ page_buffer);
+ }
+
+ free(page_buffer);
+ free(ecc_flash_buffer);
+
+ /* Enable DMA after channel set up !
+ LLI only works when DMA is the flow controller!
+ */
+ /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC),
+ *FlowCntrl = 2 (Pher -> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/
+ target_write_u32(target,
+ 0x31000110,
+ 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18);
+ /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
+ target_write_u32(target, 0x20020010, 0x3);
+
+ /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
+ target_write_u32(target, 0x20020028, 2);
+
+ /* SLC_TC */
+ if (!data && oob)
+ target_write_u32(target, 0x20020030,
+ (nand->page_size == 2048 ? 0x10 : 0x04));
+ else
+ target_write_u32(target, 0x20020030,
+ (nand->page_size == 2048 ? 0x840 : 0x210));
+
+ nand_write_finish(nand);
+
+ if (!lpc3180_tc_ready(nand, 1000)) {
+ LOG_ERROR("timeout while waiting for completion of DMA");
+ return ERROR_NAND_OPERATION_FAILED;
+ }
+
+ target_free_working_area(target, pworking_area);
+
+ LOG_INFO("Page = 0x%" PRIx32 " was written.", page);
+
+ } else
+ return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
+ }
return ERROR_OK;
}
-static int lpc3180_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
+static int lpc3180_read_page(struct nand_device *nand,
+ uint32_t page,
+ uint8_t *data,
+ uint32_t data_size,
+ uint8_t *oob,
+ uint32_t oob_size)
{
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
uint8_t *page_buffer;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER)
- {
+ if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
return ERROR_NAND_OPERATION_FAILED;
- }
- else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
uint8_t *oob_buffer;
uint32_t page_bytes_done = 0;
uint32_t oob_bytes_done = 0;
uint32_t mlc_isr;
#if 0
- if (oob && (oob_size > 6))
- {
+ if (oob && (oob_size > 6)) {
LOG_ERROR("LPC3180 MLC controller can't read more than 6 bytes of OOB data");
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
#endif
- if (data_size > (uint32_t)nand->page_size)
- {
+ if (data_size > (uint32_t)nand->page_size) {
LOG_ERROR("data size exceeds page size");
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
- if (nand->page_size == 2048)
- {
+ if (nand->page_size == 2048) {
page_buffer = malloc(2048);
oob_buffer = malloc(64);
- }
- else
- {
+ } else {
page_buffer = malloc(512);
oob_buffer = malloc(16);
}
- if (!data && oob)
- {
+ if (!data && oob) {
/* MLC_CMD = Read OOB
* we can use the READOOB command on both small and large page devices,
* as the controller translates the 0x50 command to a 0x0 with appropriate
* positioning of the serial buffer read pointer
*/
target_write_u32(target, 0x200b8000, NAND_CMD_READOOB);
- }
- else
- {
+ } else {
/* MLC_CMD = Read0 */
target_write_u32(target, 0x200b8000, NAND_CMD_READ0);
}
- if (nand->page_size == 512)
- {
- /* small page device */
- /* MLC_ADDR = 0x0 (one column cycle) */
+ if (nand->page_size == 512) {
+ /* small page device
+ * MLC_ADDR = 0x0 (one column cycle) */
target_write_u32(target, 0x200b8004, 0x0);
/* MLC_ADDR = row */
if (nand->address_cycles == 4)
target_write_u32(target, 0x200b8004, (page >> 16) & 0xff);
- }
- else
- {
- /* large page device */
- /* MLC_ADDR = 0x0 (two column cycles) */
+ } else {
+ /* large page device
+ * MLC_ADDR = 0x0 (two column cycles) */
target_write_u32(target, 0x200b8004, 0x0);
target_write_u32(target, 0x200b8004, 0x0);
target_write_u32(target, 0x200b8000, NAND_CMD_READSTART);
}
- while (page_bytes_done < (uint32_t)nand->page_size)
- {
+ while (page_bytes_done < (uint32_t)nand->page_size) {
/* MLC_ECC_AUTO_DEC_REG = dummy */
target_write_u32(target, 0x200b8014, 0xaa55aa55);
- if (!lpc3180_controller_ready(nand, 1000))
- {
- LOG_ERROR("timeout while waiting for completion of auto decode cycle");
+ if (!lpc3180_controller_ready(nand, 1000)) {
+ LOG_ERROR(
+ "timeout while waiting for completion of auto decode cycle");
return ERROR_NAND_OPERATION_FAILED;
}
target_read_u32(target, 0x200b8048, &mlc_isr);
- if (mlc_isr & 0x8)
- {
- if (mlc_isr & 0x40)
- {
- LOG_ERROR("uncorrectable error detected: 0x%2.2x", (unsigned)mlc_isr);
+ if (mlc_isr & 0x8) {
+ if (mlc_isr & 0x40) {
+ LOG_ERROR("uncorrectable error detected: 0x%2.2x",
+ (unsigned)mlc_isr);
return ERROR_NAND_OPERATION_FAILED;
}
- LOG_WARNING("%i symbol error detected and corrected", ((int)(((mlc_isr & 0x30) >> 4) + 1)));
+ LOG_WARNING("%i symbol error detected and corrected",
+ ((int)(((mlc_isr & 0x30) >> 4) + 1)));
}
if (data)
- {
- target_read_memory(target, 0x200a8000, 4, 128, page_buffer + page_bytes_done);
- }
+ target_read_memory(target,
+ 0x200a8000,
+ 4,
+ 128,
+ page_buffer + page_bytes_done);
if (oob)
- {
- target_read_memory(target, 0x200a8000, 4, 4, oob_buffer + oob_bytes_done);
- }
+ target_read_memory(target,
+ 0x200a8000,
+ 4,
+ 4,
+ oob_buffer + oob_bytes_done);
page_bytes_done += 512;
oob_bytes_done += 16;
free(page_buffer);
free(oob_buffer);
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
+
+ /**********************************************************************
+ * Read both SLC NAND flash page main area and spare area.
+ * Small page -
+ * ------------------------------------------
+ * | 512 bytes main | 16 bytes spare |
+ * ------------------------------------------
+ * Large page -
+ * ------------------------------------------
+ * | 2048 bytes main | 64 bytes spare |
+ * ------------------------------------------
+ * If DMA & ECC enabled, then the ECC generated for the 1st 256-byte
+ * data is compared with the 3rd word of the spare area. The ECC
+ * generated for the 2nd 256-byte data is compared with the 4th word
+ * of the spare area. The ECC generated for the 3rd 256-byte data is
+ * compared with the 7th word of the spare area. The ECC generated
+ * for the 4th 256-byte data is compared with the 8th word of the
+ * spare area and so on.
+ *
+ **********************************************************************/
+
+ int retval, i, target_mem_base;
+ uint8_t *ecc_hw_buffer;
+ uint8_t *ecc_flash_buffer;
+ struct working_area *pworking_area;
+
+ if (lpc3180_info->is_bulk) {
+
+ /* read always the data and also oob areas*/
+
+ retval = nand_page_command(nand, page, NAND_CMD_READ0, 0);
+ if (ERROR_OK != retval)
+ return retval;
+
+ /* allocate a working area */
+ if (target->working_area_size < (uint32_t) nand->page_size + 0x200) {
+ LOG_ERROR("Reserve at least 0x%x physical target working area",
+ nand->page_size + 0x200);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ if (target->working_area_phys%4) {
+ LOG_ERROR(
+ "Reserve the physical target working area at word boundary");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ if (target_alloc_working_area(target, target->working_area_size,
+ &pworking_area) != ERROR_OK) {
+ LOG_ERROR("no working area specified, can't read LPC internal flash");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ target_mem_base = target->working_area_phys;
+
+ if (nand->page_size == 2048)
+ page_buffer = malloc(2048);
+ else
+ page_buffer = malloc(512);
+
+ ecc_hw_buffer = malloc(32);
+ ecc_flash_buffer = malloc(64);
+
+ /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst
+ *enabled, DMA read from SLC, WIDTH = bus_width) */
+ target_write_u32(target, 0x20020014, 0x3e);
+
+ /* set DMA LLI-s in target memory and in DMA*/
+ for (i = 0; i < nand->page_size/0x100; i++) {
+ int tmp;
+ /* -------LLI for 256 byte block---------
+ * DMACC0SrcAddr = SLC_DMA_DATA*/
+ target_write_u32(target, target_mem_base+0+i*32, 0x20020038);
+ if (i == 0)
+ target_write_u32(target, 0x31000100, 0x20020038);
+ /* DMACCxDestAddr = SRAM */
+ target_write_u32(target,
+ target_mem_base+4+i*32,
+ target_mem_base+DATA_OFFS+i*256);
+ if (i == 0)
+ target_write_u32(target,
+ 0x31000104,
+ target_mem_base+DATA_OFFS);
+ /* DMACCxLLI = next element */
+ tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc;
+ target_write_u32(target, target_mem_base+8+i*32, tmp);
+ if (i == 0)
+ target_write_u32(target, 0x31000108, tmp);
+ /* DMACCxControl = TransferSize =64, Source burst size =16,
+ * Destination burst size = 16, Source transfer width = 32 bit,
+ * Destination transfer width = 32 bit, Source AHB master select = M0,
+ * Destination AHB master select = M0, Source increment = 0,
+ * Destination increment = 1, Terminal count interrupt enable bit = 0*/
+ target_write_u32(target,
+ target_mem_base+12+i*32,
+ 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<
+ 31);
+ if (i == 0)
+ target_write_u32(target,
+ 0x3100010c,
+ 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<
+ 31);
+
+ /* -------LLI for 3 byte ECC---------
+ * DMACC0SrcAddr = SLC_ECC*/
+ target_write_u32(target, target_mem_base+16+i*32, 0x20020034);
+ /* DMACCxDestAddr = SRAM */
+ target_write_u32(target,
+ target_mem_base+20+i*32,
+ target_mem_base+ECC_OFFS+i*4);
+ /* DMACCxLLI = next element */
+ tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc;
+ target_write_u32(target, target_mem_base+24+i*32, tmp);
+ /* DMACCxControl = TransferSize =1, Source burst size =4,
+ * Destination burst size = 4, Source transfer width = 32 bit,
+ * Destination transfer width = 32 bit, Source AHB master select = M0,
+ * Destination AHB master select = M0, Source increment = 0,
+ * Destination increment = 1, Terminal count interrupt enable bit = 0*/
+ target_write_u32(target,
+ target_mem_base+28+i*32,
+ 0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<
+ 31);
+ }
+
+ /* -------LLI for spare area---------
+ * DMACC0SrcAddr = SLC_DMA_DATA*/
+ target_write_u32(target, target_mem_base+0+i*32, 0x20020038);
+ /* DMACCxDestAddr = SRAM */
+ target_write_u32(target, target_mem_base+4+i*32, target_mem_base+SPARE_OFFS);
+ /* DMACCxLLI = next element = NULL */
+ target_write_u32(target, target_mem_base+8+i*32, 0);
+ /* DMACCxControl = TransferSize =16 for large page or 4 for small page,
+ * Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
+ * Destination transfer width = 32 bit, Source AHB master select = M0,
+ * Destination AHB master select = M0, Source increment = 0,
+ * Destination increment = 1, Terminal count interrupt enable bit = 0*/
+ target_write_u32(target,
+ target_mem_base + 12 + i * 32,
+ (nand->page_size == 2048 ? 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 |
+ 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<31);
+
+ /* Enable DMA after channel set up !
+ LLI only works when DMA is the flow controller!
+ */
+ /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC),
+ *FlowCntrl = 2 (Pher-> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/
+ target_write_u32(target,
+ 0x31000110,
+ 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18);
+
+ /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
+ target_write_u32(target, 0x20020010, 0x3);
+
+ /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
+ target_write_u32(target, 0x20020028, 2);
+
+ /* SLC_TC */
+ target_write_u32(target, 0x20020030,
+ (nand->page_size == 2048 ? 0x840 : 0x210));
+
+ if (!lpc3180_tc_ready(nand, 1000)) {
+ LOG_ERROR("timeout while waiting for completion of DMA");
+ free(page_buffer);
+ free(ecc_hw_buffer);
+ free(ecc_flash_buffer);
+ target_free_working_area(target, pworking_area);
+ return ERROR_NAND_OPERATION_FAILED;
+ }
+
+ if (data) {
+ target_read_memory(target,
+ target_mem_base+DATA_OFFS,
+ 4,
+ nand->page_size == 2048 ? 512 : 128,
+ page_buffer);
+ memcpy(data, page_buffer, data_size);
+
+ LOG_INFO("Page = 0x%" PRIx32 " was read.", page);
+
+ /* check hw generated ECC for each 256 bytes block with the saved
+ *ECC in flash spare area*/
+ int idx = nand->page_size/0x200;
+ target_read_memory(target,
+ target_mem_base+SPARE_OFFS,
+ 4,
+ 16,
+ ecc_flash_buffer);
+ target_read_memory(target,
+ target_mem_base+ECC_OFFS,
+ 4,
+ 8,
+ ecc_hw_buffer);
+ for (i = 0; i < idx; i++) {
+ if ((0x00ffffff & *(uint32_t *)(void *)(ecc_hw_buffer+i*8)) !=
+ (0x00ffffff & *(uint32_t *)(void *)(ecc_flash_buffer+8+i*16)))
+ LOG_WARNING(
+ "ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32,
+ i * 2 + 1, page);
+ if ((0x00ffffff & *(uint32_t *)(void *)(ecc_hw_buffer+4+i*8)) !=
+ (0x00ffffff & *(uint32_t *)(void *)(ecc_flash_buffer+12+i*16)))
+ LOG_WARNING(
+ "ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32,
+ i * 2 + 2, page);
+ }
+ }
+
+ if (oob)
+ memcpy(oob, ecc_flash_buffer, oob_size);
- /**********************************************************************
- * Read both SLC NAND flash page main area and spare area.
- * Small page -
- * ------------------------------------------
- * | 512 bytes main | 16 bytes spare |
- * ------------------------------------------
- * Large page -
- * ------------------------------------------
- * | 2048 bytes main | 64 bytes spare |
- * ------------------------------------------
- * If DMA & ECC enabled, then the ECC generated for the 1st 256-byte
- * data is compared with the 3rd word of the spare area. The ECC
- * generated for the 2nd 256-byte data is compared with the 4th word
- * of the spare area. The ECC generated for the 3rd 256-byte data is
- * compared with the 7th word of the spare area. The ECC generated
- * for the 4th 256-byte data is compared with the 8th word of the
- * spare area and so on.
- *
- **********************************************************************/
-
- int retval,i,target_mem_base;
- uint8_t *ecc_hw_buffer;
- uint8_t *ecc_flash_buffer;
- struct working_area *pworking_area;
-
- if(lpc3180_info->is_bulk){
-
- /* read always the data and also oob areas*/
-
- retval = nand_page_command(nand, page, NAND_CMD_READ0, 0);
- if (ERROR_OK != retval)
- return retval;
-
- /* allocate a working area */
- if (target->working_area_size < (uint32_t) nand->page_size + 0x200){
- LOG_ERROR("Reserve at least 0x%x physical target working area",nand->page_size + 0x200);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (target->working_area_phys%4){
- LOG_ERROR("Reserve the physical target working area at word boundary");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (target_alloc_working_area(target, target->working_area_size, &pworking_area) != ERROR_OK)
- {
- LOG_ERROR("no working area specified, can't read LPC internal flash");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- target_mem_base = target->working_area_phys;
-
- if (nand->page_size == 2048)
- {
- page_buffer = malloc(2048);
- }
- else
- {
- page_buffer = malloc(512);
- }
-
- ecc_hw_buffer = malloc(32);
- ecc_flash_buffer = malloc(64);
-
- /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled, DMA read from SLC, WIDTH = bus_width) */
- target_write_u32(target, 0x20020014, 0x3e);
-
- /* set DMA LLI-s in target memory and in DMA*/
- for(i=0;i<nand->page_size/0x100;i++){
- int tmp;
- /* -------LLI for 256 byte block---------*/
- /* DMACC0SrcAddr = SLC_DMA_DATA*/
- target_write_u32(target,target_mem_base+0+i*32,0x20020038 );
- if(i==0) target_write_u32(target,0x31000100,0x20020038 );
- /* DMACCxDestAddr = SRAM */
- target_write_u32(target,target_mem_base+4+i*32,target_mem_base+DATA_OFFS+i*256 );
- if(i==0) target_write_u32(target,0x31000104,target_mem_base+DATA_OFFS );
- /* DMACCxLLI = next element */
- tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc;
- target_write_u32(target,target_mem_base+8+i*32, tmp );
- if(i==0) target_write_u32(target,0x31000108, tmp );
- /* DMACCxControl = TransferSize =64, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
- Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0,
- Destination increment = 1, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,target_mem_base+12+i*32,0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
- if(i==0) target_write_u32(target,0x3100010c,0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
-
- /* -------LLI for 3 byte ECC---------*/
- /* DMACC0SrcAddr = SLC_ECC*/
- target_write_u32(target,target_mem_base+16+i*32,0x20020034 );
- /* DMACCxDestAddr = SRAM */
- target_write_u32(target,target_mem_base+20+i*32,target_mem_base+ECC_OFFS+i*4 );
- /* DMACCxLLI = next element */
- tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc;
- target_write_u32(target,target_mem_base+24+i*32, tmp );
- /* DMACCxControl = TransferSize =1, Source burst size =4, Destination burst size = 4, Source transfer width = 32 bit,
- Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0,
- Destination increment = 1, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,target_mem_base+28+i*32,0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
-
-
- }
-
- /* -------LLI for spare area---------*/
- /* DMACC0SrcAddr = SLC_DMA_DATA*/
- target_write_u32(target,target_mem_base+0+i*32,0x20020038 );
- /* DMACCxDestAddr = SRAM */
- target_write_u32(target,target_mem_base+4+i*32,target_mem_base+SPARE_OFFS );
- /* DMACCxLLI = next element = NULL */
- target_write_u32(target,target_mem_base+8+i*32, 0 );
- /* DMACCxControl = TransferSize =16 for large page or 4 for small page, Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
- Destination transfer width = 32 bit, Source AHB master select = M0, Destination AHB master select = M0, Source increment = 0,
- Destination increment = 1, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,target_mem_base+12+i*32, (nand->page_size==2048?0x10:0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27| 0<<31);
-
- /* Enable DMA after channel set up !
- LLI only works when DMA is the flow controller!
- */
- /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC), FlowCntrl = 2 (Pher-> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/
- target_write_u32(target,0x31000110, 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18);
-
-
- /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
- target_write_u32(target, 0x20020010, 0x3);
-
- /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
- target_write_u32(target, 0x20020028, 2);
-
- /* SLC_TC */
- target_write_u32(target, 0x20020030, (nand->page_size==2048?0x840:0x210));
-
- if (!lpc3180_tc_ready(nand, 1000))
- {
- LOG_ERROR("timeout while waiting for completion of DMA");
- free(page_buffer);
- free(ecc_hw_buffer);
- free(ecc_flash_buffer);
- target_free_working_area(target,pworking_area);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (data){
- target_read_memory(target, target_mem_base+DATA_OFFS, 4, nand->page_size == 2048?512:128, page_buffer);
- memcpy(data, page_buffer, data_size);
-
- LOG_INFO("Page = 0x%" PRIx32 " was read.",page);
-
- /* check hw generated ECC for each 256 bytes block with the saved ECC in flash spare area*/
- int idx = nand->page_size/0x200 ;
- target_read_memory(target, target_mem_base+SPARE_OFFS, 4, 16, ecc_flash_buffer);
- target_read_memory(target, target_mem_base+ECC_OFFS, 4, 8, ecc_hw_buffer);
- for(i=0;i<idx;i++){
- if( (0x00ffffff&*(uint32_t *)(void *)(ecc_hw_buffer+i*8)) != (0x00ffffff&*(uint32_t *)(void *)(ecc_flash_buffer+8+i*16)) )
- LOG_WARNING("ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32,i*2+1,page);
- if( (0x00ffffff&*(uint32_t *)(void *)(ecc_hw_buffer+4+i*8)) != (0x00ffffff&*(uint32_t *)(void *)(ecc_flash_buffer+12+i*16)) )
- LOG_WARNING("ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32,i*2+2,page);
- }
- }
-
- if (oob)
- memcpy(oob, ecc_flash_buffer, oob_size);
-
- free(page_buffer);
- free(ecc_hw_buffer);
- free(ecc_flash_buffer);
-
- target_free_working_area(target,pworking_area);
-
- }
- else
- return nand_read_page_raw(nand, page, data, data_size, oob, oob_size);
+ free(page_buffer);
+ free(ecc_hw_buffer);
+ free(ecc_flash_buffer);
+
+ target_free_working_area(target, pworking_area);
+
+ } else
+ return nand_read_page_raw(nand, page, data, data_size, oob, oob_size);
}
return ERROR_OK;
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
LOG_DEBUG("lpc3180_controller_ready count start=%d", timeout);
- do
- {
- if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ do {
+ if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
uint8_t status;
/* Read MLC_ISR, wait for controller to become ready */
if (status & 2) {
LOG_DEBUG("lpc3180_controller_ready count=%d",
- timeout);
+ timeout);
return 1;
}
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
uint32_t status;
/* Read SLC_STAT and check READY bit */
if (status & 1) {
LOG_DEBUG("lpc3180_controller_ready count=%d",
- timeout);
+ timeout);
return 1;
}
}
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
LOG_DEBUG("lpc3180_nand_ready count start=%d", timeout);
- do
- {
- if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- {
+ do {
+ if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
uint8_t status = 0x0;
/* Read MLC_ISR, wait for NAND flash device to become ready */
if (status & 1) {
LOG_DEBUG("lpc3180_nand_ready count end=%d",
- timeout);
+ timeout);
return 1;
}
- }
- else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
+ } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
uint32_t status = 0x0;
/* Read SLC_STAT and check READY bit */
if (status & 1) {
LOG_DEBUG("lpc3180_nand_ready count end=%d",
- timeout);
+ timeout);
return 1;
}
}
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
+ if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
- LOG_DEBUG("lpc3180_tc_ready count start=%d",
- timeout);
+ LOG_DEBUG("lpc3180_tc_ready count start=%d",
+ timeout);
- do
- {
- if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
- {
- uint32_t status = 0x0;
+ do {
+ if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
+ uint32_t status = 0x0;
/* Read SLC_INT_STAT and check INT_TC_STAT bit */
target_read_u32(target, 0x2002001c, &status);
- if (status & 2){
- LOG_DEBUG("lpc3180_tc_ready count=%d",
- timeout);
- return 1;
- }
+ if (status & 2) {
+ LOG_DEBUG("lpc3180_tc_ready count=%d",
+ timeout);
+ return 1;
+ }
}
alive_sleep(1);
return 0;
}
-
COMMAND_HANDLER(handle_lpc3180_select_command)
{
struct lpc3180_nand_controller *lpc3180_info = NULL;
- char *selected[] =
- {
+ char *selected[] = {
"no", "mlc", "slc"
};
if ((CMD_ARGC < 1) || (CMD_ARGC > 3))
- {
return ERROR_COMMAND_SYNTAX_ERROR;
- }
unsigned num;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
struct nand_device *nand = get_nand_device_by_num(num);
- if (!nand)
- {
+ if (!nand) {
command_print(CMD_CTX, "nand device '#%s' is out of bounds", CMD_ARGV[0]);
return ERROR_OK;
}
lpc3180_info = nand->controller_priv;
- if (CMD_ARGC >= 2)
- {
+ if (CMD_ARGC >= 2) {
if (strcmp(CMD_ARGV[1], "mlc") == 0)
- {
lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER;
- }
- else if (strcmp(CMD_ARGV[1], "slc") == 0)
- {
+ else if (strcmp(CMD_ARGV[1], "slc") == 0) {
lpc3180_info->selected_controller = LPC3180_SLC_CONTROLLER;
- if (CMD_ARGC == 3 && strcmp(CMD_ARGV[2], "bulk") == 0){
- lpc3180_info->is_bulk = 1;
- }
- else{
- lpc3180_info->is_bulk = 0;
- }
- }
- else
- {
+ if (CMD_ARGC == 3 && strcmp(CMD_ARGV[2], "bulk") == 0)
+ lpc3180_info->is_bulk = 1;
+ else
+ lpc3180_info->is_bulk = 0;
+ } else
return ERROR_COMMAND_SYNTAX_ERROR;
- }
}
- if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- command_print(CMD_CTX, "%s controller selected", selected[lpc3180_info->selected_controller]);
- else{
- command_print(CMD_CTX, lpc3180_info->is_bulk?"%s controller selected bulk mode is available":"%s controller selected bulk mode is not available", selected[lpc3180_info->selected_controller]);
- }
-
+ if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
+ command_print(CMD_CTX, "%s controller selected",
+ selected[lpc3180_info->selected_controller]);
+ else
+ command_print(CMD_CTX,
+ lpc3180_info->is_bulk ? "%s controller selected bulk mode is available" :
+ "%s controller selected bulk mode is not available",
+ selected[lpc3180_info->selected_controller]);
return ERROR_OK;
}
.name = "select",
.handler = handle_lpc3180_select_command,
.mode = COMMAND_EXEC,
- .help = "select MLC or SLC controller (default is MLC), SLC can be set to bulk mode",
+ .help =
+ "select MLC or SLC controller (default is MLC), SLC can be set to bulk mode",
.usage = "bank_id ['mlc'|'slc' ['bulk'] ]",
},
COMMAND_REGISTRATION_DONE
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifndef LPC3180_NAND_CONTROLLER_H
#define LPC3180_NAND_CONTROLLER_H
-enum lpc3180_selected_controller
-{
+enum lpc3180_selected_controller {
LPC3180_NO_CONTROLLER,
LPC3180_MLC_CONTROLLER,
LPC3180_SLC_CONTROLLER,
};
-struct lpc3180_nand_controller
-{
+struct lpc3180_nand_controller {
int osc_freq;
enum lpc3180_selected_controller selected_controller;
int is_bulk;
uint32_t sw_wp_upper_bound;
};
-#endif /*LPC3180_NAND_CONTROLLER_H */
+#endif /*LPC3180_NAND_CONTROLLER_H */
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
static int lpc32xx_controller_ready(struct nand_device *nand, int timeout);
static int lpc32xx_tc_ready(struct nand_device *nand, int timeout);
extern int nand_correct_data(struct nand_device *nand, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc);
+ u_char *read_ecc, u_char *calc_ecc);
/* These are offset with the working area in IRAM when using DMA to
* read/write data to the SLC controller.
*/
NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command)
{
- if (CMD_ARGC < 3) {
+ if (CMD_ARGC < 3)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
uint32_t osc_freq;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
if ((lpc32xx_info->osc_freq < 1000) || (lpc32xx_info->osc_freq > 20000))
LOG_WARNING("LPC32xx oscillator frequency should be between "
- "1000 and 20000 kHz, was %i",
- lpc32xx_info->osc_freq);
+ "1000 and 20000 kHz, was %i",
+ lpc32xx_info->osc_freq);
lpc32xx_info->selected_controller = LPC32xx_NO_CONTROLLER;
lpc32xx_info->sw_write_protection = 0;
if (!lock)
LOG_WARNING("PLL is not locked");
- if (!bypass && direct) /* direct mode */
+ if (!bypass && direct) /* direct mode */
return (m * fclkin) / n;
- if (bypass && !direct) /* bypass mode */
+ if (bypass && !direct) /* bypass mode */
return fclkin / (2 * p);
- if (bypass & direct) /* direct bypass mode */
+ if (bypass & direct) /* direct bypass mode */
return fclkin;
- if (feedback) /* integer mode */
+ if (feedback) /* integer mode */
return m * (fclkin / n);
- else /* non-integer mode */
+ else /* non-integer mode */
return (m / (2 * p)) * (fclkin / n);
}
return ERROR_NAND_OPERATION_FAILED;
}
- if ((pwr_ctrl & (1 << 2)) == 0) { /* DIRECT RUN mode */
+ if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
hclk = sysclk;
- } else {
+ else {
retval = target_read_u32(target, 0x40004058, &hclkpll_ctrl);
if (ERROR_OK != retval) {
LOG_ERROR("could not read HCLKPLL_CTRL");
return ERROR_NAND_OPERATION_FAILED;
}
- if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
+ if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1);
- else /* HCLK uses HCLK_PLL */
+ else /* HCLK uses HCLK_PLL */
hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3));
}
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
+ "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
/* select MLC controller if none is currently selected */
if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
LOG_DEBUG("no LPC32xx NAND flash controller selected, "
- "using default 'slc'");
+ "using default 'slc'");
lpc32xx_info->selected_controller = LPC32xx_SLC_CONTROLLER;
}
/* MLC_TIME_REG */
retval = target_write_u32(target, 0x200b8034,
- (twp & 0xf)
- | ((twh & 0xf) << 4)
- | ((trp & 0xf) << 8)
- | ((treh & 0xf) << 12)
- | ((trhz & 0x7) << 16)
- | ((trbwb & 0x1f) << 19)
- | ((tcea & 0x3) << 24));
+ (twp & 0xf)
+ | ((twh & 0xf) << 4)
+ | ((trp & 0xf) << 8)
+ | ((treh & 0xf) << 12)
+ | ((trhz & 0x7) << 16)
+ | ((trbwb & 0x1f) << 19)
+ | ((tcea & 0x3) << 24));
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_TIME_REG");
return ERROR_NAND_OPERATION_FAILED;
WIDTH = bus_width)
*/
retval = target_write_u32(target, 0x20020014,
- 0x3e | (bus_width == 16) ? 1 : 0);
+ 0x3e | (bus_width == 16) ? 1 : 0);
if (ERROR_OK != retval) {
LOG_ERROR("could not set SLC_CFG");
return ERROR_NAND_OPERATION_FAILED;
/* SLC_TAC: SLC timing arcs register */
retval = target_write_u32(target, 0x2002002c,
- (r_setup & 0xf)
- | ((r_hold & 0xf) << 4)
- | ((r_width & 0xf) << 8)
- | ((r_rdy & 0xf) << 12)
- | ((w_setup & 0xf) << 16)
- | ((w_hold & 0xf) << 20)
- | ((w_width & 0xf) << 24)
- | ((w_rdy & 0xf) << 28));
+ (r_setup & 0xf)
+ | ((r_hold & 0xf) << 4)
+ | ((r_width & 0xf) << 8)
+ | ((r_rdy & 0xf) << 12)
+ | ((w_setup & 0xf) << 16)
+ | ((w_hold & 0xf) << 20)
+ | ((w_width & 0xf) << 24)
+ | ((w_rdy & 0xf) << 28));
if (ERROR_OK != retval) {
LOG_ERROR("could not set SLC_TAC");
return ERROR_NAND_OPERATION_FAILED;
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use "
- "LPC32xx NAND flash controller");
+ "LPC32xx NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
if (!lpc32xx_controller_ready(nand, 100)) {
LOG_ERROR("LPC32xx MLC NAND controller timed out "
- "after reset");
+ "after reset");
return ERROR_NAND_OPERATION_TIMEOUT;
}
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
return ERROR_NAND_OPERATION_FAILED;
}
- if (!lpc32xx_controller_ready(nand, 100))
- {
+ if (!lpc32xx_controller_ready(nand, 100)) {
LOG_ERROR("LPC32xx SLC NAND controller timed out "
- "after reset");
+ "after reset");
return ERROR_NAND_OPERATION_TIMEOUT;
}
}
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use "
- "LPC32xx NAND flash controller");
+ "LPC32xx NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use "
- "LPC32xx NAND flash controller");
+ "LPC32xx NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use "
- "LPC32xx NAND flash controller");
+ "LPC32xx NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
+ "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
}
static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
struct target *target = nand->target;
int retval;
return ERROR_NAND_OPERATION_FAILED;
}
retval = target_write_u32(target, 0x200b8004,
- (page >> 8) & 0xff);
+ (page >> 8) & 0xff);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED;
if (nand->address_cycles == 4) {
retval = target_write_u32(target, 0x200b8004,
- (page >> 16) & 0xff);
+ (page >> 16) & 0xff);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED;
return ERROR_NAND_OPERATION_FAILED;
}
retval = target_write_u32(target, 0x200b8004,
- (page >> 8) & 0xff);
+ (page >> 8) & 0xff);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED;
if (!lpc32xx_controller_ready(nand, 1000)) {
LOG_ERROR("timeout while waiting for "
- "completion of auto encode cycle");
+ "completion of auto encode cycle");
return ERROR_NAND_OPERATION_FAILED;
}
}
return ERROR_NAND_OPERATION_FAILED;
}
- if ((retval = nand_read_status(nand, &status)) != ERROR_OK) {
+ retval = nand_read_status(nand, &status);
+ if (retval != ERROR_OK) {
LOG_ERROR("couldn't read status");
return ERROR_NAND_OPERATION_FAILED;
}
if (status & NAND_STATUS_FAIL) {
LOG_ERROR("write operation didn't pass, status: 0x%2.2x",
- status);
+ status);
return ERROR_NAND_OPERATION_FAILED;
}
* target.
*/
static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
- int do_read)
+ int do_read)
{
uint32_t i, dmasrc, ctrl, ecc_ctrl, oob_ctrl, dmadst;
*/
ctrl = (0x40 | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
- | 0 << 25 | 0 << 26 | 0 << 27 | 0 << 31);
+ | 0 << 25 | 0 << 26 | 0 << 27 | 0 << 31);
/* DMACCxControl =
TransferSize =1,
Terminal count interrupt enable bit = 0
*/
ecc_ctrl = 0x01 | 1 << 12 | 1 << 15 | 2 << 18 | 2 << 21 | 0 << 24
- | 0 << 25 | 0 << 26 | 1 << 27 | 0 << 31;
+ | 0 << 25 | 0 << 26 | 1 << 27 | 0 << 31;
/* DMACCxControl =
TransferSize =16 for lp or 4 for sp,
Terminal count interrupt enable bit = 1 // set on last
*/
oob_ctrl = (page_size == 2048 ? 0x10 : 0x04)
- | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
- | 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31;
+ | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
+ | 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31;
if (do_read) {
- ctrl |= 1 << 27; /* Destination increment = 1 */
- oob_ctrl |= 1 << 27; /* Destination increment = 1 */
- dmasrc = 0x20020038; /* SLC_DMA_DATA */
+ ctrl |= 1 << 27;/* Destination increment = 1 */
+ oob_ctrl |= 1 << 27; /* Destination increment = 1 */
+ dmasrc = 0x20020038; /* SLC_DMA_DATA */
dmadst = target_mem_base + DATA_OFFS;
} else {
- ctrl |= 1 << 26; /* Source increment = 1 */
- oob_ctrl |= 1 << 26; /* Source increment = 1 */
+ ctrl |= 1 << 26;/* Source increment = 1 */
+ oob_ctrl |= 1 << 26; /* Source increment = 1 */
dmasrc = target_mem_base + DATA_OFFS;
- dmadst = 0x20020038; /* SLC_DMA_DATA */
+ dmadst = 0x20020038; /* SLC_DMA_DATA */
}
/*
* Write Operation Sequence for Small Block NAND
* data & 32 bytes of ECC data.
* 2. X'fer 64 bytes of Spare area from Flash to Memory.
*/
- for (i = 0; i < page_size/0x100; i++)
- {
+ for (i = 0; i < page_size/0x100; i++) {
dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256));
dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst);
dmalist[i*2].next_lli =
target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t);
dmalist[i*2].next_ctrl = ctrl;
- dmalist[(i*2) + 1].dma_src = 0x20020034; /* SLC_ECC */
+ dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */
dmalist[(i*2) + 1].dma_dest =
target_mem_base + ECC_OFFS + i * 4;
dmalist[(i*2) + 1].next_lli =
- target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t);
+ target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t);
dmalist[(i*2) + 1].next_ctrl = ecc_ctrl;
}
if (do_read)
- {
dmadst = target_mem_base + SPARE_OFFS;
- } else {
+ else {
dmasrc = target_mem_base + SPARE_OFFS;
- dmalist[(i*2) - 1].next_lli = 0; /* last link = null on write */
- dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */
+ dmalist[(i*2) - 1].next_lli = 0;/* last link = null on write */
+ dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */
}
dmalist[i*2].dma_src = dmasrc;
dmalist[i*2].dma_dest = dmadst;
dmalist[i*2].next_lli = 0;
dmalist[i*2].next_ctrl = oob_ctrl;
- return (i*2 + 1); /* Number of descriptors */
+ return i * 2 + 1; /* Number of descriptors */
}
static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count,
- int do_wait)
+ int do_wait)
{
struct target *target = nand->target;
int retval;
LOG_ERROR("Could not set DMACIntTCClear");
return retval;
}
-
+
/* DMACIntErrClear = ch0 */
retval = target_write_u32(target, 0x31000010, 1);
if (ERROR_OK != retval) {
LOG_ERROR("Could not set DMACIntErrClear");
return retval;
}
-
+
/* DMACCxConfig=
E=1,
SrcPeripheral = 1 (SLC),
H=0
*/
retval = target_write_u32(target, 0x31000110,
- 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
- | 0<<15 | 0<<16 | 0<<18);
+ 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
+ | 0<<15 | 0<<16 | 0<<18);
if (ERROR_OK != retval) {
LOG_ERROR("Could not set DMACC0Config");
return retval;
}
if ((tc_stat | err_stat) & 1) {
LOG_DEBUG("lpc32xx_dma_ready count=%d",
- timeout);
+ timeout);
if (err_stat & 1) {
LOG_ERROR("lpc32xx_dma_ready "
- "DMA error, aborted");
+ "DMA error, aborted");
return 0;
- } else {
+ } else
return 1;
- }
}
alive_sleep(1);
return 0;
}
-static uint32_t slc_ecc_copy_to_buffer(uint8_t * spare,
- const uint32_t * ecc, int count)
+static uint32_t slc_ecc_copy_to_buffer(uint8_t *spare,
+ const uint32_t *ecc, int count)
{
int i;
for (i = 0; i < (count * 3); i += 3) {
int addr = 0;
while (oob_size > 0) {
LOG_DEBUG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", addr,
- oob[0], oob[1], oob[2], oob[3],
- oob[4], oob[5], oob[6], oob[7]);
+ oob[0], oob[1], oob[2], oob[3],
+ oob[4], oob[5], oob[6], oob[7]);
oob += 8;
addr += 8;
oob_size -= 8;
- }
+ }
}
static int lpc32xx_write_page_slc(struct nand_device *nand,
- struct working_area *pworking_area,
- uint32_t page, uint8_t *data,
- uint32_t data_size, uint8_t *oob,
- uint32_t oob_size)
+ struct working_area *pworking_area,
+ uint32_t page, uint8_t *data,
+ uint32_t data_size, uint8_t *oob,
+ uint32_t oob_size)
{
struct target *target = nand->target;
int retval;
uint32_t target_mem_base;
LOG_DEBUG("SLC write page %x data=%d, oob=%d, "
- "data_size=%d, oob_size=%d",
- page, data != 0, oob != 0, data_size, oob_size);
+ "data_size=%d, oob_size=%d",
+ page, data != 0, oob != 0, data_size, oob_size);
target_mem_base = pworking_area->address;
- /*
+ /*
* Skip writting page which has all 0xFF data as this will
* generate 0x0 value.
*/
break;
}
if (all_ff)
- return ERROR_OK;
+ return ERROR_OK;
}
/* Make the dma descriptors in local memory */
int nll = lpc32xx_make_dma_list(target_mem_base, nand->page_size, 0);
XXX: Assumes host and target have same byte sex.
*/
retval = target_write_memory(target, target_mem_base, 4,
- nll * sizeof(dmac_ll_t) / 4,
- (uint8_t *)dmalist);
+ nll * sizeof(dmac_ll_t) / 4,
+ (uint8_t *)dmalist);
if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptors to IRAM");
return retval;
return retval;
}
- /* SLC_CFG =
- Force nCE assert,
- DMA ECC enabled,
- ECC enabled,
- DMA burst enabled,
- DMA write to SLC,
- WIDTH = bus_width
+ /* SLC_CFG =
+ Force nCE assert,
+ DMA ECC enabled,
+ ECC enabled,
+ DMA burst enabled,
+ DMA write to SLC,
+ WIDTH = bus_width
*/
retval = target_write_u32(target, 0x20020014, 0x3c);
if (ERROR_OK != retval) {
memset(fdata, 0xFF, nand->page_size);
memcpy(fdata, data, data_size);
retval = target_write_memory(target,
- target_mem_base + DATA_OFFS,
- 4, nand->page_size/4, fdata);
+ target_mem_base + DATA_OFFS,
+ 4, nand->page_size/4, fdata);
if (ERROR_OK != retval) {
LOG_ERROR("Could not write data to IRAM");
return retval;
/* Write first decriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4,
- sizeof(dmac_ll_t) / 4,
- (uint8_t *)dmalist);
+ sizeof(dmac_ll_t) / 4,
+ (uint8_t *)dmalist);
if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptor to DMAC");
return retval;
LOG_ERROR("DMA failed");
return retval;
}
-
+
/* Wait for DMA to finish. SLC is not finished at this stage */
if (!lpc32xx_dma_ready(nand, 100)) {
LOG_ERROR("Data DMA failed during write");
return ERROR_FLASH_OPERATION_FAILED;
}
- } /* data xfer */
+ } /* data xfer */
/* Copy OOB to iram */
static uint8_t foob[64];
int foob_size = nand->page_size == 2048 ? 64 : 16;
memset(foob, 0xFF, foob_size);
- if (oob) { /* Raw mode */
+ if (oob) /* Raw mode */
memcpy(foob, oob, oob_size);
- } else {
+ else {
/* Get HW generated ECC, made while writing data */
int ecc_count = nand->page_size == 2048 ? 8 : 2;
static uint32_t hw_ecc[8];
retval = target_read_memory(target, target_mem_base + ECC_OFFS,
- 4, ecc_count, (uint8_t *)hw_ecc);
+ 4, ecc_count, (uint8_t *)hw_ecc);
if (ERROR_OK != retval) {
LOG_ERROR("Reading hw generated ECC from IRAM failed");
return retval;
lpc32xx_dump_oob(foob, foob_size);
}
retval = target_write_memory(target, target_mem_base + SPARE_OFFS, 4,
- foob_size / 4, foob);
+ foob_size / 4, foob);
if (ERROR_OK != retval) {
LOG_ERROR("Writing OOB to IRAM failed");
return retval;
/* Write OOB decriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4,
- sizeof(dmac_ll_t) / 4,
- (uint8_t *)(&dmalist[nll-1]));
+ sizeof(dmac_ll_t) / 4,
+ (uint8_t *)(&dmalist[nll-1]));
if (ERROR_OK != retval) {
LOG_ERROR("Could not write OOB DMA descriptor to DMAC");
return retval;
return retval;
}
/* DMACCxConfig=
- E=1,
- SrcPeripheral = 1 (SLC),
- DestPeripheral = 1 (SLC),
- FlowCntrl = 2 (Pher -> Mem, DMA),
- IE = 0,
- ITC = 0,
- L= 0,
- H=0
+ * E=1,
+ * SrcPeripheral = 1 (SLC),
+ * DestPeripheral = 1 (SLC),
+ * FlowCntrl = 2 (Pher -> Mem, DMA),
+ * IE = 0,
+ * ITC = 0,
+ * L= 0,
+ * H=0
*/
retval = target_write_u32(target, 0x31000110,
- 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
- | 0<<15 | 0<<16 | 0<<18);
+ 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
+ | 0<<15 | 0<<16 | 0<<18);
if (ERROR_OK != retval) {
LOG_ERROR("Could not set DMACC0Config");
return retval;
/* Wait finish */
if (!lpc32xx_tc_ready(nand, 100)) {
LOG_ERROR("timeout while waiting for "
- "completion of DMA");
+ "completion of DMA");
return ERROR_NAND_OPERATION_FAILED;
}
} else {
}
static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
struct target *target = nand->target;
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
+ "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
} else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
if (!data && oob) {
LOG_ERROR("LPC32xx MLC controller can't write "
- "OOB data only");
+ "OOB data only");
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
if (oob && (oob_size > 24)) {
LOG_ERROR("LPC32xx MLC controller can't write more "
- "than 6 bytes for each quarter's OOB data");
+ "than 6 bytes for each quarter's OOB data");
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
}
retval = lpc32xx_write_page_mlc(nand, page, data, data_size,
- oob, oob_size);
+ oob, oob_size);
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
struct working_area *pworking_area;
if (!data && oob) {
* Anyway the code supports the oob only mode below.
*/
return nand_write_page_raw(nand, page, data,
- data_size, oob, oob_size);
+ data_size, oob, oob_size);
}
retval = target_alloc_working_area(target,
- nand->page_size + DATA_OFFS,
- &pworking_area);
+ nand->page_size + DATA_OFFS,
+ &pworking_area);
if (retval != ERROR_OK) {
LOG_ERROR("Can't allocate working area in "
- "LPC internal RAM");
+ "LPC internal RAM");
return ERROR_FLASH_OPERATION_FAILED;
}
retval = lpc32xx_write_page_slc(nand, pworking_area, page,
- data, data_size, oob, oob_size);
+ data, data_size, oob, oob_size);
target_free_working_area(target, pworking_area);
}
}
static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
struct target *target = nand->target;
static uint8_t page_buffer[2048];
return ERROR_NAND_OPERATION_FAILED;
}
if (nand->page_size == 512) {
- /* small page device */
- /* MLC_ADDR = 0x0 (one column cycle) */
+ /* small page device
+ * MLC_ADDR = 0x0 (one column cycle) */
retval = target_write_u32(target, 0x200b8004, 0x0);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED;
}
retval = target_write_u32(target, 0x200b8004,
- (page >> 8) & 0xff);
+ (page >> 8) & 0xff);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED;
if (nand->address_cycles == 4) {
retval = target_write_u32(target, 0x200b8004,
- (page >> 16) & 0xff);
+ (page >> 16) & 0xff);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED;
}
}
} else {
- /* large page device */
- /* MLC_ADDR = 0x0 (two column cycles) */
+ /* large page device
+ * MLC_ADDR = 0x0 (two column cycles) */
retval = target_write_u32(target, 0x200b8004, 0x0);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED;
}
retval = target_write_u32(target, 0x200b8004,
- (page >> 8) & 0xff);
+ (page >> 8) & 0xff);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_ADDR");
return ERROR_NAND_OPERATION_FAILED;
/* MLC_CMD = Read Start */
retval = target_write_u32(target, 0x200b8000,
- NAND_CMD_READSTART);
+ NAND_CMD_READSTART);
if (ERROR_OK != retval) {
LOG_ERROR("could not set MLC_CMD");
return ERROR_NAND_OPERATION_FAILED;
if (!lpc32xx_controller_ready(nand, 1000)) {
LOG_ERROR("timeout while waiting for "
- "completion of auto decode cycle");
+ "completion of auto decode cycle");
return ERROR_NAND_OPERATION_FAILED;
}
if (mlc_isr & 0x8) {
if (mlc_isr & 0x40) {
LOG_ERROR("uncorrectable error detected: "
- "0x%2.2x", (unsigned)mlc_isr);
+ "0x%2.2x", (unsigned)mlc_isr);
return ERROR_NAND_OPERATION_FAILED;
}
LOG_WARNING("%i symbol error detected and corrected",
- ((int)(((mlc_isr & 0x30) >> 4) + 1)));
+ ((int)(((mlc_isr & 0x30) >> 4) + 1)));
}
if (data) {
retval = target_read_memory(target, 0x200a8000, 4, 128,
- page_buffer + page_bytes_done);
+ page_buffer + page_bytes_done);
if (ERROR_OK != retval) {
LOG_ERROR("could not read MLC_BUF (data)");
return ERROR_NAND_OPERATION_FAILED;
if (oob) {
retval = target_read_memory(target, 0x200a8000, 4, 4,
- oob_buffer + oob_bytes_done);
+ oob_buffer + oob_bytes_done);
if (ERROR_OK != retval) {
LOG_ERROR("could not read MLC_BUF (oob)");
return ERROR_NAND_OPERATION_FAILED;
}
static int lpc32xx_read_page_slc(struct nand_device *nand,
- struct working_area *pworking_area,
- uint32_t page, uint8_t *data,
- uint32_t data_size, uint8_t *oob,
- uint32_t oob_size)
+ struct working_area *pworking_area,
+ uint32_t page, uint8_t *data,
+ uint32_t data_size, uint8_t *oob,
+ uint32_t oob_size)
{
struct target *target = nand->target;
int retval;
uint32_t target_mem_base;
LOG_DEBUG("SLC read page %x data=%d, oob=%d",
- page, data_size, oob_size);
+ page, data_size, oob_size);
target_mem_base = pworking_area->address;
XXX: Assumes host and target have same byte sex.
*/
retval = target_write_memory(target, target_mem_base, 4,
- nll * sizeof(dmac_ll_t) / 4,
- (uint8_t *)dmalist);
+ nll * sizeof(dmac_ll_t) / 4,
+ (uint8_t *)dmalist);
if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptors to IRAM");
return retval;
return retval;
}
- /* SLC_CFG =
- Force nCE assert,
- DMA ECC enabled,
- ECC enabled,
- DMA burst enabled,
- DMA read from SLC,
- WIDTH = bus_width
+ /* SLC_CFG =
+ Force nCE assert,
+ DMA ECC enabled,
+ ECC enabled,
+ DMA burst enabled,
+ DMA read from SLC,
+ WIDTH = bus_width
*/
retval = target_write_u32(target, 0x20020014, 0x3e);
if (ERROR_OK != retval) {
/* Write first decriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4,
- sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist);
+ sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist);
if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptor to DMAC");
return retval;
/* Copy data from iram */
if (data) {
retval = target_read_memory(target, target_mem_base + DATA_OFFS,
- 4, data_size/4, data);
+ 4, data_size/4, data);
if (ERROR_OK != retval) {
LOG_ERROR("Could not read data from IRAM");
return retval;
if (oob) {
/* No error correction, just return data as read from flash */
retval = target_read_memory(target,
- target_mem_base + SPARE_OFFS, 4,
- oob_size/4, oob);
+ target_mem_base + SPARE_OFFS, 4,
+ oob_size/4, oob);
if (ERROR_OK != retval) {
LOG_ERROR("Could not read OOB from IRAM");
return retval;
/* Copy OOB from flash, stored in IRAM */
static uint8_t foob[64];
retval = target_read_memory(target, target_mem_base + SPARE_OFFS,
- 4, nand->page_size == 2048 ? 16 : 4, foob);
+ 4, nand->page_size == 2048 ? 16 : 4, foob);
lpc32xx_dump_oob(foob, nand->page_size == 2048 ? 64 : 16);
if (ERROR_OK != retval) {
LOG_ERROR("Could not read OOB from IRAM");
}
/* Copy ECC from HW, generated while reading */
int ecc_count = nand->page_size == 2048 ? 8 : 2;
- static uint32_t hw_ecc[8]; /* max size */
+ static uint32_t hw_ecc[8]; /* max size */
retval = target_read_memory(target, target_mem_base + ECC_OFFS, 4,
- ecc_count, (uint8_t *)hw_ecc);
+ ecc_count, (uint8_t *)hw_ecc);
if (ERROR_OK != retval) {
LOG_ERROR("Could not read hw generated ECC from IRAM");
return retval;
static uint8_t ecc[24];
slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count);
/* Copy ECC from flash using correct layout */
- static uint8_t fecc[24]; /* max size */
+ static uint8_t fecc[24];/* max size */
int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout;
int i;
for (i = 0; i < ecc_count * 3; i++)
/* Compare ECC and possibly correct data */
for (i = 0; i < ecc_count; i++) {
retval = nand_correct_data(nand, data + 256*i, &fecc[i * 3],
- &ecc[i * 3]);
+ &ecc[i * 3]);
if (retval > 0)
LOG_WARNING("error detected and corrected: %d/%d",
- page, i);
+ page, i);
if (retval < 0)
break;
}
}
static int lpc32xx_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
struct target *target = nand->target;
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
+ "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
retval = lpc32xx_read_page_mlc(nand, page, data, data_size,
- oob, oob_size);
+ oob, oob_size);
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
struct working_area *pworking_area;
- retval = target_alloc_working_area(target,
- nand->page_size + 0x200,
- &pworking_area);
+ retval = target_alloc_working_area(target,
+ nand->page_size + 0x200,
+ &pworking_area);
if (retval != ERROR_OK) {
LOG_ERROR("Can't allocate working area in "
- "LPC internal RAM");
+ "LPC internal RAM");
return ERROR_FLASH_OPERATION_FAILED;
}
retval = lpc32xx_read_page_slc(nand, pworking_area, page,
- data, data_size, oob, oob_size);
- target_free_working_area(target, pworking_area);
+ data, data_size, oob, oob_size);
+ target_free_working_area(target, pworking_area);
}
return retval;
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
+ "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
if (status & 2) {
LOG_DEBUG("lpc32xx_controller_ready count=%d",
- timeout);
+ timeout);
return 1;
}
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
if (status & 1) {
LOG_DEBUG("lpc32xx_controller_ready count=%d",
- timeout);
+ timeout);
return 1;
}
}
if (target->state != TARGET_HALTED) {
LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
+ "NAND flash controller");
return ERROR_NAND_OPERATION_FAILED;
}
if (status & 1) {
LOG_DEBUG("lpc32xx_nand_ready count end=%d",
- timeout);
+ timeout);
return 1;
}
} else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
if (status & 1) {
LOG_DEBUG("lpc32xx_nand_ready count end=%d",
- timeout);
+ timeout);
return 1;
}
}
LOG_ERROR("Could not read SLC_INT_STAT");
return 0;
}
- if (status & 2){
+ if (status & 2) {
LOG_DEBUG("lpc32xx_tc_ready count=%d", timeout);
return 1;
}
"no", "mlc", "slc"
};
- if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) {
+ if ((CMD_ARGC < 1) || (CMD_ARGC > 3))
return ERROR_COMMAND_SYNTAX_ERROR;
- }
unsigned num;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
struct nand_device *nand = get_nand_device_by_num(num);
if (!nand) {
command_print(CMD_CTX, "nand device '#%s' is out of bounds",
- CMD_ARGV[0]);
+ CMD_ARGV[0]);
return ERROR_OK;
}
} else if (strcmp(CMD_ARGV[1], "slc") == 0) {
lpc32xx_info->selected_controller =
LPC32xx_SLC_CONTROLLER;
- } else {
+ } else
return ERROR_COMMAND_SYNTAX_ERROR;
- }
}
command_print(CMD_CTX, "%s controller selected",
- selected[lpc32xx_info->selected_controller]);
+ selected[lpc32xx_info->selected_controller]);
return ERROR_OK;
}
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifndef LPC32xx_NAND_CONTROLLER_H
#define LPC32xx_NAND_CONTROLLER_H
-enum lpc32xx_selected_controller
-{
+enum lpc32xx_selected_controller {
LPC32xx_NO_CONTROLLER,
LPC32xx_MLC_CONTROLLER,
LPC32xx_SLC_CONTROLLER,
};
-struct lpc32xx_nand_controller
-{
+struct lpc32xx_nand_controller {
int osc_freq;
enum lpc32xx_selected_controller selected_controller;
int sw_write_protection;
uint32_t sw_wp_upper_bound;
};
-#endif /*LPC32xx_NAND_CONTROLLER_H */
+#endif /*LPC32xx_NAND_CONTROLLER_H */
#include <target/target.h>
static const char target_not_halted_err_msg[] =
- "target must be halted to use mx3 NAND flash controller";
+ "target must be halted to use mx3 NAND flash controller";
static const char data_block_size_err_msg[] =
- "minimal granularity is one half-word, %" PRId32 " is incorrect";
+ "minimal granularity is one half-word, %" PRId32 " is incorrect";
static const char sram_buffer_bounds_err_msg[] =
- "trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
+ "trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
static const char get_status_register_err_msg[] = "can't get NAND status";
static uint32_t in_sram_address;
static unsigned char sign_of_sequental_byte_read;
-static int test_iomux_settings (struct target * target, uint32_t value,
- uint32_t mask, const char *text);
-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_halfword_from_sram_buffer (struct target * target,
- uint16_t * value);
-static int poll_for_complete_op (struct target * target, const char *text);
-static int validate_target_state (struct nand_device *nand);
-static int do_data_output (struct nand_device *nand);
+static int test_iomux_settings(struct target *target, uint32_t value,
+ uint32_t mask, const char *text);
+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_halfword_from_sram_buffer(struct target *target,
+ uint16_t *value);
+static int poll_for_complete_op(struct target *target, const char *text);
+static int validate_target_state(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_address (struct nand_device *nand, uint8_t address);
+static int imx31_command(struct nand_device *nand, uint8_t command);
+static int imx31_address(struct nand_device *nand, uint8_t address);
NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
{
struct mx3_nf_controller *mx3_nf_info;
- mx3_nf_info = malloc (sizeof (struct mx3_nf_controller));
- if (mx3_nf_info == NULL)
- {
- LOG_ERROR ("no memory for nand controller");
- return ERROR_FAIL;
+ mx3_nf_info = malloc(sizeof(struct mx3_nf_controller));
+ if (mx3_nf_info == NULL) {
+ LOG_ERROR("no memory for nand controller");
+ return ERROR_FAIL;
}
nand->controller_priv = mx3_nf_info;
if (CMD_ARGC < 3)
- {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
+ return ERROR_COMMAND_SYNTAX_ERROR;
/*
* check hwecc requirements
*/
{
- int hwecc_needed;
- hwecc_needed = strcmp (CMD_ARGV[2], "hwecc");
- if (hwecc_needed == 0)
- {
- mx3_nf_info->flags.hw_ecc_enabled = 1;
- }
- else
- {
- mx3_nf_info->flags.hw_ecc_enabled = 0;
- }
+ int hwecc_needed;
+ hwecc_needed = strcmp(CMD_ARGV[2], "hwecc");
+ if (hwecc_needed == 0)
+ mx3_nf_info->flags.hw_ecc_enabled = 1;
+ else
+ mx3_nf_info->flags.hw_ecc_enabled = 0;
}
mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
mx3_nf_info->fin = MX3_NF_FIN_NONE;
mx3_nf_info->flags.target_little_endian =
- (nand->target->endianness == TARGET_LITTLE_ENDIAN);
+ (nand->target->endianness == TARGET_LITTLE_ENDIAN);
/*
* testing host endianness
*/
{
- int x = 1;
- if (*(char *) &x == 1)
- {
- mx3_nf_info->flags.host_little_endian = 1;
- }
- else
- {
- mx3_nf_info->flags.host_little_endian = 0;
- }
+ int x = 1;
+ if (*(char *) &x == 1)
+ mx3_nf_info->flags.host_little_endian = 1;
+ else
+ mx3_nf_info->flags.host_little_endian = 0;
}
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 target *target = nand->target;
{
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- {
- return validate_target_result;
- }
+ /*
+ * validate target state
+ */
+ int validate_target_result;
+ validate_target_result = validate_target_state(nand);
+ if (validate_target_result != ERROR_OK)
+ return validate_target_result;
}
{
- uint16_t buffsize_register_content;
- target_read_u16 (target, MX3_NF_BUFSIZ, &buffsize_register_content);
- mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
+ uint16_t buffsize_register_content;
+ target_read_u16(target, MX3_NF_BUFSIZ, &buffsize_register_content);
+ mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
}
{
- uint32_t pcsr_register_content;
- target_read_u32 (target, MX3_PCSR, &pcsr_register_content);
- if (!nand->bus_width)
- {
- nand->bus_width =
- (pcsr_register_content & 0x80000000) ? 16 : 8;
- }
- else
- {
- pcsr_register_content |=
- ((nand->bus_width == 16) ? 0x80000000 : 0x00000000);
- target_write_u32 (target, MX3_PCSR, pcsr_register_content);
- }
-
- if (!nand->page_size)
- {
- nand->page_size =
- (pcsr_register_content & 0x40000000) ? 2048 : 512;
- }
- else
- {
- pcsr_register_content |=
- ((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 pcsr_register_content;
+ target_read_u32(target, MX3_PCSR, &pcsr_register_content);
+ if (!nand->bus_width) {
+ nand->bus_width = (pcsr_register_content & 0x80000000) ? 16 : 8;
+ } else {
+ pcsr_register_content |= ((nand->bus_width == 16) ? 0x80000000 : 0x00000000);
+ target_write_u32(target, MX3_PCSR, pcsr_register_content);
+ }
+
+ if (!nand->page_size) {
+ nand->page_size = (pcsr_register_content & 0x40000000) ? 2048 : 512;
+ } else {
+ pcsr_register_content |= ((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;
- target_read_u32 (target, MX3_CCM_CGR2, &cgr_register_content);
- if (!(cgr_register_content & 0x00000300))
- {
- LOG_ERROR ("clock gating to EMI disabled");
- return ERROR_FAIL;
- }
+ uint32_t cgr_register_content;
+ target_read_u32(target, MX3_CCM_CGR2, &cgr_register_content);
+ if (!(cgr_register_content & 0x00000300)) {
+ LOG_ERROR("clock gating to EMI disabled");
+ return ERROR_FAIL;
+ }
}
{
- uint32_t gpr_register_content;
- target_read_u32 (target, MX3_GPR, &gpr_register_content);
- if (gpr_register_content & 0x00000060)
- {
- LOG_ERROR ("pins mode overrided by GPR");
- return ERROR_FAIL;
- }
+ uint32_t gpr_register_content;
+ target_read_u32(target, MX3_GPR, &gpr_register_content);
+ if (gpr_register_content & 0x00000060) {
+ LOG_ERROR("pins mode overrided by GPR");
+ return ERROR_FAIL;
+ }
}
{
- /*
- * testing IOMUX settings; must be in "functional-mode output and
- * functional-mode input" mode
- */
- int test_iomux;
- test_iomux = ERROR_OK;
- test_iomux |=
- 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_settings (target, 0x43fac0c8, 0x0000007f, "d7");
- if (nand->bus_width == 16)
- {
- 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_settings (target, 0x43fac0d0, 0x7f7f7f00,
- "nfwp,nfce,nfrb");
- test_iomux |=
- test_iomux_settings (target, 0x43fac0d4, 0x7f7f7f7f,
- "nfwe,nfre,nfale,nfcle");
- if (test_iomux != ERROR_OK)
- {
- return ERROR_FAIL;
- }
+ /*
+ * testing IOMUX settings; must be in "functional-mode output and
+ * functional-mode input" mode
+ */
+ int test_iomux;
+ test_iomux = ERROR_OK;
+ test_iomux |= 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_settings(target, 0x43fac0c8, 0x0000007f, "d7");
+ if (nand->bus_width == 16) {
+ 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_settings(target, 0x43fac0d0, 0x7f7f7f00, "nfwp,nfce,nfrb");
+ test_iomux |= test_iomux_settings(target, 0x43fac0d4, 0x7f7f7f7f,
+ "nfwe,nfre,nfale,nfcle");
+ if (test_iomux != ERROR_OK)
+ return ERROR_FAIL;
}
- initialize_nf_controller (nand);
+ initialize_nf_controller(nand);
{
- int retval;
- uint16_t nand_status_content;
- retval = ERROR_OK;
- retval |= imx31_command (nand, NAND_CMD_STATUS);
- retval |= imx31_address (nand, 0x00);
- retval |= do_data_output (nand);
- if (retval != ERROR_OK)
- {
- LOG_ERROR (get_status_register_err_msg);
- return ERROR_FAIL;
- }
- target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
- if (!(nand_status_content & 0x0080))
- {
- /*
- * is host-big-endian correctly ??
- */
- LOG_INFO ("NAND read-only");
- mx3_nf_info->flags.nand_readonly = 1;
- }
- else
- {
- mx3_nf_info->flags.nand_readonly = 0;
- }
+ int retval;
+ uint16_t nand_status_content;
+ retval = ERROR_OK;
+ retval |= imx31_command(nand, NAND_CMD_STATUS);
+ retval |= imx31_address(nand, 0x00);
+ retval |= do_data_output(nand);
+ if (retval != ERROR_OK) {
+ LOG_ERROR(get_status_register_err_msg);
+ return ERROR_FAIL;
+ }
+ target_read_u16(target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
+ if (!(nand_status_content & 0x0080)) {
+ /*
+ * is host-big-endian correctly ??
+ */
+ LOG_INFO("NAND read-only");
+ mx3_nf_info->flags.nand_readonly = 1;
+ } else
+ mx3_nf_info->flags.nand_readonly = 0;
}
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;
{
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state (nand);
- if (validate_target_result != ERROR_OK)
- {
- return validate_target_result;
- }
+ /*
+ * validate target state
+ */
+ int validate_target_result;
+ validate_target_result = validate_target_state(nand);
+ if (validate_target_result != ERROR_OK)
+ return validate_target_result;
}
{
- /*
- * get data from nand chip
- */
- int try_data_output_from_nand_chip;
- try_data_output_from_nand_chip = do_data_output (nand);
- if (try_data_output_from_nand_chip != ERROR_OK)
- {
- return try_data_output_from_nand_chip;
- }
+ /*
+ * get data from nand chip
+ */
+ int try_data_output_from_nand_chip;
+ try_data_output_from_nand_chip = do_data_output(nand);
+ if (try_data_output_from_nand_chip != ERROR_OK)
+ return try_data_output_from_nand_chip;
}
if (nand->bus_width == 16)
- {
- get_next_halfword_from_sram_buffer (target, data);
- }
+ get_next_halfword_from_sram_buffer(target, data);
else
- {
- get_next_byte_from_sram_buffer (target, data);
- }
+ get_next_byte_from_sram_buffer(target, data);
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;
}
-static int imx31_reset (struct nand_device *nand)
+static int imx31_reset(struct nand_device *nand)
{
/*
* validate target state
*/
int validate_target_result;
- validate_target_result = validate_target_state (nand);
+ validate_target_result = validate_target_state(nand);
if (validate_target_result != ERROR_OK)
- {
- return validate_target_result;
- }
- initialize_nf_controller (nand);
+ return validate_target_result;
+ initialize_nf_controller(nand);
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 target *target = nand->target;
{
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state (nand);
- if (validate_target_result != ERROR_OK)
- {
- return validate_target_result;
- }
- }
-
- switch (command)
- {
- case NAND_CMD_READOOB:
- command = NAND_CMD_READ0;
- in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
- * data_read() and
- * read_block_data() to
- * spare area in SRAM
- * buffer */
- break;
- case NAND_CMD_READ1:
- command = NAND_CMD_READ0;
/*
- * offset == one half of page size
+ * validate target state
*/
- in_sram_address =
- MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
- default:
- in_sram_address = MX3_NF_MAIN_BUFFER0;
+ int validate_target_result;
+ validate_target_result = validate_target_state(nand);
+ if (validate_target_result != ERROR_OK)
+ return validate_target_result;
+ }
+
+ switch (command) {
+ case NAND_CMD_READOOB:
+ command = NAND_CMD_READ0;
+ in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
+ * data_read() and
+ * read_block_data() to
+ * spare area in SRAM
+ * buffer */
+ break;
+ case NAND_CMD_READ1:
+ command = NAND_CMD_READ0;
+ /*
+ * offset == one half of page size
+ */
+ in_sram_address = MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
+ default:
+ 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)
*/
- 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;
- poll_result = poll_for_complete_op (target, "command");
- if (poll_result != ERROR_OK)
- {
- return poll_result;
- }
+ int poll_result;
+ poll_result = poll_for_complete_op(target, "command");
+ if (poll_result != ERROR_OK)
+ return poll_result;
}
/*
* reset cursor to begin of the buffer
*/
sign_of_sequental_byte_read = 0;
- switch (command)
- {
- case NAND_CMD_READID:
- mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_STATUS:
- mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS;
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_READ0:
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
- break;
- default:
- mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
+ switch (command) {
+ case NAND_CMD_READID:
+ mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
+ mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+ break;
+ case NAND_CMD_STATUS:
+ mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS;
+ mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+ break;
+ case NAND_CMD_READ0:
+ mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+ mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
+ break;
+ default:
+ mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
}
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;
{
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state (nand);
- if (validate_target_result != ERROR_OK)
- {
- return validate_target_result;
- }
+ /*
+ * validate target state
+ */
+ int validate_target_result;
+ validate_target_result = validate_target_state(nand);
+ if (validate_target_result != ERROR_OK)
+ 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)
*/
- 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;
- poll_result = poll_for_complete_op (target, "address");
- if (poll_result != ERROR_OK)
- {
- return poll_result;
- }
+ int poll_result;
+ poll_result = poll_for_complete_op(target, "address");
+ if (poll_result != ERROR_OK)
+ return poll_result;
}
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;
struct target *target = nand->target;
{
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state (nand);
- if (validate_target_result != ERROR_OK)
- {
- return validate_target_result;
- }
- }
-
- do
- {
- target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
- if (poll_complete_status & MX3_NF_BIT_OP_DONE)
- {
- return tout;
- }
- alive_sleep (1);
- }
- while (tout-- > 0);
+ /*
+ * validate target state
+ */
+ int validate_target_result;
+ validate_target_result = validate_target_state(nand);
+ if (validate_target_result != ERROR_OK)
+ return validate_target_result;
+ }
+
+ do {
+ target_read_u16(target, MX3_NF_CFG2, &poll_complete_status);
+ if (poll_complete_status & MX3_NF_BIT_OP_DONE)
+ return tout;
+ alive_sleep(1);
+ } while (tout-- > 0);
return tout;
}
-static int imx31_write_page (struct nand_device *nand, uint32_t page,
- uint8_t * data, uint32_t data_size, uint8_t * oob,
- uint32_t oob_size)
+static int imx31_write_page(struct nand_device *nand, uint32_t page,
+ uint8_t *data, uint32_t data_size, uint8_t *oob,
+ uint32_t oob_size)
{
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
struct target *target = nand->target;
- if (data_size % 2)
- {
- LOG_ERROR (data_block_size_err_msg, data_size);
- return ERROR_NAND_OPERATION_FAILED;
+ if (data_size % 2) {
+ LOG_ERROR(data_block_size_err_msg, data_size);
+ return ERROR_NAND_OPERATION_FAILED;
}
- if (oob_size % 2)
- {
- LOG_ERROR (data_block_size_err_msg, oob_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (!data)
- {
- LOG_ERROR ("nothing to program");
- return ERROR_NAND_OPERATION_FAILED;
+ if (oob_size % 2) {
+ LOG_ERROR(data_block_size_err_msg, oob_size);
+ return ERROR_NAND_OPERATION_FAILED;
}
- {
- /*
- * validate target state
- */
- int retval;
- retval = validate_target_state (nand);
- if (retval != ERROR_OK)
- {
- return retval;
- }
+ if (!data) {
+ LOG_ERROR("nothing to program");
+ return ERROR_NAND_OPERATION_FAILED;
}
{
- int retval = ERROR_OK;
- retval |= imx31_command(nand, NAND_CMD_SEQIN);
- retval |= imx31_address(nand, 0x00);
- retval |= imx31_address(nand, page & 0xff);
- retval |= imx31_address(nand, (page >> 8) & 0xff);
- if (nand->address_cycles >= 4)
- {
- retval |= imx31_address (nand, (page >> 16) & 0xff);
- if (nand->address_cycles >= 5)
- {
- retval |= imx31_address (nand, (page >> 24) & 0xff);
- }
- }
- target_write_buffer (target, MX3_NF_MAIN_BUFFER0, data_size, data);
- if (oob)
- {
- if (mx3_nf_info->flags.hw_ecc_enabled)
- {
- /*
- * part of spare block will be overrided by hardware
- * ECC generator
- */
- LOG_DEBUG
- ("part of spare block will be overrided by hardware ECC generator");
- }
- target_write_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
- oob);
- }
- /*
- * start data input operation (set MX3_NF_BIT_OP_DONE==0)
- */
- target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI);
- {
- int poll_result;
- poll_result = poll_for_complete_op (target, "data input");
- if (poll_result != ERROR_OK)
- {
- return poll_result;
+ /*
+ * validate target state
+ */
+ int retval;
+ retval = validate_target_state(nand);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ {
+ int retval = ERROR_OK;
+ retval |= imx31_command(nand, NAND_CMD_SEQIN);
+ retval |= imx31_address(nand, 0x00);
+ retval |= imx31_address(nand, page & 0xff);
+ retval |= imx31_address(nand, (page >> 8) & 0xff);
+ if (nand->address_cycles >= 4) {
+ retval |= imx31_address(nand, (page >> 16) & 0xff);
+ if (nand->address_cycles >= 5)
+ retval |= imx31_address(nand, (page >> 24) & 0xff);
}
- }
- retval |= imx31_command (nand, NAND_CMD_PAGEPROG);
- if (retval != ERROR_OK)
- {
- return retval;
- }
-
- /*
- * check status register
- */
- {
- uint16_t nand_status_content;
- retval = ERROR_OK;
- retval |= imx31_command(nand, NAND_CMD_STATUS);
- retval |= imx31_address(nand, 0x00);
- retval |= do_data_output(nand);
- if (retval != ERROR_OK)
+ target_write_buffer(target, MX3_NF_MAIN_BUFFER0, data_size, data);
+ if (oob) {
+ if (mx3_nf_info->flags.hw_ecc_enabled) {
+ /*
+ * part of spare block will be overrided by hardware
+ * ECC generator
+ */
+ LOG_DEBUG("part of spare block will be overrided by hardware ECC generator");
+ }
+ target_write_buffer(target, MX3_NF_SPARE_BUFFER0, oob_size, oob);
+ }
+ /*
+ * start data input operation (set MX3_NF_BIT_OP_DONE==0)
+ */
+ target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI);
{
- LOG_ERROR (get_status_register_err_msg);
- return retval;
+ int poll_result;
+ poll_result = poll_for_complete_op(target, "data input");
+ if (poll_result != ERROR_OK)
+ return poll_result;
}
- target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
- if (nand_status_content & 0x0001)
+ retval |= imx31_command(nand, NAND_CMD_PAGEPROG);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /*
+ * check status register
+ */
{
- /*
- * is host-big-endian correctly ??
- */
- return ERROR_NAND_OPERATION_FAILED;
+ uint16_t nand_status_content;
+ retval = ERROR_OK;
+ retval |= imx31_command(nand, NAND_CMD_STATUS);
+ retval |= imx31_address(nand, 0x00);
+ retval |= do_data_output(nand);
+ if (retval != ERROR_OK) {
+ LOG_ERROR(get_status_register_err_msg);
+ return retval;
+ }
+ target_read_u16(target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
+ if (nand_status_content & 0x0001) {
+ /*
+ * is host-big-endian correctly ??
+ */
+ return ERROR_NAND_OPERATION_FAILED;
+ }
}
}
- }
return ERROR_OK;
}
-static int imx31_read_page (struct nand_device *nand, uint32_t page,
- uint8_t * data, uint32_t data_size, uint8_t * oob,
- uint32_t oob_size)
+static int imx31_read_page(struct nand_device *nand, uint32_t page,
+ uint8_t *data, uint32_t data_size, uint8_t *oob,
+ uint32_t oob_size)
{
struct target *target = nand->target;
- if (data_size % 2)
- {
- LOG_ERROR (data_block_size_err_msg, data_size);
- return ERROR_NAND_OPERATION_FAILED;
+ if (data_size % 2) {
+ LOG_ERROR(data_block_size_err_msg, data_size);
+ return ERROR_NAND_OPERATION_FAILED;
}
- if (oob_size % 2)
- {
- LOG_ERROR (data_block_size_err_msg, oob_size);
- return ERROR_NAND_OPERATION_FAILED;
+ if (oob_size % 2) {
+ LOG_ERROR(data_block_size_err_msg, oob_size);
+ return ERROR_NAND_OPERATION_FAILED;
}
{
- /*
- * validate target state
- */
- int retval;
- retval = validate_target_state(nand);
- if (retval != ERROR_OK)
- {
- return retval;
- }
- }
- {
- int retval = ERROR_OK;
- retval |= imx31_command(nand, NAND_CMD_READ0);
- retval |= imx31_address(nand, 0x00);
- retval |= imx31_address(nand, page & 0xff);
- retval |= imx31_address(nand, (page >> 8) & 0xff);
- if (nand->address_cycles >= 4)
- {
- retval |= imx31_address(nand, (page >> 16) & 0xff);
- if (nand->address_cycles >= 5)
- {
- retval |= imx31_address(nand, (page >> 24) & 0xff);
- retval |= imx31_command(nand, NAND_CMD_READSTART);
- }
- }
- retval |= do_data_output (nand);
- if (retval != ERROR_OK)
- {
- return retval;
- }
-
- if (data)
- {
- target_read_buffer (target, MX3_NF_MAIN_BUFFER0, data_size,
- data);
- }
- if (oob)
- {
- target_read_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
- oob);
- }
+ /*
+ * validate target state
+ */
+ int retval;
+ retval = validate_target_state(nand);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ {
+ int retval = ERROR_OK;
+ retval |= imx31_command(nand, NAND_CMD_READ0);
+ retval |= imx31_address(nand, 0x00);
+ retval |= imx31_address(nand, page & 0xff);
+ retval |= imx31_address(nand, (page >> 8) & 0xff);
+ if (nand->address_cycles >= 4) {
+ retval |= imx31_address(nand, (page >> 16) & 0xff);
+ if (nand->address_cycles >= 5) {
+ retval |= imx31_address(nand, (page >> 24) & 0xff);
+ retval |= imx31_command(nand, NAND_CMD_READSTART);
+ }
+ }
+ retval |= do_data_output(nand);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (data) {
+ target_read_buffer(target, MX3_NF_MAIN_BUFFER0, data_size,
+ data);
+ }
+ if (oob) {
+ target_read_buffer(target, MX3_NF_SPARE_BUFFER0, oob_size,
+ oob);
+ }
}
return ERROR_OK;
}
-static int test_iomux_settings (struct target * target, uint32_t address,
- uint32_t mask, const char *text)
+static int test_iomux_settings(struct target *target, uint32_t address,
+ uint32_t mask, const char *text)
{
uint32_t register_content;
- target_read_u32 (target, address, ®ister_content);
- if ((register_content & mask) != (0x12121212 & mask))
- {
- LOG_ERROR ("IOMUX for {%s} is bad", text);
- return ERROR_FAIL;
+ target_read_u32(target, address, ®ister_content);
+ if ((register_content & mask) != (0x12121212 & mask)) {
+ LOG_ERROR("IOMUX for {%s} is bad", text);
+ return ERROR_FAIL;
}
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 target *target = nand->target;
/*
* 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;
- work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */
- if (target->endianness == TARGET_BIG_ENDIAN)
- {
- work_mode |= MX3_NF_BIT_BE_EN;
- }
- if (mx3_nf_info->flags.hw_ecc_enabled)
- {
- work_mode |= MX3_NF_BIT_ECC_EN;
- }
- target_write_u16 (target, MX3_NF_CFG1, work_mode);
+ uint16_t work_mode;
+ work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */
+ if (target->endianness == TARGET_BIG_ENDIAN)
+ work_mode |= MX3_NF_BIT_BE_EN;
+ if (mx3_nf_info->flags.hw_ecc_enabled)
+ work_mode |= MX3_NF_BIT_ECC_EN;
+ target_write_u16(target, MX3_NF_CFG1, work_mode);
}
/*
* 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;
- target_read_u16 (target, MX3_NF_FWP, &temp);
- if ((temp & 0x0007) == 1)
- {
- LOG_ERROR ("NAND flash is tight-locked, reset needed");
- return ERROR_FAIL;
- }
+ uint16_t temp;
+ target_read_u16(target, MX3_NF_FWP, &temp);
+ if ((temp & 0x0007) == 1) {
+ LOG_ERROR("NAND flash is tight-locked, reset needed");
+ return ERROR_FAIL;
+ }
}
/*
* unlock NAND flash for write
*/
- target_write_u16 (target, MX3_NF_FWP, 4);
- target_write_u16 (target, MX3_NF_LOCKSTART, 0x0000);
- target_write_u16 (target, MX3_NF_LOCKEND, 0xFFFF);
+ target_write_u16(target, MX3_NF_FWP, 4);
+ target_write_u16(target, MX3_NF_LOCKSTART, 0x0000);
+ target_write_u16(target, MX3_NF_LOCKEND, 0xFFFF);
/*
* 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
*/
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 ??
*/
if (sign_of_sequental_byte_read == 0)
- {
- even_byte = 0;
- }
- if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR)
- {
- LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
- *value = 0;
- sign_of_sequental_byte_read = 0;
- even_byte = 0;
- return ERROR_NAND_OPERATION_FAILED;
- }
- else
- {
- uint16_t temp;
- target_read_u16 (target, in_sram_address, &temp);
- if (even_byte)
- {
- *value = temp >> 8;
- even_byte = 0;
- in_sram_address += 2;
- }
- else
- {
- *value = temp & 0xff;
- even_byte = 1;
+ even_byte = 0;
+ if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) {
+ LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
+ *value = 0;
+ sign_of_sequental_byte_read = 0;
+ even_byte = 0;
+ return ERROR_NAND_OPERATION_FAILED;
+ } else {
+ uint16_t temp;
+ target_read_u16(target, in_sram_address, &temp);
+ if (even_byte) {
+ *value = temp >> 8;
+ even_byte = 0;
+ in_sram_address += 2;
+ } else {
+ *value = temp & 0xff;
+ even_byte = 1;
}
}
sign_of_sequental_byte_read = 1;
return ERROR_OK;
}
-static int get_next_halfword_from_sram_buffer (struct target * target,
- uint16_t * value)
+static int get_next_halfword_from_sram_buffer(struct target *target,
+ uint16_t *value)
{
- if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR)
- {
- LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
- *value = 0;
- return ERROR_NAND_OPERATION_FAILED;
- }
- else
- {
- target_read_u16 (target, in_sram_address, value);
- in_sram_address += 2;
+ if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) {
+ LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
+ *value = 0;
+ return ERROR_NAND_OPERATION_FAILED;
+ } else {
+ target_read_u16(target, in_sram_address, value);
+ in_sram_address += 2;
}
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;
- for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++)
- {
- usleep (25);
- target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
- if (poll_complete_status & MX3_NF_BIT_OP_DONE)
- {
- break;
- }
+ for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++) {
+ usleep(25);
+ target_read_u16(target, MX3_NF_CFG2, &poll_complete_status);
+ if (poll_complete_status & MX3_NF_BIT_OP_DONE)
+ break;
}
- if (!(poll_complete_status & MX3_NF_BIT_OP_DONE))
- {
- LOG_ERROR ("%s sending timeout", text);
- return ERROR_NAND_OPERATION_FAILED;
+ if (!(poll_complete_status & MX3_NF_BIT_OP_DONE)) {
+ LOG_ERROR("%s sending timeout", text);
+ return ERROR_NAND_OPERATION_FAILED;
}
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 target *target = nand->target;
- if (target->state != TARGET_HALTED)
- {
- LOG_ERROR (target_not_halted_err_msg);
- return ERROR_NAND_OPERATION_FAILED;
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR(target_not_halted_err_msg);
+ return ERROR_NAND_OPERATION_FAILED;
}
if (mx3_nf_info->flags.target_little_endian !=
- (target->endianness == TARGET_LITTLE_ENDIAN))
- {
- /*
- * endianness changed after NAND controller probed
- */
- return ERROR_NAND_OPERATION_FAILED;
+ (target->endianness == TARGET_LITTLE_ENDIAN)) {
+ /*
+ * endianness changed after NAND controller probed
+ */
+ return ERROR_NAND_OPERATION_FAILED;
}
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 target *target = nand->target;
- switch (mx3_nf_info->fin)
- {
- case MX3_NF_FIN_DATAOUT:
- /*
- * start data output operation (set MX3_NF_BIT_OP_DONE==0)
- */
- target_write_u16 (target, MX3_NF_CFG2,
- MX3_NF_BIT_DATAOUT_TYPE (mx3_nf_info->
- optype));
- {
- int poll_result;
- poll_result = poll_for_complete_op (target, "data output");
- if (poll_result != ERROR_OK)
+ switch (mx3_nf_info->fin) {
+ case MX3_NF_FIN_DATAOUT:
+ /*
+ * start data output operation (set MX3_NF_BIT_OP_DONE==0)
+ */
+ target_write_u16 (target, MX3_NF_CFG2,
+ MX3_NF_BIT_DATAOUT_TYPE(mx3_nf_info->optype));
{
- return poll_result;
+ int poll_result;
+ poll_result = poll_for_complete_op(target, "data output");
+ if (poll_result != ERROR_OK)
+ return poll_result;
}
- }
- mx3_nf_info->fin = MX3_NF_FIN_NONE;
- /*
- * ECC stuff
- */
- if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE)
- && mx3_nf_info->flags.hw_ecc_enabled)
- {
- uint16_t ecc_status;
- target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
- switch (ecc_status & 0x000c)
- {
+ mx3_nf_info->fin = MX3_NF_FIN_NONE;
+ /*
+ * ECC stuff
+ */
+ if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE)
+ && mx3_nf_info->flags.hw_ecc_enabled) {
+ uint16_t ecc_status;
+ target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
+ switch (ecc_status & 0x000c) {
case 1 << 2:
- LOG_DEBUG
- ("main area readed with 1 (correctable) error");
- break;
+ LOG_DEBUG("main area readed with 1 (correctable) error");
+ break;
case 2 << 2:
- LOG_DEBUG
- ("main area readed with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- break;
- }
- switch (ecc_status & 0x0003)
- {
+ LOG_DEBUG("main area readed with more than 1 (incorrectable) error");
+ return ERROR_NAND_OPERATION_FAILED;
+ break;
+ }
+ switch (ecc_status & 0x0003) {
case 1:
- LOG_DEBUG
- ("spare area readed with 1 (correctable) error");
- break;
+ LOG_DEBUG("spare area readed with 1 (correctable) error");
+ break;
case 2:
- LOG_DEBUG
- ("main area readed with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- break;
- }
- }
- break;
- case MX3_NF_FIN_NONE:
- break;
+ LOG_DEBUG("main area readed with more than 1 (incorrectable) error");
+ return ERROR_NAND_OPERATION_FAILED;
+ break;
+ }
+ }
+ break;
+ case MX3_NF_FIN_NONE:
+ break;
}
return ERROR_OK;
}
struct nand_flash_controller imx31_nand_flash_controller = {
- .name = "imx31",
- .usage = "nand device imx31 target noecc|hwecc",
- .nand_device_command = &imx31_nand_device_command,
- .init = &imx31_init,
- .reset = &imx31_reset,
- .command = &imx31_command,
- .address = &imx31_address,
- .write_data = &imx31_write_data,
- .read_data = &imx31_read_data,
- .write_page = &imx31_write_page,
- .read_page = &imx31_read_page,
- .nand_ready = &imx31_nand_ready,
- };
+ .name = "imx31",
+ .usage = "nand device imx31 target noecc|hwecc",
+ .nand_device_command = &imx31_nand_device_command,
+ .init = &imx31_init,
+ .reset = &imx31_reset,
+ .command = &imx31_command,
+ .address = &imx31_address,
+ .write_data = &imx31_write_data,
+ .read_data = &imx31_read_data,
+ .write_page = &imx31_write_page,
+ .read_page = &imx31_read_page,
+ .nand_ready = &imx31_nand_ready,
+};
-
/***************************************************************************
* Copyright (C) 2009 by Alexei Babich *
* Rezonans plc., Chelyabinsk, Russia *
* Many thanks to Ben Dooks for writing s3c24xx driver.
*/
-#define MX3_NF_BASE_ADDR 0xb8000000
-#define MX3_NF_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00)
-#define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04)
-#define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06)
-#define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08)
-#define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a)
-#define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c)
-#define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e)
-#define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10)
-#define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12)
-#define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14)
-#define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16)
-#define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18)
- /*
- * all bits not marked as self-clearing bit
- */
-#define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a)
-#define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c)
+#define MX3_NF_BASE_ADDR 0xb8000000
+#define MX3_NF_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00)
+#define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04)
+#define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06)
+#define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08)
+#define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a)
+#define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c)
+#define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e)
+#define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10)
+#define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12)
+#define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14)
+#define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16)
+#define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18)
+/*
+ * all bits not marked as self-clearing bit
+ */
+#define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a)
+#define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c)
-#define MX3_NF_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000)
-#define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200)
-#define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400)
-#define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600)
-#define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800)
-#define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810)
-#define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820)
-#define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830)
-#define MX3_NF_MAIN_BUFFER_LEN 512
-#define MX3_NF_SPARE_BUFFER_LEN 16
-#define MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2)
+#define MX3_NF_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000)
+#define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200)
+#define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400)
+#define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600)
+#define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800)
+#define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810)
+#define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820)
+#define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830)
+#define MX3_NF_MAIN_BUFFER_LEN 512
+#define MX3_NF_SPARE_BUFFER_LEN 16
+#define MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2)
/* bits in MX3_NF_CFG1 register */
-#define MX3_NF_BIT_SPARE_ONLY_EN (1<<2)
-#define MX3_NF_BIT_ECC_EN (1<<3)
-#define MX3_NF_BIT_INT_DIS (1<<4)
-#define MX3_NF_BIT_BE_EN (1<<5)
-#define MX3_NF_BIT_RESET_EN (1<<6)
-#define MX3_NF_BIT_FORCE_CE (1<<7)
+#define MX3_NF_BIT_SPARE_ONLY_EN (1<<2)
+#define MX3_NF_BIT_ECC_EN (1<<3)
+#define MX3_NF_BIT_INT_DIS (1<<4)
+#define MX3_NF_BIT_BE_EN (1<<5)
+#define MX3_NF_BIT_RESET_EN (1<<6)
+#define MX3_NF_BIT_FORCE_CE (1<<7)
/* bits in MX3_NF_CFG2 register */
/*Flash Command Input*/
-#define MX3_NF_BIT_OP_FCI (1<<0)
- /*
- * Flash Address Input
- */
-#define MX3_NF_BIT_OP_FAI (1<<1)
- /*
- * Flash Data Input
- */
-#define MX3_NF_BIT_OP_FDI (1<<2)
+#define MX3_NF_BIT_OP_FCI (1<<0)
+/*
+ * Flash Address Input
+ */
+#define MX3_NF_BIT_OP_FAI (1<<1)
+/*
+ * Flash Data Input
+ */
+#define MX3_NF_BIT_OP_FDI (1<<2)
/* see "enum mx_dataout_type" below */
-#define MX3_NF_BIT_DATAOUT_TYPE(x) ((x)<<3)
-#define MX3_NF_BIT_OP_DONE (1<<15)
+#define MX3_NF_BIT_DATAOUT_TYPE(x) ((x)<<3)
+#define MX3_NF_BIT_OP_DONE (1<<15)
-#define MX3_CCM_CGR2 0x53f80028
-#define MX3_GPR 0x43fac008
-#define MX3_PCSR 0x53f8000c
+#define MX3_CCM_CGR2 0x53f80028
+#define MX3_GPR 0x43fac008
+#define MX3_PCSR 0x53f8000c
-enum mx_dataout_type
-{
+enum mx_dataout_type {
MX3_NF_DATAOUT_PAGE = 1,
MX3_NF_DATAOUT_NANDID = 2,
MX3_NF_DATAOUT_NANDSTATUS = 4,
};
-enum mx_nf_finalize_action
-{
+enum mx_nf_finalize_action {
MX3_NF_FIN_NONE,
MX3_NF_FIN_DATAOUT,
};
-struct mx3_nf_flags
-{
+struct mx3_nf_flags {
unsigned host_little_endian:1;
unsigned target_little_endian:1;
unsigned nand_readonly:1;
unsigned hw_ecc_enabled:1;
};
-struct mx3_nf_controller
-{
+struct mx3_nf_controller {
enum mx_dataout_type optype;
enum mx_nf_finalize_action fin;
struct mx3_nf_flags flags;
#include "mxc.h"
#include <target/target.h>
-#define OOB_SIZE 64
+#define OOB_SIZE 64
#define nfc_is_v1() (mxc_nf_info->mxc_version == MXC_VERSION_MX27 || \
- mxc_nf_info->mxc_version == MXC_VERSION_MX31)
+ mxc_nf_info->mxc_version == MXC_VERSION_MX31)
#define nfc_is_v2() (mxc_nf_info->mxc_version == MXC_VERSION_MX25 || \
- mxc_nf_info->mxc_version == MXC_VERSION_MX35)
+ mxc_nf_info->mxc_version == MXC_VERSION_MX35)
/* This permits to print (in LOG_INFO) how much bytes
* has been written after a page read or write.
mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
mxc_nf_info->fin = MXC_NF_FIN_NONE;
mxc_nf_info->flags.target_little_endian =
- (nand->target->endianness == TARGET_LITTLE_ENDIAN);
+ (nand->target->endianness == TARGET_LITTLE_ENDIAN);
/*
* should factory bad block indicator be swaped
static const struct command_registration mxc_sub_command_handlers[] = {
{
.name = "biswap",
- .handler = handle_mxc_biswap_command ,
+ .handler = handle_mxc_biswap_command,
.help = "Turns on/off bad block information swaping from main area, "
- "without parameter query status.",
+ "without parameter query status.",
.usage = "bank_id ['enable'|'disable']",
},
COMMAND_REGISTRATION_DONE
else
LOG_DEBUG("MXC_NF : bus is 8-bit width");
- if (!nand->page_size) {
+ if (!nand->page_size)
nand->page_size = (sreg_content & SEL_FMS) ? 2048 : 512;
- } else {
+ else {
sreg_content |= ((nand->page_size == 2048) ? SEL_FMS : 0x00000000);
target_write_u32(target, SREG, sreg_content);
}
if (mxc_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) {
LOG_ERROR("NAND controller have only 1 kb SRAM, so "
- "pagesize 2048 is incompatible with it");
- } else {
+ "pagesize 2048 is incompatible with it");
+ } else
LOG_DEBUG("MXC_NF : NAND controller can handle pagesize of 2048");
- }
if (nfc_is_v2() && sreg_content & MX35_RCSR_NF_4K)
LOG_ERROR("MXC driver does not have support for 4k pagesize.");
if (!(nand_status_content & 0x0080)) {
LOG_INFO("NAND read-only");
mxc_nf_info->flags.nand_readonly = 1;
- } else {
+ } else
mxc_nf_info->flags.nand_readonly = 0;
- }
return ERROR_OK;
}
try_data_output_from_nand_chip = do_data_output(nand);
if (try_data_output_from_nand_chip != ERROR_OK) {
LOG_ERROR("mxc_read_data : read data failed : '%x'",
- try_data_output_from_nand_chip);
+ try_data_output_from_nand_chip);
return try_data_output_from_nand_chip;
}
return validate_target_result;
switch (command) {
- case NAND_CMD_READOOB:
- command = NAND_CMD_READ0;
- /* set read point for data_read() and read_block_data() to
- * spare area in SRAM buffer
- */
- if (nfc_is_v1())
- in_sram_address = MXC_NF_V1_SPARE_BUFFER0;
- else
- in_sram_address = MXC_NF_V2_SPARE_BUFFER0;
- break;
- case NAND_CMD_READ1:
- command = NAND_CMD_READ0;
- /*
- * offset == one half of page size
- */
- in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
- break;
- default:
- in_sram_address = MXC_NF_MAIN_BUFFER0;
- break;
+ case NAND_CMD_READOOB:
+ command = NAND_CMD_READ0;
+ /* set read point for data_read() and read_block_data() to
+ * spare area in SRAM buffer
+ */
+ if (nfc_is_v1())
+ in_sram_address = MXC_NF_V1_SPARE_BUFFER0;
+ else
+ in_sram_address = MXC_NF_V2_SPARE_BUFFER0;
+ break;
+ case NAND_CMD_READ1:
+ command = NAND_CMD_READ0;
+ /*
+ * offset == one half of page size
+ */
+ in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
+ break;
+ default:
+ in_sram_address = MXC_NF_MAIN_BUFFER0;
+ break;
}
target_write_u16(target, MXC_NF_FCMD, command);
sign_of_sequental_byte_read = 0;
/* Handle special read command and adjust NF_CFG2(FDO) */
switch (command) {
- case NAND_CMD_READID:
- mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID;
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_STATUS:
- mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS;
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- target_write_u16 (target, MXC_NF_BUFADDR, 0);
- in_sram_address = 0;
- break;
- case NAND_CMD_READ0:
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
- break;
- default:
- /* Ohter command use the default 'One page data out' FDO */
- mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
- break;
+ case NAND_CMD_READID:
+ mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID;
+ mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
+ break;
+ case NAND_CMD_STATUS:
+ mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS;
+ mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
+ target_write_u16 (target, MXC_NF_BUFADDR, 0);
+ in_sram_address = 0;
+ break;
+ case NAND_CMD_READ0:
+ mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
+ mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
+ break;
+ default:
+ /* Ohter command use the default 'One page data out' FDO */
+ mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
+ break;
}
return ERROR_OK;
}
return tout;
alive_sleep(1);
- }
- while (tout-- > 0);
+ } while (tout-- > 0);
return tout;
}
static int mxc_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target;
sign_of_sequental_byte_read = 0;
retval = ERROR_OK;
retval |= mxc_command(nand, NAND_CMD_SEQIN);
- retval |= mxc_address(nand, 0); /* col */
- retval |= mxc_address(nand, 0); /* col */
- retval |= mxc_address(nand, page & 0xff); /* page address */
- retval |= mxc_address(nand, (page >> 8) & 0xff); /* page address */
- retval |= mxc_address(nand, (page >> 16) & 0xff); /* page address */
+ retval |= mxc_address(nand, 0); /* col */
+ retval |= mxc_address(nand, 0); /* col */
+ retval |= mxc_address(nand, page & 0xff); /* page address */
+ retval |= mxc_address(nand, (page >> 8) & 0xff);/* page address */
+ retval |= mxc_address(nand, (page >> 16) & 0xff); /* page address */
target_write_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data);
if (oob) {
* ECC generator
*/
LOG_DEBUG("part of spare block will be overrided "
- "by hardware ECC generator");
+ "by hardware ECC generator");
}
if (nfc_is_v1())
target_write_buffer(target, MXC_NF_V1_SPARE_BUFFER0, oob_size, oob);
LOG_ERROR("Due to NFC Bug, oob is not correctly implemented in mxc driver");
return ERROR_NAND_OPERATION_FAILED;
}
- swap2 = 0xffff; /* Spare buffer unused forced to 0xffff */
+ swap2 = 0xffff; /* Spare buffer unused forced to 0xffff */
new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8);
swap2 = (swap1 << 8) | (swap2 & 0xFF);
target_write_u16(target, MXC_NF_MAIN_BUFFER3 + 464, new_swap1);
else
bufs = 1;
- for (uint8_t i = 0 ; i < bufs ; ++i) {
+ for (uint8_t i = 0; i < bufs; ++i) {
target_write_u16(target, MXC_NF_BUFADDR, i);
target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FDI);
poll_result = poll_for_complete_op(nand, "data input");
}
static int mxc_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
+ uint8_t *data, uint32_t data_size,
+ uint8_t *oob, uint32_t oob_size)
{
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target;
* validate target state
*/
retval = validate_target_state(nand);
- if (retval != ERROR_OK) {
+ if (retval != ERROR_OK)
return retval;
- }
- /* Reset address_cycles before mxc_command ?? */
+ /* Reset address_cycles before mxc_command ?? */
retval = mxc_command(nand, NAND_CMD_READ0);
- if (retval != ERROR_OK) return retval;
- retval = mxc_address(nand, 0); /* col */
- if (retval != ERROR_OK) return retval;
- retval = mxc_address(nand, 0); /* col */
- if (retval != ERROR_OK) return retval;
- retval = mxc_address(nand, page & 0xff); /* page address */
- if (retval != ERROR_OK) return retval;
- retval = mxc_address(nand, (page >> 8) & 0xff); /* page address */
- if (retval != ERROR_OK) return retval;
- retval = mxc_address(nand, (page >> 16) & 0xff); /* page address */
- if (retval != ERROR_OK) return retval;
+ if (retval != ERROR_OK)
+ return retval;
+ retval = mxc_address(nand, 0); /* col */
+ if (retval != ERROR_OK)
+ return retval;
+ retval = mxc_address(nand, 0); /* col */
+ if (retval != ERROR_OK)
+ return retval;
+ retval = mxc_address(nand, page & 0xff);/* page address */
+ if (retval != ERROR_OK)
+ return retval;
+ retval = mxc_address(nand, (page >> 8) & 0xff); /* page address */
+ if (retval != ERROR_OK)
+ return retval;
+ retval = mxc_address(nand, (page >> 16) & 0xff);/* page address */
+ if (retval != ERROR_OK)
+ return retval;
retval = mxc_command(nand, NAND_CMD_READSTART);
- if (retval != ERROR_OK) return retval;
+ if (retval != ERROR_OK)
+ return retval;
if (nfc_is_v1() && nand->page_size > 512)
bufs = 4;
else
bufs = 1;
- for (uint8_t i = 0 ; i < bufs ; ++i) {
+ for (uint8_t i = 0; i < bufs; ++i) {
target_write_u16(target, MXC_NF_BUFADDR, i);
mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
retval = do_data_output(nand);
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
uint32_t ret = addr;
if (addr > MXC_NF_V2_SPARE_BUFFER0 &&
- (addr & 0x1F) == MXC_NF_SPARE_BUFFER_LEN) {
+ (addr & 0x1F) == MXC_NF_SPARE_BUFFER_LEN)
ret += MXC_NF_SPARE_BUFFER_MAX - MXC_NF_SPARE_BUFFER_LEN;
- } else if (addr >= (mxc_nf_info->mxc_base_addr + (uint32_t)nand->page_size))
+ else if (addr >= (mxc_nf_info->mxc_base_addr + (uint32_t)nand->page_size))
ret = MXC_NF_V2_SPARE_BUFFER0;
return ret;
}
if (target->endianness == TARGET_BIG_ENDIAN) {
LOG_DEBUG("MXC_NF : work in Big Endian mode");
work_mode |= MXC_NF_BIT_BE_EN;
- } else {
+ } else
LOG_DEBUG("MXC_NF : work in Little Endian mode");
- }
if (mxc_nf_info->flags.hw_ecc_enabled) {
LOG_DEBUG("MXC_NF : work with ECC mode");
work_mode |= MXC_NF_BIT_ECC_EN;
- } else {
+ } else
LOG_DEBUG("MXC_NF : work without ECC mode");
- }
if (nfc_is_v2()) {
target_write_u16(target, MXC_NF_V2_SPAS, OOB_SIZE / 2);
if (nand->page_size) {
{
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target;
- static uint8_t even_byte = 0;
+ static uint8_t even_byte;
uint16_t temp;
/*
* host-big_endian ??
if (sign_of_sequental_byte_read == 0)
even_byte = 0;
- if (in_sram_address >
- (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
+ if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
*value = 0;
sign_of_sequental_byte_read = 0;
struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
struct target *target = nand->target;
- if (in_sram_address >
- (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
+ if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
*value = 0;
return ERROR_NAND_OPERATION_FAILED;
}
if (mxc_nf_info->flags.target_little_endian !=
- (target->endianness == TARGET_LITTLE_ENDIAN)) {
+ (target->endianness == TARGET_LITTLE_ENDIAN)) {
/*
* endianness changed after NAND controller probed
*/
target_read_u16(target, MXC_NF_ECCSTATUS, &ecc_status);
switch (ecc_status & 0x000c) {
- case 1 << 2:
- LOG_INFO("main area read with 1 (correctable) error");
- break;
- case 2 << 2:
- LOG_INFO("main area read with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- break;
+ case 1 << 2:
+ LOG_INFO("main area read with 1 (correctable) error");
+ break;
+ case 2 << 2:
+ LOG_INFO("main area read with more than 1 (incorrectable) error");
+ return ERROR_NAND_OPERATION_FAILED;
+ break;
}
switch (ecc_status & 0x0003) {
- case 1:
- LOG_INFO("spare area read with 1 (correctable) error");
- break;
- case 2:
- LOG_INFO("main area read with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- break;
+ case 1:
+ LOG_INFO("spare area read with 1 (correctable) error");
+ break;
+ case 2:
+ LOG_INFO("main area read with more than 1 (incorrectable) error");
+ return ERROR_NAND_OPERATION_FAILED;
+ break;
}
return ERROR_OK;
}
struct target *target = nand->target;
int poll_result;
switch (mxc_nf_info->fin) {
- case MXC_NF_FIN_DATAOUT:
- /*
- * start data output operation (set MXC_NF_BIT_OP_DONE==0)
- */
- target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_DATAOUT_TYPE(mxc_nf_info->optype));
- poll_result = poll_for_complete_op(nand, "data output");
- if (poll_result != ERROR_OK)
- return poll_result;
+ case MXC_NF_FIN_DATAOUT:
+ /*
+ * start data output operation (set MXC_NF_BIT_OP_DONE==0)
+ */
+ target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_DATAOUT_TYPE(mxc_nf_info->optype));
+ poll_result = poll_for_complete_op(nand, "data output");
+ if (poll_result != ERROR_OK)
+ return poll_result;
- mxc_nf_info->fin = MXC_NF_FIN_NONE;
- /*
- * ECC stuff
- */
- if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE &&
- mxc_nf_info->flags.hw_ecc_enabled) {
- int ecc_status;
- if (nfc_is_v1())
- ecc_status = ecc_status_v1(nand);
- else
- ecc_status = ecc_status_v2(nand);
- if (ecc_status != ERROR_OK)
- return ecc_status;
- }
- break;
- case MXC_NF_FIN_NONE:
- break;
+ mxc_nf_info->fin = MXC_NF_FIN_NONE;
+ /*
+ * ECC stuff
+ */
+ if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && mxc_nf_info->flags.hw_ecc_enabled) {
+ int ecc_status;
+ if (nfc_is_v1())
+ ecc_status = ecc_status_v1(nand);
+ else
+ ecc_status = ecc_status_v2(nand);
+ if (ecc_status != ERROR_OK)
+ return ecc_status;
+ }
+ break;
+ case MXC_NF_FIN_NONE:
+ break;
}
return ERROR_OK;
}
struct nand_flash_controller mxc_nand_flash_controller = {
- .name = "mxc",
- .nand_device_command = &mxc_nand_device_command,
- .commands = mxc_nand_command_handler,
- .init = &mxc_init,
- .reset = &mxc_reset,
- .command = &mxc_command,
- .address = &mxc_address,
- .write_data = &mxc_write_data,
- .read_data = &mxc_read_data,
- .write_page = &mxc_write_page,
- .read_page = &mxc_read_page,
- .nand_ready = &mxc_nand_ready,
+ .name = "mxc",
+ .nand_device_command = &mxc_nand_device_command,
+ .commands = mxc_nand_command_handler,
+ .init = &mxc_init,
+ .reset = &mxc_reset,
+ .command = &mxc_command,
+ .address = &mxc_address,
+ .write_data = &mxc_write_data,
+ .read_data = &mxc_read_data,
+ .write_page = &mxc_write_page,
+ .read_page = &mxc_read_page,
+ .nand_ready = &mxc_nand_ready,
};
#include "imp.h"
#include "hello.h"
-
static int nonce_nand_command(struct nand_device *nand, uint8_t command)
{
return ERROR_OK;
return ERROR_OK;
}
-struct nand_flash_controller nonce_nand_controller =
-{
- .name = "nonce",
- .commands = hello_command_handlers,
- .nand_device_command = &nonce_nand_device_command,
- .init = &nonce_nand_init,
- .reset = &nonce_nand_reset,
- .command = &nonce_nand_command,
- .address = &nonce_nand_address,
- .read_data = &nonce_nand_read,
- .write_data = &nonce_nand_write,
- .write_block_data = &nonce_nand_fast_block_write,
+struct nand_flash_controller nonce_nand_controller = {
+ .name = "nonce",
+ .commands = hello_command_handlers,
+ .nand_device_command = &nonce_nand_device_command,
+ .init = &nonce_nand_init,
+ .reset = &nonce_nand_reset,
+ .command = &nonce_nand_command,
+ .address = &nonce_nand_address,
+ .read_data = &nonce_nand_read,
+ .write_data = &nonce_nand_write,
+ .write_block_data = &nonce_nand_fast_block_write,
};
#include "arm_io.h"
#include <target/arm.h>
-struct nuc910_nand_controller
-{
+struct nuc910_nand_controller {
struct arm_nand_data io;
};
struct target *target = nand->target;
int result;
- if ((result = validate_target_state(nand)) != ERROR_OK)
+ result = validate_target_state(nand);
+ if (result != ERROR_OK)
return result;
target_write_u8(target, NUC910_SMCMD, command);
struct target *target = nand->target;
int result;
- if ((result = validate_target_state(nand)) != ERROR_OK)
+ result = validate_target_state(nand);
+ if (result != ERROR_OK)
return result;
target_write_u32(target, NUC910_SMADDR, ((address & 0xff) | NUC910_SMADDR_EOA));
struct target *target = nand->target;
int result;
- if ((result = validate_target_state(nand)) != ERROR_OK)
+ result = validate_target_state(nand);
+ if (result != ERROR_OK)
return result;
target_read_u8(target, NUC910_SMDATA, data);
struct target *target = nand->target;
int result;
- if ((result = validate_target_state(nand)) != ERROR_OK)
+ result = validate_target_state(nand);
+ if (result != ERROR_OK)
return result;
target_write_u8(target, NUC910_SMDATA, data);
struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
int result;
- if ((result = validate_target_state(nand)) != ERROR_OK)
+ result = validate_target_state(nand);
+ if (result != ERROR_OK)
return result;
nuc910_nand->io.chunk_size = nand->page_size;
struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
int result;
- if ((result = validate_target_state(nand)) != ERROR_OK)
+ result = validate_target_state(nand);
+ if (result != ERROR_OK)
return result;
nuc910_nand->io.chunk_size = nand->page_size;
do {
target_read_u32(target, NUC910_SMISR, &status);
- if (status & NUC910_SMISR_RB_) {
+ if (status & NUC910_SMISR_RB_)
return 1;
- }
alive_sleep(1);
} while (timeout-- > 0);
int bus_width = nand->bus_width ? : 8;
int result;
- if ((result = validate_target_state(nand)) != ERROR_OK)
+ result = validate_target_state(nand);
+ if (result != ERROR_OK)
return result;
/* nuc910 only supports 8bit */
- if (bus_width != 8)
- {
+ if (bus_width != 8) {
LOG_ERROR("nuc910 only supports 8 bit bus width, not %i", bus_width);
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
}
return ERROR_OK;
}
-struct nand_flash_controller nuc910_nand_controller =
-{
+struct nand_flash_controller nuc910_nand_controller = {
.name = "nuc910",
.command = nuc910_nand_command,
.address = nuc910_nand_address,
#include "arm_io.h"
#include <target/arm.h>
-
-struct orion_nand_controller
-{
+struct orion_nand_controller {
struct arm_nand_data io;
uint32_t cmd;
uint32_t base;
uint8_t ale, cle;
- if (CMD_ARGC != 3) {
+ if (CMD_ARGC != 3)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
hw = calloc(1, sizeof(*hw));
if (!hw) {
return ERROR_OK;
}
-struct nand_flash_controller orion_nand_controller =
-{
- .name = "orion",
- .usage = "<target_id> <NAND_address>",
- .command = orion_nand_command,
- .address = orion_nand_address,
- .read_data = orion_nand_read,
- .write_data = orion_nand_write,
- .write_block_data = orion_nand_fast_block_write,
- .reset = orion_nand_reset,
- .nand_device_command = orion_nand_device_command,
- .init = orion_nand_init,
+struct nand_flash_controller orion_nand_controller = {
+ .name = "orion",
+ .usage = "<target_id> <NAND_address>",
+ .command = orion_nand_command,
+ .address = orion_nand_address,
+ .read_data = orion_nand_read,
+ .write_data = orion_nand_write,
+ .write_block_data = orion_nand_fast_block_write,
+ .reset = orion_nand_reset,
+ .nand_device_command = orion_nand_device_command,
+ .init = orion_nand_init,
};
-
}
struct nand_flash_controller s3c2410_nand_controller = {
- .name = "s3c2410",
- .nand_device_command = &s3c2410_nand_device_command,
- .init = &s3c2410_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c2410_write_data,
- .read_data = &s3c2410_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .nand_ready = &s3c2410_nand_ready,
- };
+ .name = "s3c2410",
+ .nand_device_command = &s3c2410_nand_device_command,
+ .init = &s3c2410_init,
+ .reset = &s3c24xx_reset,
+ .command = &s3c24xx_command,
+ .address = &s3c24xx_address,
+ .write_data = &s3c2410_write_data,
+ .read_data = &s3c2410_read_data,
+ .write_page = s3c24xx_write_page,
+ .read_page = s3c24xx_read_page,
+ .nand_ready = &s3c2410_nand_ready,
+};
}
struct nand_flash_controller s3c2412_nand_controller = {
- .name = "s3c2412",
- .nand_device_command = &s3c2412_nand_device_command,
- .init = &s3c2412_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c24xx_write_data,
- .read_data = &s3c24xx_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .write_block_data = &s3c2440_write_block_data,
- .read_block_data = &s3c2440_read_block_data,
- .nand_ready = &s3c2440_nand_ready,
- };
+ .name = "s3c2412",
+ .nand_device_command = &s3c2412_nand_device_command,
+ .init = &s3c2412_init,
+ .reset = &s3c24xx_reset,
+ .command = &s3c24xx_command,
+ .address = &s3c24xx_address,
+ .write_data = &s3c24xx_write_data,
+ .read_data = &s3c24xx_read_data,
+ .write_page = s3c24xx_write_page,
+ .read_page = s3c24xx_read_page,
+ .write_block_data = &s3c2440_write_block_data,
+ .read_block_data = &s3c2440_read_block_data,
+ .nand_ready = &s3c2440_nand_ready,
+};
#include "s3c24xx.h"
-
NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
{
struct s3c24xx_nand_controller *info;
}
struct nand_flash_controller s3c2440_nand_controller = {
- .name = "s3c2440",
- .nand_device_command = &s3c2440_nand_device_command,
- .init = &s3c2440_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c24xx_write_data,
- .read_data = &s3c24xx_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .write_block_data = &s3c2440_write_block_data,
- .read_block_data = &s3c2440_read_block_data,
- .nand_ready = &s3c2440_nand_ready,
- };
+ .name = "s3c2440",
+ .nand_device_command = &s3c2440_nand_device_command,
+ .init = &s3c2440_init,
+ .reset = &s3c24xx_reset,
+ .command = &s3c24xx_command,
+ .address = &s3c24xx_address,
+ .write_data = &s3c24xx_write_data,
+ .read_data = &s3c24xx_read_data,
+ .write_page = s3c24xx_write_page,
+ .read_page = s3c24xx_read_page,
+ .write_block_data = &s3c2440_write_block_data,
+ .read_block_data = &s3c2440_read_block_data,
+ .nand_ready = &s3c2440_nand_ready,
+};
#include "s3c24xx.h"
-
NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command)
{
struct s3c24xx_nand_controller *info;
}
struct nand_flash_controller s3c2443_nand_controller = {
- .name = "s3c2443",
- .nand_device_command = &s3c2443_nand_device_command,
- .init = &s3c2443_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c24xx_write_data,
- .read_data = &s3c24xx_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .write_block_data = &s3c2440_write_block_data,
- .read_block_data = &s3c2440_read_block_data,
- .nand_ready = &s3c2440_nand_ready,
- };
+ .name = "s3c2443",
+ .nand_device_command = &s3c2443_nand_device_command,
+ .init = &s3c2443_init,
+ .reset = &s3c24xx_reset,
+ .command = &s3c24xx_command,
+ .address = &s3c24xx_address,
+ .write_data = &s3c24xx_write_data,
+ .read_data = &s3c24xx_read_data,
+ .write_page = s3c24xx_write_page,
+ .read_page = s3c24xx_read_page,
+ .write_block_data = &s3c2440_write_block_data,
+ .read_block_data = &s3c2440_read_block_data,
+ .nand_ready = &s3c2440_nand_ready,
+};
#include "s3c24xx.h"
-
S3C24XX_DEVICE_COMMAND()
{
*info = NULL;
return ERROR_OK;
}
-
int s3c24xx_address(struct nand_device *nand, uint8_t address)
{
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
#include "s3c24xx_regs.h"
#include <target/target.h>
-struct s3c24xx_nand_controller
-{
+struct s3c24xx_nand_controller {
/* register addresses */
uint32_t cmd;
uint32_t addr;
int s3c2440_write_block_data(struct nand_device *nand,
uint8_t *data, int data_size);
-#endif // S3C24xx_NAND_H
+#endif /* S3C24xx_NAND_H */
*/
#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)
}
struct nand_flash_controller s3c6400_nand_controller = {
- .name = "s3c6400",
- .nand_device_command = &s3c6400_nand_device_command,
- .init = &s3c6400_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c24xx_write_data,
- .read_data = &s3c24xx_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .write_block_data = &s3c2440_write_block_data,
- .read_block_data = &s3c2440_read_block_data,
- .nand_ready = &s3c2440_nand_ready,
- };
+ .name = "s3c6400",
+ .nand_device_command = &s3c6400_nand_device_command,
+ .init = &s3c6400_init,
+ .reset = &s3c24xx_reset,
+ .command = &s3c24xx_command,
+ .address = &s3c24xx_address,
+ .write_data = &s3c24xx_write_data,
+ .read_data = &s3c24xx_read_data,
+ .write_page = s3c24xx_write_page,
+ .read_page = s3c24xx_read_page,
+ .write_block_data = &s3c2440_write_block_data,
+ .read_block_data = &s3c2440_read_block_data,
+ .nand_ready = &s3c2440_nand_ready,
+};
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "fileio.h"
#include <target/target.h>
-// to be removed
+/* to be removed */
extern struct nand_device *nand_devices;
COMMAND_HANDLER(handle_nand_list_command)
struct nand_device *p;
int i;
- if (!nand_devices)
- {
+ if (!nand_devices) {
command_print(CMD_CTX, "no NAND flash devices configured");
return ERROR_OK;
}
- for (p = nand_devices, i = 0; p; p = p->next, i++)
- {
+ for (p = nand_devices, i = 0; p; p = p->next, i++) {
if (p->device)
command_print(CMD_CTX, "#%i: %s (%s) "
"pagesize: %i, buswidth: %i,\n\t"
int last = -1;
switch (CMD_ARGC) {
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- case 1:
- first = 0;
- last = INT32_MAX;
- break;
- case 2:
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
- first = last = i;
- i = 0;
- break;
- case 3:
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
- break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ case 1:
+ first = 0;
+ last = INT32_MAX;
+ break;
+ case 2:
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
+ first = last = i;
+ i = 0;
+ break;
+ case 3:
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
+ break;
}
struct nand_device *p;
if (ERROR_OK != retval)
return retval;
- if (NULL == p->device)
- {
+ if (NULL == p->device) {
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
return ERROR_OK;
}
if (last >= p->num_blocks)
last = p->num_blocks - 1;
- command_print(CMD_CTX, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
- i++, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size);
+ command_print(CMD_CTX,
+ "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
+ i++,
+ p->device->name,
+ p->manufacturer->name,
+ p->page_size,
+ p->bus_width,
+ p->erase_size);
- for (j = first; j <= last; j++)
- {
+ for (j = first; j <= last; j++) {
char *erase_state, *bad_state;
if (p->blocks[j].is_erased == 0)
bad_state = " (block condition unknown)";
command_print(CMD_CTX,
- "\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s",
- j,
- p->blocks[j].offset,
- p->blocks[j].size / 1024,
- erase_state,
- bad_state);
+ "\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s",
+ j,
+ p->blocks[j].offset,
+ p->blocks[j].size / 1024,
+ erase_state,
+ bad_state);
}
return ERROR_OK;
COMMAND_HANDLER(handle_nand_probe_command)
{
if (CMD_ARGC != 1)
- {
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct nand_device *p;
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
if (ERROR_OK != retval)
return retval;
- if ((retval = nand_probe(p)) == ERROR_OK)
- {
+ retval = nand_probe(p);
+ if (retval == ERROR_OK) {
command_print(CMD_CTX, "NAND flash device '%s (%s)' found",
- p->device->name, p->manufacturer->name);
+ p->device->name, p->manufacturer->name);
}
return retval;
COMMAND_HANDLER(handle_nand_erase_command)
{
if (CMD_ARGC != 1 && CMD_ARGC != 3)
- {
return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
struct nand_device *p;
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
if (ERROR_OK != retval)
COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
if ((length == 0) || (length % p->erase_size) != 0
- || (length + offset) > size)
+ || (length + offset) > size)
return ERROR_COMMAND_SYNTAX_ERROR;
offset /= p->erase_size;
}
retval = nand_erase(p, offset, offset + length - 1);
- if (retval == ERROR_OK)
- {
+ if (retval == ERROR_OK) {
command_print(CMD_CTX, "erased blocks %lu to %lu "
- "on NAND flash device #%s '%s'",
- offset, offset + length - 1,
- CMD_ARGV[0], p->device->name);
+ "on NAND flash device #%s '%s'",
+ offset, offset + length - 1,
+ CMD_ARGV[0], p->device->name);
}
return retval;
int last = -1;
if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2))
- {
return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
struct nand_device *p;
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
if (ERROR_OK != retval)
return retval;
- if (CMD_ARGC == 3)
- {
+ if (CMD_ARGC == 3) {
unsigned long offset;
unsigned long length;
}
retval = nand_build_bbt(p, first, last);
- if (retval == ERROR_OK)
- {
+ if (retval == ERROR_OK) {
command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
- "use \"nand info\" command to list blocks");
+ "use \"nand info\" command to list blocks");
}
return retval;
return retval;
uint32_t total_bytes = s.size;
- while (s.size > 0)
- {
+ while (s.size > 0) {
int bytes_read = nand_fileio_read(nand, &s);
- if (bytes_read <= 0)
- {
+ if (bytes_read <= 0) {
command_print(CMD_CTX, "error while reading file");
return nand_fileio_cleanup(&s);
}
retval = nand_write_page(nand, s.address / nand->page_size,
s.page, s.page_size, s.oob, s.oob_size);
- if (ERROR_OK != retval)
- {
+ if (ERROR_OK != retval) {
command_print(CMD_CTX, "failed writing file %s "
"to NAND flash %s at offset 0x%8.8" PRIx32,
CMD_ARGV[1], CMD_ARGV[0], s.address);
s.address += s.page_size;
}
- if (nand_fileio_finish(&s))
- {
+ if (nand_fileio_finish(&s)) {
command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
- "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
- CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
- duration_kbps(&s.bench, total_bytes));
+ "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
+ CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
+ duration_kbps(&s.bench, total_bytes));
}
return ERROR_OK;
}
if (ERROR_OK != retval)
return retval;
- while (file.size > 0)
- {
+ while (file.size > 0) {
retval = nand_read_page(nand, dev.address / dev.page_size,
dev.page, dev.page_size, dev.oob, dev.oob_size);
- if (ERROR_OK != retval)
- {
+ if (ERROR_OK != retval) {
command_print(CMD_CTX, "reading NAND flash page failed");
nand_fileio_cleanup(&dev);
nand_fileio_cleanup(&file);
}
int bytes_read = nand_fileio_read(nand, &file);
- if (bytes_read <= 0)
- {
+ if (bytes_read <= 0) {
command_print(CMD_CTX, "error while reading file");
nand_fileio_cleanup(&dev);
nand_fileio_cleanup(&file);
}
if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
- (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size)) )
- {
+ (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size))) {
command_print(CMD_CTX, "NAND flash contents differ "
- "at 0x%8.8" PRIx32, dev.address);
+ "at 0x%8.8" PRIx32, dev.address);
nand_fileio_cleanup(&dev);
nand_fileio_cleanup(&file);
return ERROR_FAIL;
dev.address += nand->page_size;
}
- if (nand_fileio_finish(&file) == ERROR_OK)
- {
+ if (nand_fileio_finish(&file) == ERROR_OK) {
command_print(CMD_CTX, "verified file %s in NAND flash %s "
- "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
- CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
- duration_kbps(&file.bench, dev.size));
+ "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
+ CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
+ duration_kbps(&file.bench, dev.size));
}
return nand_fileio_cleanup(&dev);
if (ERROR_OK != retval)
return retval;
- while (s.size > 0)
- {
+ while (s.size > 0) {
size_t size_written;
retval = nand_read_page(nand, s.address / nand->page_size,
s.page, s.page_size, s.oob, s.oob_size);
- if (ERROR_OK != retval)
- {
+ if (ERROR_OK != retval) {
command_print(CMD_CTX, "reading NAND flash page failed");
nand_fileio_cleanup(&s);
return retval;
if (retval != ERROR_OK)
return retval;
- if (nand_fileio_finish(&s) == ERROR_OK)
- {
+ if (nand_fileio_finish(&s) == ERROR_OK) {
command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)",
- (long)filesize, duration_elapsed(&s.bench),
- duration_kbps(&s.bench, filesize));
+ (long)filesize, duration_elapsed(&s.bench),
+ duration_kbps(&s.bench, filesize));
}
return ERROR_OK;
}
COMMAND_HANDLER(handle_nand_raw_access_command)
{
if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
- {
return ERROR_COMMAND_SYNTAX_ERROR;
- }
struct nand_device *p;
int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
if (ERROR_OK != retval)
return retval;
- if (NULL == p->device)
- {
+ if (NULL == p->device) {
command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
return ERROR_OK;
}
if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
- static bool nand_initialized = false;
- if (nand_initialized)
- {
+ static bool nand_initialized;
+ if (nand_initialized) {
LOG_INFO("'nand init' has already been called");
return ERROR_OK;
}
}
static COMMAND_HELPER(create_nand_device, const char *bank_name,
- struct nand_flash_controller *controller)
+ struct nand_flash_controller *controller)
{
struct nand_device *c;
struct target *target;
int retval;
if (CMD_ARGC < 2)
- {
return ERROR_COMMAND_SYNTAX_ERROR;
- }
target = get_target(CMD_ARGV[1]);
if (!target) {
LOG_ERROR("invalid target %s", CMD_ARGV[1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
- if (NULL != controller->commands)
- {
+ if (NULL != controller->commands) {
retval = register_commands(CMD_CTX, NULL,
controller->commands);
if (ERROR_OK != retval)
return retval;
}
c = malloc(sizeof(struct nand_device));
- if (c == NULL)
- {
+ if (c == NULL) {
LOG_ERROR("End of memory");
return ERROR_FAIL;
}
c->next = NULL;
retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
- if (ERROR_OK != retval)
- {
+ if (ERROR_OK != retval) {
LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
controller->name,
controller->usage);
COMMAND_HANDLER(handle_nand_device_command)
{
if (CMD_ARGC < 2)
- {
return ERROR_COMMAND_SYNTAX_ERROR;
- }
- // save name and increment (for compatibility) with drivers
+ /* save name and increment (for compatibility) with drivers */
const char *bank_name = *CMD_ARGV++;
CMD_ARGC--;
const char *driver_name = CMD_ARGV[0];
struct nand_flash_controller *controller;
controller = nand_driver_find_by_name(CMD_ARGV[0]);
- if (NULL == controller)
- {
+ if (NULL == controller) {
LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
}
},
COMMAND_REGISTRATION_DONE
};
+
static const struct command_registration nand_command_handlers[] = {
{
.name = "nand",
{
return register_commands(cmd_ctx, NULL, nand_command_handlers);
}
-
-