xref: /linux/drivers/mtd/nand/raw/mxc_nand.c (revision 3f77f244d8ec28e3a0a81240ffac7d626390060c)
193db446aSBoris Brezillon /*
293db446aSBoris Brezillon  * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
393db446aSBoris Brezillon  * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
493db446aSBoris Brezillon  *
593db446aSBoris Brezillon  * This program is free software; you can redistribute it and/or
693db446aSBoris Brezillon  * modify it under the terms of the GNU General Public License
793db446aSBoris Brezillon  * as published by the Free Software Foundation; either version 2
893db446aSBoris Brezillon  * of the License, or (at your option) any later version.
993db446aSBoris Brezillon  * This program is distributed in the hope that it will be useful,
1093db446aSBoris Brezillon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1193db446aSBoris Brezillon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1293db446aSBoris Brezillon  * GNU General Public License for more details.
1393db446aSBoris Brezillon  *
1493db446aSBoris Brezillon  * You should have received a copy of the GNU General Public License
1593db446aSBoris Brezillon  * along with this program; if not, write to the Free Software
1693db446aSBoris Brezillon  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
1793db446aSBoris Brezillon  * MA 02110-1301, USA.
1893db446aSBoris Brezillon  */
1993db446aSBoris Brezillon 
2093db446aSBoris Brezillon #include <linux/delay.h>
2193db446aSBoris Brezillon #include <linux/slab.h>
2293db446aSBoris Brezillon #include <linux/init.h>
2393db446aSBoris Brezillon #include <linux/module.h>
2493db446aSBoris Brezillon #include <linux/mtd/mtd.h>
2593db446aSBoris Brezillon #include <linux/mtd/rawnand.h>
2693db446aSBoris Brezillon #include <linux/mtd/partitions.h>
2793db446aSBoris Brezillon #include <linux/interrupt.h>
2893db446aSBoris Brezillon #include <linux/device.h>
2993db446aSBoris Brezillon #include <linux/platform_device.h>
3093db446aSBoris Brezillon #include <linux/clk.h>
3193db446aSBoris Brezillon #include <linux/err.h>
3293db446aSBoris Brezillon #include <linux/io.h>
3393db446aSBoris Brezillon #include <linux/irq.h>
3493db446aSBoris Brezillon #include <linux/completion.h>
3593db446aSBoris Brezillon #include <linux/of.h>
3693db446aSBoris Brezillon #include <linux/of_device.h>
3793db446aSBoris Brezillon 
3893db446aSBoris Brezillon #include <asm/mach/flash.h>
3993db446aSBoris Brezillon #include <linux/platform_data/mtd-mxc_nand.h>
4093db446aSBoris Brezillon 
4193db446aSBoris Brezillon #define DRIVER_NAME "mxc_nand"
4293db446aSBoris Brezillon 
4393db446aSBoris Brezillon /* Addresses for NFC registers */
4493db446aSBoris Brezillon #define NFC_V1_V2_BUF_SIZE		(host->regs + 0x00)
4593db446aSBoris Brezillon #define NFC_V1_V2_BUF_ADDR		(host->regs + 0x04)
4693db446aSBoris Brezillon #define NFC_V1_V2_FLASH_ADDR		(host->regs + 0x06)
4793db446aSBoris Brezillon #define NFC_V1_V2_FLASH_CMD		(host->regs + 0x08)
4893db446aSBoris Brezillon #define NFC_V1_V2_CONFIG		(host->regs + 0x0a)
4993db446aSBoris Brezillon #define NFC_V1_V2_ECC_STATUS_RESULT	(host->regs + 0x0c)
5093db446aSBoris Brezillon #define NFC_V1_V2_RSLTMAIN_AREA		(host->regs + 0x0e)
51*3f77f244SMartin Kaiser #define NFC_V21_RSLTSPARE_AREA		(host->regs + 0x10)
5293db446aSBoris Brezillon #define NFC_V1_V2_WRPROT		(host->regs + 0x12)
5393db446aSBoris Brezillon #define NFC_V1_UNLOCKSTART_BLKADDR	(host->regs + 0x14)
5493db446aSBoris Brezillon #define NFC_V1_UNLOCKEND_BLKADDR	(host->regs + 0x16)
5593db446aSBoris Brezillon #define NFC_V21_UNLOCKSTART_BLKADDR0	(host->regs + 0x20)
5693db446aSBoris Brezillon #define NFC_V21_UNLOCKSTART_BLKADDR1	(host->regs + 0x24)
5793db446aSBoris Brezillon #define NFC_V21_UNLOCKSTART_BLKADDR2	(host->regs + 0x28)
5893db446aSBoris Brezillon #define NFC_V21_UNLOCKSTART_BLKADDR3	(host->regs + 0x2c)
5993db446aSBoris Brezillon #define NFC_V21_UNLOCKEND_BLKADDR0	(host->regs + 0x22)
6093db446aSBoris Brezillon #define NFC_V21_UNLOCKEND_BLKADDR1	(host->regs + 0x26)
6193db446aSBoris Brezillon #define NFC_V21_UNLOCKEND_BLKADDR2	(host->regs + 0x2a)
6293db446aSBoris Brezillon #define NFC_V21_UNLOCKEND_BLKADDR3	(host->regs + 0x2e)
6393db446aSBoris Brezillon #define NFC_V1_V2_NF_WRPRST		(host->regs + 0x18)
6493db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1		(host->regs + 0x1a)
6593db446aSBoris Brezillon #define NFC_V1_V2_CONFIG2		(host->regs + 0x1c)
6693db446aSBoris Brezillon 
6793db446aSBoris Brezillon #define NFC_V2_CONFIG1_ECC_MODE_4	(1 << 0)
6893db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_SP_EN		(1 << 2)
6993db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_ECC_EN	(1 << 3)
7093db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_INT_MSK	(1 << 4)
7193db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_BIG		(1 << 5)
7293db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_RST		(1 << 6)
7393db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_CE		(1 << 7)
7493db446aSBoris Brezillon #define NFC_V2_CONFIG1_ONE_CYCLE	(1 << 8)
7593db446aSBoris Brezillon #define NFC_V2_CONFIG1_PPB(x)		(((x) & 0x3) << 9)
7693db446aSBoris Brezillon #define NFC_V2_CONFIG1_FP_INT		(1 << 11)
7793db446aSBoris Brezillon 
7893db446aSBoris Brezillon #define NFC_V1_V2_CONFIG2_INT		(1 << 15)
7993db446aSBoris Brezillon 
8093db446aSBoris Brezillon /*
8193db446aSBoris Brezillon  * Operation modes for the NFC. Valid for v1, v2 and v3
8293db446aSBoris Brezillon  * type controllers.
8393db446aSBoris Brezillon  */
8493db446aSBoris Brezillon #define NFC_CMD				(1 << 0)
8593db446aSBoris Brezillon #define NFC_ADDR			(1 << 1)
8693db446aSBoris Brezillon #define NFC_INPUT			(1 << 2)
8793db446aSBoris Brezillon #define NFC_OUTPUT			(1 << 3)
8893db446aSBoris Brezillon #define NFC_ID				(1 << 4)
8993db446aSBoris Brezillon #define NFC_STATUS			(1 << 5)
9093db446aSBoris Brezillon 
9193db446aSBoris Brezillon #define NFC_V3_FLASH_CMD		(host->regs_axi + 0x00)
9293db446aSBoris Brezillon #define NFC_V3_FLASH_ADDR0		(host->regs_axi + 0x04)
9393db446aSBoris Brezillon 
9493db446aSBoris Brezillon #define NFC_V3_CONFIG1			(host->regs_axi + 0x34)
9593db446aSBoris Brezillon #define NFC_V3_CONFIG1_SP_EN		(1 << 0)
9693db446aSBoris Brezillon #define NFC_V3_CONFIG1_RBA(x)		(((x) & 0x7 ) << 4)
9793db446aSBoris Brezillon 
9893db446aSBoris Brezillon #define NFC_V3_ECC_STATUS_RESULT	(host->regs_axi + 0x38)
9993db446aSBoris Brezillon 
10093db446aSBoris Brezillon #define NFC_V3_LAUNCH			(host->regs_axi + 0x40)
10193db446aSBoris Brezillon 
10293db446aSBoris Brezillon #define NFC_V3_WRPROT			(host->regs_ip + 0x0)
10393db446aSBoris Brezillon #define NFC_V3_WRPROT_LOCK_TIGHT	(1 << 0)
10493db446aSBoris Brezillon #define NFC_V3_WRPROT_LOCK		(1 << 1)
10593db446aSBoris Brezillon #define NFC_V3_WRPROT_UNLOCK		(1 << 2)
10693db446aSBoris Brezillon #define NFC_V3_WRPROT_BLS_UNLOCK	(2 << 6)
10793db446aSBoris Brezillon 
10893db446aSBoris Brezillon #define NFC_V3_WRPROT_UNLOCK_BLK_ADD0   (host->regs_ip + 0x04)
10993db446aSBoris Brezillon 
11093db446aSBoris Brezillon #define NFC_V3_CONFIG2			(host->regs_ip + 0x24)
11193db446aSBoris Brezillon #define NFC_V3_CONFIG2_PS_512			(0 << 0)
11293db446aSBoris Brezillon #define NFC_V3_CONFIG2_PS_2048			(1 << 0)
11393db446aSBoris Brezillon #define NFC_V3_CONFIG2_PS_4096			(2 << 0)
11493db446aSBoris Brezillon #define NFC_V3_CONFIG2_ONE_CYCLE		(1 << 2)
11593db446aSBoris Brezillon #define NFC_V3_CONFIG2_ECC_EN			(1 << 3)
11693db446aSBoris Brezillon #define NFC_V3_CONFIG2_2CMD_PHASES		(1 << 4)
11793db446aSBoris Brezillon #define NFC_V3_CONFIG2_NUM_ADDR_PHASE0		(1 << 5)
11893db446aSBoris Brezillon #define NFC_V3_CONFIG2_ECC_MODE_8		(1 << 6)
11993db446aSBoris Brezillon #define NFC_V3_CONFIG2_PPB(x, shift)		(((x) & 0x3) << shift)
12093db446aSBoris Brezillon #define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x)	(((x) & 0x3) << 12)
12193db446aSBoris Brezillon #define NFC_V3_CONFIG2_INT_MSK			(1 << 15)
12293db446aSBoris Brezillon #define NFC_V3_CONFIG2_ST_CMD(x)		(((x) & 0xff) << 24)
12393db446aSBoris Brezillon #define NFC_V3_CONFIG2_SPAS(x)			(((x) & 0xff) << 16)
12493db446aSBoris Brezillon 
12593db446aSBoris Brezillon #define NFC_V3_CONFIG3				(host->regs_ip + 0x28)
12693db446aSBoris Brezillon #define NFC_V3_CONFIG3_ADD_OP(x)		(((x) & 0x3) << 0)
12793db446aSBoris Brezillon #define NFC_V3_CONFIG3_FW8			(1 << 3)
12893db446aSBoris Brezillon #define NFC_V3_CONFIG3_SBB(x)			(((x) & 0x7) << 8)
12993db446aSBoris Brezillon #define NFC_V3_CONFIG3_NUM_OF_DEVICES(x)	(((x) & 0x7) << 12)
13093db446aSBoris Brezillon #define NFC_V3_CONFIG3_RBB_MODE			(1 << 15)
13193db446aSBoris Brezillon #define NFC_V3_CONFIG3_NO_SDMA			(1 << 20)
13293db446aSBoris Brezillon 
13393db446aSBoris Brezillon #define NFC_V3_IPC			(host->regs_ip + 0x2C)
13493db446aSBoris Brezillon #define NFC_V3_IPC_CREQ			(1 << 0)
13593db446aSBoris Brezillon #define NFC_V3_IPC_INT			(1 << 31)
13693db446aSBoris Brezillon 
13793db446aSBoris Brezillon #define NFC_V3_DELAY_LINE		(host->regs_ip + 0x34)
13893db446aSBoris Brezillon 
13993db446aSBoris Brezillon struct mxc_nand_host;
14093db446aSBoris Brezillon 
14193db446aSBoris Brezillon struct mxc_nand_devtype_data {
14293db446aSBoris Brezillon 	void (*preset)(struct mtd_info *);
14393db446aSBoris Brezillon 	int (*read_page)(struct nand_chip *chip, void *buf, void *oob, bool ecc,
14493db446aSBoris Brezillon 			 int page);
14593db446aSBoris Brezillon 	void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
14693db446aSBoris Brezillon 	void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
14793db446aSBoris Brezillon 	void (*send_page)(struct mtd_info *, unsigned int);
14893db446aSBoris Brezillon 	void (*send_read_id)(struct mxc_nand_host *);
14993db446aSBoris Brezillon 	uint16_t (*get_dev_status)(struct mxc_nand_host *);
15093db446aSBoris Brezillon 	int (*check_int)(struct mxc_nand_host *);
15193db446aSBoris Brezillon 	void (*irq_control)(struct mxc_nand_host *, int);
15293db446aSBoris Brezillon 	u32 (*get_ecc_status)(struct mxc_nand_host *);
15393db446aSBoris Brezillon 	const struct mtd_ooblayout_ops *ooblayout;
15493db446aSBoris Brezillon 	void (*select_chip)(struct mtd_info *mtd, int chip);
15593db446aSBoris Brezillon 	int (*setup_data_interface)(struct mtd_info *mtd, int csline,
15693db446aSBoris Brezillon 				    const struct nand_data_interface *conf);
15793db446aSBoris Brezillon 	void (*enable_hwecc)(struct nand_chip *chip, bool enable);
15893db446aSBoris Brezillon 
15993db446aSBoris Brezillon 	/*
16093db446aSBoris Brezillon 	 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
16193db446aSBoris Brezillon 	 * (CONFIG1:INT_MSK is set). To handle this the driver uses
16293db446aSBoris Brezillon 	 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
16393db446aSBoris Brezillon 	 */
16493db446aSBoris Brezillon 	int irqpending_quirk;
16593db446aSBoris Brezillon 	int needs_ip;
16693db446aSBoris Brezillon 
16793db446aSBoris Brezillon 	size_t regs_offset;
16893db446aSBoris Brezillon 	size_t spare0_offset;
16993db446aSBoris Brezillon 	size_t axi_offset;
17093db446aSBoris Brezillon 
17193db446aSBoris Brezillon 	int spare_len;
17293db446aSBoris Brezillon 	int eccbytes;
17393db446aSBoris Brezillon 	int eccsize;
17493db446aSBoris Brezillon 	int ppb_shift;
17593db446aSBoris Brezillon };
17693db446aSBoris Brezillon 
17793db446aSBoris Brezillon struct mxc_nand_host {
17893db446aSBoris Brezillon 	struct nand_chip	nand;
17993db446aSBoris Brezillon 	struct device		*dev;
18093db446aSBoris Brezillon 
18193db446aSBoris Brezillon 	void __iomem		*spare0;
18293db446aSBoris Brezillon 	void __iomem		*main_area0;
18393db446aSBoris Brezillon 
18493db446aSBoris Brezillon 	void __iomem		*base;
18593db446aSBoris Brezillon 	void __iomem		*regs;
18693db446aSBoris Brezillon 	void __iomem		*regs_axi;
18793db446aSBoris Brezillon 	void __iomem		*regs_ip;
18893db446aSBoris Brezillon 	int			status_request;
18993db446aSBoris Brezillon 	struct clk		*clk;
19093db446aSBoris Brezillon 	int			clk_act;
19193db446aSBoris Brezillon 	int			irq;
19293db446aSBoris Brezillon 	int			eccsize;
19393db446aSBoris Brezillon 	int			used_oobsize;
19493db446aSBoris Brezillon 	int			active_cs;
19593db446aSBoris Brezillon 
19693db446aSBoris Brezillon 	struct completion	op_completion;
19793db446aSBoris Brezillon 
19893db446aSBoris Brezillon 	uint8_t			*data_buf;
19993db446aSBoris Brezillon 	unsigned int		buf_start;
20093db446aSBoris Brezillon 
20193db446aSBoris Brezillon 	const struct mxc_nand_devtype_data *devtype_data;
20293db446aSBoris Brezillon 	struct mxc_nand_platform_data pdata;
20393db446aSBoris Brezillon };
20493db446aSBoris Brezillon 
20593db446aSBoris Brezillon static const char * const part_probes[] = {
20693db446aSBoris Brezillon 	"cmdlinepart", "RedBoot", "ofpart", NULL };
20793db446aSBoris Brezillon 
20893db446aSBoris Brezillon static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
20993db446aSBoris Brezillon {
21093db446aSBoris Brezillon 	int i;
21193db446aSBoris Brezillon 	u32 *t = trg;
21293db446aSBoris Brezillon 	const __iomem u32 *s = src;
21393db446aSBoris Brezillon 
21493db446aSBoris Brezillon 	for (i = 0; i < (size >> 2); i++)
21593db446aSBoris Brezillon 		*t++ = __raw_readl(s++);
21693db446aSBoris Brezillon }
21793db446aSBoris Brezillon 
21893db446aSBoris Brezillon static void memcpy16_fromio(void *trg, const void __iomem  *src, size_t size)
21993db446aSBoris Brezillon {
22093db446aSBoris Brezillon 	int i;
22193db446aSBoris Brezillon 	u16 *t = trg;
22293db446aSBoris Brezillon 	const __iomem u16 *s = src;
22393db446aSBoris Brezillon 
22493db446aSBoris Brezillon 	/* We assume that src (IO) is always 32bit aligned */
22593db446aSBoris Brezillon 	if (PTR_ALIGN(trg, 4) == trg && IS_ALIGNED(size, 4)) {
22693db446aSBoris Brezillon 		memcpy32_fromio(trg, src, size);
22793db446aSBoris Brezillon 		return;
22893db446aSBoris Brezillon 	}
22993db446aSBoris Brezillon 
23093db446aSBoris Brezillon 	for (i = 0; i < (size >> 1); i++)
23193db446aSBoris Brezillon 		*t++ = __raw_readw(s++);
23293db446aSBoris Brezillon }
23393db446aSBoris Brezillon 
23493db446aSBoris Brezillon static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
23593db446aSBoris Brezillon {
23693db446aSBoris Brezillon 	/* __iowrite32_copy use 32bit size values so divide by 4 */
23793db446aSBoris Brezillon 	__iowrite32_copy(trg, src, size / 4);
23893db446aSBoris Brezillon }
23993db446aSBoris Brezillon 
24093db446aSBoris Brezillon static void memcpy16_toio(void __iomem *trg, const void *src, int size)
24193db446aSBoris Brezillon {
24293db446aSBoris Brezillon 	int i;
24393db446aSBoris Brezillon 	__iomem u16 *t = trg;
24493db446aSBoris Brezillon 	const u16 *s = src;
24593db446aSBoris Brezillon 
24693db446aSBoris Brezillon 	/* We assume that trg (IO) is always 32bit aligned */
24793db446aSBoris Brezillon 	if (PTR_ALIGN(src, 4) == src && IS_ALIGNED(size, 4)) {
24893db446aSBoris Brezillon 		memcpy32_toio(trg, src, size);
24993db446aSBoris Brezillon 		return;
25093db446aSBoris Brezillon 	}
25193db446aSBoris Brezillon 
25293db446aSBoris Brezillon 	for (i = 0; i < (size >> 1); i++)
25393db446aSBoris Brezillon 		__raw_writew(*s++, t++);
25493db446aSBoris Brezillon }
25593db446aSBoris Brezillon 
25693db446aSBoris Brezillon /*
25793db446aSBoris Brezillon  * The controller splits a page into data chunks of 512 bytes + partial oob.
25893db446aSBoris Brezillon  * There are writesize / 512 such chunks, the size of the partial oob parts is
25993db446aSBoris Brezillon  * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then
26093db446aSBoris Brezillon  * contains additionally the byte lost by rounding (if any).
26193db446aSBoris Brezillon  * This function handles the needed shuffling between host->data_buf (which
26293db446aSBoris Brezillon  * holds a page in natural order, i.e. writesize bytes data + oobsize bytes
26393db446aSBoris Brezillon  * spare) and the NFC buffer.
26493db446aSBoris Brezillon  */
26593db446aSBoris Brezillon static void copy_spare(struct mtd_info *mtd, bool bfrom, void *buf)
26693db446aSBoris Brezillon {
26793db446aSBoris Brezillon 	struct nand_chip *this = mtd_to_nand(mtd);
26893db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(this);
26993db446aSBoris Brezillon 	u16 i, oob_chunk_size;
27093db446aSBoris Brezillon 	u16 num_chunks = mtd->writesize / 512;
27193db446aSBoris Brezillon 
27293db446aSBoris Brezillon 	u8 *d = buf;
27393db446aSBoris Brezillon 	u8 __iomem *s = host->spare0;
27493db446aSBoris Brezillon 	u16 sparebuf_size = host->devtype_data->spare_len;
27593db446aSBoris Brezillon 
27693db446aSBoris Brezillon 	/* size of oob chunk for all but possibly the last one */
27793db446aSBoris Brezillon 	oob_chunk_size = (host->used_oobsize / num_chunks) & ~1;
27893db446aSBoris Brezillon 
27993db446aSBoris Brezillon 	if (bfrom) {
28093db446aSBoris Brezillon 		for (i = 0; i < num_chunks - 1; i++)
28193db446aSBoris Brezillon 			memcpy16_fromio(d + i * oob_chunk_size,
28293db446aSBoris Brezillon 					s + i * sparebuf_size,
28393db446aSBoris Brezillon 					oob_chunk_size);
28493db446aSBoris Brezillon 
28593db446aSBoris Brezillon 		/* the last chunk */
28693db446aSBoris Brezillon 		memcpy16_fromio(d + i * oob_chunk_size,
28793db446aSBoris Brezillon 				s + i * sparebuf_size,
28893db446aSBoris Brezillon 				host->used_oobsize - i * oob_chunk_size);
28993db446aSBoris Brezillon 	} else {
29093db446aSBoris Brezillon 		for (i = 0; i < num_chunks - 1; i++)
29193db446aSBoris Brezillon 			memcpy16_toio(&s[i * sparebuf_size],
29293db446aSBoris Brezillon 				      &d[i * oob_chunk_size],
29393db446aSBoris Brezillon 				      oob_chunk_size);
29493db446aSBoris Brezillon 
29593db446aSBoris Brezillon 		/* the last chunk */
29693db446aSBoris Brezillon 		memcpy16_toio(&s[i * sparebuf_size],
29793db446aSBoris Brezillon 			      &d[i * oob_chunk_size],
29893db446aSBoris Brezillon 			      host->used_oobsize - i * oob_chunk_size);
29993db446aSBoris Brezillon 	}
30093db446aSBoris Brezillon }
30193db446aSBoris Brezillon 
30293db446aSBoris Brezillon /*
30393db446aSBoris Brezillon  * MXC NANDFC can only perform full page+spare or spare-only read/write.  When
30493db446aSBoris Brezillon  * the upper layers perform a read/write buf operation, the saved column address
30593db446aSBoris Brezillon  * is used to index into the full page. So usually this function is called with
30693db446aSBoris Brezillon  * column == 0 (unless no column cycle is needed indicated by column == -1)
30793db446aSBoris Brezillon  */
30893db446aSBoris Brezillon static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
30993db446aSBoris Brezillon {
31093db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
31193db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
31293db446aSBoris Brezillon 
31393db446aSBoris Brezillon 	/* Write out column address, if necessary */
31493db446aSBoris Brezillon 	if (column != -1) {
31593db446aSBoris Brezillon 		host->devtype_data->send_addr(host, column & 0xff,
31693db446aSBoris Brezillon 					      page_addr == -1);
31793db446aSBoris Brezillon 		if (mtd->writesize > 512)
31893db446aSBoris Brezillon 			/* another col addr cycle for 2k page */
31993db446aSBoris Brezillon 			host->devtype_data->send_addr(host,
32093db446aSBoris Brezillon 						      (column >> 8) & 0xff,
32193db446aSBoris Brezillon 						      false);
32293db446aSBoris Brezillon 	}
32393db446aSBoris Brezillon 
32493db446aSBoris Brezillon 	/* Write out page address, if necessary */
32593db446aSBoris Brezillon 	if (page_addr != -1) {
32693db446aSBoris Brezillon 		/* paddr_0 - p_addr_7 */
32793db446aSBoris Brezillon 		host->devtype_data->send_addr(host, (page_addr & 0xff), false);
32893db446aSBoris Brezillon 
32993db446aSBoris Brezillon 		if (mtd->writesize > 512) {
33093db446aSBoris Brezillon 			if (mtd->size >= 0x10000000) {
33193db446aSBoris Brezillon 				/* paddr_8 - paddr_15 */
33293db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
33393db446aSBoris Brezillon 						(page_addr >> 8) & 0xff,
33493db446aSBoris Brezillon 						false);
33593db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
33693db446aSBoris Brezillon 						(page_addr >> 16) & 0xff,
33793db446aSBoris Brezillon 						true);
33893db446aSBoris Brezillon 			} else
33993db446aSBoris Brezillon 				/* paddr_8 - paddr_15 */
34093db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
34193db446aSBoris Brezillon 						(page_addr >> 8) & 0xff, true);
34293db446aSBoris Brezillon 		} else {
34393db446aSBoris Brezillon 			if (nand_chip->options & NAND_ROW_ADDR_3) {
34493db446aSBoris Brezillon 				/* paddr_8 - paddr_15 */
34593db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
34693db446aSBoris Brezillon 						(page_addr >> 8) & 0xff,
34793db446aSBoris Brezillon 						false);
34893db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
34993db446aSBoris Brezillon 						(page_addr >> 16) & 0xff,
35093db446aSBoris Brezillon 						true);
35193db446aSBoris Brezillon 			} else
35293db446aSBoris Brezillon 				/* paddr_8 - paddr_15 */
35393db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
35493db446aSBoris Brezillon 						(page_addr >> 8) & 0xff, true);
35593db446aSBoris Brezillon 		}
35693db446aSBoris Brezillon 	}
35793db446aSBoris Brezillon }
35893db446aSBoris Brezillon 
35993db446aSBoris Brezillon static int check_int_v3(struct mxc_nand_host *host)
36093db446aSBoris Brezillon {
36193db446aSBoris Brezillon 	uint32_t tmp;
36293db446aSBoris Brezillon 
36393db446aSBoris Brezillon 	tmp = readl(NFC_V3_IPC);
36493db446aSBoris Brezillon 	if (!(tmp & NFC_V3_IPC_INT))
36593db446aSBoris Brezillon 		return 0;
36693db446aSBoris Brezillon 
36793db446aSBoris Brezillon 	tmp &= ~NFC_V3_IPC_INT;
36893db446aSBoris Brezillon 	writel(tmp, NFC_V3_IPC);
36993db446aSBoris Brezillon 
37093db446aSBoris Brezillon 	return 1;
37193db446aSBoris Brezillon }
37293db446aSBoris Brezillon 
37393db446aSBoris Brezillon static int check_int_v1_v2(struct mxc_nand_host *host)
37493db446aSBoris Brezillon {
37593db446aSBoris Brezillon 	uint32_t tmp;
37693db446aSBoris Brezillon 
37793db446aSBoris Brezillon 	tmp = readw(NFC_V1_V2_CONFIG2);
37893db446aSBoris Brezillon 	if (!(tmp & NFC_V1_V2_CONFIG2_INT))
37993db446aSBoris Brezillon 		return 0;
38093db446aSBoris Brezillon 
38193db446aSBoris Brezillon 	if (!host->devtype_data->irqpending_quirk)
38293db446aSBoris Brezillon 		writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
38393db446aSBoris Brezillon 
38493db446aSBoris Brezillon 	return 1;
38593db446aSBoris Brezillon }
38693db446aSBoris Brezillon 
38793db446aSBoris Brezillon static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
38893db446aSBoris Brezillon {
38993db446aSBoris Brezillon 	uint16_t tmp;
39093db446aSBoris Brezillon 
39193db446aSBoris Brezillon 	tmp = readw(NFC_V1_V2_CONFIG1);
39293db446aSBoris Brezillon 
39393db446aSBoris Brezillon 	if (activate)
39493db446aSBoris Brezillon 		tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
39593db446aSBoris Brezillon 	else
39693db446aSBoris Brezillon 		tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
39793db446aSBoris Brezillon 
39893db446aSBoris Brezillon 	writew(tmp, NFC_V1_V2_CONFIG1);
39993db446aSBoris Brezillon }
40093db446aSBoris Brezillon 
40193db446aSBoris Brezillon static void irq_control_v3(struct mxc_nand_host *host, int activate)
40293db446aSBoris Brezillon {
40393db446aSBoris Brezillon 	uint32_t tmp;
40493db446aSBoris Brezillon 
40593db446aSBoris Brezillon 	tmp = readl(NFC_V3_CONFIG2);
40693db446aSBoris Brezillon 
40793db446aSBoris Brezillon 	if (activate)
40893db446aSBoris Brezillon 		tmp &= ~NFC_V3_CONFIG2_INT_MSK;
40993db446aSBoris Brezillon 	else
41093db446aSBoris Brezillon 		tmp |= NFC_V3_CONFIG2_INT_MSK;
41193db446aSBoris Brezillon 
41293db446aSBoris Brezillon 	writel(tmp, NFC_V3_CONFIG2);
41393db446aSBoris Brezillon }
41493db446aSBoris Brezillon 
41593db446aSBoris Brezillon static void irq_control(struct mxc_nand_host *host, int activate)
41693db446aSBoris Brezillon {
41793db446aSBoris Brezillon 	if (host->devtype_data->irqpending_quirk) {
41893db446aSBoris Brezillon 		if (activate)
41993db446aSBoris Brezillon 			enable_irq(host->irq);
42093db446aSBoris Brezillon 		else
42193db446aSBoris Brezillon 			disable_irq_nosync(host->irq);
42293db446aSBoris Brezillon 	} else {
42393db446aSBoris Brezillon 		host->devtype_data->irq_control(host, activate);
42493db446aSBoris Brezillon 	}
42593db446aSBoris Brezillon }
42693db446aSBoris Brezillon 
42793db446aSBoris Brezillon static u32 get_ecc_status_v1(struct mxc_nand_host *host)
42893db446aSBoris Brezillon {
42993db446aSBoris Brezillon 	return readw(NFC_V1_V2_ECC_STATUS_RESULT);
43093db446aSBoris Brezillon }
43193db446aSBoris Brezillon 
43293db446aSBoris Brezillon static u32 get_ecc_status_v2(struct mxc_nand_host *host)
43393db446aSBoris Brezillon {
43493db446aSBoris Brezillon 	return readl(NFC_V1_V2_ECC_STATUS_RESULT);
43593db446aSBoris Brezillon }
43693db446aSBoris Brezillon 
43793db446aSBoris Brezillon static u32 get_ecc_status_v3(struct mxc_nand_host *host)
43893db446aSBoris Brezillon {
43993db446aSBoris Brezillon 	return readl(NFC_V3_ECC_STATUS_RESULT);
44093db446aSBoris Brezillon }
44193db446aSBoris Brezillon 
44293db446aSBoris Brezillon static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
44393db446aSBoris Brezillon {
44493db446aSBoris Brezillon 	struct mxc_nand_host *host = dev_id;
44593db446aSBoris Brezillon 
44693db446aSBoris Brezillon 	if (!host->devtype_data->check_int(host))
44793db446aSBoris Brezillon 		return IRQ_NONE;
44893db446aSBoris Brezillon 
44993db446aSBoris Brezillon 	irq_control(host, 0);
45093db446aSBoris Brezillon 
45193db446aSBoris Brezillon 	complete(&host->op_completion);
45293db446aSBoris Brezillon 
45393db446aSBoris Brezillon 	return IRQ_HANDLED;
45493db446aSBoris Brezillon }
45593db446aSBoris Brezillon 
45693db446aSBoris Brezillon /* This function polls the NANDFC to wait for the basic operation to
45793db446aSBoris Brezillon  * complete by checking the INT bit of config2 register.
45893db446aSBoris Brezillon  */
45993db446aSBoris Brezillon static int wait_op_done(struct mxc_nand_host *host, int useirq)
46093db446aSBoris Brezillon {
46193db446aSBoris Brezillon 	int ret = 0;
46293db446aSBoris Brezillon 
46393db446aSBoris Brezillon 	/*
46493db446aSBoris Brezillon 	 * If operation is already complete, don't bother to setup an irq or a
46593db446aSBoris Brezillon 	 * loop.
46693db446aSBoris Brezillon 	 */
46793db446aSBoris Brezillon 	if (host->devtype_data->check_int(host))
46893db446aSBoris Brezillon 		return 0;
46993db446aSBoris Brezillon 
47093db446aSBoris Brezillon 	if (useirq) {
47193db446aSBoris Brezillon 		unsigned long timeout;
47293db446aSBoris Brezillon 
47393db446aSBoris Brezillon 		reinit_completion(&host->op_completion);
47493db446aSBoris Brezillon 
47593db446aSBoris Brezillon 		irq_control(host, 1);
47693db446aSBoris Brezillon 
47793db446aSBoris Brezillon 		timeout = wait_for_completion_timeout(&host->op_completion, HZ);
47893db446aSBoris Brezillon 		if (!timeout && !host->devtype_data->check_int(host)) {
47993db446aSBoris Brezillon 			dev_dbg(host->dev, "timeout waiting for irq\n");
48093db446aSBoris Brezillon 			ret = -ETIMEDOUT;
48193db446aSBoris Brezillon 		}
48293db446aSBoris Brezillon 	} else {
48393db446aSBoris Brezillon 		int max_retries = 8000;
48493db446aSBoris Brezillon 		int done;
48593db446aSBoris Brezillon 
48693db446aSBoris Brezillon 		do {
48793db446aSBoris Brezillon 			udelay(1);
48893db446aSBoris Brezillon 
48993db446aSBoris Brezillon 			done = host->devtype_data->check_int(host);
49093db446aSBoris Brezillon 			if (done)
49193db446aSBoris Brezillon 				break;
49293db446aSBoris Brezillon 
49393db446aSBoris Brezillon 		} while (--max_retries);
49493db446aSBoris Brezillon 
49593db446aSBoris Brezillon 		if (!done) {
49693db446aSBoris Brezillon 			dev_dbg(host->dev, "timeout polling for completion\n");
49793db446aSBoris Brezillon 			ret = -ETIMEDOUT;
49893db446aSBoris Brezillon 		}
49993db446aSBoris Brezillon 	}
50093db446aSBoris Brezillon 
50193db446aSBoris Brezillon 	WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq);
50293db446aSBoris Brezillon 
50393db446aSBoris Brezillon 	return ret;
50493db446aSBoris Brezillon }
50593db446aSBoris Brezillon 
50693db446aSBoris Brezillon static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
50793db446aSBoris Brezillon {
50893db446aSBoris Brezillon 	/* fill command */
50993db446aSBoris Brezillon 	writel(cmd, NFC_V3_FLASH_CMD);
51093db446aSBoris Brezillon 
51193db446aSBoris Brezillon 	/* send out command */
51293db446aSBoris Brezillon 	writel(NFC_CMD, NFC_V3_LAUNCH);
51393db446aSBoris Brezillon 
51493db446aSBoris Brezillon 	/* Wait for operation to complete */
51593db446aSBoris Brezillon 	wait_op_done(host, useirq);
51693db446aSBoris Brezillon }
51793db446aSBoris Brezillon 
51893db446aSBoris Brezillon /* This function issues the specified command to the NAND device and
51993db446aSBoris Brezillon  * waits for completion. */
52093db446aSBoris Brezillon static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
52193db446aSBoris Brezillon {
52293db446aSBoris Brezillon 	dev_dbg(host->dev, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
52393db446aSBoris Brezillon 
52493db446aSBoris Brezillon 	writew(cmd, NFC_V1_V2_FLASH_CMD);
52593db446aSBoris Brezillon 	writew(NFC_CMD, NFC_V1_V2_CONFIG2);
52693db446aSBoris Brezillon 
52793db446aSBoris Brezillon 	if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
52893db446aSBoris Brezillon 		int max_retries = 100;
52993db446aSBoris Brezillon 		/* Reset completion is indicated by NFC_CONFIG2 */
53093db446aSBoris Brezillon 		/* being set to 0 */
53193db446aSBoris Brezillon 		while (max_retries-- > 0) {
53293db446aSBoris Brezillon 			if (readw(NFC_V1_V2_CONFIG2) == 0) {
53393db446aSBoris Brezillon 				break;
53493db446aSBoris Brezillon 			}
53593db446aSBoris Brezillon 			udelay(1);
53693db446aSBoris Brezillon 		}
53793db446aSBoris Brezillon 		if (max_retries < 0)
53893db446aSBoris Brezillon 			dev_dbg(host->dev, "%s: RESET failed\n", __func__);
53993db446aSBoris Brezillon 	} else {
54093db446aSBoris Brezillon 		/* Wait for operation to complete */
54193db446aSBoris Brezillon 		wait_op_done(host, useirq);
54293db446aSBoris Brezillon 	}
54393db446aSBoris Brezillon }
54493db446aSBoris Brezillon 
54593db446aSBoris Brezillon static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
54693db446aSBoris Brezillon {
54793db446aSBoris Brezillon 	/* fill address */
54893db446aSBoris Brezillon 	writel(addr, NFC_V3_FLASH_ADDR0);
54993db446aSBoris Brezillon 
55093db446aSBoris Brezillon 	/* send out address */
55193db446aSBoris Brezillon 	writel(NFC_ADDR, NFC_V3_LAUNCH);
55293db446aSBoris Brezillon 
55393db446aSBoris Brezillon 	wait_op_done(host, 0);
55493db446aSBoris Brezillon }
55593db446aSBoris Brezillon 
55693db446aSBoris Brezillon /* This function sends an address (or partial address) to the
55793db446aSBoris Brezillon  * NAND device. The address is used to select the source/destination for
55893db446aSBoris Brezillon  * a NAND command. */
55993db446aSBoris Brezillon static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
56093db446aSBoris Brezillon {
56193db446aSBoris Brezillon 	dev_dbg(host->dev, "send_addr(host, 0x%x %d)\n", addr, islast);
56293db446aSBoris Brezillon 
56393db446aSBoris Brezillon 	writew(addr, NFC_V1_V2_FLASH_ADDR);
56493db446aSBoris Brezillon 	writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
56593db446aSBoris Brezillon 
56693db446aSBoris Brezillon 	/* Wait for operation to complete */
56793db446aSBoris Brezillon 	wait_op_done(host, islast);
56893db446aSBoris Brezillon }
56993db446aSBoris Brezillon 
57093db446aSBoris Brezillon static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
57193db446aSBoris Brezillon {
57293db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
57393db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
57493db446aSBoris Brezillon 	uint32_t tmp;
57593db446aSBoris Brezillon 
57693db446aSBoris Brezillon 	tmp = readl(NFC_V3_CONFIG1);
57793db446aSBoris Brezillon 	tmp &= ~(7 << 4);
57893db446aSBoris Brezillon 	writel(tmp, NFC_V3_CONFIG1);
57993db446aSBoris Brezillon 
58093db446aSBoris Brezillon 	/* transfer data from NFC ram to nand */
58193db446aSBoris Brezillon 	writel(ops, NFC_V3_LAUNCH);
58293db446aSBoris Brezillon 
58393db446aSBoris Brezillon 	wait_op_done(host, false);
58493db446aSBoris Brezillon }
58593db446aSBoris Brezillon 
58693db446aSBoris Brezillon static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
58793db446aSBoris Brezillon {
58893db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
58993db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
59093db446aSBoris Brezillon 
59193db446aSBoris Brezillon 	/* NANDFC buffer 0 is used for page read/write */
59293db446aSBoris Brezillon 	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
59393db446aSBoris Brezillon 
59493db446aSBoris Brezillon 	writew(ops, NFC_V1_V2_CONFIG2);
59593db446aSBoris Brezillon 
59693db446aSBoris Brezillon 	/* Wait for operation to complete */
59793db446aSBoris Brezillon 	wait_op_done(host, true);
59893db446aSBoris Brezillon }
59993db446aSBoris Brezillon 
60093db446aSBoris Brezillon static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
60193db446aSBoris Brezillon {
60293db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
60393db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
60493db446aSBoris Brezillon 	int bufs, i;
60593db446aSBoris Brezillon 
60693db446aSBoris Brezillon 	if (mtd->writesize > 512)
60793db446aSBoris Brezillon 		bufs = 4;
60893db446aSBoris Brezillon 	else
60993db446aSBoris Brezillon 		bufs = 1;
61093db446aSBoris Brezillon 
61193db446aSBoris Brezillon 	for (i = 0; i < bufs; i++) {
61293db446aSBoris Brezillon 
61393db446aSBoris Brezillon 		/* NANDFC buffer 0 is used for page read/write */
61493db446aSBoris Brezillon 		writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
61593db446aSBoris Brezillon 
61693db446aSBoris Brezillon 		writew(ops, NFC_V1_V2_CONFIG2);
61793db446aSBoris Brezillon 
61893db446aSBoris Brezillon 		/* Wait for operation to complete */
61993db446aSBoris Brezillon 		wait_op_done(host, true);
62093db446aSBoris Brezillon 	}
62193db446aSBoris Brezillon }
62293db446aSBoris Brezillon 
62393db446aSBoris Brezillon static void send_read_id_v3(struct mxc_nand_host *host)
62493db446aSBoris Brezillon {
62593db446aSBoris Brezillon 	/* Read ID into main buffer */
62693db446aSBoris Brezillon 	writel(NFC_ID, NFC_V3_LAUNCH);
62793db446aSBoris Brezillon 
62893db446aSBoris Brezillon 	wait_op_done(host, true);
62993db446aSBoris Brezillon 
63093db446aSBoris Brezillon 	memcpy32_fromio(host->data_buf, host->main_area0, 16);
63193db446aSBoris Brezillon }
63293db446aSBoris Brezillon 
63393db446aSBoris Brezillon /* Request the NANDFC to perform a read of the NAND device ID. */
63493db446aSBoris Brezillon static void send_read_id_v1_v2(struct mxc_nand_host *host)
63593db446aSBoris Brezillon {
63693db446aSBoris Brezillon 	/* NANDFC buffer 0 is used for device ID output */
63793db446aSBoris Brezillon 	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
63893db446aSBoris Brezillon 
63993db446aSBoris Brezillon 	writew(NFC_ID, NFC_V1_V2_CONFIG2);
64093db446aSBoris Brezillon 
64193db446aSBoris Brezillon 	/* Wait for operation to complete */
64293db446aSBoris Brezillon 	wait_op_done(host, true);
64393db446aSBoris Brezillon 
64493db446aSBoris Brezillon 	memcpy32_fromio(host->data_buf, host->main_area0, 16);
64593db446aSBoris Brezillon }
64693db446aSBoris Brezillon 
64793db446aSBoris Brezillon static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
64893db446aSBoris Brezillon {
64993db446aSBoris Brezillon 	writew(NFC_STATUS, NFC_V3_LAUNCH);
65093db446aSBoris Brezillon 	wait_op_done(host, true);
65193db446aSBoris Brezillon 
65293db446aSBoris Brezillon 	return readl(NFC_V3_CONFIG1) >> 16;
65393db446aSBoris Brezillon }
65493db446aSBoris Brezillon 
65593db446aSBoris Brezillon /* This function requests the NANDFC to perform a read of the
65693db446aSBoris Brezillon  * NAND device status and returns the current status. */
65793db446aSBoris Brezillon static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
65893db446aSBoris Brezillon {
65993db446aSBoris Brezillon 	void __iomem *main_buf = host->main_area0;
66093db446aSBoris Brezillon 	uint32_t store;
66193db446aSBoris Brezillon 	uint16_t ret;
66293db446aSBoris Brezillon 
66393db446aSBoris Brezillon 	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
66493db446aSBoris Brezillon 
66593db446aSBoris Brezillon 	/*
66693db446aSBoris Brezillon 	 * The device status is stored in main_area0. To
66793db446aSBoris Brezillon 	 * prevent corruption of the buffer save the value
66893db446aSBoris Brezillon 	 * and restore it afterwards.
66993db446aSBoris Brezillon 	 */
67093db446aSBoris Brezillon 	store = readl(main_buf);
67193db446aSBoris Brezillon 
67293db446aSBoris Brezillon 	writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
67393db446aSBoris Brezillon 	wait_op_done(host, true);
67493db446aSBoris Brezillon 
67593db446aSBoris Brezillon 	ret = readw(main_buf);
67693db446aSBoris Brezillon 
67793db446aSBoris Brezillon 	writel(store, main_buf);
67893db446aSBoris Brezillon 
67993db446aSBoris Brezillon 	return ret;
68093db446aSBoris Brezillon }
68193db446aSBoris Brezillon 
68293db446aSBoris Brezillon static void mxc_nand_enable_hwecc_v1_v2(struct nand_chip *chip, bool enable)
68393db446aSBoris Brezillon {
68493db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
68593db446aSBoris Brezillon 	uint16_t config1;
68693db446aSBoris Brezillon 
68793db446aSBoris Brezillon 	if (chip->ecc.mode != NAND_ECC_HW)
68893db446aSBoris Brezillon 		return;
68993db446aSBoris Brezillon 
69093db446aSBoris Brezillon 	config1 = readw(NFC_V1_V2_CONFIG1);
69193db446aSBoris Brezillon 
69293db446aSBoris Brezillon 	if (enable)
69393db446aSBoris Brezillon 		config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
69493db446aSBoris Brezillon 	else
69593db446aSBoris Brezillon 		config1 &= ~NFC_V1_V2_CONFIG1_ECC_EN;
69693db446aSBoris Brezillon 
69793db446aSBoris Brezillon 	writew(config1, NFC_V1_V2_CONFIG1);
69893db446aSBoris Brezillon }
69993db446aSBoris Brezillon 
70093db446aSBoris Brezillon static void mxc_nand_enable_hwecc_v3(struct nand_chip *chip, bool enable)
70193db446aSBoris Brezillon {
70293db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
70393db446aSBoris Brezillon 	uint32_t config2;
70493db446aSBoris Brezillon 
70593db446aSBoris Brezillon 	if (chip->ecc.mode != NAND_ECC_HW)
70693db446aSBoris Brezillon 		return;
70793db446aSBoris Brezillon 
70893db446aSBoris Brezillon 	config2 = readl(NFC_V3_CONFIG2);
70993db446aSBoris Brezillon 
71093db446aSBoris Brezillon 	if (enable)
71193db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_ECC_EN;
71293db446aSBoris Brezillon 	else
71393db446aSBoris Brezillon 		config2 &= ~NFC_V3_CONFIG2_ECC_EN;
71493db446aSBoris Brezillon 
71593db446aSBoris Brezillon 	writel(config2, NFC_V3_CONFIG2);
71693db446aSBoris Brezillon }
71793db446aSBoris Brezillon 
71893db446aSBoris Brezillon /* This functions is used by upper layer to checks if device is ready */
71993db446aSBoris Brezillon static int mxc_nand_dev_ready(struct mtd_info *mtd)
72093db446aSBoris Brezillon {
72193db446aSBoris Brezillon 	/*
72293db446aSBoris Brezillon 	 * NFC handles R/B internally. Therefore, this function
72393db446aSBoris Brezillon 	 * always returns status as ready.
72493db446aSBoris Brezillon 	 */
72593db446aSBoris Brezillon 	return 1;
72693db446aSBoris Brezillon }
72793db446aSBoris Brezillon 
72893db446aSBoris Brezillon static int mxc_nand_read_page_v1(struct nand_chip *chip, void *buf, void *oob,
72993db446aSBoris Brezillon 				 bool ecc, int page)
73093db446aSBoris Brezillon {
73193db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
73293db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
73393db446aSBoris Brezillon 	unsigned int bitflips_corrected = 0;
73493db446aSBoris Brezillon 	int no_subpages;
73593db446aSBoris Brezillon 	int i;
73693db446aSBoris Brezillon 
73793db446aSBoris Brezillon 	host->devtype_data->enable_hwecc(chip, ecc);
73893db446aSBoris Brezillon 
73993db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_READ0, false);
74093db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, 0, page);
74193db446aSBoris Brezillon 
74293db446aSBoris Brezillon 	if (mtd->writesize > 512)
74393db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, NAND_CMD_READSTART, true);
74493db446aSBoris Brezillon 
74593db446aSBoris Brezillon 	no_subpages = mtd->writesize >> 9;
74693db446aSBoris Brezillon 
74793db446aSBoris Brezillon 	for (i = 0; i < no_subpages; i++) {
74893db446aSBoris Brezillon 		uint16_t ecc_stats;
74993db446aSBoris Brezillon 
75093db446aSBoris Brezillon 		/* NANDFC buffer 0 is used for page read/write */
75193db446aSBoris Brezillon 		writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
75293db446aSBoris Brezillon 
75393db446aSBoris Brezillon 		writew(NFC_OUTPUT, NFC_V1_V2_CONFIG2);
75493db446aSBoris Brezillon 
75593db446aSBoris Brezillon 		/* Wait for operation to complete */
75693db446aSBoris Brezillon 		wait_op_done(host, true);
75793db446aSBoris Brezillon 
75893db446aSBoris Brezillon 		ecc_stats = get_ecc_status_v1(host);
75993db446aSBoris Brezillon 
76093db446aSBoris Brezillon 		ecc_stats >>= 2;
76193db446aSBoris Brezillon 
76293db446aSBoris Brezillon 		if (buf && ecc) {
76393db446aSBoris Brezillon 			switch (ecc_stats & 0x3) {
76493db446aSBoris Brezillon 			case 0:
76593db446aSBoris Brezillon 			default:
76693db446aSBoris Brezillon 				break;
76793db446aSBoris Brezillon 			case 1:
76893db446aSBoris Brezillon 				mtd->ecc_stats.corrected++;
76993db446aSBoris Brezillon 				bitflips_corrected = 1;
77093db446aSBoris Brezillon 				break;
77193db446aSBoris Brezillon 			case 2:
77293db446aSBoris Brezillon 				mtd->ecc_stats.failed++;
77393db446aSBoris Brezillon 				break;
77493db446aSBoris Brezillon 			}
77593db446aSBoris Brezillon 		}
77693db446aSBoris Brezillon 	}
77793db446aSBoris Brezillon 
77893db446aSBoris Brezillon 	if (buf)
77993db446aSBoris Brezillon 		memcpy32_fromio(buf, host->main_area0, mtd->writesize);
78093db446aSBoris Brezillon 	if (oob)
78193db446aSBoris Brezillon 		copy_spare(mtd, true, oob);
78293db446aSBoris Brezillon 
78393db446aSBoris Brezillon 	return bitflips_corrected;
78493db446aSBoris Brezillon }
78593db446aSBoris Brezillon 
78693db446aSBoris Brezillon static int mxc_nand_read_page_v2_v3(struct nand_chip *chip, void *buf,
78793db446aSBoris Brezillon 				    void *oob, bool ecc, int page)
78893db446aSBoris Brezillon {
78993db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
79093db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
79193db446aSBoris Brezillon 	unsigned int max_bitflips = 0;
79293db446aSBoris Brezillon 	u32 ecc_stat, err;
79393db446aSBoris Brezillon 	int no_subpages;
79493db446aSBoris Brezillon 	u8 ecc_bit_mask, err_limit;
79593db446aSBoris Brezillon 
79693db446aSBoris Brezillon 	host->devtype_data->enable_hwecc(chip, ecc);
79793db446aSBoris Brezillon 
79893db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_READ0, false);
79993db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, 0, page);
80093db446aSBoris Brezillon 
80193db446aSBoris Brezillon 	if (mtd->writesize > 512)
80293db446aSBoris Brezillon 		host->devtype_data->send_cmd(host,
80393db446aSBoris Brezillon 				NAND_CMD_READSTART, true);
80493db446aSBoris Brezillon 
80593db446aSBoris Brezillon 	host->devtype_data->send_page(mtd, NFC_OUTPUT);
80693db446aSBoris Brezillon 
80793db446aSBoris Brezillon 	if (buf)
80893db446aSBoris Brezillon 		memcpy32_fromio(buf, host->main_area0, mtd->writesize);
80993db446aSBoris Brezillon 	if (oob)
81093db446aSBoris Brezillon 		copy_spare(mtd, true, oob);
81193db446aSBoris Brezillon 
81293db446aSBoris Brezillon 	ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
81393db446aSBoris Brezillon 	err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
81493db446aSBoris Brezillon 
81593db446aSBoris Brezillon 	no_subpages = mtd->writesize >> 9;
81693db446aSBoris Brezillon 
81793db446aSBoris Brezillon 	ecc_stat = host->devtype_data->get_ecc_status(host);
81893db446aSBoris Brezillon 
81993db446aSBoris Brezillon 	do {
82093db446aSBoris Brezillon 		err = ecc_stat & ecc_bit_mask;
82193db446aSBoris Brezillon 		if (err > err_limit) {
82293db446aSBoris Brezillon 			mtd->ecc_stats.failed++;
82393db446aSBoris Brezillon 		} else {
82493db446aSBoris Brezillon 			mtd->ecc_stats.corrected += err;
82593db446aSBoris Brezillon 			max_bitflips = max_t(unsigned int, max_bitflips, err);
82693db446aSBoris Brezillon 		}
82793db446aSBoris Brezillon 
82893db446aSBoris Brezillon 		ecc_stat >>= 4;
82993db446aSBoris Brezillon 	} while (--no_subpages);
83093db446aSBoris Brezillon 
83193db446aSBoris Brezillon 	return max_bitflips;
83293db446aSBoris Brezillon }
83393db446aSBoris Brezillon 
83493db446aSBoris Brezillon static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
83593db446aSBoris Brezillon 			      uint8_t *buf, int oob_required, int page)
83693db446aSBoris Brezillon {
83793db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
83893db446aSBoris Brezillon 	void *oob_buf;
83993db446aSBoris Brezillon 
84093db446aSBoris Brezillon 	if (oob_required)
84193db446aSBoris Brezillon 		oob_buf = chip->oob_poi;
84293db446aSBoris Brezillon 	else
84393db446aSBoris Brezillon 		oob_buf = NULL;
84493db446aSBoris Brezillon 
84593db446aSBoris Brezillon 	return host->devtype_data->read_page(chip, buf, oob_buf, 1, page);
84693db446aSBoris Brezillon }
84793db446aSBoris Brezillon 
84893db446aSBoris Brezillon static int mxc_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
84993db446aSBoris Brezillon 				  uint8_t *buf, int oob_required, int page)
85093db446aSBoris Brezillon {
85193db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
85293db446aSBoris Brezillon 	void *oob_buf;
85393db446aSBoris Brezillon 
85493db446aSBoris Brezillon 	if (oob_required)
85593db446aSBoris Brezillon 		oob_buf = chip->oob_poi;
85693db446aSBoris Brezillon 	else
85793db446aSBoris Brezillon 		oob_buf = NULL;
85893db446aSBoris Brezillon 
85993db446aSBoris Brezillon 	return host->devtype_data->read_page(chip, buf, oob_buf, 0, page);
86093db446aSBoris Brezillon }
86193db446aSBoris Brezillon 
86293db446aSBoris Brezillon static int mxc_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
86393db446aSBoris Brezillon 			     int page)
86493db446aSBoris Brezillon {
86593db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
86693db446aSBoris Brezillon 
86793db446aSBoris Brezillon 	return host->devtype_data->read_page(chip, NULL, chip->oob_poi, 0,
86893db446aSBoris Brezillon 					     page);
86993db446aSBoris Brezillon }
87093db446aSBoris Brezillon 
87193db446aSBoris Brezillon static int mxc_nand_write_page(struct nand_chip *chip, const uint8_t *buf,
87293db446aSBoris Brezillon 			       bool ecc, int page)
87393db446aSBoris Brezillon {
87493db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
87593db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
87693db446aSBoris Brezillon 
87793db446aSBoris Brezillon 	host->devtype_data->enable_hwecc(chip, ecc);
87893db446aSBoris Brezillon 
87993db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_SEQIN, false);
88093db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, 0, page);
88193db446aSBoris Brezillon 
88293db446aSBoris Brezillon 	memcpy32_toio(host->main_area0, buf, mtd->writesize);
88393db446aSBoris Brezillon 	copy_spare(mtd, false, chip->oob_poi);
88493db446aSBoris Brezillon 
88593db446aSBoris Brezillon 	host->devtype_data->send_page(mtd, NFC_INPUT);
88693db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_PAGEPROG, true);
88793db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, 0, page);
88893db446aSBoris Brezillon 
88993db446aSBoris Brezillon 	return 0;
89093db446aSBoris Brezillon }
89193db446aSBoris Brezillon 
89293db446aSBoris Brezillon static int mxc_nand_write_page_ecc(struct mtd_info *mtd, struct nand_chip *chip,
89393db446aSBoris Brezillon 				   const uint8_t *buf, int oob_required,
89493db446aSBoris Brezillon 				   int page)
89593db446aSBoris Brezillon {
89693db446aSBoris Brezillon 	return mxc_nand_write_page(chip, buf, true, page);
89793db446aSBoris Brezillon }
89893db446aSBoris Brezillon 
89993db446aSBoris Brezillon static int mxc_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
90093db446aSBoris Brezillon 				   const uint8_t *buf, int oob_required, int page)
90193db446aSBoris Brezillon {
90293db446aSBoris Brezillon 	return mxc_nand_write_page(chip, buf, false, page);
90393db446aSBoris Brezillon }
90493db446aSBoris Brezillon 
90593db446aSBoris Brezillon static int mxc_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
90693db446aSBoris Brezillon 			      int page)
90793db446aSBoris Brezillon {
90893db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
90993db446aSBoris Brezillon 
91093db446aSBoris Brezillon 	memset(host->data_buf, 0xff, mtd->writesize);
91193db446aSBoris Brezillon 
91293db446aSBoris Brezillon 	return mxc_nand_write_page(chip, host->data_buf, false, page);
91393db446aSBoris Brezillon }
91493db446aSBoris Brezillon 
91593db446aSBoris Brezillon static u_char mxc_nand_read_byte(struct mtd_info *mtd)
91693db446aSBoris Brezillon {
91793db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
91893db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
91993db446aSBoris Brezillon 	uint8_t ret;
92093db446aSBoris Brezillon 
92193db446aSBoris Brezillon 	/* Check for status request */
92293db446aSBoris Brezillon 	if (host->status_request)
92393db446aSBoris Brezillon 		return host->devtype_data->get_dev_status(host) & 0xFF;
92493db446aSBoris Brezillon 
92593db446aSBoris Brezillon 	if (nand_chip->options & NAND_BUSWIDTH_16) {
92693db446aSBoris Brezillon 		/* only take the lower byte of each word */
92793db446aSBoris Brezillon 		ret = *(uint16_t *)(host->data_buf + host->buf_start);
92893db446aSBoris Brezillon 
92993db446aSBoris Brezillon 		host->buf_start += 2;
93093db446aSBoris Brezillon 	} else {
93193db446aSBoris Brezillon 		ret = *(uint8_t *)(host->data_buf + host->buf_start);
93293db446aSBoris Brezillon 		host->buf_start++;
93393db446aSBoris Brezillon 	}
93493db446aSBoris Brezillon 
93593db446aSBoris Brezillon 	dev_dbg(host->dev, "%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start);
93693db446aSBoris Brezillon 	return ret;
93793db446aSBoris Brezillon }
93893db446aSBoris Brezillon 
93993db446aSBoris Brezillon static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
94093db446aSBoris Brezillon {
94193db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
94293db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
94393db446aSBoris Brezillon 	uint16_t ret;
94493db446aSBoris Brezillon 
94593db446aSBoris Brezillon 	ret = *(uint16_t *)(host->data_buf + host->buf_start);
94693db446aSBoris Brezillon 	host->buf_start += 2;
94793db446aSBoris Brezillon 
94893db446aSBoris Brezillon 	return ret;
94993db446aSBoris Brezillon }
95093db446aSBoris Brezillon 
95193db446aSBoris Brezillon /* Write data of length len to buffer buf. The data to be
95293db446aSBoris Brezillon  * written on NAND Flash is first copied to RAMbuffer. After the Data Input
95393db446aSBoris Brezillon  * Operation by the NFC, the data is written to NAND Flash */
95493db446aSBoris Brezillon static void mxc_nand_write_buf(struct mtd_info *mtd,
95593db446aSBoris Brezillon 				const u_char *buf, int len)
95693db446aSBoris Brezillon {
95793db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
95893db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
95993db446aSBoris Brezillon 	u16 col = host->buf_start;
96093db446aSBoris Brezillon 	int n = mtd->oobsize + mtd->writesize - col;
96193db446aSBoris Brezillon 
96293db446aSBoris Brezillon 	n = min(n, len);
96393db446aSBoris Brezillon 
96493db446aSBoris Brezillon 	memcpy(host->data_buf + col, buf, n);
96593db446aSBoris Brezillon 
96693db446aSBoris Brezillon 	host->buf_start += n;
96793db446aSBoris Brezillon }
96893db446aSBoris Brezillon 
96993db446aSBoris Brezillon /* Read the data buffer from the NAND Flash. To read the data from NAND
97093db446aSBoris Brezillon  * Flash first the data output cycle is initiated by the NFC, which copies
97193db446aSBoris Brezillon  * the data to RAMbuffer. This data of length len is then copied to buffer buf.
97293db446aSBoris Brezillon  */
97393db446aSBoris Brezillon static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
97493db446aSBoris Brezillon {
97593db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
97693db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
97793db446aSBoris Brezillon 	u16 col = host->buf_start;
97893db446aSBoris Brezillon 	int n = mtd->oobsize + mtd->writesize - col;
97993db446aSBoris Brezillon 
98093db446aSBoris Brezillon 	n = min(n, len);
98193db446aSBoris Brezillon 
98293db446aSBoris Brezillon 	memcpy(buf, host->data_buf + col, n);
98393db446aSBoris Brezillon 
98493db446aSBoris Brezillon 	host->buf_start += n;
98593db446aSBoris Brezillon }
98693db446aSBoris Brezillon 
98793db446aSBoris Brezillon /* This function is used by upper layer for select and
98893db446aSBoris Brezillon  * deselect of the NAND chip */
98993db446aSBoris Brezillon static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
99093db446aSBoris Brezillon {
99193db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
99293db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
99393db446aSBoris Brezillon 
99493db446aSBoris Brezillon 	if (chip == -1) {
99593db446aSBoris Brezillon 		/* Disable the NFC clock */
99693db446aSBoris Brezillon 		if (host->clk_act) {
99793db446aSBoris Brezillon 			clk_disable_unprepare(host->clk);
99893db446aSBoris Brezillon 			host->clk_act = 0;
99993db446aSBoris Brezillon 		}
100093db446aSBoris Brezillon 		return;
100193db446aSBoris Brezillon 	}
100293db446aSBoris Brezillon 
100393db446aSBoris Brezillon 	if (!host->clk_act) {
100493db446aSBoris Brezillon 		/* Enable the NFC clock */
100593db446aSBoris Brezillon 		clk_prepare_enable(host->clk);
100693db446aSBoris Brezillon 		host->clk_act = 1;
100793db446aSBoris Brezillon 	}
100893db446aSBoris Brezillon }
100993db446aSBoris Brezillon 
101093db446aSBoris Brezillon static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
101193db446aSBoris Brezillon {
101293db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
101393db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
101493db446aSBoris Brezillon 
101593db446aSBoris Brezillon 	if (chip == -1) {
101693db446aSBoris Brezillon 		/* Disable the NFC clock */
101793db446aSBoris Brezillon 		if (host->clk_act) {
101893db446aSBoris Brezillon 			clk_disable_unprepare(host->clk);
101993db446aSBoris Brezillon 			host->clk_act = 0;
102093db446aSBoris Brezillon 		}
102193db446aSBoris Brezillon 		return;
102293db446aSBoris Brezillon 	}
102393db446aSBoris Brezillon 
102493db446aSBoris Brezillon 	if (!host->clk_act) {
102593db446aSBoris Brezillon 		/* Enable the NFC clock */
102693db446aSBoris Brezillon 		clk_prepare_enable(host->clk);
102793db446aSBoris Brezillon 		host->clk_act = 1;
102893db446aSBoris Brezillon 	}
102993db446aSBoris Brezillon 
103093db446aSBoris Brezillon 	host->active_cs = chip;
103193db446aSBoris Brezillon 	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
103293db446aSBoris Brezillon }
103393db446aSBoris Brezillon 
103493db446aSBoris Brezillon #define MXC_V1_ECCBYTES		5
103593db446aSBoris Brezillon 
103693db446aSBoris Brezillon static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
103793db446aSBoris Brezillon 				struct mtd_oob_region *oobregion)
103893db446aSBoris Brezillon {
103993db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
104093db446aSBoris Brezillon 
104193db446aSBoris Brezillon 	if (section >= nand_chip->ecc.steps)
104293db446aSBoris Brezillon 		return -ERANGE;
104393db446aSBoris Brezillon 
104493db446aSBoris Brezillon 	oobregion->offset = (section * 16) + 6;
104593db446aSBoris Brezillon 	oobregion->length = MXC_V1_ECCBYTES;
104693db446aSBoris Brezillon 
104793db446aSBoris Brezillon 	return 0;
104893db446aSBoris Brezillon }
104993db446aSBoris Brezillon 
105093db446aSBoris Brezillon static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
105193db446aSBoris Brezillon 				 struct mtd_oob_region *oobregion)
105293db446aSBoris Brezillon {
105393db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
105493db446aSBoris Brezillon 
105593db446aSBoris Brezillon 	if (section > nand_chip->ecc.steps)
105693db446aSBoris Brezillon 		return -ERANGE;
105793db446aSBoris Brezillon 
105893db446aSBoris Brezillon 	if (!section) {
105993db446aSBoris Brezillon 		if (mtd->writesize <= 512) {
106093db446aSBoris Brezillon 			oobregion->offset = 0;
106193db446aSBoris Brezillon 			oobregion->length = 5;
106293db446aSBoris Brezillon 		} else {
106393db446aSBoris Brezillon 			oobregion->offset = 2;
106493db446aSBoris Brezillon 			oobregion->length = 4;
106593db446aSBoris Brezillon 		}
106693db446aSBoris Brezillon 	} else {
106793db446aSBoris Brezillon 		oobregion->offset = ((section - 1) * 16) + MXC_V1_ECCBYTES + 6;
106893db446aSBoris Brezillon 		if (section < nand_chip->ecc.steps)
106993db446aSBoris Brezillon 			oobregion->length = (section * 16) + 6 -
107093db446aSBoris Brezillon 					    oobregion->offset;
107193db446aSBoris Brezillon 		else
107293db446aSBoris Brezillon 			oobregion->length = mtd->oobsize - oobregion->offset;
107393db446aSBoris Brezillon 	}
107493db446aSBoris Brezillon 
107593db446aSBoris Brezillon 	return 0;
107693db446aSBoris Brezillon }
107793db446aSBoris Brezillon 
107893db446aSBoris Brezillon static const struct mtd_ooblayout_ops mxc_v1_ooblayout_ops = {
107993db446aSBoris Brezillon 	.ecc = mxc_v1_ooblayout_ecc,
108093db446aSBoris Brezillon 	.free = mxc_v1_ooblayout_free,
108193db446aSBoris Brezillon };
108293db446aSBoris Brezillon 
108393db446aSBoris Brezillon static int mxc_v2_ooblayout_ecc(struct mtd_info *mtd, int section,
108493db446aSBoris Brezillon 				struct mtd_oob_region *oobregion)
108593db446aSBoris Brezillon {
108693db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
108793db446aSBoris Brezillon 	int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26;
108893db446aSBoris Brezillon 
108993db446aSBoris Brezillon 	if (section >= nand_chip->ecc.steps)
109093db446aSBoris Brezillon 		return -ERANGE;
109193db446aSBoris Brezillon 
109293db446aSBoris Brezillon 	oobregion->offset = (section * stepsize) + 7;
109393db446aSBoris Brezillon 	oobregion->length = nand_chip->ecc.bytes;
109493db446aSBoris Brezillon 
109593db446aSBoris Brezillon 	return 0;
109693db446aSBoris Brezillon }
109793db446aSBoris Brezillon 
109893db446aSBoris Brezillon static int mxc_v2_ooblayout_free(struct mtd_info *mtd, int section,
109993db446aSBoris Brezillon 				 struct mtd_oob_region *oobregion)
110093db446aSBoris Brezillon {
110193db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
110293db446aSBoris Brezillon 	int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26;
110393db446aSBoris Brezillon 
110493db446aSBoris Brezillon 	if (section >= nand_chip->ecc.steps)
110593db446aSBoris Brezillon 		return -ERANGE;
110693db446aSBoris Brezillon 
110793db446aSBoris Brezillon 	if (!section) {
110893db446aSBoris Brezillon 		if (mtd->writesize <= 512) {
110993db446aSBoris Brezillon 			oobregion->offset = 0;
111093db446aSBoris Brezillon 			oobregion->length = 5;
111193db446aSBoris Brezillon 		} else {
111293db446aSBoris Brezillon 			oobregion->offset = 2;
111393db446aSBoris Brezillon 			oobregion->length = 4;
111493db446aSBoris Brezillon 		}
111593db446aSBoris Brezillon 	} else {
111693db446aSBoris Brezillon 		oobregion->offset = section * stepsize;
111793db446aSBoris Brezillon 		oobregion->length = 7;
111893db446aSBoris Brezillon 	}
111993db446aSBoris Brezillon 
112093db446aSBoris Brezillon 	return 0;
112193db446aSBoris Brezillon }
112293db446aSBoris Brezillon 
112393db446aSBoris Brezillon static const struct mtd_ooblayout_ops mxc_v2_ooblayout_ops = {
112493db446aSBoris Brezillon 	.ecc = mxc_v2_ooblayout_ecc,
112593db446aSBoris Brezillon 	.free = mxc_v2_ooblayout_free,
112693db446aSBoris Brezillon };
112793db446aSBoris Brezillon 
112893db446aSBoris Brezillon /*
112993db446aSBoris Brezillon  * v2 and v3 type controllers can do 4bit or 8bit ecc depending
113093db446aSBoris Brezillon  * on how much oob the nand chip has. For 8bit ecc we need at least
113193db446aSBoris Brezillon  * 26 bytes of oob data per 512 byte block.
113293db446aSBoris Brezillon  */
113393db446aSBoris Brezillon static int get_eccsize(struct mtd_info *mtd)
113493db446aSBoris Brezillon {
113593db446aSBoris Brezillon 	int oobbytes_per_512 = 0;
113693db446aSBoris Brezillon 
113793db446aSBoris Brezillon 	oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
113893db446aSBoris Brezillon 
113993db446aSBoris Brezillon 	if (oobbytes_per_512 < 26)
114093db446aSBoris Brezillon 		return 4;
114193db446aSBoris Brezillon 	else
114293db446aSBoris Brezillon 		return 8;
114393db446aSBoris Brezillon }
114493db446aSBoris Brezillon 
114593db446aSBoris Brezillon static void preset_v1(struct mtd_info *mtd)
114693db446aSBoris Brezillon {
114793db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
114893db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
114993db446aSBoris Brezillon 	uint16_t config1 = 0;
115093db446aSBoris Brezillon 
115193db446aSBoris Brezillon 	if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize)
115293db446aSBoris Brezillon 		config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
115393db446aSBoris Brezillon 
115493db446aSBoris Brezillon 	if (!host->devtype_data->irqpending_quirk)
115593db446aSBoris Brezillon 		config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
115693db446aSBoris Brezillon 
115793db446aSBoris Brezillon 	host->eccsize = 1;
115893db446aSBoris Brezillon 
115993db446aSBoris Brezillon 	writew(config1, NFC_V1_V2_CONFIG1);
116093db446aSBoris Brezillon 	/* preset operation */
116193db446aSBoris Brezillon 
116293db446aSBoris Brezillon 	/* Unlock the internal RAM Buffer */
116393db446aSBoris Brezillon 	writew(0x2, NFC_V1_V2_CONFIG);
116493db446aSBoris Brezillon 
116593db446aSBoris Brezillon 	/* Blocks to be unlocked */
116693db446aSBoris Brezillon 	writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
116793db446aSBoris Brezillon 	writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
116893db446aSBoris Brezillon 
116993db446aSBoris Brezillon 	/* Unlock Block Command for given address range */
117093db446aSBoris Brezillon 	writew(0x4, NFC_V1_V2_WRPROT);
117193db446aSBoris Brezillon }
117293db446aSBoris Brezillon 
117393db446aSBoris Brezillon static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd, int csline,
117493db446aSBoris Brezillon 					const struct nand_data_interface *conf)
117593db446aSBoris Brezillon {
117693db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
117793db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
117893db446aSBoris Brezillon 	int tRC_min_ns, tRC_ps, ret;
117993db446aSBoris Brezillon 	unsigned long rate, rate_round;
118093db446aSBoris Brezillon 	const struct nand_sdr_timings *timings;
118193db446aSBoris Brezillon 	u16 config1;
118293db446aSBoris Brezillon 
118393db446aSBoris Brezillon 	timings = nand_get_sdr_timings(conf);
118493db446aSBoris Brezillon 	if (IS_ERR(timings))
118593db446aSBoris Brezillon 		return -ENOTSUPP;
118693db446aSBoris Brezillon 
118793db446aSBoris Brezillon 	config1 = readw(NFC_V1_V2_CONFIG1);
118893db446aSBoris Brezillon 
118993db446aSBoris Brezillon 	tRC_min_ns = timings->tRC_min / 1000;
119093db446aSBoris Brezillon 	rate = 1000000000 / tRC_min_ns;
119193db446aSBoris Brezillon 
119293db446aSBoris Brezillon 	/*
119393db446aSBoris Brezillon 	 * For tRC < 30ns we have to use EDO mode. In this case the controller
119493db446aSBoris Brezillon 	 * does one access per clock cycle. Otherwise the controller does one
119593db446aSBoris Brezillon 	 * access in two clock cycles, thus we have to double the rate to the
119693db446aSBoris Brezillon 	 * controller.
119793db446aSBoris Brezillon 	 */
119893db446aSBoris Brezillon 	if (tRC_min_ns < 30) {
119993db446aSBoris Brezillon 		rate_round = clk_round_rate(host->clk, rate);
120093db446aSBoris Brezillon 		config1 |= NFC_V2_CONFIG1_ONE_CYCLE;
120193db446aSBoris Brezillon 		tRC_ps = 1000000000 / (rate_round / 1000);
120293db446aSBoris Brezillon 	} else {
120393db446aSBoris Brezillon 		rate *= 2;
120493db446aSBoris Brezillon 		rate_round = clk_round_rate(host->clk, rate);
120593db446aSBoris Brezillon 		config1 &= ~NFC_V2_CONFIG1_ONE_CYCLE;
120693db446aSBoris Brezillon 		tRC_ps = 1000000000 / (rate_round / 1000 / 2);
120793db446aSBoris Brezillon 	}
120893db446aSBoris Brezillon 
120993db446aSBoris Brezillon 	/*
121093db446aSBoris Brezillon 	 * The timing values compared against are from the i.MX25 Automotive
121193db446aSBoris Brezillon 	 * datasheet, Table 50. NFC Timing Parameters
121293db446aSBoris Brezillon 	 */
121393db446aSBoris Brezillon 	if (timings->tCLS_min > tRC_ps - 1000 ||
121493db446aSBoris Brezillon 	    timings->tCLH_min > tRC_ps - 2000 ||
121593db446aSBoris Brezillon 	    timings->tCS_min > tRC_ps - 1000 ||
121693db446aSBoris Brezillon 	    timings->tCH_min > tRC_ps - 2000 ||
121793db446aSBoris Brezillon 	    timings->tWP_min > tRC_ps - 1500 ||
121893db446aSBoris Brezillon 	    timings->tALS_min > tRC_ps ||
121993db446aSBoris Brezillon 	    timings->tALH_min > tRC_ps - 3000 ||
122093db446aSBoris Brezillon 	    timings->tDS_min > tRC_ps ||
122193db446aSBoris Brezillon 	    timings->tDH_min > tRC_ps - 5000 ||
122293db446aSBoris Brezillon 	    timings->tWC_min > 2 * tRC_ps ||
122393db446aSBoris Brezillon 	    timings->tWH_min > tRC_ps - 2500 ||
122493db446aSBoris Brezillon 	    timings->tRR_min > 6 * tRC_ps ||
122593db446aSBoris Brezillon 	    timings->tRP_min > 3 * tRC_ps / 2 ||
122693db446aSBoris Brezillon 	    timings->tRC_min > 2 * tRC_ps ||
122793db446aSBoris Brezillon 	    timings->tREH_min > (tRC_ps / 2) - 2500) {
122893db446aSBoris Brezillon 		dev_dbg(host->dev, "Timing out of bounds\n");
122993db446aSBoris Brezillon 		return -EINVAL;
123093db446aSBoris Brezillon 	}
123193db446aSBoris Brezillon 
123293db446aSBoris Brezillon 	if (csline == NAND_DATA_IFACE_CHECK_ONLY)
123393db446aSBoris Brezillon 		return 0;
123493db446aSBoris Brezillon 
123593db446aSBoris Brezillon 	ret = clk_set_rate(host->clk, rate);
123693db446aSBoris Brezillon 	if (ret)
123793db446aSBoris Brezillon 		return ret;
123893db446aSBoris Brezillon 
123993db446aSBoris Brezillon 	writew(config1, NFC_V1_V2_CONFIG1);
124093db446aSBoris Brezillon 
124193db446aSBoris Brezillon 	dev_dbg(host->dev, "Setting rate to %ldHz, %s mode\n", rate_round,
124293db446aSBoris Brezillon 		config1 & NFC_V2_CONFIG1_ONE_CYCLE ? "One cycle (EDO)" :
124393db446aSBoris Brezillon 		"normal");
124493db446aSBoris Brezillon 
124593db446aSBoris Brezillon 	return 0;
124693db446aSBoris Brezillon }
124793db446aSBoris Brezillon 
124893db446aSBoris Brezillon static void preset_v2(struct mtd_info *mtd)
124993db446aSBoris Brezillon {
125093db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
125193db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
125293db446aSBoris Brezillon 	uint16_t config1 = 0;
125393db446aSBoris Brezillon 
125493db446aSBoris Brezillon 	config1 |= NFC_V2_CONFIG1_FP_INT;
125593db446aSBoris Brezillon 
125693db446aSBoris Brezillon 	if (!host->devtype_data->irqpending_quirk)
125793db446aSBoris Brezillon 		config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
125893db446aSBoris Brezillon 
125993db446aSBoris Brezillon 	if (mtd->writesize) {
126093db446aSBoris Brezillon 		uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
126193db446aSBoris Brezillon 
126293db446aSBoris Brezillon 		if (nand_chip->ecc.mode == NAND_ECC_HW)
126393db446aSBoris Brezillon 			config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
126493db446aSBoris Brezillon 
126593db446aSBoris Brezillon 		host->eccsize = get_eccsize(mtd);
126693db446aSBoris Brezillon 		if (host->eccsize == 4)
126793db446aSBoris Brezillon 			config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
126893db446aSBoris Brezillon 
126993db446aSBoris Brezillon 		config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
127093db446aSBoris Brezillon 	} else {
127193db446aSBoris Brezillon 		host->eccsize = 1;
127293db446aSBoris Brezillon 	}
127393db446aSBoris Brezillon 
127493db446aSBoris Brezillon 	writew(config1, NFC_V1_V2_CONFIG1);
127593db446aSBoris Brezillon 	/* preset operation */
127693db446aSBoris Brezillon 
1277*3f77f244SMartin Kaiser 	/* spare area size in 16-bit half-words */
1278*3f77f244SMartin Kaiser 	writew(mtd->oobsize / 2, NFC_V21_RSLTSPARE_AREA);
1279*3f77f244SMartin Kaiser 
128093db446aSBoris Brezillon 	/* Unlock the internal RAM Buffer */
128193db446aSBoris Brezillon 	writew(0x2, NFC_V1_V2_CONFIG);
128293db446aSBoris Brezillon 
128393db446aSBoris Brezillon 	/* Blocks to be unlocked */
128493db446aSBoris Brezillon 	writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
128593db446aSBoris Brezillon 	writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
128693db446aSBoris Brezillon 	writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
128793db446aSBoris Brezillon 	writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
128893db446aSBoris Brezillon 	writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
128993db446aSBoris Brezillon 	writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
129093db446aSBoris Brezillon 	writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
129193db446aSBoris Brezillon 	writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
129293db446aSBoris Brezillon 
129393db446aSBoris Brezillon 	/* Unlock Block Command for given address range */
129493db446aSBoris Brezillon 	writew(0x4, NFC_V1_V2_WRPROT);
129593db446aSBoris Brezillon }
129693db446aSBoris Brezillon 
129793db446aSBoris Brezillon static void preset_v3(struct mtd_info *mtd)
129893db446aSBoris Brezillon {
129993db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
130093db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
130193db446aSBoris Brezillon 	uint32_t config2, config3;
130293db446aSBoris Brezillon 	int i, addr_phases;
130393db446aSBoris Brezillon 
130493db446aSBoris Brezillon 	writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
130593db446aSBoris Brezillon 	writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
130693db446aSBoris Brezillon 
130793db446aSBoris Brezillon 	/* Unlock the internal RAM Buffer */
130893db446aSBoris Brezillon 	writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
130993db446aSBoris Brezillon 			NFC_V3_WRPROT);
131093db446aSBoris Brezillon 
131193db446aSBoris Brezillon 	/* Blocks to be unlocked */
131293db446aSBoris Brezillon 	for (i = 0; i < NAND_MAX_CHIPS; i++)
131393db446aSBoris Brezillon 		writel(0xffff << 16, NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
131493db446aSBoris Brezillon 
131593db446aSBoris Brezillon 	writel(0, NFC_V3_IPC);
131693db446aSBoris Brezillon 
131793db446aSBoris Brezillon 	config2 = NFC_V3_CONFIG2_ONE_CYCLE |
131893db446aSBoris Brezillon 		NFC_V3_CONFIG2_2CMD_PHASES |
131993db446aSBoris Brezillon 		NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
132093db446aSBoris Brezillon 		NFC_V3_CONFIG2_ST_CMD(0x70) |
132193db446aSBoris Brezillon 		NFC_V3_CONFIG2_INT_MSK |
132293db446aSBoris Brezillon 		NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
132393db446aSBoris Brezillon 
132493db446aSBoris Brezillon 	addr_phases = fls(chip->pagemask) >> 3;
132593db446aSBoris Brezillon 
132693db446aSBoris Brezillon 	if (mtd->writesize == 2048) {
132793db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_PS_2048;
132893db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
132993db446aSBoris Brezillon 	} else if (mtd->writesize == 4096) {
133093db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_PS_4096;
133193db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
133293db446aSBoris Brezillon 	} else {
133393db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_PS_512;
133493db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
133593db446aSBoris Brezillon 	}
133693db446aSBoris Brezillon 
133793db446aSBoris Brezillon 	if (mtd->writesize) {
133893db446aSBoris Brezillon 		if (chip->ecc.mode == NAND_ECC_HW)
133993db446aSBoris Brezillon 			config2 |= NFC_V3_CONFIG2_ECC_EN;
134093db446aSBoris Brezillon 
134193db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_PPB(
134293db446aSBoris Brezillon 				ffs(mtd->erasesize / mtd->writesize) - 6,
134393db446aSBoris Brezillon 				host->devtype_data->ppb_shift);
134493db446aSBoris Brezillon 		host->eccsize = get_eccsize(mtd);
134593db446aSBoris Brezillon 		if (host->eccsize == 8)
134693db446aSBoris Brezillon 			config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
134793db446aSBoris Brezillon 	}
134893db446aSBoris Brezillon 
134993db446aSBoris Brezillon 	writel(config2, NFC_V3_CONFIG2);
135093db446aSBoris Brezillon 
135193db446aSBoris Brezillon 	config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
135293db446aSBoris Brezillon 			NFC_V3_CONFIG3_NO_SDMA |
135393db446aSBoris Brezillon 			NFC_V3_CONFIG3_RBB_MODE |
135493db446aSBoris Brezillon 			NFC_V3_CONFIG3_SBB(6) | /* Reset default */
135593db446aSBoris Brezillon 			NFC_V3_CONFIG3_ADD_OP(0);
135693db446aSBoris Brezillon 
135793db446aSBoris Brezillon 	if (!(chip->options & NAND_BUSWIDTH_16))
135893db446aSBoris Brezillon 		config3 |= NFC_V3_CONFIG3_FW8;
135993db446aSBoris Brezillon 
136093db446aSBoris Brezillon 	writel(config3, NFC_V3_CONFIG3);
136193db446aSBoris Brezillon 
136293db446aSBoris Brezillon 	writel(0, NFC_V3_DELAY_LINE);
136393db446aSBoris Brezillon }
136493db446aSBoris Brezillon 
136593db446aSBoris Brezillon /* Used by the upper layer to write command to NAND Flash for
136693db446aSBoris Brezillon  * different operations to be carried out on NAND Flash */
136793db446aSBoris Brezillon static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
136893db446aSBoris Brezillon 				int column, int page_addr)
136993db446aSBoris Brezillon {
137093db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
137193db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
137293db446aSBoris Brezillon 
137393db446aSBoris Brezillon 	dev_dbg(host->dev, "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
137493db446aSBoris Brezillon 	      command, column, page_addr);
137593db446aSBoris Brezillon 
137693db446aSBoris Brezillon 	/* Reset command state information */
137793db446aSBoris Brezillon 	host->status_request = false;
137893db446aSBoris Brezillon 
137993db446aSBoris Brezillon 	/* Command pre-processing step */
138093db446aSBoris Brezillon 	switch (command) {
138193db446aSBoris Brezillon 	case NAND_CMD_RESET:
138293db446aSBoris Brezillon 		host->devtype_data->preset(mtd);
138393db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, false);
138493db446aSBoris Brezillon 		break;
138593db446aSBoris Brezillon 
138693db446aSBoris Brezillon 	case NAND_CMD_STATUS:
138793db446aSBoris Brezillon 		host->buf_start = 0;
138893db446aSBoris Brezillon 		host->status_request = true;
138993db446aSBoris Brezillon 
139093db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, true);
139193db446aSBoris Brezillon 		WARN_ONCE(column != -1 || page_addr != -1,
139293db446aSBoris Brezillon 			  "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
139393db446aSBoris Brezillon 			  command, column, page_addr);
139493db446aSBoris Brezillon 		mxc_do_addr_cycle(mtd, column, page_addr);
139593db446aSBoris Brezillon 		break;
139693db446aSBoris Brezillon 
139793db446aSBoris Brezillon 	case NAND_CMD_READID:
139893db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, true);
139993db446aSBoris Brezillon 		mxc_do_addr_cycle(mtd, column, page_addr);
140093db446aSBoris Brezillon 		host->devtype_data->send_read_id(host);
140193db446aSBoris Brezillon 		host->buf_start = 0;
140293db446aSBoris Brezillon 		break;
140393db446aSBoris Brezillon 
140493db446aSBoris Brezillon 	case NAND_CMD_ERASE1:
140593db446aSBoris Brezillon 	case NAND_CMD_ERASE2:
140693db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, false);
140793db446aSBoris Brezillon 		WARN_ONCE(column != -1,
140893db446aSBoris Brezillon 			  "Unexpected column value (cmd=%u, col=%d)\n",
140993db446aSBoris Brezillon 			  command, column);
141093db446aSBoris Brezillon 		mxc_do_addr_cycle(mtd, column, page_addr);
141193db446aSBoris Brezillon 
141293db446aSBoris Brezillon 		break;
141393db446aSBoris Brezillon 	case NAND_CMD_PARAM:
141493db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, false);
141593db446aSBoris Brezillon 		mxc_do_addr_cycle(mtd, column, page_addr);
141693db446aSBoris Brezillon 		host->devtype_data->send_page(mtd, NFC_OUTPUT);
141793db446aSBoris Brezillon 		memcpy32_fromio(host->data_buf, host->main_area0, 512);
141893db446aSBoris Brezillon 		host->buf_start = 0;
141993db446aSBoris Brezillon 		break;
142093db446aSBoris Brezillon 	default:
142193db446aSBoris Brezillon 		WARN_ONCE(1, "Unimplemented command (cmd=%u)\n",
142293db446aSBoris Brezillon 			  command);
142393db446aSBoris Brezillon 		break;
142493db446aSBoris Brezillon 	}
142593db446aSBoris Brezillon }
142693db446aSBoris Brezillon 
1427b958758eSMiquel Raynal static int mxc_nand_set_features(struct mtd_info *mtd, struct nand_chip *chip,
1428b958758eSMiquel Raynal 				 int addr, u8 *subfeature_param)
142993db446aSBoris Brezillon {
143093db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
143193db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
143293db446aSBoris Brezillon 	int i;
143393db446aSBoris Brezillon 
143493db446aSBoris Brezillon 	host->buf_start = 0;
143593db446aSBoris Brezillon 
143693db446aSBoris Brezillon 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
143793db446aSBoris Brezillon 		chip->write_byte(mtd, subfeature_param[i]);
143893db446aSBoris Brezillon 
143993db446aSBoris Brezillon 	memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
144093db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_SET_FEATURES, false);
144193db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, addr, -1);
144293db446aSBoris Brezillon 	host->devtype_data->send_page(mtd, NFC_INPUT);
144393db446aSBoris Brezillon 
144493db446aSBoris Brezillon 	return 0;
144593db446aSBoris Brezillon }
144693db446aSBoris Brezillon 
1447b958758eSMiquel Raynal static int mxc_nand_get_features(struct mtd_info *mtd, struct nand_chip *chip,
1448b958758eSMiquel Raynal 				 int addr, u8 *subfeature_param)
144993db446aSBoris Brezillon {
145093db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
145193db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
145293db446aSBoris Brezillon 	int i;
145393db446aSBoris Brezillon 
145493db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_GET_FEATURES, false);
145593db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, addr, -1);
145693db446aSBoris Brezillon 	host->devtype_data->send_page(mtd, NFC_OUTPUT);
145793db446aSBoris Brezillon 	memcpy32_fromio(host->data_buf, host->main_area0, 512);
145893db446aSBoris Brezillon 	host->buf_start = 0;
145993db446aSBoris Brezillon 
146093db446aSBoris Brezillon 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
146193db446aSBoris Brezillon 		*subfeature_param++ = chip->read_byte(mtd);
146293db446aSBoris Brezillon 
146393db446aSBoris Brezillon 	return 0;
146493db446aSBoris Brezillon }
146593db446aSBoris Brezillon 
146693db446aSBoris Brezillon /*
146793db446aSBoris Brezillon  * The generic flash bbt decriptors overlap with our ecc
146893db446aSBoris Brezillon  * hardware, so define some i.MX specific ones.
146993db446aSBoris Brezillon  */
147093db446aSBoris Brezillon static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
147193db446aSBoris Brezillon static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
147293db446aSBoris Brezillon 
147393db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_descr = {
147493db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
147593db446aSBoris Brezillon 	    | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
147693db446aSBoris Brezillon 	.offs = 0,
147793db446aSBoris Brezillon 	.len = 4,
147893db446aSBoris Brezillon 	.veroffs = 4,
147993db446aSBoris Brezillon 	.maxblocks = 4,
148093db446aSBoris Brezillon 	.pattern = bbt_pattern,
148193db446aSBoris Brezillon };
148293db446aSBoris Brezillon 
148393db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_descr = {
148493db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
148593db446aSBoris Brezillon 	    | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
148693db446aSBoris Brezillon 	.offs = 0,
148793db446aSBoris Brezillon 	.len = 4,
148893db446aSBoris Brezillon 	.veroffs = 4,
148993db446aSBoris Brezillon 	.maxblocks = 4,
149093db446aSBoris Brezillon 	.pattern = mirror_pattern,
149193db446aSBoris Brezillon };
149293db446aSBoris Brezillon 
149393db446aSBoris Brezillon /* v1 + irqpending_quirk: i.MX21 */
149493db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
149593db446aSBoris Brezillon 	.preset = preset_v1,
149693db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v1,
149793db446aSBoris Brezillon 	.send_cmd = send_cmd_v1_v2,
149893db446aSBoris Brezillon 	.send_addr = send_addr_v1_v2,
149993db446aSBoris Brezillon 	.send_page = send_page_v1,
150093db446aSBoris Brezillon 	.send_read_id = send_read_id_v1_v2,
150193db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v1_v2,
150293db446aSBoris Brezillon 	.check_int = check_int_v1_v2,
150393db446aSBoris Brezillon 	.irq_control = irq_control_v1_v2,
150493db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v1,
150593db446aSBoris Brezillon 	.ooblayout = &mxc_v1_ooblayout_ops,
150693db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v1_v3,
150793db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
150893db446aSBoris Brezillon 	.irqpending_quirk = 1,
150993db446aSBoris Brezillon 	.needs_ip = 0,
151093db446aSBoris Brezillon 	.regs_offset = 0xe00,
151193db446aSBoris Brezillon 	.spare0_offset = 0x800,
151293db446aSBoris Brezillon 	.spare_len = 16,
151393db446aSBoris Brezillon 	.eccbytes = 3,
151493db446aSBoris Brezillon 	.eccsize = 1,
151593db446aSBoris Brezillon };
151693db446aSBoris Brezillon 
151793db446aSBoris Brezillon /* v1 + !irqpending_quirk: i.MX27, i.MX31 */
151893db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
151993db446aSBoris Brezillon 	.preset = preset_v1,
152093db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v1,
152193db446aSBoris Brezillon 	.send_cmd = send_cmd_v1_v2,
152293db446aSBoris Brezillon 	.send_addr = send_addr_v1_v2,
152393db446aSBoris Brezillon 	.send_page = send_page_v1,
152493db446aSBoris Brezillon 	.send_read_id = send_read_id_v1_v2,
152593db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v1_v2,
152693db446aSBoris Brezillon 	.check_int = check_int_v1_v2,
152793db446aSBoris Brezillon 	.irq_control = irq_control_v1_v2,
152893db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v1,
152993db446aSBoris Brezillon 	.ooblayout = &mxc_v1_ooblayout_ops,
153093db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v1_v3,
153193db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
153293db446aSBoris Brezillon 	.irqpending_quirk = 0,
153393db446aSBoris Brezillon 	.needs_ip = 0,
153493db446aSBoris Brezillon 	.regs_offset = 0xe00,
153593db446aSBoris Brezillon 	.spare0_offset = 0x800,
153693db446aSBoris Brezillon 	.axi_offset = 0,
153793db446aSBoris Brezillon 	.spare_len = 16,
153893db446aSBoris Brezillon 	.eccbytes = 3,
153993db446aSBoris Brezillon 	.eccsize = 1,
154093db446aSBoris Brezillon };
154193db446aSBoris Brezillon 
154293db446aSBoris Brezillon /* v21: i.MX25, i.MX35 */
154393db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
154493db446aSBoris Brezillon 	.preset = preset_v2,
154593db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v2_v3,
154693db446aSBoris Brezillon 	.send_cmd = send_cmd_v1_v2,
154793db446aSBoris Brezillon 	.send_addr = send_addr_v1_v2,
154893db446aSBoris Brezillon 	.send_page = send_page_v2,
154993db446aSBoris Brezillon 	.send_read_id = send_read_id_v1_v2,
155093db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v1_v2,
155193db446aSBoris Brezillon 	.check_int = check_int_v1_v2,
155293db446aSBoris Brezillon 	.irq_control = irq_control_v1_v2,
155393db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v2,
155493db446aSBoris Brezillon 	.ooblayout = &mxc_v2_ooblayout_ops,
155593db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v2,
155693db446aSBoris Brezillon 	.setup_data_interface = mxc_nand_v2_setup_data_interface,
155793db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
155893db446aSBoris Brezillon 	.irqpending_quirk = 0,
155993db446aSBoris Brezillon 	.needs_ip = 0,
156093db446aSBoris Brezillon 	.regs_offset = 0x1e00,
156193db446aSBoris Brezillon 	.spare0_offset = 0x1000,
156293db446aSBoris Brezillon 	.axi_offset = 0,
156393db446aSBoris Brezillon 	.spare_len = 64,
156493db446aSBoris Brezillon 	.eccbytes = 9,
156593db446aSBoris Brezillon 	.eccsize = 0,
156693db446aSBoris Brezillon };
156793db446aSBoris Brezillon 
156893db446aSBoris Brezillon /* v3.2a: i.MX51 */
156993db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
157093db446aSBoris Brezillon 	.preset = preset_v3,
157193db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v2_v3,
157293db446aSBoris Brezillon 	.send_cmd = send_cmd_v3,
157393db446aSBoris Brezillon 	.send_addr = send_addr_v3,
157493db446aSBoris Brezillon 	.send_page = send_page_v3,
157593db446aSBoris Brezillon 	.send_read_id = send_read_id_v3,
157693db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v3,
157793db446aSBoris Brezillon 	.check_int = check_int_v3,
157893db446aSBoris Brezillon 	.irq_control = irq_control_v3,
157993db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v3,
158093db446aSBoris Brezillon 	.ooblayout = &mxc_v2_ooblayout_ops,
158193db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v1_v3,
158293db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v3,
158393db446aSBoris Brezillon 	.irqpending_quirk = 0,
158493db446aSBoris Brezillon 	.needs_ip = 1,
158593db446aSBoris Brezillon 	.regs_offset = 0,
158693db446aSBoris Brezillon 	.spare0_offset = 0x1000,
158793db446aSBoris Brezillon 	.axi_offset = 0x1e00,
158893db446aSBoris Brezillon 	.spare_len = 64,
158993db446aSBoris Brezillon 	.eccbytes = 0,
159093db446aSBoris Brezillon 	.eccsize = 0,
159193db446aSBoris Brezillon 	.ppb_shift = 7,
159293db446aSBoris Brezillon };
159393db446aSBoris Brezillon 
159493db446aSBoris Brezillon /* v3.2b: i.MX53 */
159593db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
159693db446aSBoris Brezillon 	.preset = preset_v3,
159793db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v2_v3,
159893db446aSBoris Brezillon 	.send_cmd = send_cmd_v3,
159993db446aSBoris Brezillon 	.send_addr = send_addr_v3,
160093db446aSBoris Brezillon 	.send_page = send_page_v3,
160193db446aSBoris Brezillon 	.send_read_id = send_read_id_v3,
160293db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v3,
160393db446aSBoris Brezillon 	.check_int = check_int_v3,
160493db446aSBoris Brezillon 	.irq_control = irq_control_v3,
160593db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v3,
160693db446aSBoris Brezillon 	.ooblayout = &mxc_v2_ooblayout_ops,
160793db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v1_v3,
160893db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v3,
160993db446aSBoris Brezillon 	.irqpending_quirk = 0,
161093db446aSBoris Brezillon 	.needs_ip = 1,
161193db446aSBoris Brezillon 	.regs_offset = 0,
161293db446aSBoris Brezillon 	.spare0_offset = 0x1000,
161393db446aSBoris Brezillon 	.axi_offset = 0x1e00,
161493db446aSBoris Brezillon 	.spare_len = 64,
161593db446aSBoris Brezillon 	.eccbytes = 0,
161693db446aSBoris Brezillon 	.eccsize = 0,
161793db446aSBoris Brezillon 	.ppb_shift = 8,
161893db446aSBoris Brezillon };
161993db446aSBoris Brezillon 
162093db446aSBoris Brezillon static inline int is_imx21_nfc(struct mxc_nand_host *host)
162193db446aSBoris Brezillon {
162293db446aSBoris Brezillon 	return host->devtype_data == &imx21_nand_devtype_data;
162393db446aSBoris Brezillon }
162493db446aSBoris Brezillon 
162593db446aSBoris Brezillon static inline int is_imx27_nfc(struct mxc_nand_host *host)
162693db446aSBoris Brezillon {
162793db446aSBoris Brezillon 	return host->devtype_data == &imx27_nand_devtype_data;
162893db446aSBoris Brezillon }
162993db446aSBoris Brezillon 
163093db446aSBoris Brezillon static inline int is_imx25_nfc(struct mxc_nand_host *host)
163193db446aSBoris Brezillon {
163293db446aSBoris Brezillon 	return host->devtype_data == &imx25_nand_devtype_data;
163393db446aSBoris Brezillon }
163493db446aSBoris Brezillon 
163593db446aSBoris Brezillon static inline int is_imx51_nfc(struct mxc_nand_host *host)
163693db446aSBoris Brezillon {
163793db446aSBoris Brezillon 	return host->devtype_data == &imx51_nand_devtype_data;
163893db446aSBoris Brezillon }
163993db446aSBoris Brezillon 
164093db446aSBoris Brezillon static inline int is_imx53_nfc(struct mxc_nand_host *host)
164193db446aSBoris Brezillon {
164293db446aSBoris Brezillon 	return host->devtype_data == &imx53_nand_devtype_data;
164393db446aSBoris Brezillon }
164493db446aSBoris Brezillon 
164593db446aSBoris Brezillon static const struct platform_device_id mxcnd_devtype[] = {
164693db446aSBoris Brezillon 	{
164793db446aSBoris Brezillon 		.name = "imx21-nand",
164893db446aSBoris Brezillon 		.driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
164993db446aSBoris Brezillon 	}, {
165093db446aSBoris Brezillon 		.name = "imx27-nand",
165193db446aSBoris Brezillon 		.driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
165293db446aSBoris Brezillon 	}, {
165393db446aSBoris Brezillon 		.name = "imx25-nand",
165493db446aSBoris Brezillon 		.driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
165593db446aSBoris Brezillon 	}, {
165693db446aSBoris Brezillon 		.name = "imx51-nand",
165793db446aSBoris Brezillon 		.driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
165893db446aSBoris Brezillon 	}, {
165993db446aSBoris Brezillon 		.name = "imx53-nand",
166093db446aSBoris Brezillon 		.driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
166193db446aSBoris Brezillon 	}, {
166293db446aSBoris Brezillon 		/* sentinel */
166393db446aSBoris Brezillon 	}
166493db446aSBoris Brezillon };
166593db446aSBoris Brezillon MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
166693db446aSBoris Brezillon 
166793db446aSBoris Brezillon #ifdef CONFIG_OF
166893db446aSBoris Brezillon static const struct of_device_id mxcnd_dt_ids[] = {
166993db446aSBoris Brezillon 	{
167093db446aSBoris Brezillon 		.compatible = "fsl,imx21-nand",
167193db446aSBoris Brezillon 		.data = &imx21_nand_devtype_data,
167293db446aSBoris Brezillon 	}, {
167393db446aSBoris Brezillon 		.compatible = "fsl,imx27-nand",
167493db446aSBoris Brezillon 		.data = &imx27_nand_devtype_data,
167593db446aSBoris Brezillon 	}, {
167693db446aSBoris Brezillon 		.compatible = "fsl,imx25-nand",
167793db446aSBoris Brezillon 		.data = &imx25_nand_devtype_data,
167893db446aSBoris Brezillon 	}, {
167993db446aSBoris Brezillon 		.compatible = "fsl,imx51-nand",
168093db446aSBoris Brezillon 		.data = &imx51_nand_devtype_data,
168193db446aSBoris Brezillon 	}, {
168293db446aSBoris Brezillon 		.compatible = "fsl,imx53-nand",
168393db446aSBoris Brezillon 		.data = &imx53_nand_devtype_data,
168493db446aSBoris Brezillon 	},
168593db446aSBoris Brezillon 	{ /* sentinel */ }
168693db446aSBoris Brezillon };
168793db446aSBoris Brezillon MODULE_DEVICE_TABLE(of, mxcnd_dt_ids);
168893db446aSBoris Brezillon 
168993db446aSBoris Brezillon static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
169093db446aSBoris Brezillon {
169193db446aSBoris Brezillon 	struct device_node *np = host->dev->of_node;
169293db446aSBoris Brezillon 	const struct of_device_id *of_id =
169393db446aSBoris Brezillon 		of_match_device(mxcnd_dt_ids, host->dev);
169493db446aSBoris Brezillon 
169593db446aSBoris Brezillon 	if (!np)
169693db446aSBoris Brezillon 		return 1;
169793db446aSBoris Brezillon 
169893db446aSBoris Brezillon 	host->devtype_data = of_id->data;
169993db446aSBoris Brezillon 
170093db446aSBoris Brezillon 	return 0;
170193db446aSBoris Brezillon }
170293db446aSBoris Brezillon #else
170393db446aSBoris Brezillon static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
170493db446aSBoris Brezillon {
170593db446aSBoris Brezillon 	return 1;
170693db446aSBoris Brezillon }
170793db446aSBoris Brezillon #endif
170893db446aSBoris Brezillon 
170993db446aSBoris Brezillon static int mxcnd_probe(struct platform_device *pdev)
171093db446aSBoris Brezillon {
171193db446aSBoris Brezillon 	struct nand_chip *this;
171293db446aSBoris Brezillon 	struct mtd_info *mtd;
171393db446aSBoris Brezillon 	struct mxc_nand_host *host;
171493db446aSBoris Brezillon 	struct resource *res;
171593db446aSBoris Brezillon 	int err = 0;
171693db446aSBoris Brezillon 
171793db446aSBoris Brezillon 	/* Allocate memory for MTD device structure and private data */
171893db446aSBoris Brezillon 	host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
171993db446aSBoris Brezillon 			GFP_KERNEL);
172093db446aSBoris Brezillon 	if (!host)
172193db446aSBoris Brezillon 		return -ENOMEM;
172293db446aSBoris Brezillon 
172393db446aSBoris Brezillon 	/* allocate a temporary buffer for the nand_scan_ident() */
172493db446aSBoris Brezillon 	host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
172593db446aSBoris Brezillon 	if (!host->data_buf)
172693db446aSBoris Brezillon 		return -ENOMEM;
172793db446aSBoris Brezillon 
172893db446aSBoris Brezillon 	host->dev = &pdev->dev;
172993db446aSBoris Brezillon 	/* structures must be linked */
173093db446aSBoris Brezillon 	this = &host->nand;
173193db446aSBoris Brezillon 	mtd = nand_to_mtd(this);
173293db446aSBoris Brezillon 	mtd->dev.parent = &pdev->dev;
173393db446aSBoris Brezillon 	mtd->name = DRIVER_NAME;
173493db446aSBoris Brezillon 
173593db446aSBoris Brezillon 	/* 50 us command delay time */
173693db446aSBoris Brezillon 	this->chip_delay = 5;
173793db446aSBoris Brezillon 
173893db446aSBoris Brezillon 	nand_set_controller_data(this, host);
173993db446aSBoris Brezillon 	nand_set_flash_node(this, pdev->dev.of_node),
174093db446aSBoris Brezillon 	this->dev_ready = mxc_nand_dev_ready;
174193db446aSBoris Brezillon 	this->cmdfunc = mxc_nand_command;
174293db446aSBoris Brezillon 	this->read_byte = mxc_nand_read_byte;
174393db446aSBoris Brezillon 	this->read_word = mxc_nand_read_word;
174493db446aSBoris Brezillon 	this->write_buf = mxc_nand_write_buf;
174593db446aSBoris Brezillon 	this->read_buf = mxc_nand_read_buf;
1746b958758eSMiquel Raynal 	this->set_features = mxc_nand_set_features;
1747b958758eSMiquel Raynal 	this->get_features = mxc_nand_get_features;
174893db446aSBoris Brezillon 
174993db446aSBoris Brezillon 	host->clk = devm_clk_get(&pdev->dev, NULL);
175093db446aSBoris Brezillon 	if (IS_ERR(host->clk))
175193db446aSBoris Brezillon 		return PTR_ERR(host->clk);
175293db446aSBoris Brezillon 
175393db446aSBoris Brezillon 	err = mxcnd_probe_dt(host);
175493db446aSBoris Brezillon 	if (err > 0) {
175593db446aSBoris Brezillon 		struct mxc_nand_platform_data *pdata =
175693db446aSBoris Brezillon 					dev_get_platdata(&pdev->dev);
175793db446aSBoris Brezillon 		if (pdata) {
175893db446aSBoris Brezillon 			host->pdata = *pdata;
175993db446aSBoris Brezillon 			host->devtype_data = (struct mxc_nand_devtype_data *)
176093db446aSBoris Brezillon 						pdev->id_entry->driver_data;
176193db446aSBoris Brezillon 		} else {
176293db446aSBoris Brezillon 			err = -ENODEV;
176393db446aSBoris Brezillon 		}
176493db446aSBoris Brezillon 	}
176593db446aSBoris Brezillon 	if (err < 0)
176693db446aSBoris Brezillon 		return err;
176793db446aSBoris Brezillon 
176893db446aSBoris Brezillon 	this->setup_data_interface = host->devtype_data->setup_data_interface;
176993db446aSBoris Brezillon 
177093db446aSBoris Brezillon 	if (host->devtype_data->needs_ip) {
177193db446aSBoris Brezillon 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
177293db446aSBoris Brezillon 		host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
177393db446aSBoris Brezillon 		if (IS_ERR(host->regs_ip))
177493db446aSBoris Brezillon 			return PTR_ERR(host->regs_ip);
177593db446aSBoris Brezillon 
177693db446aSBoris Brezillon 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
177793db446aSBoris Brezillon 	} else {
177893db446aSBoris Brezillon 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
177993db446aSBoris Brezillon 	}
178093db446aSBoris Brezillon 
178193db446aSBoris Brezillon 	host->base = devm_ioremap_resource(&pdev->dev, res);
178293db446aSBoris Brezillon 	if (IS_ERR(host->base))
178393db446aSBoris Brezillon 		return PTR_ERR(host->base);
178493db446aSBoris Brezillon 
178593db446aSBoris Brezillon 	host->main_area0 = host->base;
178693db446aSBoris Brezillon 
178793db446aSBoris Brezillon 	if (host->devtype_data->regs_offset)
178893db446aSBoris Brezillon 		host->regs = host->base + host->devtype_data->regs_offset;
178993db446aSBoris Brezillon 	host->spare0 = host->base + host->devtype_data->spare0_offset;
179093db446aSBoris Brezillon 	if (host->devtype_data->axi_offset)
179193db446aSBoris Brezillon 		host->regs_axi = host->base + host->devtype_data->axi_offset;
179293db446aSBoris Brezillon 
179393db446aSBoris Brezillon 	this->ecc.bytes = host->devtype_data->eccbytes;
179493db446aSBoris Brezillon 	host->eccsize = host->devtype_data->eccsize;
179593db446aSBoris Brezillon 
179693db446aSBoris Brezillon 	this->select_chip = host->devtype_data->select_chip;
179793db446aSBoris Brezillon 	this->ecc.size = 512;
179893db446aSBoris Brezillon 	mtd_set_ooblayout(mtd, host->devtype_data->ooblayout);
179993db446aSBoris Brezillon 
180093db446aSBoris Brezillon 	if (host->pdata.hw_ecc) {
180193db446aSBoris Brezillon 		this->ecc.mode = NAND_ECC_HW;
180293db446aSBoris Brezillon 	} else {
180393db446aSBoris Brezillon 		this->ecc.mode = NAND_ECC_SOFT;
180493db446aSBoris Brezillon 		this->ecc.algo = NAND_ECC_HAMMING;
180593db446aSBoris Brezillon 	}
180693db446aSBoris Brezillon 
180793db446aSBoris Brezillon 	/* NAND bus width determines access functions used by upper layer */
180893db446aSBoris Brezillon 	if (host->pdata.width == 2)
180993db446aSBoris Brezillon 		this->options |= NAND_BUSWIDTH_16;
181093db446aSBoris Brezillon 
181193db446aSBoris Brezillon 	/* update flash based bbt */
181293db446aSBoris Brezillon 	if (host->pdata.flash_bbt)
181393db446aSBoris Brezillon 		this->bbt_options |= NAND_BBT_USE_FLASH;
181493db446aSBoris Brezillon 
181593db446aSBoris Brezillon 	init_completion(&host->op_completion);
181693db446aSBoris Brezillon 
181793db446aSBoris Brezillon 	host->irq = platform_get_irq(pdev, 0);
181893db446aSBoris Brezillon 	if (host->irq < 0)
181993db446aSBoris Brezillon 		return host->irq;
182093db446aSBoris Brezillon 
182193db446aSBoris Brezillon 	/*
182293db446aSBoris Brezillon 	 * Use host->devtype_data->irq_control() here instead of irq_control()
182393db446aSBoris Brezillon 	 * because we must not disable_irq_nosync without having requested the
182493db446aSBoris Brezillon 	 * irq.
182593db446aSBoris Brezillon 	 */
182693db446aSBoris Brezillon 	host->devtype_data->irq_control(host, 0);
182793db446aSBoris Brezillon 
182893db446aSBoris Brezillon 	err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
182993db446aSBoris Brezillon 			0, DRIVER_NAME, host);
183093db446aSBoris Brezillon 	if (err)
183193db446aSBoris Brezillon 		return err;
183293db446aSBoris Brezillon 
183393db446aSBoris Brezillon 	err = clk_prepare_enable(host->clk);
183493db446aSBoris Brezillon 	if (err)
183593db446aSBoris Brezillon 		return err;
183693db446aSBoris Brezillon 	host->clk_act = 1;
183793db446aSBoris Brezillon 
183893db446aSBoris Brezillon 	/*
183993db446aSBoris Brezillon 	 * Now that we "own" the interrupt make sure the interrupt mask bit is
184093db446aSBoris Brezillon 	 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
184193db446aSBoris Brezillon 	 * on this machine.
184293db446aSBoris Brezillon 	 */
184393db446aSBoris Brezillon 	if (host->devtype_data->irqpending_quirk) {
184493db446aSBoris Brezillon 		disable_irq_nosync(host->irq);
184593db446aSBoris Brezillon 		host->devtype_data->irq_control(host, 1);
184693db446aSBoris Brezillon 	}
184793db446aSBoris Brezillon 
184893db446aSBoris Brezillon 	/* first scan to find the device and get the page size */
184993db446aSBoris Brezillon 	err = nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL);
185093db446aSBoris Brezillon 	if (err)
185193db446aSBoris Brezillon 		goto escan;
185293db446aSBoris Brezillon 
185393db446aSBoris Brezillon 	switch (this->ecc.mode) {
185493db446aSBoris Brezillon 	case NAND_ECC_HW:
185593db446aSBoris Brezillon 		this->ecc.read_page = mxc_nand_read_page;
185693db446aSBoris Brezillon 		this->ecc.read_page_raw = mxc_nand_read_page_raw;
185793db446aSBoris Brezillon 		this->ecc.read_oob = mxc_nand_read_oob;
185893db446aSBoris Brezillon 		this->ecc.write_page = mxc_nand_write_page_ecc;
185993db446aSBoris Brezillon 		this->ecc.write_page_raw = mxc_nand_write_page_raw;
186093db446aSBoris Brezillon 		this->ecc.write_oob = mxc_nand_write_oob;
186193db446aSBoris Brezillon 		break;
186293db446aSBoris Brezillon 
186393db446aSBoris Brezillon 	case NAND_ECC_SOFT:
186493db446aSBoris Brezillon 		break;
186593db446aSBoris Brezillon 
186693db446aSBoris Brezillon 	default:
186793db446aSBoris Brezillon 		err = -EINVAL;
186893db446aSBoris Brezillon 		goto escan;
186993db446aSBoris Brezillon 	}
187093db446aSBoris Brezillon 
187193db446aSBoris Brezillon 	if (this->bbt_options & NAND_BBT_USE_FLASH) {
187293db446aSBoris Brezillon 		this->bbt_td = &bbt_main_descr;
187393db446aSBoris Brezillon 		this->bbt_md = &bbt_mirror_descr;
187493db446aSBoris Brezillon 	}
187593db446aSBoris Brezillon 
187693db446aSBoris Brezillon 	/* allocate the right size buffer now */
187793db446aSBoris Brezillon 	devm_kfree(&pdev->dev, (void *)host->data_buf);
187893db446aSBoris Brezillon 	host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
187993db446aSBoris Brezillon 					GFP_KERNEL);
188093db446aSBoris Brezillon 	if (!host->data_buf) {
188193db446aSBoris Brezillon 		err = -ENOMEM;
188293db446aSBoris Brezillon 		goto escan;
188393db446aSBoris Brezillon 	}
188493db446aSBoris Brezillon 
188593db446aSBoris Brezillon 	/* Call preset again, with correct writesize this time */
188693db446aSBoris Brezillon 	host->devtype_data->preset(mtd);
188793db446aSBoris Brezillon 
188893db446aSBoris Brezillon 	if (!this->ecc.bytes) {
188993db446aSBoris Brezillon 		if (host->eccsize == 8)
189093db446aSBoris Brezillon 			this->ecc.bytes = 18;
189193db446aSBoris Brezillon 		else if (host->eccsize == 4)
189293db446aSBoris Brezillon 			this->ecc.bytes = 9;
189393db446aSBoris Brezillon 	}
189493db446aSBoris Brezillon 
189593db446aSBoris Brezillon 	/*
189693db446aSBoris Brezillon 	 * Experimentation shows that i.MX NFC can only handle up to 218 oob
189793db446aSBoris Brezillon 	 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
189893db446aSBoris Brezillon 	 * into copying invalid data to/from the spare IO buffer, as this
189993db446aSBoris Brezillon 	 * might cause ECC data corruption when doing sub-page write to a
190093db446aSBoris Brezillon 	 * partially written page.
190193db446aSBoris Brezillon 	 */
190293db446aSBoris Brezillon 	host->used_oobsize = min(mtd->oobsize, 218U);
190393db446aSBoris Brezillon 
190493db446aSBoris Brezillon 	if (this->ecc.mode == NAND_ECC_HW) {
190593db446aSBoris Brezillon 		if (is_imx21_nfc(host) || is_imx27_nfc(host))
190693db446aSBoris Brezillon 			this->ecc.strength = 1;
190793db446aSBoris Brezillon 		else
190893db446aSBoris Brezillon 			this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
190993db446aSBoris Brezillon 	}
191093db446aSBoris Brezillon 
191193db446aSBoris Brezillon 	/* second phase scan */
191293db446aSBoris Brezillon 	err = nand_scan_tail(mtd);
191393db446aSBoris Brezillon 	if (err)
191493db446aSBoris Brezillon 		goto escan;
191593db446aSBoris Brezillon 
191693db446aSBoris Brezillon 	/* Register the partitions */
1917be051bf2SMiquel Raynal 	err = mtd_device_parse_register(mtd, part_probes, NULL,
191893db446aSBoris Brezillon 					host->pdata.parts,
191993db446aSBoris Brezillon 					host->pdata.nr_parts);
1920be051bf2SMiquel Raynal 	if (err)
1921be051bf2SMiquel Raynal 		goto cleanup_nand;
192293db446aSBoris Brezillon 
192393db446aSBoris Brezillon 	platform_set_drvdata(pdev, host);
192493db446aSBoris Brezillon 
192593db446aSBoris Brezillon 	return 0;
192693db446aSBoris Brezillon 
1927be051bf2SMiquel Raynal cleanup_nand:
1928be051bf2SMiquel Raynal 	nand_cleanup(this);
192993db446aSBoris Brezillon escan:
193093db446aSBoris Brezillon 	if (host->clk_act)
193193db446aSBoris Brezillon 		clk_disable_unprepare(host->clk);
193293db446aSBoris Brezillon 
193393db446aSBoris Brezillon 	return err;
193493db446aSBoris Brezillon }
193593db446aSBoris Brezillon 
193693db446aSBoris Brezillon static int mxcnd_remove(struct platform_device *pdev)
193793db446aSBoris Brezillon {
193893db446aSBoris Brezillon 	struct mxc_nand_host *host = platform_get_drvdata(pdev);
193993db446aSBoris Brezillon 
194093db446aSBoris Brezillon 	nand_release(nand_to_mtd(&host->nand));
194193db446aSBoris Brezillon 	if (host->clk_act)
194293db446aSBoris Brezillon 		clk_disable_unprepare(host->clk);
194393db446aSBoris Brezillon 
194493db446aSBoris Brezillon 	return 0;
194593db446aSBoris Brezillon }
194693db446aSBoris Brezillon 
194793db446aSBoris Brezillon static struct platform_driver mxcnd_driver = {
194893db446aSBoris Brezillon 	.driver = {
194993db446aSBoris Brezillon 		   .name = DRIVER_NAME,
195093db446aSBoris Brezillon 		   .of_match_table = of_match_ptr(mxcnd_dt_ids),
195193db446aSBoris Brezillon 	},
195293db446aSBoris Brezillon 	.id_table = mxcnd_devtype,
195393db446aSBoris Brezillon 	.probe = mxcnd_probe,
195493db446aSBoris Brezillon 	.remove = mxcnd_remove,
195593db446aSBoris Brezillon };
195693db446aSBoris Brezillon module_platform_driver(mxcnd_driver);
195793db446aSBoris Brezillon 
195893db446aSBoris Brezillon MODULE_AUTHOR("Freescale Semiconductor, Inc.");
195993db446aSBoris Brezillon MODULE_DESCRIPTION("MXC NAND MTD driver");
196093db446aSBoris Brezillon MODULE_LICENSE("GPL");
1961