blob: b6e4618bb0432e6c09cb2a9a14d40aa3478b7320 [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);
154};
155
Sascha Hauer34f6e152008-09-02 17:16:59 +0200156struct mxc_nand_host {
157 struct mtd_info mtd;
158 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200159 struct device *dev;
160
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200161 void *spare0;
162 void *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200163
164 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200165 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200166 void __iomem *regs_axi;
167 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200168 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200169 struct clk *clk;
170 int clk_act;
171 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200172 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200173 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200174
Sascha Hauer63f14742010-10-18 10:16:26 +0200175 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200176
177 uint8_t *data_buf;
178 unsigned int buf_start;
179 int spare_len;
Sascha Hauer5f973042010-08-06 15:53:06 +0200180
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200181 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König85569582012-04-23 11:23:34 +0200182
183 /*
184 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
185 * (CONFIG1:INT_MSK is set). To handle this the driver uses
186 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
187 */
188 int irqpending_quirk;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200189};
190
Sascha Hauer34f6e152008-09-02 17:16:59 +0200191/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200192static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200193 .eccbytes = 5,
194 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200195 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200196};
197
Sascha Hauer94671142009-10-05 12:14:21 +0200198static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400199 .eccbytes = 20,
200 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
201 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
202 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200203};
204
Sascha Hauer94671142009-10-05 12:14:21 +0200205/* OOB description for 512 byte pages with 16 byte OOB */
206static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
207 .eccbytes = 1 * 9,
208 .eccpos = {
209 7, 8, 9, 10, 11, 12, 13, 14, 15
210 },
211 .oobfree = {
212 {.offset = 0, .length = 5}
213 }
214};
215
216/* OOB description for 2048 byte pages with 64 byte OOB */
217static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
218 .eccbytes = 4 * 9,
219 .eccpos = {
220 7, 8, 9, 10, 11, 12, 13, 14, 15,
221 23, 24, 25, 26, 27, 28, 29, 30, 31,
222 39, 40, 41, 42, 43, 44, 45, 46, 47,
223 55, 56, 57, 58, 59, 60, 61, 62, 63
224 },
225 .oobfree = {
226 {.offset = 2, .length = 4},
227 {.offset = 16, .length = 7},
228 {.offset = 32, .length = 7},
229 {.offset = 48, .length = 7}
230 }
231};
232
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200233/* OOB description for 4096 byte pages with 128 byte OOB */
234static struct nand_ecclayout nandv2_hw_eccoob_4k = {
235 .eccbytes = 8 * 9,
236 .eccpos = {
237 7, 8, 9, 10, 11, 12, 13, 14, 15,
238 23, 24, 25, 26, 27, 28, 29, 30, 31,
239 39, 40, 41, 42, 43, 44, 45, 46, 47,
240 55, 56, 57, 58, 59, 60, 61, 62, 63,
241 71, 72, 73, 74, 75, 76, 77, 78, 79,
242 87, 88, 89, 90, 91, 92, 93, 94, 95,
243 103, 104, 105, 106, 107, 108, 109, 110, 111,
244 119, 120, 121, 122, 123, 124, 125, 126, 127,
245 },
246 .oobfree = {
247 {.offset = 2, .length = 4},
248 {.offset = 16, .length = 7},
249 {.offset = 32, .length = 7},
250 {.offset = 48, .length = 7},
251 {.offset = 64, .length = 7},
252 {.offset = 80, .length = 7},
253 {.offset = 96, .length = 7},
254 {.offset = 112, .length = 7},
255 }
256};
257
Sascha Hauer34f6e152008-09-02 17:16:59 +0200258static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200259
Sascha Hauer71ec5152010-08-06 15:53:11 +0200260static int check_int_v3(struct mxc_nand_host *host)
261{
262 uint32_t tmp;
263
264 tmp = readl(NFC_V3_IPC);
265 if (!(tmp & NFC_V3_IPC_INT))
266 return 0;
267
268 tmp &= ~NFC_V3_IPC_INT;
269 writel(tmp, NFC_V3_IPC);
270
271 return 1;
272}
273
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200274static int check_int_v1_v2(struct mxc_nand_host *host)
275{
276 uint32_t tmp;
277
Sascha Hauer1bc99182010-08-06 15:53:08 +0200278 tmp = readw(NFC_V1_V2_CONFIG2);
279 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200280 return 0;
281
Uwe Kleine-König85569582012-04-23 11:23:34 +0200282 if (!host->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200283 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200284
285 return 1;
286}
287
Sascha Hauer63f14742010-10-18 10:16:26 +0200288static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
289{
290 uint16_t tmp;
291
292 tmp = readw(NFC_V1_V2_CONFIG1);
293
294 if (activate)
295 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
296 else
297 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
298
299 writew(tmp, NFC_V1_V2_CONFIG1);
300}
301
302static void irq_control_v3(struct mxc_nand_host *host, int activate)
303{
304 uint32_t tmp;
305
306 tmp = readl(NFC_V3_CONFIG2);
307
308 if (activate)
309 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
310 else
311 tmp |= NFC_V3_CONFIG2_INT_MSK;
312
313 writel(tmp, NFC_V3_CONFIG2);
314}
315
Uwe Kleine-König85569582012-04-23 11:23:34 +0200316static void irq_control(struct mxc_nand_host *host, int activate)
317{
318 if (host->irqpending_quirk) {
319 if (activate)
320 enable_irq(host->irq);
321 else
322 disable_irq_nosync(host->irq);
323 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200324 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200325 }
326}
327
328static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
329{
330 struct mxc_nand_host *host = dev_id;
331
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200332 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200333 return IRQ_NONE;
334
335 irq_control(host, 0);
336
337 complete(&host->op_completion);
338
339 return IRQ_HANDLED;
340}
341
Sascha Hauer34f6e152008-09-02 17:16:59 +0200342/* This function polls the NANDFC to wait for the basic operation to
343 * complete by checking the INT bit of config2 register.
344 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200345static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200346{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200347 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200348
349 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200350 if (!host->devtype_data->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200351 INIT_COMPLETION(host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200352 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200353 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200354 }
355 } else {
356 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200357 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200358 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200359
Sascha Hauer34f6e152008-09-02 17:16:59 +0200360 udelay(1);
361 }
Roel Kluin43950a62009-06-04 16:24:59 +0200362 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700363 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200364 }
365}
366
Sascha Hauer71ec5152010-08-06 15:53:11 +0200367static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
368{
369 /* fill command */
370 writel(cmd, NFC_V3_FLASH_CMD);
371
372 /* send out command */
373 writel(NFC_CMD, NFC_V3_LAUNCH);
374
375 /* Wait for operation to complete */
376 wait_op_done(host, useirq);
377}
378
Sascha Hauer34f6e152008-09-02 17:16:59 +0200379/* This function issues the specified command to the NAND device and
380 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200381static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200382{
Brian Norris289c0522011-07-19 10:06:09 -0700383 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200384
Sascha Hauer1bc99182010-08-06 15:53:08 +0200385 writew(cmd, NFC_V1_V2_FLASH_CMD);
386 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200387
Uwe Kleine-König85569582012-04-23 11:23:34 +0200388 if (host->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200389 int max_retries = 100;
390 /* Reset completion is indicated by NFC_CONFIG2 */
391 /* being set to 0 */
392 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200393 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200394 break;
395 }
396 udelay(1);
397 }
398 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700399 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200400 } else {
401 /* Wait for operation to complete */
402 wait_op_done(host, useirq);
403 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200404}
405
Sascha Hauer71ec5152010-08-06 15:53:11 +0200406static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
407{
408 /* fill address */
409 writel(addr, NFC_V3_FLASH_ADDR0);
410
411 /* send out address */
412 writel(NFC_ADDR, NFC_V3_LAUNCH);
413
414 wait_op_done(host, 0);
415}
416
Sascha Hauer34f6e152008-09-02 17:16:59 +0200417/* This function sends an address (or partial address) to the
418 * NAND device. The address is used to select the source/destination for
419 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200420static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200421{
Brian Norris289c0522011-07-19 10:06:09 -0700422 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200423
Sascha Hauer1bc99182010-08-06 15:53:08 +0200424 writew(addr, NFC_V1_V2_FLASH_ADDR);
425 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200426
427 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200428 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200429}
430
Sascha Hauer71ec5152010-08-06 15:53:11 +0200431static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
432{
433 struct nand_chip *nand_chip = mtd->priv;
434 struct mxc_nand_host *host = nand_chip->priv;
435 uint32_t tmp;
436
437 tmp = readl(NFC_V3_CONFIG1);
438 tmp &= ~(7 << 4);
439 writel(tmp, NFC_V3_CONFIG1);
440
441 /* transfer data from NFC ram to nand */
442 writel(ops, NFC_V3_LAUNCH);
443
444 wait_op_done(host, false);
445}
446
Sascha Hauer5f973042010-08-06 15:53:06 +0200447static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200448{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200449 struct nand_chip *nand_chip = mtd->priv;
450 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200451 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200452
Sascha Hauer94671142009-10-05 12:14:21 +0200453 if (nfc_is_v1() && mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200454 bufs = 4;
455 else
456 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200457
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200458 for (i = 0; i < bufs; i++) {
459
460 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200461 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200462
Sascha Hauer1bc99182010-08-06 15:53:08 +0200463 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200464
465 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200466 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200467 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200468}
469
Sascha Hauer71ec5152010-08-06 15:53:11 +0200470static void send_read_id_v3(struct mxc_nand_host *host)
471{
472 /* Read ID into main buffer */
473 writel(NFC_ID, NFC_V3_LAUNCH);
474
475 wait_op_done(host, true);
476
477 memcpy(host->data_buf, host->main_area0, 16);
478}
479
Sascha Hauer34f6e152008-09-02 17:16:59 +0200480/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200481static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200482{
483 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200484
485 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200486 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200487
Sascha Hauer1bc99182010-08-06 15:53:08 +0200488 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200489
490 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200491 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200492
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200493 memcpy(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200494
495 if (this->options & NAND_BUSWIDTH_16) {
496 /* compress the ID info */
497 host->data_buf[1] = host->data_buf[2];
498 host->data_buf[2] = host->data_buf[4];
499 host->data_buf[3] = host->data_buf[6];
500 host->data_buf[4] = host->data_buf[8];
501 host->data_buf[5] = host->data_buf[10];
502 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200503}
504
Sascha Hauer71ec5152010-08-06 15:53:11 +0200505static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200506{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200507 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200508 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200509
Sascha Hauer71ec5152010-08-06 15:53:11 +0200510 return readl(NFC_V3_CONFIG1) >> 16;
511}
512
Sascha Hauer34f6e152008-09-02 17:16:59 +0200513/* This function requests the NANDFC to perform a read of the
514 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200515static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200516{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200517 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200518 uint32_t store;
519 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200520
Baruch Siachd178e3e2011-03-14 09:01:56 +0200521 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200522
523 /*
524 * The device status is stored in main_area0. To
525 * prevent corruption of the buffer save the value
526 * and restore it afterwards.
527 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200528 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200529
Sascha Hauer1bc99182010-08-06 15:53:08 +0200530 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200531 wait_op_done(host, true);
532
Sascha Hauer34f6e152008-09-02 17:16:59 +0200533 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200534
Sascha Hauer34f6e152008-09-02 17:16:59 +0200535 writel(store, main_buf);
536
537 return ret;
538}
539
540/* This functions is used by upper layer to checks if device is ready */
541static int mxc_nand_dev_ready(struct mtd_info *mtd)
542{
543 /*
544 * NFC handles R/B internally. Therefore, this function
545 * always returns status as ready.
546 */
547 return 1;
548}
549
550static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
551{
552 /*
553 * If HW ECC is enabled, we turn it on during init. There is
554 * no need to enable again here.
555 */
556}
557
Sascha Hauer94f77e52010-08-06 15:53:09 +0200558static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200559 u_char *read_ecc, u_char *calc_ecc)
560{
561 struct nand_chip *nand_chip = mtd->priv;
562 struct mxc_nand_host *host = nand_chip->priv;
563
564 /*
565 * 1-Bit errors are automatically corrected in HW. No need for
566 * additional correction. 2-Bit errors cannot be corrected by
567 * HW ECC, so we need to return failure
568 */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200569 uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200570
571 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700572 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200573 return -1;
574 }
575
576 return 0;
577}
578
Sascha Hauer94f77e52010-08-06 15:53:09 +0200579static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
580 u_char *read_ecc, u_char *calc_ecc)
581{
582 struct nand_chip *nand_chip = mtd->priv;
583 struct mxc_nand_host *host = nand_chip->priv;
584 u32 ecc_stat, err;
585 int no_subpages = 1;
586 int ret = 0;
587 u8 ecc_bit_mask, err_limit;
588
589 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
590 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
591
592 no_subpages = mtd->writesize >> 9;
593
Sascha Hauer71ec5152010-08-06 15:53:11 +0200594 if (nfc_is_v21())
595 ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT);
596 else
597 ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200598
599 do {
600 err = ecc_stat & ecc_bit_mask;
601 if (err > err_limit) {
602 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
603 return -1;
604 } else {
605 ret += err;
606 }
607 ecc_stat >>= 4;
608 } while (--no_subpages);
609
610 mtd->ecc_stats.corrected += ret;
611 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
612
613 return ret;
614}
615
Sascha Hauer34f6e152008-09-02 17:16:59 +0200616static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
617 u_char *ecc_code)
618{
619 return 0;
620}
621
622static u_char mxc_nand_read_byte(struct mtd_info *mtd)
623{
624 struct nand_chip *nand_chip = mtd->priv;
625 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200626 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200627
628 /* Check for status request */
629 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200630 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200631
Sascha Hauerf8f96082009-06-04 17:12:26 +0200632 ret = *(uint8_t *)(host->data_buf + host->buf_start);
633 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200634
635 return ret;
636}
637
638static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
639{
640 struct nand_chip *nand_chip = mtd->priv;
641 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200642 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200643
Sascha Hauerf8f96082009-06-04 17:12:26 +0200644 ret = *(uint16_t *)(host->data_buf + host->buf_start);
645 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200646
647 return ret;
648}
649
650/* Write data of length len to buffer buf. The data to be
651 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
652 * Operation by the NFC, the data is written to NAND Flash */
653static void mxc_nand_write_buf(struct mtd_info *mtd,
654 const u_char *buf, int len)
655{
656 struct nand_chip *nand_chip = mtd->priv;
657 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200658 u16 col = host->buf_start;
659 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200660
Sascha Hauerf8f96082009-06-04 17:12:26 +0200661 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200662
Sascha Hauerf8f96082009-06-04 17:12:26 +0200663 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200664
Sascha Hauerf8f96082009-06-04 17:12:26 +0200665 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200666}
667
668/* Read the data buffer from the NAND Flash. To read the data from NAND
669 * Flash first the data output cycle is initiated by the NFC, which copies
670 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
671 */
672static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
673{
674 struct nand_chip *nand_chip = mtd->priv;
675 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200676 u16 col = host->buf_start;
677 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200678
Sascha Hauerf8f96082009-06-04 17:12:26 +0200679 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200680
Baruch Siach5d9d9932011-03-02 16:47:55 +0200681 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200682
Baruch Siach5d9d9932011-03-02 16:47:55 +0200683 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200684}
685
686/* Used by the upper layer to verify the data in NAND Flash
687 * with the data in the buf. */
688static int mxc_nand_verify_buf(struct mtd_info *mtd,
689 const u_char *buf, int len)
690{
691 return -EFAULT;
692}
693
694/* This function is used by upper layer for select and
695 * deselect of the NAND chip */
696static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
697{
698 struct nand_chip *nand_chip = mtd->priv;
699 struct mxc_nand_host *host = nand_chip->priv;
700
Baruch Siachd178e3e2011-03-14 09:01:56 +0200701 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200702 /* Disable the NFC clock */
703 if (host->clk_act) {
704 clk_disable(host->clk);
705 host->clk_act = 0;
706 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200707 return;
708 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200709
Baruch Siachd178e3e2011-03-14 09:01:56 +0200710 if (!host->clk_act) {
711 /* Enable the NFC clock */
712 clk_enable(host->clk);
713 host->clk_act = 1;
714 }
715
716 if (nfc_is_v21()) {
717 host->active_cs = chip;
718 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200719 }
720}
721
Sascha Hauerf8f96082009-06-04 17:12:26 +0200722/*
723 * Function to transfer data to/from spare area.
724 */
725static void copy_spare(struct mtd_info *mtd, bool bfrom)
726{
727 struct nand_chip *this = mtd->priv;
728 struct mxc_nand_host *host = this->priv;
729 u16 i, j;
730 u16 n = mtd->writesize >> 9;
731 u8 *d = host->data_buf + mtd->writesize;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200732 u8 *s = host->spare0;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200733 u16 t = host->spare_len;
734
735 j = (mtd->oobsize / n >> 1) << 1;
736
737 if (bfrom) {
738 for (i = 0; i < n - 1; i++)
739 memcpy(d + i * j, s + i * t, j);
740
741 /* the last section */
742 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
743 } else {
744 for (i = 0; i < n - 1; i++)
745 memcpy(&s[i * t], &d[i * j], j);
746
747 /* the last section */
748 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
749 }
750}
751
Sascha Hauera3e65b62009-06-02 11:47:59 +0200752static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200753{
754 struct nand_chip *nand_chip = mtd->priv;
755 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200756
757 /* Write out column address, if necessary */
758 if (column != -1) {
759 /*
760 * MXC NANDFC can only perform full page+spare or
761 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100762 * perform a read/write buf operation, the saved column
763 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200764 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200765 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200766 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200767 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200768 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200769 }
770
771 /* Write out page address, if necessary */
772 if (page_addr != -1) {
773 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200774 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200775
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200776 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400777 if (mtd->size >= 0x10000000) {
778 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200779 host->devtype_data->send_addr(host,
780 (page_addr >> 8) & 0xff,
781 false);
782 host->devtype_data->send_addr(host,
783 (page_addr >> 16) & 0xff,
784 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400785 } else
786 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200787 host->devtype_data->send_addr(host,
788 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200789 } else {
790 /* One more address cycle for higher density devices */
791 if (mtd->size >= 0x4000000) {
792 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200793 host->devtype_data->send_addr(host,
794 (page_addr >> 8) & 0xff,
795 false);
796 host->devtype_data->send_addr(host,
797 (page_addr >> 16) & 0xff,
798 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200799 } else
800 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200801 host->devtype_data->send_addr(host,
802 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200803 }
804 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200805}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200806
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200807/*
808 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
809 * on how much oob the nand chip has. For 8bit ecc we need at least
810 * 26 bytes of oob data per 512 byte block.
811 */
812static int get_eccsize(struct mtd_info *mtd)
813{
814 int oobbytes_per_512 = 0;
815
816 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
817
818 if (oobbytes_per_512 < 26)
819 return 4;
820 else
821 return 8;
822}
823
Sascha Hauer5f973042010-08-06 15:53:06 +0200824static void preset_v1_v2(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200825{
826 struct nand_chip *nand_chip = mtd->priv;
827 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200828 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200829
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200830 if (nand_chip->ecc.mode == NAND_ECC_HW)
831 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
832
833 if (nfc_is_v21())
834 config1 |= NFC_V2_CONFIG1_FP_INT;
835
Uwe Kleine-König85569582012-04-23 11:23:34 +0200836 if (!host->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200837 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200838
839 if (nfc_is_v21() && mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200840 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
841
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200842 host->eccsize = get_eccsize(mtd);
843 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200844 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
845
846 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200847 } else {
848 host->eccsize = 1;
849 }
850
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200851 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200852 /* preset operation */
853
854 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200855 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200856
857 /* Blocks to be unlocked */
858 if (nfc_is_v21()) {
Baruch Siachd178e3e2011-03-14 09:01:56 +0200859 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
860 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
861 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
862 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
863 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
864 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
865 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
866 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200867 } else if (nfc_is_v1()) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200868 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
Wolfram Stering5172ac12011-09-23 13:53:44 +0200869 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
Ivo Claryssed4840182010-04-08 16:14:44 +0200870 } else
871 BUG();
872
873 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200874 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200875}
876
Sascha Hauer71ec5152010-08-06 15:53:11 +0200877static void preset_v3(struct mtd_info *mtd)
878{
879 struct nand_chip *chip = mtd->priv;
880 struct mxc_nand_host *host = chip->priv;
881 uint32_t config2, config3;
882 int i, addr_phases;
883
884 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
885 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
886
887 /* Unlock the internal RAM Buffer */
888 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
889 NFC_V3_WRPROT);
890
891 /* Blocks to be unlocked */
892 for (i = 0; i < NAND_MAX_CHIPS; i++)
893 writel(0x0 | (0xffff << 16),
894 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
895
896 writel(0, NFC_V3_IPC);
897
898 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
899 NFC_V3_CONFIG2_2CMD_PHASES |
900 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
901 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +0200902 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +0200903 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
904
905 if (chip->ecc.mode == NAND_ECC_HW)
906 config2 |= NFC_V3_CONFIG2_ECC_EN;
907
908 addr_phases = fls(chip->pagemask) >> 3;
909
910 if (mtd->writesize == 2048) {
911 config2 |= NFC_V3_CONFIG2_PS_2048;
912 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
913 } else if (mtd->writesize == 4096) {
914 config2 |= NFC_V3_CONFIG2_PS_4096;
915 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
916 } else {
917 config2 |= NFC_V3_CONFIG2_PS_512;
918 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
919 }
920
921 if (mtd->writesize) {
922 config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
923 host->eccsize = get_eccsize(mtd);
924 if (host->eccsize == 8)
925 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
926 }
927
928 writel(config2, NFC_V3_CONFIG2);
929
930 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
931 NFC_V3_CONFIG3_NO_SDMA |
932 NFC_V3_CONFIG3_RBB_MODE |
933 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
934 NFC_V3_CONFIG3_ADD_OP(0);
935
936 if (!(chip->options & NAND_BUSWIDTH_16))
937 config3 |= NFC_V3_CONFIG3_FW8;
938
939 writel(config3, NFC_V3_CONFIG3);
940
941 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200942}
943
Sascha Hauer34f6e152008-09-02 17:16:59 +0200944/* Used by the upper layer to write command to NAND Flash for
945 * different operations to be carried out on NAND Flash */
946static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
947 int column, int page_addr)
948{
949 struct nand_chip *nand_chip = mtd->priv;
950 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200951
Brian Norris289c0522011-07-19 10:06:09 -0700952 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +0200953 command, column, page_addr);
954
955 /* Reset command state information */
956 host->status_request = false;
957
958 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200959 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +0200960 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200961 host->devtype_data->preset(mtd);
962 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +0200963 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200964
Sascha Hauer34f6e152008-09-02 17:16:59 +0200965 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +0200966 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200967 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +0200968
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200969 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +0200970 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200971 break;
972
Sascha Hauer34f6e152008-09-02 17:16:59 +0200973 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +0200974 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +0200975 if (command == NAND_CMD_READ0)
976 host->buf_start = column;
977 else
978 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200979
Sascha Hauer5ea32022010-04-27 15:24:01 +0200980 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +0200981
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200982 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +0200983 mxc_do_addr_cycle(mtd, column, page_addr);
984
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200985 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200986 host->devtype_data->send_cmd(host,
987 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200988
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200989 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +0200990
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200991 memcpy(host->data_buf, host->main_area0, mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +0200992 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200993 break;
994
Sascha Hauer34f6e152008-09-02 17:16:59 +0200995 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +0200996 if (column >= mtd->writesize)
997 /* call ourself to read a page */
998 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200999
Sascha Hauer5ea32022010-04-27 15:24:01 +02001000 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001001
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001002 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001003 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001004 break;
1005
1006 case NAND_CMD_PAGEPROG:
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001007 memcpy(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001008 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001009 host->devtype_data->send_page(mtd, NFC_INPUT);
1010 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001011 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001012 break;
1013
Sascha Hauer34f6e152008-09-02 17:16:59 +02001014 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001015 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001016 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001017 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001018 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001019 break;
1020
Sascha Hauer89121a62009-06-04 17:18:01 +02001021 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001022 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001023 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001024 mxc_do_addr_cycle(mtd, column, page_addr);
1025
Sascha Hauer34f6e152008-09-02 17:16:59 +02001026 break;
1027 }
1028}
1029
Sascha Hauerf1372052009-10-21 14:25:27 +02001030/*
1031 * The generic flash bbt decriptors overlap with our ecc
1032 * hardware, so define some i.MX specific ones.
1033 */
1034static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1035static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1036
1037static struct nand_bbt_descr bbt_main_descr = {
1038 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1039 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1040 .offs = 0,
1041 .len = 4,
1042 .veroffs = 4,
1043 .maxblocks = 4,
1044 .pattern = bbt_pattern,
1045};
1046
1047static struct nand_bbt_descr bbt_mirror_descr = {
1048 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1049 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1050 .offs = 0,
1051 .len = 4,
1052 .veroffs = 4,
1053 .maxblocks = 4,
1054 .pattern = mirror_pattern,
1055};
1056
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001057/* v1: i.MX21, i.MX27, i.MX31 */
1058static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
1059 .preset = preset_v1_v2,
1060 .send_cmd = send_cmd_v1_v2,
1061 .send_addr = send_addr_v1_v2,
1062 .send_page = send_page_v1_v2,
1063 .send_read_id = send_read_id_v1_v2,
1064 .get_dev_status = get_dev_status_v1_v2,
1065 .check_int = check_int_v1_v2,
1066 .irq_control = irq_control_v1_v2,
1067};
1068
1069/* v21: i.MX25, i.MX35 */
1070static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
1071 .preset = preset_v1_v2,
1072 .send_cmd = send_cmd_v1_v2,
1073 .send_addr = send_addr_v1_v2,
1074 .send_page = send_page_v1_v2,
1075 .send_read_id = send_read_id_v1_v2,
1076 .get_dev_status = get_dev_status_v1_v2,
1077 .check_int = check_int_v1_v2,
1078 .irq_control = irq_control_v1_v2,
1079};
1080
1081/* v3: i.MX51, i.MX53 */
1082static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1083 .preset = preset_v3,
1084 .send_cmd = send_cmd_v3,
1085 .send_addr = send_addr_v3,
1086 .send_page = send_page_v3,
1087 .send_read_id = send_read_id_v3,
1088 .get_dev_status = get_dev_status_v3,
1089 .check_int = check_int_v3,
1090 .irq_control = irq_control_v3,
1091};
1092
Sascha Hauer34f6e152008-09-02 17:16:59 +02001093static int __init mxcnd_probe(struct platform_device *pdev)
1094{
1095 struct nand_chip *this;
1096 struct mtd_info *mtd;
1097 struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
1098 struct mxc_nand_host *host;
1099 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001100 int err = 0;
Sascha Hauer94671142009-10-05 12:14:21 +02001101 struct nand_ecclayout *oob_smallpage, *oob_largepage;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001102
1103 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +02001104 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
1105 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001106 if (!host)
1107 return -ENOMEM;
1108
Sascha Hauerf8f96082009-06-04 17:12:26 +02001109 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001110
Sascha Hauer34f6e152008-09-02 17:16:59 +02001111 host->dev = &pdev->dev;
1112 /* structures must be linked */
1113 this = &host->nand;
1114 mtd = &host->mtd;
1115 mtd->priv = this;
1116 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001117 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001118 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001119
1120 /* 50 us command delay time */
1121 this->chip_delay = 5;
1122
1123 this->priv = host;
1124 this->dev_ready = mxc_nand_dev_ready;
1125 this->cmdfunc = mxc_nand_command;
1126 this->select_chip = mxc_nand_select_chip;
1127 this->read_byte = mxc_nand_read_byte;
1128 this->read_word = mxc_nand_read_word;
1129 this->write_buf = mxc_nand_write_buf;
1130 this->read_buf = mxc_nand_read_buf;
1131 this->verify_buf = mxc_nand_verify_buf;
1132
Sascha Hauere65fb002009-02-16 14:29:10 +01001133 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +04001134 if (IS_ERR(host->clk)) {
1135 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001136 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +04001137 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001138
1139 clk_enable(host->clk);
1140 host->clk_act = 1;
1141
1142 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1143 if (!res) {
1144 err = -ENODEV;
1145 goto eres;
1146 }
1147
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001148 host->base = ioremap(res->start, resource_size(res));
1149 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +04001150 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001151 goto eres;
1152 }
1153
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001154 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001155
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001156 if (nfc_is_v1()) {
1157 host->devtype_data = &imx21_nand_devtype_data;
Sascha Hauer63f14742010-10-18 10:16:26 +02001158 if (cpu_is_mx21())
Uwe Kleine-König85569582012-04-23 11:23:34 +02001159 host->irqpending_quirk = 1;
Sascha Hauer938cf992010-08-06 15:53:04 +02001160 host->regs = host->base + 0xe00;
Sascha Hauer94671142009-10-05 12:14:21 +02001161 host->spare0 = host->base + 0x800;
1162 host->spare_len = 16;
1163 oob_smallpage = &nandv1_hw_eccoob_smallpage;
1164 oob_largepage = &nandv1_hw_eccoob_largepage;
Sascha Hauer94671142009-10-05 12:14:21 +02001165 this->ecc.bytes = 3;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001166 host->eccsize = 1;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001167 } else if (nfc_is_v21()) {
1168 host->devtype_data = &imx25_nand_devtype_data;
1169 host->regs = host->base + 0x1e00;
1170 host->spare0 = host->base + 0x1000;
1171 host->spare_len = 64;
1172 oob_smallpage = &nandv2_hw_eccoob_smallpage;
1173 oob_largepage = &nandv2_hw_eccoob_largepage;
1174 this->ecc.bytes = 9;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001175 } else if (nfc_is_v3_2()) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001176 host->devtype_data = &imx51_nand_devtype_data;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001177 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1178 if (!res) {
1179 err = -ENODEV;
1180 goto eirq;
1181 }
1182 host->regs_ip = ioremap(res->start, resource_size(res));
1183 if (!host->regs_ip) {
1184 err = -ENOMEM;
1185 goto eirq;
1186 }
1187 host->regs_axi = host->base + 0x1e00;
1188 host->spare0 = host->base + 0x1000;
1189 host->spare_len = 64;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001190 oob_smallpage = &nandv2_hw_eccoob_smallpage;
1191 oob_largepage = &nandv2_hw_eccoob_largepage;
Sascha Hauer94671142009-10-05 12:14:21 +02001192 } else
1193 BUG();
Sascha Hauer34f6e152008-09-02 17:16:59 +02001194
Sascha Hauer13e1add2009-10-21 10:39:05 +02001195 this->ecc.size = 512;
Sascha Hauer94671142009-10-05 12:14:21 +02001196 this->ecc.layout = oob_smallpage;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001197
1198 if (pdata->hw_ecc) {
1199 this->ecc.calculate = mxc_nand_calculate_ecc;
1200 this->ecc.hwctl = mxc_nand_enable_hwecc;
Sascha Hauer94f77e52010-08-06 15:53:09 +02001201 if (nfc_is_v1())
1202 this->ecc.correct = mxc_nand_correct_data_v1;
1203 else
1204 this->ecc.correct = mxc_nand_correct_data_v2_v3;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001205 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001206 } else {
1207 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001208 }
1209
Sascha Hauer34f6e152008-09-02 17:16:59 +02001210 /* NAND bus width determines access funtions used by upper layer */
Sascha Hauer13e1add2009-10-21 10:39:05 +02001211 if (pdata->width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001212 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001213
Sascha Hauerf1372052009-10-21 14:25:27 +02001214 if (pdata->flash_bbt) {
1215 this->bbt_td = &bbt_main_descr;
1216 this->bbt_md = &bbt_mirror_descr;
1217 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001218 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001219 }
1220
Sascha Hauer63f14742010-10-18 10:16:26 +02001221 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001222
1223 host->irq = platform_get_irq(pdev, 0);
1224
Sascha Hauer63f14742010-10-18 10:16:26 +02001225 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001226 * Use host->devtype_data->irq_control() here instead of irq_control()
1227 * because we must not disable_irq_nosync without having requested the
1228 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001229 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001230 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001231
Ivo Claryssea47bfd22010-04-08 16:16:51 +02001232 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001233 if (err)
1234 goto eirq;
1235
Sascha Hauer63f14742010-10-18 10:16:26 +02001236 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001237 * Now that we "own" the interrupt make sure the interrupt mask bit is
1238 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1239 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001240 */
Uwe Kleine-König85569582012-04-23 11:23:34 +02001241 if (host->irqpending_quirk) {
1242 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001243 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001244 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001245
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001246 /* first scan to find the device and get the page size */
Baruch Siachd178e3e2011-03-14 09:01:56 +02001247 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001248 err = -ENXIO;
1249 goto escan;
1250 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001251
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001252 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001253 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001254
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001255 if (mtd->writesize == 2048)
Sascha Hauer94671142009-10-05 12:14:21 +02001256 this->ecc.layout = oob_largepage;
Baruch Siach2c1c5f12011-03-09 16:12:20 +02001257 if (nfc_is_v21() && mtd->writesize == 4096)
1258 this->ecc.layout = &nandv2_hw_eccoob_4k;
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001259
1260 /* second phase scan */
1261 if (nand_scan_tail(mtd)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +02001262 err = -ENXIO;
1263 goto escan;
1264 }
1265
Mike Dunn6a918ba2012-03-11 14:21:11 -07001266 if (this->ecc.mode == NAND_ECC_HW) {
1267 if (nfc_is_v1())
1268 this->ecc.strength = 1;
1269 else
1270 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1271 }
1272
Sascha Hauer34f6e152008-09-02 17:16:59 +02001273 /* Register the partitions */
Artem Bityutskiy42d7fbe2012-03-09 19:24:26 +02001274 mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts,
1275 pdata->nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001276
1277 platform_set_drvdata(pdev, host);
1278
1279 return 0;
1280
1281escan:
Magnus Liljab258fd82009-05-08 21:57:47 +02001282 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001283eirq:
Sascha Hauer71ec5152010-08-06 15:53:11 +02001284 if (host->regs_ip)
1285 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001286 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001287eres:
1288 clk_put(host->clk);
1289eclk:
1290 kfree(host);
1291
1292 return err;
1293}
1294
Uwe Kleine-König51eeb872009-12-07 09:44:05 +00001295static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001296{
1297 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1298
1299 clk_put(host->clk);
1300
1301 platform_set_drvdata(pdev, NULL);
1302
1303 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +02001304 free_irq(host->irq, host);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001305 if (host->regs_ip)
1306 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001307 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001308 kfree(host);
1309
1310 return 0;
1311}
1312
Sascha Hauer34f6e152008-09-02 17:16:59 +02001313static struct platform_driver mxcnd_driver = {
1314 .driver = {
1315 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001316 .owner = THIS_MODULE,
Eric Bénard04dd0d32010-06-17 20:59:04 +02001317 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +01001318 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +02001319};
1320
1321static int __init mxc_nd_init(void)
1322{
Vladimir Barinov8541c112009-04-23 15:47:22 +04001323 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001324}
1325
1326static void __exit mxc_nd_cleanup(void)
1327{
1328 /* Unregister the device structure */
1329 platform_driver_unregister(&mxcnd_driver);
1330}
1331
1332module_init(mxc_nd_init);
1333module_exit(mxc_nd_cleanup);
1334
1335MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1336MODULE_DESCRIPTION("MXC NAND MTD driver");
1337MODULE_LICENSE("GPL");