* [U-Boot] [PATCH 1/5] mtd/nand: Add function board_nand_init_tail() for some special NAND controllers @ 2011-12-08 10:49 Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 2/5] mtd/nand: Fixup for support ONFI detect Shengzhou Liu 2011-12-08 16:35 ` [U-Boot] [PATCH 1/5] mtd/nand: Add function board_nand_init_tail() for some special NAND controllers Marek Vasut 0 siblings, 2 replies; 14+ messages in thread From: Shengzhou Liu @ 2011-12-08 10:49 UTC (permalink / raw) To: u-boot In some NAND controllers there is a size limitation of RAM buffer(2K bytes). To support large-page NAND chips with greater than 2K pagesize, we need a large buffer, but we don't know pagesize before calling nand_scan_ident(), for more flexible and to identify different cases of large-page greater than 2K bytes, we have a board_nand_init_tail() between nand_scan_ident() and nand_scan_tail(). Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> --- drivers/mtd/nand/nand.c | 19 ++++++++++++++++++- 1 files changed, 18 insertions(+), 1 deletions(-) diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c index d987f4c..800541e 100644 --- a/drivers/mtd/nand/nand.c +++ b/drivers/mtd/nand/nand.c @@ -39,6 +39,14 @@ static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIS static const char default_nand_name[] = "nand"; static __attribute__((unused)) char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8]; +int __board_nand_init_tail(struct mtd_info *mtd, struct nand_chip *nand) +{ + /* Allow for init at tail in controller-specific file for some reason */ + return 0; +} +int board_nand_init_tail(struct mtd_info *mtd, struct nand_chip *nand) +__attribute__((weak, alias("__board_nand_init_tail"))); + static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr) { @@ -51,7 +59,16 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; if (board_nand_init(nand) == 0) { - if (nand_scan(mtd, maxchips) == 0) { + if (!nand_scan_ident(mtd, maxchips, NULL)) { + if (board_nand_init_tail(mtd, nand)) { + mtd->name = NULL; + return; + } + + if (nand_scan_tail(mtd)) { + mtd->name = NULL; + return; + } if (!mtd->name) mtd->name = (char *)default_nand_name; #ifdef CONFIG_NEEDS_MANUAL_RELOC -- 1.6.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 2/5] mtd/nand: Fixup for support ONFI detect 2011-12-08 10:49 [U-Boot] [PATCH 1/5] mtd/nand: Add function board_nand_init_tail() for some special NAND controllers Shengzhou Liu @ 2011-12-08 10:49 ` Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 3/5] mtd/nand: remove CONFIG_SYS_NAND_ONFI_DETECTION to enable ONFI detection Shengzhou Liu 2011-12-08 16:35 ` [U-Boot] [PATCH 1/5] mtd/nand: Add function board_nand_init_tail() for some special NAND controllers Marek Vasut 1 sibling, 1 reply; 14+ messages in thread From: Shengzhou Liu @ 2011-12-08 10:49 UTC (permalink / raw) To: u-boot In the past the ONFI never worked dut to u-boot aborted when nand device id not found in ids table. Now if not found in ids table, u-boot still continues to detect by ONFI way. Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> --- drivers/mtd/nand/nand_base.c | 26 ++++++++++++++++---------- 1 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 6aac6a2..017ff5d 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2592,10 +2592,17 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, if (*dev_id == type->id) break; + if (!type->name || !type->pagesize) { + /* Check if chip is ONFI compliant */ + ret = nand_flash_detect_onfi(mtd, chip, &busw); + if (ret) + goto ident_done; + } + if (!type->name) { /* supress warning if there is no nand */ if (*maf_id != 0x00 && *maf_id != 0xff && - *dev_id != 0x00 && *dev_id != 0xff) + *dev_id != 0x00 && *dev_id != 0xff) printk(KERN_INFO "%s: unknown NAND device: " "Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", __func__, *maf_id, *dev_id); @@ -2608,14 +2615,19 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->chipsize = (uint64_t)type->chipsize << 20; chip->onfi_version = 0; - ret = nand_flash_detect_onfi(mtd, chip, &busw); - if (!ret) - nand_flash_detect_non_onfi(mtd, chip, type, &busw); + nand_flash_detect_non_onfi(mtd, chip, type, &busw); /* Get chip options, preserve non chip based options */ chip->options &= ~NAND_CHIPOPTIONS_MSK; chip->options |= type->options & NAND_CHIPOPTIONS_MSK; + /* Check if chip is a not a samsung device. Do not clear the + * options for chips which are not having an extended id. + */ + if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) + chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; + +ident_done: /* * Set chip as a default. Board drivers can override it, if necessary */ @@ -2657,12 +2669,6 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->badblockpos = mtd->writesize > 512 ? NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; - /* Check if chip is a not a samsung device. Do not clear the - * options for chips which are not having an extended id. - */ - if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) - chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; - /* Check for AND chips with 4 page planes */ if (chip->options & NAND_4PAGE_ARRAY) chip->erase_cmd = multi_erase_cmd; -- 1.6.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 3/5] mtd/nand: remove CONFIG_SYS_NAND_ONFI_DETECTION to enable ONFI detection 2011-12-08 10:49 ` [U-Boot] [PATCH 2/5] mtd/nand: Fixup for support ONFI detect Shengzhou Liu @ 2011-12-08 10:49 ` Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller Shengzhou Liu 0 siblings, 1 reply; 14+ messages in thread From: Shengzhou Liu @ 2011-12-08 10:49 UTC (permalink / raw) To: u-boot remove CONFIG_SYS_NAND_ONFI_DETECTION to enable ONFI detection. Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> --- drivers/mtd/nand/nand_base.c | 9 --------- include/linux/mtd/nand.h | 2 -- 2 files changed, 0 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 017ff5d..2a42a8d 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2415,7 +2415,6 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } -#ifdef CONFIG_SYS_NAND_ONFI_DETECTION static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) { int i; @@ -2493,14 +2492,6 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, return 1; } -#else -static inline int nand_flash_detect_onfi(struct mtd_info *mtd, - struct nand_chip *chip, - int *busw) -{ - return 0; -} -#endif static void nand_flash_detect_non_onfi(struct mtd_info *mtd, struct nand_chip *chip, diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 987a2ec..e61149e 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -472,9 +472,7 @@ struct nand_chip { uint8_t cellinfo; int badblockpos; int onfi_version; -#ifdef CONFIG_SYS_NAND_ONFI_DETECTION struct nand_onfi_params onfi_params; -#endif int state; -- 1.6.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller 2011-12-08 10:49 ` [U-Boot] [PATCH 3/5] mtd/nand: remove CONFIG_SYS_NAND_ONFI_DETECTION to enable ONFI detection Shengzhou Liu @ 2011-12-08 10:49 ` Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip Shengzhou Liu 2011-12-08 18:09 ` [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller Scott Wood 0 siblings, 2 replies; 14+ messages in thread From: Shengzhou Liu @ 2011-12-08 10:49 UTC (permalink / raw) To: u-boot - fix NAND_CMD_READID command for ONFI detect. - add NAND_CMD_PARAM command to read the ONFI parameter page. Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> --- drivers/mtd/nand/fsl_elbc_nand.c | 19 ++++++++++++------- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 4d1e527..52362b1 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -340,20 +340,25 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, /* READID must read all 5 possible bytes while CEB is active */ case NAND_CMD_READID: - vdbg("fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); + case NAND_CMD_PARAM: + vdbg("fsl_elbc_cmdfunc: NAND_CMD 0x%x.\n", command); out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) | (FIR_OP_UA << FIR_OP1_SHIFT) | (FIR_OP_RBW << FIR_OP2_SHIFT)); - out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); - /* 5 bytes for manuf, device and exts */ - out_be32(&lbc->fbcr, 5); - ctrl->read_bytes = 5; + out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT); + /* + * although currently it's 8 bytes for READID, we always read + * the maximum 256 bytes(for PARAM) + */ + out_be32(&lbc->fbcr, 256); + ctrl->read_bytes = 256; ctrl->use_mdr = 1; - ctrl->mdr = 0; - + ctrl->mdr = column; set_addr(mtd, 0, 0, 0); fsl_elbc_run_command(mtd); + if (mtd->writesize > 2048) + memcpy_fromio(ctrl->buffer, ctrl->addr, 256); return; /* ERASE1 stores the block and page address */ -- 1.6.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip 2011-12-08 10:49 ` [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller Shengzhou Liu @ 2011-12-08 10:49 ` Shengzhou Liu 2011-12-08 16:37 ` Marek Vasut 2011-12-08 18:09 ` [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller Scott Wood 1 sibling, 1 reply; 14+ messages in thread From: Shengzhou Liu @ 2011-12-08 10:49 UTC (permalink / raw) To: u-boot Freescale FCM controller has a 2K size limitation of buffer RAM. In order to support the Nand flash chip whose page size is larger than 2K bytes, we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB and save them to a large buffer. Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> Signed-off-by: Liu Shuo <b35362@freescale.com> --- drivers/mtd/nand/fsl_elbc_nand.c | 279 +++++++++++++++++++++++++++++++++---- 1 files changed, 248 insertions(+), 31 deletions(-) diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 52362b1..3983c8c 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -64,7 +64,6 @@ struct fsl_elbc_mtd { struct device *dev; int bank; /* Chip select bank number */ u8 __iomem *vbase; /* Chip select base virtual address */ - int page_size; /* NAND page size (0=512, 1=2048) */ unsigned int fmr; /* FCM Flash Mode Register value */ }; @@ -85,6 +84,8 @@ struct fsl_elbc_ctrl { unsigned int mdr; /* UPM/FCM Data Register value */ unsigned int use_mdr; /* Non zero if the MDR is to be set */ unsigned int oob; /* Non zero if operating on OOB data */ + char *buffer; /* just used when pagesize is greater */ + /* than FCM RAM 2K limitation */ }; /* These map to the positions used by the FCM hardware ECC generator */ @@ -159,6 +160,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { .pattern = mirror_pattern, }; +static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob) +{ + struct nand_chip *chip = mtd->priv; + struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_ctrl *ctrl = priv->ctrl; + void *src, *dst; + int len = (oob ? 64 : 2048); + + /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */ + if (oob) + dst = ctrl->buffer + mtd->writesize + subpage * 64; + else + dst = ctrl->buffer + subpage * 2048; + + src = ctrl->addr + (oob ? 2048 : 0); + memcpy_fromio(dst, src, len); +} + +static void buffer_to_io(struct mtd_info *mtd, int subpage, int oob) +{ + struct nand_chip *chip = mtd->priv; + struct fsl_elbc_mtd *priv = chip->priv; + struct fsl_elbc_ctrl *ctrl = priv->ctrl; + void *src, *dst; + int len = (oob ? 64 : 2048); + + if (oob) + src = ctrl->buffer + mtd->writesize + subpage * 64; + else + src = ctrl->buffer + subpage * 2048; + + dst = ctrl->addr + (oob ? 2048 : 0); + + memcpy_toio(dst, src, len); + /* See the in_8() in fsl_elbc_write_buf() */ + in_8(ctrl->addr); +} + /*=================================*/ /* @@ -175,7 +214,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) ctrl->page = page_addr; - if (priv->page_size) { + if (mtd->writesize >= 2048) { out_be32(&lbc->fbar, page_addr >> 6); out_be32(&lbc->fpar, ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | @@ -194,7 +233,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) /* for OOB data point to the second half of the buffer */ if (oob) - ctrl->index += priv->page_size ? 2048 : 512; + ctrl->index += mtd->writesize; vdbg("set_addr: bank=%d, ctrl->addr=0x%p (0x%p), " "index %x, pes %d ps %d\n", @@ -256,13 +295,14 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) return ctrl->status == LTESR_CC ? 0 : -EIO; } -static void fsl_elbc_do_read(struct nand_chip *chip, int oob) +static void fsl_elbc_do_read(struct mtd_info *mtd, int oob) { + struct nand_chip *chip = mtd->priv; struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_ctrl *ctrl = priv->ctrl; fsl_lbc_t *lbc = ctrl->regs; - if (priv->page_size) { + if (mtd->writesize >= 2048) { out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) | (FIR_OP_CA << FIR_OP1_SHIFT) | @@ -295,6 +335,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_ctrl *ctrl = priv->ctrl; fsl_lbc_t *lbc = ctrl->regs; + int i, nps = mtd->writesize / 2048; ctrl->use_mdr = 0; @@ -319,8 +360,27 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, ctrl->read_bytes = mtd->writesize + mtd->oobsize; ctrl->index += column; - fsl_elbc_do_read(chip, 0); + fsl_elbc_do_read(mtd, 0); fsl_elbc_run_command(mtd); + + if (mtd->writesize <= 2048) + return; + + /* Continue to read the rest bytes if writesize > 2048 */ + io_to_buffer(mtd, 0, 0); + io_to_buffer(mtd, 0, 1); + /* + * Maybe there are some reasons of FCM hardware timing, + * we must insert a FIR_OP_NOP(0x00) before FIR_OP_RB. + */ + out_be32(&lbc->fir, FIR_OP_RB << FIR_OP1_SHIFT); + + for (i = 1; i < nps; i++) { + fsl_elbc_run_command(mtd); + io_to_buffer(mtd, i, 0); + io_to_buffer(mtd, i, 1); + } + return; /* READOOB reads only the OOB because no ECC is performed. */ @@ -328,14 +388,35 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, vdbg("fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" " 0x%x, column: 0x%x.\n", page_addr, column); - out_be32(&lbc->fbcr, mtd->oobsize - column); - set_addr(mtd, column, page_addr, 1); + if (mtd->writesize <= 2048) { + out_be32(&lbc->fbcr, mtd->oobsize - column); + set_addr(mtd, column, page_addr, 1); + } else { + out_be32(&lbc->fbcr, 64); + set_addr(mtd, 0, page_addr, 1); + ctrl->index += column; + } ctrl->read_bytes = mtd->writesize + mtd->oobsize; - - fsl_elbc_do_read(chip, 1); + fsl_elbc_do_read(mtd, 1); fsl_elbc_run_command(mtd); + if (mtd->writesize <= 2048) + return; + + if (column < 64) + io_to_buffer(mtd, 0, 1); + + out_be32(&lbc->fpar, in_be32(&lbc->fpar) & ~FPAR_LP_MS); + out_be32(&lbc->fir, FIR_OP_RB << FIR_OP1_SHIFT); + out_be32(&lbc->fbcr, 2112); + + for (i = 1; i < nps; i++) { + fsl_elbc_run_command(mtd); + if (column < (64 * (i + 1))) + io_to_buffer(mtd, i, 1); + } + return; /* READID must read all 5 possible bytes while CEB is active */ @@ -395,9 +476,28 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, page_addr, column); ctrl->column = column; - ctrl->oob = 0; + if (column >= mtd->writesize) { + /* OOB area */ + column -= mtd->writesize; + ctrl->oob = 1; + } else { + ctrl->oob = 0; + } - if (priv->page_size) { + if (mtd->writesize > 2048) { + /* writesize > 2048 */ + fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | + (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | + (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT); + if (ctrl->oob) + fcr |= NAND_CMD_RNDIN << FCR_CMD0_SHIFT; + + out_be32(&lbc->fir, + (FIR_OP_CM2 << FIR_OP0_SHIFT) | + (FIR_OP_CA << FIR_OP1_SHIFT) | + (FIR_OP_PA << FIR_OP2_SHIFT) | + (FIR_OP_WB << FIR_OP3_SHIFT)); + } else if (mtd->writesize == 2048) { fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) | (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT); @@ -419,11 +519,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, (FIR_OP_WB << FIR_OP4_SHIFT) | (FIR_OP_CW1 << FIR_OP5_SHIFT)); - if (column >= mtd->writesize) { + if (ctrl->oob) { /* OOB area --> READOOB */ - column -= mtd->writesize; fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; - ctrl->oob = 1; } else if (column < 256) { /* First 256 bytes --> READ0 */ fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT; @@ -434,12 +532,19 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, } out_be32(&lbc->fcr, fcr); - set_addr(mtd, column, page_addr, ctrl->oob); + if (column >= mtd->writesize && mtd->writesize > 2048) { + /* for write oob && writesize > 2048 */ + set_addr(mtd, 0, page_addr, 0); + ctrl->index = column; + } else { + set_addr(mtd, column, page_addr, ctrl->oob); + } return; } /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ case NAND_CMD_PAGEPROG: { + int pos; vdbg("fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " "writing %d bytes.\n", ctrl->index); @@ -447,14 +552,71 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, * then set the exact length, otherwise use a full page * write so the HW generates the ECC. */ + if (ctrl->oob || ctrl->column != 0 || - ctrl->index != mtd->writesize + mtd->oobsize) - out_be32(&lbc->fbcr, ctrl->index); - else + ctrl->index != mtd->writesize + mtd->oobsize) { + if (ctrl->oob && mtd->writesize > 2048) { + out_be32(&lbc->fbcr, 64); + } else { + out_be32(&lbc->fbcr, ctrl->index - + ctrl->column); + } + } else { out_be32(&lbc->fbcr, 0); + } + + if (mtd->writesize > 2048) { + if (!ctrl->oob) + buffer_to_io(mtd, 0, 0); + buffer_to_io(mtd, 0, 1); + } fsl_elbc_run_command(mtd); + if (mtd->writesize <= 2048) + return; + + if (ctrl->oob) { + pos = 2048; + out_be32(&lbc->fir, + (FIR_OP_CM0 << FIR_OP0_SHIFT) | + (FIR_OP_UA << FIR_OP1_SHIFT) | + (FIR_OP_UA << FIR_OP2_SHIFT) | + (FIR_OP_WB << FIR_OP3_SHIFT)); + + for (i = 1; i < nps; i++) { + pos += 2112; + ctrl->mdr = pos; + ctrl->use_mdr = 1; + if (i == nps - 1) { + out_be32(&lbc->fir, + (FIR_OP_CM0 << FIR_OP1_SHIFT) | + (FIR_OP_UA << FIR_OP2_SHIFT) | + (FIR_OP_UA << FIR_OP3_SHIFT) | + (FIR_OP_WB << FIR_OP4_SHIFT) | + (FIR_OP_CM3 << FIR_OP5_SHIFT) | + (FIR_OP_CW1 << FIR_OP6_SHIFT) | + (FIR_OP_RS << FIR_OP7_SHIFT)); + } + buffer_to_io(mtd, i, 1); + fsl_elbc_run_command(mtd); + } + } else { + out_be32(&lbc->fir, FIR_OP_WB << FIR_OP1_SHIFT); + for (i = 1; i < nps; i++) { + if (i == nps - 1) { + ctrl->use_mdr = 1; + out_be32(&lbc->fir, + (FIR_OP_WB << FIR_OP1_SHIFT) | + (FIR_OP_CM3 << FIR_OP2_SHIFT) | + (FIR_OP_CW1 << FIR_OP3_SHIFT) | + (FIR_OP_RS << FIR_OP4_SHIFT)); + } + buffer_to_io(mtd, i, 0); + buffer_to_io(mtd, i, 1); + fsl_elbc_run_command(mtd); + } + } return; } @@ -475,6 +637,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, * write-protected, even when it is not. */ out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP); + ctrl->buffer[0] = in_8(ctrl->addr); return; /* RESET without waiting for the ready line */ @@ -521,7 +684,11 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) len = bufsize - ctrl->index; } - memcpy_toio(&ctrl->addr[ctrl->index], buf, len); + if (mtd->writesize > 2048) + memcpy(&ctrl->buffer[ctrl->index], buf, len); + else + memcpy_toio(&ctrl->addr[ctrl->index], buf, len); + /* * This is workaround for the weird elbc hangs during nand write, * Scott Wood says: "...perhaps difference in how long it takes a @@ -545,8 +712,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd) struct fsl_elbc_ctrl *ctrl = priv->ctrl; /* If there are still bytes in the FCM, then use the next byte. */ - if (ctrl->index < ctrl->read_bytes) - return in_8(&ctrl->addr[ctrl->index++]); + if (ctrl->index < ctrl->read_bytes) { + int index = ctrl->index++; + if (mtd->writesize > 2048) + return ctrl->buffer[index]; + else + return in_8(&ctrl->addr[index]); + } printf("read_byte beyond end of buffer\n"); return ERR_BYTE; @@ -566,7 +738,10 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) return; avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index); - memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail); + if (mtd->writesize > 2048) + memcpy(buf, &ctrl->buffer[ctrl->index], avail); + else + memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail); ctrl->index += avail; if (len > avail) @@ -600,9 +775,17 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, return -EINVAL; } - for (i = 0; i < len; i++) - if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i]) - break; + if (mtd->writesize > 2048) { + for (i = 0; i < len; i++) { + if (ctrl->buffer[ctrl->index + i] != buf[i]) + break; + } + } else { + for (i = 0; i < len; i++) { + if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i]) + break; + } + } ctrl->index += len; return i == len && ctrl->status == LTESR_CC ? 0 : -EIO; @@ -639,6 +822,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) * write-protected, even when it is not. */ out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP); + ctrl->buffer[0] = in_8(ctrl->addr); return fsl_elbc_read_byte(mtd); } @@ -668,11 +852,11 @@ static void fsl_elbc_write_page(struct mtd_info *mtd, static struct fsl_elbc_ctrl *elbc_ctrl; -static void fsl_elbc_ctrl_init(void) +static int fsl_elbc_ctrl_init(void) { elbc_ctrl = kzalloc(sizeof(*elbc_ctrl), GFP_KERNEL); if (!elbc_ctrl) - return; + return -ENOMEM; elbc_ctrl->regs = LBC_BASE_ADDR; @@ -686,6 +870,22 @@ static void fsl_elbc_ctrl_init(void) elbc_ctrl->read_bytes = 0; elbc_ctrl->index = 0; elbc_ctrl->addr = NULL; + + /* + * Freescale FCM controller has a 2K size limitation of buffer + * RAM, so elbc_fcm_ctrl->buffer have to be used if writesize + * of chip is greater than 2048. + * We kmalloc a 9 KB buffer for now (if there will be 16k pagesize, + * modify it later) at this point, because we don't know writesize + * before calling nand_scan(). We will re-malloc later if needed. + */ + elbc_ctrl->buffer = kmalloc(1024 * 8 + 1024, GFP_KERNEL); + if (!elbc_ctrl->buffer) { + printf("failed to allocate memory for elbc_ctrl->buffer\n"); + return -ENOMEM; + } + + return 0; } int board_nand_init(struct nand_chip *nand) @@ -694,8 +894,7 @@ int board_nand_init(struct nand_chip *nand) uint32_t br = 0, or = 0; if (!elbc_ctrl) { - fsl_elbc_ctrl_init(); - if (!elbc_ctrl) + if (fsl_elbc_ctrl_init()) return -1; } @@ -784,7 +983,6 @@ int board_nand_init(struct nand_chip *nand) /* Large-page-specific setup */ if (or & OR_FCM_PGS) { - priv->page_size = 1; nand->badblock_pattern = &largepage_memorybased; /* adjust ecc setup if needed */ @@ -798,3 +996,22 @@ int board_nand_init(struct nand_chip *nand) return 0; } + + +int board_nand_init_tail(struct mtd_info *mtd, struct nand_chip *nand) +{ + struct fsl_elbc_mtd *priv = nand->priv; + struct fsl_elbc_ctrl *ctrl = priv->ctrl; + + kfree(ctrl->buffer); + ctrl->buffer = NULL; + + if (mtd->writesize > 2048) { + ctrl->buffer = kmalloc(mtd->writesize + mtd->oobsize, + GFP_KERNEL); + if (!ctrl->buffer) + return -ENOMEM; + } + + return 0; +} -- 1.6.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip 2011-12-08 10:49 ` [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip Shengzhou Liu @ 2011-12-08 16:37 ` Marek Vasut 2011-12-09 2:33 ` LiuShuo 0 siblings, 1 reply; 14+ messages in thread From: Marek Vasut @ 2011-12-08 16:37 UTC (permalink / raw) To: u-boot > Freescale FCM controller has a 2K size limitation of buffer RAM. In order > to support the Nand flash chip whose page size is larger than 2K bytes, > we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB and save > them to a large buffer. > > Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> > Signed-off-by: Liu Shuo <b35362@freescale.com> > --- > drivers/mtd/nand/fsl_elbc_nand.c | 279 > +++++++++++++++++++++++++++++++++---- 1 files changed, 248 insertions(+), > 31 deletions(-) > > diff --git a/drivers/mtd/nand/fsl_elbc_nand.c > b/drivers/mtd/nand/fsl_elbc_nand.c index 52362b1..3983c8c 100644 > --- a/drivers/mtd/nand/fsl_elbc_nand.c > +++ b/drivers/mtd/nand/fsl_elbc_nand.c > @@ -64,7 +64,6 @@ struct fsl_elbc_mtd { > struct device *dev; > int bank; /* Chip select bank number */ > u8 __iomem *vbase; /* Chip select base virtual address */ > - int page_size; /* NAND page size (0=512, 1=2048) */ > unsigned int fmr; /* FCM Flash Mode Register value */ > }; > > @@ -85,6 +84,8 @@ struct fsl_elbc_ctrl { > unsigned int mdr; /* UPM/FCM Data Register value */ > unsigned int use_mdr; /* Non zero if the MDR is to be set */ > unsigned int oob; /* Non zero if operating on OOB data */ > + char *buffer; /* just used when pagesize is greater */ Start sentence with capital letter > + /* than FCM RAM 2K limitation */ > }; > > /* These map to the positions used by the FCM hardware ECC generator */ > @@ -159,6 +160,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { > .pattern = mirror_pattern, > }; > > +static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob) > +{ > + struct nand_chip *chip = mtd->priv; > + struct fsl_elbc_mtd *priv = chip->priv; > + struct fsl_elbc_ctrl *ctrl = priv->ctrl; > + void *src, *dst; > + int len = (oob ? 64 : 2048); No parenthesis ... > + > + /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */ > + if (oob) > + dst = ctrl->buffer + mtd->writesize + subpage * 64; > + else > + dst = ctrl->buffer + subpage * 2048; subpage * len ? > + > + src = ctrl->addr + (oob ? 2048 : 0); > + memcpy_fromio(dst, src, len); > +} > + > +static void buffer_to_io(struct mtd_info *mtd, int subpage, int oob) > +{ > + struct nand_chip *chip = mtd->priv; > + struct fsl_elbc_mtd *priv = chip->priv; > + struct fsl_elbc_ctrl *ctrl = priv->ctrl; > + void *src, *dst; > + int len = (oob ? 64 : 2048); > + > + if (oob) > + src = ctrl->buffer + mtd->writesize + subpage * 64; > + else > + src = ctrl->buffer + subpage * 2048; DTTO M ^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip 2011-12-08 16:37 ` Marek Vasut @ 2011-12-09 2:33 ` LiuShuo 2011-12-09 8:27 ` Marek Vasut 0 siblings, 1 reply; 14+ messages in thread From: LiuShuo @ 2011-12-09 2:33 UTC (permalink / raw) To: u-boot ? 2011?12?09? 00:37, Marek Vasut ??: >> Freescale FCM controller has a 2K size limitation of buffer RAM. In order >> to support the Nand flash chip whose page size is larger than 2K bytes, >> we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB and save >> them to a large buffer. >> >> Signed-off-by: Shengzhou Liu<Shengzhou.Liu@freescale.com> >> Signed-off-by: Liu Shuo<b35362@freescale.com> >> --- >> drivers/mtd/nand/fsl_elbc_nand.c | 279 >> +++++++++++++++++++++++++++++++++---- 1 files changed, 248 insertions(+), >> 31 deletions(-) >> >> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c >> b/drivers/mtd/nand/fsl_elbc_nand.c index 52362b1..3983c8c 100644 >> --- a/drivers/mtd/nand/fsl_elbc_nand.c >> +++ b/drivers/mtd/nand/fsl_elbc_nand.c >> @@ -64,7 +64,6 @@ struct fsl_elbc_mtd { >> struct device *dev; >> int bank; /* Chip select bank number */ >> u8 __iomem *vbase; /* Chip select base virtual address */ >> - int page_size; /* NAND page size (0=512, 1=2048) */ >> unsigned int fmr; /* FCM Flash Mode Register value */ >> }; >> >> @@ -85,6 +84,8 @@ struct fsl_elbc_ctrl { >> unsigned int mdr; /* UPM/FCM Data Register value */ >> unsigned int use_mdr; /* Non zero if the MDR is to be set */ >> unsigned int oob; /* Non zero if operating on OOB data */ >> + char *buffer; /* just used when pagesize is greater */ > Start sentence with capital letter > >> + /* than FCM RAM 2K limitation */ >> }; >> >> /* These map to the positions used by the FCM hardware ECC generator */ >> @@ -159,6 +160,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { >> .pattern = mirror_pattern, >> }; >> >> +static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob) >> +{ >> + struct nand_chip *chip = mtd->priv; >> + struct fsl_elbc_mtd *priv = chip->priv; >> + struct fsl_elbc_ctrl *ctrl = priv->ctrl; >> + void *src, *dst; >> + int len = (oob ? 64 : 2048); > No parenthesis ... > >> + >> + /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */ >> + if (oob) >> + dst = ctrl->buffer + mtd->writesize + subpage * 64; >> + else >> + dst = ctrl->buffer + subpage * 2048; > subpage * len ? dst = ctrl->buffer + (oob ? mtd->writesize : 0) + subpage * len ? Is this important ? I think it is ok. -LiuShuo > >> + >> + src = ctrl->addr + (oob ? 2048 : 0); >> + memcpy_fromio(dst, src, len); >> +} >> + >> +static void buffer_to_io(struct mtd_info *mtd, int subpage, int oob) >> +{ >> + struct nand_chip *chip = mtd->priv; >> + struct fsl_elbc_mtd *priv = chip->priv; >> + struct fsl_elbc_ctrl *ctrl = priv->ctrl; >> + void *src, *dst; >> + int len = (oob ? 64 : 2048); >> + >> + if (oob) >> + src = ctrl->buffer + mtd->writesize + subpage * 64; >> + else >> + src = ctrl->buffer + subpage * 2048; > DTTO > > M > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip 2011-12-09 2:33 ` LiuShuo @ 2011-12-09 8:27 ` Marek Vasut 2011-12-09 8:58 ` LiuShuo 0 siblings, 1 reply; 14+ messages in thread From: Marek Vasut @ 2011-12-09 8:27 UTC (permalink / raw) To: u-boot > ? 2011?12?09? 00:37, Marek Vasut ??: > >> Freescale FCM controller has a 2K size limitation of buffer RAM. In > >> order to support the Nand flash chip whose page size is larger than 2K > >> bytes, we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB > >> and save them to a large buffer. > >> > >> Signed-off-by: Shengzhou Liu<Shengzhou.Liu@freescale.com> > >> Signed-off-by: Liu Shuo<b35362@freescale.com> > >> --- > >> > >> drivers/mtd/nand/fsl_elbc_nand.c | 279 > >> > >> +++++++++++++++++++++++++++++++++---- 1 files changed, 248 > >> insertions(+), 31 deletions(-) > >> > >> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c > >> b/drivers/mtd/nand/fsl_elbc_nand.c index 52362b1..3983c8c 100644 > >> --- a/drivers/mtd/nand/fsl_elbc_nand.c > >> +++ b/drivers/mtd/nand/fsl_elbc_nand.c > >> @@ -64,7 +64,6 @@ struct fsl_elbc_mtd { > >> > >> struct device *dev; > >> int bank; /* Chip select bank number */ > >> u8 __iomem *vbase; /* Chip select base virtual address */ > >> > >> - int page_size; /* NAND page size (0=512, 1=2048) */ > >> > >> unsigned int fmr; /* FCM Flash Mode Register value */ > >> > >> }; > >> > >> @@ -85,6 +84,8 @@ struct fsl_elbc_ctrl { > >> > >> unsigned int mdr; /* UPM/FCM Data Register value */ > >> unsigned int use_mdr; /* Non zero if the MDR is to be set */ > >> unsigned int oob; /* Non zero if operating on OOB data */ > >> > >> + char *buffer; /* just used when pagesize is greater */ > > > > Start sentence with capital letter > > > >> + /* than FCM RAM 2K limitation */ > >> > >> }; > >> > >> /* These map to the positions used by the FCM hardware ECC generator > >> */ > >> > >> @@ -159,6 +160,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { > >> > >> .pattern = mirror_pattern, > >> > >> }; > >> > >> +static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob) > >> +{ > >> + struct nand_chip *chip = mtd->priv; > >> + struct fsl_elbc_mtd *priv = chip->priv; > >> + struct fsl_elbc_ctrl *ctrl = priv->ctrl; > >> + void *src, *dst; > >> + int len = (oob ? 64 : 2048); > > > > No parenthesis ... > > > >> + > >> + /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */ > >> + if (oob) > >> + dst = ctrl->buffer + mtd->writesize + subpage * 64; > >> + else > >> + dst = ctrl->buffer + subpage * 2048; > > > > subpage * len ? > > dst = ctrl->buffer + (oob ? mtd->writesize : 0) + subpage * len ? > Is this important ? I think it is ok. dst = ctrl->buffer + subpage * len; if (oob) dst += mtd->writesize; it's important, this code looks like mess. You introduce len and don't use it anywhere then ? M ^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip 2011-12-09 8:27 ` Marek Vasut @ 2011-12-09 8:58 ` LiuShuo 2011-12-09 9:11 ` Marek Vasut 0 siblings, 1 reply; 14+ messages in thread From: LiuShuo @ 2011-12-09 8:58 UTC (permalink / raw) To: u-boot ? 2011?12?09? 16:27, Marek Vasut ??: >> ? 2011?12?09? 00:37, Marek Vasut ??: >>>> Freescale FCM controller has a 2K size limitation of buffer RAM. In >>>> order to support the Nand flash chip whose page size is larger than 2K >>>> bytes, we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB >>>> and save them to a large buffer. >>>> >>>> Signed-off-by: Shengzhou Liu<Shengzhou.Liu@freescale.com> >>>> Signed-off-by: Liu Shuo<b35362@freescale.com> >>>> --- >>>> >>>> drivers/mtd/nand/fsl_elbc_nand.c | 279 >>>> >>>> +++++++++++++++++++++++++++++++++---- 1 files changed, 248 >>>> insertions(+), 31 deletions(-) >>>> >>>> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c >>>> b/drivers/mtd/nand/fsl_elbc_nand.c index 52362b1..3983c8c 100644 >>>> --- a/drivers/mtd/nand/fsl_elbc_nand.c >>>> +++ b/drivers/mtd/nand/fsl_elbc_nand.c >>>> @@ -64,7 +64,6 @@ struct fsl_elbc_mtd { >>>> >>>> struct device *dev; >>>> int bank; /* Chip select bank number */ >>>> u8 __iomem *vbase; /* Chip select base virtual address */ >>>> >>>> - int page_size; /* NAND page size (0=512, 1=2048) */ >>>> >>>> unsigned int fmr; /* FCM Flash Mode Register value */ >>>> >>>> }; >>>> >>>> @@ -85,6 +84,8 @@ struct fsl_elbc_ctrl { >>>> >>>> unsigned int mdr; /* UPM/FCM Data Register value */ >>>> unsigned int use_mdr; /* Non zero if the MDR is to be set */ >>>> unsigned int oob; /* Non zero if operating on OOB data */ >>>> >>>> + char *buffer; /* just used when pagesize is greater */ >>> Start sentence with capital letter >>> >>>> + /* than FCM RAM 2K limitation */ >>>> >>>> }; >>>> >>>> /* These map to the positions used by the FCM hardware ECC generator >>>> */ >>>> >>>> @@ -159,6 +160,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { >>>> >>>> .pattern = mirror_pattern, >>>> >>>> }; >>>> >>>> +static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob) >>>> +{ >>>> + struct nand_chip *chip = mtd->priv; >>>> + struct fsl_elbc_mtd *priv = chip->priv; >>>> + struct fsl_elbc_ctrl *ctrl = priv->ctrl; >>>> + void *src, *dst; >>>> + int len = (oob ? 64 : 2048); >>> No parenthesis ... >>> >>>> + >>>> + /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */ >>>> + if (oob) >>>> + dst = ctrl->buffer + mtd->writesize + subpage * 64; >>>> + else >>>> + dst = ctrl->buffer + subpage * 2048; >>> subpage * len ? >> dst = ctrl->buffer + (oob ? mtd->writesize : 0) + subpage * len ? >> Is this important ? I think it is ok. > dst = ctrl->buffer + subpage * len; > > if (oob) > dst += mtd->writesize; > > it's important, this code looks like mess. You introduce len and don't use it > anywhere then ? memcpy_fromio(dst, src, len); -Liu Shuo > M > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip 2011-12-09 8:58 ` LiuShuo @ 2011-12-09 9:11 ` Marek Vasut 2011-12-09 9:32 ` LiuShuo 0 siblings, 1 reply; 14+ messages in thread From: Marek Vasut @ 2011-12-09 9:11 UTC (permalink / raw) To: u-boot > ? 2011?12?09? 16:27, Marek Vasut ??: > >> ? 2011?12?09? 00:37, Marek Vasut ??: > >>>> Freescale FCM controller has a 2K size limitation of buffer RAM. In > >>>> order to support the Nand flash chip whose page size is larger than 2K > >>>> bytes, we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB > >>>> and save them to a large buffer. > >>>> > >>>> Signed-off-by: Shengzhou Liu<Shengzhou.Liu@freescale.com> > >>>> Signed-off-by: Liu Shuo<b35362@freescale.com> > >>>> --- > >>>> > >>>> drivers/mtd/nand/fsl_elbc_nand.c | 279 > >>>> > >>>> +++++++++++++++++++++++++++++++++---- 1 files changed, 248 > >>>> insertions(+), 31 deletions(-) > >>>> > >>>> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c > >>>> b/drivers/mtd/nand/fsl_elbc_nand.c index 52362b1..3983c8c 100644 > >>>> --- a/drivers/mtd/nand/fsl_elbc_nand.c > >>>> +++ b/drivers/mtd/nand/fsl_elbc_nand.c > >>>> @@ -64,7 +64,6 @@ struct fsl_elbc_mtd { > >>>> > >>>> struct device *dev; > >>>> int bank; /* Chip select bank number */ > >>>> u8 __iomem *vbase; /* Chip select base virtual address */ > >>>> > >>>> - int page_size; /* NAND page size (0=512, 1=2048) */ > >>>> > >>>> unsigned int fmr; /* FCM Flash Mode Register value */ > >>>> > >>>> }; > >>>> > >>>> @@ -85,6 +84,8 @@ struct fsl_elbc_ctrl { > >>>> > >>>> unsigned int mdr; /* UPM/FCM Data Register value > >>>> */ unsigned int use_mdr; /* Non zero if the MDR is to be set > >>>> */ unsigned int oob; /* Non zero if operating on OOB > >>>> data */ > >>>> > >>>> + char *buffer; /* just used when pagesize is greater */ > >>> > >>> Start sentence with capital letter > >>> > >>>> + /* than FCM RAM 2K limitation */ > >>>> > >>>> }; > >>>> > >>>> /* These map to the positions used by the FCM hardware ECC > >>>> generator */ > >>>> > >>>> @@ -159,6 +160,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { > >>>> > >>>> .pattern = mirror_pattern, > >>>> > >>>> }; > >>>> > >>>> +static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob) > >>>> +{ > >>>> + struct nand_chip *chip = mtd->priv; > >>>> + struct fsl_elbc_mtd *priv = chip->priv; > >>>> + struct fsl_elbc_ctrl *ctrl = priv->ctrl; > >>>> + void *src, *dst; > >>>> + int len = (oob ? 64 : 2048); > >>> > >>> No parenthesis ... > >>> > >>>> + > >>>> + /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */ > >>>> + if (oob) > >>>> + dst = ctrl->buffer + mtd->writesize + subpage * 64; > >>>> + else > >>>> + dst = ctrl->buffer + subpage * 2048; > >>> > >>> subpage * len ? > >> > >> dst = ctrl->buffer + (oob ? mtd->writesize : 0) + subpage * len ? > >> Is this important ? I think it is ok. > > > > dst = ctrl->buffer + subpage * len; > > > > if (oob) > > > > dst += mtd->writesize; > > > > it's important, this code looks like mess. You introduce len and don't > > use it anywhere then ? > > memcpy_fromio(dst, src, len); Ok, why not use it consistently then. M ^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip 2011-12-09 9:11 ` Marek Vasut @ 2011-12-09 9:32 ` LiuShuo 2011-12-09 9:46 ` Marek Vasut 0 siblings, 1 reply; 14+ messages in thread From: LiuShuo @ 2011-12-09 9:32 UTC (permalink / raw) To: u-boot ? 2011?12?09? 17:11, Marek Vasut ??: >> ? 2011?12?09? 16:27, Marek Vasut ??: >>>> ? 2011?12?09? 00:37, Marek Vasut ??: >>>>>> Freescale FCM controller has a 2K size limitation of buffer RAM. In >>>>>> order to support the Nand flash chip whose page size is larger than 2K >>>>>> bytes, we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB >>>>>> and save them to a large buffer. >>>>>> >>>>>> Signed-off-by: Shengzhou Liu<Shengzhou.Liu@freescale.com> >>>>>> Signed-off-by: Liu Shuo<b35362@freescale.com> >>>>>> --- >>>>>> >>>>>> drivers/mtd/nand/fsl_elbc_nand.c | 279 >>>>>> >>>>>> +++++++++++++++++++++++++++++++++---- 1 files changed, 248 >>>>>> insertions(+), 31 deletions(-) >>>>>> >>>>>> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c >>>>>> b/drivers/mtd/nand/fsl_elbc_nand.c index 52362b1..3983c8c 100644 >>>>>> --- a/drivers/mtd/nand/fsl_elbc_nand.c >>>>>> +++ b/drivers/mtd/nand/fsl_elbc_nand.c >>>>>> @@ -64,7 +64,6 @@ struct fsl_elbc_mtd { >>>>>> >>>>>> struct device *dev; >>>>>> int bank; /* Chip select bank number */ >>>>>> u8 __iomem *vbase; /* Chip select base virtual address */ >>>>>> >>>>>> - int page_size; /* NAND page size (0=512, 1=2048) */ >>>>>> >>>>>> unsigned int fmr; /* FCM Flash Mode Register value */ >>>>>> >>>>>> }; >>>>>> >>>>>> @@ -85,6 +84,8 @@ struct fsl_elbc_ctrl { >>>>>> >>>>>> unsigned int mdr; /* UPM/FCM Data Register value >>>>>> */ unsigned int use_mdr; /* Non zero if the MDR is to be set >>>>>> */ unsigned int oob; /* Non zero if operating on OOB >>>>>> data */ >>>>>> >>>>>> + char *buffer; /* just used when pagesize is greater > */ >>>>> Start sentence with capital letter >>>>> >>>>>> + /* than FCM RAM 2K limitation > */ >>>>>> }; >>>>>> >>>>>> /* These map to the positions used by the FCM hardware ECC >>>>>> generator */ >>>>>> >>>>>> @@ -159,6 +160,44 @@ static struct nand_bbt_descr bbt_mirror_descr = { >>>>>> >>>>>> .pattern = mirror_pattern, >>>>>> >>>>>> }; >>>>>> >>>>>> +static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob) >>>>>> +{ >>>>>> + struct nand_chip *chip = mtd->priv; >>>>>> + struct fsl_elbc_mtd *priv = chip->priv; >>>>>> + struct fsl_elbc_ctrl *ctrl = priv->ctrl; >>>>>> + void *src, *dst; >>>>>> + int len = (oob ? 64 : 2048); >>>>> No parenthesis ... >>>>> >>>>>> + >>>>>> + /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */ >>>>>> + if (oob) >>>>>> + dst = ctrl->buffer + mtd->writesize + subpage * 64; >>>>>> + else >>>>>> + dst = ctrl->buffer + subpage * 2048; >>>>> subpage * len ? >>>> dst = ctrl->buffer + (oob ? mtd->writesize : 0) + subpage * len ? >>>> Is this important ? I think it is ok. >>> dst = ctrl->buffer + subpage * len; >>> >>> if (oob) >>> >>> dst += mtd->writesize; >>> >>> it's important, this code looks like mess. You introduce len and don't >>> use it anywhere then ? >> memcpy_fromio(dst, src, len); > Ok, why not use it consistently then. I think it is pellucid. I still don't think it is very important. - LiuShuo > M > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip 2011-12-09 9:32 ` LiuShuo @ 2011-12-09 9:46 ` Marek Vasut 0 siblings, 0 replies; 14+ messages in thread From: Marek Vasut @ 2011-12-09 9:46 UTC (permalink / raw) To: u-boot > ? 2011?12?09? 17:11, Marek Vasut ??: > >> ? 2011?12?09? 16:27, Marek Vasut ??: > >>>> ? 2011?12?09? 00:37, Marek Vasut ??: > >>>>>> Freescale FCM controller has a 2K size limitation of buffer RAM. In > >>>>>> order to support the Nand flash chip whose page size is larger than > >>>>>> 2K bytes, we read/write 2k data repeatedly by issuing > >>>>>> FIR_OP_RB/FIR_OP_WB and save them to a large buffer. > >>>>>> > >>>>>> Signed-off-by: Shengzhou Liu<Shengzhou.Liu@freescale.com> > >>>>>> Signed-off-by: Liu Shuo<b35362@freescale.com> > >>>>>> --- > >>>>>> > >>>>>> drivers/mtd/nand/fsl_elbc_nand.c | 279 > >>>>>> > >>>>>> +++++++++++++++++++++++++++++++++---- 1 files changed, 248 > >>>>>> insertions(+), 31 deletions(-) > >>>>>> > >>>>>> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c > >>>>>> b/drivers/mtd/nand/fsl_elbc_nand.c index 52362b1..3983c8c 100644 > >>>>>> --- a/drivers/mtd/nand/fsl_elbc_nand.c > >>>>>> +++ b/drivers/mtd/nand/fsl_elbc_nand.c > >>>>>> @@ -64,7 +64,6 @@ struct fsl_elbc_mtd { > >>>>>> > >>>>>> struct device *dev; > >>>>>> int bank; /* Chip select bank number */ > >>>>>> u8 __iomem *vbase; /* Chip select base virtual address */ > >>>>>> > >>>>>> - int page_size; /* NAND page size (0=512, 1=2048) */ > >>>>>> > >>>>>> unsigned int fmr; /* FCM Flash Mode Register value */ > >>>>>> > >>>>>> }; > >>>>>> > >>>>>> @@ -85,6 +84,8 @@ struct fsl_elbc_ctrl { > >>>>>> > >>>>>> unsigned int mdr; /* UPM/FCM Data Register value > >>>>>> */ unsigned int use_mdr; /* Non zero if the MDR is to be set > >>>>>> > >>>>>> */ unsigned int oob; /* Non zero if operating on OOB > >>>>>> > >>>>>> data */ > >>>>>> > >>>>>> + char *buffer; /* just used when pagesize is greater > > > > */ > > > >>>>> Start sentence with capital letter > >>>>> > >>>>>> + /* than FCM RAM 2K limitation > > > > */ > > > >>>>>> }; > >>>>>> > >>>>>> /* These map to the positions used by the FCM hardware ECC > >>>>>> generator */ > >>>>>> > >>>>>> @@ -159,6 +160,44 @@ static struct nand_bbt_descr bbt_mirror_descr = > >>>>>> { > >>>>>> > >>>>>> .pattern = mirror_pattern, > >>>>>> > >>>>>> }; > >>>>>> > >>>>>> +static void io_to_buffer(struct mtd_info *mtd, int subpage, int > >>>>>> oob) +{ > >>>>>> + struct nand_chip *chip = mtd->priv; > >>>>>> + struct fsl_elbc_mtd *priv = chip->priv; > >>>>>> + struct fsl_elbc_ctrl *ctrl = priv->ctrl; > >>>>>> + void *src, *dst; > >>>>>> + int len = (oob ? 64 : 2048); > >>>>> > >>>>> No parenthesis ... > >>>>> > >>>>>> + > >>>>>> + /* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */ > >>>>>> + if (oob) > >>>>>> + dst = ctrl->buffer + mtd->writesize + subpage * 64; > >>>>>> + else > >>>>>> + dst = ctrl->buffer + subpage * 2048; > >>>>> > >>>>> subpage * len ? > >>>> > >>>> dst = ctrl->buffer + (oob ? mtd->writesize : 0) + subpage * len ? > >>>> Is this important ? I think it is ok. > >>> > >>> dst = ctrl->buffer + subpage * len; > >>> > >>> if (oob) > >>> > >>> dst += mtd->writesize; > >>> > >>> it's important, this code looks like mess. You introduce len and don't > >>> use it anywhere then ? > >> > >> memcpy_fromio(dst, src, len); > > > > Ok, why not use it consistently then. > > I think it is pellucid. I still don't think it is very important. Ok, enough of this stuff, apparently I'm loosing time here. Let's see what others think. M ^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller 2011-12-08 10:49 ` [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip Shengzhou Liu @ 2011-12-08 18:09 ` Scott Wood 1 sibling, 0 replies; 14+ messages in thread From: Scott Wood @ 2011-12-08 18:09 UTC (permalink / raw) To: u-boot On 12/08/2011 04:49 AM, Shengzhou Liu wrote: > - fix NAND_CMD_READID command for ONFI detect. > - add NAND_CMD_PARAM command to read the ONFI parameter page. > > Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> > --- > drivers/mtd/nand/fsl_elbc_nand.c | 19 ++++++++++++------- > 1 files changed, 12 insertions(+), 7 deletions(-) > > diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c > index 4d1e527..52362b1 100644 > --- a/drivers/mtd/nand/fsl_elbc_nand.c > +++ b/drivers/mtd/nand/fsl_elbc_nand.c > @@ -340,20 +340,25 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, > > /* READID must read all 5 possible bytes while CEB is active */ > case NAND_CMD_READID: > - vdbg("fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); > + case NAND_CMD_PARAM: > + vdbg("fsl_elbc_cmdfunc: NAND_CMD 0x%x.\n", command); > > out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) | > (FIR_OP_UA << FIR_OP1_SHIFT) | > (FIR_OP_RBW << FIR_OP2_SHIFT)); > - out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); > - /* 5 bytes for manuf, device and exts */ > - out_be32(&lbc->fbcr, 5); > - ctrl->read_bytes = 5; > + out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT); > + /* > + * although currently it's 8 bytes for READID, we always read > + * the maximum 256 bytes(for PARAM) > + */ > + out_be32(&lbc->fbcr, 256); > + ctrl->read_bytes = 256; > ctrl->use_mdr = 1; > - ctrl->mdr = 0; > - > + ctrl->mdr = column; > set_addr(mtd, 0, 0, 0); > fsl_elbc_run_command(mtd); > + if (mtd->writesize > 2048) > + memcpy_fromio(ctrl->buffer, ctrl->addr, 256); This memcpy_fromio looks like leakage from patch 5/5. -Scott ^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH 1/5] mtd/nand: Add function board_nand_init_tail() for some special NAND controllers 2011-12-08 10:49 [U-Boot] [PATCH 1/5] mtd/nand: Add function board_nand_init_tail() for some special NAND controllers Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 2/5] mtd/nand: Fixup for support ONFI detect Shengzhou Liu @ 2011-12-08 16:35 ` Marek Vasut 1 sibling, 0 replies; 14+ messages in thread From: Marek Vasut @ 2011-12-08 16:35 UTC (permalink / raw) To: u-boot > In some NAND controllers there is a size limitation of RAM buffer(2K > bytes). To support large-page NAND chips with greater than 2K pagesize, we > need a large buffer, but we don't know pagesize before calling > nand_scan_ident(), for more flexible and to identify different cases of > large-page greater than 2K bytes, we have a board_nand_init_tail() between > nand_scan_ident() and nand_scan_tail(). > > Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> > --- > drivers/mtd/nand/nand.c | 19 ++++++++++++++++++- > 1 files changed, 18 insertions(+), 1 deletions(-) > > diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c > index d987f4c..800541e 100644 > --- a/drivers/mtd/nand/nand.c > +++ b/drivers/mtd/nand/nand.c > @@ -39,6 +39,14 @@ static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = > CONFIG_SYS_NAND_BASE_LIS static const char default_nand_name[] = "nand"; > static __attribute__((unused)) char > dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8]; > > +int __board_nand_init_tail(struct mtd_info *mtd, struct nand_chip *nand) > +{ Isn't struct nand_chip * already passed in mtd->priv ? M > + /* Allow for init at tail in controller-specific file for some reason */ > + return 0; > +} > +int board_nand_init_tail(struct mtd_info *mtd, struct nand_chip *nand) > +__attribute__((weak, alias("__board_nand_init_tail"))); > + > static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, > ulong base_addr) > { > @@ -51,7 +59,16 @@ static void nand_init_chip(struct mtd_info *mtd, struct > nand_chip *nand, > > nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; > if (board_nand_init(nand) == 0) { > - if (nand_scan(mtd, maxchips) == 0) { > + if (!nand_scan_ident(mtd, maxchips, NULL)) { > + if (board_nand_init_tail(mtd, nand)) { > + mtd->name = NULL; > + return; > + } > + > + if (nand_scan_tail(mtd)) { > + mtd->name = NULL; > + return; > + } > if (!mtd->name) > mtd->name = (char *)default_nand_name; > #ifdef CONFIG_NEEDS_MANUAL_RELOC ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2011-12-09 9:46 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-12-08 10:49 [U-Boot] [PATCH 1/5] mtd/nand: Add function board_nand_init_tail() for some special NAND controllers Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 2/5] mtd/nand: Fixup for support ONFI detect Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 3/5] mtd/nand: remove CONFIG_SYS_NAND_ONFI_DETECTION to enable ONFI detection Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller Shengzhou Liu 2011-12-08 10:49 ` [U-Boot] [PATCH 5/5] mtd/nand: workaround for Freescale FCM to support 4k pagesize Nand chip Shengzhou Liu 2011-12-08 16:37 ` Marek Vasut 2011-12-09 2:33 ` LiuShuo 2011-12-09 8:27 ` Marek Vasut 2011-12-09 8:58 ` LiuShuo 2011-12-09 9:11 ` Marek Vasut 2011-12-09 9:32 ` LiuShuo 2011-12-09 9:46 ` Marek Vasut 2011-12-08 18:09 ` [U-Boot] [PATCH 4/5] mtd/nand: Add ONFI support for FSL NAND controller Scott Wood 2011-12-08 16:35 ` [U-Boot] [PATCH 1/5] mtd/nand: Add function board_nand_init_tail() for some special NAND controllers Marek Vasut
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.