blob: 4a6d763ab7f7ad6d28a837729b1705fc6f7468b9 [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önig69d023b2012-04-23 11:23:39 +0200157 int (*correct_data)(struct mtd_info *mtd, u_char *dat,
158 u_char *read_ecc, u_char *calc_ecc);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200159};
160
Sascha Hauer34f6e152008-09-02 17:16:59 +0200161struct mxc_nand_host {
162 struct mtd_info mtd;
163 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200164 struct device *dev;
165
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200166 void *spare0;
167 void *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200168
169 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200170 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200171 void __iomem *regs_axi;
172 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200173 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200174 struct clk *clk;
175 int clk_act;
176 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200177 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200178 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200179
Sascha Hauer63f14742010-10-18 10:16:26 +0200180 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200181
182 uint8_t *data_buf;
183 unsigned int buf_start;
184 int spare_len;
Sascha Hauer5f973042010-08-06 15:53:06 +0200185
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200186 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König85569582012-04-23 11:23:34 +0200187
188 /*
189 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
190 * (CONFIG1:INT_MSK is set). To handle this the driver uses
191 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
192 */
193 int irqpending_quirk;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200194};
195
Sascha Hauer34f6e152008-09-02 17:16:59 +0200196/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200197static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200198 .eccbytes = 5,
199 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200200 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200201};
202
Sascha Hauer94671142009-10-05 12:14:21 +0200203static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400204 .eccbytes = 20,
205 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
206 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
207 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200208};
209
Sascha Hauer94671142009-10-05 12:14:21 +0200210/* OOB description for 512 byte pages with 16 byte OOB */
211static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
212 .eccbytes = 1 * 9,
213 .eccpos = {
214 7, 8, 9, 10, 11, 12, 13, 14, 15
215 },
216 .oobfree = {
217 {.offset = 0, .length = 5}
218 }
219};
220
221/* OOB description for 2048 byte pages with 64 byte OOB */
222static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
223 .eccbytes = 4 * 9,
224 .eccpos = {
225 7, 8, 9, 10, 11, 12, 13, 14, 15,
226 23, 24, 25, 26, 27, 28, 29, 30, 31,
227 39, 40, 41, 42, 43, 44, 45, 46, 47,
228 55, 56, 57, 58, 59, 60, 61, 62, 63
229 },
230 .oobfree = {
231 {.offset = 2, .length = 4},
232 {.offset = 16, .length = 7},
233 {.offset = 32, .length = 7},
234 {.offset = 48, .length = 7}
235 }
236};
237
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200238/* OOB description for 4096 byte pages with 128 byte OOB */
239static struct nand_ecclayout nandv2_hw_eccoob_4k = {
240 .eccbytes = 8 * 9,
241 .eccpos = {
242 7, 8, 9, 10, 11, 12, 13, 14, 15,
243 23, 24, 25, 26, 27, 28, 29, 30, 31,
244 39, 40, 41, 42, 43, 44, 45, 46, 47,
245 55, 56, 57, 58, 59, 60, 61, 62, 63,
246 71, 72, 73, 74, 75, 76, 77, 78, 79,
247 87, 88, 89, 90, 91, 92, 93, 94, 95,
248 103, 104, 105, 106, 107, 108, 109, 110, 111,
249 119, 120, 121, 122, 123, 124, 125, 126, 127,
250 },
251 .oobfree = {
252 {.offset = 2, .length = 4},
253 {.offset = 16, .length = 7},
254 {.offset = 32, .length = 7},
255 {.offset = 48, .length = 7},
256 {.offset = 64, .length = 7},
257 {.offset = 80, .length = 7},
258 {.offset = 96, .length = 7},
259 {.offset = 112, .length = 7},
260 }
261};
262
Sascha Hauer34f6e152008-09-02 17:16:59 +0200263static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200264
Sascha Hauer71ec5152010-08-06 15:53:11 +0200265static int check_int_v3(struct mxc_nand_host *host)
266{
267 uint32_t tmp;
268
269 tmp = readl(NFC_V3_IPC);
270 if (!(tmp & NFC_V3_IPC_INT))
271 return 0;
272
273 tmp &= ~NFC_V3_IPC_INT;
274 writel(tmp, NFC_V3_IPC);
275
276 return 1;
277}
278
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200279static int check_int_v1_v2(struct mxc_nand_host *host)
280{
281 uint32_t tmp;
282
Sascha Hauer1bc99182010-08-06 15:53:08 +0200283 tmp = readw(NFC_V1_V2_CONFIG2);
284 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200285 return 0;
286
Uwe Kleine-König85569582012-04-23 11:23:34 +0200287 if (!host->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200288 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200289
290 return 1;
291}
292
Sascha Hauer63f14742010-10-18 10:16:26 +0200293static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
294{
295 uint16_t tmp;
296
297 tmp = readw(NFC_V1_V2_CONFIG1);
298
299 if (activate)
300 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
301 else
302 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
303
304 writew(tmp, NFC_V1_V2_CONFIG1);
305}
306
307static void irq_control_v3(struct mxc_nand_host *host, int activate)
308{
309 uint32_t tmp;
310
311 tmp = readl(NFC_V3_CONFIG2);
312
313 if (activate)
314 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
315 else
316 tmp |= NFC_V3_CONFIG2_INT_MSK;
317
318 writel(tmp, NFC_V3_CONFIG2);
319}
320
Uwe Kleine-König85569582012-04-23 11:23:34 +0200321static void irq_control(struct mxc_nand_host *host, int activate)
322{
323 if (host->irqpending_quirk) {
324 if (activate)
325 enable_irq(host->irq);
326 else
327 disable_irq_nosync(host->irq);
328 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200329 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200330 }
331}
332
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200333static u32 get_ecc_status_v1(struct mxc_nand_host *host)
334{
335 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
336}
337
338static u32 get_ecc_status_v2(struct mxc_nand_host *host)
339{
340 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
341}
342
343static u32 get_ecc_status_v3(struct mxc_nand_host *host)
344{
345 return readl(NFC_V3_ECC_STATUS_RESULT);
346}
347
Uwe Kleine-König85569582012-04-23 11:23:34 +0200348static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
349{
350 struct mxc_nand_host *host = dev_id;
351
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200352 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200353 return IRQ_NONE;
354
355 irq_control(host, 0);
356
357 complete(&host->op_completion);
358
359 return IRQ_HANDLED;
360}
361
Sascha Hauer34f6e152008-09-02 17:16:59 +0200362/* This function polls the NANDFC to wait for the basic operation to
363 * complete by checking the INT bit of config2 register.
364 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200365static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200366{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200367 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200368
369 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200370 if (!host->devtype_data->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200371 INIT_COMPLETION(host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200372 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200373 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200374 }
375 } else {
376 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200377 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200378 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200379
Sascha Hauer34f6e152008-09-02 17:16:59 +0200380 udelay(1);
381 }
Roel Kluin43950a62009-06-04 16:24:59 +0200382 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700383 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200384 }
385}
386
Sascha Hauer71ec5152010-08-06 15:53:11 +0200387static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
388{
389 /* fill command */
390 writel(cmd, NFC_V3_FLASH_CMD);
391
392 /* send out command */
393 writel(NFC_CMD, NFC_V3_LAUNCH);
394
395 /* Wait for operation to complete */
396 wait_op_done(host, useirq);
397}
398
Sascha Hauer34f6e152008-09-02 17:16:59 +0200399/* This function issues the specified command to the NAND device and
400 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200401static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200402{
Brian Norris289c0522011-07-19 10:06:09 -0700403 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200404
Sascha Hauer1bc99182010-08-06 15:53:08 +0200405 writew(cmd, NFC_V1_V2_FLASH_CMD);
406 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200407
Uwe Kleine-König85569582012-04-23 11:23:34 +0200408 if (host->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200409 int max_retries = 100;
410 /* Reset completion is indicated by NFC_CONFIG2 */
411 /* being set to 0 */
412 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200413 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200414 break;
415 }
416 udelay(1);
417 }
418 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700419 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200420 } else {
421 /* Wait for operation to complete */
422 wait_op_done(host, useirq);
423 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200424}
425
Sascha Hauer71ec5152010-08-06 15:53:11 +0200426static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
427{
428 /* fill address */
429 writel(addr, NFC_V3_FLASH_ADDR0);
430
431 /* send out address */
432 writel(NFC_ADDR, NFC_V3_LAUNCH);
433
434 wait_op_done(host, 0);
435}
436
Sascha Hauer34f6e152008-09-02 17:16:59 +0200437/* This function sends an address (or partial address) to the
438 * NAND device. The address is used to select the source/destination for
439 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200440static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200441{
Brian Norris289c0522011-07-19 10:06:09 -0700442 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200443
Sascha Hauer1bc99182010-08-06 15:53:08 +0200444 writew(addr, NFC_V1_V2_FLASH_ADDR);
445 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200446
447 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200448 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200449}
450
Sascha Hauer71ec5152010-08-06 15:53:11 +0200451static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
452{
453 struct nand_chip *nand_chip = mtd->priv;
454 struct mxc_nand_host *host = nand_chip->priv;
455 uint32_t tmp;
456
457 tmp = readl(NFC_V3_CONFIG1);
458 tmp &= ~(7 << 4);
459 writel(tmp, NFC_V3_CONFIG1);
460
461 /* transfer data from NFC ram to nand */
462 writel(ops, NFC_V3_LAUNCH);
463
464 wait_op_done(host, false);
465}
466
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200467static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
468{
469 struct nand_chip *nand_chip = mtd->priv;
470 struct mxc_nand_host *host = nand_chip->priv;
471
472 /* NANDFC buffer 0 is used for page read/write */
473 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
474
475 writew(ops, NFC_V1_V2_CONFIG2);
476
477 /* Wait for operation to complete */
478 wait_op_done(host, true);
479}
480
481static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200482{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200483 struct nand_chip *nand_chip = mtd->priv;
484 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200485 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200486
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200487 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200488 bufs = 4;
489 else
490 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200491
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200492 for (i = 0; i < bufs; i++) {
493
494 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200495 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200496
Sascha Hauer1bc99182010-08-06 15:53:08 +0200497 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200498
499 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200500 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200501 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200502}
503
Sascha Hauer71ec5152010-08-06 15:53:11 +0200504static void send_read_id_v3(struct mxc_nand_host *host)
505{
506 /* Read ID into main buffer */
507 writel(NFC_ID, NFC_V3_LAUNCH);
508
509 wait_op_done(host, true);
510
511 memcpy(host->data_buf, host->main_area0, 16);
512}
513
Sascha Hauer34f6e152008-09-02 17:16:59 +0200514/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200515static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200516{
517 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200518
519 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200520 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200521
Sascha Hauer1bc99182010-08-06 15:53:08 +0200522 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200523
524 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200525 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200526
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200527 memcpy(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200528
529 if (this->options & NAND_BUSWIDTH_16) {
530 /* compress the ID info */
531 host->data_buf[1] = host->data_buf[2];
532 host->data_buf[2] = host->data_buf[4];
533 host->data_buf[3] = host->data_buf[6];
534 host->data_buf[4] = host->data_buf[8];
535 host->data_buf[5] = host->data_buf[10];
536 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200537}
538
Sascha Hauer71ec5152010-08-06 15:53:11 +0200539static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200540{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200541 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200542 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200543
Sascha Hauer71ec5152010-08-06 15:53:11 +0200544 return readl(NFC_V3_CONFIG1) >> 16;
545}
546
Sascha Hauer34f6e152008-09-02 17:16:59 +0200547/* This function requests the NANDFC to perform a read of the
548 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200549static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200550{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200551 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200552 uint32_t store;
553 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200554
Baruch Siachd178e3e2011-03-14 09:01:56 +0200555 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200556
557 /*
558 * The device status is stored in main_area0. To
559 * prevent corruption of the buffer save the value
560 * and restore it afterwards.
561 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200562 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200563
Sascha Hauer1bc99182010-08-06 15:53:08 +0200564 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200565 wait_op_done(host, true);
566
Sascha Hauer34f6e152008-09-02 17:16:59 +0200567 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200568
Sascha Hauer34f6e152008-09-02 17:16:59 +0200569 writel(store, main_buf);
570
571 return ret;
572}
573
574/* This functions is used by upper layer to checks if device is ready */
575static int mxc_nand_dev_ready(struct mtd_info *mtd)
576{
577 /*
578 * NFC handles R/B internally. Therefore, this function
579 * always returns status as ready.
580 */
581 return 1;
582}
583
584static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
585{
586 /*
587 * If HW ECC is enabled, we turn it on during init. There is
588 * no need to enable again here.
589 */
590}
591
Sascha Hauer94f77e52010-08-06 15:53:09 +0200592static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200593 u_char *read_ecc, u_char *calc_ecc)
594{
595 struct nand_chip *nand_chip = mtd->priv;
596 struct mxc_nand_host *host = nand_chip->priv;
597
598 /*
599 * 1-Bit errors are automatically corrected in HW. No need for
600 * additional correction. 2-Bit errors cannot be corrected by
601 * HW ECC, so we need to return failure
602 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200603 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200604
605 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700606 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200607 return -1;
608 }
609
610 return 0;
611}
612
Sascha Hauer94f77e52010-08-06 15:53:09 +0200613static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
614 u_char *read_ecc, u_char *calc_ecc)
615{
616 struct nand_chip *nand_chip = mtd->priv;
617 struct mxc_nand_host *host = nand_chip->priv;
618 u32 ecc_stat, err;
619 int no_subpages = 1;
620 int ret = 0;
621 u8 ecc_bit_mask, err_limit;
622
623 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
624 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
625
626 no_subpages = mtd->writesize >> 9;
627
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200628 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200629
630 do {
631 err = ecc_stat & ecc_bit_mask;
632 if (err > err_limit) {
633 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
634 return -1;
635 } else {
636 ret += err;
637 }
638 ecc_stat >>= 4;
639 } while (--no_subpages);
640
641 mtd->ecc_stats.corrected += ret;
642 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
643
644 return ret;
645}
646
Sascha Hauer34f6e152008-09-02 17:16:59 +0200647static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
648 u_char *ecc_code)
649{
650 return 0;
651}
652
653static u_char mxc_nand_read_byte(struct mtd_info *mtd)
654{
655 struct nand_chip *nand_chip = mtd->priv;
656 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200657 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200658
659 /* Check for status request */
660 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200661 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200662
Sascha Hauerf8f96082009-06-04 17:12:26 +0200663 ret = *(uint8_t *)(host->data_buf + host->buf_start);
664 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200665
666 return ret;
667}
668
669static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
670{
671 struct nand_chip *nand_chip = mtd->priv;
672 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200673 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200674
Sascha Hauerf8f96082009-06-04 17:12:26 +0200675 ret = *(uint16_t *)(host->data_buf + host->buf_start);
676 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200677
678 return ret;
679}
680
681/* Write data of length len to buffer buf. The data to be
682 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
683 * Operation by the NFC, the data is written to NAND Flash */
684static void mxc_nand_write_buf(struct mtd_info *mtd,
685 const u_char *buf, int len)
686{
687 struct nand_chip *nand_chip = mtd->priv;
688 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200689 u16 col = host->buf_start;
690 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200691
Sascha Hauerf8f96082009-06-04 17:12:26 +0200692 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200693
Sascha Hauerf8f96082009-06-04 17:12:26 +0200694 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200695
Sascha Hauerf8f96082009-06-04 17:12:26 +0200696 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200697}
698
699/* Read the data buffer from the NAND Flash. To read the data from NAND
700 * Flash first the data output cycle is initiated by the NFC, which copies
701 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
702 */
703static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
704{
705 struct nand_chip *nand_chip = mtd->priv;
706 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200707 u16 col = host->buf_start;
708 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200709
Sascha Hauerf8f96082009-06-04 17:12:26 +0200710 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200711
Baruch Siach5d9d9932011-03-02 16:47:55 +0200712 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200713
Baruch Siach5d9d9932011-03-02 16:47:55 +0200714 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200715}
716
717/* Used by the upper layer to verify the data in NAND Flash
718 * with the data in the buf. */
719static int mxc_nand_verify_buf(struct mtd_info *mtd,
720 const u_char *buf, int len)
721{
722 return -EFAULT;
723}
724
725/* This function is used by upper layer for select and
726 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200727static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
728{
729 struct nand_chip *nand_chip = mtd->priv;
730 struct mxc_nand_host *host = nand_chip->priv;
731
732 if (chip == -1) {
733 /* Disable the NFC clock */
734 if (host->clk_act) {
735 clk_disable(host->clk);
736 host->clk_act = 0;
737 }
738 return;
739 }
740
741 if (!host->clk_act) {
742 /* Enable the NFC clock */
743 clk_enable(host->clk);
744 host->clk_act = 1;
745 }
746}
747
748static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200749{
750 struct nand_chip *nand_chip = mtd->priv;
751 struct mxc_nand_host *host = nand_chip->priv;
752
Baruch Siachd178e3e2011-03-14 09:01:56 +0200753 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200754 /* Disable the NFC clock */
755 if (host->clk_act) {
756 clk_disable(host->clk);
757 host->clk_act = 0;
758 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200759 return;
760 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200761
Baruch Siachd178e3e2011-03-14 09:01:56 +0200762 if (!host->clk_act) {
763 /* Enable the NFC clock */
764 clk_enable(host->clk);
765 host->clk_act = 1;
766 }
767
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200768 host->active_cs = chip;
769 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200770}
771
Sascha Hauerf8f96082009-06-04 17:12:26 +0200772/*
773 * Function to transfer data to/from spare area.
774 */
775static void copy_spare(struct mtd_info *mtd, bool bfrom)
776{
777 struct nand_chip *this = mtd->priv;
778 struct mxc_nand_host *host = this->priv;
779 u16 i, j;
780 u16 n = mtd->writesize >> 9;
781 u8 *d = host->data_buf + mtd->writesize;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200782 u8 *s = host->spare0;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200783 u16 t = host->spare_len;
784
785 j = (mtd->oobsize / n >> 1) << 1;
786
787 if (bfrom) {
788 for (i = 0; i < n - 1; i++)
789 memcpy(d + i * j, s + i * t, j);
790
791 /* the last section */
792 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
793 } else {
794 for (i = 0; i < n - 1; i++)
795 memcpy(&s[i * t], &d[i * j], j);
796
797 /* the last section */
798 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
799 }
800}
801
Sascha Hauera3e65b62009-06-02 11:47:59 +0200802static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200803{
804 struct nand_chip *nand_chip = mtd->priv;
805 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200806
807 /* Write out column address, if necessary */
808 if (column != -1) {
809 /*
810 * MXC NANDFC can only perform full page+spare or
811 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100812 * perform a read/write buf operation, the saved column
813 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200814 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200815 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200816 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200817 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200818 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200819 }
820
821 /* Write out page address, if necessary */
822 if (page_addr != -1) {
823 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200824 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200825
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200826 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400827 if (mtd->size >= 0x10000000) {
828 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200829 host->devtype_data->send_addr(host,
830 (page_addr >> 8) & 0xff,
831 false);
832 host->devtype_data->send_addr(host,
833 (page_addr >> 16) & 0xff,
834 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400835 } else
836 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200837 host->devtype_data->send_addr(host,
838 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200839 } else {
840 /* One more address cycle for higher density devices */
841 if (mtd->size >= 0x4000000) {
842 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200843 host->devtype_data->send_addr(host,
844 (page_addr >> 8) & 0xff,
845 false);
846 host->devtype_data->send_addr(host,
847 (page_addr >> 16) & 0xff,
848 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200849 } else
850 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200851 host->devtype_data->send_addr(host,
852 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200853 }
854 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200855}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200856
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200857/*
858 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
859 * on how much oob the nand chip has. For 8bit ecc we need at least
860 * 26 bytes of oob data per 512 byte block.
861 */
862static int get_eccsize(struct mtd_info *mtd)
863{
864 int oobbytes_per_512 = 0;
865
866 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
867
868 if (oobbytes_per_512 < 26)
869 return 4;
870 else
871 return 8;
872}
873
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200874static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200875{
876 struct nand_chip *nand_chip = mtd->priv;
877 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200878 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200879
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200880 if (nand_chip->ecc.mode == NAND_ECC_HW)
881 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
882
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200883 if (!host->irqpending_quirk)
884 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
885
886 host->eccsize = 1;
887
888 writew(config1, NFC_V1_V2_CONFIG1);
889 /* preset operation */
890
891 /* Unlock the internal RAM Buffer */
892 writew(0x2, NFC_V1_V2_CONFIG);
893
894 /* Blocks to be unlocked */
895 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
896 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
897
898 /* Unlock Block Command for given address range */
899 writew(0x4, NFC_V1_V2_WRPROT);
900}
901
902static void preset_v2(struct mtd_info *mtd)
903{
904 struct nand_chip *nand_chip = mtd->priv;
905 struct mxc_nand_host *host = nand_chip->priv;
906 uint16_t config1 = 0;
907
908 if (nand_chip->ecc.mode == NAND_ECC_HW)
909 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
910
911 config1 |= NFC_V2_CONFIG1_FP_INT;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200912
Uwe Kleine-König85569582012-04-23 11:23:34 +0200913 if (!host->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200914 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200915
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200916 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200917 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
918
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200919 host->eccsize = get_eccsize(mtd);
920 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200921 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
922
923 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200924 } else {
925 host->eccsize = 1;
926 }
927
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200928 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200929 /* preset operation */
930
931 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200932 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200933
934 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200935 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
936 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
937 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
938 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
939 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
940 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
941 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
942 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200943
944 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200945 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200946}
947
Sascha Hauer71ec5152010-08-06 15:53:11 +0200948static void preset_v3(struct mtd_info *mtd)
949{
950 struct nand_chip *chip = mtd->priv;
951 struct mxc_nand_host *host = chip->priv;
952 uint32_t config2, config3;
953 int i, addr_phases;
954
955 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
956 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
957
958 /* Unlock the internal RAM Buffer */
959 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
960 NFC_V3_WRPROT);
961
962 /* Blocks to be unlocked */
963 for (i = 0; i < NAND_MAX_CHIPS; i++)
964 writel(0x0 | (0xffff << 16),
965 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
966
967 writel(0, NFC_V3_IPC);
968
969 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
970 NFC_V3_CONFIG2_2CMD_PHASES |
971 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
972 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +0200973 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +0200974 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
975
976 if (chip->ecc.mode == NAND_ECC_HW)
977 config2 |= NFC_V3_CONFIG2_ECC_EN;
978
979 addr_phases = fls(chip->pagemask) >> 3;
980
981 if (mtd->writesize == 2048) {
982 config2 |= NFC_V3_CONFIG2_PS_2048;
983 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
984 } else if (mtd->writesize == 4096) {
985 config2 |= NFC_V3_CONFIG2_PS_4096;
986 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
987 } else {
988 config2 |= NFC_V3_CONFIG2_PS_512;
989 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
990 }
991
992 if (mtd->writesize) {
993 config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
994 host->eccsize = get_eccsize(mtd);
995 if (host->eccsize == 8)
996 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
997 }
998
999 writel(config2, NFC_V3_CONFIG2);
1000
1001 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1002 NFC_V3_CONFIG3_NO_SDMA |
1003 NFC_V3_CONFIG3_RBB_MODE |
1004 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1005 NFC_V3_CONFIG3_ADD_OP(0);
1006
1007 if (!(chip->options & NAND_BUSWIDTH_16))
1008 config3 |= NFC_V3_CONFIG3_FW8;
1009
1010 writel(config3, NFC_V3_CONFIG3);
1011
1012 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001013}
1014
Sascha Hauer34f6e152008-09-02 17:16:59 +02001015/* Used by the upper layer to write command to NAND Flash for
1016 * different operations to be carried out on NAND Flash */
1017static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1018 int column, int page_addr)
1019{
1020 struct nand_chip *nand_chip = mtd->priv;
1021 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001022
Brian Norris289c0522011-07-19 10:06:09 -07001023 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001024 command, column, page_addr);
1025
1026 /* Reset command state information */
1027 host->status_request = false;
1028
1029 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001030 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001031 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001032 host->devtype_data->preset(mtd);
1033 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001034 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001035
Sascha Hauer34f6e152008-09-02 17:16:59 +02001036 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001037 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001038 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001039
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001040 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001041 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001042 break;
1043
Sascha Hauer34f6e152008-09-02 17:16:59 +02001044 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001045 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001046 if (command == NAND_CMD_READ0)
1047 host->buf_start = column;
1048 else
1049 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001050
Sascha Hauer5ea32022010-04-27 15:24:01 +02001051 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001052
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001053 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001054 mxc_do_addr_cycle(mtd, column, page_addr);
1055
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001056 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001057 host->devtype_data->send_cmd(host,
1058 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001059
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001060 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001061
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001062 memcpy(host->data_buf, host->main_area0, mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001063 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001064 break;
1065
Sascha Hauer34f6e152008-09-02 17:16:59 +02001066 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001067 if (column >= mtd->writesize)
1068 /* call ourself to read a page */
1069 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001070
Sascha Hauer5ea32022010-04-27 15:24:01 +02001071 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001072
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001073 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001074 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001075 break;
1076
1077 case NAND_CMD_PAGEPROG:
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001078 memcpy(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001079 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001080 host->devtype_data->send_page(mtd, NFC_INPUT);
1081 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001082 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001083 break;
1084
Sascha Hauer34f6e152008-09-02 17:16:59 +02001085 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001086 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001087 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001088 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001089 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001090 break;
1091
Sascha Hauer89121a62009-06-04 17:18:01 +02001092 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001093 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001094 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001095 mxc_do_addr_cycle(mtd, column, page_addr);
1096
Sascha Hauer34f6e152008-09-02 17:16:59 +02001097 break;
1098 }
1099}
1100
Sascha Hauerf1372052009-10-21 14:25:27 +02001101/*
1102 * The generic flash bbt decriptors overlap with our ecc
1103 * hardware, so define some i.MX specific ones.
1104 */
1105static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1106static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1107
1108static struct nand_bbt_descr bbt_main_descr = {
1109 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1110 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1111 .offs = 0,
1112 .len = 4,
1113 .veroffs = 4,
1114 .maxblocks = 4,
1115 .pattern = bbt_pattern,
1116};
1117
1118static struct nand_bbt_descr bbt_mirror_descr = {
1119 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1120 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1121 .offs = 0,
1122 .len = 4,
1123 .veroffs = 4,
1124 .maxblocks = 4,
1125 .pattern = mirror_pattern,
1126};
1127
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001128/* v1: i.MX21, i.MX27, i.MX31 */
1129static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001130 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001131 .send_cmd = send_cmd_v1_v2,
1132 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001133 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001134 .send_read_id = send_read_id_v1_v2,
1135 .get_dev_status = get_dev_status_v1_v2,
1136 .check_int = check_int_v1_v2,
1137 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001138 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001139 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1140 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1141 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001142 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001143 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001144};
1145
1146/* v21: i.MX25, i.MX35 */
1147static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001148 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001149 .send_cmd = send_cmd_v1_v2,
1150 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001151 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001152 .send_read_id = send_read_id_v1_v2,
1153 .get_dev_status = get_dev_status_v1_v2,
1154 .check_int = check_int_v1_v2,
1155 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001156 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001157 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1158 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1159 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001160 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001161 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001162};
1163
1164/* v3: i.MX51, i.MX53 */
1165static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1166 .preset = preset_v3,
1167 .send_cmd = send_cmd_v3,
1168 .send_addr = send_addr_v3,
1169 .send_page = send_page_v3,
1170 .send_read_id = send_read_id_v3,
1171 .get_dev_status = get_dev_status_v3,
1172 .check_int = check_int_v3,
1173 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001174 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001175 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1176 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1177 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001178 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001179 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001180};
1181
Sascha Hauer34f6e152008-09-02 17:16:59 +02001182static int __init mxcnd_probe(struct platform_device *pdev)
1183{
1184 struct nand_chip *this;
1185 struct mtd_info *mtd;
1186 struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
1187 struct mxc_nand_host *host;
1188 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001189 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001190
1191 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +02001192 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
1193 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001194 if (!host)
1195 return -ENOMEM;
1196
Sascha Hauerf8f96082009-06-04 17:12:26 +02001197 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001198
Sascha Hauer34f6e152008-09-02 17:16:59 +02001199 host->dev = &pdev->dev;
1200 /* structures must be linked */
1201 this = &host->nand;
1202 mtd = &host->mtd;
1203 mtd->priv = this;
1204 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001205 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001206 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001207
1208 /* 50 us command delay time */
1209 this->chip_delay = 5;
1210
1211 this->priv = host;
1212 this->dev_ready = mxc_nand_dev_ready;
1213 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001214 this->read_byte = mxc_nand_read_byte;
1215 this->read_word = mxc_nand_read_word;
1216 this->write_buf = mxc_nand_write_buf;
1217 this->read_buf = mxc_nand_read_buf;
1218 this->verify_buf = mxc_nand_verify_buf;
1219
Sascha Hauere65fb002009-02-16 14:29:10 +01001220 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +04001221 if (IS_ERR(host->clk)) {
1222 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001223 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +04001224 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001225
1226 clk_enable(host->clk);
1227 host->clk_act = 1;
1228
1229 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1230 if (!res) {
1231 err = -ENODEV;
1232 goto eres;
1233 }
1234
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001235 host->base = ioremap(res->start, resource_size(res));
1236 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +04001237 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001238 goto eres;
1239 }
1240
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001241 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001242
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001243 if (nfc_is_v1()) {
1244 host->devtype_data = &imx21_nand_devtype_data;
Sascha Hauer63f14742010-10-18 10:16:26 +02001245 if (cpu_is_mx21())
Uwe Kleine-König85569582012-04-23 11:23:34 +02001246 host->irqpending_quirk = 1;
Sascha Hauer938cf992010-08-06 15:53:04 +02001247 host->regs = host->base + 0xe00;
Sascha Hauer94671142009-10-05 12:14:21 +02001248 host->spare0 = host->base + 0x800;
1249 host->spare_len = 16;
Sascha Hauer94671142009-10-05 12:14:21 +02001250 this->ecc.bytes = 3;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001251 host->eccsize = 1;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001252 } else if (nfc_is_v21()) {
1253 host->devtype_data = &imx25_nand_devtype_data;
1254 host->regs = host->base + 0x1e00;
1255 host->spare0 = host->base + 0x1000;
1256 host->spare_len = 64;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001257 this->ecc.bytes = 9;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001258 } else if (nfc_is_v3_2()) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001259 host->devtype_data = &imx51_nand_devtype_data;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001260 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1261 if (!res) {
1262 err = -ENODEV;
1263 goto eirq;
1264 }
1265 host->regs_ip = ioremap(res->start, resource_size(res));
1266 if (!host->regs_ip) {
1267 err = -ENOMEM;
1268 goto eirq;
1269 }
1270 host->regs_axi = host->base + 0x1e00;
1271 host->spare0 = host->base + 0x1000;
1272 host->spare_len = 64;
Sascha Hauer94671142009-10-05 12:14:21 +02001273 } else
1274 BUG();
Sascha Hauer34f6e152008-09-02 17:16:59 +02001275
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001276 this->select_chip = host->devtype_data->select_chip;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001277 this->ecc.size = 512;
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001278 this->ecc.layout = host->devtype_data->ecclayout_512;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001279
1280 if (pdata->hw_ecc) {
1281 this->ecc.calculate = mxc_nand_calculate_ecc;
1282 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001283 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001284 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001285 } else {
1286 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001287 }
1288
Sascha Hauer34f6e152008-09-02 17:16:59 +02001289 /* NAND bus width determines access funtions used by upper layer */
Sascha Hauer13e1add2009-10-21 10:39:05 +02001290 if (pdata->width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001291 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001292
Sascha Hauerf1372052009-10-21 14:25:27 +02001293 if (pdata->flash_bbt) {
1294 this->bbt_td = &bbt_main_descr;
1295 this->bbt_md = &bbt_mirror_descr;
1296 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001297 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001298 }
1299
Sascha Hauer63f14742010-10-18 10:16:26 +02001300 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001301
1302 host->irq = platform_get_irq(pdev, 0);
1303
Sascha Hauer63f14742010-10-18 10:16:26 +02001304 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001305 * Use host->devtype_data->irq_control() here instead of irq_control()
1306 * because we must not disable_irq_nosync without having requested the
1307 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001308 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001309 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001310
Ivo Claryssea47bfd22010-04-08 16:16:51 +02001311 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001312 if (err)
1313 goto eirq;
1314
Sascha Hauer63f14742010-10-18 10:16:26 +02001315 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001316 * Now that we "own" the interrupt make sure the interrupt mask bit is
1317 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1318 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001319 */
Uwe Kleine-König85569582012-04-23 11:23:34 +02001320 if (host->irqpending_quirk) {
1321 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001322 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001323 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001324
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001325 /* first scan to find the device and get the page size */
Baruch Siachd178e3e2011-03-14 09:01:56 +02001326 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001327 err = -ENXIO;
1328 goto escan;
1329 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001330
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001331 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001332 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001333
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001334 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001335 this->ecc.layout = host->devtype_data->ecclayout_2k;
1336 else if (mtd->writesize == 4096)
1337 this->ecc.layout = host->devtype_data->ecclayout_4k;
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001338
1339 /* second phase scan */
1340 if (nand_scan_tail(mtd)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +02001341 err = -ENXIO;
1342 goto escan;
1343 }
1344
Mike Dunn6a918ba2012-03-11 14:21:11 -07001345 if (this->ecc.mode == NAND_ECC_HW) {
1346 if (nfc_is_v1())
1347 this->ecc.strength = 1;
1348 else
1349 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1350 }
1351
Sascha Hauer34f6e152008-09-02 17:16:59 +02001352 /* Register the partitions */
Artem Bityutskiy42d7fbe2012-03-09 19:24:26 +02001353 mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts,
1354 pdata->nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001355
1356 platform_set_drvdata(pdev, host);
1357
1358 return 0;
1359
1360escan:
Magnus Liljab258fd82009-05-08 21:57:47 +02001361 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001362eirq:
Sascha Hauer71ec5152010-08-06 15:53:11 +02001363 if (host->regs_ip)
1364 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001365 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001366eres:
1367 clk_put(host->clk);
1368eclk:
1369 kfree(host);
1370
1371 return err;
1372}
1373
Uwe Kleine-König51eeb872009-12-07 09:44:05 +00001374static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001375{
1376 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1377
1378 clk_put(host->clk);
1379
1380 platform_set_drvdata(pdev, NULL);
1381
1382 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +02001383 free_irq(host->irq, host);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001384 if (host->regs_ip)
1385 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001386 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001387 kfree(host);
1388
1389 return 0;
1390}
1391
Sascha Hauer34f6e152008-09-02 17:16:59 +02001392static struct platform_driver mxcnd_driver = {
1393 .driver = {
1394 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001395 .owner = THIS_MODULE,
Eric Bénard04dd0d32010-06-17 20:59:04 +02001396 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +01001397 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +02001398};
1399
1400static int __init mxc_nd_init(void)
1401{
Vladimir Barinov8541c112009-04-23 15:47:22 +04001402 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001403}
1404
1405static void __exit mxc_nd_cleanup(void)
1406{
1407 /* Unregister the device structure */
1408 platform_driver_unregister(&mxcnd_driver);
1409}
1410
1411module_init(mxc_nd_init);
1412module_exit(mxc_nd_cleanup);
1413
1414MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1415MODULE_DESCRIPTION("MXC NAND MTD driver");
1416MODULE_LICENSE("GPL");