X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fmtd%2Fnand%2Ffsl_elbc_nand.c;h=795209788ba038d8333e6df1697d0c35764672c7;hb=3be2bdf5dc69b3142c1162a59bc67191c9077567;hp=ab3e0fdf56481114e4f697eb3f46cefb55b4c44a;hpb=9c814b0a716aae884bec977b9a032dfa59cfb79a;p=u-boot diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index ab3e0fdf56..795209788b 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -5,23 +5,12 @@ * Authors: Nick Spence , * Scott Wood * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include #include +#include #include #include @@ -57,7 +46,6 @@ struct fsl_elbc_ctrl; /* mtd information per set */ struct fsl_elbc_mtd { - struct mtd_info mtd; struct nand_chip chip; struct fsl_elbc_ctrl *ctrl; @@ -75,7 +63,7 @@ struct fsl_elbc_ctrl { struct fsl_elbc_mtd *chips[MAX_BANKS]; /* device info */ - lbus83xx_t *regs; + fsl_lbc_t *regs; u8 __iomem *addr; /* Address of assigned FCM buffer */ unsigned int page; /* Last page written to / read from */ unsigned int read_bytes; /* Number of bytes read during command */ @@ -85,7 +73,6 @@ 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 */ - uint8_t *oob_poi; /* Place to write ECC after read back */ }; /* These map to the positions used by the FCM hardware ECC generator */ @@ -95,7 +82,6 @@ static struct nand_ecclayout fsl_elbc_oob_sp_eccm0 = { .eccbytes = 3, .eccpos = {6, 7, 8}, .oobfree = { {0, 5}, {9, 7} }, - .oobavail = 12, }; /* Small Page FLASH with FMR[ECCM] = 1 */ @@ -103,7 +89,6 @@ static struct nand_ecclayout fsl_elbc_oob_sp_eccm1 = { .eccbytes = 3, .eccpos = {8, 9, 10}, .oobfree = { {0, 5}, {6, 2}, {11, 5} }, - .oobavail = 12, }; /* Large Page FLASH with FMR[ECCM] = 0 */ @@ -111,7 +96,6 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm0 = { .eccbytes = 12, .eccpos = {6, 7, 8, 22, 23, 24, 38, 39, 40, 54, 55, 56}, .oobfree = { {1, 5}, {9, 13}, {25, 13}, {41, 13}, {57, 7} }, - .oobavail = 48, }; /* Large Page FLASH with FMR[ECCM] = 1 */ @@ -119,7 +103,48 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = { .eccbytes = 12, .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, .oobfree = { {1, 7}, {11, 13}, {27, 13}, {43, 13}, {59, 5} }, - .oobavail = 48, +}; + +/* + * fsl_elbc_oob_lp_eccm* specify that LP NAND's OOB free area starts at offset + * 1, so we have to adjust bad block pattern. This pattern should be used for + * x8 chips only. So far hardware does not support x16 chips anyway. + */ +static u8 scan_ff_pattern[] = { 0xff, }; + +static struct nand_bbt_descr largepage_memorybased = { + .options = 0, + .offs = 0, + .len = 1, + .pattern = scan_ff_pattern, +}; + +/* + * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt, + * interfere with ECC positions, that's why we implement our own descriptors. + * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0. + */ +static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; +static u8 mirror_pattern[] = {'1', 't', 'b', 'B' }; + +static struct nand_bbt_descr bbt_main_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | + NAND_BBT_2BIT | NAND_BBT_VERSION, + .offs = 11, + .len = 4, + .veroffs = 15, + .maxblocks = 4, + .pattern = bbt_pattern, +}; + +static struct nand_bbt_descr bbt_mirror_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | + NAND_BBT_2BIT | NAND_BBT_VERSION, + .offs = 11, + .len = 4, + .veroffs = 15, + .maxblocks = 4, + .pattern = mirror_pattern, }; /*=================================*/ @@ -133,23 +158,22 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) struct nand_chip *chip = mtd->priv; struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_ctrl *ctrl = priv->ctrl; - lbus83xx_t *lbc = ctrl->regs; + fsl_lbc_t *lbc = ctrl->regs; int buf_num; ctrl->page = page_addr; - out_be32(&lbc->fbar, - page_addr >> (chip->phys_erase_shift - chip->page_shift)); - if (priv->page_size) { + 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); + ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | + (oob ? FPAR_LP_MS : 0) | column); buf_num = (page_addr & 1) << 2; } else { + 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); + ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) | + (oob ? FPAR_SP_MS : 0) | column); buf_num = page_addr & 7; } @@ -174,7 +198,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) struct nand_chip *chip = mtd->priv; struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_ctrl *ctrl = priv->ctrl; - lbus83xx_t *lbc = ctrl->regs; + fsl_lbc_t *lbc = ctrl->regs; long long end_tick; u32 ltesr; @@ -224,28 +248,28 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob) { struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_ctrl *ctrl = priv->ctrl; - lbus83xx_t *lbc = ctrl->regs; + fsl_lbc_t *lbc = ctrl->regs; if (priv->page_size) { out_be32(&lbc->fir, - (FIR_OP_CW0 << FIR_OP0_SHIFT) | - (FIR_OP_CA << FIR_OP1_SHIFT) | - (FIR_OP_PA << FIR_OP2_SHIFT) | - (FIR_OP_CW1 << FIR_OP3_SHIFT) | - (FIR_OP_RBW << FIR_OP4_SHIFT)); + (FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA << FIR_OP1_SHIFT) | + (FIR_OP_PA << FIR_OP2_SHIFT) | + (FIR_OP_CW1 << FIR_OP3_SHIFT) | + (FIR_OP_RBW << FIR_OP4_SHIFT)); out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | - (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); + (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); } else { out_be32(&lbc->fir, - (FIR_OP_CW0 << FIR_OP0_SHIFT) | - (FIR_OP_CA << FIR_OP1_SHIFT) | - (FIR_OP_PA << FIR_OP2_SHIFT) | - (FIR_OP_RBW << FIR_OP3_SHIFT)); + (FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA << FIR_OP1_SHIFT) | + (FIR_OP_PA << FIR_OP2_SHIFT) | + (FIR_OP_RBW << FIR_OP3_SHIFT)); if (oob) out_be32(&lbc->fcr, - NAND_CMD_READOOB << FCR_CMD0_SHIFT); + NAND_CMD_READOOB << FCR_CMD0_SHIFT); else out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT); } @@ -253,12 +277,12 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob) /* cmdfunc send commands to the FCM */ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, - int column, int page_addr) + int column, int page_addr) { struct nand_chip *chip = mtd->priv; struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_ctrl *ctrl = priv->ctrl; - lbus83xx_t *lbc = ctrl->regs; + fsl_lbc_t *lbc = ctrl->regs; ctrl->use_mdr = 0; @@ -304,18 +328,21 @@ 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; + (FIR_OP_UA << FIR_OP1_SHIFT) | + (FIR_OP_RBW << FIR_OP2_SHIFT)); + 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); return; @@ -332,13 +359,13 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, vdbg("fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); out_be32(&lbc->fir, - (FIR_OP_CW0 << FIR_OP0_SHIFT) | - (FIR_OP_PA << FIR_OP1_SHIFT) | - (FIR_OP_CM1 << FIR_OP2_SHIFT)); + (FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_PA << FIR_OP1_SHIFT) | + (FIR_OP_CM1 << FIR_OP2_SHIFT)); out_be32(&lbc->fcr, - (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) | - (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT)); + (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) | + (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT)); out_be32(&lbc->fbcr, 0); ctrl->read_bytes = 0; @@ -361,22 +388,22 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT); out_be32(&lbc->fir, - (FIR_OP_CW0 << FIR_OP0_SHIFT) | - (FIR_OP_CA << FIR_OP1_SHIFT) | - (FIR_OP_PA << FIR_OP2_SHIFT) | - (FIR_OP_WB << FIR_OP3_SHIFT) | - (FIR_OP_CW1 << FIR_OP4_SHIFT)); + (FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA << FIR_OP1_SHIFT) | + (FIR_OP_PA << FIR_OP2_SHIFT) | + (FIR_OP_WB << FIR_OP3_SHIFT) | + (FIR_OP_CW1 << FIR_OP4_SHIFT)); } else { fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT); out_be32(&lbc->fir, - (FIR_OP_CW0 << FIR_OP0_SHIFT) | - (FIR_OP_CM2 << FIR_OP1_SHIFT) | - (FIR_OP_CA << FIR_OP2_SHIFT) | - (FIR_OP_PA << FIR_OP3_SHIFT) | - (FIR_OP_WB << FIR_OP4_SHIFT) | - (FIR_OP_CW1 << FIR_OP5_SHIFT)); + (FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CM2 << FIR_OP1_SHIFT) | + (FIR_OP_CA << FIR_OP2_SHIFT) | + (FIR_OP_PA << FIR_OP3_SHIFT) | + (FIR_OP_WB << FIR_OP4_SHIFT) | + (FIR_OP_CW1 << FIR_OP5_SHIFT)); if (column >= mtd->writesize) { /* OOB area --> READOOB */ @@ -399,7 +426,6 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ case NAND_CMD_PAGEPROG: { - int full_page; vdbg("fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " "writing %d bytes.\n", ctrl->index); @@ -408,34 +434,13 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, * write so the HW generates the ECC. */ if (ctrl->oob || ctrl->column != 0 || - ctrl->index != mtd->writesize + mtd->oobsize) { + ctrl->index != mtd->writesize + mtd->oobsize) out_be32(&lbc->fbcr, ctrl->index); - full_page = 0; - } else { + else out_be32(&lbc->fbcr, 0); - full_page = 1; - } fsl_elbc_run_command(mtd); - /* Read back the page in order to fill in the ECC for the - * caller. Is this really needed? - */ - if (full_page && ctrl->oob_poi) { - out_be32(&lbc->fbcr, 3); - set_addr(mtd, 6, page_addr, 1); - - ctrl->read_bytes = mtd->writesize + 9; - - fsl_elbc_do_read(chip, 1); - fsl_elbc_run_command(mtd); - - memcpy_fromio(ctrl->oob_poi + 6, - &ctrl->addr[ctrl->index], 3); - ctrl->index += 3; - } - - ctrl->oob_poi = NULL; return; } @@ -443,8 +448,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, /* Note - it does not wait for the ready line */ case NAND_CMD_STATUS: out_be32(&lbc->fir, - (FIR_OP_CM0 << FIR_OP0_SHIFT) | - (FIR_OP_RBW << FIR_OP1_SHIFT)); + (FIR_OP_CM0 << FIR_OP0_SHIFT) | + (FIR_OP_RBW << FIR_OP1_SHIFT)); out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); out_be32(&lbc->fbcr, 1); set_addr(mtd, 0, 0, 0); @@ -468,7 +473,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, default: printf("fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", - command); + command); } } @@ -560,7 +565,7 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) * Verify buffer against the FCM Controller Data Buffer */ static int fsl_elbc_verify_buf(struct mtd_info *mtd, - const u_char *buf, int len) + const u_char *buf, int len) { struct nand_chip *chip = mtd->priv; struct fsl_elbc_mtd *priv = chip->priv; @@ -596,7 +601,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) { struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_ctrl *ctrl = priv->ctrl; - lbus83xx_t *lbc = ctrl->regs; + fsl_lbc_t *lbc = ctrl->regs; if (ctrl->status != LTESR_CC) return NAND_STATUS_FAIL; @@ -604,8 +609,8 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) /* Use READ_STATUS command, but wait for the device to be ready */ ctrl->use_mdr = 0; out_be32(&lbc->fir, - (FIR_OP_CW0 << FIR_OP0_SHIFT) | - (FIR_OP_RBW << FIR_OP1_SHIFT)); + (FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_RBW << FIR_OP1_SHIFT)); out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); out_be32(&lbc->fbcr, 1); set_addr(mtd, 0, 0, 0); @@ -623,9 +628,8 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) return fsl_elbc_read_byte(mtd); } -static int fsl_elbc_read_page(struct mtd_info *mtd, - struct nand_chip *chip, - uint8_t *buf) +static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) { fsl_elbc_read_buf(mtd, buf, mtd->writesize); fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -639,30 +643,24 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static void fsl_elbc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf) +static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required) { - struct fsl_elbc_mtd *priv = chip->priv; - struct fsl_elbc_ctrl *ctrl = priv->ctrl; - fsl_elbc_write_buf(mtd, buf, mtd->writesize); fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); - ctrl->oob_poi = chip->oob_poi; + return 0; } static struct fsl_elbc_ctrl *elbc_ctrl; static void fsl_elbc_ctrl_init(void) { - immap_t *im = (immap_t *)CFG_IMMR; - elbc_ctrl = kzalloc(sizeof(*elbc_ctrl), GFP_KERNEL); if (!elbc_ctrl) return; - elbc_ctrl->regs = &im->lbus; + elbc_ctrl->regs = LBC_BASE_ADDR; /* clear event registers */ out_be32(&elbc_ctrl->regs->ltesr, LTESR_NAND_MASK); @@ -676,10 +674,13 @@ static void fsl_elbc_ctrl_init(void) elbc_ctrl->addr = NULL; } -int board_nand_init(struct nand_chip *nand) +static int fsl_elbc_chip_init(int devnum, u8 *addr) { + struct mtd_info *mtd = &nand_info[devnum]; + struct nand_chip *nand; struct fsl_elbc_mtd *priv; - uint32_t br, or; + uint32_t br = 0, or = 0; + int ret; if (!elbc_ctrl) { fsl_elbc_ctrl_init(); @@ -692,17 +693,19 @@ int board_nand_init(struct nand_chip *nand) return -ENOMEM; priv->ctrl = elbc_ctrl; - priv->vbase = nand->IO_ADDR_R; + priv->vbase = addr; /* Find which chip select it is connected to. It'd be nice * if we could pass more than one datum to the NAND driver... */ for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) { + phys_addr_t phys_addr = virt_to_phys(addr); + br = in_be32(&elbc_ctrl->regs->bank[priv->bank].br); or = in_be32(&elbc_ctrl->regs->bank[priv->bank].or); if ((br & BR_V) && (br & BR_MSEL) == BR_MS_FCM && - (br & or & BR_BA) == (phys_addr_t)nand->IO_ADDR_R) + (br & or & BR_BA) == BR_PHYS_ADDR(phys_addr)) break; } @@ -712,6 +715,9 @@ int board_nand_init(struct nand_chip *nand) return -ENODEV; } + nand = &priv->chip; + mtd->priv = nand; + elbc_ctrl->chips[priv->bank] = priv; /* fill in nand_chip structure */ @@ -725,7 +731,12 @@ int board_nand_init(struct nand_chip *nand) nand->waitfunc = fsl_elbc_wait; /* set up nand options */ - nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; + nand->bbt_td = &bbt_main_descr; + nand->bbt_md = &bbt_mirror_descr; + + /* set up nand options */ + nand->options = NAND_NO_SUBPAGE_WRITE; + nand->bbt_options = NAND_BBT_USE_FLASH; nand->controller = &elbc_ctrl->controller; nand->priv = priv; @@ -733,36 +744,82 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.read_page = fsl_elbc_read_page; nand->ecc.write_page = fsl_elbc_write_page; + priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT); + /* If CS Base Register selects full hardware ECC then use it */ if ((br & BR_DECC) == BR_DECC_CHK_GEN) { nand->ecc.mode = NAND_ECC_HW; nand->ecc.layout = (priv->fmr & FMR_ECCM) ? - &fsl_elbc_oob_sp_eccm1 : - &fsl_elbc_oob_sp_eccm0; + &fsl_elbc_oob_sp_eccm1 : + &fsl_elbc_oob_sp_eccm0; nand->ecc.size = 512; nand->ecc.bytes = 3; nand->ecc.steps = 1; + nand->ecc.strength = 1; } else { /* otherwise fall back to default software ECC */ nand->ecc.mode = NAND_ECC_SOFT; } - priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT); + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) + return ret; + + /* Large-page-specific setup */ + if (mtd->writesize == 2048) { + setbits_be32(&elbc_ctrl->regs->bank[priv->bank].or, + OR_FCM_PGS); + in_be32(&elbc_ctrl->regs->bank[priv->bank].or); - /* adjust Option Register and ECC to match Flash page size */ - if (or & OR_FCM_PGS) { priv->page_size = 1; + nand->badblock_pattern = &largepage_memorybased; + + /* + * Hardware expects small page has ECCM0, large page has + * ECCM1 when booting from NAND, and we follow that even + * when not booting from NAND. + */ + priv->fmr |= FMR_ECCM; /* adjust ecc setup if needed */ if ((br & BR_DECC) == BR_DECC_CHK_GEN) { nand->ecc.steps = 4; nand->ecc.layout = (priv->fmr & FMR_ECCM) ? - &fsl_elbc_oob_lp_eccm1 : - &fsl_elbc_oob_lp_eccm0; + &fsl_elbc_oob_lp_eccm1 : + &fsl_elbc_oob_lp_eccm0; } + } else if (mtd->writesize == 512) { + clrbits_be32(&elbc_ctrl->regs->bank[priv->bank].or, + OR_FCM_PGS); + in_be32(&elbc_ctrl->regs->bank[priv->bank].or); + } else { + return -ENODEV; } + ret = nand_scan_tail(mtd); + if (ret) + return ret; + + ret = nand_register(devnum); + if (ret) + return ret; + return 0; } + +#ifndef CONFIG_SYS_NAND_BASE_LIST +#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } +#endif + +static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] = + CONFIG_SYS_NAND_BASE_LIST; + +void board_nand_init(void) +{ + int i; + + for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) + fsl_elbc_chip_init(i, (u8 *)base_address[i]); +}