11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
293db446aSBoris Brezillon /* Freescale Enhanced Local Bus Controller NAND driver
393db446aSBoris Brezillon  *
493db446aSBoris Brezillon  * Copyright © 2006-2007, 2010 Freescale Semiconductor
593db446aSBoris Brezillon  *
693db446aSBoris Brezillon  * Authors: Nick Spence <nick.spence@freescale.com>,
793db446aSBoris Brezillon  *          Scott Wood <scottwood@freescale.com>
893db446aSBoris Brezillon  *          Jack Lan <jack.lan@freescale.com>
993db446aSBoris Brezillon  *          Roy Zang <tie-fei.zang@freescale.com>
1093db446aSBoris Brezillon  */
1193db446aSBoris Brezillon 
1293db446aSBoris Brezillon #include <linux/module.h>
1393db446aSBoris Brezillon #include <linux/types.h>
1493db446aSBoris Brezillon #include <linux/kernel.h>
1593db446aSBoris Brezillon #include <linux/string.h>
1693db446aSBoris Brezillon #include <linux/ioport.h>
1793db446aSBoris Brezillon #include <linux/of_address.h>
1893db446aSBoris Brezillon #include <linux/of_platform.h>
1993db446aSBoris Brezillon #include <linux/platform_device.h>
2093db446aSBoris Brezillon #include <linux/slab.h>
2193db446aSBoris Brezillon #include <linux/interrupt.h>
2293db446aSBoris Brezillon 
2393db446aSBoris Brezillon #include <linux/mtd/mtd.h>
2493db446aSBoris Brezillon #include <linux/mtd/rawnand.h>
2593db446aSBoris Brezillon #include <linux/mtd/partitions.h>
2693db446aSBoris Brezillon 
2793db446aSBoris Brezillon #include <asm/io.h>
2893db446aSBoris Brezillon #include <asm/fsl_lbc.h>
2993db446aSBoris Brezillon 
3093db446aSBoris Brezillon #define MAX_BANKS 8
3193db446aSBoris Brezillon #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
3293db446aSBoris Brezillon #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
3393db446aSBoris Brezillon 
3493db446aSBoris Brezillon /* mtd information per set */
3593db446aSBoris Brezillon 
3693db446aSBoris Brezillon struct fsl_elbc_mtd {
3793db446aSBoris Brezillon 	struct nand_chip chip;
3893db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl;
3993db446aSBoris Brezillon 
4093db446aSBoris Brezillon 	struct device *dev;
4193db446aSBoris Brezillon 	int bank;               /* Chip select bank number           */
4293db446aSBoris Brezillon 	u8 __iomem *vbase;      /* Chip select base virtual address  */
4393db446aSBoris Brezillon 	int page_size;          /* NAND page size (0=512, 1=2048)    */
4493db446aSBoris Brezillon 	unsigned int fmr;       /* FCM Flash Mode Register value     */
4593db446aSBoris Brezillon };
4693db446aSBoris Brezillon 
4793db446aSBoris Brezillon /* Freescale eLBC FCM controller information */
4893db446aSBoris Brezillon 
4993db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl {
507da45139SMiquel Raynal 	struct nand_controller controller;
5193db446aSBoris Brezillon 	struct fsl_elbc_mtd *chips[MAX_BANKS];
5293db446aSBoris Brezillon 
5393db446aSBoris Brezillon 	u8 __iomem *addr;        /* Address of assigned FCM buffer        */
5493db446aSBoris Brezillon 	unsigned int page;       /* Last page written to / read from      */
5593db446aSBoris Brezillon 	unsigned int read_bytes; /* Number of bytes read during command   */
5693db446aSBoris Brezillon 	unsigned int column;     /* Saved column from SEQIN               */
5793db446aSBoris Brezillon 	unsigned int index;      /* Pointer to next byte to 'read'        */
5893db446aSBoris Brezillon 	unsigned int status;     /* status read from LTESR after last op  */
5993db446aSBoris Brezillon 	unsigned int mdr;        /* UPM/FCM Data Register value           */
6093db446aSBoris Brezillon 	unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
6193db446aSBoris Brezillon 	unsigned int oob;        /* Non zero if operating on OOB data     */
6293db446aSBoris Brezillon 	unsigned int counter;	 /* counter for the initializations	  */
6393db446aSBoris Brezillon 	unsigned int max_bitflips;  /* Saved during READ0 cmd		  */
6493db446aSBoris Brezillon };
6593db446aSBoris Brezillon 
6693db446aSBoris Brezillon /* These map to the positions used by the FCM hardware ECC generator */
6793db446aSBoris Brezillon 
fsl_elbc_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * oobregion)6893db446aSBoris Brezillon static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section,
6993db446aSBoris Brezillon 				  struct mtd_oob_region *oobregion)
7093db446aSBoris Brezillon {
7193db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
7293db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
7393db446aSBoris Brezillon 
7493db446aSBoris Brezillon 	if (section >= chip->ecc.steps)
7593db446aSBoris Brezillon 		return -ERANGE;
7693db446aSBoris Brezillon 
7793db446aSBoris Brezillon 	oobregion->offset = (16 * section) + 6;
7893db446aSBoris Brezillon 	if (priv->fmr & FMR_ECCM)
7993db446aSBoris Brezillon 		oobregion->offset += 2;
8093db446aSBoris Brezillon 
8193db446aSBoris Brezillon 	oobregion->length = chip->ecc.bytes;
8293db446aSBoris Brezillon 
8393db446aSBoris Brezillon 	return 0;
8493db446aSBoris Brezillon }
8593db446aSBoris Brezillon 
fsl_elbc_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * oobregion)8693db446aSBoris Brezillon static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section,
8793db446aSBoris Brezillon 				   struct mtd_oob_region *oobregion)
8893db446aSBoris Brezillon {
8993db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
9093db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
9193db446aSBoris Brezillon 
9293db446aSBoris Brezillon 	if (section > chip->ecc.steps)
9393db446aSBoris Brezillon 		return -ERANGE;
9493db446aSBoris Brezillon 
9593db446aSBoris Brezillon 	if (!section) {
9693db446aSBoris Brezillon 		oobregion->offset = 0;
9793db446aSBoris Brezillon 		if (mtd->writesize > 512)
9893db446aSBoris Brezillon 			oobregion->offset++;
9993db446aSBoris Brezillon 		oobregion->length = (priv->fmr & FMR_ECCM) ? 7 : 5;
10093db446aSBoris Brezillon 	} else {
10193db446aSBoris Brezillon 		oobregion->offset = (16 * section) -
10293db446aSBoris Brezillon 				    ((priv->fmr & FMR_ECCM) ? 5 : 7);
10393db446aSBoris Brezillon 		if (section < chip->ecc.steps)
10493db446aSBoris Brezillon 			oobregion->length = 13;
10593db446aSBoris Brezillon 		else
10693db446aSBoris Brezillon 			oobregion->length = mtd->oobsize - oobregion->offset;
10793db446aSBoris Brezillon 	}
10893db446aSBoris Brezillon 
10993db446aSBoris Brezillon 	return 0;
11093db446aSBoris Brezillon }
11193db446aSBoris Brezillon 
11293db446aSBoris Brezillon static const struct mtd_ooblayout_ops fsl_elbc_ooblayout_ops = {
11393db446aSBoris Brezillon 	.ecc = fsl_elbc_ooblayout_ecc,
11493db446aSBoris Brezillon 	.free = fsl_elbc_ooblayout_free,
11593db446aSBoris Brezillon };
11693db446aSBoris Brezillon 
11793db446aSBoris Brezillon /*
11893db446aSBoris Brezillon  * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
11993db446aSBoris Brezillon  * interfere with ECC positions, that's why we implement our own descriptors.
12093db446aSBoris Brezillon  * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0.
12193db446aSBoris Brezillon  */
12293db446aSBoris Brezillon static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
12393db446aSBoris Brezillon static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
12493db446aSBoris Brezillon 
12593db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_descr = {
12693db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
12793db446aSBoris Brezillon 		   NAND_BBT_2BIT | NAND_BBT_VERSION,
12893db446aSBoris Brezillon 	.offs =	11,
12993db446aSBoris Brezillon 	.len = 4,
13093db446aSBoris Brezillon 	.veroffs = 15,
13193db446aSBoris Brezillon 	.maxblocks = 4,
13293db446aSBoris Brezillon 	.pattern = bbt_pattern,
13393db446aSBoris Brezillon };
13493db446aSBoris Brezillon 
13593db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_descr = {
13693db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
13793db446aSBoris Brezillon 		   NAND_BBT_2BIT | NAND_BBT_VERSION,
13893db446aSBoris Brezillon 	.offs =	11,
13993db446aSBoris Brezillon 	.len = 4,
14093db446aSBoris Brezillon 	.veroffs = 15,
14193db446aSBoris Brezillon 	.maxblocks = 4,
14293db446aSBoris Brezillon 	.pattern = mirror_pattern,
14393db446aSBoris Brezillon };
14493db446aSBoris Brezillon 
14593db446aSBoris Brezillon /*=================================*/
14693db446aSBoris Brezillon 
14793db446aSBoris Brezillon /*
14893db446aSBoris Brezillon  * Set up the FCM hardware block and page address fields, and the fcm
14993db446aSBoris Brezillon  * structure addr field to point to the correct FCM buffer in memory
15093db446aSBoris Brezillon  */
set_addr(struct mtd_info * mtd,int column,int page_addr,int oob)15193db446aSBoris Brezillon static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
15293db446aSBoris Brezillon {
15393db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
15493db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
15593db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
15693db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
15793db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
15893db446aSBoris Brezillon 	int buf_num;
15993db446aSBoris Brezillon 
16093db446aSBoris Brezillon 	elbc_fcm_ctrl->page = page_addr;
16193db446aSBoris Brezillon 
16293db446aSBoris Brezillon 	if (priv->page_size) {
16393db446aSBoris Brezillon 		/*
16493db446aSBoris Brezillon 		 * large page size chip : FPAR[PI] save the lowest 6 bits,
16593db446aSBoris Brezillon 		 *                        FBAR[BLK] save the other bits.
16693db446aSBoris Brezillon 		 */
16793db446aSBoris Brezillon 		out_be32(&lbc->fbar, page_addr >> 6);
16893db446aSBoris Brezillon 		out_be32(&lbc->fpar,
16993db446aSBoris Brezillon 		         ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
17093db446aSBoris Brezillon 		         (oob ? FPAR_LP_MS : 0) | column);
17193db446aSBoris Brezillon 		buf_num = (page_addr & 1) << 2;
17293db446aSBoris Brezillon 	} else {
17393db446aSBoris Brezillon 		/*
17493db446aSBoris Brezillon 		 * small page size chip : FPAR[PI] save the lowest 5 bits,
17593db446aSBoris Brezillon 		 *                        FBAR[BLK] save the other bits.
17693db446aSBoris Brezillon 		 */
17793db446aSBoris Brezillon 		out_be32(&lbc->fbar, page_addr >> 5);
17893db446aSBoris Brezillon 		out_be32(&lbc->fpar,
17993db446aSBoris Brezillon 		         ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
18093db446aSBoris Brezillon 		         (oob ? FPAR_SP_MS : 0) | column);
18193db446aSBoris Brezillon 		buf_num = page_addr & 7;
18293db446aSBoris Brezillon 	}
18393db446aSBoris Brezillon 
18493db446aSBoris Brezillon 	elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
18593db446aSBoris Brezillon 	elbc_fcm_ctrl->index = column;
18693db446aSBoris Brezillon 
18793db446aSBoris Brezillon 	/* for OOB data point to the second half of the buffer */
18893db446aSBoris Brezillon 	if (oob)
18993db446aSBoris Brezillon 		elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
19093db446aSBoris Brezillon 
19193db446aSBoris Brezillon 	dev_vdbg(priv->dev, "set_addr: bank=%d, "
19293db446aSBoris Brezillon 			    "elbc_fcm_ctrl->addr=0x%p (0x%p), "
19393db446aSBoris Brezillon 	                    "index %x, pes %d ps %d\n",
19493db446aSBoris Brezillon 		 buf_num, elbc_fcm_ctrl->addr, priv->vbase,
19593db446aSBoris Brezillon 		 elbc_fcm_ctrl->index,
19693db446aSBoris Brezillon 	         chip->phys_erase_shift, chip->page_shift);
19793db446aSBoris Brezillon }
19893db446aSBoris Brezillon 
19993db446aSBoris Brezillon /*
20093db446aSBoris Brezillon  * execute FCM command and wait for it to complete
20193db446aSBoris Brezillon  */
fsl_elbc_run_command(struct mtd_info * mtd)20293db446aSBoris Brezillon static int fsl_elbc_run_command(struct mtd_info *mtd)
20393db446aSBoris Brezillon {
20493db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
20593db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
20693db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
20793db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
20893db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
20993db446aSBoris Brezillon 
21093db446aSBoris Brezillon 	/* Setup the FMR[OP] to execute without write protection */
21193db446aSBoris Brezillon 	out_be32(&lbc->fmr, priv->fmr | 3);
21293db446aSBoris Brezillon 	if (elbc_fcm_ctrl->use_mdr)
21393db446aSBoris Brezillon 		out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
21493db446aSBoris Brezillon 
21593db446aSBoris Brezillon 	dev_vdbg(priv->dev,
21693db446aSBoris Brezillon 	         "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
21793db446aSBoris Brezillon 	         in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
21893db446aSBoris Brezillon 	dev_vdbg(priv->dev,
21993db446aSBoris Brezillon 	         "fsl_elbc_run_command: fbar=%08x fpar=%08x "
22093db446aSBoris Brezillon 	         "fbcr=%08x bank=%d\n",
22193db446aSBoris Brezillon 	         in_be32(&lbc->fbar), in_be32(&lbc->fpar),
22293db446aSBoris Brezillon 	         in_be32(&lbc->fbcr), priv->bank);
22393db446aSBoris Brezillon 
22493db446aSBoris Brezillon 	ctrl->irq_status = 0;
22593db446aSBoris Brezillon 	/* execute special operation */
22693db446aSBoris Brezillon 	out_be32(&lbc->lsor, priv->bank);
22793db446aSBoris Brezillon 
22893db446aSBoris Brezillon 	/* wait for FCM complete flag or timeout */
22993db446aSBoris Brezillon 	wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
23093db446aSBoris Brezillon 	                   FCM_TIMEOUT_MSECS * HZ/1000);
23193db446aSBoris Brezillon 	elbc_fcm_ctrl->status = ctrl->irq_status;
23293db446aSBoris Brezillon 	/* store mdr value in case it was needed */
23393db446aSBoris Brezillon 	if (elbc_fcm_ctrl->use_mdr)
23493db446aSBoris Brezillon 		elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
23593db446aSBoris Brezillon 
23693db446aSBoris Brezillon 	elbc_fcm_ctrl->use_mdr = 0;
23793db446aSBoris Brezillon 
23893db446aSBoris Brezillon 	if (elbc_fcm_ctrl->status != LTESR_CC) {
23993db446aSBoris Brezillon 		dev_info(priv->dev,
24093db446aSBoris Brezillon 		         "command failed: fir %x fcr %x status %x mdr %x\n",
24193db446aSBoris Brezillon 		         in_be32(&lbc->fir), in_be32(&lbc->fcr),
24293db446aSBoris Brezillon 			 elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
24393db446aSBoris Brezillon 		return -EIO;
24493db446aSBoris Brezillon 	}
24593db446aSBoris Brezillon 
246bace41f8SMiquel Raynal 	if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
24793db446aSBoris Brezillon 		return 0;
24893db446aSBoris Brezillon 
24993db446aSBoris Brezillon 	elbc_fcm_ctrl->max_bitflips = 0;
25093db446aSBoris Brezillon 
25193db446aSBoris Brezillon 	if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) {
25293db446aSBoris Brezillon 		uint32_t lteccr = in_be32(&lbc->lteccr);
25393db446aSBoris Brezillon 		/*
25493db446aSBoris Brezillon 		 * if command was a full page read and the ELBC
25593db446aSBoris Brezillon 		 * has the LTECCR register, then bits 12-15 (ppc order) of
25693db446aSBoris Brezillon 		 * LTECCR indicates which 512 byte sub-pages had fixed errors.
25793db446aSBoris Brezillon 		 * bits 28-31 are uncorrectable errors, marked elsewhere.
25893db446aSBoris Brezillon 		 * for small page nand only 1 bit is used.
25993db446aSBoris Brezillon 		 * if the ELBC doesn't have the lteccr register it reads 0
26093db446aSBoris Brezillon 		 * FIXME: 4 bits can be corrected on NANDs with 2k pages, so
26193db446aSBoris Brezillon 		 * count the number of sub-pages with bitflips and update
26293db446aSBoris Brezillon 		 * ecc_stats.corrected accordingly.
26393db446aSBoris Brezillon 		 */
26493db446aSBoris Brezillon 		if (lteccr & 0x000F000F)
26593db446aSBoris Brezillon 			out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */
26693db446aSBoris Brezillon 		if (lteccr & 0x000F0000) {
26793db446aSBoris Brezillon 			mtd->ecc_stats.corrected++;
26893db446aSBoris Brezillon 			elbc_fcm_ctrl->max_bitflips = 1;
26993db446aSBoris Brezillon 		}
27093db446aSBoris Brezillon 	}
27193db446aSBoris Brezillon 
27293db446aSBoris Brezillon 	return 0;
27393db446aSBoris Brezillon }
27493db446aSBoris Brezillon 
fsl_elbc_do_read(struct nand_chip * chip,int oob)27593db446aSBoris Brezillon static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
27693db446aSBoris Brezillon {
27793db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
27893db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
27993db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
28093db446aSBoris Brezillon 
28193db446aSBoris Brezillon 	if (priv->page_size) {
28293db446aSBoris Brezillon 		out_be32(&lbc->fir,
28393db446aSBoris Brezillon 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
28493db446aSBoris Brezillon 		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
28593db446aSBoris Brezillon 		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
28693db446aSBoris Brezillon 		         (FIR_OP_CM1 << FIR_OP3_SHIFT) |
28793db446aSBoris Brezillon 		         (FIR_OP_RBW << FIR_OP4_SHIFT));
28893db446aSBoris Brezillon 
28993db446aSBoris Brezillon 		out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
29093db446aSBoris Brezillon 		                    (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
29193db446aSBoris Brezillon 	} else {
29293db446aSBoris Brezillon 		out_be32(&lbc->fir,
29393db446aSBoris Brezillon 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
29493db446aSBoris Brezillon 		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
29593db446aSBoris Brezillon 		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
29693db446aSBoris Brezillon 		         (FIR_OP_RBW << FIR_OP3_SHIFT));
29793db446aSBoris Brezillon 
29893db446aSBoris Brezillon 		if (oob)
29993db446aSBoris Brezillon 			out_be32(&lbc->fcr, NAND_CMD_READOOB << FCR_CMD0_SHIFT);
30093db446aSBoris Brezillon 		else
30193db446aSBoris Brezillon 			out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
30293db446aSBoris Brezillon 	}
30393db446aSBoris Brezillon }
30493db446aSBoris Brezillon 
30593db446aSBoris Brezillon /* cmdfunc send commands to the FCM */
fsl_elbc_cmdfunc(struct nand_chip * chip,unsigned int command,int column,int page_addr)3065295cf2eSBoris Brezillon static void fsl_elbc_cmdfunc(struct nand_chip *chip, unsigned int command,
30793db446aSBoris Brezillon                              int column, int page_addr)
30893db446aSBoris Brezillon {
3095295cf2eSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
31093db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
31193db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
31293db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
31393db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
31493db446aSBoris Brezillon 
31593db446aSBoris Brezillon 	elbc_fcm_ctrl->use_mdr = 0;
31693db446aSBoris Brezillon 
31793db446aSBoris Brezillon 	/* clear the read buffer */
31893db446aSBoris Brezillon 	elbc_fcm_ctrl->read_bytes = 0;
31993db446aSBoris Brezillon 	if (command != NAND_CMD_PAGEPROG)
32093db446aSBoris Brezillon 		elbc_fcm_ctrl->index = 0;
32193db446aSBoris Brezillon 
32293db446aSBoris Brezillon 	switch (command) {
32393db446aSBoris Brezillon 	/* READ0 and READ1 read the entire buffer to use hardware ECC. */
32493db446aSBoris Brezillon 	case NAND_CMD_READ1:
32593db446aSBoris Brezillon 		column += 256;
326025a06c1SMiquel Raynal 		fallthrough;
32793db446aSBoris Brezillon 	case NAND_CMD_READ0:
32893db446aSBoris Brezillon 		dev_dbg(priv->dev,
32993db446aSBoris Brezillon 		        "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
33093db446aSBoris Brezillon 		        " 0x%x, column: 0x%x.\n", page_addr, column);
33193db446aSBoris Brezillon 
33293db446aSBoris Brezillon 
33393db446aSBoris Brezillon 		out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
33493db446aSBoris Brezillon 		set_addr(mtd, 0, page_addr, 0);
33593db446aSBoris Brezillon 
33693db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
33793db446aSBoris Brezillon 		elbc_fcm_ctrl->index += column;
33893db446aSBoris Brezillon 
33993db446aSBoris Brezillon 		fsl_elbc_do_read(chip, 0);
34093db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
34193db446aSBoris Brezillon 		return;
34293db446aSBoris Brezillon 
343070fb974SMarek Behún 	/* RNDOUT moves the pointer inside the page */
344070fb974SMarek Behún 	case NAND_CMD_RNDOUT:
345070fb974SMarek Behún 		dev_dbg(priv->dev,
346070fb974SMarek Behún 			"fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n",
347070fb974SMarek Behún 			column);
348070fb974SMarek Behún 
349070fb974SMarek Behún 		elbc_fcm_ctrl->index = column;
350070fb974SMarek Behún 		return;
351070fb974SMarek Behún 
35293db446aSBoris Brezillon 	/* READOOB reads only the OOB because no ECC is performed. */
35393db446aSBoris Brezillon 	case NAND_CMD_READOOB:
35493db446aSBoris Brezillon 		dev_vdbg(priv->dev,
35593db446aSBoris Brezillon 		         "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
35693db446aSBoris Brezillon 			 " 0x%x, column: 0x%x.\n", page_addr, column);
35793db446aSBoris Brezillon 
35893db446aSBoris Brezillon 		out_be32(&lbc->fbcr, mtd->oobsize - column);
35993db446aSBoris Brezillon 		set_addr(mtd, column, page_addr, 1);
36093db446aSBoris Brezillon 
36193db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
36293db446aSBoris Brezillon 
36393db446aSBoris Brezillon 		fsl_elbc_do_read(chip, 1);
36493db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
36593db446aSBoris Brezillon 		return;
36693db446aSBoris Brezillon 
36793db446aSBoris Brezillon 	case NAND_CMD_READID:
36893db446aSBoris Brezillon 	case NAND_CMD_PARAM:
36993db446aSBoris Brezillon 		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command);
37093db446aSBoris Brezillon 
37193db446aSBoris Brezillon 		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
37293db446aSBoris Brezillon 		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
37393db446aSBoris Brezillon 		                    (FIR_OP_RBW << FIR_OP2_SHIFT));
37493db446aSBoris Brezillon 		out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT);
37593db446aSBoris Brezillon 		/*
37693db446aSBoris Brezillon 		 * although currently it's 8 bytes for READID, we always read
37793db446aSBoris Brezillon 		 * the maximum 256 bytes(for PARAM)
37893db446aSBoris Brezillon 		 */
37993db446aSBoris Brezillon 		out_be32(&lbc->fbcr, 256);
38093db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = 256;
38193db446aSBoris Brezillon 		elbc_fcm_ctrl->use_mdr = 1;
38293db446aSBoris Brezillon 		elbc_fcm_ctrl->mdr = column;
38393db446aSBoris Brezillon 		set_addr(mtd, 0, 0, 0);
38493db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
38593db446aSBoris Brezillon 		return;
38693db446aSBoris Brezillon 
38793db446aSBoris Brezillon 	/* ERASE1 stores the block and page address */
38893db446aSBoris Brezillon 	case NAND_CMD_ERASE1:
38993db446aSBoris Brezillon 		dev_vdbg(priv->dev,
39093db446aSBoris Brezillon 		         "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
39193db446aSBoris Brezillon 		         "page_addr: 0x%x.\n", page_addr);
39293db446aSBoris Brezillon 		set_addr(mtd, 0, page_addr, 0);
39393db446aSBoris Brezillon 		return;
39493db446aSBoris Brezillon 
39593db446aSBoris Brezillon 	/* ERASE2 uses the block and page address from ERASE1 */
39693db446aSBoris Brezillon 	case NAND_CMD_ERASE2:
39793db446aSBoris Brezillon 		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
39893db446aSBoris Brezillon 
39993db446aSBoris Brezillon 		out_be32(&lbc->fir,
40093db446aSBoris Brezillon 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
40193db446aSBoris Brezillon 		         (FIR_OP_PA  << FIR_OP1_SHIFT) |
40293db446aSBoris Brezillon 		         (FIR_OP_CM2 << FIR_OP2_SHIFT) |
40393db446aSBoris Brezillon 		         (FIR_OP_CW1 << FIR_OP3_SHIFT) |
40493db446aSBoris Brezillon 		         (FIR_OP_RS  << FIR_OP4_SHIFT));
40593db446aSBoris Brezillon 
40693db446aSBoris Brezillon 		out_be32(&lbc->fcr,
40793db446aSBoris Brezillon 		         (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
40893db446aSBoris Brezillon 		         (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
40993db446aSBoris Brezillon 		         (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
41093db446aSBoris Brezillon 
41193db446aSBoris Brezillon 		out_be32(&lbc->fbcr, 0);
41293db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = 0;
41393db446aSBoris Brezillon 		elbc_fcm_ctrl->use_mdr = 1;
41493db446aSBoris Brezillon 
41593db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
41693db446aSBoris Brezillon 		return;
41793db446aSBoris Brezillon 
41893db446aSBoris Brezillon 	/* SEQIN sets up the addr buffer and all registers except the length */
41993db446aSBoris Brezillon 	case NAND_CMD_SEQIN: {
42093db446aSBoris Brezillon 		__be32 fcr;
42193db446aSBoris Brezillon 		dev_vdbg(priv->dev,
42293db446aSBoris Brezillon 			 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
42393db446aSBoris Brezillon 		         "page_addr: 0x%x, column: 0x%x.\n",
42493db446aSBoris Brezillon 		         page_addr, column);
42593db446aSBoris Brezillon 
42693db446aSBoris Brezillon 		elbc_fcm_ctrl->column = column;
42793db446aSBoris Brezillon 		elbc_fcm_ctrl->use_mdr = 1;
42893db446aSBoris Brezillon 
42993db446aSBoris Brezillon 		if (column >= mtd->writesize) {
43093db446aSBoris Brezillon 			/* OOB area */
43193db446aSBoris Brezillon 			column -= mtd->writesize;
43293db446aSBoris Brezillon 			elbc_fcm_ctrl->oob = 1;
43393db446aSBoris Brezillon 		} else {
43493db446aSBoris Brezillon 			WARN_ON(column != 0);
43593db446aSBoris Brezillon 			elbc_fcm_ctrl->oob = 0;
43693db446aSBoris Brezillon 		}
43793db446aSBoris Brezillon 
43893db446aSBoris Brezillon 		fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
43993db446aSBoris Brezillon 		      (NAND_CMD_SEQIN    << FCR_CMD2_SHIFT) |
44093db446aSBoris Brezillon 		      (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT);
44193db446aSBoris Brezillon 
44293db446aSBoris Brezillon 		if (priv->page_size) {
44393db446aSBoris Brezillon 			out_be32(&lbc->fir,
44493db446aSBoris Brezillon 			         (FIR_OP_CM2 << FIR_OP0_SHIFT) |
44593db446aSBoris Brezillon 			         (FIR_OP_CA  << FIR_OP1_SHIFT) |
44693db446aSBoris Brezillon 			         (FIR_OP_PA  << FIR_OP2_SHIFT) |
44793db446aSBoris Brezillon 			         (FIR_OP_WB  << FIR_OP3_SHIFT) |
44893db446aSBoris Brezillon 			         (FIR_OP_CM3 << FIR_OP4_SHIFT) |
44993db446aSBoris Brezillon 			         (FIR_OP_CW1 << FIR_OP5_SHIFT) |
45093db446aSBoris Brezillon 			         (FIR_OP_RS  << FIR_OP6_SHIFT));
45193db446aSBoris Brezillon 		} else {
45293db446aSBoris Brezillon 			out_be32(&lbc->fir,
45393db446aSBoris Brezillon 			         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
45493db446aSBoris Brezillon 			         (FIR_OP_CM2 << FIR_OP1_SHIFT) |
45593db446aSBoris Brezillon 			         (FIR_OP_CA  << FIR_OP2_SHIFT) |
45693db446aSBoris Brezillon 			         (FIR_OP_PA  << FIR_OP3_SHIFT) |
45793db446aSBoris Brezillon 			         (FIR_OP_WB  << FIR_OP4_SHIFT) |
45893db446aSBoris Brezillon 			         (FIR_OP_CM3 << FIR_OP5_SHIFT) |
45993db446aSBoris Brezillon 			         (FIR_OP_CW1 << FIR_OP6_SHIFT) |
46093db446aSBoris Brezillon 			         (FIR_OP_RS  << FIR_OP7_SHIFT));
46193db446aSBoris Brezillon 
46293db446aSBoris Brezillon 			if (elbc_fcm_ctrl->oob)
46393db446aSBoris Brezillon 				/* OOB area --> READOOB */
46493db446aSBoris Brezillon 				fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
46593db446aSBoris Brezillon 			else
46693db446aSBoris Brezillon 				/* First 256 bytes --> READ0 */
46793db446aSBoris Brezillon 				fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
46893db446aSBoris Brezillon 		}
46993db446aSBoris Brezillon 
47093db446aSBoris Brezillon 		out_be32(&lbc->fcr, fcr);
47193db446aSBoris Brezillon 		set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
47293db446aSBoris Brezillon 		return;
47393db446aSBoris Brezillon 	}
47493db446aSBoris Brezillon 
47593db446aSBoris Brezillon 	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
47693db446aSBoris Brezillon 	case NAND_CMD_PAGEPROG: {
47793db446aSBoris Brezillon 		dev_vdbg(priv->dev,
47893db446aSBoris Brezillon 		         "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
47993db446aSBoris Brezillon 			 "writing %d bytes.\n", elbc_fcm_ctrl->index);
48093db446aSBoris Brezillon 
48193db446aSBoris Brezillon 		/* if the write did not start at 0 or is not a full page
48293db446aSBoris Brezillon 		 * then set the exact length, otherwise use a full page
48393db446aSBoris Brezillon 		 * write so the HW generates the ECC.
48493db446aSBoris Brezillon 		 */
48593db446aSBoris Brezillon 		if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
48693db446aSBoris Brezillon 		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize)
48793db446aSBoris Brezillon 			out_be32(&lbc->fbcr,
48893db446aSBoris Brezillon 				elbc_fcm_ctrl->index - elbc_fcm_ctrl->column);
48993db446aSBoris Brezillon 		else
49093db446aSBoris Brezillon 			out_be32(&lbc->fbcr, 0);
49193db446aSBoris Brezillon 
49293db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
49393db446aSBoris Brezillon 		return;
49493db446aSBoris Brezillon 	}
49593db446aSBoris Brezillon 
49693db446aSBoris Brezillon 	/* CMD_STATUS must read the status byte while CEB is active */
49793db446aSBoris Brezillon 	/* Note - it does not wait for the ready line */
49893db446aSBoris Brezillon 	case NAND_CMD_STATUS:
49993db446aSBoris Brezillon 		out_be32(&lbc->fir,
50093db446aSBoris Brezillon 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
50193db446aSBoris Brezillon 		         (FIR_OP_RBW << FIR_OP1_SHIFT));
50293db446aSBoris Brezillon 		out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
50393db446aSBoris Brezillon 		out_be32(&lbc->fbcr, 1);
50493db446aSBoris Brezillon 		set_addr(mtd, 0, 0, 0);
50593db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = 1;
50693db446aSBoris Brezillon 
50793db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
50893db446aSBoris Brezillon 
50993db446aSBoris Brezillon 		/* The chip always seems to report that it is
51093db446aSBoris Brezillon 		 * write-protected, even when it is not.
51193db446aSBoris Brezillon 		 */
51293db446aSBoris Brezillon 		setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
51393db446aSBoris Brezillon 		return;
51493db446aSBoris Brezillon 
51593db446aSBoris Brezillon 	/* RESET without waiting for the ready line */
51693db446aSBoris Brezillon 	case NAND_CMD_RESET:
51793db446aSBoris Brezillon 		dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
51893db446aSBoris Brezillon 		out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
51993db446aSBoris Brezillon 		out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
52093db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
52193db446aSBoris Brezillon 		return;
52293db446aSBoris Brezillon 
52393db446aSBoris Brezillon 	default:
52493db446aSBoris Brezillon 		dev_err(priv->dev,
52593db446aSBoris Brezillon 		        "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
52693db446aSBoris Brezillon 		        command);
52793db446aSBoris Brezillon 	}
52893db446aSBoris Brezillon }
52993db446aSBoris Brezillon 
fsl_elbc_select_chip(struct nand_chip * chip,int cs)530758b56f5SBoris Brezillon static void fsl_elbc_select_chip(struct nand_chip *chip, int cs)
53193db446aSBoris Brezillon {
53293db446aSBoris Brezillon 	/* The hardware does not seem to support multiple
53393db446aSBoris Brezillon 	 * chips per bank.
53493db446aSBoris Brezillon 	 */
53593db446aSBoris Brezillon }
53693db446aSBoris Brezillon 
53793db446aSBoris Brezillon /*
53893db446aSBoris Brezillon  * Write buf to the FCM Controller Data Buffer
53993db446aSBoris Brezillon  */
fsl_elbc_write_buf(struct nand_chip * chip,const u8 * buf,int len)540c0739d85SBoris Brezillon static void fsl_elbc_write_buf(struct nand_chip *chip, const u8 *buf, int len)
54193db446aSBoris Brezillon {
542c0739d85SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
54393db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
54493db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
54593db446aSBoris Brezillon 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
54693db446aSBoris Brezillon 
54793db446aSBoris Brezillon 	if (len <= 0) {
54893db446aSBoris Brezillon 		dev_err(priv->dev, "write_buf of %d bytes", len);
54993db446aSBoris Brezillon 		elbc_fcm_ctrl->status = 0;
55093db446aSBoris Brezillon 		return;
55193db446aSBoris Brezillon 	}
55293db446aSBoris Brezillon 
55393db446aSBoris Brezillon 	if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
55493db446aSBoris Brezillon 		dev_err(priv->dev,
55593db446aSBoris Brezillon 		        "write_buf beyond end of buffer "
55693db446aSBoris Brezillon 		        "(%d requested, %u available)\n",
55793db446aSBoris Brezillon 			len, bufsize - elbc_fcm_ctrl->index);
55893db446aSBoris Brezillon 		len = bufsize - elbc_fcm_ctrl->index;
55993db446aSBoris Brezillon 	}
56093db446aSBoris Brezillon 
56193db446aSBoris Brezillon 	memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
56293db446aSBoris Brezillon 	/*
56393db446aSBoris Brezillon 	 * This is workaround for the weird elbc hangs during nand write,
56493db446aSBoris Brezillon 	 * Scott Wood says: "...perhaps difference in how long it takes a
56593db446aSBoris Brezillon 	 * write to make it through the localbus compared to a write to IMMR
56693db446aSBoris Brezillon 	 * is causing problems, and sync isn't helping for some reason."
56793db446aSBoris Brezillon 	 * Reading back the last byte helps though.
56893db446aSBoris Brezillon 	 */
56993db446aSBoris Brezillon 	in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
57093db446aSBoris Brezillon 
57193db446aSBoris Brezillon 	elbc_fcm_ctrl->index += len;
57293db446aSBoris Brezillon }
57393db446aSBoris Brezillon 
57493db446aSBoris Brezillon /*
57593db446aSBoris Brezillon  * read a byte from either the FCM hardware buffer if it has any data left
57693db446aSBoris Brezillon  * otherwise issue a command to read a single byte.
57793db446aSBoris Brezillon  */
fsl_elbc_read_byte(struct nand_chip * chip)5787e534323SBoris Brezillon static u8 fsl_elbc_read_byte(struct nand_chip *chip)
57993db446aSBoris Brezillon {
58093db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
58193db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
58293db446aSBoris Brezillon 
58393db446aSBoris Brezillon 	/* If there are still bytes in the FCM, then use the next byte. */
58493db446aSBoris Brezillon 	if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
58593db446aSBoris Brezillon 		return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
58693db446aSBoris Brezillon 
58793db446aSBoris Brezillon 	dev_err(priv->dev, "read_byte beyond end of buffer\n");
58893db446aSBoris Brezillon 	return ERR_BYTE;
58993db446aSBoris Brezillon }
59093db446aSBoris Brezillon 
59193db446aSBoris Brezillon /*
59293db446aSBoris Brezillon  * Read from the FCM Controller Data Buffer
59393db446aSBoris Brezillon  */
fsl_elbc_read_buf(struct nand_chip * chip,u8 * buf,int len)5947e534323SBoris Brezillon static void fsl_elbc_read_buf(struct nand_chip *chip, u8 *buf, int len)
59593db446aSBoris Brezillon {
59693db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
59793db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
59893db446aSBoris Brezillon 	int avail;
59993db446aSBoris Brezillon 
60093db446aSBoris Brezillon 	if (len < 0)
60193db446aSBoris Brezillon 		return;
60293db446aSBoris Brezillon 
60393db446aSBoris Brezillon 	avail = min((unsigned int)len,
60493db446aSBoris Brezillon 			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
60593db446aSBoris Brezillon 	memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
60693db446aSBoris Brezillon 	elbc_fcm_ctrl->index += avail;
60793db446aSBoris Brezillon 
60893db446aSBoris Brezillon 	if (len > avail)
60993db446aSBoris Brezillon 		dev_err(priv->dev,
61093db446aSBoris Brezillon 		        "read_buf beyond end of buffer "
61193db446aSBoris Brezillon 		        "(%d requested, %d available)\n",
61293db446aSBoris Brezillon 		        len, avail);
61393db446aSBoris Brezillon }
61493db446aSBoris Brezillon 
61593db446aSBoris Brezillon /* This function is called after Program and Erase Operations to
61693db446aSBoris Brezillon  * check for success or failure.
61793db446aSBoris Brezillon  */
fsl_elbc_wait(struct nand_chip * chip)618f1d46942SBoris Brezillon static int fsl_elbc_wait(struct nand_chip *chip)
61993db446aSBoris Brezillon {
62093db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
62193db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
62293db446aSBoris Brezillon 
62393db446aSBoris Brezillon 	if (elbc_fcm_ctrl->status != LTESR_CC)
62493db446aSBoris Brezillon 		return NAND_STATUS_FAIL;
62593db446aSBoris Brezillon 
62693db446aSBoris Brezillon 	/* The chip always seems to report that it is
62793db446aSBoris Brezillon 	 * write-protected, even when it is not.
62893db446aSBoris Brezillon 	 */
62993db446aSBoris Brezillon 	return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
63093db446aSBoris Brezillon }
63193db446aSBoris Brezillon 
fsl_elbc_read_page(struct nand_chip * chip,uint8_t * buf,int oob_required,int page)632b9761687SBoris Brezillon static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf,
633b9761687SBoris Brezillon 			      int oob_required, int page)
63493db446aSBoris Brezillon {
635b9761687SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
63693db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
63793db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
63893db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
63993db446aSBoris Brezillon 
64093db446aSBoris Brezillon 	nand_read_page_op(chip, page, 0, buf, mtd->writesize);
64193db446aSBoris Brezillon 	if (oob_required)
6427e534323SBoris Brezillon 		fsl_elbc_read_buf(chip, chip->oob_poi, mtd->oobsize);
64393db446aSBoris Brezillon 
644f1d46942SBoris Brezillon 	if (fsl_elbc_wait(chip) & NAND_STATUS_FAIL)
64593db446aSBoris Brezillon 		mtd->ecc_stats.failed++;
64693db446aSBoris Brezillon 
64793db446aSBoris Brezillon 	return elbc_fcm_ctrl->max_bitflips;
64893db446aSBoris Brezillon }
64993db446aSBoris Brezillon 
65093db446aSBoris Brezillon /* ECC will be calculated automatically, and errors will be detected in
65193db446aSBoris Brezillon  * waitfunc.
65293db446aSBoris Brezillon  */
fsl_elbc_write_page(struct nand_chip * chip,const uint8_t * buf,int oob_required,int page)653767eb6fbSBoris Brezillon static int fsl_elbc_write_page(struct nand_chip *chip, const uint8_t *buf,
654767eb6fbSBoris Brezillon 			       int oob_required, int page)
65593db446aSBoris Brezillon {
656767eb6fbSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
657767eb6fbSBoris Brezillon 
65893db446aSBoris Brezillon 	nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
659c0739d85SBoris Brezillon 	fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize);
66093db446aSBoris Brezillon 
66193db446aSBoris Brezillon 	return nand_prog_page_end_op(chip);
66293db446aSBoris Brezillon }
66393db446aSBoris Brezillon 
66493db446aSBoris Brezillon /* ECC will be calculated automatically, and errors will be detected in
66593db446aSBoris Brezillon  * waitfunc.
66693db446aSBoris Brezillon  */
fsl_elbc_write_subpage(struct nand_chip * chip,uint32_t offset,uint32_t data_len,const uint8_t * buf,int oob_required,int page)667767eb6fbSBoris Brezillon static int fsl_elbc_write_subpage(struct nand_chip *chip, uint32_t offset,
668767eb6fbSBoris Brezillon 				  uint32_t data_len, const uint8_t *buf,
669767eb6fbSBoris Brezillon 				  int oob_required, int page)
67093db446aSBoris Brezillon {
671767eb6fbSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
672767eb6fbSBoris Brezillon 
67393db446aSBoris Brezillon 	nand_prog_page_begin_op(chip, page, 0, NULL, 0);
674c0739d85SBoris Brezillon 	fsl_elbc_write_buf(chip, buf, mtd->writesize);
675c0739d85SBoris Brezillon 	fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize);
67693db446aSBoris Brezillon 	return nand_prog_page_end_op(chip);
67793db446aSBoris Brezillon }
67893db446aSBoris Brezillon 
fsl_elbc_chip_init(struct fsl_elbc_mtd * priv)67993db446aSBoris Brezillon static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
68093db446aSBoris Brezillon {
68193db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
68293db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
68393db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
68493db446aSBoris Brezillon 	struct nand_chip *chip = &priv->chip;
68593db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
68693db446aSBoris Brezillon 
68793db446aSBoris Brezillon 	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
68893db446aSBoris Brezillon 
68993db446aSBoris Brezillon 	/* Fill in fsl_elbc_mtd structure */
69093db446aSBoris Brezillon 	mtd->dev.parent = priv->dev;
69193db446aSBoris Brezillon 	nand_set_flash_node(chip, priv->dev->of_node);
69293db446aSBoris Brezillon 
69393db446aSBoris Brezillon 	/* set timeout to maximum */
69493db446aSBoris Brezillon 	priv->fmr = 15 << FMR_CWTO_SHIFT;
69593db446aSBoris Brezillon 	if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS)
69693db446aSBoris Brezillon 		priv->fmr |= FMR_ECCM;
69793db446aSBoris Brezillon 
69893db446aSBoris Brezillon 	/* fill in nand_chip structure */
69993db446aSBoris Brezillon 	/* set up function call table */
700716bbbabSBoris Brezillon 	chip->legacy.read_byte = fsl_elbc_read_byte;
701716bbbabSBoris Brezillon 	chip->legacy.write_buf = fsl_elbc_write_buf;
702716bbbabSBoris Brezillon 	chip->legacy.read_buf = fsl_elbc_read_buf;
7037d6c37e9SBoris Brezillon 	chip->legacy.select_chip = fsl_elbc_select_chip;
704bf6065c6SBoris Brezillon 	chip->legacy.cmdfunc = fsl_elbc_cmdfunc;
7058395b753SBoris Brezillon 	chip->legacy.waitfunc = fsl_elbc_wait;
70645240367SBoris Brezillon 	chip->legacy.set_features = nand_get_set_features_notsupp;
70745240367SBoris Brezillon 	chip->legacy.get_features = nand_get_set_features_notsupp;
70893db446aSBoris Brezillon 
70993db446aSBoris Brezillon 	chip->bbt_td = &bbt_main_descr;
71093db446aSBoris Brezillon 	chip->bbt_md = &bbt_mirror_descr;
71193db446aSBoris Brezillon 
71293db446aSBoris Brezillon 	/* set up nand options */
71393db446aSBoris Brezillon 	chip->bbt_options = NAND_BBT_USE_FLASH;
71493db446aSBoris Brezillon 
71593db446aSBoris Brezillon 	chip->controller = &elbc_fcm_ctrl->controller;
71693db446aSBoris Brezillon 	nand_set_controller_data(chip, priv);
71793db446aSBoris Brezillon 
71893db446aSBoris Brezillon 	return 0;
71993db446aSBoris Brezillon }
72093db446aSBoris Brezillon 
fsl_elbc_attach_chip(struct nand_chip * chip)7219fed3115SMarek Behún static int fsl_elbc_attach_chip(struct nand_chip *chip)
7229fed3115SMarek Behún {
7239fed3115SMarek Behún 	struct mtd_info *mtd = nand_to_mtd(chip);
7249fed3115SMarek Behún 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
7259fed3115SMarek Behún 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
7269fed3115SMarek Behún 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
7279fed3115SMarek Behún 	unsigned int al;
728b5626525SPali Rohár 	u32 br;
7299fed3115SMarek Behún 
730f6424c22SMarek Behún 	/*
731f6424c22SMarek Behún 	 * if ECC was not chosen in DT, decide whether to use HW or SW ECC from
732f6424c22SMarek Behún 	 * CS Base Register
733f6424c22SMarek Behún 	 */
734049e43b9SPali Rohár 	if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID) {
735f6424c22SMarek Behún 		/* If CS Base Register selects full hardware ECC then use it */
736f6424c22SMarek Behún 		if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
737f6424c22SMarek Behún 		    BR_DECC_CHK_GEN) {
738bace41f8SMiquel Raynal 			chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
739f6424c22SMarek Behún 		} else {
740f6424c22SMarek Behún 			/* otherwise fall back to default software ECC */
741bace41f8SMiquel Raynal 			chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
742e0a564aeSMiquel Raynal 			chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
743f6424c22SMarek Behún 		}
744049e43b9SPali Rohár 	}
745049e43b9SPali Rohár 
746049e43b9SPali Rohár 	switch (chip->ecc.engine_type) {
747049e43b9SPali Rohár 	/* if HW ECC was chosen, setup ecc and oob layout */
748049e43b9SPali Rohár 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
749049e43b9SPali Rohár 		chip->ecc.read_page = fsl_elbc_read_page;
750049e43b9SPali Rohár 		chip->ecc.write_page = fsl_elbc_write_page;
751049e43b9SPali Rohár 		chip->ecc.write_subpage = fsl_elbc_write_subpage;
752049e43b9SPali Rohár 		mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops);
753049e43b9SPali Rohár 		chip->ecc.size = 512;
754049e43b9SPali Rohár 		chip->ecc.bytes = 3;
755049e43b9SPali Rohár 		chip->ecc.strength = 1;
756f6424c22SMarek Behún 		break;
757f6424c22SMarek Behún 
758049e43b9SPali Rohár 	/* if none or SW ECC was chosen, we do not need to set anything here */
759049e43b9SPali Rohár 	case NAND_ECC_ENGINE_TYPE_NONE:
760bace41f8SMiquel Raynal 	case NAND_ECC_ENGINE_TYPE_SOFT:
761049e43b9SPali Rohár 	case NAND_ECC_ENGINE_TYPE_ON_DIE:
762f6424c22SMarek Behún 		break;
763f6424c22SMarek Behún 
764f6424c22SMarek Behún 	default:
765f6424c22SMarek Behún 		return -EINVAL;
766f6424c22SMarek Behún 	}
767f6424c22SMarek Behún 
768b5626525SPali Rohár 	/* enable/disable HW ECC checking and generating based on if HW ECC was chosen */
769b5626525SPali Rohár 	br = in_be32(&lbc->bank[priv->bank].br) & ~BR_DECC;
770b5626525SPali Rohár 	if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST)
771b5626525SPali Rohár 		out_be32(&lbc->bank[priv->bank].br, br | BR_DECC_CHK_GEN);
772b5626525SPali Rohár 	else
773b5626525SPali Rohár 		out_be32(&lbc->bank[priv->bank].br, br | BR_DECC_OFF);
774b5626525SPali Rohár 
7759fed3115SMarek Behún 	/* calculate FMR Address Length field */
7769fed3115SMarek Behún 	al = 0;
7779fed3115SMarek Behún 	if (chip->pagemask & 0xffff0000)
7789fed3115SMarek Behún 		al++;
7799fed3115SMarek Behún 	if (chip->pagemask & 0xff000000)
7809fed3115SMarek Behún 		al++;
7819fed3115SMarek Behún 
7829fed3115SMarek Behún 	priv->fmr |= al << FMR_AL_SHIFT;
7839fed3115SMarek Behún 
7849fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
7859fed3115SMarek Behún 	        nanddev_ntargets(&chip->base));
7869fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
7879fed3115SMarek Behún 	        nanddev_target_size(&chip->base));
7889fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
7899fed3115SMarek Behún 	        chip->pagemask);
7909fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->legacy.chip_delay = %d\n",
7919fed3115SMarek Behún 	        chip->legacy.chip_delay);
7929fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
7939fed3115SMarek Behún 	        chip->badblockpos);
7949fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
7959fed3115SMarek Behún 	        chip->chip_shift);
7969fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
7979fed3115SMarek Behún 	        chip->page_shift);
7989fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
7999fed3115SMarek Behún 	        chip->phys_erase_shift);
800bace41f8SMiquel Raynal 	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.engine_type = %d\n",
801bace41f8SMiquel Raynal 		chip->ecc.engine_type);
8029fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
8039fed3115SMarek Behún 	        chip->ecc.steps);
8049fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
8059fed3115SMarek Behún 	        chip->ecc.bytes);
8069fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
8079fed3115SMarek Behún 	        chip->ecc.total);
8089fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->ooblayout = %p\n",
8099fed3115SMarek Behún 		mtd->ooblayout);
8109fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
8119fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
8129fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
8139fed3115SMarek Behún 	        mtd->erasesize);
8149fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
8159fed3115SMarek Behún 	        mtd->writesize);
8169fed3115SMarek Behún 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
8179fed3115SMarek Behún 	        mtd->oobsize);
8189fed3115SMarek Behún 
8199fed3115SMarek Behún 	/* adjust Option Register and ECC to match Flash page size */
8209fed3115SMarek Behún 	if (mtd->writesize == 512) {
8219fed3115SMarek Behún 		priv->page_size = 0;
8229fed3115SMarek Behún 		clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
8239fed3115SMarek Behún 	} else if (mtd->writesize == 2048) {
8249fed3115SMarek Behún 		priv->page_size = 1;
8259fed3115SMarek Behún 		setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
8269fed3115SMarek Behún 	} else {
8279fed3115SMarek Behún 		dev_err(priv->dev,
8289fed3115SMarek Behún 		        "fsl_elbc_init: page size %d is not supported\n",
8299fed3115SMarek Behún 		        mtd->writesize);
8309fed3115SMarek Behún 		return -ENOTSUPP;
8319fed3115SMarek Behún 	}
8329fed3115SMarek Behún 
8339fed3115SMarek Behún 	return 0;
8349fed3115SMarek Behún }
8359fed3115SMarek Behún 
8369fed3115SMarek Behún static const struct nand_controller_ops fsl_elbc_controller_ops = {
8379fed3115SMarek Behún 	.attach_chip = fsl_elbc_attach_chip,
8389fed3115SMarek Behún };
8399fed3115SMarek Behún 
fsl_elbc_chip_remove(struct fsl_elbc_mtd * priv)84093db446aSBoris Brezillon static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
84193db446aSBoris Brezillon {
84293db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
84393db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
84493db446aSBoris Brezillon 
84593db446aSBoris Brezillon 	kfree(mtd->name);
84693db446aSBoris Brezillon 
84793db446aSBoris Brezillon 	if (priv->vbase)
84893db446aSBoris Brezillon 		iounmap(priv->vbase);
84993db446aSBoris Brezillon 
85093db446aSBoris Brezillon 	elbc_fcm_ctrl->chips[priv->bank] = NULL;
85193db446aSBoris Brezillon 	kfree(priv);
85293db446aSBoris Brezillon 	return 0;
85393db446aSBoris Brezillon }
85493db446aSBoris Brezillon 
85593db446aSBoris Brezillon static DEFINE_MUTEX(fsl_elbc_nand_mutex);
85693db446aSBoris Brezillon 
fsl_elbc_nand_probe(struct platform_device * pdev)85793db446aSBoris Brezillon static int fsl_elbc_nand_probe(struct platform_device *pdev)
85893db446aSBoris Brezillon {
85993db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc;
86093db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv;
86193db446aSBoris Brezillon 	struct resource res;
86293db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
86393db446aSBoris Brezillon 	static const char *part_probe_types[]
86493db446aSBoris Brezillon 		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
86593db446aSBoris Brezillon 	int ret;
86693db446aSBoris Brezillon 	int bank;
86793db446aSBoris Brezillon 	struct device *dev;
86893db446aSBoris Brezillon 	struct device_node *node = pdev->dev.of_node;
86993db446aSBoris Brezillon 	struct mtd_info *mtd;
87093db446aSBoris Brezillon 
87193db446aSBoris Brezillon 	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
87293db446aSBoris Brezillon 		return -ENODEV;
87393db446aSBoris Brezillon 	lbc = fsl_lbc_ctrl_dev->regs;
87493db446aSBoris Brezillon 	dev = fsl_lbc_ctrl_dev->dev;
87593db446aSBoris Brezillon 
87693db446aSBoris Brezillon 	/* get, allocate and map the memory resource */
87793db446aSBoris Brezillon 	ret = of_address_to_resource(node, 0, &res);
87893db446aSBoris Brezillon 	if (ret) {
87993db446aSBoris Brezillon 		dev_err(dev, "failed to get resource\n");
88093db446aSBoris Brezillon 		return ret;
88193db446aSBoris Brezillon 	}
88293db446aSBoris Brezillon 
88393db446aSBoris Brezillon 	/* find which chip select it is connected to */
88493db446aSBoris Brezillon 	for (bank = 0; bank < MAX_BANKS; bank++)
88593db446aSBoris Brezillon 		if ((in_be32(&lbc->bank[bank].br) & BR_V) &&
88693db446aSBoris Brezillon 		    (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
88793db446aSBoris Brezillon 		    (in_be32(&lbc->bank[bank].br) &
88893db446aSBoris Brezillon 		     in_be32(&lbc->bank[bank].or) & BR_BA)
88993db446aSBoris Brezillon 		     == fsl_lbc_addr(res.start))
89093db446aSBoris Brezillon 			break;
89193db446aSBoris Brezillon 
89293db446aSBoris Brezillon 	if (bank >= MAX_BANKS) {
89393db446aSBoris Brezillon 		dev_err(dev, "address did not match any chip selects\n");
89493db446aSBoris Brezillon 		return -ENODEV;
89593db446aSBoris Brezillon 	}
89693db446aSBoris Brezillon 
89793db446aSBoris Brezillon 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
89893db446aSBoris Brezillon 	if (!priv)
89993db446aSBoris Brezillon 		return -ENOMEM;
90093db446aSBoris Brezillon 
90193db446aSBoris Brezillon 	mutex_lock(&fsl_elbc_nand_mutex);
90293db446aSBoris Brezillon 	if (!fsl_lbc_ctrl_dev->nand) {
90393db446aSBoris Brezillon 		elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
90493db446aSBoris Brezillon 		if (!elbc_fcm_ctrl) {
90593db446aSBoris Brezillon 			mutex_unlock(&fsl_elbc_nand_mutex);
90693db446aSBoris Brezillon 			ret = -ENOMEM;
90793db446aSBoris Brezillon 			goto err;
90893db446aSBoris Brezillon 		}
90993db446aSBoris Brezillon 		elbc_fcm_ctrl->counter++;
91093db446aSBoris Brezillon 
9117da45139SMiquel Raynal 		nand_controller_init(&elbc_fcm_ctrl->controller);
91293db446aSBoris Brezillon 		fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
91393db446aSBoris Brezillon 	} else {
91493db446aSBoris Brezillon 		elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
91593db446aSBoris Brezillon 	}
91693db446aSBoris Brezillon 	mutex_unlock(&fsl_elbc_nand_mutex);
91793db446aSBoris Brezillon 
91893db446aSBoris Brezillon 	elbc_fcm_ctrl->chips[bank] = priv;
91993db446aSBoris Brezillon 	priv->bank = bank;
92093db446aSBoris Brezillon 	priv->ctrl = fsl_lbc_ctrl_dev;
92193db446aSBoris Brezillon 	priv->dev = &pdev->dev;
92293db446aSBoris Brezillon 	dev_set_drvdata(priv->dev, priv);
92393db446aSBoris Brezillon 
92493db446aSBoris Brezillon 	priv->vbase = ioremap(res.start, resource_size(&res));
92593db446aSBoris Brezillon 	if (!priv->vbase) {
92693db446aSBoris Brezillon 		dev_err(dev, "failed to map chip region\n");
92793db446aSBoris Brezillon 		ret = -ENOMEM;
92893db446aSBoris Brezillon 		goto err;
92993db446aSBoris Brezillon 	}
93093db446aSBoris Brezillon 
93193db446aSBoris Brezillon 	mtd = nand_to_mtd(&priv->chip);
93293db446aSBoris Brezillon 	mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
93393db446aSBoris Brezillon 	if (!nand_to_mtd(&priv->chip)->name) {
93493db446aSBoris Brezillon 		ret = -ENOMEM;
93593db446aSBoris Brezillon 		goto err;
93693db446aSBoris Brezillon 	}
93793db446aSBoris Brezillon 
93893db446aSBoris Brezillon 	ret = fsl_elbc_chip_init(priv);
93993db446aSBoris Brezillon 	if (ret)
94093db446aSBoris Brezillon 		goto err;
94193db446aSBoris Brezillon 
9425bf3e76bSMiquel Raynal 	priv->chip.controller->ops = &fsl_elbc_controller_ops;
94300ad378fSBoris Brezillon 	ret = nand_scan(&priv->chip, 1);
94493db446aSBoris Brezillon 	if (ret)
94593db446aSBoris Brezillon 		goto err;
94693db446aSBoris Brezillon 
94793db446aSBoris Brezillon 	/* First look for RedBoot table or partitions on the command
94893db446aSBoris Brezillon 	 * line, these take precedence over device tree information */
94939b77c58SMiquel Raynal 	ret = mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0);
95039b77c58SMiquel Raynal 	if (ret)
95139b77c58SMiquel Raynal 		goto cleanup_nand;
95293db446aSBoris Brezillon 
95363fa37f0SShreeya Patel 	pr_info("eLBC NAND device at 0x%llx, bank %d\n",
95493db446aSBoris Brezillon 		(unsigned long long)res.start, priv->bank);
95539b77c58SMiquel Raynal 
95693db446aSBoris Brezillon 	return 0;
95793db446aSBoris Brezillon 
95839b77c58SMiquel Raynal cleanup_nand:
95939b77c58SMiquel Raynal 	nand_cleanup(&priv->chip);
96093db446aSBoris Brezillon err:
96193db446aSBoris Brezillon 	fsl_elbc_chip_remove(priv);
96239b77c58SMiquel Raynal 
96393db446aSBoris Brezillon 	return ret;
96493db446aSBoris Brezillon }
96593db446aSBoris Brezillon 
fsl_elbc_nand_remove(struct platform_device * pdev)966*ec185b18SUwe Kleine-König static void fsl_elbc_nand_remove(struct platform_device *pdev)
96793db446aSBoris Brezillon {
96893db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
96993db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev);
970128bbbf0SMiquel Raynal 	struct nand_chip *chip = &priv->chip;
971128bbbf0SMiquel Raynal 	int ret;
97293db446aSBoris Brezillon 
973128bbbf0SMiquel Raynal 	ret = mtd_device_unregister(nand_to_mtd(chip));
974128bbbf0SMiquel Raynal 	WARN_ON(ret);
975128bbbf0SMiquel Raynal 	nand_cleanup(chip);
976128bbbf0SMiquel Raynal 
97793db446aSBoris Brezillon 	fsl_elbc_chip_remove(priv);
97893db446aSBoris Brezillon 
97993db446aSBoris Brezillon 	mutex_lock(&fsl_elbc_nand_mutex);
98093db446aSBoris Brezillon 	elbc_fcm_ctrl->counter--;
98193db446aSBoris Brezillon 	if (!elbc_fcm_ctrl->counter) {
98293db446aSBoris Brezillon 		fsl_lbc_ctrl_dev->nand = NULL;
98393db446aSBoris Brezillon 		kfree(elbc_fcm_ctrl);
98493db446aSBoris Brezillon 	}
98593db446aSBoris Brezillon 	mutex_unlock(&fsl_elbc_nand_mutex);
98693db446aSBoris Brezillon 
98793db446aSBoris Brezillon }
98893db446aSBoris Brezillon 
98993db446aSBoris Brezillon static const struct of_device_id fsl_elbc_nand_match[] = {
99093db446aSBoris Brezillon 	{ .compatible = "fsl,elbc-fcm-nand", },
99193db446aSBoris Brezillon 	{}
99293db446aSBoris Brezillon };
99393db446aSBoris Brezillon MODULE_DEVICE_TABLE(of, fsl_elbc_nand_match);
99493db446aSBoris Brezillon 
99593db446aSBoris Brezillon static struct platform_driver fsl_elbc_nand_driver = {
99693db446aSBoris Brezillon 	.driver = {
99793db446aSBoris Brezillon 		.name = "fsl,elbc-fcm-nand",
99893db446aSBoris Brezillon 		.of_match_table = fsl_elbc_nand_match,
99993db446aSBoris Brezillon 	},
100093db446aSBoris Brezillon 	.probe = fsl_elbc_nand_probe,
1001*ec185b18SUwe Kleine-König 	.remove_new = fsl_elbc_nand_remove,
100293db446aSBoris Brezillon };
100393db446aSBoris Brezillon 
100493db446aSBoris Brezillon module_platform_driver(fsl_elbc_nand_driver);
100593db446aSBoris Brezillon 
100693db446aSBoris Brezillon MODULE_LICENSE("GPL");
100793db446aSBoris Brezillon MODULE_AUTHOR("Freescale");
100893db446aSBoris Brezillon MODULE_DESCRIPTION("Freescale Enhanced Local Bus Controller MTD NAND driver");
1009