X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmtd%2Fnand%2Ffsl_ifc_nand.c;h=98a09c0641c5ffc59fbf27bb08dafcb210c089c1;hb=af1679bc30b11b90f9f6650d211b3fe350f4044f;hp=0878bece675bd3267d044919dbf0c870d966042b;hpb=612404c28a64a6df300642a1550a65dcc8e01f82;p=u-boot diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 0878bece67..98a09c0641 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -4,23 +4,12 @@ * * Authors: Dipen Dudhat * - * 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 @@ -41,7 +30,6 @@ struct fsl_ifc_ctrl; /* mtd information per set */ struct fsl_ifc_mtd { - struct mtd_info mtd; struct nand_chip chip; struct fsl_ifc_ctrl *ctrl; @@ -391,7 +379,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, timing = IFC_FIR_OP_RBCD; out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | (timing << IFC_NAND_FIR0_OP2_SHIFT)); out_be32(&ifc->ifc_nand.nand_fcr0, @@ -686,9 +674,8 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) return nand_fsr; } -static int fsl_ifc_read_page(struct mtd_info *mtd, - struct nand_chip *chip, - uint8_t *buf, int page) +static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) { struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; @@ -705,12 +692,13 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static void fsl_ifc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf) +static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required) { fsl_ifc_write_buf(mtd, buf, mtd->writesize); fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; } static void fsl_ifc_ctrl_init(void) @@ -758,7 +746,7 @@ static void fsl_ifc_sram_init(void) /* READID */ out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); out_be32(&ifc->ifc_nand.nand_fcr0, @@ -794,11 +782,14 @@ static void fsl_ifc_sram_init(void) out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext); } -int board_nand_init(struct nand_chip *nand) +static int fsl_ifc_chip_init(int devnum, u8 *addr) { + struct mtd_info *mtd = &nand_info[devnum]; + struct nand_chip *nand; struct fsl_ifc_mtd *priv; struct nand_ecclayout *layout; uint32_t cspr = 0, csor = 0, ver = 0; + int ret; if (!ifc_ctrl) { fsl_ifc_ctrl_init(); @@ -811,18 +802,18 @@ int board_nand_init(struct nand_chip *nand) return -ENOMEM; priv->ctrl = ifc_ctrl; - priv->vbase = nand->IO_ADDR_R; + priv->vbase = addr; /* Find which chip select it is connected to. */ for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) { - phys_addr_t base_addr = virt_to_phys(nand->IO_ADDR_R); + phys_addr_t phys_addr = virt_to_phys(addr); cspr = in_be32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr); csor = in_be32(&ifc_ctrl->regs->csor_cs[priv->bank].csor); if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND && - (cspr & CSPR_BA) == CSPR_PHYS_ADDR(base_addr)) { + (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) { ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT; break; } @@ -835,6 +826,9 @@ int board_nand_init(struct nand_chip *nand) return -ENODEV; } + nand = &priv->chip; + mtd->priv = nand; + ifc_ctrl->chips[priv->bank] = priv; /* fill in nand_chip structure */ @@ -852,8 +846,8 @@ int board_nand_init(struct nand_chip *nand) nand->bbt_md = &bbt_mirror_descr; /* set up nand options */ - nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | - NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE; + nand->options = NAND_NO_SUBPAGE_WRITE; + nand->bbt_options = NAND_BBT_USE_FLASH; if (cspr & CSPR_PORT_SIZE_16) { nand->read_byte = fsl_ifc_read_byte16; @@ -884,11 +878,13 @@ int board_nand_init(struct nand_chip *nand) bbt_mirror_descr.offs = 0; } + nand->ecc.strength = 4; priv->bufnum_mask = 15; break; case CSOR_NAND_PGS_2K: layout = &oob_2048_ecc4; + nand->ecc.strength = 4; priv->bufnum_mask = 3; break; @@ -896,8 +892,10 @@ int board_nand_init(struct nand_chip *nand) if ((csor & CSOR_NAND_ECC_MODE_MASK) == CSOR_NAND_ECC_MODE_4) { layout = &oob_4096_ecc4; + nand->ecc.strength = 4; } else { layout = &oob_4096_ecc8; + nand->ecc.strength = 8; nand->ecc.bytes = 16; } @@ -921,5 +919,31 @@ int board_nand_init(struct nand_chip *nand) if (ver == FSL_IFC_V1_1_0) fsl_ifc_sram_init(); + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) + return ret; + + 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_ifc_chip_init(i, (u8 *)base_address[i]); +}