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