diff options
Diffstat (limited to 'drivers/mtd/nand/fsl_ifc_nand.c')
| -rw-r--r-- | drivers/mtd/nand/fsl_ifc_nand.c | 62 | 
1 files changed, 49 insertions, 13 deletions
| diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index b13d8a930..439822c5a 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -21,6 +21,7 @@  #include <common.h>  #include <malloc.h> +#include <nand.h>  #include <linux/mtd/mtd.h>  #include <linux/mtd/nand.h> @@ -41,7 +42,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; @@ -686,9 +686,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 +704,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) @@ -794,11 +794,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 +814,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 +838,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 +858,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 +890,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 +904,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 +931,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]); +} |