blob: 1433a83891096eb19979ce92bf3426c0740a4055 [file] [log] [blame]
Sascha Hauer34f6e152008-09-02 17:16:59 +02001/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#include <linux/delay.h>
21#include <linux/slab.h>
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/mtd/mtd.h>
25#include <linux/mtd/nand.h>
26#include <linux/mtd/partitions.h>
27#include <linux/interrupt.h>
28#include <linux/device.h>
29#include <linux/platform_device.h>
30#include <linux/clk.h>
31#include <linux/err.h>
32#include <linux/io.h>
33
34#include <asm/mach/flash.h>
35#include <mach/mxc_nand.h>
Sascha Hauer94671142009-10-05 12:14:21 +020036#include <mach/hardware.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020037
38#define DRIVER_NAME "mxc_nand"
39
Sascha Hauer94671142009-10-05 12:14:21 +020040#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
Ivo Claryssea47bfd22010-04-08 16:16:51 +020041#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
Sascha Hauer94671142009-10-05 12:14:21 +020042
Sascha Hauer34f6e152008-09-02 17:16:59 +020043/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020044#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
45#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
46#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
47#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
48#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
49#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
50#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
51#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
52#define NFC_V1_V2_WRPROT (host->regs + 0x12)
53#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
54#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
55#define NFC_V21_UNLOCKSTART_BLKADDR (host->regs + 0x20)
56#define NFC_V21_UNLOCKEND_BLKADDR (host->regs + 0x22)
57#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
58#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
59#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020060
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020061#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020062#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
63#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
64#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
65#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
66#define NFC_V1_V2_CONFIG1_RST (1 << 6)
67#define NFC_V1_V2_CONFIG1_CE (1 << 7)
68#define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8)
Sascha Hauer34f6e152008-09-02 17:16:59 +020069
Sascha Hauer1bc99182010-08-06 15:53:08 +020070#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020071
Sascha Hauer1bc99182010-08-06 15:53:08 +020072/*
73 * Operation modes for the NFC. Valid for v1, v2 and v3
74 * type controllers.
75 */
76#define NFC_CMD (1 << 0)
77#define NFC_ADDR (1 << 1)
78#define NFC_INPUT (1 << 2)
79#define NFC_OUTPUT (1 << 3)
80#define NFC_ID (1 << 4)
81#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020082
83struct mxc_nand_host {
84 struct mtd_info mtd;
85 struct nand_chip nand;
86 struct mtd_partition *parts;
87 struct device *dev;
88
Sascha Hauerc6de7e12009-10-05 11:14:35 +020089 void *spare0;
90 void *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +020091
92 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +020093 void __iomem *regs;
Sascha Hauer34f6e152008-09-02 17:16:59 +020094 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +020095 struct clk *clk;
96 int clk_act;
97 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +020098 int eccsize;
Sascha Hauer34f6e152008-09-02 17:16:59 +020099
100 wait_queue_head_t irq_waitq;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200101
102 uint8_t *data_buf;
103 unsigned int buf_start;
104 int spare_len;
Sascha Hauer5f973042010-08-06 15:53:06 +0200105
106 void (*preset)(struct mtd_info *);
107 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
108 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
109 void (*send_page)(struct mtd_info *, unsigned int);
110 void (*send_read_id)(struct mxc_nand_host *);
111 uint16_t (*get_dev_status)(struct mxc_nand_host *);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200112 int (*check_int)(struct mxc_nand_host *);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200113};
114
Sascha Hauer34f6e152008-09-02 17:16:59 +0200115/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200116static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200117 .eccbytes = 5,
118 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200119 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200120};
121
Sascha Hauer94671142009-10-05 12:14:21 +0200122static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400123 .eccbytes = 20,
124 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
125 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
126 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200127};
128
Sascha Hauer94671142009-10-05 12:14:21 +0200129/* OOB description for 512 byte pages with 16 byte OOB */
130static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
131 .eccbytes = 1 * 9,
132 .eccpos = {
133 7, 8, 9, 10, 11, 12, 13, 14, 15
134 },
135 .oobfree = {
136 {.offset = 0, .length = 5}
137 }
138};
139
140/* OOB description for 2048 byte pages with 64 byte OOB */
141static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
142 .eccbytes = 4 * 9,
143 .eccpos = {
144 7, 8, 9, 10, 11, 12, 13, 14, 15,
145 23, 24, 25, 26, 27, 28, 29, 30, 31,
146 39, 40, 41, 42, 43, 44, 45, 46, 47,
147 55, 56, 57, 58, 59, 60, 61, 62, 63
148 },
149 .oobfree = {
150 {.offset = 2, .length = 4},
151 {.offset = 16, .length = 7},
152 {.offset = 32, .length = 7},
153 {.offset = 48, .length = 7}
154 }
155};
156
Sascha Hauer34f6e152008-09-02 17:16:59 +0200157#ifdef CONFIG_MTD_PARTITIONS
158static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
159#endif
160
161static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
162{
163 struct mxc_nand_host *host = dev_id;
164
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200165 disable_irq_nosync(irq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200166
167 wake_up(&host->irq_waitq);
168
169 return IRQ_HANDLED;
170}
171
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200172static int check_int_v1_v2(struct mxc_nand_host *host)
173{
174 uint32_t tmp;
175
Sascha Hauer1bc99182010-08-06 15:53:08 +0200176 tmp = readw(NFC_V1_V2_CONFIG2);
177 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200178 return 0;
179
Sascha Hauer1bc99182010-08-06 15:53:08 +0200180 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200181
182 return 1;
183}
184
Sascha Hauer34f6e152008-09-02 17:16:59 +0200185/* This function polls the NANDFC to wait for the basic operation to
186 * complete by checking the INT bit of config2 register.
187 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200188static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200189{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200190 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200191
192 if (useirq) {
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200193 if (!host->check_int(host)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200194
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200195 enable_irq(host->irq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200196
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200197 wait_event(host->irq_waitq, host->check_int(host));
Sascha Hauer34f6e152008-09-02 17:16:59 +0200198 }
199 } else {
200 while (max_retries-- > 0) {
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200201 if (host->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200202 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200203
Sascha Hauer34f6e152008-09-02 17:16:59 +0200204 udelay(1);
205 }
Roel Kluin43950a62009-06-04 16:24:59 +0200206 if (max_retries < 0)
Sascha Hauer62465492009-06-04 15:57:20 +0200207 DEBUG(MTD_DEBUG_LEVEL0, "%s: INT not set\n",
208 __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200209 }
210}
211
212/* This function issues the specified command to the NAND device and
213 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200214static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200215{
216 DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
217
Sascha Hauer1bc99182010-08-06 15:53:08 +0200218 writew(cmd, NFC_V1_V2_FLASH_CMD);
219 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200220
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200221 if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
222 int max_retries = 100;
223 /* Reset completion is indicated by NFC_CONFIG2 */
224 /* being set to 0 */
225 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200226 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200227 break;
228 }
229 udelay(1);
230 }
231 if (max_retries < 0)
232 DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n",
233 __func__);
234 } else {
235 /* Wait for operation to complete */
236 wait_op_done(host, useirq);
237 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200238}
239
240/* This function sends an address (or partial address) to the
241 * NAND device. The address is used to select the source/destination for
242 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200243static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200244{
245 DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
246
Sascha Hauer1bc99182010-08-06 15:53:08 +0200247 writew(addr, NFC_V1_V2_FLASH_ADDR);
248 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200249
250 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200251 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200252}
253
Sascha Hauer5f973042010-08-06 15:53:06 +0200254static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200255{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200256 struct nand_chip *nand_chip = mtd->priv;
257 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200258 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200259
Sascha Hauer94671142009-10-05 12:14:21 +0200260 if (nfc_is_v1() && mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200261 bufs = 4;
262 else
263 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200264
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200265 for (i = 0; i < bufs; i++) {
266
267 /* NANDFC buffer 0 is used for page read/write */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200268 writew(i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200269
Sascha Hauer1bc99182010-08-06 15:53:08 +0200270 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200271
272 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200273 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200274 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200275}
276
277/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200278static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200279{
280 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200281
282 /* NANDFC buffer 0 is used for device ID output */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200283 writew(0x0, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200284
Sascha Hauer1bc99182010-08-06 15:53:08 +0200285 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200286
287 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200288 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200289
290 if (this->options & NAND_BUSWIDTH_16) {
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200291 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200292 /* compress the ID info */
293 writeb(readb(main_buf + 2), main_buf + 1);
294 writeb(readb(main_buf + 4), main_buf + 2);
295 writeb(readb(main_buf + 6), main_buf + 3);
296 writeb(readb(main_buf + 8), main_buf + 4);
297 writeb(readb(main_buf + 10), main_buf + 5);
298 }
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200299 memcpy(host->data_buf, host->main_area0, 16);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200300}
301
302/* This function requests the NANDFC to perform a read of the
303 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200304static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200305{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200306 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200307 uint32_t store;
Sascha Hauerf06368f2009-10-05 17:18:42 +0200308 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200309
Sascha Hauerc29c6072010-08-06 15:53:05 +0200310 writew(0x0, NFC_V1_V2_BUF_ADDR);
311
312 /*
313 * The device status is stored in main_area0. To
314 * prevent corruption of the buffer save the value
315 * and restore it afterwards.
316 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200317 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200318
Sascha Hauer1bc99182010-08-06 15:53:08 +0200319 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200320 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200321
Sascha Hauer34f6e152008-09-02 17:16:59 +0200322 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200323
Sascha Hauer34f6e152008-09-02 17:16:59 +0200324 writel(store, main_buf);
325
326 return ret;
327}
328
329/* This functions is used by upper layer to checks if device is ready */
330static int mxc_nand_dev_ready(struct mtd_info *mtd)
331{
332 /*
333 * NFC handles R/B internally. Therefore, this function
334 * always returns status as ready.
335 */
336 return 1;
337}
338
339static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
340{
341 /*
342 * If HW ECC is enabled, we turn it on during init. There is
343 * no need to enable again here.
344 */
345}
346
Sascha Hauer94f77e52010-08-06 15:53:09 +0200347static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200348 u_char *read_ecc, u_char *calc_ecc)
349{
350 struct nand_chip *nand_chip = mtd->priv;
351 struct mxc_nand_host *host = nand_chip->priv;
352
353 /*
354 * 1-Bit errors are automatically corrected in HW. No need for
355 * additional correction. 2-Bit errors cannot be corrected by
356 * HW ECC, so we need to return failure
357 */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200358 uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200359
360 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
361 DEBUG(MTD_DEBUG_LEVEL0,
362 "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
363 return -1;
364 }
365
366 return 0;
367}
368
Sascha Hauer94f77e52010-08-06 15:53:09 +0200369static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
370 u_char *read_ecc, u_char *calc_ecc)
371{
372 struct nand_chip *nand_chip = mtd->priv;
373 struct mxc_nand_host *host = nand_chip->priv;
374 u32 ecc_stat, err;
375 int no_subpages = 1;
376 int ret = 0;
377 u8 ecc_bit_mask, err_limit;
378
379 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
380 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
381
382 no_subpages = mtd->writesize >> 9;
383
384 ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT);
385
386 do {
387 err = ecc_stat & ecc_bit_mask;
388 if (err > err_limit) {
389 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
390 return -1;
391 } else {
392 ret += err;
393 }
394 ecc_stat >>= 4;
395 } while (--no_subpages);
396
397 mtd->ecc_stats.corrected += ret;
398 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
399
400 return ret;
401}
402
Sascha Hauer34f6e152008-09-02 17:16:59 +0200403static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
404 u_char *ecc_code)
405{
406 return 0;
407}
408
409static u_char mxc_nand_read_byte(struct mtd_info *mtd)
410{
411 struct nand_chip *nand_chip = mtd->priv;
412 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200413 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200414
415 /* Check for status request */
416 if (host->status_request)
Sascha Hauer5f973042010-08-06 15:53:06 +0200417 return host->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200418
Sascha Hauerf8f96082009-06-04 17:12:26 +0200419 ret = *(uint8_t *)(host->data_buf + host->buf_start);
420 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200421
422 return ret;
423}
424
425static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
426{
427 struct nand_chip *nand_chip = mtd->priv;
428 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200429 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200430
Sascha Hauerf8f96082009-06-04 17:12:26 +0200431 ret = *(uint16_t *)(host->data_buf + host->buf_start);
432 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200433
434 return ret;
435}
436
437/* Write data of length len to buffer buf. The data to be
438 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
439 * Operation by the NFC, the data is written to NAND Flash */
440static void mxc_nand_write_buf(struct mtd_info *mtd,
441 const u_char *buf, int len)
442{
443 struct nand_chip *nand_chip = mtd->priv;
444 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200445 u16 col = host->buf_start;
446 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200447
Sascha Hauerf8f96082009-06-04 17:12:26 +0200448 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200449
Sascha Hauerf8f96082009-06-04 17:12:26 +0200450 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200451
Sascha Hauerf8f96082009-06-04 17:12:26 +0200452 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200453}
454
455/* Read the data buffer from the NAND Flash. To read the data from NAND
456 * Flash first the data output cycle is initiated by the NFC, which copies
457 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
458 */
459static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
460{
461 struct nand_chip *nand_chip = mtd->priv;
462 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200463 u16 col = host->buf_start;
464 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200465
Sascha Hauerf8f96082009-06-04 17:12:26 +0200466 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200467
Sascha Hauerf8f96082009-06-04 17:12:26 +0200468 memcpy(buf, host->data_buf + col, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200469
Sascha Hauerf8f96082009-06-04 17:12:26 +0200470 host->buf_start += len;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200471}
472
473/* Used by the upper layer to verify the data in NAND Flash
474 * with the data in the buf. */
475static int mxc_nand_verify_buf(struct mtd_info *mtd,
476 const u_char *buf, int len)
477{
478 return -EFAULT;
479}
480
481/* This function is used by upper layer for select and
482 * deselect of the NAND chip */
483static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
484{
485 struct nand_chip *nand_chip = mtd->priv;
486 struct mxc_nand_host *host = nand_chip->priv;
487
Sascha Hauer34f6e152008-09-02 17:16:59 +0200488 switch (chip) {
489 case -1:
490 /* Disable the NFC clock */
491 if (host->clk_act) {
492 clk_disable(host->clk);
493 host->clk_act = 0;
494 }
495 break;
496 case 0:
497 /* Enable the NFC clock */
498 if (!host->clk_act) {
499 clk_enable(host->clk);
500 host->clk_act = 1;
501 }
502 break;
503
504 default:
505 break;
506 }
507}
508
Sascha Hauerf8f96082009-06-04 17:12:26 +0200509/*
510 * Function to transfer data to/from spare area.
511 */
512static void copy_spare(struct mtd_info *mtd, bool bfrom)
513{
514 struct nand_chip *this = mtd->priv;
515 struct mxc_nand_host *host = this->priv;
516 u16 i, j;
517 u16 n = mtd->writesize >> 9;
518 u8 *d = host->data_buf + mtd->writesize;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200519 u8 *s = host->spare0;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200520 u16 t = host->spare_len;
521
522 j = (mtd->oobsize / n >> 1) << 1;
523
524 if (bfrom) {
525 for (i = 0; i < n - 1; i++)
526 memcpy(d + i * j, s + i * t, j);
527
528 /* the last section */
529 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
530 } else {
531 for (i = 0; i < n - 1; i++)
532 memcpy(&s[i * t], &d[i * j], j);
533
534 /* the last section */
535 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
536 }
537}
538
Sascha Hauera3e65b62009-06-02 11:47:59 +0200539static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200540{
541 struct nand_chip *nand_chip = mtd->priv;
542 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200543
544 /* Write out column address, if necessary */
545 if (column != -1) {
546 /*
547 * MXC NANDFC can only perform full page+spare or
548 * spare-only read/write. When the upper layers
549 * layers perform a read/write buf operation,
Daniel Mack3ad2f3f2010-02-03 08:01:28 +0800550 * we will used the saved column address to index into
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551 * the full page.
552 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200553 host->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200554 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200555 /* another col addr cycle for 2k page */
Sascha Hauer5f973042010-08-06 15:53:06 +0200556 host->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200557 }
558
559 /* Write out page address, if necessary */
560 if (page_addr != -1) {
561 /* paddr_0 - p_addr_7 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200562 host->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200563
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200564 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400565 if (mtd->size >= 0x10000000) {
566 /* paddr_8 - paddr_15 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200567 host->send_addr(host, (page_addr >> 8) & 0xff, false);
568 host->send_addr(host, (page_addr >> 16) & 0xff, true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400569 } else
570 /* paddr_8 - paddr_15 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200571 host->send_addr(host, (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200572 } else {
573 /* One more address cycle for higher density devices */
574 if (mtd->size >= 0x4000000) {
575 /* paddr_8 - paddr_15 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200576 host->send_addr(host, (page_addr >> 8) & 0xff, false);
577 host->send_addr(host, (page_addr >> 16) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200578 } else
579 /* paddr_8 - paddr_15 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200580 host->send_addr(host, (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200581 }
582 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200583}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200584
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200585/*
586 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
587 * on how much oob the nand chip has. For 8bit ecc we need at least
588 * 26 bytes of oob data per 512 byte block.
589 */
590static int get_eccsize(struct mtd_info *mtd)
591{
592 int oobbytes_per_512 = 0;
593
594 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
595
596 if (oobbytes_per_512 < 26)
597 return 4;
598 else
599 return 8;
600}
601
Sascha Hauer5f973042010-08-06 15:53:06 +0200602static void preset_v1_v2(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200603{
604 struct nand_chip *nand_chip = mtd->priv;
605 struct mxc_nand_host *host = nand_chip->priv;
606 uint16_t tmp;
607
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200608 /* enable interrupt, disable spare enable */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200609 tmp = readw(NFC_V1_V2_CONFIG1);
610 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
611 tmp &= ~NFC_V1_V2_CONFIG1_SP_EN;
Ivo Claryssed4840182010-04-08 16:14:44 +0200612 if (nand_chip->ecc.mode == NAND_ECC_HW) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200613 tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
Ivo Claryssed4840182010-04-08 16:14:44 +0200614 } else {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200615 tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
Ivo Claryssed4840182010-04-08 16:14:44 +0200616 }
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200617
618 if (nfc_is_v21() && mtd->writesize) {
619 host->eccsize = get_eccsize(mtd);
620 if (host->eccsize == 4)
621 tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
622 } else {
623 host->eccsize = 1;
624 }
625
Sascha Hauer1bc99182010-08-06 15:53:08 +0200626 writew(tmp, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200627 /* preset operation */
628
629 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200630 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200631
632 /* Blocks to be unlocked */
633 if (nfc_is_v21()) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200634 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR);
635 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR);
Ivo Claryssed4840182010-04-08 16:14:44 +0200636 } else if (nfc_is_v1()) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200637 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
638 writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
Ivo Claryssed4840182010-04-08 16:14:44 +0200639 } else
640 BUG();
641
642 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200643 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200644}
645
Sascha Hauer34f6e152008-09-02 17:16:59 +0200646/* Used by the upper layer to write command to NAND Flash for
647 * different operations to be carried out on NAND Flash */
648static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
649 int column, int page_addr)
650{
651 struct nand_chip *nand_chip = mtd->priv;
652 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200653
654 DEBUG(MTD_DEBUG_LEVEL3,
655 "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
656 command, column, page_addr);
657
658 /* Reset command state information */
659 host->status_request = false;
660
661 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200662 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +0200663 case NAND_CMD_RESET:
Sascha Hauer5f973042010-08-06 15:53:06 +0200664 host->preset(mtd);
665 host->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +0200666 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200667
Sascha Hauer34f6e152008-09-02 17:16:59 +0200668 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +0200669 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200670 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +0200671
Sascha Hauer5f973042010-08-06 15:53:06 +0200672 host->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +0200673 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200674 break;
675
Sascha Hauer34f6e152008-09-02 17:16:59 +0200676 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +0200677 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +0200678 if (command == NAND_CMD_READ0)
679 host->buf_start = column;
680 else
681 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200682
Sascha Hauer6c499392010-05-28 10:02:17 +0200683 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +0200684
Sascha Hauer5f973042010-08-06 15:53:06 +0200685 host->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +0200686 mxc_do_addr_cycle(mtd, column, page_addr);
687
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200688 if (mtd->writesize > 512)
Sascha Hauer5f973042010-08-06 15:53:06 +0200689 host->send_cmd(host, NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200690
Sascha Hauer5f973042010-08-06 15:53:06 +0200691 host->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +0200692
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200693 memcpy(host->data_buf, host->main_area0, mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +0200694 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200695 break;
696
Sascha Hauer34f6e152008-09-02 17:16:59 +0200697 case NAND_CMD_SEQIN:
Sascha Hauer6c499392010-05-28 10:02:17 +0200698 if (column >= mtd->writesize)
699 /* call ourself to read a page */
700 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200701
Sascha Hauer6c499392010-05-28 10:02:17 +0200702 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +0200703
Sascha Hauer5f973042010-08-06 15:53:06 +0200704 host->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +0200705 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200706 break;
707
708 case NAND_CMD_PAGEPROG:
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200709 memcpy(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200710 copy_spare(mtd, false);
Sascha Hauer5f973042010-08-06 15:53:06 +0200711 host->send_page(mtd, NFC_INPUT);
712 host->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +0200713 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200714 break;
715
Sascha Hauer34f6e152008-09-02 17:16:59 +0200716 case NAND_CMD_READID:
Sascha Hauer5f973042010-08-06 15:53:06 +0200717 host->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +0200718 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer5f973042010-08-06 15:53:06 +0200719 host->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +0200720 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200721 break;
722
Sascha Hauer89121a62009-06-04 17:18:01 +0200723 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +0200724 case NAND_CMD_ERASE2:
Sascha Hauer5f973042010-08-06 15:53:06 +0200725 host->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +0200726 mxc_do_addr_cycle(mtd, column, page_addr);
727
Sascha Hauer34f6e152008-09-02 17:16:59 +0200728 break;
729 }
730}
731
Sascha Hauerf1372052009-10-21 14:25:27 +0200732/*
733 * The generic flash bbt decriptors overlap with our ecc
734 * hardware, so define some i.MX specific ones.
735 */
736static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
737static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
738
739static struct nand_bbt_descr bbt_main_descr = {
740 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
741 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
742 .offs = 0,
743 .len = 4,
744 .veroffs = 4,
745 .maxblocks = 4,
746 .pattern = bbt_pattern,
747};
748
749static struct nand_bbt_descr bbt_mirror_descr = {
750 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
751 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
752 .offs = 0,
753 .len = 4,
754 .veroffs = 4,
755 .maxblocks = 4,
756 .pattern = mirror_pattern,
757};
758
Sascha Hauer34f6e152008-09-02 17:16:59 +0200759static int __init mxcnd_probe(struct platform_device *pdev)
760{
761 struct nand_chip *this;
762 struct mtd_info *mtd;
763 struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
764 struct mxc_nand_host *host;
765 struct resource *res;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200766 int err = 0, nr_parts = 0;
Sascha Hauer94671142009-10-05 12:14:21 +0200767 struct nand_ecclayout *oob_smallpage, *oob_largepage;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200768
769 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +0200770 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
771 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200772 if (!host)
773 return -ENOMEM;
774
Sascha Hauerf8f96082009-06-04 17:12:26 +0200775 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200776
Sascha Hauer34f6e152008-09-02 17:16:59 +0200777 host->dev = &pdev->dev;
778 /* structures must be linked */
779 this = &host->nand;
780 mtd = &host->mtd;
781 mtd->priv = this;
782 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -0700783 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +0200784 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200785
786 /* 50 us command delay time */
787 this->chip_delay = 5;
788
789 this->priv = host;
790 this->dev_ready = mxc_nand_dev_ready;
791 this->cmdfunc = mxc_nand_command;
792 this->select_chip = mxc_nand_select_chip;
793 this->read_byte = mxc_nand_read_byte;
794 this->read_word = mxc_nand_read_word;
795 this->write_buf = mxc_nand_write_buf;
796 this->read_buf = mxc_nand_read_buf;
797 this->verify_buf = mxc_nand_verify_buf;
798
Sascha Hauere65fb002009-02-16 14:29:10 +0100799 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +0400800 if (IS_ERR(host->clk)) {
801 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200802 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +0400803 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200804
805 clk_enable(host->clk);
806 host->clk_act = 1;
807
808 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
809 if (!res) {
810 err = -ENODEV;
811 goto eres;
812 }
813
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200814 host->base = ioremap(res->start, resource_size(res));
815 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +0400816 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200817 goto eres;
818 }
819
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200820 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +0200821
Sascha Hauer5f973042010-08-06 15:53:06 +0200822 if (nfc_is_v1() || nfc_is_v21()) {
823 host->preset = preset_v1_v2;
824 host->send_cmd = send_cmd_v1_v2;
825 host->send_addr = send_addr_v1_v2;
826 host->send_page = send_page_v1_v2;
827 host->send_read_id = send_read_id_v1_v2;
828 host->get_dev_status = get_dev_status_v1_v2;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200829 host->check_int = check_int_v1_v2;
Sascha Hauer5f973042010-08-06 15:53:06 +0200830 }
831
Sascha Hauer94671142009-10-05 12:14:21 +0200832 if (nfc_is_v21()) {
Sascha Hauer938cf992010-08-06 15:53:04 +0200833 host->regs = host->base + 0x1e00;
Sascha Hauer94671142009-10-05 12:14:21 +0200834 host->spare0 = host->base + 0x1000;
835 host->spare_len = 64;
836 oob_smallpage = &nandv2_hw_eccoob_smallpage;
837 oob_largepage = &nandv2_hw_eccoob_largepage;
Ivo Claryssed4840182010-04-08 16:14:44 +0200838 this->ecc.bytes = 9;
Sascha Hauer94671142009-10-05 12:14:21 +0200839 } else if (nfc_is_v1()) {
Sascha Hauer938cf992010-08-06 15:53:04 +0200840 host->regs = host->base + 0xe00;
Sascha Hauer94671142009-10-05 12:14:21 +0200841 host->spare0 = host->base + 0x800;
842 host->spare_len = 16;
843 oob_smallpage = &nandv1_hw_eccoob_smallpage;
844 oob_largepage = &nandv1_hw_eccoob_largepage;
Sascha Hauer94671142009-10-05 12:14:21 +0200845 this->ecc.bytes = 3;
846 } else
847 BUG();
Sascha Hauer34f6e152008-09-02 17:16:59 +0200848
Sascha Hauer13e1add2009-10-21 10:39:05 +0200849 this->ecc.size = 512;
Sascha Hauer94671142009-10-05 12:14:21 +0200850 this->ecc.layout = oob_smallpage;
Sascha Hauer13e1add2009-10-21 10:39:05 +0200851
852 if (pdata->hw_ecc) {
853 this->ecc.calculate = mxc_nand_calculate_ecc;
854 this->ecc.hwctl = mxc_nand_enable_hwecc;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200855 if (nfc_is_v1())
856 this->ecc.correct = mxc_nand_correct_data_v1;
857 else
858 this->ecc.correct = mxc_nand_correct_data_v2_v3;
Sascha Hauer13e1add2009-10-21 10:39:05 +0200859 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +0200860 } else {
861 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200862 }
863
Sascha Hauer34f6e152008-09-02 17:16:59 +0200864 /* NAND bus width determines access funtions used by upper layer */
Sascha Hauer13e1add2009-10-21 10:39:05 +0200865 if (pdata->width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200866 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +0200867
Sascha Hauerf1372052009-10-21 14:25:27 +0200868 if (pdata->flash_bbt) {
869 this->bbt_td = &bbt_main_descr;
870 this->bbt_md = &bbt_mirror_descr;
871 /* update flash based bbt */
872 this->options |= NAND_USE_FLASH_BBT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200873 }
874
Ivo Claryssed4840182010-04-08 16:14:44 +0200875 init_waitqueue_head(&host->irq_waitq);
876
877 host->irq = platform_get_irq(pdev, 0);
878
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200879 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +0200880 if (err)
881 goto eirq;
882
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400883 /* first scan to find the device and get the page size */
David Woodhouse5e81e882010-02-26 18:32:56 +0000884 if (nand_scan_ident(mtd, 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400885 err = -ENXIO;
886 goto escan;
887 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200888
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200889 /* Call preset again, with correct writesize this time */
890 host->preset(mtd);
891
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200892 if (mtd->writesize == 2048)
Sascha Hauer94671142009-10-05 12:14:21 +0200893 this->ecc.layout = oob_largepage;
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400894
895 /* second phase scan */
896 if (nand_scan_tail(mtd)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200897 err = -ENXIO;
898 goto escan;
899 }
900
901 /* Register the partitions */
902#ifdef CONFIG_MTD_PARTITIONS
903 nr_parts =
904 parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
905 if (nr_parts > 0)
906 add_mtd_partitions(mtd, host->parts, nr_parts);
907 else
908#endif
909 {
910 pr_info("Registering %s as whole device\n", mtd->name);
911 add_mtd_device(mtd);
912 }
913
914 platform_set_drvdata(pdev, host);
915
916 return 0;
917
918escan:
Magnus Liljab258fd82009-05-08 21:57:47 +0200919 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200920eirq:
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200921 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200922eres:
923 clk_put(host->clk);
924eclk:
925 kfree(host);
926
927 return err;
928}
929
Uwe Kleine-König51eeb872009-12-07 09:44:05 +0000930static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200931{
932 struct mxc_nand_host *host = platform_get_drvdata(pdev);
933
934 clk_put(host->clk);
935
936 platform_set_drvdata(pdev, NULL);
937
938 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +0200939 free_irq(host->irq, host);
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200940 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200941 kfree(host);
942
943 return 0;
944}
945
Sascha Hauer34f6e152008-09-02 17:16:59 +0200946static struct platform_driver mxcnd_driver = {
947 .driver = {
948 .name = DRIVER_NAME,
Eric Bénard04dd0d32010-06-17 20:59:04 +0200949 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +0100950 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +0200951};
952
953static int __init mxc_nd_init(void)
954{
Vladimir Barinov8541c112009-04-23 15:47:22 +0400955 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200956}
957
958static void __exit mxc_nd_cleanup(void)
959{
960 /* Unregister the device structure */
961 platform_driver_unregister(&mxcnd_driver);
962}
963
964module_init(mxc_nd_init);
965module_exit(mxc_nd_cleanup);
966
967MODULE_AUTHOR("Freescale Semiconductor, Inc.");
968MODULE_DESCRIPTION("MXC NAND MTD driver");
969MODULE_LICENSE("GPL");