xref: /linux/drivers/mtd/nand/raw/mxc_nand.c (revision ec185b18c22323cb0cde0319fa90b3e467b1ed2d)
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 
2593db446aSBoris Brezillon #define DRIVER_NAME "mxc_nand"
2693db446aSBoris Brezillon 
2793db446aSBoris Brezillon /* Addresses for NFC registers */
2893db446aSBoris Brezillon #define NFC_V1_V2_BUF_SIZE		(host->regs + 0x00)
2993db446aSBoris Brezillon #define NFC_V1_V2_BUF_ADDR		(host->regs + 0x04)
3093db446aSBoris Brezillon #define NFC_V1_V2_FLASH_ADDR		(host->regs + 0x06)
3193db446aSBoris Brezillon #define NFC_V1_V2_FLASH_CMD		(host->regs + 0x08)
3293db446aSBoris Brezillon #define NFC_V1_V2_CONFIG		(host->regs + 0x0a)
3393db446aSBoris Brezillon #define NFC_V1_V2_ECC_STATUS_RESULT	(host->regs + 0x0c)
3493db446aSBoris Brezillon #define NFC_V1_V2_RSLTMAIN_AREA		(host->regs + 0x0e)
353f77f244SMartin Kaiser #define NFC_V21_RSLTSPARE_AREA		(host->regs + 0x10)
3693db446aSBoris Brezillon #define NFC_V1_V2_WRPROT		(host->regs + 0x12)
3793db446aSBoris Brezillon #define NFC_V1_UNLOCKSTART_BLKADDR	(host->regs + 0x14)
3893db446aSBoris Brezillon #define NFC_V1_UNLOCKEND_BLKADDR	(host->regs + 0x16)
3993db446aSBoris Brezillon #define NFC_V21_UNLOCKSTART_BLKADDR0	(host->regs + 0x20)
4093db446aSBoris Brezillon #define NFC_V21_UNLOCKSTART_BLKADDR1	(host->regs + 0x24)
4193db446aSBoris Brezillon #define NFC_V21_UNLOCKSTART_BLKADDR2	(host->regs + 0x28)
4293db446aSBoris Brezillon #define NFC_V21_UNLOCKSTART_BLKADDR3	(host->regs + 0x2c)
4393db446aSBoris Brezillon #define NFC_V21_UNLOCKEND_BLKADDR0	(host->regs + 0x22)
4493db446aSBoris Brezillon #define NFC_V21_UNLOCKEND_BLKADDR1	(host->regs + 0x26)
4593db446aSBoris Brezillon #define NFC_V21_UNLOCKEND_BLKADDR2	(host->regs + 0x2a)
4693db446aSBoris Brezillon #define NFC_V21_UNLOCKEND_BLKADDR3	(host->regs + 0x2e)
4793db446aSBoris Brezillon #define NFC_V1_V2_NF_WRPRST		(host->regs + 0x18)
4893db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1		(host->regs + 0x1a)
4993db446aSBoris Brezillon #define NFC_V1_V2_CONFIG2		(host->regs + 0x1c)
5093db446aSBoris Brezillon 
5193db446aSBoris Brezillon #define NFC_V2_CONFIG1_ECC_MODE_4	(1 << 0)
5293db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_SP_EN		(1 << 2)
5393db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_ECC_EN	(1 << 3)
5493db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_INT_MSK	(1 << 4)
5593db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_BIG		(1 << 5)
5693db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_RST		(1 << 6)
5793db446aSBoris Brezillon #define NFC_V1_V2_CONFIG1_CE		(1 << 7)
5893db446aSBoris Brezillon #define NFC_V2_CONFIG1_ONE_CYCLE	(1 << 8)
5993db446aSBoris Brezillon #define NFC_V2_CONFIG1_PPB(x)		(((x) & 0x3) << 9)
6093db446aSBoris Brezillon #define NFC_V2_CONFIG1_FP_INT		(1 << 11)
6193db446aSBoris Brezillon 
6293db446aSBoris Brezillon #define NFC_V1_V2_CONFIG2_INT		(1 << 15)
6393db446aSBoris Brezillon 
6493db446aSBoris Brezillon /*
6593db446aSBoris Brezillon  * Operation modes for the NFC. Valid for v1, v2 and v3
6693db446aSBoris Brezillon  * type controllers.
6793db446aSBoris Brezillon  */
6893db446aSBoris Brezillon #define NFC_CMD				(1 << 0)
6993db446aSBoris Brezillon #define NFC_ADDR			(1 << 1)
7093db446aSBoris Brezillon #define NFC_INPUT			(1 << 2)
7193db446aSBoris Brezillon #define NFC_OUTPUT			(1 << 3)
7293db446aSBoris Brezillon #define NFC_ID				(1 << 4)
7393db446aSBoris Brezillon #define NFC_STATUS			(1 << 5)
7493db446aSBoris Brezillon 
7593db446aSBoris Brezillon #define NFC_V3_FLASH_CMD		(host->regs_axi + 0x00)
7693db446aSBoris Brezillon #define NFC_V3_FLASH_ADDR0		(host->regs_axi + 0x04)
7793db446aSBoris Brezillon 
7893db446aSBoris Brezillon #define NFC_V3_CONFIG1			(host->regs_axi + 0x34)
7993db446aSBoris Brezillon #define NFC_V3_CONFIG1_SP_EN		(1 << 0)
8093db446aSBoris Brezillon #define NFC_V3_CONFIG1_RBA(x)		(((x) & 0x7 ) << 4)
8193db446aSBoris Brezillon 
8293db446aSBoris Brezillon #define NFC_V3_ECC_STATUS_RESULT	(host->regs_axi + 0x38)
8393db446aSBoris Brezillon 
8493db446aSBoris Brezillon #define NFC_V3_LAUNCH			(host->regs_axi + 0x40)
8593db446aSBoris Brezillon 
8693db446aSBoris Brezillon #define NFC_V3_WRPROT			(host->regs_ip + 0x0)
8793db446aSBoris Brezillon #define NFC_V3_WRPROT_LOCK_TIGHT	(1 << 0)
8893db446aSBoris Brezillon #define NFC_V3_WRPROT_LOCK		(1 << 1)
8993db446aSBoris Brezillon #define NFC_V3_WRPROT_UNLOCK		(1 << 2)
9093db446aSBoris Brezillon #define NFC_V3_WRPROT_BLS_UNLOCK	(2 << 6)
9193db446aSBoris Brezillon 
9293db446aSBoris Brezillon #define NFC_V3_WRPROT_UNLOCK_BLK_ADD0   (host->regs_ip + 0x04)
9393db446aSBoris Brezillon 
9493db446aSBoris Brezillon #define NFC_V3_CONFIG2			(host->regs_ip + 0x24)
9593db446aSBoris Brezillon #define NFC_V3_CONFIG2_PS_512			(0 << 0)
9693db446aSBoris Brezillon #define NFC_V3_CONFIG2_PS_2048			(1 << 0)
9793db446aSBoris Brezillon #define NFC_V3_CONFIG2_PS_4096			(2 << 0)
9893db446aSBoris Brezillon #define NFC_V3_CONFIG2_ONE_CYCLE		(1 << 2)
9993db446aSBoris Brezillon #define NFC_V3_CONFIG2_ECC_EN			(1 << 3)
10093db446aSBoris Brezillon #define NFC_V3_CONFIG2_2CMD_PHASES		(1 << 4)
10193db446aSBoris Brezillon #define NFC_V3_CONFIG2_NUM_ADDR_PHASE0		(1 << 5)
10293db446aSBoris Brezillon #define NFC_V3_CONFIG2_ECC_MODE_8		(1 << 6)
10393db446aSBoris Brezillon #define NFC_V3_CONFIG2_PPB(x, shift)		(((x) & 0x3) << shift)
10493db446aSBoris Brezillon #define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x)	(((x) & 0x3) << 12)
10593db446aSBoris Brezillon #define NFC_V3_CONFIG2_INT_MSK			(1 << 15)
10693db446aSBoris Brezillon #define NFC_V3_CONFIG2_ST_CMD(x)		(((x) & 0xff) << 24)
10793db446aSBoris Brezillon #define NFC_V3_CONFIG2_SPAS(x)			(((x) & 0xff) << 16)
10893db446aSBoris Brezillon 
10993db446aSBoris Brezillon #define NFC_V3_CONFIG3				(host->regs_ip + 0x28)
11093db446aSBoris Brezillon #define NFC_V3_CONFIG3_ADD_OP(x)		(((x) & 0x3) << 0)
11193db446aSBoris Brezillon #define NFC_V3_CONFIG3_FW8			(1 << 3)
11293db446aSBoris Brezillon #define NFC_V3_CONFIG3_SBB(x)			(((x) & 0x7) << 8)
11393db446aSBoris Brezillon #define NFC_V3_CONFIG3_NUM_OF_DEVICES(x)	(((x) & 0x7) << 12)
11493db446aSBoris Brezillon #define NFC_V3_CONFIG3_RBB_MODE			(1 << 15)
11593db446aSBoris Brezillon #define NFC_V3_CONFIG3_NO_SDMA			(1 << 20)
11693db446aSBoris Brezillon 
11793db446aSBoris Brezillon #define NFC_V3_IPC			(host->regs_ip + 0x2C)
11893db446aSBoris Brezillon #define NFC_V3_IPC_CREQ			(1 << 0)
11993db446aSBoris Brezillon #define NFC_V3_IPC_INT			(1 << 31)
12093db446aSBoris Brezillon 
12193db446aSBoris Brezillon #define NFC_V3_DELAY_LINE		(host->regs_ip + 0x34)
12293db446aSBoris Brezillon 
12393db446aSBoris Brezillon struct mxc_nand_host;
12493db446aSBoris Brezillon 
12593db446aSBoris Brezillon struct mxc_nand_devtype_data {
12693db446aSBoris Brezillon 	void (*preset)(struct mtd_info *);
12793db446aSBoris Brezillon 	int (*read_page)(struct nand_chip *chip, void *buf, void *oob, bool ecc,
12893db446aSBoris Brezillon 			 int page);
12993db446aSBoris Brezillon 	void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
13093db446aSBoris Brezillon 	void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
13193db446aSBoris Brezillon 	void (*send_page)(struct mtd_info *, unsigned int);
13293db446aSBoris Brezillon 	void (*send_read_id)(struct mxc_nand_host *);
13393db446aSBoris Brezillon 	uint16_t (*get_dev_status)(struct mxc_nand_host *);
13493db446aSBoris Brezillon 	int (*check_int)(struct mxc_nand_host *);
13593db446aSBoris Brezillon 	void (*irq_control)(struct mxc_nand_host *, int);
13693db446aSBoris Brezillon 	u32 (*get_ecc_status)(struct mxc_nand_host *);
13793db446aSBoris Brezillon 	const struct mtd_ooblayout_ops *ooblayout;
138758b56f5SBoris Brezillon 	void (*select_chip)(struct nand_chip *chip, int cs);
1394c46667bSMiquel Raynal 	int (*setup_interface)(struct nand_chip *chip, int csline,
1404c46667bSMiquel Raynal 			       const struct nand_interface_config *conf);
14193db446aSBoris Brezillon 	void (*enable_hwecc)(struct nand_chip *chip, bool enable);
14293db446aSBoris Brezillon 
14393db446aSBoris Brezillon 	/*
14493db446aSBoris Brezillon 	 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
14593db446aSBoris Brezillon 	 * (CONFIG1:INT_MSK is set). To handle this the driver uses
14693db446aSBoris Brezillon 	 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
14793db446aSBoris Brezillon 	 */
14893db446aSBoris Brezillon 	int irqpending_quirk;
14993db446aSBoris Brezillon 	int needs_ip;
15093db446aSBoris Brezillon 
15193db446aSBoris Brezillon 	size_t regs_offset;
15293db446aSBoris Brezillon 	size_t spare0_offset;
15393db446aSBoris Brezillon 	size_t axi_offset;
15493db446aSBoris Brezillon 
15593db446aSBoris Brezillon 	int spare_len;
15693db446aSBoris Brezillon 	int eccbytes;
15793db446aSBoris Brezillon 	int eccsize;
15893db446aSBoris Brezillon 	int ppb_shift;
15993db446aSBoris Brezillon };
16093db446aSBoris Brezillon 
16193db446aSBoris Brezillon struct mxc_nand_host {
16293db446aSBoris Brezillon 	struct nand_chip	nand;
16393db446aSBoris Brezillon 	struct device		*dev;
16493db446aSBoris Brezillon 
16593db446aSBoris Brezillon 	void __iomem		*spare0;
16693db446aSBoris Brezillon 	void __iomem		*main_area0;
16793db446aSBoris Brezillon 
16893db446aSBoris Brezillon 	void __iomem		*base;
16993db446aSBoris Brezillon 	void __iomem		*regs;
17093db446aSBoris Brezillon 	void __iomem		*regs_axi;
17193db446aSBoris Brezillon 	void __iomem		*regs_ip;
17293db446aSBoris Brezillon 	int			status_request;
17393db446aSBoris Brezillon 	struct clk		*clk;
17493db446aSBoris Brezillon 	int			clk_act;
17593db446aSBoris Brezillon 	int			irq;
17693db446aSBoris Brezillon 	int			eccsize;
17793db446aSBoris Brezillon 	int			used_oobsize;
17893db446aSBoris Brezillon 	int			active_cs;
17993db446aSBoris Brezillon 
18093db446aSBoris Brezillon 	struct completion	op_completion;
18193db446aSBoris Brezillon 
18293db446aSBoris Brezillon 	uint8_t			*data_buf;
18393db446aSBoris Brezillon 	unsigned int		buf_start;
18493db446aSBoris Brezillon 
18593db446aSBoris Brezillon 	const struct mxc_nand_devtype_data *devtype_data;
18693db446aSBoris Brezillon };
18793db446aSBoris Brezillon 
18893db446aSBoris Brezillon static const char * const part_probes[] = {
18993db446aSBoris Brezillon 	"cmdlinepart", "RedBoot", "ofpart", NULL };
19093db446aSBoris Brezillon 
19193db446aSBoris Brezillon static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
19293db446aSBoris Brezillon {
19393db446aSBoris Brezillon 	int i;
19493db446aSBoris Brezillon 	u32 *t = trg;
19593db446aSBoris Brezillon 	const __iomem u32 *s = src;
19693db446aSBoris Brezillon 
19793db446aSBoris Brezillon 	for (i = 0; i < (size >> 2); i++)
19893db446aSBoris Brezillon 		*t++ = __raw_readl(s++);
19993db446aSBoris Brezillon }
20093db446aSBoris Brezillon 
20193db446aSBoris Brezillon static void memcpy16_fromio(void *trg, const void __iomem  *src, size_t size)
20293db446aSBoris Brezillon {
20393db446aSBoris Brezillon 	int i;
20493db446aSBoris Brezillon 	u16 *t = trg;
20593db446aSBoris Brezillon 	const __iomem u16 *s = src;
20693db446aSBoris Brezillon 
20793db446aSBoris Brezillon 	/* We assume that src (IO) is always 32bit aligned */
20893db446aSBoris Brezillon 	if (PTR_ALIGN(trg, 4) == trg && IS_ALIGNED(size, 4)) {
20993db446aSBoris Brezillon 		memcpy32_fromio(trg, src, size);
21093db446aSBoris Brezillon 		return;
21193db446aSBoris Brezillon 	}
21293db446aSBoris Brezillon 
21393db446aSBoris Brezillon 	for (i = 0; i < (size >> 1); i++)
21493db446aSBoris Brezillon 		*t++ = __raw_readw(s++);
21593db446aSBoris Brezillon }
21693db446aSBoris Brezillon 
21793db446aSBoris Brezillon static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
21893db446aSBoris Brezillon {
21993db446aSBoris Brezillon 	/* __iowrite32_copy use 32bit size values so divide by 4 */
22093db446aSBoris Brezillon 	__iowrite32_copy(trg, src, size / 4);
22193db446aSBoris Brezillon }
22293db446aSBoris Brezillon 
22393db446aSBoris Brezillon static void memcpy16_toio(void __iomem *trg, const void *src, int size)
22493db446aSBoris Brezillon {
22593db446aSBoris Brezillon 	int i;
22693db446aSBoris Brezillon 	__iomem u16 *t = trg;
22793db446aSBoris Brezillon 	const u16 *s = src;
22893db446aSBoris Brezillon 
22993db446aSBoris Brezillon 	/* We assume that trg (IO) is always 32bit aligned */
23093db446aSBoris Brezillon 	if (PTR_ALIGN(src, 4) == src && IS_ALIGNED(size, 4)) {
23193db446aSBoris Brezillon 		memcpy32_toio(trg, src, size);
23293db446aSBoris Brezillon 		return;
23393db446aSBoris Brezillon 	}
23493db446aSBoris Brezillon 
23593db446aSBoris Brezillon 	for (i = 0; i < (size >> 1); i++)
23693db446aSBoris Brezillon 		__raw_writew(*s++, t++);
23793db446aSBoris Brezillon }
23893db446aSBoris Brezillon 
23993db446aSBoris Brezillon /*
24093db446aSBoris Brezillon  * The controller splits a page into data chunks of 512 bytes + partial oob.
24193db446aSBoris Brezillon  * There are writesize / 512 such chunks, the size of the partial oob parts is
24293db446aSBoris Brezillon  * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then
24393db446aSBoris Brezillon  * contains additionally the byte lost by rounding (if any).
24493db446aSBoris Brezillon  * This function handles the needed shuffling between host->data_buf (which
24593db446aSBoris Brezillon  * holds a page in natural order, i.e. writesize bytes data + oobsize bytes
24693db446aSBoris Brezillon  * spare) and the NFC buffer.
24793db446aSBoris Brezillon  */
24893db446aSBoris Brezillon static void copy_spare(struct mtd_info *mtd, bool bfrom, void *buf)
24993db446aSBoris Brezillon {
25093db446aSBoris Brezillon 	struct nand_chip *this = mtd_to_nand(mtd);
25193db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(this);
25293db446aSBoris Brezillon 	u16 i, oob_chunk_size;
25393db446aSBoris Brezillon 	u16 num_chunks = mtd->writesize / 512;
25493db446aSBoris Brezillon 
25593db446aSBoris Brezillon 	u8 *d = buf;
25693db446aSBoris Brezillon 	u8 __iomem *s = host->spare0;
25793db446aSBoris Brezillon 	u16 sparebuf_size = host->devtype_data->spare_len;
25893db446aSBoris Brezillon 
25993db446aSBoris Brezillon 	/* size of oob chunk for all but possibly the last one */
26093db446aSBoris Brezillon 	oob_chunk_size = (host->used_oobsize / num_chunks) & ~1;
26193db446aSBoris Brezillon 
26293db446aSBoris Brezillon 	if (bfrom) {
26393db446aSBoris Brezillon 		for (i = 0; i < num_chunks - 1; i++)
26493db446aSBoris Brezillon 			memcpy16_fromio(d + i * oob_chunk_size,
26593db446aSBoris Brezillon 					s + i * sparebuf_size,
26693db446aSBoris Brezillon 					oob_chunk_size);
26793db446aSBoris Brezillon 
26893db446aSBoris Brezillon 		/* the last chunk */
26993db446aSBoris Brezillon 		memcpy16_fromio(d + i * oob_chunk_size,
27093db446aSBoris Brezillon 				s + i * sparebuf_size,
27193db446aSBoris Brezillon 				host->used_oobsize - i * oob_chunk_size);
27293db446aSBoris Brezillon 	} else {
27393db446aSBoris Brezillon 		for (i = 0; i < num_chunks - 1; i++)
27493db446aSBoris Brezillon 			memcpy16_toio(&s[i * sparebuf_size],
27593db446aSBoris Brezillon 				      &d[i * oob_chunk_size],
27693db446aSBoris Brezillon 				      oob_chunk_size);
27793db446aSBoris Brezillon 
27893db446aSBoris Brezillon 		/* the last chunk */
27993db446aSBoris Brezillon 		memcpy16_toio(&s[i * sparebuf_size],
28093db446aSBoris Brezillon 			      &d[i * oob_chunk_size],
28193db446aSBoris Brezillon 			      host->used_oobsize - i * oob_chunk_size);
28293db446aSBoris Brezillon 	}
28393db446aSBoris Brezillon }
28493db446aSBoris Brezillon 
28593db446aSBoris Brezillon /*
28693db446aSBoris Brezillon  * MXC NANDFC can only perform full page+spare or spare-only read/write.  When
28793db446aSBoris Brezillon  * the upper layers perform a read/write buf operation, the saved column address
28893db446aSBoris Brezillon  * is used to index into the full page. So usually this function is called with
28993db446aSBoris Brezillon  * column == 0 (unless no column cycle is needed indicated by column == -1)
29093db446aSBoris Brezillon  */
29193db446aSBoris Brezillon static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
29293db446aSBoris Brezillon {
29393db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
29493db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
29593db446aSBoris Brezillon 
29693db446aSBoris Brezillon 	/* Write out column address, if necessary */
29793db446aSBoris Brezillon 	if (column != -1) {
29893db446aSBoris Brezillon 		host->devtype_data->send_addr(host, column & 0xff,
29993db446aSBoris Brezillon 					      page_addr == -1);
30093db446aSBoris Brezillon 		if (mtd->writesize > 512)
30193db446aSBoris Brezillon 			/* another col addr cycle for 2k page */
30293db446aSBoris Brezillon 			host->devtype_data->send_addr(host,
30393db446aSBoris Brezillon 						      (column >> 8) & 0xff,
30493db446aSBoris Brezillon 						      false);
30593db446aSBoris Brezillon 	}
30693db446aSBoris Brezillon 
30793db446aSBoris Brezillon 	/* Write out page address, if necessary */
30893db446aSBoris Brezillon 	if (page_addr != -1) {
30993db446aSBoris Brezillon 		/* paddr_0 - p_addr_7 */
31093db446aSBoris Brezillon 		host->devtype_data->send_addr(host, (page_addr & 0xff), false);
31193db446aSBoris Brezillon 
31293db446aSBoris Brezillon 		if (mtd->writesize > 512) {
31393db446aSBoris Brezillon 			if (mtd->size >= 0x10000000) {
31493db446aSBoris Brezillon 				/* paddr_8 - paddr_15 */
31593db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
31693db446aSBoris Brezillon 						(page_addr >> 8) & 0xff,
31793db446aSBoris Brezillon 						false);
31893db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
31993db446aSBoris Brezillon 						(page_addr >> 16) & 0xff,
32093db446aSBoris Brezillon 						true);
32193db446aSBoris Brezillon 			} else
32293db446aSBoris Brezillon 				/* paddr_8 - paddr_15 */
32393db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
32493db446aSBoris Brezillon 						(page_addr >> 8) & 0xff, true);
32593db446aSBoris Brezillon 		} else {
32693db446aSBoris Brezillon 			if (nand_chip->options & NAND_ROW_ADDR_3) {
32793db446aSBoris Brezillon 				/* paddr_8 - paddr_15 */
32893db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
32993db446aSBoris Brezillon 						(page_addr >> 8) & 0xff,
33093db446aSBoris Brezillon 						false);
33193db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
33293db446aSBoris Brezillon 						(page_addr >> 16) & 0xff,
33393db446aSBoris Brezillon 						true);
33493db446aSBoris Brezillon 			} else
33593db446aSBoris Brezillon 				/* paddr_8 - paddr_15 */
33693db446aSBoris Brezillon 				host->devtype_data->send_addr(host,
33793db446aSBoris Brezillon 						(page_addr >> 8) & 0xff, true);
33893db446aSBoris Brezillon 		}
33993db446aSBoris Brezillon 	}
34093db446aSBoris Brezillon }
34193db446aSBoris Brezillon 
34293db446aSBoris Brezillon static int check_int_v3(struct mxc_nand_host *host)
34393db446aSBoris Brezillon {
34493db446aSBoris Brezillon 	uint32_t tmp;
34593db446aSBoris Brezillon 
34693db446aSBoris Brezillon 	tmp = readl(NFC_V3_IPC);
34793db446aSBoris Brezillon 	if (!(tmp & NFC_V3_IPC_INT))
34893db446aSBoris Brezillon 		return 0;
34993db446aSBoris Brezillon 
35093db446aSBoris Brezillon 	tmp &= ~NFC_V3_IPC_INT;
35193db446aSBoris Brezillon 	writel(tmp, NFC_V3_IPC);
35293db446aSBoris Brezillon 
35393db446aSBoris Brezillon 	return 1;
35493db446aSBoris Brezillon }
35593db446aSBoris Brezillon 
35693db446aSBoris Brezillon static int check_int_v1_v2(struct mxc_nand_host *host)
35793db446aSBoris Brezillon {
35893db446aSBoris Brezillon 	uint32_t tmp;
35993db446aSBoris Brezillon 
36093db446aSBoris Brezillon 	tmp = readw(NFC_V1_V2_CONFIG2);
36193db446aSBoris Brezillon 	if (!(tmp & NFC_V1_V2_CONFIG2_INT))
36293db446aSBoris Brezillon 		return 0;
36393db446aSBoris Brezillon 
36493db446aSBoris Brezillon 	if (!host->devtype_data->irqpending_quirk)
36593db446aSBoris Brezillon 		writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
36693db446aSBoris Brezillon 
36793db446aSBoris Brezillon 	return 1;
36893db446aSBoris Brezillon }
36993db446aSBoris Brezillon 
37093db446aSBoris Brezillon static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
37193db446aSBoris Brezillon {
37293db446aSBoris Brezillon 	uint16_t tmp;
37393db446aSBoris Brezillon 
37493db446aSBoris Brezillon 	tmp = readw(NFC_V1_V2_CONFIG1);
37593db446aSBoris Brezillon 
37693db446aSBoris Brezillon 	if (activate)
37793db446aSBoris Brezillon 		tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
37893db446aSBoris Brezillon 	else
37993db446aSBoris Brezillon 		tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
38093db446aSBoris Brezillon 
38193db446aSBoris Brezillon 	writew(tmp, NFC_V1_V2_CONFIG1);
38293db446aSBoris Brezillon }
38393db446aSBoris Brezillon 
38493db446aSBoris Brezillon static void irq_control_v3(struct mxc_nand_host *host, int activate)
38593db446aSBoris Brezillon {
38693db446aSBoris Brezillon 	uint32_t tmp;
38793db446aSBoris Brezillon 
38893db446aSBoris Brezillon 	tmp = readl(NFC_V3_CONFIG2);
38993db446aSBoris Brezillon 
39093db446aSBoris Brezillon 	if (activate)
39193db446aSBoris Brezillon 		tmp &= ~NFC_V3_CONFIG2_INT_MSK;
39293db446aSBoris Brezillon 	else
39393db446aSBoris Brezillon 		tmp |= NFC_V3_CONFIG2_INT_MSK;
39493db446aSBoris Brezillon 
39593db446aSBoris Brezillon 	writel(tmp, NFC_V3_CONFIG2);
39693db446aSBoris Brezillon }
39793db446aSBoris Brezillon 
39893db446aSBoris Brezillon static void irq_control(struct mxc_nand_host *host, int activate)
39993db446aSBoris Brezillon {
40093db446aSBoris Brezillon 	if (host->devtype_data->irqpending_quirk) {
40193db446aSBoris Brezillon 		if (activate)
40293db446aSBoris Brezillon 			enable_irq(host->irq);
40393db446aSBoris Brezillon 		else
40493db446aSBoris Brezillon 			disable_irq_nosync(host->irq);
40593db446aSBoris Brezillon 	} else {
40693db446aSBoris Brezillon 		host->devtype_data->irq_control(host, activate);
40793db446aSBoris Brezillon 	}
40893db446aSBoris Brezillon }
40993db446aSBoris Brezillon 
41093db446aSBoris Brezillon static u32 get_ecc_status_v1(struct mxc_nand_host *host)
41193db446aSBoris Brezillon {
41293db446aSBoris Brezillon 	return readw(NFC_V1_V2_ECC_STATUS_RESULT);
41393db446aSBoris Brezillon }
41493db446aSBoris Brezillon 
41593db446aSBoris Brezillon static u32 get_ecc_status_v2(struct mxc_nand_host *host)
41693db446aSBoris Brezillon {
41793db446aSBoris Brezillon 	return readl(NFC_V1_V2_ECC_STATUS_RESULT);
41893db446aSBoris Brezillon }
41993db446aSBoris Brezillon 
42093db446aSBoris Brezillon static u32 get_ecc_status_v3(struct mxc_nand_host *host)
42193db446aSBoris Brezillon {
42293db446aSBoris Brezillon 	return readl(NFC_V3_ECC_STATUS_RESULT);
42393db446aSBoris Brezillon }
42493db446aSBoris Brezillon 
42593db446aSBoris Brezillon static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
42693db446aSBoris Brezillon {
42793db446aSBoris Brezillon 	struct mxc_nand_host *host = dev_id;
42893db446aSBoris Brezillon 
42993db446aSBoris Brezillon 	if (!host->devtype_data->check_int(host))
43093db446aSBoris Brezillon 		return IRQ_NONE;
43193db446aSBoris Brezillon 
43293db446aSBoris Brezillon 	irq_control(host, 0);
43393db446aSBoris Brezillon 
43493db446aSBoris Brezillon 	complete(&host->op_completion);
43593db446aSBoris Brezillon 
43693db446aSBoris Brezillon 	return IRQ_HANDLED;
43793db446aSBoris Brezillon }
43893db446aSBoris Brezillon 
43993db446aSBoris Brezillon /* This function polls the NANDFC to wait for the basic operation to
44093db446aSBoris Brezillon  * complete by checking the INT bit of config2 register.
44193db446aSBoris Brezillon  */
44293db446aSBoris Brezillon static int wait_op_done(struct mxc_nand_host *host, int useirq)
44393db446aSBoris Brezillon {
44493db446aSBoris Brezillon 	int ret = 0;
44593db446aSBoris Brezillon 
44693db446aSBoris Brezillon 	/*
44793db446aSBoris Brezillon 	 * If operation is already complete, don't bother to setup an irq or a
44893db446aSBoris Brezillon 	 * loop.
44993db446aSBoris Brezillon 	 */
45093db446aSBoris Brezillon 	if (host->devtype_data->check_int(host))
45193db446aSBoris Brezillon 		return 0;
45293db446aSBoris Brezillon 
45393db446aSBoris Brezillon 	if (useirq) {
45493db446aSBoris Brezillon 		unsigned long timeout;
45593db446aSBoris Brezillon 
45693db446aSBoris Brezillon 		reinit_completion(&host->op_completion);
45793db446aSBoris Brezillon 
45893db446aSBoris Brezillon 		irq_control(host, 1);
45993db446aSBoris Brezillon 
46093db446aSBoris Brezillon 		timeout = wait_for_completion_timeout(&host->op_completion, HZ);
46193db446aSBoris Brezillon 		if (!timeout && !host->devtype_data->check_int(host)) {
46293db446aSBoris Brezillon 			dev_dbg(host->dev, "timeout waiting for irq\n");
46393db446aSBoris Brezillon 			ret = -ETIMEDOUT;
46493db446aSBoris Brezillon 		}
46593db446aSBoris Brezillon 	} else {
46693db446aSBoris Brezillon 		int max_retries = 8000;
46793db446aSBoris Brezillon 		int done;
46893db446aSBoris Brezillon 
46993db446aSBoris Brezillon 		do {
47093db446aSBoris Brezillon 			udelay(1);
47193db446aSBoris Brezillon 
47293db446aSBoris Brezillon 			done = host->devtype_data->check_int(host);
47393db446aSBoris Brezillon 			if (done)
47493db446aSBoris Brezillon 				break;
47593db446aSBoris Brezillon 
47693db446aSBoris Brezillon 		} while (--max_retries);
47793db446aSBoris Brezillon 
47893db446aSBoris Brezillon 		if (!done) {
47993db446aSBoris Brezillon 			dev_dbg(host->dev, "timeout polling for completion\n");
48093db446aSBoris Brezillon 			ret = -ETIMEDOUT;
48193db446aSBoris Brezillon 		}
48293db446aSBoris Brezillon 	}
48393db446aSBoris Brezillon 
48493db446aSBoris Brezillon 	WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq);
48593db446aSBoris Brezillon 
48693db446aSBoris Brezillon 	return ret;
48793db446aSBoris Brezillon }
48893db446aSBoris Brezillon 
48993db446aSBoris Brezillon static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
49093db446aSBoris Brezillon {
49193db446aSBoris Brezillon 	/* fill command */
49293db446aSBoris Brezillon 	writel(cmd, NFC_V3_FLASH_CMD);
49393db446aSBoris Brezillon 
49493db446aSBoris Brezillon 	/* send out command */
49593db446aSBoris Brezillon 	writel(NFC_CMD, NFC_V3_LAUNCH);
49693db446aSBoris Brezillon 
49793db446aSBoris Brezillon 	/* Wait for operation to complete */
49893db446aSBoris Brezillon 	wait_op_done(host, useirq);
49993db446aSBoris Brezillon }
50093db446aSBoris Brezillon 
50193db446aSBoris Brezillon /* This function issues the specified command to the NAND device and
50293db446aSBoris Brezillon  * waits for completion. */
50393db446aSBoris Brezillon static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
50493db446aSBoris Brezillon {
50593db446aSBoris Brezillon 	dev_dbg(host->dev, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
50693db446aSBoris Brezillon 
50793db446aSBoris Brezillon 	writew(cmd, NFC_V1_V2_FLASH_CMD);
50893db446aSBoris Brezillon 	writew(NFC_CMD, NFC_V1_V2_CONFIG2);
50993db446aSBoris Brezillon 
51093db446aSBoris Brezillon 	if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
51193db446aSBoris Brezillon 		int max_retries = 100;
51293db446aSBoris Brezillon 		/* Reset completion is indicated by NFC_CONFIG2 */
51393db446aSBoris Brezillon 		/* being set to 0 */
51493db446aSBoris Brezillon 		while (max_retries-- > 0) {
51593db446aSBoris Brezillon 			if (readw(NFC_V1_V2_CONFIG2) == 0) {
51693db446aSBoris Brezillon 				break;
51793db446aSBoris Brezillon 			}
51893db446aSBoris Brezillon 			udelay(1);
51993db446aSBoris Brezillon 		}
52093db446aSBoris Brezillon 		if (max_retries < 0)
52193db446aSBoris Brezillon 			dev_dbg(host->dev, "%s: RESET failed\n", __func__);
52293db446aSBoris Brezillon 	} else {
52393db446aSBoris Brezillon 		/* Wait for operation to complete */
52493db446aSBoris Brezillon 		wait_op_done(host, useirq);
52593db446aSBoris Brezillon 	}
52693db446aSBoris Brezillon }
52793db446aSBoris Brezillon 
52893db446aSBoris Brezillon static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
52993db446aSBoris Brezillon {
53093db446aSBoris Brezillon 	/* fill address */
53193db446aSBoris Brezillon 	writel(addr, NFC_V3_FLASH_ADDR0);
53293db446aSBoris Brezillon 
53393db446aSBoris Brezillon 	/* send out address */
53493db446aSBoris Brezillon 	writel(NFC_ADDR, NFC_V3_LAUNCH);
53593db446aSBoris Brezillon 
53693db446aSBoris Brezillon 	wait_op_done(host, 0);
53793db446aSBoris Brezillon }
53893db446aSBoris Brezillon 
53993db446aSBoris Brezillon /* This function sends an address (or partial address) to the
54093db446aSBoris Brezillon  * NAND device. The address is used to select the source/destination for
54193db446aSBoris Brezillon  * a NAND command. */
54293db446aSBoris Brezillon static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
54393db446aSBoris Brezillon {
54493db446aSBoris Brezillon 	dev_dbg(host->dev, "send_addr(host, 0x%x %d)\n", addr, islast);
54593db446aSBoris Brezillon 
54693db446aSBoris Brezillon 	writew(addr, NFC_V1_V2_FLASH_ADDR);
54793db446aSBoris Brezillon 	writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
54893db446aSBoris Brezillon 
54993db446aSBoris Brezillon 	/* Wait for operation to complete */
55093db446aSBoris Brezillon 	wait_op_done(host, islast);
55193db446aSBoris Brezillon }
55293db446aSBoris Brezillon 
55393db446aSBoris Brezillon static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
55493db446aSBoris Brezillon {
55593db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
55693db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
55793db446aSBoris Brezillon 	uint32_t tmp;
55893db446aSBoris Brezillon 
55993db446aSBoris Brezillon 	tmp = readl(NFC_V3_CONFIG1);
56093db446aSBoris Brezillon 	tmp &= ~(7 << 4);
56193db446aSBoris Brezillon 	writel(tmp, NFC_V3_CONFIG1);
56293db446aSBoris Brezillon 
56393db446aSBoris Brezillon 	/* transfer data from NFC ram to nand */
56493db446aSBoris Brezillon 	writel(ops, NFC_V3_LAUNCH);
56593db446aSBoris Brezillon 
56693db446aSBoris Brezillon 	wait_op_done(host, false);
56793db446aSBoris Brezillon }
56893db446aSBoris Brezillon 
56993db446aSBoris Brezillon static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
57093db446aSBoris Brezillon {
57193db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
57293db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
57393db446aSBoris Brezillon 
57493db446aSBoris Brezillon 	/* NANDFC buffer 0 is used for page read/write */
57593db446aSBoris Brezillon 	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
57693db446aSBoris Brezillon 
57793db446aSBoris Brezillon 	writew(ops, NFC_V1_V2_CONFIG2);
57893db446aSBoris Brezillon 
57993db446aSBoris Brezillon 	/* Wait for operation to complete */
58093db446aSBoris Brezillon 	wait_op_done(host, true);
58193db446aSBoris Brezillon }
58293db446aSBoris Brezillon 
58393db446aSBoris Brezillon static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
58493db446aSBoris Brezillon {
58593db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
58693db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
58793db446aSBoris Brezillon 	int bufs, i;
58893db446aSBoris Brezillon 
58993db446aSBoris Brezillon 	if (mtd->writesize > 512)
59093db446aSBoris Brezillon 		bufs = 4;
59193db446aSBoris Brezillon 	else
59293db446aSBoris Brezillon 		bufs = 1;
59393db446aSBoris Brezillon 
59493db446aSBoris Brezillon 	for (i = 0; i < bufs; i++) {
59593db446aSBoris Brezillon 
59693db446aSBoris Brezillon 		/* NANDFC buffer 0 is used for page read/write */
59793db446aSBoris Brezillon 		writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
59893db446aSBoris Brezillon 
59993db446aSBoris Brezillon 		writew(ops, NFC_V1_V2_CONFIG2);
60093db446aSBoris Brezillon 
60193db446aSBoris Brezillon 		/* Wait for operation to complete */
60293db446aSBoris Brezillon 		wait_op_done(host, true);
60393db446aSBoris Brezillon 	}
60493db446aSBoris Brezillon }
60593db446aSBoris Brezillon 
60693db446aSBoris Brezillon static void send_read_id_v3(struct mxc_nand_host *host)
60793db446aSBoris Brezillon {
60893db446aSBoris Brezillon 	/* Read ID into main buffer */
60993db446aSBoris Brezillon 	writel(NFC_ID, NFC_V3_LAUNCH);
61093db446aSBoris Brezillon 
61193db446aSBoris Brezillon 	wait_op_done(host, true);
61293db446aSBoris Brezillon 
61393db446aSBoris Brezillon 	memcpy32_fromio(host->data_buf, host->main_area0, 16);
61493db446aSBoris Brezillon }
61593db446aSBoris Brezillon 
61693db446aSBoris Brezillon /* Request the NANDFC to perform a read of the NAND device ID. */
61793db446aSBoris Brezillon static void send_read_id_v1_v2(struct mxc_nand_host *host)
61893db446aSBoris Brezillon {
61993db446aSBoris Brezillon 	/* NANDFC buffer 0 is used for device ID output */
62093db446aSBoris Brezillon 	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
62193db446aSBoris Brezillon 
62293db446aSBoris Brezillon 	writew(NFC_ID, NFC_V1_V2_CONFIG2);
62393db446aSBoris Brezillon 
62493db446aSBoris Brezillon 	/* Wait for operation to complete */
62593db446aSBoris Brezillon 	wait_op_done(host, true);
62693db446aSBoris Brezillon 
62793db446aSBoris Brezillon 	memcpy32_fromio(host->data_buf, host->main_area0, 16);
62893db446aSBoris Brezillon }
62993db446aSBoris Brezillon 
63093db446aSBoris Brezillon static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
63193db446aSBoris Brezillon {
63293db446aSBoris Brezillon 	writew(NFC_STATUS, NFC_V3_LAUNCH);
63393db446aSBoris Brezillon 	wait_op_done(host, true);
63493db446aSBoris Brezillon 
63593db446aSBoris Brezillon 	return readl(NFC_V3_CONFIG1) >> 16;
63693db446aSBoris Brezillon }
63793db446aSBoris Brezillon 
63893db446aSBoris Brezillon /* This function requests the NANDFC to perform a read of the
63993db446aSBoris Brezillon  * NAND device status and returns the current status. */
64093db446aSBoris Brezillon static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
64193db446aSBoris Brezillon {
64293db446aSBoris Brezillon 	void __iomem *main_buf = host->main_area0;
64393db446aSBoris Brezillon 	uint32_t store;
64493db446aSBoris Brezillon 	uint16_t ret;
64593db446aSBoris Brezillon 
64693db446aSBoris Brezillon 	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
64793db446aSBoris Brezillon 
64893db446aSBoris Brezillon 	/*
64993db446aSBoris Brezillon 	 * The device status is stored in main_area0. To
65093db446aSBoris Brezillon 	 * prevent corruption of the buffer save the value
65193db446aSBoris Brezillon 	 * and restore it afterwards.
65293db446aSBoris Brezillon 	 */
65393db446aSBoris Brezillon 	store = readl(main_buf);
65493db446aSBoris Brezillon 
65593db446aSBoris Brezillon 	writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
65693db446aSBoris Brezillon 	wait_op_done(host, true);
65793db446aSBoris Brezillon 
65893db446aSBoris Brezillon 	ret = readw(main_buf);
65993db446aSBoris Brezillon 
66093db446aSBoris Brezillon 	writel(store, main_buf);
66193db446aSBoris Brezillon 
66293db446aSBoris Brezillon 	return ret;
66393db446aSBoris Brezillon }
66493db446aSBoris Brezillon 
66593db446aSBoris Brezillon static void mxc_nand_enable_hwecc_v1_v2(struct nand_chip *chip, bool enable)
66693db446aSBoris Brezillon {
66793db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
66893db446aSBoris Brezillon 	uint16_t config1;
66993db446aSBoris Brezillon 
670bace41f8SMiquel Raynal 	if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
67193db446aSBoris Brezillon 		return;
67293db446aSBoris Brezillon 
67393db446aSBoris Brezillon 	config1 = readw(NFC_V1_V2_CONFIG1);
67493db446aSBoris Brezillon 
67593db446aSBoris Brezillon 	if (enable)
67693db446aSBoris Brezillon 		config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
67793db446aSBoris Brezillon 	else
67893db446aSBoris Brezillon 		config1 &= ~NFC_V1_V2_CONFIG1_ECC_EN;
67993db446aSBoris Brezillon 
68093db446aSBoris Brezillon 	writew(config1, NFC_V1_V2_CONFIG1);
68193db446aSBoris Brezillon }
68293db446aSBoris Brezillon 
68393db446aSBoris Brezillon static void mxc_nand_enable_hwecc_v3(struct nand_chip *chip, bool enable)
68493db446aSBoris Brezillon {
68593db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
68693db446aSBoris Brezillon 	uint32_t config2;
68793db446aSBoris Brezillon 
688bace41f8SMiquel Raynal 	if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
68993db446aSBoris Brezillon 		return;
69093db446aSBoris Brezillon 
69193db446aSBoris Brezillon 	config2 = readl(NFC_V3_CONFIG2);
69293db446aSBoris Brezillon 
69393db446aSBoris Brezillon 	if (enable)
69493db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_ECC_EN;
69593db446aSBoris Brezillon 	else
69693db446aSBoris Brezillon 		config2 &= ~NFC_V3_CONFIG2_ECC_EN;
69793db446aSBoris Brezillon 
69893db446aSBoris Brezillon 	writel(config2, NFC_V3_CONFIG2);
69993db446aSBoris Brezillon }
70093db446aSBoris Brezillon 
70193db446aSBoris Brezillon /* This functions is used by upper layer to checks if device is ready */
70250a487e7SBoris Brezillon static int mxc_nand_dev_ready(struct nand_chip *chip)
70393db446aSBoris Brezillon {
70493db446aSBoris Brezillon 	/*
70593db446aSBoris Brezillon 	 * NFC handles R/B internally. Therefore, this function
70693db446aSBoris Brezillon 	 * always returns status as ready.
70793db446aSBoris Brezillon 	 */
70893db446aSBoris Brezillon 	return 1;
70993db446aSBoris Brezillon }
71093db446aSBoris Brezillon 
71193db446aSBoris Brezillon static int mxc_nand_read_page_v1(struct nand_chip *chip, void *buf, void *oob,
71293db446aSBoris Brezillon 				 bool ecc, int page)
71393db446aSBoris Brezillon {
71493db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
71593db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
71693db446aSBoris Brezillon 	unsigned int bitflips_corrected = 0;
71793db446aSBoris Brezillon 	int no_subpages;
71893db446aSBoris Brezillon 	int i;
71993db446aSBoris Brezillon 
72093db446aSBoris Brezillon 	host->devtype_data->enable_hwecc(chip, ecc);
72193db446aSBoris Brezillon 
72293db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_READ0, false);
72393db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, 0, page);
72493db446aSBoris Brezillon 
72593db446aSBoris Brezillon 	if (mtd->writesize > 512)
72693db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, NAND_CMD_READSTART, true);
72793db446aSBoris Brezillon 
72893db446aSBoris Brezillon 	no_subpages = mtd->writesize >> 9;
72993db446aSBoris Brezillon 
73093db446aSBoris Brezillon 	for (i = 0; i < no_subpages; i++) {
73193db446aSBoris Brezillon 		uint16_t ecc_stats;
73293db446aSBoris Brezillon 
73393db446aSBoris Brezillon 		/* NANDFC buffer 0 is used for page read/write */
73493db446aSBoris Brezillon 		writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
73593db446aSBoris Brezillon 
73693db446aSBoris Brezillon 		writew(NFC_OUTPUT, NFC_V1_V2_CONFIG2);
73793db446aSBoris Brezillon 
73893db446aSBoris Brezillon 		/* Wait for operation to complete */
73993db446aSBoris Brezillon 		wait_op_done(host, true);
74093db446aSBoris Brezillon 
74193db446aSBoris Brezillon 		ecc_stats = get_ecc_status_v1(host);
74293db446aSBoris Brezillon 
74393db446aSBoris Brezillon 		ecc_stats >>= 2;
74493db446aSBoris Brezillon 
74593db446aSBoris Brezillon 		if (buf && ecc) {
74693db446aSBoris Brezillon 			switch (ecc_stats & 0x3) {
74793db446aSBoris Brezillon 			case 0:
74893db446aSBoris Brezillon 			default:
74993db446aSBoris Brezillon 				break;
75093db446aSBoris Brezillon 			case 1:
75193db446aSBoris Brezillon 				mtd->ecc_stats.corrected++;
75293db446aSBoris Brezillon 				bitflips_corrected = 1;
75393db446aSBoris Brezillon 				break;
75493db446aSBoris Brezillon 			case 2:
75593db446aSBoris Brezillon 				mtd->ecc_stats.failed++;
75693db446aSBoris Brezillon 				break;
75793db446aSBoris Brezillon 			}
75893db446aSBoris Brezillon 		}
75993db446aSBoris Brezillon 	}
76093db446aSBoris Brezillon 
76193db446aSBoris Brezillon 	if (buf)
76293db446aSBoris Brezillon 		memcpy32_fromio(buf, host->main_area0, mtd->writesize);
76393db446aSBoris Brezillon 	if (oob)
76493db446aSBoris Brezillon 		copy_spare(mtd, true, oob);
76593db446aSBoris Brezillon 
76693db446aSBoris Brezillon 	return bitflips_corrected;
76793db446aSBoris Brezillon }
76893db446aSBoris Brezillon 
76993db446aSBoris Brezillon static int mxc_nand_read_page_v2_v3(struct nand_chip *chip, void *buf,
77093db446aSBoris Brezillon 				    void *oob, bool ecc, int page)
77193db446aSBoris Brezillon {
77293db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
77393db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
77493db446aSBoris Brezillon 	unsigned int max_bitflips = 0;
77593db446aSBoris Brezillon 	u32 ecc_stat, err;
77693db446aSBoris Brezillon 	int no_subpages;
77793db446aSBoris Brezillon 	u8 ecc_bit_mask, err_limit;
77893db446aSBoris Brezillon 
77993db446aSBoris Brezillon 	host->devtype_data->enable_hwecc(chip, ecc);
78093db446aSBoris Brezillon 
78193db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_READ0, false);
78293db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, 0, page);
78393db446aSBoris Brezillon 
78493db446aSBoris Brezillon 	if (mtd->writesize > 512)
78593db446aSBoris Brezillon 		host->devtype_data->send_cmd(host,
78693db446aSBoris Brezillon 				NAND_CMD_READSTART, true);
78793db446aSBoris Brezillon 
78893db446aSBoris Brezillon 	host->devtype_data->send_page(mtd, NFC_OUTPUT);
78993db446aSBoris Brezillon 
79093db446aSBoris Brezillon 	if (buf)
79193db446aSBoris Brezillon 		memcpy32_fromio(buf, host->main_area0, mtd->writesize);
79293db446aSBoris Brezillon 	if (oob)
79393db446aSBoris Brezillon 		copy_spare(mtd, true, oob);
79493db446aSBoris Brezillon 
79593db446aSBoris Brezillon 	ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
79693db446aSBoris Brezillon 	err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
79793db446aSBoris Brezillon 
79893db446aSBoris Brezillon 	no_subpages = mtd->writesize >> 9;
79993db446aSBoris Brezillon 
80093db446aSBoris Brezillon 	ecc_stat = host->devtype_data->get_ecc_status(host);
80193db446aSBoris Brezillon 
80293db446aSBoris Brezillon 	do {
80393db446aSBoris Brezillon 		err = ecc_stat & ecc_bit_mask;
80493db446aSBoris Brezillon 		if (err > err_limit) {
80593db446aSBoris Brezillon 			mtd->ecc_stats.failed++;
80693db446aSBoris Brezillon 		} else {
80793db446aSBoris Brezillon 			mtd->ecc_stats.corrected += err;
80893db446aSBoris Brezillon 			max_bitflips = max_t(unsigned int, max_bitflips, err);
80993db446aSBoris Brezillon 		}
81093db446aSBoris Brezillon 
81193db446aSBoris Brezillon 		ecc_stat >>= 4;
81293db446aSBoris Brezillon 	} while (--no_subpages);
81393db446aSBoris Brezillon 
81493db446aSBoris Brezillon 	return max_bitflips;
81593db446aSBoris Brezillon }
81693db446aSBoris Brezillon 
817b9761687SBoris Brezillon static int mxc_nand_read_page(struct nand_chip *chip, uint8_t *buf,
818b9761687SBoris Brezillon 			      int oob_required, int page)
81993db446aSBoris Brezillon {
82093db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
82193db446aSBoris Brezillon 	void *oob_buf;
82293db446aSBoris Brezillon 
82393db446aSBoris Brezillon 	if (oob_required)
82493db446aSBoris Brezillon 		oob_buf = chip->oob_poi;
82593db446aSBoris Brezillon 	else
82693db446aSBoris Brezillon 		oob_buf = NULL;
82793db446aSBoris Brezillon 
82893db446aSBoris Brezillon 	return host->devtype_data->read_page(chip, buf, oob_buf, 1, page);
82993db446aSBoris Brezillon }
83093db446aSBoris Brezillon 
831b9761687SBoris Brezillon static int mxc_nand_read_page_raw(struct nand_chip *chip, uint8_t *buf,
832b9761687SBoris Brezillon 				  int oob_required, int page)
83393db446aSBoris Brezillon {
83493db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
83593db446aSBoris Brezillon 	void *oob_buf;
83693db446aSBoris Brezillon 
83793db446aSBoris Brezillon 	if (oob_required)
83893db446aSBoris Brezillon 		oob_buf = chip->oob_poi;
83993db446aSBoris Brezillon 	else
84093db446aSBoris Brezillon 		oob_buf = NULL;
84193db446aSBoris Brezillon 
84293db446aSBoris Brezillon 	return host->devtype_data->read_page(chip, buf, oob_buf, 0, page);
84393db446aSBoris Brezillon }
84493db446aSBoris Brezillon 
845b9761687SBoris Brezillon static int mxc_nand_read_oob(struct nand_chip *chip, int page)
84693db446aSBoris Brezillon {
84793db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
84893db446aSBoris Brezillon 
84993db446aSBoris Brezillon 	return host->devtype_data->read_page(chip, NULL, chip->oob_poi, 0,
85093db446aSBoris Brezillon 					     page);
85193db446aSBoris Brezillon }
85293db446aSBoris Brezillon 
85393db446aSBoris Brezillon static int mxc_nand_write_page(struct nand_chip *chip, const uint8_t *buf,
85493db446aSBoris Brezillon 			       bool ecc, int page)
85593db446aSBoris Brezillon {
85693db446aSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
85793db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
85893db446aSBoris Brezillon 
85993db446aSBoris Brezillon 	host->devtype_data->enable_hwecc(chip, ecc);
86093db446aSBoris Brezillon 
86193db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_SEQIN, false);
86293db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, 0, page);
86393db446aSBoris Brezillon 
86493db446aSBoris Brezillon 	memcpy32_toio(host->main_area0, buf, mtd->writesize);
86593db446aSBoris Brezillon 	copy_spare(mtd, false, chip->oob_poi);
86693db446aSBoris Brezillon 
86793db446aSBoris Brezillon 	host->devtype_data->send_page(mtd, NFC_INPUT);
86893db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_PAGEPROG, true);
86993db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, 0, page);
87093db446aSBoris Brezillon 
87193db446aSBoris Brezillon 	return 0;
87293db446aSBoris Brezillon }
87393db446aSBoris Brezillon 
874767eb6fbSBoris Brezillon static int mxc_nand_write_page_ecc(struct nand_chip *chip, const uint8_t *buf,
875767eb6fbSBoris Brezillon 				   int oob_required, int page)
87693db446aSBoris Brezillon {
87793db446aSBoris Brezillon 	return mxc_nand_write_page(chip, buf, true, page);
87893db446aSBoris Brezillon }
87993db446aSBoris Brezillon 
880767eb6fbSBoris Brezillon static int mxc_nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
881767eb6fbSBoris Brezillon 				   int oob_required, int page)
88293db446aSBoris Brezillon {
88393db446aSBoris Brezillon 	return mxc_nand_write_page(chip, buf, false, page);
88493db446aSBoris Brezillon }
88593db446aSBoris Brezillon 
886767eb6fbSBoris Brezillon static int mxc_nand_write_oob(struct nand_chip *chip, int page)
88793db446aSBoris Brezillon {
888767eb6fbSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
88993db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
89093db446aSBoris Brezillon 
89193db446aSBoris Brezillon 	memset(host->data_buf, 0xff, mtd->writesize);
89293db446aSBoris Brezillon 
89393db446aSBoris Brezillon 	return mxc_nand_write_page(chip, host->data_buf, false, page);
89493db446aSBoris Brezillon }
89593db446aSBoris Brezillon 
8967e534323SBoris Brezillon static u_char mxc_nand_read_byte(struct nand_chip *nand_chip)
89793db446aSBoris Brezillon {
89893db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
89993db446aSBoris Brezillon 	uint8_t ret;
90093db446aSBoris Brezillon 
90193db446aSBoris Brezillon 	/* Check for status request */
90293db446aSBoris Brezillon 	if (host->status_request)
90393db446aSBoris Brezillon 		return host->devtype_data->get_dev_status(host) & 0xFF;
90493db446aSBoris Brezillon 
90593db446aSBoris Brezillon 	if (nand_chip->options & NAND_BUSWIDTH_16) {
90693db446aSBoris Brezillon 		/* only take the lower byte of each word */
90793db446aSBoris Brezillon 		ret = *(uint16_t *)(host->data_buf + host->buf_start);
90893db446aSBoris Brezillon 
90993db446aSBoris Brezillon 		host->buf_start += 2;
91093db446aSBoris Brezillon 	} else {
91193db446aSBoris Brezillon 		ret = *(uint8_t *)(host->data_buf + host->buf_start);
91293db446aSBoris Brezillon 		host->buf_start++;
91393db446aSBoris Brezillon 	}
91493db446aSBoris Brezillon 
91593db446aSBoris Brezillon 	dev_dbg(host->dev, "%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start);
91693db446aSBoris Brezillon 	return ret;
91793db446aSBoris Brezillon }
91893db446aSBoris Brezillon 
91993db446aSBoris Brezillon /* Write data of length len to buffer buf. The data to be
92093db446aSBoris Brezillon  * written on NAND Flash is first copied to RAMbuffer. After the Data Input
92193db446aSBoris Brezillon  * Operation by the NFC, the data is written to NAND Flash */
922c0739d85SBoris Brezillon static void mxc_nand_write_buf(struct nand_chip *nand_chip, const u_char *buf,
923c0739d85SBoris Brezillon 			       int len)
92493db446aSBoris Brezillon {
925c0739d85SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(nand_chip);
92693db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
92793db446aSBoris Brezillon 	u16 col = host->buf_start;
92893db446aSBoris Brezillon 	int n = mtd->oobsize + mtd->writesize - col;
92993db446aSBoris Brezillon 
93093db446aSBoris Brezillon 	n = min(n, len);
93193db446aSBoris Brezillon 
93293db446aSBoris Brezillon 	memcpy(host->data_buf + col, buf, n);
93393db446aSBoris Brezillon 
93493db446aSBoris Brezillon 	host->buf_start += n;
93593db446aSBoris Brezillon }
93693db446aSBoris Brezillon 
93793db446aSBoris Brezillon /* Read the data buffer from the NAND Flash. To read the data from NAND
93893db446aSBoris Brezillon  * Flash first the data output cycle is initiated by the NFC, which copies
93993db446aSBoris Brezillon  * the data to RAMbuffer. This data of length len is then copied to buffer buf.
94093db446aSBoris Brezillon  */
9417e534323SBoris Brezillon static void mxc_nand_read_buf(struct nand_chip *nand_chip, u_char *buf,
9427e534323SBoris Brezillon 			      int len)
94393db446aSBoris Brezillon {
9447e534323SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(nand_chip);
94593db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
94693db446aSBoris Brezillon 	u16 col = host->buf_start;
94793db446aSBoris Brezillon 	int n = mtd->oobsize + mtd->writesize - col;
94893db446aSBoris Brezillon 
94993db446aSBoris Brezillon 	n = min(n, len);
95093db446aSBoris Brezillon 
95193db446aSBoris Brezillon 	memcpy(buf, host->data_buf + col, n);
95293db446aSBoris Brezillon 
95393db446aSBoris Brezillon 	host->buf_start += n;
95493db446aSBoris Brezillon }
95593db446aSBoris Brezillon 
95693db446aSBoris Brezillon /* This function is used by upper layer for select and
95793db446aSBoris Brezillon  * deselect of the NAND chip */
958758b56f5SBoris Brezillon static void mxc_nand_select_chip_v1_v3(struct nand_chip *nand_chip, int chip)
95993db446aSBoris Brezillon {
96093db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
96193db446aSBoris Brezillon 
96293db446aSBoris Brezillon 	if (chip == -1) {
96393db446aSBoris Brezillon 		/* Disable the NFC clock */
96493db446aSBoris Brezillon 		if (host->clk_act) {
96593db446aSBoris Brezillon 			clk_disable_unprepare(host->clk);
96693db446aSBoris Brezillon 			host->clk_act = 0;
96793db446aSBoris Brezillon 		}
96893db446aSBoris Brezillon 		return;
96993db446aSBoris Brezillon 	}
97093db446aSBoris Brezillon 
97193db446aSBoris Brezillon 	if (!host->clk_act) {
97293db446aSBoris Brezillon 		/* Enable the NFC clock */
97393db446aSBoris Brezillon 		clk_prepare_enable(host->clk);
97493db446aSBoris Brezillon 		host->clk_act = 1;
97593db446aSBoris Brezillon 	}
97693db446aSBoris Brezillon }
97793db446aSBoris Brezillon 
978758b56f5SBoris Brezillon static void mxc_nand_select_chip_v2(struct nand_chip *nand_chip, int chip)
97993db446aSBoris Brezillon {
98093db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
98193db446aSBoris Brezillon 
98293db446aSBoris Brezillon 	if (chip == -1) {
98393db446aSBoris Brezillon 		/* Disable the NFC clock */
98493db446aSBoris Brezillon 		if (host->clk_act) {
98593db446aSBoris Brezillon 			clk_disable_unprepare(host->clk);
98693db446aSBoris Brezillon 			host->clk_act = 0;
98793db446aSBoris Brezillon 		}
98893db446aSBoris Brezillon 		return;
98993db446aSBoris Brezillon 	}
99093db446aSBoris Brezillon 
99193db446aSBoris Brezillon 	if (!host->clk_act) {
99293db446aSBoris Brezillon 		/* Enable the NFC clock */
99393db446aSBoris Brezillon 		clk_prepare_enable(host->clk);
99493db446aSBoris Brezillon 		host->clk_act = 1;
99593db446aSBoris Brezillon 	}
99693db446aSBoris Brezillon 
99793db446aSBoris Brezillon 	host->active_cs = chip;
99893db446aSBoris Brezillon 	writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
99993db446aSBoris Brezillon }
100093db446aSBoris Brezillon 
100193db446aSBoris Brezillon #define MXC_V1_ECCBYTES		5
100293db446aSBoris Brezillon 
100393db446aSBoris Brezillon static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
100493db446aSBoris Brezillon 				struct mtd_oob_region *oobregion)
100593db446aSBoris Brezillon {
100693db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
100793db446aSBoris Brezillon 
100893db446aSBoris Brezillon 	if (section >= nand_chip->ecc.steps)
100993db446aSBoris Brezillon 		return -ERANGE;
101093db446aSBoris Brezillon 
101193db446aSBoris Brezillon 	oobregion->offset = (section * 16) + 6;
101293db446aSBoris Brezillon 	oobregion->length = MXC_V1_ECCBYTES;
101393db446aSBoris Brezillon 
101493db446aSBoris Brezillon 	return 0;
101593db446aSBoris Brezillon }
101693db446aSBoris Brezillon 
101793db446aSBoris Brezillon static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
101893db446aSBoris Brezillon 				 struct mtd_oob_region *oobregion)
101993db446aSBoris Brezillon {
102093db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
102193db446aSBoris Brezillon 
102293db446aSBoris Brezillon 	if (section > nand_chip->ecc.steps)
102393db446aSBoris Brezillon 		return -ERANGE;
102493db446aSBoris Brezillon 
102593db446aSBoris Brezillon 	if (!section) {
102693db446aSBoris Brezillon 		if (mtd->writesize <= 512) {
102793db446aSBoris Brezillon 			oobregion->offset = 0;
102893db446aSBoris Brezillon 			oobregion->length = 5;
102993db446aSBoris Brezillon 		} else {
103093db446aSBoris Brezillon 			oobregion->offset = 2;
103193db446aSBoris Brezillon 			oobregion->length = 4;
103293db446aSBoris Brezillon 		}
103393db446aSBoris Brezillon 	} else {
103493db446aSBoris Brezillon 		oobregion->offset = ((section - 1) * 16) + MXC_V1_ECCBYTES + 6;
103593db446aSBoris Brezillon 		if (section < nand_chip->ecc.steps)
103693db446aSBoris Brezillon 			oobregion->length = (section * 16) + 6 -
103793db446aSBoris Brezillon 					    oobregion->offset;
103893db446aSBoris Brezillon 		else
103993db446aSBoris Brezillon 			oobregion->length = mtd->oobsize - oobregion->offset;
104093db446aSBoris Brezillon 	}
104193db446aSBoris Brezillon 
104293db446aSBoris Brezillon 	return 0;
104393db446aSBoris Brezillon }
104493db446aSBoris Brezillon 
104593db446aSBoris Brezillon static const struct mtd_ooblayout_ops mxc_v1_ooblayout_ops = {
104693db446aSBoris Brezillon 	.ecc = mxc_v1_ooblayout_ecc,
104793db446aSBoris Brezillon 	.free = mxc_v1_ooblayout_free,
104893db446aSBoris Brezillon };
104993db446aSBoris Brezillon 
105093db446aSBoris Brezillon static int mxc_v2_ooblayout_ecc(struct mtd_info *mtd, int section,
105193db446aSBoris Brezillon 				struct mtd_oob_region *oobregion)
105293db446aSBoris Brezillon {
105393db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
105493db446aSBoris Brezillon 	int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26;
105593db446aSBoris Brezillon 
105693db446aSBoris Brezillon 	if (section >= nand_chip->ecc.steps)
105793db446aSBoris Brezillon 		return -ERANGE;
105893db446aSBoris Brezillon 
105993db446aSBoris Brezillon 	oobregion->offset = (section * stepsize) + 7;
106093db446aSBoris Brezillon 	oobregion->length = nand_chip->ecc.bytes;
106193db446aSBoris Brezillon 
106293db446aSBoris Brezillon 	return 0;
106393db446aSBoris Brezillon }
106493db446aSBoris Brezillon 
106593db446aSBoris Brezillon static int mxc_v2_ooblayout_free(struct mtd_info *mtd, int section,
106693db446aSBoris Brezillon 				 struct mtd_oob_region *oobregion)
106793db446aSBoris Brezillon {
106893db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
106993db446aSBoris Brezillon 	int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26;
107093db446aSBoris Brezillon 
107193db446aSBoris Brezillon 	if (section >= nand_chip->ecc.steps)
107293db446aSBoris Brezillon 		return -ERANGE;
107393db446aSBoris Brezillon 
107493db446aSBoris Brezillon 	if (!section) {
107593db446aSBoris Brezillon 		if (mtd->writesize <= 512) {
107693db446aSBoris Brezillon 			oobregion->offset = 0;
107793db446aSBoris Brezillon 			oobregion->length = 5;
107893db446aSBoris Brezillon 		} else {
107993db446aSBoris Brezillon 			oobregion->offset = 2;
108093db446aSBoris Brezillon 			oobregion->length = 4;
108193db446aSBoris Brezillon 		}
108293db446aSBoris Brezillon 	} else {
108393db446aSBoris Brezillon 		oobregion->offset = section * stepsize;
108493db446aSBoris Brezillon 		oobregion->length = 7;
108593db446aSBoris Brezillon 	}
108693db446aSBoris Brezillon 
108793db446aSBoris Brezillon 	return 0;
108893db446aSBoris Brezillon }
108993db446aSBoris Brezillon 
109093db446aSBoris Brezillon static const struct mtd_ooblayout_ops mxc_v2_ooblayout_ops = {
109193db446aSBoris Brezillon 	.ecc = mxc_v2_ooblayout_ecc,
109293db446aSBoris Brezillon 	.free = mxc_v2_ooblayout_free,
109393db446aSBoris Brezillon };
109493db446aSBoris Brezillon 
109593db446aSBoris Brezillon /*
109693db446aSBoris Brezillon  * v2 and v3 type controllers can do 4bit or 8bit ecc depending
109793db446aSBoris Brezillon  * on how much oob the nand chip has. For 8bit ecc we need at least
109893db446aSBoris Brezillon  * 26 bytes of oob data per 512 byte block.
109993db446aSBoris Brezillon  */
110093db446aSBoris Brezillon static int get_eccsize(struct mtd_info *mtd)
110193db446aSBoris Brezillon {
110293db446aSBoris Brezillon 	int oobbytes_per_512 = 0;
110393db446aSBoris Brezillon 
110493db446aSBoris Brezillon 	oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
110593db446aSBoris Brezillon 
110693db446aSBoris Brezillon 	if (oobbytes_per_512 < 26)
110793db446aSBoris Brezillon 		return 4;
110893db446aSBoris Brezillon 	else
110993db446aSBoris Brezillon 		return 8;
111093db446aSBoris Brezillon }
111193db446aSBoris Brezillon 
111293db446aSBoris Brezillon static void preset_v1(struct mtd_info *mtd)
111393db446aSBoris Brezillon {
111493db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
111593db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
111693db446aSBoris Brezillon 	uint16_t config1 = 0;
111793db446aSBoris Brezillon 
1118bace41f8SMiquel Raynal 	if (nand_chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST &&
1119bace41f8SMiquel Raynal 	    mtd->writesize)
112093db446aSBoris Brezillon 		config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
112193db446aSBoris Brezillon 
112293db446aSBoris Brezillon 	if (!host->devtype_data->irqpending_quirk)
112393db446aSBoris Brezillon 		config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
112493db446aSBoris Brezillon 
112593db446aSBoris Brezillon 	host->eccsize = 1;
112693db446aSBoris Brezillon 
112793db446aSBoris Brezillon 	writew(config1, NFC_V1_V2_CONFIG1);
112893db446aSBoris Brezillon 	/* preset operation */
112993db446aSBoris Brezillon 
113093db446aSBoris Brezillon 	/* Unlock the internal RAM Buffer */
113193db446aSBoris Brezillon 	writew(0x2, NFC_V1_V2_CONFIG);
113293db446aSBoris Brezillon 
113393db446aSBoris Brezillon 	/* Blocks to be unlocked */
113493db446aSBoris Brezillon 	writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
113593db446aSBoris Brezillon 	writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
113693db446aSBoris Brezillon 
113793db446aSBoris Brezillon 	/* Unlock Block Command for given address range */
113893db446aSBoris Brezillon 	writew(0x4, NFC_V1_V2_WRPROT);
113993db446aSBoris Brezillon }
114093db446aSBoris Brezillon 
11414c46667bSMiquel Raynal static int mxc_nand_v2_setup_interface(struct nand_chip *chip, int csline,
11424c46667bSMiquel Raynal 				       const struct nand_interface_config *conf)
114393db446aSBoris Brezillon {
1144858838b8SBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
114593db446aSBoris Brezillon 	int tRC_min_ns, tRC_ps, ret;
114693db446aSBoris Brezillon 	unsigned long rate, rate_round;
114793db446aSBoris Brezillon 	const struct nand_sdr_timings *timings;
114893db446aSBoris Brezillon 	u16 config1;
114993db446aSBoris Brezillon 
115093db446aSBoris Brezillon 	timings = nand_get_sdr_timings(conf);
115193db446aSBoris Brezillon 	if (IS_ERR(timings))
115293db446aSBoris Brezillon 		return -ENOTSUPP;
115393db446aSBoris Brezillon 
115493db446aSBoris Brezillon 	config1 = readw(NFC_V1_V2_CONFIG1);
115593db446aSBoris Brezillon 
115693db446aSBoris Brezillon 	tRC_min_ns = timings->tRC_min / 1000;
115793db446aSBoris Brezillon 	rate = 1000000000 / tRC_min_ns;
115893db446aSBoris Brezillon 
115993db446aSBoris Brezillon 	/*
116093db446aSBoris Brezillon 	 * For tRC < 30ns we have to use EDO mode. In this case the controller
116193db446aSBoris Brezillon 	 * does one access per clock cycle. Otherwise the controller does one
116293db446aSBoris Brezillon 	 * access in two clock cycles, thus we have to double the rate to the
116393db446aSBoris Brezillon 	 * controller.
116493db446aSBoris Brezillon 	 */
116593db446aSBoris Brezillon 	if (tRC_min_ns < 30) {
116693db446aSBoris Brezillon 		rate_round = clk_round_rate(host->clk, rate);
116793db446aSBoris Brezillon 		config1 |= NFC_V2_CONFIG1_ONE_CYCLE;
116893db446aSBoris Brezillon 		tRC_ps = 1000000000 / (rate_round / 1000);
116993db446aSBoris Brezillon 	} else {
117093db446aSBoris Brezillon 		rate *= 2;
117193db446aSBoris Brezillon 		rate_round = clk_round_rate(host->clk, rate);
117293db446aSBoris Brezillon 		config1 &= ~NFC_V2_CONFIG1_ONE_CYCLE;
117393db446aSBoris Brezillon 		tRC_ps = 1000000000 / (rate_round / 1000 / 2);
117493db446aSBoris Brezillon 	}
117593db446aSBoris Brezillon 
117693db446aSBoris Brezillon 	/*
117793db446aSBoris Brezillon 	 * The timing values compared against are from the i.MX25 Automotive
117893db446aSBoris Brezillon 	 * datasheet, Table 50. NFC Timing Parameters
117993db446aSBoris Brezillon 	 */
118093db446aSBoris Brezillon 	if (timings->tCLS_min > tRC_ps - 1000 ||
118193db446aSBoris Brezillon 	    timings->tCLH_min > tRC_ps - 2000 ||
118293db446aSBoris Brezillon 	    timings->tCS_min > tRC_ps - 1000 ||
118393db446aSBoris Brezillon 	    timings->tCH_min > tRC_ps - 2000 ||
118493db446aSBoris Brezillon 	    timings->tWP_min > tRC_ps - 1500 ||
118593db446aSBoris Brezillon 	    timings->tALS_min > tRC_ps ||
118693db446aSBoris Brezillon 	    timings->tALH_min > tRC_ps - 3000 ||
118793db446aSBoris Brezillon 	    timings->tDS_min > tRC_ps ||
118893db446aSBoris Brezillon 	    timings->tDH_min > tRC_ps - 5000 ||
118993db446aSBoris Brezillon 	    timings->tWC_min > 2 * tRC_ps ||
119093db446aSBoris Brezillon 	    timings->tWH_min > tRC_ps - 2500 ||
119193db446aSBoris Brezillon 	    timings->tRR_min > 6 * tRC_ps ||
119293db446aSBoris Brezillon 	    timings->tRP_min > 3 * tRC_ps / 2 ||
119393db446aSBoris Brezillon 	    timings->tRC_min > 2 * tRC_ps ||
119493db446aSBoris Brezillon 	    timings->tREH_min > (tRC_ps / 2) - 2500) {
119593db446aSBoris Brezillon 		dev_dbg(host->dev, "Timing out of bounds\n");
119693db446aSBoris Brezillon 		return -EINVAL;
119793db446aSBoris Brezillon 	}
119893db446aSBoris Brezillon 
119993db446aSBoris Brezillon 	if (csline == NAND_DATA_IFACE_CHECK_ONLY)
120093db446aSBoris Brezillon 		return 0;
120193db446aSBoris Brezillon 
120293db446aSBoris Brezillon 	ret = clk_set_rate(host->clk, rate);
120393db446aSBoris Brezillon 	if (ret)
120493db446aSBoris Brezillon 		return ret;
120593db446aSBoris Brezillon 
120693db446aSBoris Brezillon 	writew(config1, NFC_V1_V2_CONFIG1);
120793db446aSBoris Brezillon 
120893db446aSBoris Brezillon 	dev_dbg(host->dev, "Setting rate to %ldHz, %s mode\n", rate_round,
120993db446aSBoris Brezillon 		config1 & NFC_V2_CONFIG1_ONE_CYCLE ? "One cycle (EDO)" :
121093db446aSBoris Brezillon 		"normal");
121193db446aSBoris Brezillon 
121293db446aSBoris Brezillon 	return 0;
121393db446aSBoris Brezillon }
121493db446aSBoris Brezillon 
121593db446aSBoris Brezillon static void preset_v2(struct mtd_info *mtd)
121693db446aSBoris Brezillon {
121793db446aSBoris Brezillon 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
121893db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
121993db446aSBoris Brezillon 	uint16_t config1 = 0;
122093db446aSBoris Brezillon 
122193db446aSBoris Brezillon 	config1 |= NFC_V2_CONFIG1_FP_INT;
122293db446aSBoris Brezillon 
122393db446aSBoris Brezillon 	if (!host->devtype_data->irqpending_quirk)
122493db446aSBoris Brezillon 		config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
122593db446aSBoris Brezillon 
122693db446aSBoris Brezillon 	if (mtd->writesize) {
122793db446aSBoris Brezillon 		uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
122893db446aSBoris Brezillon 
1229bace41f8SMiquel Raynal 		if (nand_chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST)
123093db446aSBoris Brezillon 			config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
123193db446aSBoris Brezillon 
123293db446aSBoris Brezillon 		host->eccsize = get_eccsize(mtd);
123393db446aSBoris Brezillon 		if (host->eccsize == 4)
123493db446aSBoris Brezillon 			config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
123593db446aSBoris Brezillon 
123693db446aSBoris Brezillon 		config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
123793db446aSBoris Brezillon 	} else {
123893db446aSBoris Brezillon 		host->eccsize = 1;
123993db446aSBoris Brezillon 	}
124093db446aSBoris Brezillon 
124193db446aSBoris Brezillon 	writew(config1, NFC_V1_V2_CONFIG1);
124293db446aSBoris Brezillon 	/* preset operation */
124393db446aSBoris Brezillon 
12443f77f244SMartin Kaiser 	/* spare area size in 16-bit half-words */
12453f77f244SMartin Kaiser 	writew(mtd->oobsize / 2, NFC_V21_RSLTSPARE_AREA);
12463f77f244SMartin Kaiser 
124793db446aSBoris Brezillon 	/* Unlock the internal RAM Buffer */
124893db446aSBoris Brezillon 	writew(0x2, NFC_V1_V2_CONFIG);
124993db446aSBoris Brezillon 
125093db446aSBoris Brezillon 	/* Blocks to be unlocked */
125193db446aSBoris Brezillon 	writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
125293db446aSBoris Brezillon 	writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
125393db446aSBoris Brezillon 	writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
125493db446aSBoris Brezillon 	writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
125593db446aSBoris Brezillon 	writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
125693db446aSBoris Brezillon 	writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
125793db446aSBoris Brezillon 	writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
125893db446aSBoris Brezillon 	writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
125993db446aSBoris Brezillon 
126093db446aSBoris Brezillon 	/* Unlock Block Command for given address range */
126193db446aSBoris Brezillon 	writew(0x4, NFC_V1_V2_WRPROT);
126293db446aSBoris Brezillon }
126393db446aSBoris Brezillon 
126493db446aSBoris Brezillon static void preset_v3(struct mtd_info *mtd)
126593db446aSBoris Brezillon {
126693db446aSBoris Brezillon 	struct nand_chip *chip = mtd_to_nand(mtd);
126793db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
126893db446aSBoris Brezillon 	uint32_t config2, config3;
126993db446aSBoris Brezillon 	int i, addr_phases;
127093db446aSBoris Brezillon 
127193db446aSBoris Brezillon 	writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
127293db446aSBoris Brezillon 	writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
127393db446aSBoris Brezillon 
127493db446aSBoris Brezillon 	/* Unlock the internal RAM Buffer */
127593db446aSBoris Brezillon 	writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
127693db446aSBoris Brezillon 			NFC_V3_WRPROT);
127793db446aSBoris Brezillon 
127893db446aSBoris Brezillon 	/* Blocks to be unlocked */
127993db446aSBoris Brezillon 	for (i = 0; i < NAND_MAX_CHIPS; i++)
128093db446aSBoris Brezillon 		writel(0xffff << 16, NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
128193db446aSBoris Brezillon 
128293db446aSBoris Brezillon 	writel(0, NFC_V3_IPC);
128393db446aSBoris Brezillon 
128493db446aSBoris Brezillon 	config2 = NFC_V3_CONFIG2_ONE_CYCLE |
128593db446aSBoris Brezillon 		NFC_V3_CONFIG2_2CMD_PHASES |
128693db446aSBoris Brezillon 		NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
128793db446aSBoris Brezillon 		NFC_V3_CONFIG2_ST_CMD(0x70) |
128893db446aSBoris Brezillon 		NFC_V3_CONFIG2_INT_MSK |
128993db446aSBoris Brezillon 		NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
129093db446aSBoris Brezillon 
129193db446aSBoris Brezillon 	addr_phases = fls(chip->pagemask) >> 3;
129293db446aSBoris Brezillon 
129393db446aSBoris Brezillon 	if (mtd->writesize == 2048) {
129493db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_PS_2048;
129593db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
129693db446aSBoris Brezillon 	} else if (mtd->writesize == 4096) {
129793db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_PS_4096;
129893db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
129993db446aSBoris Brezillon 	} else {
130093db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_PS_512;
130193db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
130293db446aSBoris Brezillon 	}
130393db446aSBoris Brezillon 
130493db446aSBoris Brezillon 	if (mtd->writesize) {
1305bace41f8SMiquel Raynal 		if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST)
130693db446aSBoris Brezillon 			config2 |= NFC_V3_CONFIG2_ECC_EN;
130793db446aSBoris Brezillon 
130893db446aSBoris Brezillon 		config2 |= NFC_V3_CONFIG2_PPB(
130993db446aSBoris Brezillon 				ffs(mtd->erasesize / mtd->writesize) - 6,
131093db446aSBoris Brezillon 				host->devtype_data->ppb_shift);
131193db446aSBoris Brezillon 		host->eccsize = get_eccsize(mtd);
131293db446aSBoris Brezillon 		if (host->eccsize == 8)
131393db446aSBoris Brezillon 			config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
131493db446aSBoris Brezillon 	}
131593db446aSBoris Brezillon 
131693db446aSBoris Brezillon 	writel(config2, NFC_V3_CONFIG2);
131793db446aSBoris Brezillon 
131893db446aSBoris Brezillon 	config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
131993db446aSBoris Brezillon 			NFC_V3_CONFIG3_NO_SDMA |
132093db446aSBoris Brezillon 			NFC_V3_CONFIG3_RBB_MODE |
132193db446aSBoris Brezillon 			NFC_V3_CONFIG3_SBB(6) | /* Reset default */
132293db446aSBoris Brezillon 			NFC_V3_CONFIG3_ADD_OP(0);
132393db446aSBoris Brezillon 
132493db446aSBoris Brezillon 	if (!(chip->options & NAND_BUSWIDTH_16))
132593db446aSBoris Brezillon 		config3 |= NFC_V3_CONFIG3_FW8;
132693db446aSBoris Brezillon 
132793db446aSBoris Brezillon 	writel(config3, NFC_V3_CONFIG3);
132893db446aSBoris Brezillon 
132993db446aSBoris Brezillon 	writel(0, NFC_V3_DELAY_LINE);
133093db446aSBoris Brezillon }
133193db446aSBoris Brezillon 
133293db446aSBoris Brezillon /* Used by the upper layer to write command to NAND Flash for
133393db446aSBoris Brezillon  * different operations to be carried out on NAND Flash */
13345295cf2eSBoris Brezillon static void mxc_nand_command(struct nand_chip *nand_chip, unsigned command,
133593db446aSBoris Brezillon 			     int column, int page_addr)
133693db446aSBoris Brezillon {
13375295cf2eSBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(nand_chip);
133893db446aSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
133993db446aSBoris Brezillon 
134093db446aSBoris Brezillon 	dev_dbg(host->dev, "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
134193db446aSBoris Brezillon 	      command, column, page_addr);
134293db446aSBoris Brezillon 
134393db446aSBoris Brezillon 	/* Reset command state information */
134493db446aSBoris Brezillon 	host->status_request = false;
134593db446aSBoris Brezillon 
134693db446aSBoris Brezillon 	/* Command pre-processing step */
134793db446aSBoris Brezillon 	switch (command) {
134893db446aSBoris Brezillon 	case NAND_CMD_RESET:
134993db446aSBoris Brezillon 		host->devtype_data->preset(mtd);
135093db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, false);
135193db446aSBoris Brezillon 		break;
135293db446aSBoris Brezillon 
135393db446aSBoris Brezillon 	case NAND_CMD_STATUS:
135493db446aSBoris Brezillon 		host->buf_start = 0;
135593db446aSBoris Brezillon 		host->status_request = true;
135693db446aSBoris Brezillon 
135793db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, true);
135893db446aSBoris Brezillon 		WARN_ONCE(column != -1 || page_addr != -1,
135993db446aSBoris Brezillon 			  "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
136093db446aSBoris Brezillon 			  command, column, page_addr);
136193db446aSBoris Brezillon 		mxc_do_addr_cycle(mtd, column, page_addr);
136293db446aSBoris Brezillon 		break;
136393db446aSBoris Brezillon 
136493db446aSBoris Brezillon 	case NAND_CMD_READID:
136593db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, true);
136693db446aSBoris Brezillon 		mxc_do_addr_cycle(mtd, column, page_addr);
136793db446aSBoris Brezillon 		host->devtype_data->send_read_id(host);
136893db446aSBoris Brezillon 		host->buf_start = 0;
136993db446aSBoris Brezillon 		break;
137093db446aSBoris Brezillon 
137193db446aSBoris Brezillon 	case NAND_CMD_ERASE1:
137293db446aSBoris Brezillon 	case NAND_CMD_ERASE2:
137393db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, false);
137493db446aSBoris Brezillon 		WARN_ONCE(column != -1,
137593db446aSBoris Brezillon 			  "Unexpected column value (cmd=%u, col=%d)\n",
137693db446aSBoris Brezillon 			  command, column);
137793db446aSBoris Brezillon 		mxc_do_addr_cycle(mtd, column, page_addr);
137893db446aSBoris Brezillon 
137993db446aSBoris Brezillon 		break;
138093db446aSBoris Brezillon 	case NAND_CMD_PARAM:
138193db446aSBoris Brezillon 		host->devtype_data->send_cmd(host, command, false);
138293db446aSBoris Brezillon 		mxc_do_addr_cycle(mtd, column, page_addr);
138393db446aSBoris Brezillon 		host->devtype_data->send_page(mtd, NFC_OUTPUT);
138493db446aSBoris Brezillon 		memcpy32_fromio(host->data_buf, host->main_area0, 512);
138593db446aSBoris Brezillon 		host->buf_start = 0;
138693db446aSBoris Brezillon 		break;
138793db446aSBoris Brezillon 	default:
138893db446aSBoris Brezillon 		WARN_ONCE(1, "Unimplemented command (cmd=%u)\n",
138993db446aSBoris Brezillon 			  command);
139093db446aSBoris Brezillon 		break;
139193db446aSBoris Brezillon 	}
139293db446aSBoris Brezillon }
139393db446aSBoris Brezillon 
1394aa36ff25SBoris Brezillon static int mxc_nand_set_features(struct nand_chip *chip, int addr,
1395aa36ff25SBoris Brezillon 				 u8 *subfeature_param)
139693db446aSBoris Brezillon {
1397aa36ff25SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
1398aa36ff25SBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
139993db446aSBoris Brezillon 	int i;
140093db446aSBoris Brezillon 
140193db446aSBoris Brezillon 	host->buf_start = 0;
140293db446aSBoris Brezillon 
140393db446aSBoris Brezillon 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
1404716bbbabSBoris Brezillon 		chip->legacy.write_byte(chip, subfeature_param[i]);
140593db446aSBoris Brezillon 
140693db446aSBoris Brezillon 	memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
140793db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_SET_FEATURES, false);
140893db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, addr, -1);
140993db446aSBoris Brezillon 	host->devtype_data->send_page(mtd, NFC_INPUT);
141093db446aSBoris Brezillon 
141193db446aSBoris Brezillon 	return 0;
141293db446aSBoris Brezillon }
141393db446aSBoris Brezillon 
1414aa36ff25SBoris Brezillon static int mxc_nand_get_features(struct nand_chip *chip, int addr,
1415aa36ff25SBoris Brezillon 				 u8 *subfeature_param)
141693db446aSBoris Brezillon {
1417aa36ff25SBoris Brezillon 	struct mtd_info *mtd = nand_to_mtd(chip);
1418aa36ff25SBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
141993db446aSBoris Brezillon 	int i;
142093db446aSBoris Brezillon 
142193db446aSBoris Brezillon 	host->devtype_data->send_cmd(host, NAND_CMD_GET_FEATURES, false);
142293db446aSBoris Brezillon 	mxc_do_addr_cycle(mtd, addr, -1);
142393db446aSBoris Brezillon 	host->devtype_data->send_page(mtd, NFC_OUTPUT);
142493db446aSBoris Brezillon 	memcpy32_fromio(host->data_buf, host->main_area0, 512);
142593db446aSBoris Brezillon 	host->buf_start = 0;
142693db446aSBoris Brezillon 
142793db446aSBoris Brezillon 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
1428716bbbabSBoris Brezillon 		*subfeature_param++ = chip->legacy.read_byte(chip);
142993db446aSBoris Brezillon 
143093db446aSBoris Brezillon 	return 0;
143193db446aSBoris Brezillon }
143293db446aSBoris Brezillon 
143393db446aSBoris Brezillon /*
1434735bf220SKieran Bingham  * The generic flash bbt descriptors overlap with our ecc
143593db446aSBoris Brezillon  * hardware, so define some i.MX specific ones.
143693db446aSBoris Brezillon  */
143793db446aSBoris Brezillon static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
143893db446aSBoris Brezillon static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
143993db446aSBoris Brezillon 
144093db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_descr = {
144193db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
144293db446aSBoris Brezillon 	    | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
144393db446aSBoris Brezillon 	.offs = 0,
144493db446aSBoris Brezillon 	.len = 4,
144593db446aSBoris Brezillon 	.veroffs = 4,
144693db446aSBoris Brezillon 	.maxblocks = 4,
144793db446aSBoris Brezillon 	.pattern = bbt_pattern,
144893db446aSBoris Brezillon };
144993db446aSBoris Brezillon 
145093db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_descr = {
145193db446aSBoris Brezillon 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
145293db446aSBoris Brezillon 	    | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
145393db446aSBoris Brezillon 	.offs = 0,
145493db446aSBoris Brezillon 	.len = 4,
145593db446aSBoris Brezillon 	.veroffs = 4,
145693db446aSBoris Brezillon 	.maxblocks = 4,
145793db446aSBoris Brezillon 	.pattern = mirror_pattern,
145893db446aSBoris Brezillon };
145993db446aSBoris Brezillon 
146093db446aSBoris Brezillon /* v1 + irqpending_quirk: i.MX21 */
146193db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
146293db446aSBoris Brezillon 	.preset = preset_v1,
146393db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v1,
146493db446aSBoris Brezillon 	.send_cmd = send_cmd_v1_v2,
146593db446aSBoris Brezillon 	.send_addr = send_addr_v1_v2,
146693db446aSBoris Brezillon 	.send_page = send_page_v1,
146793db446aSBoris Brezillon 	.send_read_id = send_read_id_v1_v2,
146893db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v1_v2,
146993db446aSBoris Brezillon 	.check_int = check_int_v1_v2,
147093db446aSBoris Brezillon 	.irq_control = irq_control_v1_v2,
147193db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v1,
147293db446aSBoris Brezillon 	.ooblayout = &mxc_v1_ooblayout_ops,
147393db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v1_v3,
147493db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
147593db446aSBoris Brezillon 	.irqpending_quirk = 1,
147693db446aSBoris Brezillon 	.needs_ip = 0,
147793db446aSBoris Brezillon 	.regs_offset = 0xe00,
147893db446aSBoris Brezillon 	.spare0_offset = 0x800,
147993db446aSBoris Brezillon 	.spare_len = 16,
148093db446aSBoris Brezillon 	.eccbytes = 3,
148193db446aSBoris Brezillon 	.eccsize = 1,
148293db446aSBoris Brezillon };
148393db446aSBoris Brezillon 
148493db446aSBoris Brezillon /* v1 + !irqpending_quirk: i.MX27, i.MX31 */
148593db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
148693db446aSBoris Brezillon 	.preset = preset_v1,
148793db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v1,
148893db446aSBoris Brezillon 	.send_cmd = send_cmd_v1_v2,
148993db446aSBoris Brezillon 	.send_addr = send_addr_v1_v2,
149093db446aSBoris Brezillon 	.send_page = send_page_v1,
149193db446aSBoris Brezillon 	.send_read_id = send_read_id_v1_v2,
149293db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v1_v2,
149393db446aSBoris Brezillon 	.check_int = check_int_v1_v2,
149493db446aSBoris Brezillon 	.irq_control = irq_control_v1_v2,
149593db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v1,
149693db446aSBoris Brezillon 	.ooblayout = &mxc_v1_ooblayout_ops,
149793db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v1_v3,
149893db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
149993db446aSBoris Brezillon 	.irqpending_quirk = 0,
150093db446aSBoris Brezillon 	.needs_ip = 0,
150193db446aSBoris Brezillon 	.regs_offset = 0xe00,
150293db446aSBoris Brezillon 	.spare0_offset = 0x800,
150393db446aSBoris Brezillon 	.axi_offset = 0,
150493db446aSBoris Brezillon 	.spare_len = 16,
150593db446aSBoris Brezillon 	.eccbytes = 3,
150693db446aSBoris Brezillon 	.eccsize = 1,
150793db446aSBoris Brezillon };
150893db446aSBoris Brezillon 
150993db446aSBoris Brezillon /* v21: i.MX25, i.MX35 */
151093db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
151193db446aSBoris Brezillon 	.preset = preset_v2,
151293db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v2_v3,
151393db446aSBoris Brezillon 	.send_cmd = send_cmd_v1_v2,
151493db446aSBoris Brezillon 	.send_addr = send_addr_v1_v2,
151593db446aSBoris Brezillon 	.send_page = send_page_v2,
151693db446aSBoris Brezillon 	.send_read_id = send_read_id_v1_v2,
151793db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v1_v2,
151893db446aSBoris Brezillon 	.check_int = check_int_v1_v2,
151993db446aSBoris Brezillon 	.irq_control = irq_control_v1_v2,
152093db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v2,
152193db446aSBoris Brezillon 	.ooblayout = &mxc_v2_ooblayout_ops,
152293db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v2,
15234c46667bSMiquel Raynal 	.setup_interface = mxc_nand_v2_setup_interface,
152493db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v1_v2,
152593db446aSBoris Brezillon 	.irqpending_quirk = 0,
152693db446aSBoris Brezillon 	.needs_ip = 0,
152793db446aSBoris Brezillon 	.regs_offset = 0x1e00,
152893db446aSBoris Brezillon 	.spare0_offset = 0x1000,
152993db446aSBoris Brezillon 	.axi_offset = 0,
153093db446aSBoris Brezillon 	.spare_len = 64,
153193db446aSBoris Brezillon 	.eccbytes = 9,
153293db446aSBoris Brezillon 	.eccsize = 0,
153393db446aSBoris Brezillon };
153493db446aSBoris Brezillon 
153593db446aSBoris Brezillon /* v3.2a: i.MX51 */
153693db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
153793db446aSBoris Brezillon 	.preset = preset_v3,
153893db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v2_v3,
153993db446aSBoris Brezillon 	.send_cmd = send_cmd_v3,
154093db446aSBoris Brezillon 	.send_addr = send_addr_v3,
154193db446aSBoris Brezillon 	.send_page = send_page_v3,
154293db446aSBoris Brezillon 	.send_read_id = send_read_id_v3,
154393db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v3,
154493db446aSBoris Brezillon 	.check_int = check_int_v3,
154593db446aSBoris Brezillon 	.irq_control = irq_control_v3,
154693db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v3,
154793db446aSBoris Brezillon 	.ooblayout = &mxc_v2_ooblayout_ops,
154893db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v1_v3,
154993db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v3,
155093db446aSBoris Brezillon 	.irqpending_quirk = 0,
155193db446aSBoris Brezillon 	.needs_ip = 1,
155293db446aSBoris Brezillon 	.regs_offset = 0,
155393db446aSBoris Brezillon 	.spare0_offset = 0x1000,
155493db446aSBoris Brezillon 	.axi_offset = 0x1e00,
155593db446aSBoris Brezillon 	.spare_len = 64,
155693db446aSBoris Brezillon 	.eccbytes = 0,
155793db446aSBoris Brezillon 	.eccsize = 0,
155893db446aSBoris Brezillon 	.ppb_shift = 7,
155993db446aSBoris Brezillon };
156093db446aSBoris Brezillon 
156193db446aSBoris Brezillon /* v3.2b: i.MX53 */
156293db446aSBoris Brezillon static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
156393db446aSBoris Brezillon 	.preset = preset_v3,
156493db446aSBoris Brezillon 	.read_page = mxc_nand_read_page_v2_v3,
156593db446aSBoris Brezillon 	.send_cmd = send_cmd_v3,
156693db446aSBoris Brezillon 	.send_addr = send_addr_v3,
156793db446aSBoris Brezillon 	.send_page = send_page_v3,
156893db446aSBoris Brezillon 	.send_read_id = send_read_id_v3,
156993db446aSBoris Brezillon 	.get_dev_status = get_dev_status_v3,
157093db446aSBoris Brezillon 	.check_int = check_int_v3,
157193db446aSBoris Brezillon 	.irq_control = irq_control_v3,
157293db446aSBoris Brezillon 	.get_ecc_status = get_ecc_status_v3,
157393db446aSBoris Brezillon 	.ooblayout = &mxc_v2_ooblayout_ops,
157493db446aSBoris Brezillon 	.select_chip = mxc_nand_select_chip_v1_v3,
157593db446aSBoris Brezillon 	.enable_hwecc = mxc_nand_enable_hwecc_v3,
157693db446aSBoris Brezillon 	.irqpending_quirk = 0,
157793db446aSBoris Brezillon 	.needs_ip = 1,
157893db446aSBoris Brezillon 	.regs_offset = 0,
157993db446aSBoris Brezillon 	.spare0_offset = 0x1000,
158093db446aSBoris Brezillon 	.axi_offset = 0x1e00,
158193db446aSBoris Brezillon 	.spare_len = 64,
158293db446aSBoris Brezillon 	.eccbytes = 0,
158393db446aSBoris Brezillon 	.eccsize = 0,
158493db446aSBoris Brezillon 	.ppb_shift = 8,
158593db446aSBoris Brezillon };
158693db446aSBoris Brezillon 
158793db446aSBoris Brezillon static inline int is_imx21_nfc(struct mxc_nand_host *host)
158893db446aSBoris Brezillon {
158993db446aSBoris Brezillon 	return host->devtype_data == &imx21_nand_devtype_data;
159093db446aSBoris Brezillon }
159193db446aSBoris Brezillon 
159293db446aSBoris Brezillon static inline int is_imx27_nfc(struct mxc_nand_host *host)
159393db446aSBoris Brezillon {
159493db446aSBoris Brezillon 	return host->devtype_data == &imx27_nand_devtype_data;
159593db446aSBoris Brezillon }
159693db446aSBoris Brezillon 
159793db446aSBoris Brezillon static inline int is_imx25_nfc(struct mxc_nand_host *host)
159893db446aSBoris Brezillon {
159993db446aSBoris Brezillon 	return host->devtype_data == &imx25_nand_devtype_data;
160093db446aSBoris Brezillon }
160193db446aSBoris Brezillon 
160293db446aSBoris Brezillon static const struct of_device_id mxcnd_dt_ids[] = {
16035e214b25SFabio Estevam 	{ .compatible = "fsl,imx21-nand", .data = &imx21_nand_devtype_data, },
16045e214b25SFabio Estevam 	{ .compatible = "fsl,imx27-nand", .data = &imx27_nand_devtype_data, },
16055e214b25SFabio Estevam 	{ .compatible = "fsl,imx25-nand", .data = &imx25_nand_devtype_data, },
16065e214b25SFabio Estevam 	{ .compatible = "fsl,imx51-nand", .data = &imx51_nand_devtype_data, },
16075e214b25SFabio Estevam 	{ .compatible = "fsl,imx53-nand", .data = &imx53_nand_devtype_data, },
160893db446aSBoris Brezillon 	{ /* sentinel */ }
160993db446aSBoris Brezillon };
161093db446aSBoris Brezillon MODULE_DEVICE_TABLE(of, mxcnd_dt_ids);
161193db446aSBoris Brezillon 
161296fa8e6eSMiquel Raynal static int mxcnd_attach_chip(struct nand_chip *chip)
161396fa8e6eSMiquel Raynal {
161496fa8e6eSMiquel Raynal 	struct mtd_info *mtd = nand_to_mtd(chip);
161596fa8e6eSMiquel Raynal 	struct mxc_nand_host *host = nand_get_controller_data(chip);
161696fa8e6eSMiquel Raynal 	struct device *dev = mtd->dev.parent;
161796fa8e6eSMiquel Raynal 
16181b8d1070SFabio Estevam 	chip->ecc.bytes = host->devtype_data->eccbytes;
16191b8d1070SFabio Estevam 	host->eccsize = host->devtype_data->eccsize;
16201b8d1070SFabio Estevam 	chip->ecc.size = 512;
16211b8d1070SFabio Estevam 	mtd_set_ooblayout(mtd, host->devtype_data->ooblayout);
16221b8d1070SFabio Estevam 
1623bace41f8SMiquel Raynal 	switch (chip->ecc.engine_type) {
1624bace41f8SMiquel Raynal 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
162596fa8e6eSMiquel Raynal 		chip->ecc.read_page = mxc_nand_read_page;
162696fa8e6eSMiquel Raynal 		chip->ecc.read_page_raw = mxc_nand_read_page_raw;
162796fa8e6eSMiquel Raynal 		chip->ecc.read_oob = mxc_nand_read_oob;
162896fa8e6eSMiquel Raynal 		chip->ecc.write_page = mxc_nand_write_page_ecc;
162996fa8e6eSMiquel Raynal 		chip->ecc.write_page_raw = mxc_nand_write_page_raw;
163096fa8e6eSMiquel Raynal 		chip->ecc.write_oob = mxc_nand_write_oob;
163196fa8e6eSMiquel Raynal 		break;
163296fa8e6eSMiquel Raynal 
1633bace41f8SMiquel Raynal 	case NAND_ECC_ENGINE_TYPE_SOFT:
163496fa8e6eSMiquel Raynal 		break;
163596fa8e6eSMiquel Raynal 
163696fa8e6eSMiquel Raynal 	default:
163796fa8e6eSMiquel Raynal 		return -EINVAL;
163896fa8e6eSMiquel Raynal 	}
163996fa8e6eSMiquel Raynal 
164096fa8e6eSMiquel Raynal 	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
164196fa8e6eSMiquel Raynal 		chip->bbt_td = &bbt_main_descr;
164296fa8e6eSMiquel Raynal 		chip->bbt_md = &bbt_mirror_descr;
164396fa8e6eSMiquel Raynal 	}
164496fa8e6eSMiquel Raynal 
164596fa8e6eSMiquel Raynal 	/* Allocate the right size buffer now */
164696fa8e6eSMiquel Raynal 	devm_kfree(dev, (void *)host->data_buf);
164796fa8e6eSMiquel Raynal 	host->data_buf = devm_kzalloc(dev, mtd->writesize + mtd->oobsize,
164896fa8e6eSMiquel Raynal 				      GFP_KERNEL);
164996fa8e6eSMiquel Raynal 	if (!host->data_buf)
165096fa8e6eSMiquel Raynal 		return -ENOMEM;
165196fa8e6eSMiquel Raynal 
165296fa8e6eSMiquel Raynal 	/* Call preset again, with correct writesize chip time */
165396fa8e6eSMiquel Raynal 	host->devtype_data->preset(mtd);
165496fa8e6eSMiquel Raynal 
165596fa8e6eSMiquel Raynal 	if (!chip->ecc.bytes) {
165696fa8e6eSMiquel Raynal 		if (host->eccsize == 8)
165796fa8e6eSMiquel Raynal 			chip->ecc.bytes = 18;
165896fa8e6eSMiquel Raynal 		else if (host->eccsize == 4)
165996fa8e6eSMiquel Raynal 			chip->ecc.bytes = 9;
166096fa8e6eSMiquel Raynal 	}
166196fa8e6eSMiquel Raynal 
166296fa8e6eSMiquel Raynal 	/*
166396fa8e6eSMiquel Raynal 	 * Experimentation shows that i.MX NFC can only handle up to 218 oob
166496fa8e6eSMiquel Raynal 	 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
166596fa8e6eSMiquel Raynal 	 * into copying invalid data to/from the spare IO buffer, as this
166696fa8e6eSMiquel Raynal 	 * might cause ECC data corruption when doing sub-page write to a
166796fa8e6eSMiquel Raynal 	 * partially written page.
166896fa8e6eSMiquel Raynal 	 */
166996fa8e6eSMiquel Raynal 	host->used_oobsize = min(mtd->oobsize, 218U);
167096fa8e6eSMiquel Raynal 
1671bace41f8SMiquel Raynal 	if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) {
167296fa8e6eSMiquel Raynal 		if (is_imx21_nfc(host) || is_imx27_nfc(host))
167396fa8e6eSMiquel Raynal 			chip->ecc.strength = 1;
167496fa8e6eSMiquel Raynal 		else
167596fa8e6eSMiquel Raynal 			chip->ecc.strength = (host->eccsize == 4) ? 4 : 8;
167696fa8e6eSMiquel Raynal 	}
167796fa8e6eSMiquel Raynal 
167896fa8e6eSMiquel Raynal 	return 0;
167996fa8e6eSMiquel Raynal }
168096fa8e6eSMiquel Raynal 
16814c46667bSMiquel Raynal static int mxcnd_setup_interface(struct nand_chip *chip, int chipnr,
16824c46667bSMiquel Raynal 				 const struct nand_interface_config *conf)
16837a08dbaeSBoris Brezillon {
16847a08dbaeSBoris Brezillon 	struct mxc_nand_host *host = nand_get_controller_data(chip);
16857a08dbaeSBoris Brezillon 
16864c46667bSMiquel Raynal 	return host->devtype_data->setup_interface(chip, chipnr, conf);
16877a08dbaeSBoris Brezillon }
16887a08dbaeSBoris Brezillon 
168996fa8e6eSMiquel Raynal static const struct nand_controller_ops mxcnd_controller_ops = {
169096fa8e6eSMiquel Raynal 	.attach_chip = mxcnd_attach_chip,
16914c46667bSMiquel Raynal 	.setup_interface = mxcnd_setup_interface,
169296fa8e6eSMiquel Raynal };
169396fa8e6eSMiquel Raynal 
169493db446aSBoris Brezillon static int mxcnd_probe(struct platform_device *pdev)
169593db446aSBoris Brezillon {
169693db446aSBoris Brezillon 	struct nand_chip *this;
169793db446aSBoris Brezillon 	struct mtd_info *mtd;
169893db446aSBoris Brezillon 	struct mxc_nand_host *host;
169993db446aSBoris Brezillon 	struct resource *res;
170093db446aSBoris Brezillon 	int err = 0;
170193db446aSBoris Brezillon 
170293db446aSBoris Brezillon 	/* Allocate memory for MTD device structure and private data */
170393db446aSBoris Brezillon 	host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
170493db446aSBoris Brezillon 			GFP_KERNEL);
170593db446aSBoris Brezillon 	if (!host)
170693db446aSBoris Brezillon 		return -ENOMEM;
170793db446aSBoris Brezillon 
170893db446aSBoris Brezillon 	/* allocate a temporary buffer for the nand_scan_ident() */
170993db446aSBoris Brezillon 	host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
171093db446aSBoris Brezillon 	if (!host->data_buf)
171193db446aSBoris Brezillon 		return -ENOMEM;
171293db446aSBoris Brezillon 
171393db446aSBoris Brezillon 	host->dev = &pdev->dev;
171493db446aSBoris Brezillon 	/* structures must be linked */
171593db446aSBoris Brezillon 	this = &host->nand;
171693db446aSBoris Brezillon 	mtd = nand_to_mtd(this);
171793db446aSBoris Brezillon 	mtd->dev.parent = &pdev->dev;
171893db446aSBoris Brezillon 	mtd->name = DRIVER_NAME;
171993db446aSBoris Brezillon 
172093db446aSBoris Brezillon 	/* 50 us command delay time */
17213cece3abSBoris Brezillon 	this->legacy.chip_delay = 5;
172293db446aSBoris Brezillon 
172393db446aSBoris Brezillon 	nand_set_controller_data(this, host);
172463f559d3SZheng Yongjun 	nand_set_flash_node(this, pdev->dev.of_node);
17258395b753SBoris Brezillon 	this->legacy.dev_ready = mxc_nand_dev_ready;
1726bf6065c6SBoris Brezillon 	this->legacy.cmdfunc = mxc_nand_command;
1727716bbbabSBoris Brezillon 	this->legacy.read_byte = mxc_nand_read_byte;
1728716bbbabSBoris Brezillon 	this->legacy.write_buf = mxc_nand_write_buf;
1729716bbbabSBoris Brezillon 	this->legacy.read_buf = mxc_nand_read_buf;
173045240367SBoris Brezillon 	this->legacy.set_features = mxc_nand_set_features;
173145240367SBoris Brezillon 	this->legacy.get_features = mxc_nand_get_features;
173293db446aSBoris Brezillon 
173393db446aSBoris Brezillon 	host->clk = devm_clk_get(&pdev->dev, NULL);
173493db446aSBoris Brezillon 	if (IS_ERR(host->clk))
173593db446aSBoris Brezillon 		return PTR_ERR(host->clk);
173693db446aSBoris Brezillon 
17375876f2d9SFabio Estevam 	host->devtype_data = device_get_match_data(&pdev->dev);
173893db446aSBoris Brezillon 
17394c46667bSMiquel Raynal 	if (!host->devtype_data->setup_interface)
17407a08dbaeSBoris Brezillon 		this->options |= NAND_KEEP_TIMINGS;
174193db446aSBoris Brezillon 
174293db446aSBoris Brezillon 	if (host->devtype_data->needs_ip) {
174393db446aSBoris Brezillon 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
174493db446aSBoris Brezillon 		host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
174593db446aSBoris Brezillon 		if (IS_ERR(host->regs_ip))
174693db446aSBoris Brezillon 			return PTR_ERR(host->regs_ip);
174793db446aSBoris Brezillon 
174893db446aSBoris Brezillon 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
174993db446aSBoris Brezillon 	} else {
175093db446aSBoris Brezillon 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
175193db446aSBoris Brezillon 	}
175293db446aSBoris Brezillon 
175393db446aSBoris Brezillon 	host->base = devm_ioremap_resource(&pdev->dev, res);
175493db446aSBoris Brezillon 	if (IS_ERR(host->base))
175593db446aSBoris Brezillon 		return PTR_ERR(host->base);
175693db446aSBoris Brezillon 
175793db446aSBoris Brezillon 	host->main_area0 = host->base;
175893db446aSBoris Brezillon 
175993db446aSBoris Brezillon 	if (host->devtype_data->regs_offset)
176093db446aSBoris Brezillon 		host->regs = host->base + host->devtype_data->regs_offset;
176193db446aSBoris Brezillon 	host->spare0 = host->base + host->devtype_data->spare0_offset;
176293db446aSBoris Brezillon 	if (host->devtype_data->axi_offset)
176393db446aSBoris Brezillon 		host->regs_axi = host->base + host->devtype_data->axi_offset;
176493db446aSBoris Brezillon 
17657d6c37e9SBoris Brezillon 	this->legacy.select_chip = host->devtype_data->select_chip;
176693db446aSBoris Brezillon 
176793db446aSBoris Brezillon 	init_completion(&host->op_completion);
176893db446aSBoris Brezillon 
176993db446aSBoris Brezillon 	host->irq = platform_get_irq(pdev, 0);
177093db446aSBoris Brezillon 	if (host->irq < 0)
177193db446aSBoris Brezillon 		return host->irq;
177293db446aSBoris Brezillon 
177393db446aSBoris Brezillon 	/*
177493db446aSBoris Brezillon 	 * Use host->devtype_data->irq_control() here instead of irq_control()
177593db446aSBoris Brezillon 	 * because we must not disable_irq_nosync without having requested the
177693db446aSBoris Brezillon 	 * irq.
177793db446aSBoris Brezillon 	 */
177893db446aSBoris Brezillon 	host->devtype_data->irq_control(host, 0);
177993db446aSBoris Brezillon 
178093db446aSBoris Brezillon 	err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
178193db446aSBoris Brezillon 			0, DRIVER_NAME, host);
178293db446aSBoris Brezillon 	if (err)
178393db446aSBoris Brezillon 		return err;
178493db446aSBoris Brezillon 
178593db446aSBoris Brezillon 	err = clk_prepare_enable(host->clk);
178693db446aSBoris Brezillon 	if (err)
178793db446aSBoris Brezillon 		return err;
178893db446aSBoris Brezillon 	host->clk_act = 1;
178993db446aSBoris Brezillon 
179093db446aSBoris Brezillon 	/*
179193db446aSBoris Brezillon 	 * Now that we "own" the interrupt make sure the interrupt mask bit is
179293db446aSBoris Brezillon 	 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
179393db446aSBoris Brezillon 	 * on this machine.
179493db446aSBoris Brezillon 	 */
179593db446aSBoris Brezillon 	if (host->devtype_data->irqpending_quirk) {
179693db446aSBoris Brezillon 		disable_irq_nosync(host->irq);
179793db446aSBoris Brezillon 		host->devtype_data->irq_control(host, 1);
179893db446aSBoris Brezillon 	}
179993db446aSBoris Brezillon 
180096fa8e6eSMiquel Raynal 	/* Scan the NAND device */
18017b6a9b28SBoris Brezillon 	this->legacy.dummy_controller.ops = &mxcnd_controller_ops;
180200ad378fSBoris Brezillon 	err = nand_scan(this, is_imx25_nfc(host) ? 4 : 1);
180393db446aSBoris Brezillon 	if (err)
180493db446aSBoris Brezillon 		goto escan;
180593db446aSBoris Brezillon 
180693db446aSBoris Brezillon 	/* Register the partitions */
18070f6b7919SFabio Estevam 	err = mtd_device_parse_register(mtd, part_probes, NULL, NULL, 0);
1808be051bf2SMiquel Raynal 	if (err)
1809be051bf2SMiquel Raynal 		goto cleanup_nand;
181093db446aSBoris Brezillon 
181193db446aSBoris Brezillon 	platform_set_drvdata(pdev, host);
181293db446aSBoris Brezillon 
181393db446aSBoris Brezillon 	return 0;
181493db446aSBoris Brezillon 
1815be051bf2SMiquel Raynal cleanup_nand:
1816be051bf2SMiquel Raynal 	nand_cleanup(this);
181793db446aSBoris Brezillon escan:
181893db446aSBoris Brezillon 	if (host->clk_act)
181993db446aSBoris Brezillon 		clk_disable_unprepare(host->clk);
182093db446aSBoris Brezillon 
182193db446aSBoris Brezillon 	return err;
182293db446aSBoris Brezillon }
182393db446aSBoris Brezillon 
1824*ec185b18SUwe Kleine-König static void mxcnd_remove(struct platform_device *pdev)
182593db446aSBoris Brezillon {
182693db446aSBoris Brezillon 	struct mxc_nand_host *host = platform_get_drvdata(pdev);
1827c6dc0827SMiquel Raynal 	struct nand_chip *chip = &host->nand;
1828c6dc0827SMiquel Raynal 	int ret;
182993db446aSBoris Brezillon 
1830c6dc0827SMiquel Raynal 	ret = mtd_device_unregister(nand_to_mtd(chip));
1831c6dc0827SMiquel Raynal 	WARN_ON(ret);
1832c6dc0827SMiquel Raynal 	nand_cleanup(chip);
183393db446aSBoris Brezillon 	if (host->clk_act)
183493db446aSBoris Brezillon 		clk_disable_unprepare(host->clk);
183593db446aSBoris Brezillon }
183693db446aSBoris Brezillon 
183793db446aSBoris Brezillon static struct platform_driver mxcnd_driver = {
183893db446aSBoris Brezillon 	.driver = {
183993db446aSBoris Brezillon 		   .name = DRIVER_NAME,
18401200c7f8SFabio Estevam 		   .of_match_table = mxcnd_dt_ids,
184193db446aSBoris Brezillon 	},
184293db446aSBoris Brezillon 	.probe = mxcnd_probe,
1843*ec185b18SUwe Kleine-König 	.remove_new = mxcnd_remove,
184493db446aSBoris Brezillon };
184593db446aSBoris Brezillon module_platform_driver(mxcnd_driver);
184693db446aSBoris Brezillon 
184793db446aSBoris Brezillon MODULE_AUTHOR("Freescale Semiconductor, Inc.");
184893db446aSBoris Brezillon MODULE_DESCRIPTION("MXC NAND MTD driver");
184993db446aSBoris Brezillon MODULE_LICENSE("GPL");
1850