diff options
Diffstat (limited to 'drivers/mtd/nand/fsl_elbc_nand.c')
-rw-r--r-- | drivers/mtd/nand/fsl_elbc_nand.c | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index eedd8ee2c9ac..7195ee6efe12 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -166,15 +166,22 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) elbc_fcm_ctrl->page = page_addr; - out_be32(&lbc->fbar, - page_addr >> (chip->phys_erase_shift - chip->page_shift)); - if (priv->page_size) { + /* + * large page size chip : FPAR[PI] save the lowest 6 bits, + * FBAR[BLK] save the other bits. + */ + out_be32(&lbc->fbar, page_addr >> 6); out_be32(&lbc->fpar, ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | (oob ? FPAR_LP_MS : 0) | column); buf_num = (page_addr & 1) << 2; } else { + /* + * small page size chip : FPAR[PI] save the lowest 5 bits, + * FBAR[BLK] save the other bits. + */ + out_be32(&lbc->fbar, page_addr >> 5); out_be32(&lbc->fpar, ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) | (oob ? FPAR_SP_MS : 0) | column); @@ -349,20 +356,22 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, fsl_elbc_run_command(mtd); return; - /* READID must read all 5 possible bytes while CEB is active */ case NAND_CMD_READID: - dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); + case NAND_CMD_PARAM: + dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command); out_be32(&lbc->fir, (FIR_OP_CM0 << 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); - /* nand_get_flash_type() reads 8 bytes of entire ID string */ - out_be32(&lbc->fbcr, 8); - elbc_fcm_ctrl->read_bytes = 8; + 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); + elbc_fcm_ctrl->read_bytes = 256; elbc_fcm_ctrl->use_mdr = 1; - elbc_fcm_ctrl->mdr = 0; - + elbc_fcm_ctrl->mdr = column; set_addr(mtd, 0, 0, 0); fsl_elbc_run_command(mtd); return; @@ -407,9 +416,17 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, page_addr, column); elbc_fcm_ctrl->column = column; - elbc_fcm_ctrl->oob = 0; elbc_fcm_ctrl->use_mdr = 1; + if (column >= mtd->writesize) { + /* OOB area */ + column -= mtd->writesize; + elbc_fcm_ctrl->oob = 1; + } else { + WARN_ON(column != 0); + elbc_fcm_ctrl->oob = 0; + } + fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT); @@ -434,16 +451,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, (FIR_OP_CW1 << FIR_OP6_SHIFT) | (FIR_OP_RS << FIR_OP7_SHIFT)); - if (column >= mtd->writesize) { + if (elbc_fcm_ctrl->oob) /* OOB area --> READOOB */ - column -= mtd->writesize; fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; - elbc_fcm_ctrl->oob = 1; - } else { - WARN_ON(column != 0); + else /* First 256 bytes --> READ0 */ fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT; - } } out_be32(&lbc->fcr, fcr); @@ -463,7 +476,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, */ if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) - out_be32(&lbc->fbcr, elbc_fcm_ctrl->index); + out_be32(&lbc->fbcr, + elbc_fcm_ctrl->index - elbc_fcm_ctrl->column); else out_be32(&lbc->fbcr, 0); @@ -659,9 +673,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) if (chip->pagemask & 0xff000000) al++; - /* add to ECCM mode set in fsl_elbc_init */ - priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ - (al << FMR_AL_SHIFT); + priv->fmr |= al << FMR_AL_SHIFT; dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", chip->numchips); @@ -764,8 +776,10 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) priv->mtd.priv = chip; priv->mtd.owner = THIS_MODULE; - /* Set the ECCM according to the settings in bootloader.*/ - priv->fmr = in_be32(&lbc->fmr) & FMR_ECCM; + /* set timeout to maximum */ + priv->fmr = 15 << FMR_CWTO_SHIFT; + if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS) + priv->fmr |= FMR_ECCM; /* fill in nand_chip structure */ /* set up function call table */ @@ -971,18 +985,7 @@ static struct platform_driver fsl_elbc_nand_driver = { .remove = fsl_elbc_nand_remove, }; -static int __init fsl_elbc_nand_init(void) -{ - return platform_driver_register(&fsl_elbc_nand_driver); -} - -static void __exit fsl_elbc_nand_exit(void) -{ - platform_driver_unregister(&fsl_elbc_nand_driver); -} - -module_init(fsl_elbc_nand_init); -module_exit(fsl_elbc_nand_exit); +module_platform_driver(fsl_elbc_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Freescale"); |