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