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