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