[U-Boot] [PATCH 00/13] mxc nand: Add support for i.MX5

Hi all,
This series aims at adding support for i.MX5 to the mxc nand mtd and spl drivers. It also fixes several issues and cleans up the code a little bit.
Best regards, Benoît

This patches fixes the TODO to use same register definitions in mtd mxc_nand and nand_spl fsl nfc drivers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../drivers/mtd/nand/mxc_nand.c | 247 ++++---------------- .../include/fsl_nfc.h | 97 ++++---- .../nand_spl/nand_boot_fsl_nfc.c | 58 ++--- 3 files changed, 128 insertions(+), 274 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index 936186f..9a9260c 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -25,168 +25,23 @@ #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) #include <asm/arch/imx-regs.h> #endif +#include <fsl_nfc.h>
#define DRIVER_NAME "mxc_nand"
-/* - * TODO: Use same register defs here as nand_spl mxc nand driver. - */ -/* - * Register map and bit definitions for the Freescale NAND Flash Controller - * present in various i.MX devices. - * - * MX31 and MX27 have version 1 which has - * 4 512 byte main buffers and - * 4 16 byte spare buffers - * to support up to 2K byte pagesize nand. - * Reading or writing a 2K page requires 4 FDI/FDO cycles. - * - * MX25 has version 1.1 which has - * 8 512 byte main buffers and - * 8 64 byte spare buffers - * to support up to 4K byte pagesize nand. - * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. - * Also some of registers are moved and/or changed meaning as seen below. - */ -#if defined(CONFIG_MX31) || defined(CONFIG_MX27) -#define MXC_NFC_V1 -#elif defined(CONFIG_MX25) || defined(CONFIG_MX35) -#define MXC_NFC_V1_1 -#else -#warning "MXC NFC version not defined" -#endif - -#if defined(MXC_NFC_V1) -#define NAND_MXC_NR_BUFS 4 -#define NAND_MXC_SPARE_BUF_SIZE 16 -#define NAND_MXC_REG_OFFSET 0xe00 -#define is_mxc_nfc_11() 0 -#elif defined(MXC_NFC_V1_1) -#define NAND_MXC_NR_BUFS 8 -#define NAND_MXC_SPARE_BUF_SIZE 64 -#define NAND_MXC_REG_OFFSET 0x1e00 -#define is_mxc_nfc_11() 1 -#else -#error "define CONFIG_NAND_MXC_VXXX to use mtd mxc nand driver" -#endif -struct nfc_regs { - uint8_t main_area[NAND_MXC_NR_BUFS][0x200]; - uint8_t spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE]; - /* - * reserved size is offset of nfc registers - * minus total main and spare sizes - */ - uint8_t reserved1[NAND_MXC_REG_OFFSET - - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)]; -#if defined(MXC_NFC_V1) - uint16_t nfc_buf_size; - uint16_t reserved2; - uint16_t nfc_buf_addr; - uint16_t nfc_flash_addr; - uint16_t nfc_flash_cmd; - uint16_t nfc_config; - uint16_t nfc_ecc_status_result; - uint16_t nfc_rsltmain_area; - uint16_t nfc_rsltspare_area; - uint16_t nfc_wrprot; - uint16_t nfc_unlockstart_blkaddr; - uint16_t nfc_unlockend_blkaddr; - uint16_t nfc_nf_wrprst; - uint16_t nfc_config1; - uint16_t nfc_config2; -#elif defined(MXC_NFC_V1_1) - uint16_t reserved2[2]; - uint16_t nfc_buf_addr; - uint16_t nfc_flash_addr; - uint16_t nfc_flash_cmd; - uint16_t nfc_config; - uint16_t nfc_ecc_status_result; - uint16_t nfc_ecc_status_result2; - uint16_t nfc_spare_area_size; - uint16_t nfc_wrprot; - uint16_t reserved3[2]; - uint16_t nfc_nf_wrprst; - uint16_t nfc_config1; - uint16_t nfc_config2; - uint16_t reserved4; - uint16_t nfc_unlockstart_blkaddr; - uint16_t nfc_unlockend_blkaddr; - uint16_t nfc_unlockstart_blkaddr1; - uint16_t nfc_unlockend_blkaddr1; - uint16_t nfc_unlockstart_blkaddr2; - uint16_t nfc_unlockend_blkaddr2; - uint16_t nfc_unlockstart_blkaddr3; - uint16_t nfc_unlockend_blkaddr3; -#endif -}; - -/* - * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register - * for Command operation - */ -#define NFC_CMD 0x1 - -/* - * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register - * for Address operation - */ -#define NFC_ADDR 0x2 - -/* - * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register - * for Input operation - */ -#define NFC_INPUT 0x4 - -/* - * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register - * for Data Output operation - */ -#define NFC_OUTPUT 0x8 - -/* - * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register - * for Read ID operation - */ -#define NFC_ID 0x10 - -/* - * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register - * for Read Status operation - */ -#define NFC_STATUS 0x20 - -/* - * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read - * Status operation - */ -#define NFC_INT 0x8000 - -#ifdef MXC_NFC_V1_1 -#define NFC_4_8N_ECC (1 << 0) -#else -#define NFC_4_8N_ECC 0 -#endif -#define NFC_SP_EN (1 << 2) -#define NFC_ECC_EN (1 << 3) -#define NFC_BIG (1 << 5) -#define NFC_RST (1 << 6) -#define NFC_CE (1 << 7) -#define NFC_ONE_CYCLE (1 << 8) - typedef enum {false, true} bool;
struct mxc_nand_host { - struct mtd_info mtd; - struct nand_chip *nand; - - struct nfc_regs __iomem *regs; - int spare_only; - int status_request; - int pagesize_2k; - int clk_act; - uint16_t col_addr; - unsigned int page_addr; + struct mtd_info mtd; + struct nand_chip *nand; + + struct fsl_nfc_regs __iomem *regs; + int spare_only; + int status_request; + int pagesize_2k; + int clk_act; + uint16_t col_addr; + unsigned int page_addr; };
static struct mxc_nand_host mxc_host; @@ -304,10 +159,10 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint32_t tmp;
while (max_retries-- > 0) { - if (readw(&host->regs->nfc_config2) & NFC_INT) { - tmp = readw(&host->regs->nfc_config2); + if (readw(&host->regs->config2) & NFC_INT) { + tmp = readw(&host->regs->config2); tmp &= ~NFC_INT; - writew(tmp, &host->regs->nfc_config2); + writew(tmp, &host->regs->config2); break; } udelay(1); @@ -326,8 +181,8 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
- writew(cmd, &host->regs->nfc_flash_cmd); - writew(NFC_CMD, &host->regs->nfc_config2); + writew(cmd, &host->regs->flash_cmd); + writew(NFC_CMD, &host->regs->config2);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, cmd); @@ -342,8 +197,8 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
- writew(addr, &host->regs->nfc_flash_addr); - writew(NFC_ADDR, &host->regs->nfc_config2); + writew(addr, &host->regs->flash_addr); + writew(NFC_ADDR, &host->regs->config2);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, addr); @@ -375,19 +230,19 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, } }
- writew(buf_id, &host->regs->nfc_buf_addr); + writew(buf_id, &host->regs->buf_addr);
/* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint16_t config1 = readw(&host->regs->nfc_config1); + uint16_t config1 = readw(&host->regs->config1); if (spare_only) config1 |= NFC_SP_EN; else config1 &= ~(NFC_SP_EN); - writew(config1, &host->regs->nfc_config1); + writew(config1, &host->regs->config1); }
- writew(NFC_INPUT, &host->regs->nfc_config2); + writew(NFC_INPUT, &host->regs->config2);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); @@ -402,19 +257,19 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
- writew(buf_id, &host->regs->nfc_buf_addr); + writew(buf_id, &host->regs->buf_addr);
/* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint32_t config1 = readw(&host->regs->nfc_config1); + uint32_t config1 = readw(&host->regs->config1); if (spare_only) config1 |= NFC_SP_EN; else config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->nfc_config1); + writew(config1, &host->regs->config1); }
- writew(NFC_OUTPUT, &host->regs->nfc_config2); + writew(NFC_OUTPUT, &host->regs->config2);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); @@ -442,14 +297,14 @@ static void send_read_id(struct mxc_nand_host *host) uint16_t tmp;
/* NANDFC buffer 0 is used for device ID output */ - writew(0x0, &host->regs->nfc_buf_addr); + writew(0x0, &host->regs->buf_addr);
/* Read ID into main buffer */ - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1);
- writew(NFC_ID, &host->regs->nfc_config2); + writew(NFC_ID, &host->regs->config2);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); @@ -469,14 +324,14 @@ static uint16_t get_dev_status(struct mxc_nand_host *host) /* store the main area1 first word, later do recovery */ store = readl(main_buf); /* NANDFC buffer 1 is used for device status */ - writew(1, &host->regs->nfc_buf_addr); + writew(1, &host->regs->buf_addr);
/* Read status into main buffer */ - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1);
- writew(NFC_STATUS, &host->regs->nfc_config2); + writew(NFC_STATUS, &host->regs->config2);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); @@ -515,13 +370,13 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t tmp = readw(&host->regs->nfc_config1); + uint16_t tmp = readw(&host->regs->config1);
if (on) tmp |= NFC_ECC_EN; else tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); }
static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, @@ -799,7 +654,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result); + uint16_t ecc_status = readw(&host->regs->ecc_status_result); int subpages = mtd->writesize / nand_chip->subpagesize; int pg2blk_shift = nand_chip->phys_erase_shift - nand_chip->page_shift; @@ -845,7 +700,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, * additional correction. 2-Bit errors cannot be corrected by * HW ECC, so we need to return failure */ - uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result); + uint16_t ecc_status = readw(&host->regs->ecc_status_result);
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { MTDDEBUG(MTD_DEBUG_LEVEL0, @@ -1289,14 +1144,14 @@ static void mxc_setup_config1(void) { uint16_t tmp;
- tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp |= NFC_ONE_CYCLE; tmp |= NFC_4_8N_ECC; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); if (host->pagesize_2k) - writew(64/2, &host->regs->nfc_spare_area_size); + writew(64/2, &host->regs->spare_area_size); else - writew(16/2, &host->regs->nfc_spare_area_size); + writew(16/2, &host->regs->spare_area_size); } #else #define mxc_setup_config1() @@ -1359,7 +1214,7 @@ int board_nand_init(struct nand_chip *this) this->read_buf = mxc_nand_read_buf; this->verify_buf = mxc_nand_verify_buf;
- host->regs = (struct nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; + host->regs = (struct fsl_nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; host->clk_act = 1;
#ifdef CONFIG_MXC_NAND_HWECC @@ -1383,15 +1238,15 @@ int board_nand_init(struct nand_chip *this) host->pagesize_2k = 0;
this->ecc.size = 512; - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp |= NFC_ECC_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); #else this->ecc.layout = &nand_soft_eccoob; this->ecc.mode = NAND_ECC_SOFT; - tmp = readw(&host->regs->nfc_config1); + tmp = readw(&host->regs->config1); tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->nfc_config1); + writew(tmp, &host->regs->config1); #endif /* Reset NAND */ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); @@ -1400,10 +1255,10 @@ int board_nand_init(struct nand_chip *this) * preset operation * Unlock the internal RAM Buffer */ - writew(0x2, &host->regs->nfc_config); + writew(0x2, &host->regs->config);
/* Blocks to be unlocked */ - writew(0x0, &host->regs->nfc_unlockstart_blkaddr); + writew(0x0, &host->regs->unlockstart_blkaddr); /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the * unlockend_blkaddr, but the magic 0x4000 does not always work * when writing more than some 32 megabytes (on 2k page nands) @@ -1415,10 +1270,10 @@ int board_nand_init(struct nand_chip *this) * This might be NAND chip specific and the i.MX31 datasheet is * extremely vague about the semantics of this register. */ - writew(0xFFFF, &host->regs->nfc_unlockend_blkaddr); + writew(0xFFFF, &host->regs->unlockend_blkaddr);
/* Unlock Block Command for given address range */ - writew(0x4, &host->regs->nfc_wrprot); + writew(0x4, &host->regs->wrprot);
/* NAND bus width determines access functions used by upper layer */ if (is_16bit_nand()) diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index 279aaa5..6691e41 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -24,28 +24,25 @@ #define __FSL_NFC_H
/* - * TODO: Use same register defs for nand_spl mxc nand driver - * and mtd mxc nand driver. + * Register map and bit definitions for the Freescale NAND Flash Controller + * present in various i.MX devices. * - * Register map and bit definitions for the Freescale NAND Flash - * Controller present in various i.MX devices. + * MX31 and MX27 have version 1, which has: + * 4 512-byte main buffers and + * 4 16-byte spare buffers + * to support up to 2K byte pagesize nand. + * Reading or writing a 2K page requires 4 FDI/FDO cycles. * - * MX31 and MX27 have version 1 which has - * 4 512 byte main buffers and - * 4 16 byte spare buffers - * to support up to 2K byte pagesize nand. - * Reading or writing a 2K page requires 4 FDI/FDO cycles. - * - * MX25 has version 1.1 which has - * 8 512 byte main buffers and - * 8 64 byte spare buffers - * to support up to 4K byte pagesize nand. - * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. - * Also some of registers are moved and/or changed meaning as seen below. + * MX25 and MX35 have version 1.1, which has: + * 8 512-byte main buffers and + * 8 64-byte spare buffers + * to support up to 4K byte pagesize nand. + * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. + * Also some of registers are moved and/or changed meaning as seen below. */ -#if defined(CONFIG_MX31) || defined(CONFIG_MX27) +#if defined(CONFIG_MX27) || defined(CONFIG_MX31) #define MXC_NFC_V1 -#elif defined(CONFIG_MX25) +#elif defined(CONFIG_MX25) || defined(CONFIG_MX35) #define MXC_NFC_V1_1 #else #warning "MXC NFC version not defined" @@ -55,18 +52,20 @@ #define NAND_MXC_NR_BUFS 4 #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 -#define NAND_MXC_2K_MULTI_CYCLE 1 +#define NAND_MXC_2K_MULTI_CYCLE +#define is_mxc_nfc_11() 0 #elif defined(MXC_NFC_V1_1) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 +#define is_mxc_nfc_11() 1 #else -#error "define CONFIG_NAND_MXC_VXXX to use the mxc spl_nand driver" +#error "define CONFIG_NAND_MXC_VXXX to use the mxc nand driver" #endif
struct fsl_nfc_regs { - u32 main_area[NAND_MXC_NR_BUFS][512/4]; - u32 spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE/4]; + u8 main_area[NAND_MXC_NR_BUFS][0x200]; + u8 spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE]; /* * reserved size is offset of nfc registers * minus total main and spare sizes @@ -74,44 +73,44 @@ struct fsl_nfc_regs { u8 reserved1[NAND_MXC_REG_OFFSET - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)]; #if defined(MXC_NFC_V1) - u16 bufsiz; + u16 buf_size; u16 reserved2; - u16 buffer_address; - u16 flash_add; + u16 buf_addr; + u16 flash_addr; u16 flash_cmd; - u16 configuration; + u16 config; u16 ecc_status_result; - u16 ecc_rslt_main_area; - u16 ecc_rslt_spare_area; - u16 nf_wr_prot; - u16 unlock_start_blk_add; - u16 unlock_end_blk_add; - u16 nand_flash_wr_pr_st; - u16 nand_flash_config1; - u16 nand_flash_config2; + u16 rsltmain_area; + u16 rsltspare_area; + u16 wrprot; + u16 unlockstart_blkaddr; + u16 unlockend_blkaddr; + u16 nf_wrprst; + u16 config1; + u16 config2; #elif defined(MXC_NFC_V1_1) u16 reserved2[2]; - u16 buffer_address; - u16 flash_add; + u16 buf_addr; + u16 flash_addr; u16 flash_cmd; - u16 configuration; + u16 config; u16 ecc_status_result; u16 ecc_status_result2; u16 spare_area_size; - u16 nf_wr_prot; + u16 wrprot; u16 reserved3[2]; - u16 nand_flash_wr_pr_st; - u16 nand_flash_config1; - u16 nand_flash_config2; + u16 nf_wrprst; + u16 config1; + u16 config2; u16 reserved4; - u16 unlock_start_blk_add0; - u16 unlock_end_blk_add0; - u16 unlock_start_blk_add1; - u16 unlock_end_blk_add1; - u16 unlock_start_blk_add2; - u16 unlock_end_blk_add2; - u16 unlock_start_blk_add3; - u16 unlock_end_blk_add3; + u16 unlockstart_blkaddr; + u16 unlockend_blkaddr; + u16 unlockstart_blkaddr1; + u16 unlockend_blkaddr1; + u16 unlockstart_blkaddr2; + u16 unlockend_blkaddr2; + u16 unlockstart_blkaddr3; + u16 unlockend_blkaddr3; #endif };
diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index d6b0d9b..f437deb 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -36,13 +36,13 @@ static void nfc_wait_ready(void) { uint32_t tmp;
- while (!(readw(&nfc->nand_flash_config2) & NFC_INT)) + while (!(readw(&nfc->config2) & NFC_INT)) ;
/* Reset interrupt flag */ - tmp = readw(&nfc->nand_flash_config2); + tmp = readw(&nfc->config2); tmp &= ~NFC_INT; - writew(tmp, &nfc->nand_flash_config2); + writew(tmp, &nfc->config2); }
void nfc_nand_init(void) @@ -54,10 +54,10 @@ void nfc_nand_init(void) writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size);
/* unlocking RAM Buff */ - writew(0x2, &nfc->configuration); + writew(0x2, &nfc->config);
/* hardware ECC checking and correct */ - config1 = readw(&nfc->nand_flash_config1) | NFC_ECC_EN | 0x800; + config1 = readw(&nfc->config1) | NFC_ECC_EN | 0x800; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 @@ -66,20 +66,20 @@ void nfc_nand_init(void) config1 &= ~NFC_4_8N_ECC; else config1 |= NFC_4_8N_ECC; - writew(config1, &nfc->nand_flash_config1); + writew(config1, &nfc->config1); #elif defined(MXC_NFC_V1) /* unlocking RAM Buff */ - writew(0x2, &nfc->configuration); + writew(0x2, &nfc->config);
/* hardware ECC checking and correct */ - writew(NFC_ECC_EN, &nfc->nand_flash_config1); + writew(NFC_ECC_EN, &nfc->config1); #endif }
static void nfc_nand_command(unsigned short command) { writew(command, &nfc->flash_cmd); - writew(NFC_CMD, &nfc->nand_flash_config2); + writew(NFC_CMD, &nfc->config2); nfc_wait_ready(); }
@@ -87,14 +87,14 @@ static void nfc_nand_page_address(unsigned int page_address) { unsigned int page_count;
- writew(0x00, &nfc->flash_add); - writew(NFC_ADDR, &nfc->nand_flash_config2); + writew(0x00, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); nfc_wait_ready();
/* code only for large page flash */ if (CONFIG_SYS_NAND_PAGE_SIZE > 512) { - writew(0x00, &nfc->flash_add); - writew(NFC_ADDR, &nfc->nand_flash_config2); + writew(0x00, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); nfc_wait_ready(); }
@@ -103,30 +103,30 @@ static void nfc_nand_page_address(unsigned int page_address) if (page_address <= page_count) { page_count--; /* transform 0x01000000 to 0x00ffffff */ do { - writew(page_address & 0xff, &nfc->flash_add); - writew(NFC_ADDR, &nfc->nand_flash_config2); + writew(page_address & 0xff, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); nfc_wait_ready(); page_address = page_address >> 8; page_count = page_count >> 8; } while (page_count); }
- writew(0x00, &nfc->flash_add); - writew(NFC_ADDR, &nfc->nand_flash_config2); + writew(0x00, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); nfc_wait_ready(); }
static void nfc_nand_data_output(void) { - int config1 = readw(&nfc->nand_flash_config1); + int config1 = readw(&nfc->config1); #ifdef NAND_MXC_2K_MULTI_CYCLE int i; #endif
config1 |= NFC_ECC_EN | NFC_INT_MSK; - writew(config1, &nfc->nand_flash_config1); - writew(0, &nfc->buffer_address); - writew(NFC_OUTPUT, &nfc->nand_flash_config2); + writew(config1, &nfc->config1); + writew(0, &nfc->buf_addr); + writew(NFC_OUTPUT, &nfc->config2); nfc_wait_ready(); #ifdef NAND_MXC_2K_MULTI_CYCLE /* @@ -134,11 +134,11 @@ static void nfc_nand_data_output(void) * for pages larger than 512 bytes. */ for (i = 1; i < (CONFIG_SYS_NAND_PAGE_SIZE / 512); i++) { - config1 = readw(&nfc->nand_flash_config1); + config1 = readw(&nfc->config1); config1 |= NFC_ECC_EN | NFC_INT_MSK; - writew(config1, &nfc->nand_flash_config1); - writew(i, &nfc->buffer_address); - writew(NFC_OUTPUT, &nfc->nand_flash_config2); + writew(config1, &nfc->config1); + writew(i, &nfc->buf_addr); + writew(NFC_OUTPUT, &nfc->config2); nfc_wait_ready(); } #endif @@ -155,7 +155,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) u32 *src; u32 *dst;
- writew(0, &nfc->buffer_address); /* read in first 0 buffer */ + writew(0, &nfc->buf_addr); /* read in first 0 buffer */ nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page_address);
@@ -167,7 +167,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) if (nfc_nand_check_ecc()) return -1;
- src = &nfc->main_area[0][0]; + src = (u32 *)&nfc->main_area[0][0]; dst = (u32 *)buf;
/* main copy loop from NAND-buffer to SDRAM memory */ @@ -188,7 +188,7 @@ static int is_badblock(int pagenumber)
/* Check the first two pages for bad block markers */ for (page = pagenumber; page < pagenumber + 2; page++) { - writew(0, &nfc->buffer_address); /* read in first 0 buffer */ + writew(0, &nfc->buf_addr); /* read in first 0 buffer */ nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page);
@@ -197,7 +197,7 @@ static int is_badblock(int pagenumber)
nfc_nand_data_output(); /* fill the main buffer 0 */
- src = &nfc->spare_area[0][0]; + src = (u32 *)&nfc->spare_area[0][0];
/* * IMPORTANT NOTE: The nand flash controller uses a non-

On 13/08/2012 22:48, Benoît Thébaudeau wrote:
This patches fixes the TODO to use same register definitions in mtd mxc_nand and nand_spl fsl nfc drivers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Hi Benoît,
before going deeper in the review there is a general issue.
nand_spl was used in the past and it was the first implementation to have a first loader able to copy u-boot into RAM when the SOC boots from NAND. It is replaced by the general SPL framework. All new implementations must use the new SPL framework, What you see under nand_spl is referred to already supported boards.
With general SPL, we do not have two drivers for NAND, and we are able to boot from other devices, too. So it makes no sense to try to uniform the driver under nand_spl with the main driver, we want to use only the main driver.
Best regards, Stefano Babic

Hi Stefano,
On 13/08/2012 22:48, Benoît Thébaudeau wrote:
This patches fixes the TODO to use same register definitions in mtd mxc_nand and nand_spl fsl nfc drivers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Hi Benoît,
before going deeper in the review there is a general issue.
nand_spl was used in the past and it was the first implementation to have a first loader able to copy u-boot into RAM when the SOC boots from NAND. It is replaced by the general SPL framework. All new implementations must use the new SPL framework, What you see under nand_spl is referred to already supported boards.
With general SPL, we do not have two drivers for NAND, and we are able to boot from other devices, too. So it makes no sense to try to uniform the driver under nand_spl with the main driver, we want to use only the main driver.
Then, I don't know what to do with these patches.
Note that this is not a new implementation, but only an enhancement of the existing one. But I understand your point.
I don't see any i.MX board using the general SPL for NAND. So we can't say that it's usable with the current mtd mxc_nand driver in its current state. Moreover, with the general SPL, I'd be very concerned as to the code size of mxc_nand (the target size of the whole SPL code is only 2 kiB for current i.MX users of nand_spl).
IMHO, we could improve and fix the nand_spl code while it's still there and used. This does not prevent from moving to the general SPL once ready for mxc_nand. These are two different topics.
Best regards, Benoît

On 14/08/2012 12:15, Benoît Thébaudeau wrote:
Then, I don't know what to do with these patches.
I see two main points in your patches. You cleanup mxc-nand code and add support for i.MX5. This is one topic, and it can go on.
Note that this is not a new implementation, but only an enhancement of the existing one. But I understand your point.
;-)
I don't see any i.MX board using the general SPL for NAND.
At least the MX28, and using nand_spl with MX28 was rejected for the same reason when it was pushed. Then it was switched to SPL.
But surely it should be better to have more examples - I am working to get a MX35 booting from external SD, and using the SPL.
So we can't say that it's usable with the current mtd mxc_nand driver in its current state. Moreover, with the general SPL, I'd be very concerned as to the code size of mxc_nand (the target size of the whole SPL code is only 2 kiB for current i.MX users of nand_spl).
Mainly because the restriction came from the original implementation, that was for PowerPC 4xx with only a small buffer (NFC buffer) to copy data from NAND.
We have currently only two boards supporting this mechanismus, using MX25 (karo tx25) and MX31. Both MX25 and MX31 have an internal RAM (128KB) that is is suitable for installing the SPL. Note that TI SOCs have less RAM available, and they support SPL.
IMHO the fact that only two IMX boards are using this mechanism (nand_spl) is also due the fact that is not very flexible. And moving to SPL we are not fixed to boot exclusively from NAND,
IMHO, we could improve and fix the nand_spl code while it's still there and used.
However, as you say, if the code is still available, this makes people think that is the correct way to do and we will have two distinct implementation (the old one and the new one), both to be supported.
Not to forget that the SPL is thought to work with different SOCs, even if currently it is mainly used by TI, and with different media storage. All features taht we discussed previously in the ML if we had to add them to nand_spl, before the new implementation was pushed.
This does not prevent from moving to the general SPL once ready for mxc_nand. These are two different topics.
The fact is it will be nice if also the two supported boards will move to SPL. Of couse, we cannot break these boards, but a move will be more difficult if we increase the number of boards using nand_spl.
Best regards, Stefano Babic

Hi Stefano,
On 14/08/2012 12:15, Benoît Thébaudeau wrote:
Then, I don't know what to do with these patches.
I see two main points in your patches. You cleanup mxc-nand code and add support for i.MX5. This is one topic, and it can go on.
OK, but then do you want to keep the register definitions inside mxc_nand?
Note that this is not a new implementation, but only an enhancement of the existing one. But I understand your point.
;-)
I don't see any i.MX board using the general SPL for NAND.
At least the MX28, and using nand_spl with MX28 was rejected for the same reason when it was pushed. Then it was switched to SPL.
OK. But I meant MXC. MXS does not use the same NAND driver.
But surely it should be better to have more examples - I am working to get a MX35 booting from external SD, and using the SPL.
Great! Having mxc_nand examples would be great too.
So we can't say that it's usable with the current mtd mxc_nand driver in its current state. Moreover, with the general SPL, I'd be very concerned as to the code size of mxc_nand (the target size of the whole SPL code is only 2 kiB for current i.MX users of nand_spl).
Mainly because the restriction came from the original implementation, that was for PowerPC 4xx with only a small buffer (NFC buffer) to copy data from NAND.
We have currently only two boards supporting this mechanismus, using MX25 (karo tx25) and MX31. Both MX25 and MX31 have an internal RAM (128KB) that is is suitable for installing the SPL. Note that TI SOCs have less RAM available, and they support SPL.
The available RAM size is not the issue. i.MX boards using nand_spl can use internal or external RAM. The issue comes from the i.MX ROM bootloader that only uses the NFC buffer. On i.MX31, that means max 2 kiB for SPL, and 4 kiB on i.MX25/35/51. What can be done on the latter if using internal boot (with DCD header) is to use at most one NF block (more is not possible because the i.MX bootloader goes back to serial mode if any bad block is found, and one of the 1st or 2nd block has to be good).
IMHO the fact that only two IMX boards are using this mechanism (nand_spl) is also due the fact that is not very flexible. And moving to SPL we are not fixed to boot exclusively from NAND,
Sure.
IMHO, we could improve and fix the nand_spl code while it's still there and used.
However, as you say, if the code is still available, this makes people think that is the correct way to do and we will have two distinct implementation (the old one and the new one), both to be supported.
Right.
Not to forget that the SPL is thought to work with different SOCs, even if currently it is mainly used by TI, and with different media storage. All features taht we discussed previously in the ML if we had to add them to nand_spl, before the new implementation was pushed.
OK.
This does not prevent from moving to the general SPL once ready for mxc_nand. These are two different topics.
The fact is it will be nice if also the two supported boards will move to SPL.
Sure, but I don't have time to do that.
Of couse, we cannot break these boards,
They're already broken with the current nand_spl. See my 07/13.
but a move will be more difficult if we increase the number of boards using nand_spl.
Sure, but my series does not add new boards.
Just tell me what to do. I don't have time to port nand_spl boards to general SPL. The only thing I may find time for is to refactor the series in an acceptable way for you.
Best regards, Benoît

On 14/08/2012 13:13, Benoît Thébaudeau wrote:
Hi Stefano,
Hi Benoît,
We have currently only two boards supporting this mechanismus, using MX25 (karo tx25) and MX31. Both MX25 and MX31 have an internal RAM (128KB) that is is suitable for installing the SPL. Note that TI SOCs have less RAM available, and they support SPL.
The available RAM size is not the issue. i.MX boards using nand_spl can use internal or external RAM. The issue comes from the i.MX ROM bootloader that only uses the NFC buffer. On i.MX31, that means max 2 kiB for SPL, and 4 kiB on i.MX25/35/51. What can be done on the latter if using internal boot (with DCD header) is to use at most one NF block (more is not possible because the i.MX bootloader goes back to serial mode if any bad block is found, and one of the 1st or 2nd block has to be good).
We are both a little off-topic here, but because we are reading probably the same part of the manuals I would like to clear this point.
What you are saying is not exactly what I read from the manual - I checked it now in mx35, I will take a look also on the other ones.
In 7.4.1.6 NAND Flash Boot Operation, I read:
"1. On device power-on, the boot ROM copies the first 4 Kbytes of boot code from the NAND Flash to the NFC buffer."
So this correspond to your statement - and DCD tables go into NFC buffer. DCD table must be smaller as 4KB, but this is always the case.
"2. ROM code checks the first 4 Kbytes of boot data copied in step 1 above. a) If no ECC error, then DCD is verified. – If DCD verification is successful, then the rest of the boot code image is copied to destination RAM (internal RAM or SDRAM) and secure boot is performed."
I understand this part as the mx35 goes on to copy the whole image, depending on the size set into the header, to the address specified in the table itself. There is no limitation. Exactly in the same way it works on i.MX5 (I know, this does not mean nothing, but..)
I think the limitation of 2KB or 4KB is not correct and is valid only for the DCD data. Do you agree ?
Of couse, we cannot break these boards,
They're already broken with the current nand_spl. See my 07/13.
Mmmhh...a bug is a bug, and should be fixed, I agree with you on this point.
but a move will be more difficult if we increase the number of boards using nand_spl.
Sure, but my series does not add new boards.
Right. Maybe I was expecting a new patch series from you adding a new board, because I thought you have a "use case" for i.MX5, (that means, support for NAND in i.MX5). In other words, a new board based on nand_spl will be not accepted.
But again, fixing current issues is another thing. I will go on on to review the rest of patches (I admit I skip the rest of nand_spl related patches).
Just tell me what to do. I don't have time to port nand_spl boards to general SPL. The only thing I may find time for is to refactor the series in an acceptable way for you.
You convinced me that you are fixing current issues in already supported boards - then it is fine with me to go on with this patchset.
Best regards, Stefano

Hi Stefano,
On 14/08/2012 13:13, Benoît Thébaudeau wrote:
Hi Stefano,
Hi Benoît,
We have currently only two boards supporting this mechanismus, using MX25 (karo tx25) and MX31. Both MX25 and MX31 have an internal RAM (128KB) that is is suitable for installing the SPL. Note that TI SOCs have less RAM available, and they support SPL.
The available RAM size is not the issue. i.MX boards using nand_spl can use internal or external RAM. The issue comes from the i.MX ROM bootloader that only uses the NFC buffer. On i.MX31, that means max 2 kiB for SPL, and 4 kiB on i.MX25/35/51. What can be done on the latter if using internal boot (with DCD header) is to use at most one NF block (more is not possible because the i.MX bootloader goes back to serial mode if any bad block is found, and one of the 1st or 2nd block has to be good).
We are both a little off-topic here, but because we are reading probably the same part of the manuals I would like to clear this point.
OK.
What you are saying is not exactly what I read from the manual - I checked it now in mx35, I will take a look also on the other ones.
In 7.4.1.6 NAND Flash Boot Operation, I read:
"1. On device power-on, the boot ROM copies the first 4 Kbytes of boot code from the NAND Flash to the NFC buffer."
So this correspond to your statement - and DCD tables go into NFC buffer. DCD table must be smaller as 4KB, but this is always the case.
Indeed.
"2. ROM code checks the first 4 Kbytes of boot data copied in step 1 above. a) If no ECC error, then DCD is verified. – If DCD verification is successful, then the rest of the boot code image is copied to destination RAM (internal RAM or SDRAM) and secure boot is performed."
I understand this part as the mx35 goes on to copy the whole image, depending on the size set into the header, to the address specified in the table itself. There is no limitation. Exactly in the same way it works on i.MX5 (I know, this does not mean nothing, but..)
I think the limitation of 2KB or 4KB is not correct and is valid only for the DCD data. Do you agree ?
No, it's way more complicated than that.
First, there various boot modes available depending on the device for NAND: i.MX31: external only i.MX25 and i.MX35: internal or external i.MX51: internal only
External means that the NFC buffer is filled from NAND and executed without any DCD or flash header. The limit is 2 kiB on i.MX31. On i.MX25 and i.MX35, it is not clear from the RMs if only a single NF page is read, or if the NFC buffer is fully filled (4 kiB). This is the use case for mx31pdk and tx25.
Internal means that 4 kiB are read from NF. If this fails from the 1st block, it is retried with the 2nd block. If it fails again, boot is aborted. If it succeeds, DCD and Flash headers are checked and executed. The behavior of the ROM bootloader while loading the image indicated by the headers is not clear from the RMs in case of bad blocks, so I asked FSL support which told me that as soon as a bad block is found, the boot is aborted. This means that an SPL is required for NAND boot to be reliable, even with internal boot. This also means that this SPL can not be larger than a single block.
Of couse, we cannot break these boards,
They're already broken with the current nand_spl. See my 07/13.
Mmmhh...a bug is a bug, and should be fixed, I agree with you on this point.
OK.
but a move will be more difficult if we increase the number of boards using nand_spl.
Sure, but my series does not add new boards.
Right. Maybe I was expecting a new patch series from you adding a new board, because I thought you have a "use case" for i.MX5, (that means, support for NAND in i.MX5). In other words, a new board based on nand_spl will be not accepted.
I indeed have such boards supported locally, but they are not yet ready for upstream, and I did not intend to post patches for them before the other i.MX nand_spl boards have moved to generic SPL.
But again, fixing current issues is another thing. I will go on on to review the rest of patches (I admit I skip the rest of nand_spl related patches).
OK.
Just tell me what to do. I don't have time to port nand_spl boards to general SPL. The only thing I may find time for is to refactor the series in an acceptable way for you.
You convinced me that you are fixing current issues in already supported boards - then it is fine with me to go on with this patchset.
Great.
Best regards, Benoît

Hi Stefano,
On 08/14/2012 04:29:04 PM, Benoît Thébaudeau wrote:
Hi Stefano,
On 14/08/2012 13:13, Benoît Thébaudeau wrote:
Hi Stefano,
Hi Benoît,
We have currently only two boards supporting this mechanismus, using MX25 (karo tx25) and MX31. Both MX25 and MX31 have an internal RAM (128KB) that is is suitable for installing the SPL. Note that TI SOCs have less RAM available, and they support SPL.
The available RAM size is not the issue. i.MX boards using nand_spl can use internal or external RAM. The issue comes from the i.MX ROM bootloader that only uses the NFC buffer. On i.MX31, that means max 2 kiB for SPL, and 4 kiB on i.MX25/35/51. What can be done on the latter if using internal boot (with DCD header) is to use at most one NF block (more is not possible because the i.MX bootloader goes back to serial mode if any bad block is found, and one of the 1st or 2nd block has to be good).
We are both a little off-topic here, but because we are reading probably the same part of the manuals I would like to clear this point.
OK.
What you are saying is not exactly what I read from the manual - I checked it now in mx35, I will take a look also on the other ones.
In 7.4.1.6 NAND Flash Boot Operation, I read:
"1. On device power-on, the boot ROM copies the first 4 Kbytes of boot code from the NAND Flash to the NFC buffer."
So this correspond to your statement - and DCD tables go into NFC buffer. DCD table must be smaller as 4KB, but this is always the case.
Indeed.
"2. ROM code checks the first 4 Kbytes of boot data copied in step 1 above. a) If no ECC error, then DCD is verified. – If DCD verification is successful, then the rest of the boot code image is copied to destination RAM (internal RAM or SDRAM) and secure boot is performed."
I understand this part as the mx35 goes on to copy the whole image, depending on the size set into the header, to the address specified in the table itself. There is no limitation. Exactly in the same way it works on i.MX5 (I know, this does not mean nothing, but..)
I think the limitation of 2KB or 4KB is not correct and is valid only for the DCD data. Do you agree ?
No, it's way more complicated than that.
First, there various boot modes available depending on the device for NAND: i.MX31: external only
Note that internal NAND Flash boot is also mentioned in the RM, but without further details. FSL should be contacted to know more. But the RM refers to secure boot and HAB, so it's probably something close to the internal boot modes of i.MX25 and i.MX35. Anyway, it does not seem to be used by U-Boot i.MX31 boards.
i.MX25 and i.MX35: internal or external i.MX51: internal only
External means that the NFC buffer is filled from NAND and executed without any DCD or flash header. The limit is 2 kiB on i.MX31. On i.MX25 and i.MX35, it is not clear from the RMs if only a single NF page is read, or if the NFC buffer is fully filled (4 kiB). This is the use case for mx31pdk and tx25.
The details about external NF boot are in the NFC chapter of the RMs. For i.MX31, it's perfectly clear: The whole 2-kiB NFC buffer is filled whether the NF pages are 512-B or 2-kiB. For i.MX25 and i.MX35, it's more difficult to find the details, but I interpret the RMs as meaning that the whole 4-kiB NFC buffer is filled whatever the NF page sizes. In both cases, the code is run from the NFC buffer, so that the SPL size cannot exceed 2 kiB for mx31pdk, and 4 kiB for tx25.
Internal means that 4 kiB are read from NF. If this fails from the 1st block, it is retried with the 2nd block. If it fails again, boot is aborted. If it succeeds, DCD and Flash headers are checked and executed. The behavior of the ROM bootloader while loading the image indicated by the headers is not clear from the RMs in case of bad blocks, so I asked FSL support which told me that as soon as a bad block is found, the boot is aborted. This means that an SPL is required for NAND boot to be reliable, even with internal boot. This also means that this SPL can not be larger than a single block.
Best regards, Benoît

On 15/08/2012 20:11, Benoît Thébaudeau wrote:
Hi Stefano,
Hi Benoît,
I understand this part as the mx35 goes on to copy the whole image, depending on the size set into the header, to the address specified in the table itself. There is no limitation. Exactly in the same way it works on i.MX5 (I know, this does not mean nothing, but..)
I think the limitation of 2KB or 4KB is not correct and is valid only for the DCD data. Do you agree ?
No, it's way more complicated than that.
First, there various boot modes available depending on the device for NAND: i.MX31: external only
Note that internal NAND Flash boot is also mentioned in the RM, but without further details.
I know - thanks for sharing your information.
FSL should be contacted to know more. But the RM refers to secure boot and HAB, so it's probably something close to the internal boot modes of i.MX25 and i.MX35. Anyway, it does not seem to be used by U-Boot i.MX31 boards.
I have the same feeling.
The details about external NF boot are in the NFC chapter of the RMs. For i.MX31, it's perfectly clear: The whole 2-kiB NFC buffer is filled whether the NF pages are 512-B or 2-kiB. For i.MX25 and i.MX35, it's more difficult to find the details, but I interpret the RMs as meaning that the whole 4-kiB NFC buffer is filled whatever the NF page sizes. In both cases, the code is run from the NFC buffer, so that the SPL size cannot exceed 2 kiB for mx31pdk, and 4 kiB for tx25.
I have the same interpretation - for this reason it was interesting for me to understand the behavior with internal boot, where I can set the size of the whole image in the imx header.
However, if the boot stops after a bad block is found instead of skipping it and reading the next one, it seems to me that this feature cannot be really used. It will be also interesting to know if the behavior is the same also for the newer i.MX, I mean MX5 and MX6.
Internal means that 4 kiB are read from NF. If this fails from the 1st block, it is retried with the 2nd block. If it fails again, boot is aborted. If it succeeds, DCD and Flash headers are checked and executed.
The
behavior of the ROM bootloader while loading the image indicated by the headers is not clear from the RMs in case of bad blocks, so I asked FSL support which told me that as soon as a bad block is found, the boot is aborted. This means that an SPL is required for NAND boot to be reliable, even with internal boot. This also means that this SPL can not be larger than a single block.
The other way that a project can take is to use SLC NAND (or in any case, NAND where is guaranted that the first sector cannot be bad). A hard limitation, anyway.
Best regards, Stefano

On 08/14/2012 03:37 AM, Stefano Babic wrote:
On 13/08/2012 22:48, Benoît Thébaudeau wrote:
This patches fixes the TODO to use same register definitions in mtd mxc_nand and nand_spl fsl nfc drivers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Hi Benoît,
before going deeper in the review there is a general issue.
nand_spl was used in the past and it was the first implementation to have a first loader able to copy u-boot into RAM when the SOC boots from NAND. It is replaced by the general SPL framework. All new implementations must use the new SPL framework, What you see under nand_spl is referred to already supported boards.
With general SPL, we do not have two drivers for NAND, and we are able to boot from other devices, too. So it makes no sense to try to uniform the driver under nand_spl with the main driver, we want to use only the main driver.
It is not true that new-SPL will always have one uniform NAND driver, nor is it true that nand_spl always has separate NAND drivers (it always has a separate NAND subsystem, but the basic nand_spl/nand_boot.c does use the standard device-specific driver).
It depends on space constraints of the target, and how big the standard device-specific driver is. With Wolfgang's mandate that no new boards be added to nand_spl, we're going to have to support boards with a small buffer for NAND booting in new SPL (even if it turns out this isn't one of them). It's not just 4xx; Freescale PPC chips are like this too, including some that have not yet had NAND boot support added to mainline U-Boot and thus can't use nand_spl.
-Scott

Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../drivers/mtd/nand/mxc_nand.c | 9 +++------ .../include/fsl_nfc.h | 1 + .../nand_spl/nand_boot_fsl_nfc.c | 14 +++++++------- 3 files changed, 11 insertions(+), 13 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index 9a9260c..62d8c6b 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -123,8 +123,7 @@ static int is_16bit_nand(void) #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) static int is_16bit_nand(void) { - struct ccm_regs *ccm = - (struct ccm_regs *)IMX_CCM_BASE; + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
if (readl(&ccm->rcsr) & CCM_RCSR_NF_16BIT_SEL) return 1; @@ -238,7 +237,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) config1 |= NFC_SP_EN; else - config1 &= ~(NFC_SP_EN); + config1 &= ~NFC_SP_EN; writew(config1, &host->regs->config1); }
@@ -687,7 +686,6 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, #define mxc_nand_write_page_syndrome NULL #define mxc_nand_write_page_raw_syndrome NULL #define mxc_nand_write_oob_syndrome NULL -#define mxc_nfc_11_nand_correct_data NULL
static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) @@ -1188,7 +1186,6 @@ int board_nand_init(struct nand_chip *this) { struct mtd_info *mtd; uint16_t tmp; - int err = 0;
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT this->options |= NAND_USE_FLASH_BBT; @@ -1287,5 +1284,5 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif mxc_setup_config1(); - return err; + return 0; } diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index 6691e41..1c16c71 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -166,5 +166,6 @@ struct fsl_nfc_regs { #define NFC_RST (1 << 6) #define NFC_CE (1 << 7) #define NFC_ONE_CYCLE (1 << 8) +#define NFC_FP_INT (1 << 11)
#endif /* __FSL_NFC_H */ diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index f437deb..b90f93e 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -45,10 +45,10 @@ static void nfc_wait_ready(void) writew(tmp, &nfc->config2); }
-void nfc_nand_init(void) +static void nfc_nand_init(void) { #if defined(MXC_NFC_V1_1) - int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int config1;
writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size); @@ -57,12 +57,12 @@ void nfc_nand_init(void) writew(0x2, &nfc->config);
/* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | 0x800; + config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 */ - if ((CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page) > 16) + if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) config1 &= ~NFC_4_8N_ECC; else config1 |= NFC_4_8N_ECC; @@ -133,7 +133,7 @@ static void nfc_nand_data_output(void) * This NAND controller requires multiple input commands * for pages larger than 512 bytes. */ - for (i = 1; i < (CONFIG_SYS_NAND_PAGE_SIZE / 512); i++) { + for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { config1 = readw(&nfc->config1); config1 |= NFC_ECC_EN | NFC_INT_MSK; writew(config1, &nfc->config1); @@ -171,7 +171,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) dst = (u32 *)buf;
/* main copy loop from NAND-buffer to SDRAM memory */ - for (i = 0; i < (CONFIG_SYS_NAND_PAGE_SIZE / 4); i++) { + for (i = 0; i < CONFIG_SYS_NAND_PAGE_SIZE / 4; i++) { writel(readl(src), dst); src++; dst++; @@ -230,7 +230,7 @@ static int nand_load(unsigned int from, unsigned int size, unsigned char *buf) page = from / CONFIG_SYS_NAND_PAGE_SIZE; i = 0;
- while (i < (size / CONFIG_SYS_NAND_PAGE_SIZE)) { + while (i < size / CONFIG_SYS_NAND_PAGE_SIZE) { if (nfc_read_page(page, buf) < 0) return -1;

On 13/08/2012 22:48, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
.../drivers/mtd/nand/mxc_nand.c | 9 +++------ .../include/fsl_nfc.h | 1 + .../nand_spl/nand_boot_fsl_nfc.c | 14 +++++++------- 3 files changed, 11 insertions(+), 13 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index 9a9260c..62d8c6b 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -123,8 +123,7 @@ static int is_16bit_nand(void) #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) static int is_16bit_nand(void) {
- struct ccm_regs *ccm =
(struct ccm_regs *)IMX_CCM_BASE;
struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE;
if (readl(&ccm->rcsr) & CCM_RCSR_NF_16BIT_SEL) return 1;
@@ -238,7 +237,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) config1 |= NFC_SP_EN; else
config1 &= ~(NFC_SP_EN);
writew(config1, &host->regs->config1); }config1 &= ~NFC_SP_EN;
@@ -687,7 +686,6 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, #define mxc_nand_write_page_syndrome NULL #define mxc_nand_write_page_raw_syndrome NULL #define mxc_nand_write_oob_syndrome NULL -#define mxc_nfc_11_nand_correct_data NULL
static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) @@ -1188,7 +1186,6 @@ int board_nand_init(struct nand_chip *this) { struct mtd_info *mtd; uint16_t tmp;
- int err = 0;
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT this->options |= NAND_USE_FLASH_BBT; @@ -1287,5 +1284,5 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif mxc_setup_config1();
- return err;
- return 0;
} diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index 6691e41..1c16c71 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -166,5 +166,6 @@ struct fsl_nfc_regs { #define NFC_RST (1 << 6) #define NFC_CE (1 << 7) #define NFC_ONE_CYCLE (1 << 8) +#define NFC_FP_INT (1 << 11)
#endif /* __FSL_NFC_H */ diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index f437deb..b90f93e 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -45,10 +45,10 @@ static void nfc_wait_ready(void) writew(tmp, &nfc->config2); }
-void nfc_nand_init(void) +static void nfc_nand_init(void) { #if defined(MXC_NFC_V1_1)
- int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512;
int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int config1;
writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size);
@@ -57,12 +57,12 @@ void nfc_nand_init(void) writew(0x2, &nfc->config);
/* hardware ECC checking and correct */
- config1 = readw(&nfc->config1) | NFC_ECC_EN | 0x800;
- config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_FP_INT; /*
*/
- if spare size is larger that 16 bytes per 512 byte hunk
- then use 8 symbol correction instead of 4
- if ((CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page) > 16)
- if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) config1 &= ~NFC_4_8N_ECC; else config1 |= NFC_4_8N_ECC;
@@ -133,7 +133,7 @@ static void nfc_nand_data_output(void) * This NAND controller requires multiple input commands * for pages larger than 512 bytes. */
- for (i = 1; i < (CONFIG_SYS_NAND_PAGE_SIZE / 512); i++) {
- for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { config1 = readw(&nfc->config1); config1 |= NFC_ECC_EN | NFC_INT_MSK; writew(config1, &nfc->config1);
@@ -171,7 +171,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) dst = (u32 *)buf;
/* main copy loop from NAND-buffer to SDRAM memory */
- for (i = 0; i < (CONFIG_SYS_NAND_PAGE_SIZE / 4); i++) {
- for (i = 0; i < CONFIG_SYS_NAND_PAGE_SIZE / 4; i++) { writel(readl(src), dst); src++; dst++;
@@ -230,7 +230,7 @@ static int nand_load(unsigned int from, unsigned int size, unsigned char *buf) page = from / CONFIG_SYS_NAND_PAGE_SIZE; i = 0;
- while (i < (size / CONFIG_SYS_NAND_PAGE_SIZE)) {
- while (i < size / CONFIG_SYS_NAND_PAGE_SIZE) { if (nfc_read_page(page, buf) < 0) return -1;
Aceked-by : Stefano Babic sbabic@denx.de
Best regards, Stefano Babic

Merge duplicated code into functions, which is better for SPL size too.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../nand_spl/nand_boot_fsl_nfc.c | 50 +++++++++----------- 1 file changed, 23 insertions(+), 27 deletions(-)
diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index b90f93e..b98fe41 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -83,37 +83,35 @@ static void nfc_nand_command(unsigned short command) nfc_wait_ready(); }
+static void nfc_nand_address(unsigned short address) +{ + writew(address, &nfc->flash_addr); + writew(NFC_ADDR, &nfc->config2); + nfc_wait_ready(); +} + static void nfc_nand_page_address(unsigned int page_address) { unsigned int page_count;
- writew(0x00, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); - nfc_wait_ready(); + nfc_nand_address(0x00);
/* code only for large page flash */ - if (CONFIG_SYS_NAND_PAGE_SIZE > 512) { - writew(0x00, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); - nfc_wait_ready(); - } + if (CONFIG_SYS_NAND_PAGE_SIZE > 512) + nfc_nand_address(0x00);
page_count = CONFIG_SYS_NAND_SIZE / CONFIG_SYS_NAND_PAGE_SIZE;
if (page_address <= page_count) { page_count--; /* transform 0x01000000 to 0x00ffffff */ do { - writew(page_address & 0xff, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); - nfc_wait_ready(); + nfc_nand_address(page_address & 0xff); page_address = page_address >> 8; page_count = page_count >> 8; } while (page_count); }
- writew(0x00, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); - nfc_wait_ready(); + nfc_nand_address(0x00); }
static void nfc_nand_data_output(void) @@ -149,12 +147,8 @@ static int nfc_nand_check_ecc(void) return readw(&nfc->ecc_status_result); }
-static int nfc_read_page(unsigned int page_address, unsigned char *buf) +static void nfc_nand_read_page(unsigned int page_address) { - int i; - u32 *src; - u32 *dst; - writew(0, &nfc->buf_addr); /* read in first 0 buffer */ nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page_address); @@ -163,6 +157,15 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) nfc_nand_command(NAND_CMD_READSTART);
nfc_nand_data_output(); /* fill the main buffer 0 */ +} + +static int nfc_read_page(unsigned int page_address, unsigned char *buf) +{ + int i; + u32 *src; + u32 *dst; + + nfc_nand_read_page(page_address);
if (nfc_nand_check_ecc()) return -1; @@ -188,14 +191,7 @@ static int is_badblock(int pagenumber)
/* Check the first two pages for bad block markers */ for (page = pagenumber; page < pagenumber + 2; page++) { - writew(0, &nfc->buf_addr); /* read in first 0 buffer */ - nfc_nand_command(NAND_CMD_READ0); - nfc_nand_page_address(page); - - if (CONFIG_SYS_NAND_PAGE_SIZE > 512) - nfc_nand_command(NAND_CMD_READSTART); - - nfc_nand_data_output(); /* fill the main buffer 0 */ + nfc_nand_read_page(page);
src = (u32 *)&nfc->spare_area[0][0];

On 13/08/2012 22:48, Benoît Thébaudeau wrote:
Merge duplicated code into functions, which is better for SPL size too.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Hi Benoît,
.../nand_spl/nand_boot_fsl_nfc.c | 50 +++++++++----------- 1 file changed, 23 insertions(+), 27 deletions(-)
diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index b90f93e..b98fe41 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -83,37 +83,35 @@ static void nfc_nand_command(unsigned short command) nfc_wait_ready(); }
Surely a good issue to fix if we go on using nand_spl - however, as I said in my previous e-mail, nand_spl is obsolete and we move to the SPL framework.
Best regards, Stefano Babic

The ECC_EN and INT_MSK bits of CONFIG1 are not volatile, so it is sufficient to set them once in nfc_nand_init().
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../nand_spl/nand_boot_fsl_nfc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index b98fe41..059969b 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -57,7 +57,7 @@ static void nfc_nand_init(void) writew(0x2, &nfc->config);
/* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_FP_INT; + config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | NFC_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 @@ -72,7 +72,7 @@ static void nfc_nand_init(void) writew(0x2, &nfc->config);
/* hardware ECC checking and correct */ - writew(NFC_ECC_EN, &nfc->config1); + writew(NFC_ECC_EN | NFC_INT_MSK, &nfc->config1); #endif }
@@ -116,13 +116,10 @@ static void nfc_nand_page_address(unsigned int page_address)
static void nfc_nand_data_output(void) { - int config1 = readw(&nfc->config1); #ifdef NAND_MXC_2K_MULTI_CYCLE int i; #endif
- config1 |= NFC_ECC_EN | NFC_INT_MSK; - writew(config1, &nfc->config1); writew(0, &nfc->buf_addr); writew(NFC_OUTPUT, &nfc->config2); nfc_wait_ready(); @@ -132,9 +129,6 @@ static void nfc_nand_data_output(void) * for pages larger than 512 bytes. */ for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { - config1 = readw(&nfc->config1); - config1 |= NFC_ECC_EN | NFC_INT_MSK; - writew(config1, &nfc->config1); writew(i, &nfc->buf_addr); writew(NFC_OUTPUT, &nfc->config2); nfc_wait_ready();

Set the spl mxc nand driver for IP 1.1 in symmetric mode, like the mtd driver. In this way, for both drivers, one input clock period of the NFC IP will produce one R/W cycle.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../nand_spl/nand_boot_fsl_nfc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index 059969b..842943c 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -57,7 +57,8 @@ static void nfc_nand_init(void) writew(0x2, &nfc->config);
/* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | NFC_FP_INT; + config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | + NFC_ONE_CYCLE | NFC_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4

On the NFC IP 1.1, the 32-bit ecc_status_result value comes from 2 consecutive 16-bit registers. This patch reads all the fields of this value, which makes a difference for 4-kiB NF pages.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../drivers/mtd/nand/mxc_nand.c | 2 +- .../include/fsl_nfc.h | 3 +-- .../nand_spl/nand_boot_fsl_nfc.c | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index 62d8c6b..4564b25 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -653,7 +653,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t ecc_status = readw(&host->regs->ecc_status_result); + uint32_t ecc_status = readl(&host->regs->ecc_status_result); int subpages = mtd->writesize / nand_chip->subpagesize; int pg2blk_shift = nand_chip->phys_erase_shift - nand_chip->page_shift; diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index 1c16c71..c248cef 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -94,8 +94,7 @@ struct fsl_nfc_regs { u16 flash_addr; u16 flash_cmd; u16 config; - u16 ecc_status_result; - u16 ecc_status_result2; + u32 ecc_status_result; u16 spare_area_size; u16 wrprot; u16 reserved3[2]; diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index 842943c..4c5a7fe 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -139,7 +139,11 @@ static void nfc_nand_data_output(void)
static int nfc_nand_check_ecc(void) { +#if defined(MXC_NFC_V1) return readw(&nfc->ecc_status_result); +#elif defined(MXC_NFC_V1_1) + return readl(&nfc->ecc_status_result); +#endif }
static void nfc_nand_read_page(unsigned int page_address)

On Mon, Aug 13, 2012 at 10:49:42PM +0200, Benoît Thébaudeau wrote:
On the NFC IP 1.1, the 32-bit ecc_status_result value comes from 2 consecutive 16-bit registers. This patch reads all the fields of this value, which makes a difference for 4-kiB NF pages.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
.../drivers/mtd/nand/mxc_nand.c | 2 +- .../include/fsl_nfc.h | 3 +-- .../nand_spl/nand_boot_fsl_nfc.c | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index 62d8c6b..4564b25 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -653,7 +653,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv;
- uint16_t ecc_status = readw(&host->regs->ecc_status_result);
- uint32_t ecc_status = readl(&host->regs->ecc_status_result); int subpages = mtd->writesize / nand_chip->subpagesize; int pg2blk_shift = nand_chip->phys_erase_shift - nand_chip->page_shift;
diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index 1c16c71..c248cef 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -94,8 +94,7 @@ struct fsl_nfc_regs { u16 flash_addr; u16 flash_cmd; u16 config;
- u16 ecc_status_result;
- u16 ecc_status_result2;
- u32 ecc_status_result; u16 spare_area_size; u16 wrprot; u16 reserved3[2];
diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index 842943c..4c5a7fe 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -139,7 +139,11 @@ static void nfc_nand_data_output(void)
static int nfc_nand_check_ecc(void) { +#if defined(MXC_NFC_V1) return readw(&nfc->ecc_status_result); +#elif defined(MXC_NFC_V1_1)
- return readl(&nfc->ecc_status_result);
+#endif }
On MXC_NFC_V1 you're using readw() on a u32 -- that's not OK, even if the ARM accessors let you get away with it. Use a union or #ifdef the struct definition, or just always readl() if you can get away with it, or do two readw()s on V1_1.
-Scott

On 09/17/2012 07:39:35 PM, Scott Wood wrote:
On Mon, Aug 13, 2012 at 10:49:42PM +0200, Benoît Thébaudeau wrote:
On the NFC IP 1.1, the 32-bit ecc_status_result value comes from 2 consecutive 16-bit registers. This patch reads all the fields of
this value,
which makes a difference for 4-kiB NF pages.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
.../drivers/mtd/nand/mxc_nand.c | 2 +- .../include/fsl_nfc.h | 3 +-- .../nand_spl/nand_boot_fsl_nfc.c | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c
u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c
index 62d8c6b..4564b25 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -653,7 +653,7 @@ static int mxc_nand_correct_data(struct
mtd_info *mtd, u_char *dat,
{ struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv;
- uint16_t ecc_status = readw(&host->regs->ecc_status_result);
- uint32_t ecc_status = readl(&host->regs->ecc_status_result); int subpages = mtd->writesize / nand_chip->subpagesize; int pg2blk_shift = nand_chip->phys_erase_shift - nand_chip->page_shift;
diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h
u-boot-4d3c95f/include/fsl_nfc.h
index 1c16c71..c248cef 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -94,8 +94,7 @@ struct fsl_nfc_regs { u16 flash_addr; u16 flash_cmd; u16 config;
- u16 ecc_status_result;
- u16 ecc_status_result2;
- u32 ecc_status_result; u16 spare_area_size; u16 wrprot; u16 reserved3[2];
diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c
u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c
index 842943c..4c5a7fe 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -139,7 +139,11 @@ static void nfc_nand_data_output(void)
static int nfc_nand_check_ecc(void) { +#if defined(MXC_NFC_V1) return readw(&nfc->ecc_status_result); +#elif defined(MXC_NFC_V1_1)
- return readl(&nfc->ecc_status_result);
+#endif }
On MXC_NFC_V1 you're using readw() on a u32 -- that's not OK, even if the ARM accessors let you get away with it. Use a union or #ifdef the struct definition, or just always readl() if you can get away with it, or do two readw()s on V1_1.
Never mind, didn't notice that the struct definition is under #ifdef MXC_NFC_V1_1.
The ARM accessors still should be fixed to do type checking...
-Scott

Do not stop boot as soon as an ECC error is detected. Only stop boot for uncorrectable ECC errors.
This fixes boards no longer booting after some time because a NAND Flash bit has flipped.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../nand_spl/nand_boot_fsl_nfc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index 4c5a7fe..ea05952 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -140,9 +140,21 @@ static void nfc_nand_data_output(void) static int nfc_nand_check_ecc(void) { #if defined(MXC_NFC_V1) - return readw(&nfc->ecc_status_result); + u16 ecc_status = readw(&nfc->ecc_status_result); + return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2; #elif defined(MXC_NFC_V1_1) - return readl(&nfc->ecc_status_result); + u32 ecc_status = readl(&nfc->ecc_status_result); + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int err_limit = CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16 ? 8 : 4; + int subpages = CONFIG_SYS_NAND_PAGE_SIZE / 512; + + do { + if ((ecc_status & 0xf) > err_limit) + return 1; + ecc_status >>= 4; + } while (--subpages); + + return 0; #endif }

Use _mxc_nand_enable_hwecc() instead of duplicating its code.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../drivers/mtd/nand/mxc_nand.c | 28 +++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index 4564b25..7a180e1 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -355,16 +355,6 @@ static int mxc_nand_dev_ready(struct mtd_info *mtd) return 1; }
-#ifdef CONFIG_MXC_NAND_HWECC -static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) -{ - /* - * If HW ECC is enabled, we turn it on during init. There is - * no need to enable again here. - */ -} - -#ifdef MXC_NFC_V1_1 static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) { struct nand_chip *nand_chip = mtd->priv; @@ -378,6 +368,16 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) writew(tmp, &host->regs->config1); }
+#ifdef CONFIG_MXC_NAND_HWECC +static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{ + /* + * If HW ECC is enabled, we turn it on during init. There is + * no need to enable again here. + */ +} + +#ifdef MXC_NFC_V1_1 static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -1235,15 +1235,11 @@ int board_nand_init(struct nand_chip *this) host->pagesize_2k = 0;
this->ecc.size = 512; - tmp = readw(&host->regs->config1); - tmp |= NFC_ECC_EN; - writew(tmp, &host->regs->config1); + _mxc_nand_enable_hwecc(mtd, 1); #else this->ecc.layout = &nand_soft_eccoob; this->ecc.mode = NAND_ECC_SOFT; - tmp = readw(&host->regs->config1); - tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->config1); + _mxc_nand_enable_hwecc(mtd, 0); #endif /* Reset NAND */ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);

On 13/08/2012 22:50, Benoît Thébaudeau wrote:
Use _mxc_nand_enable_hwecc() instead of duplicating its code.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Hi Benoît,
+#ifdef CONFIG_MXC_NAND_HWECC +static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{
- /*
* If HW ECC is enabled, we turn it on during init. There is
* no need to enable again here.
*/
+}
mxc_nand_enable_hwecc is still empty after your changes...
+#ifdef MXC_NFC_V1_1 static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -1235,15 +1235,11 @@ int board_nand_init(struct nand_chip *this) host->pagesize_2k = 0;
this->ecc.size = 512;
- tmp = readw(&host->regs->config1);
- tmp |= NFC_ECC_EN;
- writew(tmp, &host->regs->config1);
- _mxc_nand_enable_hwecc(mtd, 1);
...but you are calling it after removing the code in the init function, and I do not understand how ECC is enabled.
Best regards, Stefano Babic

Hi Stefano,
On 13/08/2012 22:50, Benoît Thébaudeau wrote:
Use _mxc_nand_enable_hwecc() instead of duplicating its code.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Hi Benoît,
+#ifdef CONFIG_MXC_NAND_HWECC +static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) +{
- /*
* If HW ECC is enabled, we turn it on during init. There is
* no need to enable again here.
*/
+}
mxc_nand_enable_hwecc is still empty after your changes...
Yes, and it's normal. The change is a move of the _mxc_nand_enable_hwecc() function, not a filling of the mxc_nand_enable_hwecc() function (note the differing underscore). For some reason, the patch looks weird because it moves mxc_nand_enable_hwecc(), but the result is the same.
+#ifdef MXC_NFC_V1_1 static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -1235,15 +1235,11 @@ int board_nand_init(struct nand_chip *this) host->pagesize_2k = 0;
this->ecc.size = 512;
- tmp = readw(&host->regs->config1);
- tmp |= NFC_ECC_EN;
- writew(tmp, &host->regs->config1);
- _mxc_nand_enable_hwecc(mtd, 1);
...but you are calling it after removing the code in the init function, and I do not understand how ECC is enabled.
It's not the same function.
Best regards, Benoît

mxc_nand_read_page_raw_syndrome() should reenable ECC upon exit. This fixes ECC errors left uncorrected after a call to this function.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../drivers/mtd/nand/mxc_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index 7a180e1..2ae41dc 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -470,7 +470,7 @@ static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd, size = mtd->oobsize - (oob - chip->oob_poi); if (size) chip->read_buf(mtd, oob, size); - _mxc_nand_enable_hwecc(mtd, 0); + _mxc_nand_enable_hwecc(mtd, 1);
return 0; }

Merge mxc_setup_config1() into board_nand_init() in order to ease the addition of i.MX5 support in the following patches.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../drivers/mtd/nand/mxc_nand.c | 53 +++++++++----------- 1 file changed, 23 insertions(+), 30 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index 2ae41dc..e743796 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -1137,24 +1137,6 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command, } }
-#ifdef MXC_NFC_V1_1 -static void mxc_setup_config1(void) -{ - uint16_t tmp; - - tmp = readw(&host->regs->config1); - tmp |= NFC_ONE_CYCLE; - tmp |= NFC_4_8N_ECC; - writew(tmp, &host->regs->config1); - if (host->pagesize_2k) - writew(64/2, &host->regs->spare_area_size); - else - writew(16/2, &host->regs->spare_area_size); -} -#else -#define mxc_setup_config1() -#endif - #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; @@ -1244,6 +1226,29 @@ int board_nand_init(struct nand_chip *this) /* Reset NAND */ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+ /* NAND bus width determines access functions used by upper layer */ + if (is_16bit_nand()) + this->options |= NAND_BUSWIDTH_16; + +#ifdef CONFIG_SYS_NAND_LARGEPAGE + host->pagesize_2k = 1; + this->ecc.layout = &nand_hw_eccoob2k; +#else + host->pagesize_2k = 0; + this->ecc.layout = &nand_hw_eccoob; +#endif + +#ifdef MXC_NFC_V1_1 + tmp = readw(&host->regs->config1); + tmp |= NFC_ONE_CYCLE; + tmp |= NFC_4_8N_ECC; + writew(tmp, &host->regs->config1); + if (host->pagesize_2k) + writew(64/2, &host->regs->spare_area_size); + else + writew(16/2, &host->regs->spare_area_size); +#endif + /* * preset operation * Unlock the internal RAM Buffer @@ -1268,17 +1273,5 @@ int board_nand_init(struct nand_chip *this) /* Unlock Block Command for given address range */ writew(0x4, &host->regs->wrprot);
- /* NAND bus width determines access functions used by upper layer */ - if (is_16bit_nand()) - this->options |= NAND_BUSWIDTH_16; - -#ifdef CONFIG_SYS_NAND_LARGEPAGE - host->pagesize_2k = 1; - this->ecc.layout = &nand_hw_eccoob2k; -#else - host->pagesize_2k = 0; - this->ecc.layout = &nand_hw_eccoob; -#endif - mxc_setup_config1(); return 0; }

There is no reason to have board configs to select the NFC IP revision. Just let the driver detect it. BTW, remove broken NFC IP revision configs from board config files.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../include/configs/flea3.h | 1 - .../include/configs/mx35pdk.h | 1 - .../include/configs/tx25.h | 1 - .../include/fsl_nfc.h | 8 +++----- 4 files changed, 3 insertions(+), 8 deletions(-)
diff --git u-boot-4d3c95f.orig/include/configs/flea3.h u-boot-4d3c95f/include/configs/flea3.h index 46939d4..43cadbc 100644 --- u-boot-4d3c95f.orig/include/configs/flea3.h +++ u-boot-4d3c95f/include/configs/flea3.h @@ -221,7 +221,6 @@ * NAND FLASH driver setup */ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (NFC_BASE_ADDR) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (NFC_BASE_ADDR) diff --git u-boot-4d3c95f.orig/include/configs/mx35pdk.h u-boot-4d3c95f/include/configs/mx35pdk.h index 6eb5da5..93a9dd7 100644 --- u-boot-4d3c95f.orig/include/configs/mx35pdk.h +++ u-boot-4d3c95f/include/configs/mx35pdk.h @@ -239,7 +239,6 @@ * NAND FLASH driver setup */ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (NFC_BASE_ADDR) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (NFC_BASE_ADDR) diff --git u-boot-4d3c95f.orig/include/configs/tx25.h u-boot-4d3c95f/include/configs/tx25.h index 6821528..870e863 100644 --- u-boot-4d3c95f.orig/include/configs/tx25.h +++ u-boot-4d3c95f/include/configs/tx25.h @@ -108,7 +108,6 @@
/* NAND */ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (0xBB000000) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (0xBB000000) diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index c248cef..6618089 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -42,10 +42,12 @@ */ #if defined(CONFIG_MX27) || defined(CONFIG_MX31) #define MXC_NFC_V1 +#define is_mxc_nfc_11() 0 #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) #define MXC_NFC_V1_1 +#define is_mxc_nfc_11() 1 #else -#warning "MXC NFC version not defined" +#error "MXC NFC implementation not supported" #endif
#if defined(MXC_NFC_V1) @@ -53,14 +55,10 @@ #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 #define NAND_MXC_2K_MULTI_CYCLE -#define is_mxc_nfc_11() 0 #elif defined(MXC_NFC_V1_1) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 -#define is_mxc_nfc_11() 1 -#else -#error "define CONFIG_NAND_MXC_VXXX to use the mxc nand driver" #endif
struct fsl_nfc_regs {

On 13/08/2012 22:50, Benoît Thébaudeau wrote:
There is no reason to have board configs to select the NFC IP revision. Just let the driver detect it. BTW, remove broken NFC IP revision configs from board config files.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Hi Benoît,
.../include/configs/flea3.h | 1 - .../include/configs/mx35pdk.h | 1 - .../include/configs/tx25.h | 1 - .../include/fsl_nfc.h | 8 +++----- 4 files changed, 3 insertions(+), 8 deletions(-)
diff --git u-boot-4d3c95f.orig/include/configs/flea3.h u-boot-4d3c95f/include/configs/flea3.h index 46939d4..43cadbc 100644 --- u-boot-4d3c95f.orig/include/configs/flea3.h +++ u-boot-4d3c95f/include/configs/flea3.h @@ -221,7 +221,6 @@
- NAND FLASH driver setup
*/ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (NFC_BASE_ADDR) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (NFC_BASE_ADDR) diff --git u-boot-4d3c95f.orig/include/configs/mx35pdk.h u-boot-4d3c95f/include/configs/mx35pdk.h index 6eb5da5..93a9dd7 100644 --- u-boot-4d3c95f.orig/include/configs/mx35pdk.h +++ u-boot-4d3c95f/include/configs/mx35pdk.h @@ -239,7 +239,6 @@
- NAND FLASH driver setup
*/ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (NFC_BASE_ADDR) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (NFC_BASE_ADDR) diff --git u-boot-4d3c95f.orig/include/configs/tx25.h u-boot-4d3c95f/include/configs/tx25.h index 6821528..870e863 100644 --- u-boot-4d3c95f.orig/include/configs/tx25.h +++ u-boot-4d3c95f/include/configs/tx25.h @@ -108,7 +108,6 @@
/* NAND */ #define CONFIG_NAND_MXC -#define CONFIG_NAND_MXC_V1_1 #define CONFIG_MXC_NAND_REGS_BASE (0xBB000000) #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE (0xBB000000) diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index c248cef..6618089 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -42,10 +42,12 @@ */ #if defined(CONFIG_MX27) || defined(CONFIG_MX31) #define MXC_NFC_V1 +#define is_mxc_nfc_11() 0 #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) #define MXC_NFC_V1_1 +#define is_mxc_nfc_11() 1 #else -#warning "MXC NFC version not defined" +#error "MXC NFC implementation not supported" #endif
#if defined(MXC_NFC_V1) @@ -53,14 +55,10 @@ #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 #define NAND_MXC_2K_MULTI_CYCLE -#define is_mxc_nfc_11() 0 #elif defined(MXC_NFC_V1_1) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 -#define is_mxc_nfc_11() 1 -#else -#error "define CONFIG_NAND_MXC_VXXX to use the mxc nand driver" #endif
struct fsl_nfc_regs {
Agree on this change. The NAND controller version belongs to the SOC, and not to the board. It should be not here.
Acked-by: Stefano Babic sbabic@denx.de
Best regards, Stefano Babic

Use the same IP revisions as in Linux in order to make the comparison more clear.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../drivers/mtd/nand/mxc_nand.c | 16 ++++++++-------- .../include/fsl_nfc.h | 16 +++++++++------- .../nand_spl/nand_boot_fsl_nfc.c | 4 ++-- 3 files changed, 19 insertions(+), 17 deletions(-)
diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index e743796..cf2a7b0 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -77,7 +77,7 @@ static struct nand_ecclayout nand_hw_eccoob2k = { .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} }, }; #endif -#elif defined(MXC_NFC_V1_1) +#elif defined(MXC_NFC_V2_1) #ifndef CONFIG_SYS_NAND_LARGEPAGE static struct nand_ecclayout nand_hw_eccoob = { .eccbytes = 9, @@ -213,7 +213,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only);
- if (is_mxc_nfc_11()) { + if (is_mxc_nfc_21()) { int i; /* * The controller copies the 64 bytes of spare data from @@ -273,7 +273,7 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only);
- if (is_mxc_nfc_11()) { + if (is_mxc_nfc_21()) { int i;
/* @@ -377,7 +377,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) */ }
-#ifdef MXC_NFC_V1_1 +#ifdef MXC_NFC_V2_1 static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -1061,7 +1061,7 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command, case NAND_CMD_PAGEPROG: send_prog_page(host, 0, host->spare_only);
- if (host->pagesize_2k && !is_mxc_nfc_11()) { + if (host->pagesize_2k && is_mxc_nfc_1()) { /* data in 4 areas */ send_prog_page(host, 1, host->spare_only); send_prog_page(host, 2, host->spare_only); @@ -1111,7 +1111,7 @@ void mxc_nand_command(struct mtd_info *mtd, unsigned command, send_cmd(host, NAND_CMD_READSTART); /* read for each AREA */ send_read_page(host, 0, host->spare_only); - if (!is_mxc_nfc_11()) { + if (is_mxc_nfc_1()) { send_read_page(host, 1, host->spare_only); send_read_page(host, 2, host->spare_only); send_read_page(host, 3, host->spare_only); @@ -1200,7 +1200,7 @@ int board_nand_init(struct nand_chip *this) this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.correct = mxc_nand_correct_data; - if (is_mxc_nfc_11()) { + if (is_mxc_nfc_21()) { this->ecc.mode = NAND_ECC_HW_SYNDROME; this->ecc.read_page = mxc_nand_read_page_syndrome; this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome; @@ -1238,7 +1238,7 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif
-#ifdef MXC_NFC_V1_1 +#ifdef MXC_NFC_V2_1 tmp = readw(&host->regs->config1); tmp |= NFC_ONE_CYCLE; tmp |= NFC_4_8N_ECC; diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index 6618089..ff537b4 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -33,7 +33,7 @@ * to support up to 2K byte pagesize nand. * Reading or writing a 2K page requires 4 FDI/FDO cycles. * - * MX25 and MX35 have version 1.1, which has: + * MX25 and MX35 have version 2.1, which has: * 8 512-byte main buffers and * 8 64-byte spare buffers * to support up to 4K byte pagesize nand. @@ -42,10 +42,12 @@ */ #if defined(CONFIG_MX27) || defined(CONFIG_MX31) #define MXC_NFC_V1 -#define is_mxc_nfc_11() 0 +#define is_mxc_nfc_1() 1 +#define is_mxc_nfc_21() 0 #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) -#define MXC_NFC_V1_1 -#define is_mxc_nfc_11() 1 +#define MXC_NFC_V2_1 +#define is_mxc_nfc_1() 0 +#define is_mxc_nfc_21() 1 #else #error "MXC NFC implementation not supported" #endif @@ -55,7 +57,7 @@ #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 #define NAND_MXC_2K_MULTI_CYCLE -#elif defined(MXC_NFC_V1_1) +#elif defined(MXC_NFC_V2_1) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 @@ -86,7 +88,7 @@ struct fsl_nfc_regs { u16 nf_wrprst; u16 config1; u16 config2; -#elif defined(MXC_NFC_V1_1) +#elif defined(MXC_NFC_V2_1) u16 reserved2[2]; u16 buf_addr; u16 flash_addr; @@ -153,7 +155,7 @@ struct fsl_nfc_regs { */ #define NFC_INT 0x8000
-#ifdef MXC_NFC_V1_1 +#ifdef MXC_NFC_V2_1 #define NFC_4_8N_ECC (1 << 0) #endif #define NFC_SP_EN (1 << 2) diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index ea05952..a40c998 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -47,7 +47,7 @@ static void nfc_wait_ready(void)
static void nfc_nand_init(void) { -#if defined(MXC_NFC_V1_1) +#if defined(MXC_NFC_V2_1) int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int config1;
@@ -142,7 +142,7 @@ static int nfc_nand_check_ecc(void) #if defined(MXC_NFC_V1) u16 ecc_status = readw(&nfc->ecc_status_result); return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2; -#elif defined(MXC_NFC_V1_1) +#elif defined(MXC_NFC_V2_1) u32 ecc_status = readl(&nfc->ecc_status_result); int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int err_limit = CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16 ? 8 : 4;

Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- .../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 217 +++++++++++++++----- .../include/fsl_nfc.h | 149 +++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 363 insertions(+), 126 deletions(-)
diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h index 7f66b61..55e9660 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -232,6 +232,15 @@ #define CS0_32M_CS1_32M_CS2_32M_CS3_32M 3
/* + * SRC register definitions + */ +#if defined(CONFIG_MX51) +#define SRC_SBMR_NF16B (1 << 2) +#elif defined(CONFIG_MX53) +#define SRC_SBMR_NF16B (1 << 13) +#endif + +/* * CSPI register definitions */ #define MXC_ECSPI diff --git u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c index cf2a7b0..b2fa2e7 100644 --- u-boot-4d3c95f.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-4d3c95f/drivers/mtd/nand/mxc_nand.c @@ -22,7 +22,8 @@ #include <nand.h> #include <linux/err.h> #include <asm/io.h> -#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) +#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) || \ + defined(CONFIG_MX51) || defined(CONFIG_MX53) #include <asm/arch/imx-regs.h> #endif #include <fsl_nfc.h> @@ -36,6 +37,9 @@ struct mxc_nand_host { struct nand_chip *nand;
struct fsl_nfc_regs __iomem *regs; +#ifdef MXC_NFC_V3_2 + struct fsl_nfc_ip_regs __iomem *ip_regs; +#endif int spare_only; int status_request; int pagesize_2k; @@ -77,7 +81,7 @@ static struct nand_ecclayout nand_hw_eccoob2k = { .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} }, }; #endif -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) #ifndef CONFIG_SYS_NAND_LARGEPAGE static struct nand_ecclayout nand_hw_eccoob = { .eccbytes = 9, @@ -130,6 +134,16 @@ static int is_16bit_nand(void) else return 0; } +#elif defined(CONFIG_MX51) || defined(CONFIG_MX53) +static int is_16bit_nand(void) +{ + struct src *src = (struct src *)SRC_BASE_ADDR; + + if (readl(&src->sbmr) & SRC_SBMR_NF16B) + return 1; + else + return 0; +} #else #warning "8/16 bit NAND autodetection not supported" static int is_16bit_nand(void) @@ -150,7 +164,7 @@ static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size
/* * This function polls the NANDFC to wait for the basic operation to - * complete by checking the INT bit of config2 register. + * complete by checking the INT bit. */ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint16_t param) @@ -158,10 +172,17 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint32_t tmp;
while (max_retries-- > 0) { - if (readw(&host->regs->config2) & NFC_INT) { - tmp = readw(&host->regs->config2); - tmp &= ~NFC_INT; - writew(tmp, &host->regs->config2); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + tmp = readnfc(&host->regs->config2); + if (tmp & NFC_V1_V2_CONFIG2_INT) { + tmp &= ~NFC_V1_V2_CONFIG2_INT; + writenfc(tmp, &host->regs->config2); +#elif defined(MXC_NFC_V3_2) + tmp = readnfc(&host->ip_regs->ipc); + if (tmp & NFC_V3_IPC_INT) { + tmp &= ~NFC_V3_IPC_INT; + writenfc(tmp, &host->ip_regs->ipc); +#endif break; } udelay(1); @@ -180,8 +201,8 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
- writew(cmd, &host->regs->flash_cmd); - writew(NFC_CMD, &host->regs->config2); + writenfc(cmd, &host->regs->flash_cmd); + writenfc(NFC_CMD, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, cmd); @@ -196,8 +217,8 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
- writew(addr, &host->regs->flash_addr); - writew(NFC_ADDR, &host->regs->config2); + writenfc(addr, &host->regs->flash_addr); + writenfc(NFC_ADDR, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, addr); @@ -213,7 +234,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only);
- if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { int i; /* * The controller copies the 64 bytes of spare data from @@ -229,19 +250,26 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, } }
- writew(buf_id, &host->regs->buf_addr); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(buf_id, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + tmp |= NFC_V3_CONFIG1_RBA(buf_id); + writenfc(tmp, &host->regs->config1); +#endif
/* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint16_t config1 = readw(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) - config1 |= NFC_SP_EN; + config1 |= NFC_CONFIG1_SP_EN; else - config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->config1); + config1 &= ~NFC_CONFIG1_SP_EN; + writenfc(config1, &host->regs->config1); }
- writew(NFC_INPUT, &host->regs->config2); + writenfc(NFC_INPUT, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); @@ -256,24 +284,31 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
- writew(buf_id, &host->regs->buf_addr); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(buf_id, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + tmp |= NFC_V3_CONFIG1_RBA(buf_id); + writenfc(tmp, &host->regs->config1); +#endif
/* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint32_t config1 = readw(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) - config1 |= NFC_SP_EN; + config1 |= NFC_CONFIG1_SP_EN; else - config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->config1); + config1 &= ~NFC_CONFIG1_SP_EN; + writenfc(config1, &host->regs->config1); }
- writew(NFC_OUTPUT, &host->regs->config2); + writenfc(NFC_OUTPUT, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only);
- if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { int i;
/* @@ -293,17 +328,23 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, /* Request the NANDFC to perform a read of the NAND device ID. */ static void send_read_id(struct mxc_nand_host *host) { - uint16_t tmp; + uint32_t tmp;
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* NANDFC buffer 0 is used for device ID output */ - writew(0x0, &host->regs->buf_addr); + writenfc(0x0, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(tmp, &host->regs->config1); +#endif
/* Read ID into main buffer */ - tmp = readw(&host->regs->config1); - tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_CONFIG1_SP_EN; + writenfc(tmp, &host->regs->config1);
- writew(NFC_ID, &host->regs->config2); + writenfc(NFC_ID, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); @@ -315,32 +356,40 @@ static void send_read_id(struct mxc_nand_host *host) */ static uint16_t get_dev_status(struct mxc_nand_host *host) { +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) void __iomem *main_buf = host->regs->main_area[1]; uint32_t store; - uint16_t ret, tmp; +#endif + uint32_t ret, tmp; /* Issue status request to NAND device */
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* store the main area1 first word, later do recovery */ store = readl(main_buf); /* NANDFC buffer 1 is used for device status */ - writew(1, &host->regs->buf_addr); + writenfc(1, &host->regs->buf_addr); +#endif
/* Read status into main buffer */ - tmp = readw(&host->regs->config1); - tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_CONFIG1_SP_EN; + writenfc(tmp, &host->regs->config1);
- writew(NFC_STATUS, &host->regs->config2); + writenfc(NFC_STATUS, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0);
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* * Status is placed in first word of main buffer * get status, then recovery area 1 data */ ret = readw(main_buf); writel(store, main_buf); +#elif defined(MXC_NFC_V3_2) + ret = readnfc(&host->regs->config1) >> 16; +#endif
return ret; } @@ -359,13 +408,23 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t tmp = readw(&host->regs->config1); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + uint16_t tmp = readnfc(&host->regs->config1); + + if (on) + tmp |= NFC_V1_V2_CONFIG1_ECC_EN; + else + tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; + writenfc(tmp, &host->regs->config1); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->ip_regs->config2);
if (on) - tmp |= NFC_ECC_EN; + tmp |= NFC_V3_CONFIG2_ECC_EN; else - tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->config1); + tmp &= ~NFC_V3_CONFIG2_ECC_EN; + writenfc(tmp, &host->ip_regs->config2); +#endif }
#ifdef CONFIG_MXC_NAND_HWECC @@ -377,7 +436,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) */ }
-#ifdef MXC_NFC_V2_1 +#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -698,7 +757,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, * additional correction. 2-Bit errors cannot be corrected by * HW ECC, so we need to return failure */ - uint16_t ecc_status = readw(&host->regs->ecc_status_result); + uint16_t ecc_status = readnfc(&host->regs->ecc_status_result);
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { MTDDEBUG(MTD_DEBUG_LEVEL0, @@ -1167,7 +1226,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { int board_nand_init(struct nand_chip *this) { struct mtd_info *mtd; - uint16_t tmp; + uint32_t tmp;
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT this->options |= NAND_USE_FLASH_BBT; @@ -1194,13 +1253,17 @@ int board_nand_init(struct nand_chip *this) this->verify_buf = mxc_nand_verify_buf;
host->regs = (struct fsl_nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; +#ifdef MXC_NFC_V3_2 + host->ip_regs = + (struct fsl_nfc_ip_regs __iomem *)CONFIG_MXC_NAND_IP_REGS_BASE; +#endif host->clk_act = 1;
#ifdef CONFIG_MXC_NAND_HWECC this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.correct = mxc_nand_correct_data; - if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { this->ecc.mode = NAND_ECC_HW_SYNDROME; this->ecc.read_page = mxc_nand_read_page_syndrome; this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome; @@ -1238,25 +1301,26 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) #ifdef MXC_NFC_V2_1 - tmp = readw(&host->regs->config1); - tmp |= NFC_ONE_CYCLE; - tmp |= NFC_4_8N_ECC; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp |= NFC_V2_CONFIG1_ONE_CYCLE; + tmp |= NFC_V2_CONFIG1_ECC_MODE_4; + writenfc(tmp, &host->regs->config1); if (host->pagesize_2k) - writew(64/2, &host->regs->spare_area_size); + writenfc(64/2, &host->regs->spare_area_size); else - writew(16/2, &host->regs->spare_area_size); + writenfc(16/2, &host->regs->spare_area_size); #endif
/* * preset operation * Unlock the internal RAM Buffer */ - writew(0x2, &host->regs->config); + writenfc(0x2, &host->regs->config);
/* Blocks to be unlocked */ - writew(0x0, &host->regs->unlockstart_blkaddr); + writenfc(0x0, &host->regs->unlockstart_blkaddr); /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the * unlockend_blkaddr, but the magic 0x4000 does not always work * when writing more than some 32 megabytes (on 2k page nands) @@ -1268,10 +1332,53 @@ int board_nand_init(struct nand_chip *this) * This might be NAND chip specific and the i.MX31 datasheet is * extremely vague about the semantics of this register. */ - writew(0xFFFF, &host->regs->unlockend_blkaddr); + writenfc(0xFFFF, &host->regs->unlockend_blkaddr);
/* Unlock Block Command for given address range */ - writew(0x4, &host->regs->wrprot); + writenfc(0x4, &host->regs->wrprot); +#elif defined(MXC_NFC_V3_2) + writenfc(NFC_V3_CONFIG1_RBA(0), &host->regs->config1); + writenfc(NFC_V3_IPC_CREQ, &host->ip_regs->ipc); + + /* Unlock the internal RAM Buffer */ + writenfc(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK, + &host->ip_regs->wrprot); + + /* Blocks to be unlocked */ + for (tmp = 0; tmp < CONFIG_SYS_NAND_MAX_CHIPS; tmp++) + writenfc(0x0 | 0xFFFF << 16, + &host->ip_regs->wrprot_unlock_blkaddr[tmp]); + + writenfc(0, &host->ip_regs->ipc); + + tmp = readnfc(&host->ip_regs->config2); + tmp &= ~(NFC_V3_CONFIG2_SPAS_MASK | NFC_V3_CONFIG2_EDC_MASK | + NFC_V3_CONFIG2_ECC_MODE_8 | NFC_V3_CONFIG2_PS_MASK); + tmp |= NFC_V3_CONFIG2_ONE_CYCLE; + + if (host->pagesize_2k) { + tmp |= NFC_V3_CONFIG2_SPAS(64/2); + tmp |= NFC_V3_CONFIG2_PS_2048; + } else { + tmp |= NFC_V3_CONFIG2_SPAS(16/2); + tmp |= NFC_V3_CONFIG2_PS_512; + } + + writenfc(tmp, &host->ip_regs->config2); + + tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) | + NFC_V3_CONFIG3_NO_SDMA | + NFC_V3_CONFIG3_RBB_MODE | + NFC_V3_CONFIG3_SBB(6) | /* Reset default */ + NFC_V3_CONFIG3_ADD_OP(0); + + if (!(this->options & NAND_BUSWIDTH_16)) + tmp |= NFC_V3_CONFIG3_FW8; + + writenfc(tmp, &host->ip_regs->config3); + + writenfc(0, &host->ip_regs->delay_line); +#endif
return 0; } diff --git u-boot-4d3c95f.orig/include/fsl_nfc.h u-boot-4d3c95f/include/fsl_nfc.h index ff537b4..48a6448 100644 --- u-boot-4d3c95f.orig/include/fsl_nfc.h +++ u-boot-4d3c95f/include/fsl_nfc.h @@ -33,7 +33,8 @@ * to support up to 2K byte pagesize nand. * Reading or writing a 2K page requires 4 FDI/FDO cycles. * - * MX25 and MX35 have version 2.1, which has: + * MX25 and MX35 have version 2.1, and MX51 and MX53 have version 3.2, which + * have: * 8 512-byte main buffers and * 8 64-byte spare buffers * to support up to 4K byte pagesize nand. @@ -44,20 +45,29 @@ #define MXC_NFC_V1 #define is_mxc_nfc_1() 1 #define is_mxc_nfc_21() 0 +#define is_mxc_nfc_32() 0 #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) #define MXC_NFC_V2_1 #define is_mxc_nfc_1() 0 #define is_mxc_nfc_21() 1 +#define is_mxc_nfc_32() 0 +#elif defined(CONFIG_MX51) || defined(CONFIG_MX53) +#define MXC_NFC_V3 +#define MXC_NFC_V3_2 +#define is_mxc_nfc_1() 0 +#define is_mxc_nfc_21() 0 +#define is_mxc_nfc_32() 1 #else #error "MXC NFC implementation not supported" #endif +#define is_mxc_nfc_3() is_mxc_nfc_32()
#if defined(MXC_NFC_V1) #define NAND_MXC_NR_BUFS 4 #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 #define NAND_MXC_2K_MULTI_CYCLE -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 @@ -110,61 +120,106 @@ struct fsl_nfc_regs { u16 unlockend_blkaddr2; u16 unlockstart_blkaddr3; u16 unlockend_blkaddr3; +#elif defined(MXC_NFC_V3_2) + u32 flash_cmd; + u32 flash_addr[12]; + u32 config1; + u32 ecc_status_result; + u32 status_sum; + u32 launch; #endif };
-/* - * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register for Command - * operation - */ -#define NFC_CMD 0x1 +#ifdef MXC_NFC_V3_2 +struct fsl_nfc_ip_regs { + u32 wrprot; + u32 wrprot_unlock_blkaddr[8]; + u32 config2; + u32 config3; + u32 ipc; + u32 err_addr; + u32 delay_line; +}; +#endif
-/* - * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register for Address - * operation - */ -#define NFC_ADDR 0x2 +/* Set FCMD to 1, rest to 0 for Command operation */ +#define NFC_CMD 0x1
-/* - * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register for Input - * operation - */ -#define NFC_INPUT 0x4 +/* Set FADD to 1, rest to 0 for Address operation */ +#define NFC_ADDR 0x2
-/* - * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register for Data - * Output operation - */ -#define NFC_OUTPUT 0x8 +/* Set FDI to 1, rest to 0 for Input operation */ +#define NFC_INPUT 0x4
-/* - * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register for Read ID - * operation - */ -#define NFC_ID 0x10 +/* Set FDO to 001, rest to 0 for Data Output operation */ +#define NFC_OUTPUT 0x8
-/* - * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register for Read - * Status operation - */ -#define NFC_STATUS 0x20 +/* Set FDO to 010, rest to 0 for Read ID operation */ +#define NFC_ID 0x10
-/* - * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read Status - * operation - */ -#define NFC_INT 0x8000 +/* Set FDO to 100, rest to 0 for Read Status operation */ +#define NFC_STATUS 0x20 + +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +#define NFC_CONFIG1_SP_EN (1 << 2) +#define NFC_CONFIG1_RST (1 << 6) +#define NFC_CONFIG1_CE (1 << 7) +#elif defined(MXC_NFC_V3_2) +#define NFC_CONFIG1_SP_EN (1 << 0) +#define NFC_CONFIG1_CE (1 << 1) +#define NFC_CONFIG1_RST (1 << 2) +#endif +#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3) +#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4) +#define NFC_V1_V2_CONFIG1_BIG (1 << 5) +#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0) +#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) +#define NFC_V2_CONFIG1_FP_INT (1 << 11) +#define NFC_V3_CONFIG1_RBA_MASK (0x7 << 4) +#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7) << 4) + +#define NFC_V1_V2_CONFIG2_INT (1 << 15) +#define NFC_V3_CONFIG2_PS_MASK (0x3 << 0) +#define NFC_V3_CONFIG2_PS_512 (0 << 0) +#define NFC_V3_CONFIG2_PS_2048 (1 << 0) +#define NFC_V3_CONFIG2_PS_4096 (2 << 0) +#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2) +#define NFC_V3_CONFIG2_ECC_EN (1 << 3) +#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4) +#define NFC_V3_CONFIG2_NUM_ADDR_PH0 (1 << 5) +#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6) +#define NFC_V3_CONFIG2_PPB_MASK (0x3 << 7) +#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7) +#define NFC_V3_CONFIG2_EDC_MASK (0x7 << 9) +#define NFC_V3_CONFIG2_EDC(x) (((x) & 0x7) << 9) +#define NFC_V3_CONFIG2_NUM_ADDR_PH1(x) (((x) & 0x3) << 12) +#define NFC_V3_CONFIG2_INT_MSK (1 << 15) +#define NFC_V3_CONFIG2_SPAS_MASK (0xff << 16) +#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16) +#define NFC_V3_CONFIG2_ST_CMD_MASK (0xff << 24) +#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24) + +#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0) +#define NFC_V3_CONFIG3_FW8 (1 << 3) +#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8) +#define NFC_V3_CONFIG3_NUM_OF_DEVS(x) (((x) & 0x7) << 12) +#define NFC_V3_CONFIG3_RBB_MODE (1 << 15) +#define NFC_V3_CONFIG3_NO_SDMA (1 << 20) + +#define NFC_V3_WRPROT_UNLOCK (1 << 2) +#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6) + +#define NFC_V3_IPC_CREQ (1 << 0) +#define NFC_V3_IPC_INT (1 << 31)
-#ifdef MXC_NFC_V2_1 -#define NFC_4_8N_ECC (1 << 0) +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +#define operation config2 +#define readnfc readw +#define writenfc writew +#elif defined(MXC_NFC_V3_2) +#define operation launch +#define readnfc readl +#define writenfc writel #endif -#define NFC_SP_EN (1 << 2) -#define NFC_ECC_EN (1 << 3) -#define NFC_INT_MSK (1 << 4) -#define NFC_BIG (1 << 5) -#define NFC_RST (1 << 6) -#define NFC_CE (1 << 7) -#define NFC_ONE_CYCLE (1 << 8) -#define NFC_FP_INT (1 << 11)
#endif /* __FSL_NFC_H */ diff --git u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c index a40c998..1096727 100644 --- u-boot-4d3c95f.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-4d3c95f/nand_spl/nand_boot_fsl_nfc.c @@ -30,64 +30,117 @@ #include <asm/io.h> #include <fsl_nfc.h>
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR; +#elif defined(MXC_NFC_V3_2) +static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR_AXI; +static struct fsl_nfc_ip_regs *const nfc_ip = (void *)NFC_BASE_ADDR; +#endif
static void nfc_wait_ready(void) { uint32_t tmp;
- while (!(readw(&nfc->config2) & NFC_INT)) +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + while (!(readnfc(&nfc->config2) & NFC_V1_V2_CONFIG2_INT)) ;
/* Reset interrupt flag */ - tmp = readw(&nfc->config2); - tmp &= ~NFC_INT; - writew(tmp, &nfc->config2); + tmp = readnfc(&nfc->config2); + tmp &= ~NFC_V1_V2_CONFIG2_INT; + writenfc(tmp, &nfc->config2); +#elif defined(MXC_NFC_V3_2) + while (!(readnfc(&nfc_ip->ipc) & NFC_V3_IPC_INT)) + ; + + /* Reset interrupt flag */ + tmp = readnfc(&nfc_ip->ipc); + tmp &= ~NFC_V3_IPC_INT; + writenfc(tmp, &nfc_ip->ipc); +#endif }
static void nfc_nand_init(void) { -#if defined(MXC_NFC_V2_1) +#if defined(MXC_NFC_V3_2) + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int tmp; + + tmp = (readnfc(&nfc_ip->config2) & ~(NFC_V3_CONFIG2_SPAS_MASK | + NFC_V3_CONFIG2_EDC_MASK | NFC_V3_CONFIG2_PS_MASK)) | + NFC_V3_CONFIG2_SPAS(CONFIG_SYS_NAND_SPARE_SIZE / 2) | + NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_ECC_EN | + NFC_V3_CONFIG2_ONE_CYCLE; + if (CONFIG_SYS_NAND_PAGE_SIZE == 4096) + tmp |= NFC_V3_CONFIG2_PS_4096; + else if (CONFIG_SYS_NAND_PAGE_SIZE == 2048) + tmp |= NFC_V3_CONFIG2_PS_2048; + else if (CONFIG_SYS_NAND_PAGE_SIZE == 512) + tmp |= NFC_V3_CONFIG2_PS_512; + /* + * if spare size is larger that 16 bytes per 512 byte hunk + * then use 8 symbol correction instead of 4 + */ + if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) + tmp |= NFC_V3_CONFIG2_ECC_MODE_8; + else + tmp &= ~NFC_V3_CONFIG2_ECC_MODE_8; + writenfc(tmp, &nfc_ip->config2); + + tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) | + NFC_V3_CONFIG3_NO_SDMA | + NFC_V3_CONFIG3_RBB_MODE | + NFC_V3_CONFIG3_SBB(6) | /* Reset default */ + NFC_V3_CONFIG3_ADD_OP(0); +#ifndef CONFIG_SYS_NAND_BUSWIDTH_16 + tmp |= NFC_V3_CONFIG3_FW8; +#endif + writenfc(tmp, &nfc_ip->config3); + + writenfc(0, &nfc_ip->delay_line); +#elif defined(MXC_NFC_V2_1) int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int config1;
- writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size); + writenfc(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size);
/* unlocking RAM Buff */ - writew(0x2, &nfc->config); + writenfc(0x2, &nfc->config);
/* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | - NFC_ONE_CYCLE | NFC_FP_INT; + config1 = readnfc(&nfc->config1) | NFC_V1_V2_CONFIG1_ECC_EN | + NFC_V1_V2_CONFIG1_INT_MSK | NFC_V2_CONFIG1_ONE_CYCLE | + NFC_V2_CONFIG1_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 */ if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) - config1 &= ~NFC_4_8N_ECC; + config1 &= ~NFC_V2_CONFIG1_ECC_MODE_4; else - config1 |= NFC_4_8N_ECC; - writew(config1, &nfc->config1); + config1 |= NFC_V2_CONFIG1_ECC_MODE_4; + writenfc(config1, &nfc->config1); #elif defined(MXC_NFC_V1) /* unlocking RAM Buff */ - writew(0x2, &nfc->config); + writenfc(0x2, &nfc->config);
/* hardware ECC checking and correct */ - writew(NFC_ECC_EN | NFC_INT_MSK, &nfc->config1); + writenfc(NFC_V1_V2_CONFIG1_ECC_EN | NFC_V1_V2_CONFIG1_INT_MSK, + &nfc->config1); #endif }
static void nfc_nand_command(unsigned short command) { - writew(command, &nfc->flash_cmd); - writew(NFC_CMD, &nfc->config2); + writenfc(command, &nfc->flash_cmd); + writenfc(NFC_CMD, &nfc->operation); nfc_wait_ready(); }
static void nfc_nand_address(unsigned short address) { - writew(address, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); + writenfc(address, &nfc->flash_addr); + writenfc(NFC_ADDR, &nfc->operation); nfc_wait_ready(); }
@@ -121,8 +174,14 @@ static void nfc_nand_data_output(void) int i; #endif
- writew(0, &nfc->buf_addr); - writew(NFC_OUTPUT, &nfc->config2); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(0, &nfc->buf_addr); +#elif defined(MXC_NFC_V3_2) + int config1 = readnfc(&nfc->config1); + config1 &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(config1, &nfc->config1); +#endif + writenfc(NFC_OUTPUT, &nfc->operation); nfc_wait_ready(); #ifdef NAND_MXC_2K_MULTI_CYCLE /* @@ -130,8 +189,8 @@ static void nfc_nand_data_output(void) * for pages larger than 512 bytes. */ for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { - writew(i, &nfc->buf_addr); - writew(NFC_OUTPUT, &nfc->config2); + writenfc(i, &nfc->buf_addr); + writenfc(NFC_OUTPUT, &nfc->operation); nfc_wait_ready(); } #endif @@ -142,7 +201,7 @@ static int nfc_nand_check_ecc(void) #if defined(MXC_NFC_V1) u16 ecc_status = readw(&nfc->ecc_status_result); return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2; -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) u32 ecc_status = readl(&nfc->ecc_status_result); int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int err_limit = CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16 ? 8 : 4; @@ -160,7 +219,14 @@ static int nfc_nand_check_ecc(void)
static void nfc_nand_read_page(unsigned int page_address) { - writew(0, &nfc->buf_addr); /* read in first 0 buffer */ + /* read in first 0 buffer */ +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(0, &nfc->buf_addr); +#elif defined(MXC_NFC_V3_2) + int config1 = readnfc(&nfc->config1); + config1 &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(config1, &nfc->config1); +#endif nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page_address);

On 8/13/2012 1:51 PM, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 217 +++++++++++++++----- .../include/fsl_nfc.h | 149 +++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 363 insertions(+), 126 deletions(-)
diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h index 7f66b61..55e9660 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -232,6 +232,15 @@ #define CS0_32M_CS1_32M_CS2_32M_CS3_32M 3
/*
- SRC register definitions
- */
+#if defined(CONFIG_MX51) +#define SRC_SBMR_NF16B (1 << 2) +#elif defined(CONFIG_MX53) +#define SRC_SBMR_NF16B (1 << 13) +#endif
You could give an error if a multi-platform kernel has both defined, if a run-time check is too difficult.

On 8/13/2012 2:04 PM, Troy Kisky wrote:
On 8/13/2012 1:51 PM, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 217 +++++++++++++++----- .../include/fsl_nfc.h | 149 +++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 363 insertions(+), 126 deletions(-)
diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h index 7f66b61..55e9660 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -232,6 +232,15 @@ #define CS0_32M_CS1_32M_CS2_32M_CS3_32M 3 /*
- SRC register definitions
- */
+#if defined(CONFIG_MX51) +#define SRC_SBMR_NF16B (1 << 2) +#elif defined(CONFIG_MX53) +#define SRC_SBMR_NF16B (1 << 13) +#endif
You could give an error if a multi-platform kernel has both defined, if a run-time check is too difficult.
Please ignore my stupid ramblings!!!!

Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- Changes for v2: - Fix warning for unused tmp variable in board_nand_init() for NFC V1.
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 219 +++++++++++++++----- .../include/fsl_nfc.h | 149 ++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 365 insertions(+), 126 deletions(-)
diff --git u-boot-imx-88e73dd.orig/arch/arm/include/asm/arch-mx5/imx-regs.h u-boot-imx-88e73dd/arch/arm/include/asm/arch-mx5/imx-regs.h index c53465f..ca73dea 100644 --- u-boot-imx-88e73dd.orig/arch/arm/include/asm/arch-mx5/imx-regs.h +++ u-boot-imx-88e73dd/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -232,6 +232,15 @@ #define CS0_32M_CS1_32M_CS2_32M_CS3_32M 3
/* + * SRC register definitions + */ +#if defined(CONFIG_MX51) +#define SRC_SBMR_NF16B (1 << 2) +#elif defined(CONFIG_MX53) +#define SRC_SBMR_NF16B (1 << 13) +#endif + +/* * CSPI register definitions */ #define MXC_ECSPI diff --git u-boot-imx-88e73dd.orig/drivers/mtd/nand/mxc_nand.c u-boot-imx-88e73dd/drivers/mtd/nand/mxc_nand.c index cf2a7b0..cead757 100644 --- u-boot-imx-88e73dd.orig/drivers/mtd/nand/mxc_nand.c +++ u-boot-imx-88e73dd/drivers/mtd/nand/mxc_nand.c @@ -22,7 +22,8 @@ #include <nand.h> #include <linux/err.h> #include <asm/io.h> -#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) +#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) || \ + defined(CONFIG_MX51) || defined(CONFIG_MX53) #include <asm/arch/imx-regs.h> #endif #include <fsl_nfc.h> @@ -36,6 +37,9 @@ struct mxc_nand_host { struct nand_chip *nand;
struct fsl_nfc_regs __iomem *regs; +#ifdef MXC_NFC_V3_2 + struct fsl_nfc_ip_regs __iomem *ip_regs; +#endif int spare_only; int status_request; int pagesize_2k; @@ -77,7 +81,7 @@ static struct nand_ecclayout nand_hw_eccoob2k = { .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} }, }; #endif -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) #ifndef CONFIG_SYS_NAND_LARGEPAGE static struct nand_ecclayout nand_hw_eccoob = { .eccbytes = 9, @@ -130,6 +134,16 @@ static int is_16bit_nand(void) else return 0; } +#elif defined(CONFIG_MX51) || defined(CONFIG_MX53) +static int is_16bit_nand(void) +{ + struct src *src = (struct src *)SRC_BASE_ADDR; + + if (readl(&src->sbmr) & SRC_SBMR_NF16B) + return 1; + else + return 0; +} #else #warning "8/16 bit NAND autodetection not supported" static int is_16bit_nand(void) @@ -150,7 +164,7 @@ static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size
/* * This function polls the NANDFC to wait for the basic operation to - * complete by checking the INT bit of config2 register. + * complete by checking the INT bit. */ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint16_t param) @@ -158,10 +172,17 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint32_t tmp;
while (max_retries-- > 0) { - if (readw(&host->regs->config2) & NFC_INT) { - tmp = readw(&host->regs->config2); - tmp &= ~NFC_INT; - writew(tmp, &host->regs->config2); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + tmp = readnfc(&host->regs->config2); + if (tmp & NFC_V1_V2_CONFIG2_INT) { + tmp &= ~NFC_V1_V2_CONFIG2_INT; + writenfc(tmp, &host->regs->config2); +#elif defined(MXC_NFC_V3_2) + tmp = readnfc(&host->ip_regs->ipc); + if (tmp & NFC_V3_IPC_INT) { + tmp &= ~NFC_V3_IPC_INT; + writenfc(tmp, &host->ip_regs->ipc); +#endif break; } udelay(1); @@ -180,8 +201,8 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
- writew(cmd, &host->regs->flash_cmd); - writew(NFC_CMD, &host->regs->config2); + writenfc(cmd, &host->regs->flash_cmd); + writenfc(NFC_CMD, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, cmd); @@ -196,8 +217,8 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
- writew(addr, &host->regs->flash_addr); - writew(NFC_ADDR, &host->regs->config2); + writenfc(addr, &host->regs->flash_addr); + writenfc(NFC_ADDR, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, addr); @@ -213,7 +234,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only);
- if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { int i; /* * The controller copies the 64 bytes of spare data from @@ -229,19 +250,26 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, } }
- writew(buf_id, &host->regs->buf_addr); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(buf_id, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + tmp |= NFC_V3_CONFIG1_RBA(buf_id); + writenfc(tmp, &host->regs->config1); +#endif
/* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint16_t config1 = readw(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) - config1 |= NFC_SP_EN; + config1 |= NFC_CONFIG1_SP_EN; else - config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->config1); + config1 &= ~NFC_CONFIG1_SP_EN; + writenfc(config1, &host->regs->config1); }
- writew(NFC_INPUT, &host->regs->config2); + writenfc(NFC_INPUT, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); @@ -256,24 +284,31 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
- writew(buf_id, &host->regs->buf_addr); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(buf_id, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + tmp |= NFC_V3_CONFIG1_RBA(buf_id); + writenfc(tmp, &host->regs->config1); +#endif
/* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint32_t config1 = readw(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) - config1 |= NFC_SP_EN; + config1 |= NFC_CONFIG1_SP_EN; else - config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->config1); + config1 &= ~NFC_CONFIG1_SP_EN; + writenfc(config1, &host->regs->config1); }
- writew(NFC_OUTPUT, &host->regs->config2); + writenfc(NFC_OUTPUT, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only);
- if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { int i;
/* @@ -293,17 +328,23 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, /* Request the NANDFC to perform a read of the NAND device ID. */ static void send_read_id(struct mxc_nand_host *host) { - uint16_t tmp; + uint32_t tmp;
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* NANDFC buffer 0 is used for device ID output */ - writew(0x0, &host->regs->buf_addr); + writenfc(0x0, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(tmp, &host->regs->config1); +#endif
/* Read ID into main buffer */ - tmp = readw(&host->regs->config1); - tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_CONFIG1_SP_EN; + writenfc(tmp, &host->regs->config1);
- writew(NFC_ID, &host->regs->config2); + writenfc(NFC_ID, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); @@ -315,32 +356,40 @@ static void send_read_id(struct mxc_nand_host *host) */ static uint16_t get_dev_status(struct mxc_nand_host *host) { +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) void __iomem *main_buf = host->regs->main_area[1]; uint32_t store; - uint16_t ret, tmp; +#endif + uint32_t ret, tmp; /* Issue status request to NAND device */
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* store the main area1 first word, later do recovery */ store = readl(main_buf); /* NANDFC buffer 1 is used for device status */ - writew(1, &host->regs->buf_addr); + writenfc(1, &host->regs->buf_addr); +#endif
/* Read status into main buffer */ - tmp = readw(&host->regs->config1); - tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_CONFIG1_SP_EN; + writenfc(tmp, &host->regs->config1);
- writew(NFC_STATUS, &host->regs->config2); + writenfc(NFC_STATUS, &host->regs->operation);
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0);
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* * Status is placed in first word of main buffer * get status, then recovery area 1 data */ ret = readw(main_buf); writel(store, main_buf); +#elif defined(MXC_NFC_V3_2) + ret = readnfc(&host->regs->config1) >> 16; +#endif
return ret; } @@ -359,13 +408,23 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t tmp = readw(&host->regs->config1); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + uint16_t tmp = readnfc(&host->regs->config1); + + if (on) + tmp |= NFC_V1_V2_CONFIG1_ECC_EN; + else + tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; + writenfc(tmp, &host->regs->config1); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->ip_regs->config2);
if (on) - tmp |= NFC_ECC_EN; + tmp |= NFC_V3_CONFIG2_ECC_EN; else - tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->config1); + tmp &= ~NFC_V3_CONFIG2_ECC_EN; + writenfc(tmp, &host->ip_regs->config2); +#endif }
#ifdef CONFIG_MXC_NAND_HWECC @@ -377,7 +436,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) */ }
-#ifdef MXC_NFC_V2_1 +#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -698,7 +757,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, * additional correction. 2-Bit errors cannot be corrected by * HW ECC, so we need to return failure */ - uint16_t ecc_status = readw(&host->regs->ecc_status_result); + uint16_t ecc_status = readnfc(&host->regs->ecc_status_result);
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { MTDDEBUG(MTD_DEBUG_LEVEL0, @@ -1167,7 +1226,9 @@ static struct nand_bbt_descr bbt_mirror_descr = { int board_nand_init(struct nand_chip *this) { struct mtd_info *mtd; - uint16_t tmp; +#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) + uint32_t tmp; +#endif
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT this->options |= NAND_USE_FLASH_BBT; @@ -1194,13 +1255,17 @@ int board_nand_init(struct nand_chip *this) this->verify_buf = mxc_nand_verify_buf;
host->regs = (struct fsl_nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; +#ifdef MXC_NFC_V3_2 + host->ip_regs = + (struct fsl_nfc_ip_regs __iomem *)CONFIG_MXC_NAND_IP_REGS_BASE; +#endif host->clk_act = 1;
#ifdef CONFIG_MXC_NAND_HWECC this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.correct = mxc_nand_correct_data; - if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { this->ecc.mode = NAND_ECC_HW_SYNDROME; this->ecc.read_page = mxc_nand_read_page_syndrome; this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome; @@ -1238,25 +1303,26 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) #ifdef MXC_NFC_V2_1 - tmp = readw(&host->regs->config1); - tmp |= NFC_ONE_CYCLE; - tmp |= NFC_4_8N_ECC; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp |= NFC_V2_CONFIG1_ONE_CYCLE; + tmp |= NFC_V2_CONFIG1_ECC_MODE_4; + writenfc(tmp, &host->regs->config1); if (host->pagesize_2k) - writew(64/2, &host->regs->spare_area_size); + writenfc(64/2, &host->regs->spare_area_size); else - writew(16/2, &host->regs->spare_area_size); + writenfc(16/2, &host->regs->spare_area_size); #endif
/* * preset operation * Unlock the internal RAM Buffer */ - writew(0x2, &host->regs->config); + writenfc(0x2, &host->regs->config);
/* Blocks to be unlocked */ - writew(0x0, &host->regs->unlockstart_blkaddr); + writenfc(0x0, &host->regs->unlockstart_blkaddr); /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the * unlockend_blkaddr, but the magic 0x4000 does not always work * when writing more than some 32 megabytes (on 2k page nands) @@ -1268,10 +1334,53 @@ int board_nand_init(struct nand_chip *this) * This might be NAND chip specific and the i.MX31 datasheet is * extremely vague about the semantics of this register. */ - writew(0xFFFF, &host->regs->unlockend_blkaddr); + writenfc(0xFFFF, &host->regs->unlockend_blkaddr);
/* Unlock Block Command for given address range */ - writew(0x4, &host->regs->wrprot); + writenfc(0x4, &host->regs->wrprot); +#elif defined(MXC_NFC_V3_2) + writenfc(NFC_V3_CONFIG1_RBA(0), &host->regs->config1); + writenfc(NFC_V3_IPC_CREQ, &host->ip_regs->ipc); + + /* Unlock the internal RAM Buffer */ + writenfc(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK, + &host->ip_regs->wrprot); + + /* Blocks to be unlocked */ + for (tmp = 0; tmp < CONFIG_SYS_NAND_MAX_CHIPS; tmp++) + writenfc(0x0 | 0xFFFF << 16, + &host->ip_regs->wrprot_unlock_blkaddr[tmp]); + + writenfc(0, &host->ip_regs->ipc); + + tmp = readnfc(&host->ip_regs->config2); + tmp &= ~(NFC_V3_CONFIG2_SPAS_MASK | NFC_V3_CONFIG2_EDC_MASK | + NFC_V3_CONFIG2_ECC_MODE_8 | NFC_V3_CONFIG2_PS_MASK); + tmp |= NFC_V3_CONFIG2_ONE_CYCLE; + + if (host->pagesize_2k) { + tmp |= NFC_V3_CONFIG2_SPAS(64/2); + tmp |= NFC_V3_CONFIG2_PS_2048; + } else { + tmp |= NFC_V3_CONFIG2_SPAS(16/2); + tmp |= NFC_V3_CONFIG2_PS_512; + } + + writenfc(tmp, &host->ip_regs->config2); + + tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) | + NFC_V3_CONFIG3_NO_SDMA | + NFC_V3_CONFIG3_RBB_MODE | + NFC_V3_CONFIG3_SBB(6) | /* Reset default */ + NFC_V3_CONFIG3_ADD_OP(0); + + if (!(this->options & NAND_BUSWIDTH_16)) + tmp |= NFC_V3_CONFIG3_FW8; + + writenfc(tmp, &host->ip_regs->config3); + + writenfc(0, &host->ip_regs->delay_line); +#endif
return 0; } diff --git u-boot-imx-88e73dd.orig/include/fsl_nfc.h u-boot-imx-88e73dd/include/fsl_nfc.h index ff537b4..48a6448 100644 --- u-boot-imx-88e73dd.orig/include/fsl_nfc.h +++ u-boot-imx-88e73dd/include/fsl_nfc.h @@ -33,7 +33,8 @@ * to support up to 2K byte pagesize nand. * Reading or writing a 2K page requires 4 FDI/FDO cycles. * - * MX25 and MX35 have version 2.1, which has: + * MX25 and MX35 have version 2.1, and MX51 and MX53 have version 3.2, which + * have: * 8 512-byte main buffers and * 8 64-byte spare buffers * to support up to 4K byte pagesize nand. @@ -44,20 +45,29 @@ #define MXC_NFC_V1 #define is_mxc_nfc_1() 1 #define is_mxc_nfc_21() 0 +#define is_mxc_nfc_32() 0 #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) #define MXC_NFC_V2_1 #define is_mxc_nfc_1() 0 #define is_mxc_nfc_21() 1 +#define is_mxc_nfc_32() 0 +#elif defined(CONFIG_MX51) || defined(CONFIG_MX53) +#define MXC_NFC_V3 +#define MXC_NFC_V3_2 +#define is_mxc_nfc_1() 0 +#define is_mxc_nfc_21() 0 +#define is_mxc_nfc_32() 1 #else #error "MXC NFC implementation not supported" #endif +#define is_mxc_nfc_3() is_mxc_nfc_32()
#if defined(MXC_NFC_V1) #define NAND_MXC_NR_BUFS 4 #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 #define NAND_MXC_2K_MULTI_CYCLE -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 @@ -110,61 +120,106 @@ struct fsl_nfc_regs { u16 unlockend_blkaddr2; u16 unlockstart_blkaddr3; u16 unlockend_blkaddr3; +#elif defined(MXC_NFC_V3_2) + u32 flash_cmd; + u32 flash_addr[12]; + u32 config1; + u32 ecc_status_result; + u32 status_sum; + u32 launch; #endif };
-/* - * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register for Command - * operation - */ -#define NFC_CMD 0x1 +#ifdef MXC_NFC_V3_2 +struct fsl_nfc_ip_regs { + u32 wrprot; + u32 wrprot_unlock_blkaddr[8]; + u32 config2; + u32 config3; + u32 ipc; + u32 err_addr; + u32 delay_line; +}; +#endif
-/* - * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register for Address - * operation - */ -#define NFC_ADDR 0x2 +/* Set FCMD to 1, rest to 0 for Command operation */ +#define NFC_CMD 0x1
-/* - * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register for Input - * operation - */ -#define NFC_INPUT 0x4 +/* Set FADD to 1, rest to 0 for Address operation */ +#define NFC_ADDR 0x2
-/* - * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register for Data - * Output operation - */ -#define NFC_OUTPUT 0x8 +/* Set FDI to 1, rest to 0 for Input operation */ +#define NFC_INPUT 0x4
-/* - * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register for Read ID - * operation - */ -#define NFC_ID 0x10 +/* Set FDO to 001, rest to 0 for Data Output operation */ +#define NFC_OUTPUT 0x8
-/* - * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register for Read - * Status operation - */ -#define NFC_STATUS 0x20 +/* Set FDO to 010, rest to 0 for Read ID operation */ +#define NFC_ID 0x10
-/* - * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read Status - * operation - */ -#define NFC_INT 0x8000 +/* Set FDO to 100, rest to 0 for Read Status operation */ +#define NFC_STATUS 0x20 + +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +#define NFC_CONFIG1_SP_EN (1 << 2) +#define NFC_CONFIG1_RST (1 << 6) +#define NFC_CONFIG1_CE (1 << 7) +#elif defined(MXC_NFC_V3_2) +#define NFC_CONFIG1_SP_EN (1 << 0) +#define NFC_CONFIG1_CE (1 << 1) +#define NFC_CONFIG1_RST (1 << 2) +#endif +#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3) +#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4) +#define NFC_V1_V2_CONFIG1_BIG (1 << 5) +#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0) +#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) +#define NFC_V2_CONFIG1_FP_INT (1 << 11) +#define NFC_V3_CONFIG1_RBA_MASK (0x7 << 4) +#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7) << 4) + +#define NFC_V1_V2_CONFIG2_INT (1 << 15) +#define NFC_V3_CONFIG2_PS_MASK (0x3 << 0) +#define NFC_V3_CONFIG2_PS_512 (0 << 0) +#define NFC_V3_CONFIG2_PS_2048 (1 << 0) +#define NFC_V3_CONFIG2_PS_4096 (2 << 0) +#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2) +#define NFC_V3_CONFIG2_ECC_EN (1 << 3) +#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4) +#define NFC_V3_CONFIG2_NUM_ADDR_PH0 (1 << 5) +#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6) +#define NFC_V3_CONFIG2_PPB_MASK (0x3 << 7) +#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7) +#define NFC_V3_CONFIG2_EDC_MASK (0x7 << 9) +#define NFC_V3_CONFIG2_EDC(x) (((x) & 0x7) << 9) +#define NFC_V3_CONFIG2_NUM_ADDR_PH1(x) (((x) & 0x3) << 12) +#define NFC_V3_CONFIG2_INT_MSK (1 << 15) +#define NFC_V3_CONFIG2_SPAS_MASK (0xff << 16) +#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16) +#define NFC_V3_CONFIG2_ST_CMD_MASK (0xff << 24) +#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24) + +#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0) +#define NFC_V3_CONFIG3_FW8 (1 << 3) +#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8) +#define NFC_V3_CONFIG3_NUM_OF_DEVS(x) (((x) & 0x7) << 12) +#define NFC_V3_CONFIG3_RBB_MODE (1 << 15) +#define NFC_V3_CONFIG3_NO_SDMA (1 << 20) + +#define NFC_V3_WRPROT_UNLOCK (1 << 2) +#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6) + +#define NFC_V3_IPC_CREQ (1 << 0) +#define NFC_V3_IPC_INT (1 << 31)
-#ifdef MXC_NFC_V2_1 -#define NFC_4_8N_ECC (1 << 0) +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +#define operation config2 +#define readnfc readw +#define writenfc writew +#elif defined(MXC_NFC_V3_2) +#define operation launch +#define readnfc readl +#define writenfc writel #endif -#define NFC_SP_EN (1 << 2) -#define NFC_ECC_EN (1 << 3) -#define NFC_INT_MSK (1 << 4) -#define NFC_BIG (1 << 5) -#define NFC_RST (1 << 6) -#define NFC_CE (1 << 7) -#define NFC_ONE_CYCLE (1 << 8) -#define NFC_FP_INT (1 << 11)
#endif /* __FSL_NFC_H */ diff --git u-boot-imx-88e73dd.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-imx-88e73dd/nand_spl/nand_boot_fsl_nfc.c index a40c998..1096727 100644 --- u-boot-imx-88e73dd.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-imx-88e73dd/nand_spl/nand_boot_fsl_nfc.c @@ -30,64 +30,117 @@ #include <asm/io.h> #include <fsl_nfc.h>
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR; +#elif defined(MXC_NFC_V3_2) +static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR_AXI; +static struct fsl_nfc_ip_regs *const nfc_ip = (void *)NFC_BASE_ADDR; +#endif
static void nfc_wait_ready(void) { uint32_t tmp;
- while (!(readw(&nfc->config2) & NFC_INT)) +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + while (!(readnfc(&nfc->config2) & NFC_V1_V2_CONFIG2_INT)) ;
/* Reset interrupt flag */ - tmp = readw(&nfc->config2); - tmp &= ~NFC_INT; - writew(tmp, &nfc->config2); + tmp = readnfc(&nfc->config2); + tmp &= ~NFC_V1_V2_CONFIG2_INT; + writenfc(tmp, &nfc->config2); +#elif defined(MXC_NFC_V3_2) + while (!(readnfc(&nfc_ip->ipc) & NFC_V3_IPC_INT)) + ; + + /* Reset interrupt flag */ + tmp = readnfc(&nfc_ip->ipc); + tmp &= ~NFC_V3_IPC_INT; + writenfc(tmp, &nfc_ip->ipc); +#endif }
static void nfc_nand_init(void) { -#if defined(MXC_NFC_V2_1) +#if defined(MXC_NFC_V3_2) + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int tmp; + + tmp = (readnfc(&nfc_ip->config2) & ~(NFC_V3_CONFIG2_SPAS_MASK | + NFC_V3_CONFIG2_EDC_MASK | NFC_V3_CONFIG2_PS_MASK)) | + NFC_V3_CONFIG2_SPAS(CONFIG_SYS_NAND_SPARE_SIZE / 2) | + NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_ECC_EN | + NFC_V3_CONFIG2_ONE_CYCLE; + if (CONFIG_SYS_NAND_PAGE_SIZE == 4096) + tmp |= NFC_V3_CONFIG2_PS_4096; + else if (CONFIG_SYS_NAND_PAGE_SIZE == 2048) + tmp |= NFC_V3_CONFIG2_PS_2048; + else if (CONFIG_SYS_NAND_PAGE_SIZE == 512) + tmp |= NFC_V3_CONFIG2_PS_512; + /* + * if spare size is larger that 16 bytes per 512 byte hunk + * then use 8 symbol correction instead of 4 + */ + if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) + tmp |= NFC_V3_CONFIG2_ECC_MODE_8; + else + tmp &= ~NFC_V3_CONFIG2_ECC_MODE_8; + writenfc(tmp, &nfc_ip->config2); + + tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) | + NFC_V3_CONFIG3_NO_SDMA | + NFC_V3_CONFIG3_RBB_MODE | + NFC_V3_CONFIG3_SBB(6) | /* Reset default */ + NFC_V3_CONFIG3_ADD_OP(0); +#ifndef CONFIG_SYS_NAND_BUSWIDTH_16 + tmp |= NFC_V3_CONFIG3_FW8; +#endif + writenfc(tmp, &nfc_ip->config3); + + writenfc(0, &nfc_ip->delay_line); +#elif defined(MXC_NFC_V2_1) int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int config1;
- writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size); + writenfc(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size);
/* unlocking RAM Buff */ - writew(0x2, &nfc->config); + writenfc(0x2, &nfc->config);
/* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | - NFC_ONE_CYCLE | NFC_FP_INT; + config1 = readnfc(&nfc->config1) | NFC_V1_V2_CONFIG1_ECC_EN | + NFC_V1_V2_CONFIG1_INT_MSK | NFC_V2_CONFIG1_ONE_CYCLE | + NFC_V2_CONFIG1_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 */ if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) - config1 &= ~NFC_4_8N_ECC; + config1 &= ~NFC_V2_CONFIG1_ECC_MODE_4; else - config1 |= NFC_4_8N_ECC; - writew(config1, &nfc->config1); + config1 |= NFC_V2_CONFIG1_ECC_MODE_4; + writenfc(config1, &nfc->config1); #elif defined(MXC_NFC_V1) /* unlocking RAM Buff */ - writew(0x2, &nfc->config); + writenfc(0x2, &nfc->config);
/* hardware ECC checking and correct */ - writew(NFC_ECC_EN | NFC_INT_MSK, &nfc->config1); + writenfc(NFC_V1_V2_CONFIG1_ECC_EN | NFC_V1_V2_CONFIG1_INT_MSK, + &nfc->config1); #endif }
static void nfc_nand_command(unsigned short command) { - writew(command, &nfc->flash_cmd); - writew(NFC_CMD, &nfc->config2); + writenfc(command, &nfc->flash_cmd); + writenfc(NFC_CMD, &nfc->operation); nfc_wait_ready(); }
static void nfc_nand_address(unsigned short address) { - writew(address, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); + writenfc(address, &nfc->flash_addr); + writenfc(NFC_ADDR, &nfc->operation); nfc_wait_ready(); }
@@ -121,8 +174,14 @@ static void nfc_nand_data_output(void) int i; #endif
- writew(0, &nfc->buf_addr); - writew(NFC_OUTPUT, &nfc->config2); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(0, &nfc->buf_addr); +#elif defined(MXC_NFC_V3_2) + int config1 = readnfc(&nfc->config1); + config1 &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(config1, &nfc->config1); +#endif + writenfc(NFC_OUTPUT, &nfc->operation); nfc_wait_ready(); #ifdef NAND_MXC_2K_MULTI_CYCLE /* @@ -130,8 +189,8 @@ static void nfc_nand_data_output(void) * for pages larger than 512 bytes. */ for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { - writew(i, &nfc->buf_addr); - writew(NFC_OUTPUT, &nfc->config2); + writenfc(i, &nfc->buf_addr); + writenfc(NFC_OUTPUT, &nfc->operation); nfc_wait_ready(); } #endif @@ -142,7 +201,7 @@ static int nfc_nand_check_ecc(void) #if defined(MXC_NFC_V1) u16 ecc_status = readw(&nfc->ecc_status_result); return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2; -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) u32 ecc_status = readl(&nfc->ecc_status_result); int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int err_limit = CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16 ? 8 : 4; @@ -160,7 +219,14 @@ static int nfc_nand_check_ecc(void)
static void nfc_nand_read_page(unsigned int page_address) { - writew(0, &nfc->buf_addr); /* read in first 0 buffer */ + /* read in first 0 buffer */ +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(0, &nfc->buf_addr); +#elif defined(MXC_NFC_V3_2) + int config1 = readnfc(&nfc->config1); + config1 &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(config1, &nfc->config1); +#endif nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page_address);

On 08/21/2012 04:04 PM, Benoît Thébaudeau wrote:
diff --git u-boot-imx-88e73dd.orig/nand_spl/nand_boot_fsl_nfc.c u-boot-imx-88e73dd/nand_spl/nand_boot_fsl_nfc.c index a40c998..1096727 100644 --- u-boot-imx-88e73dd.orig/nand_spl/nand_boot_fsl_nfc.c +++ u-boot-imx-88e73dd/nand_spl/nand_boot_fsl_nfc.c @@ -30,64 +30,117 @@ #include <asm/io.h> #include <fsl_nfc.h>
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR; +#elif defined(MXC_NFC_V3_2) +static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR_AXI; +static struct fsl_nfc_ip_regs *const nfc_ip = (void *)NFC_BASE_ADDR; +#endif
Please migrate to the new SPL.
- tmp = (readnfc(&nfc_ip->config2) & ~(NFC_V3_CONFIG2_SPAS_MASK |
NFC_V3_CONFIG2_EDC_MASK | NFC_V3_CONFIG2_PS_MASK)) |
NFC_V3_CONFIG2_SPAS(CONFIG_SYS_NAND_SPARE_SIZE / 2) |
NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_ECC_EN |
NFC_V3_CONFIG2_ONE_CYCLE;
CONFIG_SYS_NAND_SPARE_SIZE needs to go in the README.
-Scott

On Tue, Aug 21, 2012 at 11:04:14PM +0200, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Changes for v2:
- Fix warning for unused tmp variable in board_nand_init() for NFC V1.
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 219 +++++++++++++++----- .../include/fsl_nfc.h | 149 ++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 365 insertions(+), 126 deletions(-)
Unless Tom or Wolfgang object, I'm inclined to drop the objection to adding new hardware support to nand_spl in this case. I'd rather see the support be merged rather than ignored because a contributor has time for a small job but not a large one. Plus, this code will likely be reused by the new SPL support, if this platform is space constrained, so it's not dead-end effort.
It would be nice, though, if the writenfc/readnfc conversion, comment reformatting, etc. were separate from the behavioral changes.
-Scott

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 09/17/12 17:36, Scott Wood wrote:
On Tue, Aug 21, 2012 at 11:04:14PM +0200, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- Changes for v2: - Fix warning for unused tmp variable in board_nand_init() for NFC V1.
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 219 +++++++++++++++----- .../include/fsl_nfc.h | 149 ++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 365 insertions(+), 126 deletions(-)
Unless Tom or Wolfgang object, I'm inclined to drop the objection to adding new hardware support to nand_spl in this case. I'd rather see the support be merged rather than ignored because a contributor has time for a small job but not a large one. Plus, this code will likely be reused by the new SPL support, if this platform is space constrained, so it's not dead-end effort.
I'm OK with pulling this in while providing an on-the-record prod to please find some time to do a conversion or two in time for v2013.01.
- -- Tom

On 09/18/2012 01:11:21 PM, Tom Rini wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 09/17/12 17:36, Scott Wood wrote:
On Tue, Aug 21, 2012 at 11:04:14PM +0200, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- Changes for v2: - Fix warning for unused tmp variable in board_nand_init() for NFC V1.
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 219 +++++++++++++++----- .../include/fsl_nfc.h | 149 ++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 365 insertions(+), 126 deletions(-)
Unless Tom or Wolfgang object, I'm inclined to drop the objection to adding new hardware support to nand_spl in this case. I'd rather see the support be merged rather than ignored because a contributor has time for a small job but not a large one. Plus, this code will likely be reused by the new SPL support, if this platform is space constrained, so it's not dead-end effort.
I'm OK with pulling this in while providing an on-the-record prod to please find some time to do a conversion or two in time for v2013.01.
I'm going to leave this one until there's a config added that uses it, so that we at least get compile-testing.
-Scott

Hi Scott,
On Thursday, November 15, 2012 11:22:03 PM, Scott Wood wrote:
On 09/18/2012 01:11:21 PM, Tom Rini wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 09/17/12 17:36, Scott Wood wrote:
On Tue, Aug 21, 2012 at 11:04:14PM +0200, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de --- Changes for v2: - Fix warning for unused tmp variable in board_nand_init() for NFC V1.
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 219 +++++++++++++++----- .../include/fsl_nfc.h | 149 ++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 365 insertions(+), 126 deletions(-)
Unless Tom or Wolfgang object, I'm inclined to drop the objection to adding new hardware support to nand_spl in this case. I'd rather see the support be merged rather than ignored because a contributor has time for a small job but not a large one. Plus, this code will likely be reused by the new SPL support, if this platform is space constrained, so it's not dead-end effort.
I'm OK with pulling this in while providing an on-the-record prod to please find some time to do a conversion or two in time for v2013.01.
I'm going to leave this one until there's a config added that uses it, so that we at least get compile-testing.
OK.
I won't be able to add my i.MX51 board to mainline before at least a few months.
It's hard to find the schematics of all the i.MX5 boards supported by mainline U-Boot. According to the links below, at least the Genesi EFIKA MX Smartbook and the Freescale MX53 ARD boards have embedded NAND. Matt, Fabio, is it possible to find the schematics of these boards somewhere? http://www.genesi-tech.com/products/smartbook https://community.freescale.com/thread/289468
The EFIKA MX Smartbook probably has MLC if we consider its NAND size. 4-kiB pages should be supported by nand_spl/nand_boot_fsl_nfc.c, but not yet by drivers/mtd/nand/mxc_nand.c. The latter currently has a CONFIG_SYS_NAND_LARGEPAGE to differentiate 512-B and 2-kiB pages. If we were to add support for 4-kiB pages to this driver, I think that this should be replaced with a CONFIG_SYS_NAND_PAGE_SIZE like in nand_boot_fsl_nfc.c. Do you agree?
Best regards, Benoît

On 11/16/2012 02:15:33 PM, Benoît Thébaudeau wrote:
The EFIKA MX Smartbook probably has MLC if we consider its NAND size. 4-kiB pages should be supported by nand_spl/nand_boot_fsl_nfc.c, but not yet by drivers/mtd/nand/mxc_nand.c. The latter currently has a CONFIG_SYS_NAND_LARGEPAGE to differentiate 512-B and 2-kiB pages. If we were to add support for 4-kiB pages to this driver, I think that this should be replaced with a CONFIG_SYS_NAND_PAGE_SIZE like in nand_boot_fsl_nfc.c. Do you agree?
Yes.
-Scott

On 11/16/2012 02:18:51 PM, Scott Wood wrote:
On 11/16/2012 02:15:33 PM, Benoît Thébaudeau wrote:
The EFIKA MX Smartbook probably has MLC if we consider its NAND size. 4-kiB pages should be supported by nand_spl/nand_boot_fsl_nfc.c, but not yet by drivers/mtd/nand/mxc_nand.c. The latter currently has a CONFIG_SYS_NAND_LARGEPAGE to differentiate 512-B and 2-kiB pages. If we were to add support for 4-kiB pages to this driver, I think that this should be replaced with a CONFIG_SYS_NAND_PAGE_SIZE like in nand_boot_fsl_nfc.c. Do you agree?
Yes.
...or use the runtime detection if practical.
-Scott

On Friday, November 16, 2012 9:15:33 PM, Benoît Thébaudeau wrote:
Hi Scott,
On Thursday, November 15, 2012 11:22:03 PM, Scott Wood wrote:
On 09/18/2012 01:11:21 PM, Tom Rini wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 09/17/12 17:36, Scott Wood wrote:
On Tue, Aug 21, 2012 at 11:04:14PM +0200, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood
scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Changes for v2: - Fix warning for unused tmp variable in board_nand_init() for NFC V1.
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 219 +++++++++++++++----- .../include/fsl_nfc.h | 149 ++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 365 insertions(+), 126 deletions(-)
Unless Tom or Wolfgang object, I'm inclined to drop the objection to adding new hardware support to nand_spl in this case. I'd rather see the support be merged rather than ignored because a contributor has time for a small job but not a large one. Plus, this code will likely be reused by the new SPL support, if this platform is space constrained, so it's not dead-end effort.
I'm OK with pulling this in while providing an on-the-record prod to please find some time to do a conversion or two in time for v2013.01.
I'm going to leave this one until there's a config added that uses it, so that we at least get compile-testing.
OK.
I won't be able to add my i.MX51 board to mainline before at least a few months.
It's hard to find the schematics of all the i.MX5 boards supported by mainline U-Boot. According to the links below, at least the Genesi EFIKA MX Smartbook and the Freescale MX53 ARD boards have embedded NAND. Matt, Fabio, is it possible to find the schematics of these boards somewhere? http://www.genesi-tech.com/products/smartbook https://community.freescale.com/thread/289468
The EFIKA MX Smartbook probably has MLC if we consider its NAND size. 4-kiB pages should be supported by nand_spl/nand_boot_fsl_nfc.c, but not yet by drivers/mtd/nand/mxc_nand.c. The latter currently has a CONFIG_SYS_NAND_LARGEPAGE to differentiate 512-B and 2-kiB pages. If we were to add support for 4-kiB pages to this driver, I think that this should be replaced with a CONFIG_SYS_NAND_PAGE_SIZE like in nand_boot_fsl_nfc.c. Do you agree?
Also, I've noticed that some of the oobfree fields of the nand_ecclayout structures in mxc_nand.c are slightly different from what can be found in Linux. Any idea about which one is correct (if any)?
This field does not even always start at offset 0 when it looks free according to the ECC info. Is this normal?
Best regards, Benoît

On 11/16/2012 02:28:16 PM, Benoît Thébaudeau wrote:
Also, I've noticed that some of the oobfree fields of the nand_ecclayout structures in mxc_nand.c are slightly different from what can be found in Linux. Any idea about which one is correct (if any)?
Unless there's an obvious error such as overlap with ECC or a bad block marker, there isn't really a right answer (except to the extent that you're wasting bytes) -- but it's important that everyone agree. So the answer is basically, "which compatibility would it hurt more to break?"
That said, the U-Boot ones make more sense to me in terms of not having strange missing bytes.
This field does not even always start at offset 0 when it looks free according to the ECC info. Is this normal?
Yes. Bad block markers are at offset zero except on 8-bit 512b-page chips.
-Scott

Hi Scott,
On Saturday, November 17, 2012 1:01:03 AM, Scott Wood wrote:
On 11/16/2012 02:28:16 PM, Benoît Thébaudeau wrote:
Also, I've noticed that some of the oobfree fields of the nand_ecclayout structures in mxc_nand.c are slightly different from what can be found in Linux. Any idea about which one is correct (if any)?
Unless there's an obvious error such as overlap with ECC or a bad block marker, there isn't really a right answer (except to the extent that you're wasting bytes) -- but it's important that everyone agree. So the answer is basically, "which compatibility would it hurt more to break?"
That said, the U-Boot ones make more sense to me in terms of not having strange missing bytes.
I've just found this commit, which explains what's going on: http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h...
It looks like Linux is correct here because each structure is used for both 8- and 16-bit NFs, which seem to have different locations for bad block markers.
This fix is also missing from U-Boot: http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h... It would help to drop some of the pagesize_2k that are weirdly mixed with writesize.
Best regards, Benoît

On 11/16/2012 07:43:03 PM, Benoît Thébaudeau wrote:
Hi Scott,
On Saturday, November 17, 2012 1:01:03 AM, Scott Wood wrote:
On 11/16/2012 02:28:16 PM, Benoît Thébaudeau wrote:
Also, I've noticed that some of the oobfree fields of the nand_ecclayout structures in mxc_nand.c are slightly different from what can be found in Linux. Any idea about which one is correct (if any)?
Unless there's an obvious error such as overlap with ECC or a bad block marker, there isn't really a right answer (except to the extent that you're wasting bytes) -- but it's important that everyone agree. So the answer is basically, "which compatibility would it hurt more to break?"
That said, the U-Boot ones make more sense to me in terms of not having strange missing bytes.
I've just found this commit, which explains what's going on: http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h...
I don't understand the bit about "on 16bit flashes it is on byte 11" -- I thought with 16-bit NAND the bad block marker was always at offset zero, even on small-page NAND.
-Scott

On Wednesday, November 21, 2012 12:03:47 AM, Scott Wood wrote:
On 11/16/2012 07:43:03 PM, Benoît Thébaudeau wrote:
Hi Scott,
On Saturday, November 17, 2012 1:01:03 AM, Scott Wood wrote:
On 11/16/2012 02:28:16 PM, Benoît Thébaudeau wrote:
Also, I've noticed that some of the oobfree fields of the nand_ecclayout structures in mxc_nand.c are slightly different from what can be found in Linux. Any idea about which one is correct (if any)?
Unless there's an obvious error such as overlap with ECC or a bad block marker, there isn't really a right answer (except to the extent that you're wasting bytes) -- but it's important that everyone agree. So the answer is basically, "which compatibility would it hurt more to break?"
That said, the U-Boot ones make more sense to me in terms of not having strange missing bytes.
I've just found this commit, which explains what's going on: http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commitdiff;h...
I don't understand the bit about "on 16bit flashes it is on byte 11"
I thought with 16-bit NAND the bad block marker was always at offset zero, even on small-page NAND.
Indeed, you're right. After having seen this comment, I've looked for 16-bit NANDs with a bad block marker on byte 11, but haven't found any. However, for NFC v1 (e.g. i.MX31's), the reference manual gives this position for bad block information for 16-bit spare area layout. I don't know why. This is really weird. And the RM also says not to use this byte as general purpose, just like ECC bytes, as if it were used by the NFC itself. Even if some NANDs exist somewhere using this offset, they're far from being the most common, so I don't know why the reference manual would mention this byte and not bytes 0 and 1.
Best regards, Benoît

On Fri, Nov 16, 2012 at 6:15 PM, Benoît Thébaudeau benoit.thebaudeau@advansee.com wrote:
It's hard to find the schematics of all the i.MX5 boards supported by mainline U-Boot. According to the links below, at least the Genesi EFIKA MX Smartbook and the Freescale MX53 ARD boards have embedded NAND. Matt, Fabio, is it possible to find the schematics of these boards somewhere?
Yes, will send you offline.
Regards,
Fabio Estevam

Hi Benoit,
Just a FYI the Efika MX products use PATA devices (Sandisk pSSD-P2 or similar) so it's not a good test. We do have an MX53 board with NAND on the NFC - but we're sticking with Freescale's BSP U-Boot for the time being on that particular product. If I can schedule some time for it I will test it.
Matt Sealey matt@genesi-usa.com Product Development Analyst, Genesi USA, Inc.
On Sat, Nov 17, 2012 at 12:37 PM, Fabio Estevam festevam@gmail.com wrote:
On Fri, Nov 16, 2012 at 6:15 PM, Benoît Thébaudeau benoit.thebaudeau@advansee.com wrote:
It's hard to find the schematics of all the i.MX5 boards supported by
mainline
U-Boot. According to the links below, at least the Genesi EFIKA MX
Smartbook and
the Freescale MX53 ARD boards have embedded NAND. Matt, Fabio, is it
possible to
find the schematics of these boards somewhere?
Yes, will send you offline.
Regards,
Fabio Estevam _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

On Tue, Aug 21, 2012 at 11:04:14PM +0200, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Changes for v2:
- Fix warning for unused tmp variable in board_nand_init() for NFC V1.
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 219 +++++++++++++++----- .../include/fsl_nfc.h | 149 ++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 365 insertions(+), 126 deletions(-)
Is there a board that uses this?
-Scott

Hi Scott,
On Tuesday, September 18, 2012 3:01:58 AM, Scott Wood wrote:
On Tue, Aug 21, 2012 at 11:04:14PM +0200, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Scott Wood scottwood@freescale.com Cc: Stefano Babic sbabic@denx.de
Changes for v2:
- Fix warning for unused tmp variable in board_nand_init() for NFC
V1.
.../arch/arm/include/asm/arch-mx5/imx-regs.h | 9 + .../drivers/mtd/nand/mxc_nand.c | 219 +++++++++++++++----- .../include/fsl_nfc.h | 149 ++++++++----- .../nand_spl/nand_boot_fsl_nfc.c | 114 +++++++--- 4 files changed, 365 insertions(+), 126 deletions(-)
Is there a board that uses this?
I have one, but it's not yet ready for mainline.
Some of the current mx51 and mx53 mainline boards could also probably use that as an alternate boot option, but I don't have them to test.
Best regards, Benoît

On Mon, Aug 13, 2012 at 10:47:56PM +0200, Benoît Thébaudeau wrote:
Hi all,
This series aims at adding support for i.MX5 to the mxc nand mtd and spl drivers. It also fixes several issues and cleans up the code a little bit.
Applied patches 1-12 to u-boot-nand-flash. For patch 13 I'm waiting to see what Tom says, and for an answer regarding what board uses this (i.e. how can I build-test it?).
-Scott

Dear Benoît Thébaudeau,
Hi all,
This series aims at adding support for i.MX5 to the mxc nand mtd and spl drivers. It also fixes several issues and cleans up the code a little bit.
Best regards, Benoît
Did this patchset advance any further? Any chance we can see this applied? Anything I can help with to make it applied?
Best regards, Marek Vasut

Dear Marek Vasut,
On Monday, January 7, 2013 2:02:47 PM, Marek Vasut wrote:
Dear Benoît Thébaudeau,
Hi all,
This series aims at adding support for i.MX5 to the mxc nand mtd and spl drivers. It also fixes several issues and cleans up the code a little bit.
Best regards, Benoît
Did this patchset advance any further? Any chance we can see this applied? Anything I can help with to make it applied?
Only 13/13 has not yet been applied. I still have to add NFC support to one i.MX5 board for the patch to be accepted. Fabio has confirmed that mx53ard would be fine.
Fabio, can you give me the reference of the NAND Flash that you will use for testing on i.MX53? That will allow me to adjust the NFC clock and to know if I also have to add support for 4-kiB pages or multi-CS.
Marek, I hope to find some time soon to finish this, but if you can work on the remaining tasks, that's also fine with me. Thanks.
Best regards, Benoît

Dear Benoît Thébaudeau,
Dear Marek Vasut,
On Monday, January 7, 2013 2:02:47 PM, Marek Vasut wrote:
Dear Benoît Thébaudeau,
Hi all,
This series aims at adding support for i.MX5 to the mxc nand mtd and spl drivers. It also fixes several issues and cleans up the code a little bit.
Best regards, Benoît
Did this patchset advance any further? Any chance we can see this applied? Anything I can help with to make it applied?
Only 13/13 has not yet been applied. I still have to add NFC support to one i.MX5 board for the patch to be accepted. Fabio has confirmed that mx53ard would be fine.
Sigh ... I have board with NAND pending, so Scott, please apply.
Fabio, can you give me the reference of the NAND Flash that you will use for testing on i.MX53? That will allow me to adjust the NFC clock and to know if I also have to add support for 4-kiB pages or multi-CS.
Marek, I hope to find some time soon to finish this, but if you can work on the remaining tasks, that's also fine with me. Thanks.
I'll test it in a bit.
Best regards, Benoît
Best regards, Marek Vasut

On 01/07/2013 07:47:12 AM, Marek Vasut wrote:
Dear Benoît Thébaudeau,
Dear Marek Vasut,
On Monday, January 7, 2013 2:02:47 PM, Marek Vasut wrote:
Dear Benoît Thébaudeau,
Hi all,
This series aims at adding support for i.MX5 to the mxc nand mtd and spl drivers. It also fixes several issues and cleans up the code a little bit.
Best regards, Benoît
Did this patchset advance any further? Any chance we can see this applied? Anything I can help with to make it applied?
Only 13/13 has not yet been applied. I still have to add NFC
support to one
i.MX5 board for the patch to be accepted. Fabio has confirmed that
mx53ard
would be fine.
Sigh ... I have board with NAND pending, so Scott, please apply.
Can you repost it as part of a patchset with that board, and I'll ack so they can go together?
Does this board do NAND boot? If so, new-SPL rather than nand_spl would be nice. Tom's comment at the time was, "I'm OK with pulling this in while providing an on-the-record prod to please find some time to do a conversion or two in time for v2013.01." If this patch is applied now, it would be for the release after v2013.01...
-Scott

Dear Scott Wood,
On 01/07/2013 07:47:12 AM, Marek Vasut wrote:
Dear Benoît Thébaudeau,
Dear Marek Vasut,
On Monday, January 7, 2013 2:02:47 PM, Marek Vasut wrote:
Dear Benoît Thébaudeau,
Hi all,
This series aims at adding support for i.MX5 to the mxc nand mtd and spl drivers. It also fixes several issues and cleans up the code a little bit.
Best regards, Benoît
Did this patchset advance any further? Any chance we can see this applied? Anything I can help with to make it applied?
Only 13/13 has not yet been applied. I still have to add NFC
support to one
i.MX5 board for the patch to be accepted. Fabio has confirmed that
mx53ard
would be fine.
Sigh ... I have board with NAND pending, so Scott, please apply.
Can you repost it as part of a patchset with that board, and I'll ack so they can go together?
I found an issue with the patch, so will do.
Does this board do NAND boot?
No, boots from other means.
If so, new-SPL rather than nand_spl would be nice. Tom's comment at the time was, "I'm OK with pulling this in while providing an on-the-record prod to please find some time to do a conversion or two in time for v2013.01." If this patch is applied now, it would be for the release after v2013.01...
No prob.
-Scott
Best regards, Marek Vasut

Hi Benoît,
On Mon, Jan 7, 2013 at 11:37 AM, Benoît Thébaudeau benoit.thebaudeau@advansee.com wrote:
Fabio, can you give me the reference of the NAND Flash that you will use for testing on i.MX53? That will allow me to adjust the NFC clock and to know if I also have to add support for 4-kiB pages or multi-CS.
The NAND I have is a K9LAG08U0M.
Thanks,
Fabio Estevam

Dear Fabio Estevam,
Hi Benoît,
On Mon, Jan 7, 2013 at 11:37 AM, Benoît Thébaudeau
benoit.thebaudeau@advansee.com wrote:
Fabio, can you give me the reference of the NAND Flash that you will use for testing on i.MX53? That will allow me to adjust the NFC clock and to know if I also have to add support for 4-kiB pages or multi-CS.
The NAND I have is a K9LAG08U0M.
Do you guys happen to have include/config/<config>.h section for the MX5 NFC ? esp. this CONFIG_MXC_NAND_IP_REGS_BASE is what I don't quite get how it fits in.
Thanks!
Best regards, Marek Vasut

Dear Marek Vasut,
On Monday, January 7, 2013 4:08:45 PM, Marek Vasut wrote:
Dear Fabio Estevam,
Hi Benoît,
On Mon, Jan 7, 2013 at 11:37 AM, Benoît Thébaudeau
benoit.thebaudeau@advansee.com wrote:
Fabio, can you give me the reference of the NAND Flash that you will use for testing on i.MX53? That will allow me to adjust the NFC clock and to know if I also have to add support for 4-kiB pages or multi-CS.
The NAND I have is a K9LAG08U0M.
Do you guys happen to have include/config/<config>.h section for the MX5 NFC ? esp. this CONFIG_MXC_NAND_IP_REGS_BASE is what I don't quite get how it fits in.
Here is this section for my custom i.MX51 board:
#define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR_AXI #define CONFIG_NAND_MXC #define CONFIG_MXC_NAND_REGS_BASE NFC_BASE_ADDR_AXI #define CONFIG_MXC_NAND_IP_REGS_BASE NFC_BASE_ADDR #define CONFIG_SYS_NAND_LARGEPAGE #define CONFIG_MXC_NAND_HWECC #define CONFIG_SYS_NAND_USE_FLASH_BBT
Best regards, Benoît

Dear Benoît Thébaudeau,
#define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR_AXI #define CONFIG_NAND_MXC #define CONFIG_MXC_NAND_REGS_BASE NFC_BASE_ADDR_AXI #define CONFIG_MXC_NAND_IP_REGS_BASE NFC_BASE_ADDR #define CONFIG_SYS_NAND_LARGEPAGE #define CONFIG_MXC_NAND_HWECC #define CONFIG_SYS_NAND_USE_FLASH_BBT
Thanks!
Best regards, Marek Vasut

Dear Benoît Thébaudeau,
Dear Marek Vasut,
On Monday, January 7, 2013 4:08:45 PM, Marek Vasut wrote:
Dear Fabio Estevam,
Hi Benoît,
On Mon, Jan 7, 2013 at 11:37 AM, Benoît Thébaudeau
benoit.thebaudeau@advansee.com wrote:
Fabio, can you give me the reference of the NAND Flash that you will use for testing on i.MX53? That will allow me to adjust the NFC clock and to know if I also have to add support for 4-kiB pages or multi-CS.
The NAND I have is a K9LAG08U0M.
Do you guys happen to have include/config/<config>.h section for the MX5 NFC ? esp. this CONFIG_MXC_NAND_IP_REGS_BASE is what I don't quite get how it fits in.
Here is this section for my custom i.MX51 board:
#define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR_AXI #define CONFIG_NAND_MXC #define CONFIG_MXC_NAND_REGS_BASE NFC_BASE_ADDR_AXI #define CONFIG_MXC_NAND_IP_REGS_BASE NFC_BASE_ADDR #define CONFIG_SYS_NAND_LARGEPAGE #define CONFIG_MXC_NAND_HWECC #define CONFIG_SYS_NAND_USE_FLASH_BBT
Benoit, not much luck with this stuff. Am I missing something else? I believe I configured pinmux, I enabled the NAND clock too. But maybe there's something else? Can you send me some patch that enables use of this NAND driver on your MX5 platform?
Best regards, Marek Vasut

Dear Marek Vasut,
On Monday, January 7, 2013 5:42:11 PM, Marek Vasut wrote:
Dear Benoît Thébaudeau,
Dear Marek Vasut,
On Monday, January 7, 2013 4:08:45 PM, Marek Vasut wrote:
Dear Fabio Estevam,
Hi Benoît,
On Mon, Jan 7, 2013 at 11:37 AM, Benoît Thébaudeau
benoit.thebaudeau@advansee.com wrote:
Fabio, can you give me the reference of the NAND Flash that you will use for testing on i.MX53? That will allow me to adjust the NFC clock and to know if I also have to add support for 4-kiB pages or multi-CS.
The NAND I have is a K9LAG08U0M.
Do you guys happen to have include/config/<config>.h section for the MX5 NFC ? esp. this CONFIG_MXC_NAND_IP_REGS_BASE is what I don't quite get how it fits in.
Here is this section for my custom i.MX51 board:
#define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR_AXI #define CONFIG_NAND_MXC #define CONFIG_MXC_NAND_REGS_BASE NFC_BASE_ADDR_AXI #define CONFIG_MXC_NAND_IP_REGS_BASE NFC_BASE_ADDR #define CONFIG_SYS_NAND_LARGEPAGE #define CONFIG_MXC_NAND_HWECC #define CONFIG_SYS_NAND_USE_FLASH_BBT
Benoit, not much luck with this stuff. Am I missing something else? I believe I configured pinmux, I enabled the NAND clock too. But maybe there's something else? Can you send me some patch that enables use of this NAND driver on your MX5 platform?
Did you check that the NFC clock frequency is compatible with your NAND Flash?
Are your running this on i.MX51 or i.MX53?
Are you booting from NAND, or are you just accessing NAND after another source of boot?
Which NAND Flash reference are you using? As I mentioned, 4-kiB pages and multi-CS are not yet supported.
Pinmux should be NFC-ready by default (at least for CS0 on i.MX51).
What did you test and what did you get?
I don't think that I have a simple patch for what you ask. Can you instead send me your patch, and I'll take a look at it?
Best regards, Benoît

Dear Benoît Thébaudeau,
Thanks for your help. I think I got it working, so I'll patch it up a bit and submit it.
Best regards, Marek Vasut
participants (8)
-
Benoît Thébaudeau
-
Fabio Estevam
-
Marek Vasut
-
Matt Sealey
-
Scott Wood
-
Stefano Babic
-
Tom Rini
-
Troy Kisky