193db446aSBoris Brezillon /* Freescale Enhanced Local Bus Controller NAND driver
293db446aSBoris Brezillon  *
393db446aSBoris Brezillon  * Copyright © 2006-2007, 2010 Freescale Semiconductor
493db446aSBoris Brezillon  *
593db446aSBoris Brezillon  * Authors: Nick Spence <nick.spence@freescale.com>,
693db446aSBoris Brezillon  *          Scott Wood <scottwood@freescale.com>
793db446aSBoris Brezillon  *          Jack Lan <jack.lan@freescale.com>
893db446aSBoris Brezillon  *          Roy Zang <tie-fei.zang@freescale.com>
993db446aSBoris Brezillon  *
1093db446aSBoris Brezillon  * This program is free software; you can redistribute it and/or modify
1193db446aSBoris Brezillon  * it under the terms of the GNU General Public License as published by
1293db446aSBoris Brezillon  * the Free Software Foundation; either version 2 of the License, or
1393db446aSBoris Brezillon  * (at your option) any later version.
1493db446aSBoris Brezillon  *
1593db446aSBoris Brezillon  * This program is distributed in the hope that it will be useful,
1693db446aSBoris Brezillon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1793db446aSBoris Brezillon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1893db446aSBoris Brezillon  * GNU General Public License for more details.
1993db446aSBoris Brezillon  *
2093db446aSBoris Brezillon  * You should have received a copy of the GNU General Public License
2193db446aSBoris Brezillon  * along with this program; if not, write to the Free Software
2293db446aSBoris Brezillon  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
2393db446aSBoris Brezillon  */
2493db446aSBoris Brezillon 
2593db446aSBoris Brezillon #include <linux/module.h>
2693db446aSBoris Brezillon #include <linux/types.h>
2793db446aSBoris Brezillon #include <linux/kernel.h>
2893db446aSBoris Brezillon #include <linux/string.h>
2993db446aSBoris Brezillon #include <linux/ioport.h>
3093db446aSBoris Brezillon #include <linux/of_address.h>
3193db446aSBoris Brezillon #include <linux/of_platform.h>
3293db446aSBoris Brezillon #include <linux/platform_device.h>
3393db446aSBoris Brezillon #include <linux/slab.h>
3493db446aSBoris Brezillon #include <linux/interrupt.h>
3593db446aSBoris Brezillon 
3693db446aSBoris Brezillon #include <linux/mtd/mtd.h>
3793db446aSBoris Brezillon #include <linux/mtd/rawnand.h>
3893db446aSBoris Brezillon #include <linux/mtd/nand_ecc.h>
3993db446aSBoris Brezillon #include <linux/mtd/partitions.h>
4093db446aSBoris Brezillon 
4193db446aSBoris Brezillon #include <asm/io.h>
4293db446aSBoris Brezillon #include <asm/fsl_lbc.h>
4393db446aSBoris Brezillon 
4493db446aSBoris Brezillon #define MAX_BANKS 8
4593db446aSBoris Brezillon #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
4693db446aSBoris Brezillon #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
4793db446aSBoris Brezillon 
4893db446aSBoris Brezillon /* mtd information per set */
4993db446aSBoris Brezillon 
5093db446aSBoris Brezillon struct fsl_elbc_mtd {
5193db446aSBoris Brezillon 	struct nand_chip chip;
5293db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl;
5393db446aSBoris Brezillon 
5493db446aSBoris Brezillon 	struct device *dev;
5593db446aSBoris Brezillon 	int bank;               /* Chip select bank number           */
5693db446aSBoris Brezillon 	u8 __iomem *vbase;      /* Chip select base virtual address  */
5793db446aSBoris Brezillon 	int page_size;          /* NAND page size (0=512, 1=2048)    */
5893db446aSBoris Brezillon 	unsigned int fmr;       /* FCM Flash Mode Register value     */
5993db446aSBoris Brezillon };
6093db446aSBoris Brezillon 
6193db446aSBoris Brezillon /* Freescale eLBC FCM controller information */
6293db446aSBoris Brezillon 
6393db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl {
647da45139SMiquel Raynal 	struct nand_controller controller;
6593db446aSBoris Brezillon 	struct fsl_elbc_mtd *chips[MAX_BANKS];
6693db446aSBoris Brezillon 
6793db446aSBoris Brezillon 	u8 __iomem *addr;        /* Address of assigned FCM buffer        */
6893db446aSBoris Brezillon 	unsigned int page;       /* Last page written to / read from      */
6993db446aSBoris Brezillon 	unsigned int read_bytes; /* Number of bytes read during command   */
7093db446aSBoris Brezillon 	unsigned int column;     /* Saved column from SEQIN               */
7193db446aSBoris Brezillon 	unsigned int index;      /* Pointer to next byte to 'read'        */
7293db446aSBoris Brezillon 	unsigned int status;     /* status read from LTESR after last op  */
7393db446aSBoris Brezillon 	unsigned int mdr;        /* UPM/FCM Data Register value           */
7493db446aSBoris Brezillon 	unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
7593db446aSBoris Brezillon 	unsigned int oob;        /* Non zero if operating on OOB data     */
7693db446aSBoris Brezillon 	unsigned int counter;	 /* counter for the initializations	  */
7793db446aSBoris Brezillon 	unsigned int max_bitflips;  /* Saved during READ0 cmd		  */
7893db446aSBoris Brezillon };
7993db446aSBoris Brezillon 
8093db446aSBoris Brezillon /* These map to the positions used by the FCM hardware ECC generator */
8193db446aSBoris Brezillon 
8293db446aSBoris Brezillon static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section,
8393db446aSBoris Brezillon 				  struct mtd_oob_region *oobregion)
8493db446aSBoris Brezillon {
8593db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
8693db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
8793db446aSBoris Brezillon 
8893db446aSBoris Brezillon 	if (section >= chip->ecc.steps)
8993db446aSBoris Brezillon 		return -ERANGE;
9093db446aSBoris Brezillon 
9193db446aSBoris Brezillon 	oobregion->offset = (16 * section) + 6;
9293db446aSBoris Brezillon 	if (priv->fmr & FMR_ECCM)
9393db446aSBoris Brezillon 		oobregion->offset += 2;
9493db446aSBoris Brezillon 
9593db446aSBoris Brezillon 	oobregion->length = chip->ecc.bytes;
9693db446aSBoris Brezillon 
9793db446aSBoris Brezillon 	return 0;
9893db446aSBoris Brezillon }
9993db446aSBoris Brezillon 
10093db446aSBoris Brezillon static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section,
10193db446aSBoris Brezillon 				   struct mtd_oob_region *oobregion)
10293db446aSBoris Brezillon {
10393db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
10493db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
10593db446aSBoris Brezillon 
10693db446aSBoris Brezillon 	if (section > chip->ecc.steps)
10793db446aSBoris Brezillon 		return -ERANGE;
10893db446aSBoris Brezillon 
10993db446aSBoris Brezillon 	if (!section) {
11093db446aSBoris Brezillon 		oobregion->offset = 0;
11193db446aSBoris Brezillon 		if (mtd->writesize > 512)
11293db446aSBoris Brezillon 			oobregion->offset++;
11393db446aSBoris Brezillon 		oobregion->length = (priv->fmr & FMR_ECCM) ? 7 : 5;
11493db446aSBoris Brezillon 	} else {
11593db446aSBoris Brezillon 		oobregion->offset = (16 * section) -
11693db446aSBoris Brezillon 				    ((priv->fmr & FMR_ECCM) ? 5 : 7);
11793db446aSBoris Brezillon 		if (section < chip->ecc.steps)
11893db446aSBoris Brezillon 			oobregion->length = 13;
11993db446aSBoris Brezillon 		else
12093db446aSBoris Brezillon 			oobregion->length = mtd->oobsize - oobregion->offset;
12193db446aSBoris Brezillon 	}
12293db446aSBoris Brezillon 
12393db446aSBoris Brezillon 	return 0;
12493db446aSBoris Brezillon }
12593db446aSBoris Brezillon 
12693db446aSBoris Brezillon static const struct mtd_ooblayout_ops fsl_elbc_ooblayout_ops = {
12793db446aSBoris Brezillon 	.ecc = fsl_elbc_ooblayout_ecc,
12893db446aSBoris Brezillon 	.free = fsl_elbc_ooblayout_free,
12993db446aSBoris Brezillon };
13093db446aSBoris Brezillon 
13193db446aSBoris Brezillon /*
13293db446aSBoris Brezillon  * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
13393db446aSBoris Brezillon  * interfere with ECC positions, that's why we implement our own descriptors.
13493db446aSBoris Brezillon  * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0.
13593db446aSBoris Brezillon  */
13693db446aSBoris Brezillon static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
13793db446aSBoris Brezillon static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
13893db446aSBoris Brezillon 
13993db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_descr = {
14093db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
14193db446aSBoris Brezillon 		   NAND_BBT_2BIT | NAND_BBT_VERSION,
14293db446aSBoris Brezillon 	.offs =	11,
14393db446aSBoris Brezillon 	.len = 4,
14493db446aSBoris Brezillon 	.veroffs = 15,
14593db446aSBoris Brezillon 	.maxblocks = 4,
14693db446aSBoris Brezillon 	.pattern = bbt_pattern,
14793db446aSBoris Brezillon };
14893db446aSBoris Brezillon 
14993db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_descr = {
15093db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
15193db446aSBoris Brezillon 		   NAND_BBT_2BIT | NAND_BBT_VERSION,
15293db446aSBoris Brezillon 	.offs =	11,
15393db446aSBoris Brezillon 	.len = 4,
15493db446aSBoris Brezillon 	.veroffs = 15,
15593db446aSBoris Brezillon 	.maxblocks = 4,
15693db446aSBoris Brezillon 	.pattern = mirror_pattern,
15793db446aSBoris Brezillon };
15893db446aSBoris Brezillon 
15993db446aSBoris Brezillon /*=================================*/
16093db446aSBoris Brezillon 
16193db446aSBoris Brezillon /*
16293db446aSBoris Brezillon  * Set up the FCM hardware block and page address fields, and the fcm
16393db446aSBoris Brezillon  * structure addr field to point to the correct FCM buffer in memory
16493db446aSBoris Brezillon  */
16593db446aSBoris Brezillon static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
16693db446aSBoris Brezillon {
16793db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
16893db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
16993db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
17093db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
17193db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
17293db446aSBoris Brezillon 	int buf_num;
17393db446aSBoris Brezillon 
17493db446aSBoris Brezillon 	elbc_fcm_ctrl->page = page_addr;
17593db446aSBoris Brezillon 
17693db446aSBoris Brezillon 	if (priv->page_size) {
17793db446aSBoris Brezillon 		/*
17893db446aSBoris Brezillon 		 * large page size chip : FPAR[PI] save the lowest 6 bits,
17993db446aSBoris Brezillon 		 *                        FBAR[BLK] save the other bits.
18093db446aSBoris Brezillon 		 */
18193db446aSBoris Brezillon 		out_be32(&lbc->fbar, page_addr >> 6);
18293db446aSBoris Brezillon 		out_be32(&lbc->fpar,
18393db446aSBoris Brezillon 		         ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
18493db446aSBoris Brezillon 		         (oob ? FPAR_LP_MS : 0) | column);
18593db446aSBoris Brezillon 		buf_num = (page_addr & 1) << 2;
18693db446aSBoris Brezillon 	} else {
18793db446aSBoris Brezillon 		/*
18893db446aSBoris Brezillon 		 * small page size chip : FPAR[PI] save the lowest 5 bits,
18993db446aSBoris Brezillon 		 *                        FBAR[BLK] save the other bits.
19093db446aSBoris Brezillon 		 */
19193db446aSBoris Brezillon 		out_be32(&lbc->fbar, page_addr >> 5);
19293db446aSBoris Brezillon 		out_be32(&lbc->fpar,
19393db446aSBoris Brezillon 		         ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
19493db446aSBoris Brezillon 		         (oob ? FPAR_SP_MS : 0) | column);
19593db446aSBoris Brezillon 		buf_num = page_addr & 7;
19693db446aSBoris Brezillon 	}
19793db446aSBoris Brezillon 
19893db446aSBoris Brezillon 	elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
19993db446aSBoris Brezillon 	elbc_fcm_ctrl->index = column;
20093db446aSBoris Brezillon 
20193db446aSBoris Brezillon 	/* for OOB data point to the second half of the buffer */
20293db446aSBoris Brezillon 	if (oob)
20393db446aSBoris Brezillon 		elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
20493db446aSBoris Brezillon 
20593db446aSBoris Brezillon 	dev_vdbg(priv->dev, "set_addr: bank=%d, "
20693db446aSBoris Brezillon 			    "elbc_fcm_ctrl->addr=0x%p (0x%p), "
20793db446aSBoris Brezillon 	                    "index %x, pes %d ps %d\n",
20893db446aSBoris Brezillon 		 buf_num, elbc_fcm_ctrl->addr, priv->vbase,
20993db446aSBoris Brezillon 		 elbc_fcm_ctrl->index,
21093db446aSBoris Brezillon 	         chip->phys_erase_shift, chip->page_shift);
21193db446aSBoris Brezillon }
21293db446aSBoris Brezillon 
21393db446aSBoris Brezillon /*
21493db446aSBoris Brezillon  * execute FCM command and wait for it to complete
21593db446aSBoris Brezillon  */
21693db446aSBoris Brezillon static int fsl_elbc_run_command(struct mtd_info *mtd)
21793db446aSBoris Brezillon {
21893db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
21993db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
22093db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
22193db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
22293db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
22393db446aSBoris Brezillon 
22493db446aSBoris Brezillon 	/* Setup the FMR[OP] to execute without write protection */
22593db446aSBoris Brezillon 	out_be32(&lbc->fmr, priv->fmr | 3);
22693db446aSBoris Brezillon 	if (elbc_fcm_ctrl->use_mdr)
22793db446aSBoris Brezillon 		out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
22893db446aSBoris Brezillon 
22993db446aSBoris Brezillon 	dev_vdbg(priv->dev,
23093db446aSBoris Brezillon 	         "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
23193db446aSBoris Brezillon 	         in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
23293db446aSBoris Brezillon 	dev_vdbg(priv->dev,
23393db446aSBoris Brezillon 	         "fsl_elbc_run_command: fbar=%08x fpar=%08x "
23493db446aSBoris Brezillon 	         "fbcr=%08x bank=%d\n",
23593db446aSBoris Brezillon 	         in_be32(&lbc->fbar), in_be32(&lbc->fpar),
23693db446aSBoris Brezillon 	         in_be32(&lbc->fbcr), priv->bank);
23793db446aSBoris Brezillon 
23893db446aSBoris Brezillon 	ctrl->irq_status = 0;
23993db446aSBoris Brezillon 	/* execute special operation */
24093db446aSBoris Brezillon 	out_be32(&lbc->lsor, priv->bank);
24193db446aSBoris Brezillon 
24293db446aSBoris Brezillon 	/* wait for FCM complete flag or timeout */
24393db446aSBoris Brezillon 	wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
24493db446aSBoris Brezillon 	                   FCM_TIMEOUT_MSECS * HZ/1000);
24593db446aSBoris Brezillon 	elbc_fcm_ctrl->status = ctrl->irq_status;
24693db446aSBoris Brezillon 	/* store mdr value in case it was needed */
24793db446aSBoris Brezillon 	if (elbc_fcm_ctrl->use_mdr)
24893db446aSBoris Brezillon 		elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
24993db446aSBoris Brezillon 
25093db446aSBoris Brezillon 	elbc_fcm_ctrl->use_mdr = 0;
25193db446aSBoris Brezillon 
25293db446aSBoris Brezillon 	if (elbc_fcm_ctrl->status != LTESR_CC) {
25393db446aSBoris Brezillon 		dev_info(priv->dev,
25493db446aSBoris Brezillon 		         "command failed: fir %x fcr %x status %x mdr %x\n",
25593db446aSBoris Brezillon 		         in_be32(&lbc->fir), in_be32(&lbc->fcr),
25693db446aSBoris Brezillon 			 elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
25793db446aSBoris Brezillon 		return -EIO;
25893db446aSBoris Brezillon 	}
25993db446aSBoris Brezillon 
26093db446aSBoris Brezillon 	if (chip->ecc.mode != NAND_ECC_HW)
26193db446aSBoris Brezillon 		return 0;
26293db446aSBoris Brezillon 
26393db446aSBoris Brezillon 	elbc_fcm_ctrl->max_bitflips = 0;
26493db446aSBoris Brezillon 
26593db446aSBoris Brezillon 	if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) {
26693db446aSBoris Brezillon 		uint32_t lteccr = in_be32(&lbc->lteccr);
26793db446aSBoris Brezillon 		/*
26893db446aSBoris Brezillon 		 * if command was a full page read and the ELBC
26993db446aSBoris Brezillon 		 * has the LTECCR register, then bits 12-15 (ppc order) of
27093db446aSBoris Brezillon 		 * LTECCR indicates which 512 byte sub-pages had fixed errors.
27193db446aSBoris Brezillon 		 * bits 28-31 are uncorrectable errors, marked elsewhere.
27293db446aSBoris Brezillon 		 * for small page nand only 1 bit is used.
27393db446aSBoris Brezillon 		 * if the ELBC doesn't have the lteccr register it reads 0
27493db446aSBoris Brezillon 		 * FIXME: 4 bits can be corrected on NANDs with 2k pages, so
27593db446aSBoris Brezillon 		 * count the number of sub-pages with bitflips and update
27693db446aSBoris Brezillon 		 * ecc_stats.corrected accordingly.
27793db446aSBoris Brezillon 		 */
27893db446aSBoris Brezillon 		if (lteccr & 0x000F000F)
27993db446aSBoris Brezillon 			out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */
28093db446aSBoris Brezillon 		if (lteccr & 0x000F0000) {
28193db446aSBoris Brezillon 			mtd->ecc_stats.corrected++;
28293db446aSBoris Brezillon 			elbc_fcm_ctrl->max_bitflips = 1;
28393db446aSBoris Brezillon 		}
28493db446aSBoris Brezillon 	}
28593db446aSBoris Brezillon 
28693db446aSBoris Brezillon 	return 0;
28793db446aSBoris Brezillon }
28893db446aSBoris Brezillon 
28993db446aSBoris Brezillon static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
29093db446aSBoris Brezillon {
29193db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
29293db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
29393db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
29493db446aSBoris Brezillon 
29593db446aSBoris Brezillon 	if (priv->page_size) {
29693db446aSBoris Brezillon 		out_be32(&lbc->fir,
29793db446aSBoris Brezillon 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
29893db446aSBoris Brezillon 		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
29993db446aSBoris Brezillon 		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
30093db446aSBoris Brezillon 		         (FIR_OP_CM1 << FIR_OP3_SHIFT) |
30193db446aSBoris Brezillon 		         (FIR_OP_RBW << FIR_OP4_SHIFT));
30293db446aSBoris Brezillon 
30393db446aSBoris Brezillon 		out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
30493db446aSBoris Brezillon 		                    (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
30593db446aSBoris Brezillon 	} else {
30693db446aSBoris Brezillon 		out_be32(&lbc->fir,
30793db446aSBoris Brezillon 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
30893db446aSBoris Brezillon 		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
30993db446aSBoris Brezillon 		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
31093db446aSBoris Brezillon 		         (FIR_OP_RBW << FIR_OP3_SHIFT));
31193db446aSBoris Brezillon 
31293db446aSBoris Brezillon 		if (oob)
31393db446aSBoris Brezillon 			out_be32(&lbc->fcr, NAND_CMD_READOOB << FCR_CMD0_SHIFT);
31493db446aSBoris Brezillon 		else
31593db446aSBoris Brezillon 			out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
31693db446aSBoris Brezillon 	}
31793db446aSBoris Brezillon }
31893db446aSBoris Brezillon 
31993db446aSBoris Brezillon /* cmdfunc send commands to the FCM */
32093db446aSBoris Brezillon static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
32193db446aSBoris Brezillon                              int column, int page_addr)
32293db446aSBoris Brezillon {
32393db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
32493db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
32593db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
32693db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
32793db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
32893db446aSBoris Brezillon 
32993db446aSBoris Brezillon 	elbc_fcm_ctrl->use_mdr = 0;
33093db446aSBoris Brezillon 
33193db446aSBoris Brezillon 	/* clear the read buffer */
33293db446aSBoris Brezillon 	elbc_fcm_ctrl->read_bytes = 0;
33393db446aSBoris Brezillon 	if (command != NAND_CMD_PAGEPROG)
33493db446aSBoris Brezillon 		elbc_fcm_ctrl->index = 0;
33593db446aSBoris Brezillon 
33693db446aSBoris Brezillon 	switch (command) {
33793db446aSBoris Brezillon 	/* READ0 and READ1 read the entire buffer to use hardware ECC. */
33893db446aSBoris Brezillon 	case NAND_CMD_READ1:
33993db446aSBoris Brezillon 		column += 256;
34093db446aSBoris Brezillon 
34193db446aSBoris Brezillon 	/* fall-through */
34293db446aSBoris Brezillon 	case NAND_CMD_READ0:
34393db446aSBoris Brezillon 		dev_dbg(priv->dev,
34493db446aSBoris Brezillon 		        "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
34593db446aSBoris Brezillon 		        " 0x%x, column: 0x%x.\n", page_addr, column);
34693db446aSBoris Brezillon 
34793db446aSBoris Brezillon 
34893db446aSBoris Brezillon 		out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
34993db446aSBoris Brezillon 		set_addr(mtd, 0, page_addr, 0);
35093db446aSBoris Brezillon 
35193db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
35293db446aSBoris Brezillon 		elbc_fcm_ctrl->index += column;
35393db446aSBoris Brezillon 
35493db446aSBoris Brezillon 		fsl_elbc_do_read(chip, 0);
35593db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
35693db446aSBoris Brezillon 		return;
35793db446aSBoris Brezillon 
35893db446aSBoris Brezillon 	/* READOOB reads only the OOB because no ECC is performed. */
35993db446aSBoris Brezillon 	case NAND_CMD_READOOB:
36093db446aSBoris Brezillon 		dev_vdbg(priv->dev,
36193db446aSBoris Brezillon 		         "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
36293db446aSBoris Brezillon 			 " 0x%x, column: 0x%x.\n", page_addr, column);
36393db446aSBoris Brezillon 
36493db446aSBoris Brezillon 		out_be32(&lbc->fbcr, mtd->oobsize - column);
36593db446aSBoris Brezillon 		set_addr(mtd, column, page_addr, 1);
36693db446aSBoris Brezillon 
36793db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
36893db446aSBoris Brezillon 
36993db446aSBoris Brezillon 		fsl_elbc_do_read(chip, 1);
37093db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
37193db446aSBoris Brezillon 		return;
37293db446aSBoris Brezillon 
37393db446aSBoris Brezillon 	case NAND_CMD_READID:
37493db446aSBoris Brezillon 	case NAND_CMD_PARAM:
37593db446aSBoris Brezillon 		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command);
37693db446aSBoris Brezillon 
37793db446aSBoris Brezillon 		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
37893db446aSBoris Brezillon 		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
37993db446aSBoris Brezillon 		                    (FIR_OP_RBW << FIR_OP2_SHIFT));
38093db446aSBoris Brezillon 		out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT);
38193db446aSBoris Brezillon 		/*
38293db446aSBoris Brezillon 		 * although currently it's 8 bytes for READID, we always read
38393db446aSBoris Brezillon 		 * the maximum 256 bytes(for PARAM)
38493db446aSBoris Brezillon 		 */
38593db446aSBoris Brezillon 		out_be32(&lbc->fbcr, 256);
38693db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = 256;
38793db446aSBoris Brezillon 		elbc_fcm_ctrl->use_mdr = 1;
38893db446aSBoris Brezillon 		elbc_fcm_ctrl->mdr = column;
38993db446aSBoris Brezillon 		set_addr(mtd, 0, 0, 0);
39093db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
39193db446aSBoris Brezillon 		return;
39293db446aSBoris Brezillon 
39393db446aSBoris Brezillon 	/* ERASE1 stores the block and page address */
39493db446aSBoris Brezillon 	case NAND_CMD_ERASE1:
39593db446aSBoris Brezillon 		dev_vdbg(priv->dev,
39693db446aSBoris Brezillon 		         "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
39793db446aSBoris Brezillon 		         "page_addr: 0x%x.\n", page_addr);
39893db446aSBoris Brezillon 		set_addr(mtd, 0, page_addr, 0);
39993db446aSBoris Brezillon 		return;
40093db446aSBoris Brezillon 
40193db446aSBoris Brezillon 	/* ERASE2 uses the block and page address from ERASE1 */
40293db446aSBoris Brezillon 	case NAND_CMD_ERASE2:
40393db446aSBoris Brezillon 		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
40493db446aSBoris Brezillon 
40593db446aSBoris Brezillon 		out_be32(&lbc->fir,
40693db446aSBoris Brezillon 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
40793db446aSBoris Brezillon 		         (FIR_OP_PA  << FIR_OP1_SHIFT) |
40893db446aSBoris Brezillon 		         (FIR_OP_CM2 << FIR_OP2_SHIFT) |
40993db446aSBoris Brezillon 		         (FIR_OP_CW1 << FIR_OP3_SHIFT) |
41093db446aSBoris Brezillon 		         (FIR_OP_RS  << FIR_OP4_SHIFT));
41193db446aSBoris Brezillon 
41293db446aSBoris Brezillon 		out_be32(&lbc->fcr,
41393db446aSBoris Brezillon 		         (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
41493db446aSBoris Brezillon 		         (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
41593db446aSBoris Brezillon 		         (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
41693db446aSBoris Brezillon 
41793db446aSBoris Brezillon 		out_be32(&lbc->fbcr, 0);
41893db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = 0;
41993db446aSBoris Brezillon 		elbc_fcm_ctrl->use_mdr = 1;
42093db446aSBoris Brezillon 
42193db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
42293db446aSBoris Brezillon 		return;
42393db446aSBoris Brezillon 
42493db446aSBoris Brezillon 	/* SEQIN sets up the addr buffer and all registers except the length */
42593db446aSBoris Brezillon 	case NAND_CMD_SEQIN: {
42693db446aSBoris Brezillon 		__be32 fcr;
42793db446aSBoris Brezillon 		dev_vdbg(priv->dev,
42893db446aSBoris Brezillon 			 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
42993db446aSBoris Brezillon 		         "page_addr: 0x%x, column: 0x%x.\n",
43093db446aSBoris Brezillon 		         page_addr, column);
43193db446aSBoris Brezillon 
43293db446aSBoris Brezillon 		elbc_fcm_ctrl->column = column;
43393db446aSBoris Brezillon 		elbc_fcm_ctrl->use_mdr = 1;
43493db446aSBoris Brezillon 
43593db446aSBoris Brezillon 		if (column >= mtd->writesize) {
43693db446aSBoris Brezillon 			/* OOB area */
43793db446aSBoris Brezillon 			column -= mtd->writesize;
43893db446aSBoris Brezillon 			elbc_fcm_ctrl->oob = 1;
43993db446aSBoris Brezillon 		} else {
44093db446aSBoris Brezillon 			WARN_ON(column != 0);
44193db446aSBoris Brezillon 			elbc_fcm_ctrl->oob = 0;
44293db446aSBoris Brezillon 		}
44393db446aSBoris Brezillon 
44493db446aSBoris Brezillon 		fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
44593db446aSBoris Brezillon 		      (NAND_CMD_SEQIN    << FCR_CMD2_SHIFT) |
44693db446aSBoris Brezillon 		      (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT);
44793db446aSBoris Brezillon 
44893db446aSBoris Brezillon 		if (priv->page_size) {
44993db446aSBoris Brezillon 			out_be32(&lbc->fir,
45093db446aSBoris Brezillon 			         (FIR_OP_CM2 << FIR_OP0_SHIFT) |
45193db446aSBoris Brezillon 			         (FIR_OP_CA  << FIR_OP1_SHIFT) |
45293db446aSBoris Brezillon 			         (FIR_OP_PA  << FIR_OP2_SHIFT) |
45393db446aSBoris Brezillon 			         (FIR_OP_WB  << FIR_OP3_SHIFT) |
45493db446aSBoris Brezillon 			         (FIR_OP_CM3 << FIR_OP4_SHIFT) |
45593db446aSBoris Brezillon 			         (FIR_OP_CW1 << FIR_OP5_SHIFT) |
45693db446aSBoris Brezillon 			         (FIR_OP_RS  << FIR_OP6_SHIFT));
45793db446aSBoris Brezillon 		} else {
45893db446aSBoris Brezillon 			out_be32(&lbc->fir,
45993db446aSBoris Brezillon 			         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
46093db446aSBoris Brezillon 			         (FIR_OP_CM2 << FIR_OP1_SHIFT) |
46193db446aSBoris Brezillon 			         (FIR_OP_CA  << FIR_OP2_SHIFT) |
46293db446aSBoris Brezillon 			         (FIR_OP_PA  << FIR_OP3_SHIFT) |
46393db446aSBoris Brezillon 			         (FIR_OP_WB  << FIR_OP4_SHIFT) |
46493db446aSBoris Brezillon 			         (FIR_OP_CM3 << FIR_OP5_SHIFT) |
46593db446aSBoris Brezillon 			         (FIR_OP_CW1 << FIR_OP6_SHIFT) |
46693db446aSBoris Brezillon 			         (FIR_OP_RS  << FIR_OP7_SHIFT));
46793db446aSBoris Brezillon 
46893db446aSBoris Brezillon 			if (elbc_fcm_ctrl->oob)
46993db446aSBoris Brezillon 				/* OOB area --> READOOB */
47093db446aSBoris Brezillon 				fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
47193db446aSBoris Brezillon 			else
47293db446aSBoris Brezillon 				/* First 256 bytes --> READ0 */
47393db446aSBoris Brezillon 				fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
47493db446aSBoris Brezillon 		}
47593db446aSBoris Brezillon 
47693db446aSBoris Brezillon 		out_be32(&lbc->fcr, fcr);
47793db446aSBoris Brezillon 		set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
47893db446aSBoris Brezillon 		return;
47993db446aSBoris Brezillon 	}
48093db446aSBoris Brezillon 
48193db446aSBoris Brezillon 	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
48293db446aSBoris Brezillon 	case NAND_CMD_PAGEPROG: {
48393db446aSBoris Brezillon 		dev_vdbg(priv->dev,
48493db446aSBoris Brezillon 		         "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
48593db446aSBoris Brezillon 			 "writing %d bytes.\n", elbc_fcm_ctrl->index);
48693db446aSBoris Brezillon 
48793db446aSBoris Brezillon 		/* if the write did not start at 0 or is not a full page
48893db446aSBoris Brezillon 		 * then set the exact length, otherwise use a full page
48993db446aSBoris Brezillon 		 * write so the HW generates the ECC.
49093db446aSBoris Brezillon 		 */
49193db446aSBoris Brezillon 		if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
49293db446aSBoris Brezillon 		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize)
49393db446aSBoris Brezillon 			out_be32(&lbc->fbcr,
49493db446aSBoris Brezillon 				elbc_fcm_ctrl->index - elbc_fcm_ctrl->column);
49593db446aSBoris Brezillon 		else
49693db446aSBoris Brezillon 			out_be32(&lbc->fbcr, 0);
49793db446aSBoris Brezillon 
49893db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
49993db446aSBoris Brezillon 		return;
50093db446aSBoris Brezillon 	}
50193db446aSBoris Brezillon 
50293db446aSBoris Brezillon 	/* CMD_STATUS must read the status byte while CEB is active */
50393db446aSBoris Brezillon 	/* Note - it does not wait for the ready line */
50493db446aSBoris Brezillon 	case NAND_CMD_STATUS:
50593db446aSBoris Brezillon 		out_be32(&lbc->fir,
50693db446aSBoris Brezillon 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
50793db446aSBoris Brezillon 		         (FIR_OP_RBW << FIR_OP1_SHIFT));
50893db446aSBoris Brezillon 		out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
50993db446aSBoris Brezillon 		out_be32(&lbc->fbcr, 1);
51093db446aSBoris Brezillon 		set_addr(mtd, 0, 0, 0);
51193db446aSBoris Brezillon 		elbc_fcm_ctrl->read_bytes = 1;
51293db446aSBoris Brezillon 
51393db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
51493db446aSBoris Brezillon 
51593db446aSBoris Brezillon 		/* The chip always seems to report that it is
51693db446aSBoris Brezillon 		 * write-protected, even when it is not.
51793db446aSBoris Brezillon 		 */
51893db446aSBoris Brezillon 		setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
51993db446aSBoris Brezillon 		return;
52093db446aSBoris Brezillon 
52193db446aSBoris Brezillon 	/* RESET without waiting for the ready line */
52293db446aSBoris Brezillon 	case NAND_CMD_RESET:
52393db446aSBoris Brezillon 		dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
52493db446aSBoris Brezillon 		out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
52593db446aSBoris Brezillon 		out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
52693db446aSBoris Brezillon 		fsl_elbc_run_command(mtd);
52793db446aSBoris Brezillon 		return;
52893db446aSBoris Brezillon 
52993db446aSBoris Brezillon 	default:
53093db446aSBoris Brezillon 		dev_err(priv->dev,
53193db446aSBoris Brezillon 		        "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
53293db446aSBoris Brezillon 		        command);
53393db446aSBoris Brezillon 	}
53493db446aSBoris Brezillon }
53593db446aSBoris Brezillon 
53693db446aSBoris Brezillon static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
53793db446aSBoris Brezillon {
53893db446aSBoris Brezillon 	/* The hardware does not seem to support multiple
53993db446aSBoris Brezillon 	 * chips per bank.
54093db446aSBoris Brezillon 	 */
54193db446aSBoris Brezillon }
54293db446aSBoris Brezillon 
54393db446aSBoris Brezillon /*
54493db446aSBoris Brezillon  * Write buf to the FCM Controller Data Buffer
54593db446aSBoris Brezillon  */
546c0739d85SBoris Brezillon static void fsl_elbc_write_buf(struct nand_chip *chip, const u8 *buf, int len)
54793db446aSBoris Brezillon {
548c0739d85SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
54993db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
55093db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
55193db446aSBoris Brezillon 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
55293db446aSBoris Brezillon 
55393db446aSBoris Brezillon 	if (len <= 0) {
55493db446aSBoris Brezillon 		dev_err(priv->dev, "write_buf of %d bytes", len);
55593db446aSBoris Brezillon 		elbc_fcm_ctrl->status = 0;
55693db446aSBoris Brezillon 		return;
55793db446aSBoris Brezillon 	}
55893db446aSBoris Brezillon 
55993db446aSBoris Brezillon 	if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
56093db446aSBoris Brezillon 		dev_err(priv->dev,
56193db446aSBoris Brezillon 		        "write_buf beyond end of buffer "
56293db446aSBoris Brezillon 		        "(%d requested, %u available)\n",
56393db446aSBoris Brezillon 			len, bufsize - elbc_fcm_ctrl->index);
56493db446aSBoris Brezillon 		len = bufsize - elbc_fcm_ctrl->index;
56593db446aSBoris Brezillon 	}
56693db446aSBoris Brezillon 
56793db446aSBoris Brezillon 	memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
56893db446aSBoris Brezillon 	/*
56993db446aSBoris Brezillon 	 * This is workaround for the weird elbc hangs during nand write,
57093db446aSBoris Brezillon 	 * Scott Wood says: "...perhaps difference in how long it takes a
57193db446aSBoris Brezillon 	 * write to make it through the localbus compared to a write to IMMR
57293db446aSBoris Brezillon 	 * is causing problems, and sync isn't helping for some reason."
57393db446aSBoris Brezillon 	 * Reading back the last byte helps though.
57493db446aSBoris Brezillon 	 */
57593db446aSBoris Brezillon 	in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
57693db446aSBoris Brezillon 
57793db446aSBoris Brezillon 	elbc_fcm_ctrl->index += len;
57893db446aSBoris Brezillon }
57993db446aSBoris Brezillon 
58093db446aSBoris Brezillon /*
58193db446aSBoris Brezillon  * read a byte from either the FCM hardware buffer if it has any data left
58293db446aSBoris Brezillon  * otherwise issue a command to read a single byte.
58393db446aSBoris Brezillon  */
5847e534323SBoris Brezillon static u8 fsl_elbc_read_byte(struct nand_chip *chip)
58593db446aSBoris Brezillon {
58693db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
58793db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
58893db446aSBoris Brezillon 
58993db446aSBoris Brezillon 	/* If there are still bytes in the FCM, then use the next byte. */
59093db446aSBoris Brezillon 	if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
59193db446aSBoris Brezillon 		return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
59293db446aSBoris Brezillon 
59393db446aSBoris Brezillon 	dev_err(priv->dev, "read_byte beyond end of buffer\n");
59493db446aSBoris Brezillon 	return ERR_BYTE;
59593db446aSBoris Brezillon }
59693db446aSBoris Brezillon 
59793db446aSBoris Brezillon /*
59893db446aSBoris Brezillon  * Read from the FCM Controller Data Buffer
59993db446aSBoris Brezillon  */
6007e534323SBoris Brezillon static void fsl_elbc_read_buf(struct nand_chip *chip, u8 *buf, int len)
60193db446aSBoris Brezillon {
60293db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
60393db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
60493db446aSBoris Brezillon 	int avail;
60593db446aSBoris Brezillon 
60693db446aSBoris Brezillon 	if (len < 0)
60793db446aSBoris Brezillon 		return;
60893db446aSBoris Brezillon 
60993db446aSBoris Brezillon 	avail = min((unsigned int)len,
61093db446aSBoris Brezillon 			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
61193db446aSBoris Brezillon 	memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
61293db446aSBoris Brezillon 	elbc_fcm_ctrl->index += avail;
61393db446aSBoris Brezillon 
61493db446aSBoris Brezillon 	if (len > avail)
61593db446aSBoris Brezillon 		dev_err(priv->dev,
61693db446aSBoris Brezillon 		        "read_buf beyond end of buffer "
61793db446aSBoris Brezillon 		        "(%d requested, %d available)\n",
61893db446aSBoris Brezillon 		        len, avail);
61993db446aSBoris Brezillon }
62093db446aSBoris Brezillon 
62193db446aSBoris Brezillon /* This function is called after Program and Erase Operations to
62293db446aSBoris Brezillon  * check for success or failure.
62393db446aSBoris Brezillon  */
62493db446aSBoris Brezillon static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
62593db446aSBoris Brezillon {
62693db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
62793db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
62893db446aSBoris Brezillon 
62993db446aSBoris Brezillon 	if (elbc_fcm_ctrl->status != LTESR_CC)
63093db446aSBoris Brezillon 		return NAND_STATUS_FAIL;
63193db446aSBoris Brezillon 
63293db446aSBoris Brezillon 	/* The chip always seems to report that it is
63393db446aSBoris Brezillon 	 * write-protected, even when it is not.
63493db446aSBoris Brezillon 	 */
63593db446aSBoris Brezillon 	return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
63693db446aSBoris Brezillon }
63793db446aSBoris Brezillon 
6385bf3e76bSMiquel Raynal static int fsl_elbc_attach_chip(struct nand_chip *chip)
63993db446aSBoris Brezillon {
6405bf3e76bSMiquel Raynal 	struct mtd_info *mtd = nand_to_mtd(chip);
64193db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
64293db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
64393db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
64493db446aSBoris Brezillon 	unsigned int al;
64593db446aSBoris Brezillon 
64693db446aSBoris Brezillon 	/* calculate FMR Address Length field */
64793db446aSBoris Brezillon 	al = 0;
64893db446aSBoris Brezillon 	if (chip->pagemask & 0xffff0000)
64993db446aSBoris Brezillon 		al++;
65093db446aSBoris Brezillon 	if (chip->pagemask & 0xff000000)
65193db446aSBoris Brezillon 		al++;
65293db446aSBoris Brezillon 
65393db446aSBoris Brezillon 	priv->fmr |= al << FMR_AL_SHIFT;
65493db446aSBoris Brezillon 
65593db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
65693db446aSBoris Brezillon 	        chip->numchips);
65793db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
65893db446aSBoris Brezillon 	        chip->chipsize);
65993db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
66093db446aSBoris Brezillon 	        chip->pagemask);
66193db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
66293db446aSBoris Brezillon 	        chip->chip_delay);
66393db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
66493db446aSBoris Brezillon 	        chip->badblockpos);
66593db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
66693db446aSBoris Brezillon 	        chip->chip_shift);
66793db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
66893db446aSBoris Brezillon 	        chip->page_shift);
66993db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
67093db446aSBoris Brezillon 	        chip->phys_erase_shift);
67193db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
67293db446aSBoris Brezillon 	        chip->ecc.mode);
67393db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
67493db446aSBoris Brezillon 	        chip->ecc.steps);
67593db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
67693db446aSBoris Brezillon 	        chip->ecc.bytes);
67793db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
67893db446aSBoris Brezillon 	        chip->ecc.total);
67993db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->ooblayout = %p\n",
68093db446aSBoris Brezillon 		mtd->ooblayout);
68193db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
68293db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
68393db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
68493db446aSBoris Brezillon 	        mtd->erasesize);
68593db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
68693db446aSBoris Brezillon 	        mtd->writesize);
68793db446aSBoris Brezillon 	dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
68893db446aSBoris Brezillon 	        mtd->oobsize);
68993db446aSBoris Brezillon 
69093db446aSBoris Brezillon 	/* adjust Option Register and ECC to match Flash page size */
69193db446aSBoris Brezillon 	if (mtd->writesize == 512) {
69293db446aSBoris Brezillon 		priv->page_size = 0;
69393db446aSBoris Brezillon 		clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
69493db446aSBoris Brezillon 	} else if (mtd->writesize == 2048) {
69593db446aSBoris Brezillon 		priv->page_size = 1;
69693db446aSBoris Brezillon 		setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
69793db446aSBoris Brezillon 	} else {
69893db446aSBoris Brezillon 		dev_err(priv->dev,
69993db446aSBoris Brezillon 		        "fsl_elbc_init: page size %d is not supported\n",
70093db446aSBoris Brezillon 		        mtd->writesize);
70199dc9d95SMiquel Raynal 		return -ENOTSUPP;
70293db446aSBoris Brezillon 	}
70393db446aSBoris Brezillon 
70493db446aSBoris Brezillon 	return 0;
70593db446aSBoris Brezillon }
70693db446aSBoris Brezillon 
7075bf3e76bSMiquel Raynal static const struct nand_controller_ops fsl_elbc_controller_ops = {
7085bf3e76bSMiquel Raynal 	.attach_chip = fsl_elbc_attach_chip,
7095bf3e76bSMiquel Raynal };
7105bf3e76bSMiquel Raynal 
711b9761687SBoris Brezillon static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf,
712b9761687SBoris Brezillon 			      int oob_required, int page)
71393db446aSBoris Brezillon {
714b9761687SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
71593db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
71693db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
71793db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
71893db446aSBoris Brezillon 
71993db446aSBoris Brezillon 	nand_read_page_op(chip, page, 0, buf, mtd->writesize);
72093db446aSBoris Brezillon 	if (oob_required)
7217e534323SBoris Brezillon 		fsl_elbc_read_buf(chip, chip->oob_poi, mtd->oobsize);
72293db446aSBoris Brezillon 
72393db446aSBoris Brezillon 	if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL)
72493db446aSBoris Brezillon 		mtd->ecc_stats.failed++;
72593db446aSBoris Brezillon 
72693db446aSBoris Brezillon 	return elbc_fcm_ctrl->max_bitflips;
72793db446aSBoris Brezillon }
72893db446aSBoris Brezillon 
72993db446aSBoris Brezillon /* ECC will be calculated automatically, and errors will be detected in
73093db446aSBoris Brezillon  * waitfunc.
73193db446aSBoris Brezillon  */
732767eb6fbSBoris Brezillon static int fsl_elbc_write_page(struct nand_chip *chip, const uint8_t *buf,
733767eb6fbSBoris Brezillon 			       int oob_required, int page)
73493db446aSBoris Brezillon {
735767eb6fbSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
736767eb6fbSBoris Brezillon 
73793db446aSBoris Brezillon 	nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
738c0739d85SBoris Brezillon 	fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize);
73993db446aSBoris Brezillon 
74093db446aSBoris Brezillon 	return nand_prog_page_end_op(chip);
74193db446aSBoris Brezillon }
74293db446aSBoris Brezillon 
74393db446aSBoris Brezillon /* ECC will be calculated automatically, and errors will be detected in
74493db446aSBoris Brezillon  * waitfunc.
74593db446aSBoris Brezillon  */
746767eb6fbSBoris Brezillon static int fsl_elbc_write_subpage(struct nand_chip *chip, uint32_t offset,
747767eb6fbSBoris Brezillon 				  uint32_t data_len, const uint8_t *buf,
748767eb6fbSBoris Brezillon 				  int oob_required, int page)
74993db446aSBoris Brezillon {
750767eb6fbSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
751767eb6fbSBoris Brezillon 
75293db446aSBoris Brezillon 	nand_prog_page_begin_op(chip, page, 0, NULL, 0);
753c0739d85SBoris Brezillon 	fsl_elbc_write_buf(chip, buf, mtd->writesize);
754c0739d85SBoris Brezillon 	fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize);
75593db446aSBoris Brezillon 	return nand_prog_page_end_op(chip);
75693db446aSBoris Brezillon }
75793db446aSBoris Brezillon 
75893db446aSBoris Brezillon static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
75993db446aSBoris Brezillon {
76093db446aSBoris Brezillon 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
76193db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
76293db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
76393db446aSBoris Brezillon 	struct nand_chip *chip = &priv->chip;
76493db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
76593db446aSBoris Brezillon 
76693db446aSBoris Brezillon 	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
76793db446aSBoris Brezillon 
76893db446aSBoris Brezillon 	/* Fill in fsl_elbc_mtd structure */
76993db446aSBoris Brezillon 	mtd->dev.parent = priv->dev;
77093db446aSBoris Brezillon 	nand_set_flash_node(chip, priv->dev->of_node);
77193db446aSBoris Brezillon 
77293db446aSBoris Brezillon 	/* set timeout to maximum */
77393db446aSBoris Brezillon 	priv->fmr = 15 << FMR_CWTO_SHIFT;
77493db446aSBoris Brezillon 	if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS)
77593db446aSBoris Brezillon 		priv->fmr |= FMR_ECCM;
77693db446aSBoris Brezillon 
77793db446aSBoris Brezillon 	/* fill in nand_chip structure */
77893db446aSBoris Brezillon 	/* set up function call table */
77993db446aSBoris Brezillon 	chip->read_byte = fsl_elbc_read_byte;
78093db446aSBoris Brezillon 	chip->write_buf = fsl_elbc_write_buf;
78193db446aSBoris Brezillon 	chip->read_buf = fsl_elbc_read_buf;
78293db446aSBoris Brezillon 	chip->select_chip = fsl_elbc_select_chip;
78393db446aSBoris Brezillon 	chip->cmdfunc = fsl_elbc_cmdfunc;
78493db446aSBoris Brezillon 	chip->waitfunc = fsl_elbc_wait;
785b958758eSMiquel Raynal 	chip->set_features = nand_get_set_features_notsupp;
786b958758eSMiquel Raynal 	chip->get_features = nand_get_set_features_notsupp;
78793db446aSBoris Brezillon 
78893db446aSBoris Brezillon 	chip->bbt_td = &bbt_main_descr;
78993db446aSBoris Brezillon 	chip->bbt_md = &bbt_mirror_descr;
79093db446aSBoris Brezillon 
79193db446aSBoris Brezillon 	/* set up nand options */
79293db446aSBoris Brezillon 	chip->bbt_options = NAND_BBT_USE_FLASH;
79393db446aSBoris Brezillon 
79493db446aSBoris Brezillon 	chip->controller = &elbc_fcm_ctrl->controller;
79593db446aSBoris Brezillon 	nand_set_controller_data(chip, priv);
79693db446aSBoris Brezillon 
79793db446aSBoris Brezillon 	chip->ecc.read_page = fsl_elbc_read_page;
79893db446aSBoris Brezillon 	chip->ecc.write_page = fsl_elbc_write_page;
79993db446aSBoris Brezillon 	chip->ecc.write_subpage = fsl_elbc_write_subpage;
80093db446aSBoris Brezillon 
80193db446aSBoris Brezillon 	/* If CS Base Register selects full hardware ECC then use it */
80293db446aSBoris Brezillon 	if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
80393db446aSBoris Brezillon 	    BR_DECC_CHK_GEN) {
80493db446aSBoris Brezillon 		chip->ecc.mode = NAND_ECC_HW;
80593db446aSBoris Brezillon 		mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops);
80693db446aSBoris Brezillon 		chip->ecc.size = 512;
80793db446aSBoris Brezillon 		chip->ecc.bytes = 3;
80893db446aSBoris Brezillon 		chip->ecc.strength = 1;
80993db446aSBoris Brezillon 	} else {
81093db446aSBoris Brezillon 		/* otherwise fall back to default software ECC */
81193db446aSBoris Brezillon 		chip->ecc.mode = NAND_ECC_SOFT;
81293db446aSBoris Brezillon 		chip->ecc.algo = NAND_ECC_HAMMING;
81393db446aSBoris Brezillon 	}
81493db446aSBoris Brezillon 
81593db446aSBoris Brezillon 	return 0;
81693db446aSBoris Brezillon }
81793db446aSBoris Brezillon 
81893db446aSBoris Brezillon static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
81993db446aSBoris Brezillon {
82093db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
82193db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
82293db446aSBoris Brezillon 
82393db446aSBoris Brezillon 	kfree(mtd->name);
82493db446aSBoris Brezillon 
82593db446aSBoris Brezillon 	if (priv->vbase)
82693db446aSBoris Brezillon 		iounmap(priv->vbase);
82793db446aSBoris Brezillon 
82893db446aSBoris Brezillon 	elbc_fcm_ctrl->chips[priv->bank] = NULL;
82993db446aSBoris Brezillon 	kfree(priv);
83093db446aSBoris Brezillon 	return 0;
83193db446aSBoris Brezillon }
83293db446aSBoris Brezillon 
83393db446aSBoris Brezillon static DEFINE_MUTEX(fsl_elbc_nand_mutex);
83493db446aSBoris Brezillon 
83593db446aSBoris Brezillon static int fsl_elbc_nand_probe(struct platform_device *pdev)
83693db446aSBoris Brezillon {
83793db446aSBoris Brezillon 	struct fsl_lbc_regs __iomem *lbc;
83893db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv;
83993db446aSBoris Brezillon 	struct resource res;
84093db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
84193db446aSBoris Brezillon 	static const char *part_probe_types[]
84293db446aSBoris Brezillon 		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
84393db446aSBoris Brezillon 	int ret;
84493db446aSBoris Brezillon 	int bank;
84593db446aSBoris Brezillon 	struct device *dev;
84693db446aSBoris Brezillon 	struct device_node *node = pdev->dev.of_node;
84793db446aSBoris Brezillon 	struct mtd_info *mtd;
84893db446aSBoris Brezillon 
84993db446aSBoris Brezillon 	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
85093db446aSBoris Brezillon 		return -ENODEV;
85193db446aSBoris Brezillon 	lbc = fsl_lbc_ctrl_dev->regs;
85293db446aSBoris Brezillon 	dev = fsl_lbc_ctrl_dev->dev;
85393db446aSBoris Brezillon 
85493db446aSBoris Brezillon 	/* get, allocate and map the memory resource */
85593db446aSBoris Brezillon 	ret = of_address_to_resource(node, 0, &res);
85693db446aSBoris Brezillon 	if (ret) {
85793db446aSBoris Brezillon 		dev_err(dev, "failed to get resource\n");
85893db446aSBoris Brezillon 		return ret;
85993db446aSBoris Brezillon 	}
86093db446aSBoris Brezillon 
86193db446aSBoris Brezillon 	/* find which chip select it is connected to */
86293db446aSBoris Brezillon 	for (bank = 0; bank < MAX_BANKS; bank++)
86393db446aSBoris Brezillon 		if ((in_be32(&lbc->bank[bank].br) & BR_V) &&
86493db446aSBoris Brezillon 		    (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
86593db446aSBoris Brezillon 		    (in_be32(&lbc->bank[bank].br) &
86693db446aSBoris Brezillon 		     in_be32(&lbc->bank[bank].or) & BR_BA)
86793db446aSBoris Brezillon 		     == fsl_lbc_addr(res.start))
86893db446aSBoris Brezillon 			break;
86993db446aSBoris Brezillon 
87093db446aSBoris Brezillon 	if (bank >= MAX_BANKS) {
87193db446aSBoris Brezillon 		dev_err(dev, "address did not match any chip selects\n");
87293db446aSBoris Brezillon 		return -ENODEV;
87393db446aSBoris Brezillon 	}
87493db446aSBoris Brezillon 
87593db446aSBoris Brezillon 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
87693db446aSBoris Brezillon 	if (!priv)
87793db446aSBoris Brezillon 		return -ENOMEM;
87893db446aSBoris Brezillon 
87993db446aSBoris Brezillon 	mutex_lock(&fsl_elbc_nand_mutex);
88093db446aSBoris Brezillon 	if (!fsl_lbc_ctrl_dev->nand) {
88193db446aSBoris Brezillon 		elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
88293db446aSBoris Brezillon 		if (!elbc_fcm_ctrl) {
88393db446aSBoris Brezillon 			mutex_unlock(&fsl_elbc_nand_mutex);
88493db446aSBoris Brezillon 			ret = -ENOMEM;
88593db446aSBoris Brezillon 			goto err;
88693db446aSBoris Brezillon 		}
88793db446aSBoris Brezillon 		elbc_fcm_ctrl->counter++;
88893db446aSBoris Brezillon 
8897da45139SMiquel Raynal 		nand_controller_init(&elbc_fcm_ctrl->controller);
89093db446aSBoris Brezillon 		fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
89193db446aSBoris Brezillon 	} else {
89293db446aSBoris Brezillon 		elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
89393db446aSBoris Brezillon 	}
89493db446aSBoris Brezillon 	mutex_unlock(&fsl_elbc_nand_mutex);
89593db446aSBoris Brezillon 
89693db446aSBoris Brezillon 	elbc_fcm_ctrl->chips[bank] = priv;
89793db446aSBoris Brezillon 	priv->bank = bank;
89893db446aSBoris Brezillon 	priv->ctrl = fsl_lbc_ctrl_dev;
89993db446aSBoris Brezillon 	priv->dev = &pdev->dev;
90093db446aSBoris Brezillon 	dev_set_drvdata(priv->dev, priv);
90193db446aSBoris Brezillon 
90293db446aSBoris Brezillon 	priv->vbase = ioremap(res.start, resource_size(&res));
90393db446aSBoris Brezillon 	if (!priv->vbase) {
90493db446aSBoris Brezillon 		dev_err(dev, "failed to map chip region\n");
90593db446aSBoris Brezillon 		ret = -ENOMEM;
90693db446aSBoris Brezillon 		goto err;
90793db446aSBoris Brezillon 	}
90893db446aSBoris Brezillon 
90993db446aSBoris Brezillon 	mtd = nand_to_mtd(&priv->chip);
91093db446aSBoris Brezillon 	mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
91193db446aSBoris Brezillon 	if (!nand_to_mtd(&priv->chip)->name) {
91293db446aSBoris Brezillon 		ret = -ENOMEM;
91393db446aSBoris Brezillon 		goto err;
91493db446aSBoris Brezillon 	}
91593db446aSBoris Brezillon 
91693db446aSBoris Brezillon 	ret = fsl_elbc_chip_init(priv);
91793db446aSBoris Brezillon 	if (ret)
91893db446aSBoris Brezillon 		goto err;
91993db446aSBoris Brezillon 
9205bf3e76bSMiquel Raynal 	priv->chip.controller->ops = &fsl_elbc_controller_ops;
92100ad378fSBoris Brezillon 	ret = nand_scan(&priv->chip, 1);
92293db446aSBoris Brezillon 	if (ret)
92393db446aSBoris Brezillon 		goto err;
92493db446aSBoris Brezillon 
92593db446aSBoris Brezillon 	/* First look for RedBoot table or partitions on the command
92693db446aSBoris Brezillon 	 * line, these take precedence over device tree information */
92739b77c58SMiquel Raynal 	ret = mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0);
92839b77c58SMiquel Raynal 	if (ret)
92939b77c58SMiquel Raynal 		goto cleanup_nand;
93093db446aSBoris Brezillon 
93163fa37f0SShreeya Patel 	pr_info("eLBC NAND device at 0x%llx, bank %d\n",
93293db446aSBoris Brezillon 		(unsigned long long)res.start, priv->bank);
93339b77c58SMiquel Raynal 
93493db446aSBoris Brezillon 	return 0;
93593db446aSBoris Brezillon 
93639b77c58SMiquel Raynal cleanup_nand:
93739b77c58SMiquel Raynal 	nand_cleanup(&priv->chip);
93893db446aSBoris Brezillon err:
93993db446aSBoris Brezillon 	fsl_elbc_chip_remove(priv);
94039b77c58SMiquel Raynal 
94193db446aSBoris Brezillon 	return ret;
94293db446aSBoris Brezillon }
94393db446aSBoris Brezillon 
94493db446aSBoris Brezillon static int fsl_elbc_nand_remove(struct platform_device *pdev)
94593db446aSBoris Brezillon {
94693db446aSBoris Brezillon 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
94793db446aSBoris Brezillon 	struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev);
94893db446aSBoris Brezillon 
94959ac276fSBoris Brezillon 	nand_release(&priv->chip);
95093db446aSBoris Brezillon 	fsl_elbc_chip_remove(priv);
95193db446aSBoris Brezillon 
95293db446aSBoris Brezillon 	mutex_lock(&fsl_elbc_nand_mutex);
95393db446aSBoris Brezillon 	elbc_fcm_ctrl->counter--;
95493db446aSBoris Brezillon 	if (!elbc_fcm_ctrl->counter) {
95593db446aSBoris Brezillon 		fsl_lbc_ctrl_dev->nand = NULL;
95693db446aSBoris Brezillon 		kfree(elbc_fcm_ctrl);
95793db446aSBoris Brezillon 	}
95893db446aSBoris Brezillon 	mutex_unlock(&fsl_elbc_nand_mutex);
95993db446aSBoris Brezillon 
96093db446aSBoris Brezillon 	return 0;
96193db446aSBoris Brezillon 
96293db446aSBoris Brezillon }
96393db446aSBoris Brezillon 
96493db446aSBoris Brezillon static const struct of_device_id fsl_elbc_nand_match[] = {
96593db446aSBoris Brezillon 	{ .compatible = "fsl,elbc-fcm-nand", },
96693db446aSBoris Brezillon 	{}
96793db446aSBoris Brezillon };
96893db446aSBoris Brezillon MODULE_DEVICE_TABLE(of, fsl_elbc_nand_match);
96993db446aSBoris Brezillon 
97093db446aSBoris Brezillon static struct platform_driver fsl_elbc_nand_driver = {
97193db446aSBoris Brezillon 	.driver = {
97293db446aSBoris Brezillon 		.name = "fsl,elbc-fcm-nand",
97393db446aSBoris Brezillon 		.of_match_table = fsl_elbc_nand_match,
97493db446aSBoris Brezillon 	},
97593db446aSBoris Brezillon 	.probe = fsl_elbc_nand_probe,
97693db446aSBoris Brezillon 	.remove = fsl_elbc_nand_remove,
97793db446aSBoris Brezillon };
97893db446aSBoris Brezillon 
97993db446aSBoris Brezillon module_platform_driver(fsl_elbc_nand_driver);
98093db446aSBoris Brezillon 
98193db446aSBoris Brezillon MODULE_LICENSE("GPL");
98293db446aSBoris Brezillon MODULE_AUTHOR("Freescale");
98393db446aSBoris Brezillon MODULE_DESCRIPTION("Freescale Enhanced Local Bus Controller MTD NAND driver");
984