blob: 03664d5742d99c596352be928251958b9a8df374 [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>
Sascha Hauer63f14742010-10-18 10:16:26 +020033#include <linux/irq.h>
34#include <linux/completion.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020035
36#include <asm/mach/flash.h>
37#include <mach/mxc_nand.h>
Sascha Hauer94671142009-10-05 12:14:21 +020038#include <mach/hardware.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020039
40#define DRIVER_NAME "mxc_nand"
41
Sascha Hauer94671142009-10-05 12:14:21 +020042#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
Ivo Claryssea47bfd22010-04-08 16:16:51 +020043#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
Jason Liuc97926d2011-08-22 14:13:17 +080044#define nfc_is_v3_2() (cpu_is_mx51() || cpu_is_mx53())
Sascha Hauer71ec5152010-08-06 15:53:11 +020045#define nfc_is_v3() nfc_is_v3_2()
Sascha Hauer94671142009-10-05 12:14:21 +020046
Sascha Hauer34f6e152008-09-02 17:16:59 +020047/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020048#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
49#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
50#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
51#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
52#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
53#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
54#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
55#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
56#define NFC_V1_V2_WRPROT (host->regs + 0x12)
57#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
58#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
Baruch Siachd178e3e2011-03-14 09:01:56 +020059#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
60#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
61#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
62#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
63#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
64#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
65#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
66#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
Sascha Hauer1bc99182010-08-06 15:53:08 +020067#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
68#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
69#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020070
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020071#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020072#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
73#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
74#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
75#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
76#define NFC_V1_V2_CONFIG1_RST (1 << 6)
77#define NFC_V1_V2_CONFIG1_CE (1 << 7)
Sascha Hauerb8db2f52010-08-09 15:04:19 +020078#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
79#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
80#define NFC_V2_CONFIG1_FP_INT (1 << 11)
Sascha Hauer34f6e152008-09-02 17:16:59 +020081
Sascha Hauer1bc99182010-08-06 15:53:08 +020082#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020083
Sascha Hauer1bc99182010-08-06 15:53:08 +020084/*
85 * Operation modes for the NFC. Valid for v1, v2 and v3
86 * type controllers.
87 */
88#define NFC_CMD (1 << 0)
89#define NFC_ADDR (1 << 1)
90#define NFC_INPUT (1 << 2)
91#define NFC_OUTPUT (1 << 3)
92#define NFC_ID (1 << 4)
93#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020094
Sascha Hauer71ec5152010-08-06 15:53:11 +020095#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
96#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
Sascha Hauer34f6e152008-09-02 17:16:59 +020097
Sascha Hauer71ec5152010-08-06 15:53:11 +020098#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
99#define NFC_V3_CONFIG1_SP_EN (1 << 0)
100#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200101
Sascha Hauer71ec5152010-08-06 15:53:11 +0200102#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200103
Sascha Hauer71ec5152010-08-06 15:53:11 +0200104#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200105
Sascha Hauer71ec5152010-08-06 15:53:11 +0200106#define NFC_V3_WRPROT (host->regs_ip + 0x0)
107#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
108#define NFC_V3_WRPROT_LOCK (1 << 1)
109#define NFC_V3_WRPROT_UNLOCK (1 << 2)
110#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
111
112#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
113
114#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
115#define NFC_V3_CONFIG2_PS_512 (0 << 0)
116#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
117#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
118#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
119#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
120#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
121#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
122#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
123#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7)
124#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
125#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
126#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
127#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
128
129#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
130#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
131#define NFC_V3_CONFIG3_FW8 (1 << 3)
132#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
133#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
134#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
135#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
136
137#define NFC_V3_IPC (host->regs_ip + 0x2C)
138#define NFC_V3_IPC_CREQ (1 << 0)
139#define NFC_V3_IPC_INT (1 << 31)
140
141#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200142
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200143struct mxc_nand_host;
144
145struct mxc_nand_devtype_data {
146 void (*preset)(struct mtd_info *);
147 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
148 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
149 void (*send_page)(struct mtd_info *, unsigned int);
150 void (*send_read_id)(struct mxc_nand_host *);
151 uint16_t (*get_dev_status)(struct mxc_nand_host *);
152 int (*check_int)(struct mxc_nand_host *);
153 void (*irq_control)(struct mxc_nand_host *, int);
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200154 u32 (*get_ecc_status)(struct mxc_nand_host *);
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +0200155 struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k;
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200156 void (*select_chip)(struct mtd_info *mtd, int chip);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200157};
158
Sascha Hauer34f6e152008-09-02 17:16:59 +0200159struct mxc_nand_host {
160 struct mtd_info mtd;
161 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200162 struct device *dev;
163
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200164 void *spare0;
165 void *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200166
167 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200168 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200169 void __iomem *regs_axi;
170 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200171 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200172 struct clk *clk;
173 int clk_act;
174 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200175 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200176 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200177
Sascha Hauer63f14742010-10-18 10:16:26 +0200178 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200179
180 uint8_t *data_buf;
181 unsigned int buf_start;
182 int spare_len;
Sascha Hauer5f973042010-08-06 15:53:06 +0200183
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200184 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König85569582012-04-23 11:23:34 +0200185
186 /*
187 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
188 * (CONFIG1:INT_MSK is set). To handle this the driver uses
189 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
190 */
191 int irqpending_quirk;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200192};
193
Sascha Hauer34f6e152008-09-02 17:16:59 +0200194/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200195static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200196 .eccbytes = 5,
197 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200198 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200199};
200
Sascha Hauer94671142009-10-05 12:14:21 +0200201static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400202 .eccbytes = 20,
203 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
204 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
205 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200206};
207
Sascha Hauer94671142009-10-05 12:14:21 +0200208/* OOB description for 512 byte pages with 16 byte OOB */
209static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
210 .eccbytes = 1 * 9,
211 .eccpos = {
212 7, 8, 9, 10, 11, 12, 13, 14, 15
213 },
214 .oobfree = {
215 {.offset = 0, .length = 5}
216 }
217};
218
219/* OOB description for 2048 byte pages with 64 byte OOB */
220static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
221 .eccbytes = 4 * 9,
222 .eccpos = {
223 7, 8, 9, 10, 11, 12, 13, 14, 15,
224 23, 24, 25, 26, 27, 28, 29, 30, 31,
225 39, 40, 41, 42, 43, 44, 45, 46, 47,
226 55, 56, 57, 58, 59, 60, 61, 62, 63
227 },
228 .oobfree = {
229 {.offset = 2, .length = 4},
230 {.offset = 16, .length = 7},
231 {.offset = 32, .length = 7},
232 {.offset = 48, .length = 7}
233 }
234};
235
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200236/* OOB description for 4096 byte pages with 128 byte OOB */
237static struct nand_ecclayout nandv2_hw_eccoob_4k = {
238 .eccbytes = 8 * 9,
239 .eccpos = {
240 7, 8, 9, 10, 11, 12, 13, 14, 15,
241 23, 24, 25, 26, 27, 28, 29, 30, 31,
242 39, 40, 41, 42, 43, 44, 45, 46, 47,
243 55, 56, 57, 58, 59, 60, 61, 62, 63,
244 71, 72, 73, 74, 75, 76, 77, 78, 79,
245 87, 88, 89, 90, 91, 92, 93, 94, 95,
246 103, 104, 105, 106, 107, 108, 109, 110, 111,
247 119, 120, 121, 122, 123, 124, 125, 126, 127,
248 },
249 .oobfree = {
250 {.offset = 2, .length = 4},
251 {.offset = 16, .length = 7},
252 {.offset = 32, .length = 7},
253 {.offset = 48, .length = 7},
254 {.offset = 64, .length = 7},
255 {.offset = 80, .length = 7},
256 {.offset = 96, .length = 7},
257 {.offset = 112, .length = 7},
258 }
259};
260
Sascha Hauer34f6e152008-09-02 17:16:59 +0200261static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200262
Sascha Hauer71ec5152010-08-06 15:53:11 +0200263static int check_int_v3(struct mxc_nand_host *host)
264{
265 uint32_t tmp;
266
267 tmp = readl(NFC_V3_IPC);
268 if (!(tmp & NFC_V3_IPC_INT))
269 return 0;
270
271 tmp &= ~NFC_V3_IPC_INT;
272 writel(tmp, NFC_V3_IPC);
273
274 return 1;
275}
276
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200277static int check_int_v1_v2(struct mxc_nand_host *host)
278{
279 uint32_t tmp;
280
Sascha Hauer1bc99182010-08-06 15:53:08 +0200281 tmp = readw(NFC_V1_V2_CONFIG2);
282 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200283 return 0;
284
Uwe Kleine-König85569582012-04-23 11:23:34 +0200285 if (!host->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200286 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200287
288 return 1;
289}
290
Sascha Hauer63f14742010-10-18 10:16:26 +0200291static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
292{
293 uint16_t tmp;
294
295 tmp = readw(NFC_V1_V2_CONFIG1);
296
297 if (activate)
298 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
299 else
300 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
301
302 writew(tmp, NFC_V1_V2_CONFIG1);
303}
304
305static void irq_control_v3(struct mxc_nand_host *host, int activate)
306{
307 uint32_t tmp;
308
309 tmp = readl(NFC_V3_CONFIG2);
310
311 if (activate)
312 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
313 else
314 tmp |= NFC_V3_CONFIG2_INT_MSK;
315
316 writel(tmp, NFC_V3_CONFIG2);
317}
318
Uwe Kleine-König85569582012-04-23 11:23:34 +0200319static void irq_control(struct mxc_nand_host *host, int activate)
320{
321 if (host->irqpending_quirk) {
322 if (activate)
323 enable_irq(host->irq);
324 else
325 disable_irq_nosync(host->irq);
326 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200327 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200328 }
329}
330
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200331static u32 get_ecc_status_v1(struct mxc_nand_host *host)
332{
333 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
334}
335
336static u32 get_ecc_status_v2(struct mxc_nand_host *host)
337{
338 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
339}
340
341static u32 get_ecc_status_v3(struct mxc_nand_host *host)
342{
343 return readl(NFC_V3_ECC_STATUS_RESULT);
344}
345
Uwe Kleine-König85569582012-04-23 11:23:34 +0200346static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
347{
348 struct mxc_nand_host *host = dev_id;
349
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200350 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200351 return IRQ_NONE;
352
353 irq_control(host, 0);
354
355 complete(&host->op_completion);
356
357 return IRQ_HANDLED;
358}
359
Sascha Hauer34f6e152008-09-02 17:16:59 +0200360/* This function polls the NANDFC to wait for the basic operation to
361 * complete by checking the INT bit of config2 register.
362 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200363static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200364{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200365 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200366
367 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200368 if (!host->devtype_data->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200369 INIT_COMPLETION(host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200370 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200371 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200372 }
373 } else {
374 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200375 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200376 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200377
Sascha Hauer34f6e152008-09-02 17:16:59 +0200378 udelay(1);
379 }
Roel Kluin43950a62009-06-04 16:24:59 +0200380 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700381 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200382 }
383}
384
Sascha Hauer71ec5152010-08-06 15:53:11 +0200385static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
386{
387 /* fill command */
388 writel(cmd, NFC_V3_FLASH_CMD);
389
390 /* send out command */
391 writel(NFC_CMD, NFC_V3_LAUNCH);
392
393 /* Wait for operation to complete */
394 wait_op_done(host, useirq);
395}
396
Sascha Hauer34f6e152008-09-02 17:16:59 +0200397/* This function issues the specified command to the NAND device and
398 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200399static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200400{
Brian Norris289c0522011-07-19 10:06:09 -0700401 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200402
Sascha Hauer1bc99182010-08-06 15:53:08 +0200403 writew(cmd, NFC_V1_V2_FLASH_CMD);
404 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200405
Uwe Kleine-König85569582012-04-23 11:23:34 +0200406 if (host->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200407 int max_retries = 100;
408 /* Reset completion is indicated by NFC_CONFIG2 */
409 /* being set to 0 */
410 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200411 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200412 break;
413 }
414 udelay(1);
415 }
416 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700417 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200418 } else {
419 /* Wait for operation to complete */
420 wait_op_done(host, useirq);
421 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200422}
423
Sascha Hauer71ec5152010-08-06 15:53:11 +0200424static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
425{
426 /* fill address */
427 writel(addr, NFC_V3_FLASH_ADDR0);
428
429 /* send out address */
430 writel(NFC_ADDR, NFC_V3_LAUNCH);
431
432 wait_op_done(host, 0);
433}
434
Sascha Hauer34f6e152008-09-02 17:16:59 +0200435/* This function sends an address (or partial address) to the
436 * NAND device. The address is used to select the source/destination for
437 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200438static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200439{
Brian Norris289c0522011-07-19 10:06:09 -0700440 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200441
Sascha Hauer1bc99182010-08-06 15:53:08 +0200442 writew(addr, NFC_V1_V2_FLASH_ADDR);
443 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200444
445 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200446 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200447}
448
Sascha Hauer71ec5152010-08-06 15:53:11 +0200449static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
450{
451 struct nand_chip *nand_chip = mtd->priv;
452 struct mxc_nand_host *host = nand_chip->priv;
453 uint32_t tmp;
454
455 tmp = readl(NFC_V3_CONFIG1);
456 tmp &= ~(7 << 4);
457 writel(tmp, NFC_V3_CONFIG1);
458
459 /* transfer data from NFC ram to nand */
460 writel(ops, NFC_V3_LAUNCH);
461
462 wait_op_done(host, false);
463}
464
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200465static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
466{
467 struct nand_chip *nand_chip = mtd->priv;
468 struct mxc_nand_host *host = nand_chip->priv;
469
470 /* NANDFC buffer 0 is used for page read/write */
471 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
472
473 writew(ops, NFC_V1_V2_CONFIG2);
474
475 /* Wait for operation to complete */
476 wait_op_done(host, true);
477}
478
479static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200480{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200481 struct nand_chip *nand_chip = mtd->priv;
482 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200483 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200484
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200485 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200486 bufs = 4;
487 else
488 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200489
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200490 for (i = 0; i < bufs; i++) {
491
492 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200493 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200494
Sascha Hauer1bc99182010-08-06 15:53:08 +0200495 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200496
497 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200498 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200499 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200500}
501
Sascha Hauer71ec5152010-08-06 15:53:11 +0200502static void send_read_id_v3(struct mxc_nand_host *host)
503{
504 /* Read ID into main buffer */
505 writel(NFC_ID, NFC_V3_LAUNCH);
506
507 wait_op_done(host, true);
508
509 memcpy(host->data_buf, host->main_area0, 16);
510}
511
Sascha Hauer34f6e152008-09-02 17:16:59 +0200512/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200513static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200514{
515 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200516
517 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200518 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200519
Sascha Hauer1bc99182010-08-06 15:53:08 +0200520 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200521
522 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200523 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200524
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200525 memcpy(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200526
527 if (this->options & NAND_BUSWIDTH_16) {
528 /* compress the ID info */
529 host->data_buf[1] = host->data_buf[2];
530 host->data_buf[2] = host->data_buf[4];
531 host->data_buf[3] = host->data_buf[6];
532 host->data_buf[4] = host->data_buf[8];
533 host->data_buf[5] = host->data_buf[10];
534 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200535}
536
Sascha Hauer71ec5152010-08-06 15:53:11 +0200537static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200538{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200539 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200540 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200541
Sascha Hauer71ec5152010-08-06 15:53:11 +0200542 return readl(NFC_V3_CONFIG1) >> 16;
543}
544
Sascha Hauer34f6e152008-09-02 17:16:59 +0200545/* This function requests the NANDFC to perform a read of the
546 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200547static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200548{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200549 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200550 uint32_t store;
551 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200552
Baruch Siachd178e3e2011-03-14 09:01:56 +0200553 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200554
555 /*
556 * The device status is stored in main_area0. To
557 * prevent corruption of the buffer save the value
558 * and restore it afterwards.
559 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200560 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200561
Sascha Hauer1bc99182010-08-06 15:53:08 +0200562 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200563 wait_op_done(host, true);
564
Sascha Hauer34f6e152008-09-02 17:16:59 +0200565 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200566
Sascha Hauer34f6e152008-09-02 17:16:59 +0200567 writel(store, main_buf);
568
569 return ret;
570}
571
572/* This functions is used by upper layer to checks if device is ready */
573static int mxc_nand_dev_ready(struct mtd_info *mtd)
574{
575 /*
576 * NFC handles R/B internally. Therefore, this function
577 * always returns status as ready.
578 */
579 return 1;
580}
581
582static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
583{
584 /*
585 * If HW ECC is enabled, we turn it on during init. There is
586 * no need to enable again here.
587 */
588}
589
Sascha Hauer94f77e52010-08-06 15:53:09 +0200590static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200591 u_char *read_ecc, u_char *calc_ecc)
592{
593 struct nand_chip *nand_chip = mtd->priv;
594 struct mxc_nand_host *host = nand_chip->priv;
595
596 /*
597 * 1-Bit errors are automatically corrected in HW. No need for
598 * additional correction. 2-Bit errors cannot be corrected by
599 * HW ECC, so we need to return failure
600 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200601 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200602
603 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700604 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200605 return -1;
606 }
607
608 return 0;
609}
610
Sascha Hauer94f77e52010-08-06 15:53:09 +0200611static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
612 u_char *read_ecc, u_char *calc_ecc)
613{
614 struct nand_chip *nand_chip = mtd->priv;
615 struct mxc_nand_host *host = nand_chip->priv;
616 u32 ecc_stat, err;
617 int no_subpages = 1;
618 int ret = 0;
619 u8 ecc_bit_mask, err_limit;
620
621 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
622 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
623
624 no_subpages = mtd->writesize >> 9;
625
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200626 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200627
628 do {
629 err = ecc_stat & ecc_bit_mask;
630 if (err > err_limit) {
631 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
632 return -1;
633 } else {
634 ret += err;
635 }
636 ecc_stat >>= 4;
637 } while (--no_subpages);
638
639 mtd->ecc_stats.corrected += ret;
640 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
641
642 return ret;
643}
644
Sascha Hauer34f6e152008-09-02 17:16:59 +0200645static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
646 u_char *ecc_code)
647{
648 return 0;
649}
650
651static u_char mxc_nand_read_byte(struct mtd_info *mtd)
652{
653 struct nand_chip *nand_chip = mtd->priv;
654 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200655 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200656
657 /* Check for status request */
658 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200659 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200660
Sascha Hauerf8f96082009-06-04 17:12:26 +0200661 ret = *(uint8_t *)(host->data_buf + host->buf_start);
662 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200663
664 return ret;
665}
666
667static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
668{
669 struct nand_chip *nand_chip = mtd->priv;
670 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200671 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200672
Sascha Hauerf8f96082009-06-04 17:12:26 +0200673 ret = *(uint16_t *)(host->data_buf + host->buf_start);
674 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200675
676 return ret;
677}
678
679/* Write data of length len to buffer buf. The data to be
680 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
681 * Operation by the NFC, the data is written to NAND Flash */
682static void mxc_nand_write_buf(struct mtd_info *mtd,
683 const u_char *buf, int len)
684{
685 struct nand_chip *nand_chip = mtd->priv;
686 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200687 u16 col = host->buf_start;
688 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200689
Sascha Hauerf8f96082009-06-04 17:12:26 +0200690 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200691
Sascha Hauerf8f96082009-06-04 17:12:26 +0200692 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200693
Sascha Hauerf8f96082009-06-04 17:12:26 +0200694 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200695}
696
697/* Read the data buffer from the NAND Flash. To read the data from NAND
698 * Flash first the data output cycle is initiated by the NFC, which copies
699 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
700 */
701static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
702{
703 struct nand_chip *nand_chip = mtd->priv;
704 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200705 u16 col = host->buf_start;
706 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200707
Sascha Hauerf8f96082009-06-04 17:12:26 +0200708 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200709
Baruch Siach5d9d9932011-03-02 16:47:55 +0200710 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200711
Baruch Siach5d9d9932011-03-02 16:47:55 +0200712 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200713}
714
715/* Used by the upper layer to verify the data in NAND Flash
716 * with the data in the buf. */
717static int mxc_nand_verify_buf(struct mtd_info *mtd,
718 const u_char *buf, int len)
719{
720 return -EFAULT;
721}
722
723/* This function is used by upper layer for select and
724 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200725static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
726{
727 struct nand_chip *nand_chip = mtd->priv;
728 struct mxc_nand_host *host = nand_chip->priv;
729
730 if (chip == -1) {
731 /* Disable the NFC clock */
732 if (host->clk_act) {
733 clk_disable(host->clk);
734 host->clk_act = 0;
735 }
736 return;
737 }
738
739 if (!host->clk_act) {
740 /* Enable the NFC clock */
741 clk_enable(host->clk);
742 host->clk_act = 1;
743 }
744}
745
746static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200747{
748 struct nand_chip *nand_chip = mtd->priv;
749 struct mxc_nand_host *host = nand_chip->priv;
750
Baruch Siachd178e3e2011-03-14 09:01:56 +0200751 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200752 /* Disable the NFC clock */
753 if (host->clk_act) {
754 clk_disable(host->clk);
755 host->clk_act = 0;
756 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200757 return;
758 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200759
Baruch Siachd178e3e2011-03-14 09:01:56 +0200760 if (!host->clk_act) {
761 /* Enable the NFC clock */
762 clk_enable(host->clk);
763 host->clk_act = 1;
764 }
765
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200766 host->active_cs = chip;
767 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200768}
769
Sascha Hauerf8f96082009-06-04 17:12:26 +0200770/*
771 * Function to transfer data to/from spare area.
772 */
773static void copy_spare(struct mtd_info *mtd, bool bfrom)
774{
775 struct nand_chip *this = mtd->priv;
776 struct mxc_nand_host *host = this->priv;
777 u16 i, j;
778 u16 n = mtd->writesize >> 9;
779 u8 *d = host->data_buf + mtd->writesize;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200780 u8 *s = host->spare0;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200781 u16 t = host->spare_len;
782
783 j = (mtd->oobsize / n >> 1) << 1;
784
785 if (bfrom) {
786 for (i = 0; i < n - 1; i++)
787 memcpy(d + i * j, s + i * t, j);
788
789 /* the last section */
790 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
791 } else {
792 for (i = 0; i < n - 1; i++)
793 memcpy(&s[i * t], &d[i * j], j);
794
795 /* the last section */
796 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
797 }
798}
799
Sascha Hauera3e65b62009-06-02 11:47:59 +0200800static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200801{
802 struct nand_chip *nand_chip = mtd->priv;
803 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200804
805 /* Write out column address, if necessary */
806 if (column != -1) {
807 /*
808 * MXC NANDFC can only perform full page+spare or
809 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100810 * perform a read/write buf operation, the saved column
811 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200812 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200813 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200814 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200815 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200816 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200817 }
818
819 /* Write out page address, if necessary */
820 if (page_addr != -1) {
821 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200822 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200823
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200824 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400825 if (mtd->size >= 0x10000000) {
826 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200827 host->devtype_data->send_addr(host,
828 (page_addr >> 8) & 0xff,
829 false);
830 host->devtype_data->send_addr(host,
831 (page_addr >> 16) & 0xff,
832 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400833 } else
834 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200835 host->devtype_data->send_addr(host,
836 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200837 } else {
838 /* One more address cycle for higher density devices */
839 if (mtd->size >= 0x4000000) {
840 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200841 host->devtype_data->send_addr(host,
842 (page_addr >> 8) & 0xff,
843 false);
844 host->devtype_data->send_addr(host,
845 (page_addr >> 16) & 0xff,
846 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200847 } else
848 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200849 host->devtype_data->send_addr(host,
850 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200851 }
852 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200853}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200854
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200855/*
856 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
857 * on how much oob the nand chip has. For 8bit ecc we need at least
858 * 26 bytes of oob data per 512 byte block.
859 */
860static int get_eccsize(struct mtd_info *mtd)
861{
862 int oobbytes_per_512 = 0;
863
864 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
865
866 if (oobbytes_per_512 < 26)
867 return 4;
868 else
869 return 8;
870}
871
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200872static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200873{
874 struct nand_chip *nand_chip = mtd->priv;
875 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200876 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200877
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200878 if (nand_chip->ecc.mode == NAND_ECC_HW)
879 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
880
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200881 if (!host->irqpending_quirk)
882 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
883
884 host->eccsize = 1;
885
886 writew(config1, NFC_V1_V2_CONFIG1);
887 /* preset operation */
888
889 /* Unlock the internal RAM Buffer */
890 writew(0x2, NFC_V1_V2_CONFIG);
891
892 /* Blocks to be unlocked */
893 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
894 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
895
896 /* Unlock Block Command for given address range */
897 writew(0x4, NFC_V1_V2_WRPROT);
898}
899
900static void preset_v2(struct mtd_info *mtd)
901{
902 struct nand_chip *nand_chip = mtd->priv;
903 struct mxc_nand_host *host = nand_chip->priv;
904 uint16_t config1 = 0;
905
906 if (nand_chip->ecc.mode == NAND_ECC_HW)
907 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
908
909 config1 |= NFC_V2_CONFIG1_FP_INT;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200910
Uwe Kleine-König85569582012-04-23 11:23:34 +0200911 if (!host->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200912 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200913
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200914 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200915 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
916
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200917 host->eccsize = get_eccsize(mtd);
918 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200919 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
920
921 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200922 } else {
923 host->eccsize = 1;
924 }
925
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200926 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200927 /* preset operation */
928
929 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200930 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200931
932 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200933 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
934 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
935 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
936 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
937 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
938 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
939 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
940 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200941
942 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200943 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200944}
945
Sascha Hauer71ec5152010-08-06 15:53:11 +0200946static void preset_v3(struct mtd_info *mtd)
947{
948 struct nand_chip *chip = mtd->priv;
949 struct mxc_nand_host *host = chip->priv;
950 uint32_t config2, config3;
951 int i, addr_phases;
952
953 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
954 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
955
956 /* Unlock the internal RAM Buffer */
957 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
958 NFC_V3_WRPROT);
959
960 /* Blocks to be unlocked */
961 for (i = 0; i < NAND_MAX_CHIPS; i++)
962 writel(0x0 | (0xffff << 16),
963 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
964
965 writel(0, NFC_V3_IPC);
966
967 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
968 NFC_V3_CONFIG2_2CMD_PHASES |
969 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
970 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +0200971 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +0200972 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
973
974 if (chip->ecc.mode == NAND_ECC_HW)
975 config2 |= NFC_V3_CONFIG2_ECC_EN;
976
977 addr_phases = fls(chip->pagemask) >> 3;
978
979 if (mtd->writesize == 2048) {
980 config2 |= NFC_V3_CONFIG2_PS_2048;
981 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
982 } else if (mtd->writesize == 4096) {
983 config2 |= NFC_V3_CONFIG2_PS_4096;
984 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
985 } else {
986 config2 |= NFC_V3_CONFIG2_PS_512;
987 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
988 }
989
990 if (mtd->writesize) {
991 config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
992 host->eccsize = get_eccsize(mtd);
993 if (host->eccsize == 8)
994 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
995 }
996
997 writel(config2, NFC_V3_CONFIG2);
998
999 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1000 NFC_V3_CONFIG3_NO_SDMA |
1001 NFC_V3_CONFIG3_RBB_MODE |
1002 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1003 NFC_V3_CONFIG3_ADD_OP(0);
1004
1005 if (!(chip->options & NAND_BUSWIDTH_16))
1006 config3 |= NFC_V3_CONFIG3_FW8;
1007
1008 writel(config3, NFC_V3_CONFIG3);
1009
1010 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001011}
1012
Sascha Hauer34f6e152008-09-02 17:16:59 +02001013/* Used by the upper layer to write command to NAND Flash for
1014 * different operations to be carried out on NAND Flash */
1015static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1016 int column, int page_addr)
1017{
1018 struct nand_chip *nand_chip = mtd->priv;
1019 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001020
Brian Norris289c0522011-07-19 10:06:09 -07001021 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001022 command, column, page_addr);
1023
1024 /* Reset command state information */
1025 host->status_request = false;
1026
1027 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001028 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001029 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001030 host->devtype_data->preset(mtd);
1031 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001032 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001033
Sascha Hauer34f6e152008-09-02 17:16:59 +02001034 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001035 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001036 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001037
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001038 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001039 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001040 break;
1041
Sascha Hauer34f6e152008-09-02 17:16:59 +02001042 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001043 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001044 if (command == NAND_CMD_READ0)
1045 host->buf_start = column;
1046 else
1047 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001048
Sascha Hauer5ea32022010-04-27 15:24:01 +02001049 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001050
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001051 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001052 mxc_do_addr_cycle(mtd, column, page_addr);
1053
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001054 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001055 host->devtype_data->send_cmd(host,
1056 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001057
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001058 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001059
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001060 memcpy(host->data_buf, host->main_area0, mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001061 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001062 break;
1063
Sascha Hauer34f6e152008-09-02 17:16:59 +02001064 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001065 if (column >= mtd->writesize)
1066 /* call ourself to read a page */
1067 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001068
Sascha Hauer5ea32022010-04-27 15:24:01 +02001069 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001070
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001071 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001072 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001073 break;
1074
1075 case NAND_CMD_PAGEPROG:
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001076 memcpy(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001077 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001078 host->devtype_data->send_page(mtd, NFC_INPUT);
1079 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001080 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001081 break;
1082
Sascha Hauer34f6e152008-09-02 17:16:59 +02001083 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001084 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001085 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001086 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001087 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001088 break;
1089
Sascha Hauer89121a62009-06-04 17:18:01 +02001090 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001091 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001092 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001093 mxc_do_addr_cycle(mtd, column, page_addr);
1094
Sascha Hauer34f6e152008-09-02 17:16:59 +02001095 break;
1096 }
1097}
1098
Sascha Hauerf1372052009-10-21 14:25:27 +02001099/*
1100 * The generic flash bbt decriptors overlap with our ecc
1101 * hardware, so define some i.MX specific ones.
1102 */
1103static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1104static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1105
1106static struct nand_bbt_descr bbt_main_descr = {
1107 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1108 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1109 .offs = 0,
1110 .len = 4,
1111 .veroffs = 4,
1112 .maxblocks = 4,
1113 .pattern = bbt_pattern,
1114};
1115
1116static struct nand_bbt_descr bbt_mirror_descr = {
1117 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1118 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1119 .offs = 0,
1120 .len = 4,
1121 .veroffs = 4,
1122 .maxblocks = 4,
1123 .pattern = mirror_pattern,
1124};
1125
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001126/* v1: i.MX21, i.MX27, i.MX31 */
1127static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001128 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001129 .send_cmd = send_cmd_v1_v2,
1130 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001131 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001132 .send_read_id = send_read_id_v1_v2,
1133 .get_dev_status = get_dev_status_v1_v2,
1134 .check_int = check_int_v1_v2,
1135 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001136 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001137 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1138 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1139 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001140 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001141};
1142
1143/* v21: i.MX25, i.MX35 */
1144static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001145 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001146 .send_cmd = send_cmd_v1_v2,
1147 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001148 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001149 .send_read_id = send_read_id_v1_v2,
1150 .get_dev_status = get_dev_status_v1_v2,
1151 .check_int = check_int_v1_v2,
1152 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001153 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001154 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1155 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1156 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001157 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001158};
1159
1160/* v3: i.MX51, i.MX53 */
1161static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1162 .preset = preset_v3,
1163 .send_cmd = send_cmd_v3,
1164 .send_addr = send_addr_v3,
1165 .send_page = send_page_v3,
1166 .send_read_id = send_read_id_v3,
1167 .get_dev_status = get_dev_status_v3,
1168 .check_int = check_int_v3,
1169 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001170 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001171 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1172 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1173 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001174 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001175};
1176
Sascha Hauer34f6e152008-09-02 17:16:59 +02001177static int __init mxcnd_probe(struct platform_device *pdev)
1178{
1179 struct nand_chip *this;
1180 struct mtd_info *mtd;
1181 struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
1182 struct mxc_nand_host *host;
1183 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001184 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001185
1186 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +02001187 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
1188 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001189 if (!host)
1190 return -ENOMEM;
1191
Sascha Hauerf8f96082009-06-04 17:12:26 +02001192 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001193
Sascha Hauer34f6e152008-09-02 17:16:59 +02001194 host->dev = &pdev->dev;
1195 /* structures must be linked */
1196 this = &host->nand;
1197 mtd = &host->mtd;
1198 mtd->priv = this;
1199 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001200 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001201 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001202
1203 /* 50 us command delay time */
1204 this->chip_delay = 5;
1205
1206 this->priv = host;
1207 this->dev_ready = mxc_nand_dev_ready;
1208 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001209 this->read_byte = mxc_nand_read_byte;
1210 this->read_word = mxc_nand_read_word;
1211 this->write_buf = mxc_nand_write_buf;
1212 this->read_buf = mxc_nand_read_buf;
1213 this->verify_buf = mxc_nand_verify_buf;
1214
Sascha Hauere65fb002009-02-16 14:29:10 +01001215 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +04001216 if (IS_ERR(host->clk)) {
1217 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001218 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +04001219 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001220
1221 clk_enable(host->clk);
1222 host->clk_act = 1;
1223
1224 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1225 if (!res) {
1226 err = -ENODEV;
1227 goto eres;
1228 }
1229
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001230 host->base = ioremap(res->start, resource_size(res));
1231 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +04001232 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001233 goto eres;
1234 }
1235
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001236 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001237
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001238 if (nfc_is_v1()) {
1239 host->devtype_data = &imx21_nand_devtype_data;
Sascha Hauer63f14742010-10-18 10:16:26 +02001240 if (cpu_is_mx21())
Uwe Kleine-König85569582012-04-23 11:23:34 +02001241 host->irqpending_quirk = 1;
Sascha Hauer938cf992010-08-06 15:53:04 +02001242 host->regs = host->base + 0xe00;
Sascha Hauer94671142009-10-05 12:14:21 +02001243 host->spare0 = host->base + 0x800;
1244 host->spare_len = 16;
Sascha Hauer94671142009-10-05 12:14:21 +02001245 this->ecc.bytes = 3;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001246 host->eccsize = 1;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001247 } else if (nfc_is_v21()) {
1248 host->devtype_data = &imx25_nand_devtype_data;
1249 host->regs = host->base + 0x1e00;
1250 host->spare0 = host->base + 0x1000;
1251 host->spare_len = 64;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001252 this->ecc.bytes = 9;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001253 } else if (nfc_is_v3_2()) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001254 host->devtype_data = &imx51_nand_devtype_data;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001255 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1256 if (!res) {
1257 err = -ENODEV;
1258 goto eirq;
1259 }
1260 host->regs_ip = ioremap(res->start, resource_size(res));
1261 if (!host->regs_ip) {
1262 err = -ENOMEM;
1263 goto eirq;
1264 }
1265 host->regs_axi = host->base + 0x1e00;
1266 host->spare0 = host->base + 0x1000;
1267 host->spare_len = 64;
Sascha Hauer94671142009-10-05 12:14:21 +02001268 } else
1269 BUG();
Sascha Hauer34f6e152008-09-02 17:16:59 +02001270
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001271 this->select_chip = host->devtype_data->select_chip;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001272 this->ecc.size = 512;
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001273 this->ecc.layout = host->devtype_data->ecclayout_512;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001274
1275 if (pdata->hw_ecc) {
1276 this->ecc.calculate = mxc_nand_calculate_ecc;
1277 this->ecc.hwctl = mxc_nand_enable_hwecc;
Sascha Hauer94f77e52010-08-06 15:53:09 +02001278 if (nfc_is_v1())
1279 this->ecc.correct = mxc_nand_correct_data_v1;
1280 else
1281 this->ecc.correct = mxc_nand_correct_data_v2_v3;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001282 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001283 } else {
1284 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001285 }
1286
Sascha Hauer34f6e152008-09-02 17:16:59 +02001287 /* NAND bus width determines access funtions used by upper layer */
Sascha Hauer13e1add2009-10-21 10:39:05 +02001288 if (pdata->width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001289 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001290
Sascha Hauerf1372052009-10-21 14:25:27 +02001291 if (pdata->flash_bbt) {
1292 this->bbt_td = &bbt_main_descr;
1293 this->bbt_md = &bbt_mirror_descr;
1294 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001295 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001296 }
1297
Sascha Hauer63f14742010-10-18 10:16:26 +02001298 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001299
1300 host->irq = platform_get_irq(pdev, 0);
1301
Sascha Hauer63f14742010-10-18 10:16:26 +02001302 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001303 * Use host->devtype_data->irq_control() here instead of irq_control()
1304 * because we must not disable_irq_nosync without having requested the
1305 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001306 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001307 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001308
Ivo Claryssea47bfd22010-04-08 16:16:51 +02001309 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001310 if (err)
1311 goto eirq;
1312
Sascha Hauer63f14742010-10-18 10:16:26 +02001313 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001314 * Now that we "own" the interrupt make sure the interrupt mask bit is
1315 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1316 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001317 */
Uwe Kleine-König85569582012-04-23 11:23:34 +02001318 if (host->irqpending_quirk) {
1319 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001320 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001321 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001322
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001323 /* first scan to find the device and get the page size */
Baruch Siachd178e3e2011-03-14 09:01:56 +02001324 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001325 err = -ENXIO;
1326 goto escan;
1327 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001328
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001329 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001330 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001331
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001332 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001333 this->ecc.layout = host->devtype_data->ecclayout_2k;
1334 else if (mtd->writesize == 4096)
1335 this->ecc.layout = host->devtype_data->ecclayout_4k;
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001336
1337 /* second phase scan */
1338 if (nand_scan_tail(mtd)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +02001339 err = -ENXIO;
1340 goto escan;
1341 }
1342
Mike Dunn6a918ba2012-03-11 14:21:11 -07001343 if (this->ecc.mode == NAND_ECC_HW) {
1344 if (nfc_is_v1())
1345 this->ecc.strength = 1;
1346 else
1347 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1348 }
1349
Sascha Hauer34f6e152008-09-02 17:16:59 +02001350 /* Register the partitions */
Artem Bityutskiy42d7fbe2012-03-09 19:24:26 +02001351 mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts,
1352 pdata->nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001353
1354 platform_set_drvdata(pdev, host);
1355
1356 return 0;
1357
1358escan:
Magnus Liljab258fd82009-05-08 21:57:47 +02001359 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001360eirq:
Sascha Hauer71ec5152010-08-06 15:53:11 +02001361 if (host->regs_ip)
1362 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001363 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001364eres:
1365 clk_put(host->clk);
1366eclk:
1367 kfree(host);
1368
1369 return err;
1370}
1371
Uwe Kleine-König51eeb872009-12-07 09:44:05 +00001372static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001373{
1374 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1375
1376 clk_put(host->clk);
1377
1378 platform_set_drvdata(pdev, NULL);
1379
1380 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +02001381 free_irq(host->irq, host);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001382 if (host->regs_ip)
1383 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001384 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001385 kfree(host);
1386
1387 return 0;
1388}
1389
Sascha Hauer34f6e152008-09-02 17:16:59 +02001390static struct platform_driver mxcnd_driver = {
1391 .driver = {
1392 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001393 .owner = THIS_MODULE,
Eric Bénard04dd0d32010-06-17 20:59:04 +02001394 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +01001395 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +02001396};
1397
1398static int __init mxc_nd_init(void)
1399{
Vladimir Barinov8541c112009-04-23 15:47:22 +04001400 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001401}
1402
1403static void __exit mxc_nd_cleanup(void)
1404{
1405 /* Unregister the device structure */
1406 platform_driver_unregister(&mxcnd_driver);
1407}
1408
1409module_init(mxc_nd_init);
1410module_exit(mxc_nd_cleanup);
1411
1412MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1413MODULE_DESCRIPTION("MXC NAND MTD driver");
1414MODULE_LICENSE("GPL");