blob: e02d27a937c82e527f665a4e105f3a04bd615fef [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önige4303b22012-04-23 11:23:35 +0200156};
157
Sascha Hauer34f6e152008-09-02 17:16:59 +0200158struct mxc_nand_host {
159 struct mtd_info mtd;
160 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200161 struct device *dev;
162
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200163 void *spare0;
164 void *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200165
166 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200167 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200168 void __iomem *regs_axi;
169 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200170 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200171 struct clk *clk;
172 int clk_act;
173 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200174 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200175 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200176
Sascha Hauer63f14742010-10-18 10:16:26 +0200177 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200178
179 uint8_t *data_buf;
180 unsigned int buf_start;
181 int spare_len;
Sascha Hauer5f973042010-08-06 15:53:06 +0200182
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200183 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König85569582012-04-23 11:23:34 +0200184
185 /*
186 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
187 * (CONFIG1:INT_MSK is set). To handle this the driver uses
188 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
189 */
190 int irqpending_quirk;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200191};
192
Sascha Hauer34f6e152008-09-02 17:16:59 +0200193/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200194static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200195 .eccbytes = 5,
196 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200197 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200198};
199
Sascha Hauer94671142009-10-05 12:14:21 +0200200static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400201 .eccbytes = 20,
202 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
203 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
204 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200205};
206
Sascha Hauer94671142009-10-05 12:14:21 +0200207/* OOB description for 512 byte pages with 16 byte OOB */
208static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
209 .eccbytes = 1 * 9,
210 .eccpos = {
211 7, 8, 9, 10, 11, 12, 13, 14, 15
212 },
213 .oobfree = {
214 {.offset = 0, .length = 5}
215 }
216};
217
218/* OOB description for 2048 byte pages with 64 byte OOB */
219static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
220 .eccbytes = 4 * 9,
221 .eccpos = {
222 7, 8, 9, 10, 11, 12, 13, 14, 15,
223 23, 24, 25, 26, 27, 28, 29, 30, 31,
224 39, 40, 41, 42, 43, 44, 45, 46, 47,
225 55, 56, 57, 58, 59, 60, 61, 62, 63
226 },
227 .oobfree = {
228 {.offset = 2, .length = 4},
229 {.offset = 16, .length = 7},
230 {.offset = 32, .length = 7},
231 {.offset = 48, .length = 7}
232 }
233};
234
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200235/* OOB description for 4096 byte pages with 128 byte OOB */
236static struct nand_ecclayout nandv2_hw_eccoob_4k = {
237 .eccbytes = 8 * 9,
238 .eccpos = {
239 7, 8, 9, 10, 11, 12, 13, 14, 15,
240 23, 24, 25, 26, 27, 28, 29, 30, 31,
241 39, 40, 41, 42, 43, 44, 45, 46, 47,
242 55, 56, 57, 58, 59, 60, 61, 62, 63,
243 71, 72, 73, 74, 75, 76, 77, 78, 79,
244 87, 88, 89, 90, 91, 92, 93, 94, 95,
245 103, 104, 105, 106, 107, 108, 109, 110, 111,
246 119, 120, 121, 122, 123, 124, 125, 126, 127,
247 },
248 .oobfree = {
249 {.offset = 2, .length = 4},
250 {.offset = 16, .length = 7},
251 {.offset = 32, .length = 7},
252 {.offset = 48, .length = 7},
253 {.offset = 64, .length = 7},
254 {.offset = 80, .length = 7},
255 {.offset = 96, .length = 7},
256 {.offset = 112, .length = 7},
257 }
258};
259
Sascha Hauer34f6e152008-09-02 17:16:59 +0200260static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200261
Sascha Hauer71ec5152010-08-06 15:53:11 +0200262static int check_int_v3(struct mxc_nand_host *host)
263{
264 uint32_t tmp;
265
266 tmp = readl(NFC_V3_IPC);
267 if (!(tmp & NFC_V3_IPC_INT))
268 return 0;
269
270 tmp &= ~NFC_V3_IPC_INT;
271 writel(tmp, NFC_V3_IPC);
272
273 return 1;
274}
275
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200276static int check_int_v1_v2(struct mxc_nand_host *host)
277{
278 uint32_t tmp;
279
Sascha Hauer1bc99182010-08-06 15:53:08 +0200280 tmp = readw(NFC_V1_V2_CONFIG2);
281 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200282 return 0;
283
Uwe Kleine-König85569582012-04-23 11:23:34 +0200284 if (!host->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200285 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200286
287 return 1;
288}
289
Sascha Hauer63f14742010-10-18 10:16:26 +0200290static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
291{
292 uint16_t tmp;
293
294 tmp = readw(NFC_V1_V2_CONFIG1);
295
296 if (activate)
297 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
298 else
299 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
300
301 writew(tmp, NFC_V1_V2_CONFIG1);
302}
303
304static void irq_control_v3(struct mxc_nand_host *host, int activate)
305{
306 uint32_t tmp;
307
308 tmp = readl(NFC_V3_CONFIG2);
309
310 if (activate)
311 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
312 else
313 tmp |= NFC_V3_CONFIG2_INT_MSK;
314
315 writel(tmp, NFC_V3_CONFIG2);
316}
317
Uwe Kleine-König85569582012-04-23 11:23:34 +0200318static void irq_control(struct mxc_nand_host *host, int activate)
319{
320 if (host->irqpending_quirk) {
321 if (activate)
322 enable_irq(host->irq);
323 else
324 disable_irq_nosync(host->irq);
325 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200326 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200327 }
328}
329
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200330static u32 get_ecc_status_v1(struct mxc_nand_host *host)
331{
332 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
333}
334
335static u32 get_ecc_status_v2(struct mxc_nand_host *host)
336{
337 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
338}
339
340static u32 get_ecc_status_v3(struct mxc_nand_host *host)
341{
342 return readl(NFC_V3_ECC_STATUS_RESULT);
343}
344
Uwe Kleine-König85569582012-04-23 11:23:34 +0200345static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
346{
347 struct mxc_nand_host *host = dev_id;
348
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200349 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200350 return IRQ_NONE;
351
352 irq_control(host, 0);
353
354 complete(&host->op_completion);
355
356 return IRQ_HANDLED;
357}
358
Sascha Hauer34f6e152008-09-02 17:16:59 +0200359/* This function polls the NANDFC to wait for the basic operation to
360 * complete by checking the INT bit of config2 register.
361 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200362static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200363{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200364 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200365
366 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200367 if (!host->devtype_data->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200368 INIT_COMPLETION(host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200369 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200370 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200371 }
372 } else {
373 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200374 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200375 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200376
Sascha Hauer34f6e152008-09-02 17:16:59 +0200377 udelay(1);
378 }
Roel Kluin43950a62009-06-04 16:24:59 +0200379 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700380 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200381 }
382}
383
Sascha Hauer71ec5152010-08-06 15:53:11 +0200384static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
385{
386 /* fill command */
387 writel(cmd, NFC_V3_FLASH_CMD);
388
389 /* send out command */
390 writel(NFC_CMD, NFC_V3_LAUNCH);
391
392 /* Wait for operation to complete */
393 wait_op_done(host, useirq);
394}
395
Sascha Hauer34f6e152008-09-02 17:16:59 +0200396/* This function issues the specified command to the NAND device and
397 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200398static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200399{
Brian Norris289c0522011-07-19 10:06:09 -0700400 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200401
Sascha Hauer1bc99182010-08-06 15:53:08 +0200402 writew(cmd, NFC_V1_V2_FLASH_CMD);
403 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200404
Uwe Kleine-König85569582012-04-23 11:23:34 +0200405 if (host->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200406 int max_retries = 100;
407 /* Reset completion is indicated by NFC_CONFIG2 */
408 /* being set to 0 */
409 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200410 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200411 break;
412 }
413 udelay(1);
414 }
415 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700416 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200417 } else {
418 /* Wait for operation to complete */
419 wait_op_done(host, useirq);
420 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200421}
422
Sascha Hauer71ec5152010-08-06 15:53:11 +0200423static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
424{
425 /* fill address */
426 writel(addr, NFC_V3_FLASH_ADDR0);
427
428 /* send out address */
429 writel(NFC_ADDR, NFC_V3_LAUNCH);
430
431 wait_op_done(host, 0);
432}
433
Sascha Hauer34f6e152008-09-02 17:16:59 +0200434/* This function sends an address (or partial address) to the
435 * NAND device. The address is used to select the source/destination for
436 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200437static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200438{
Brian Norris289c0522011-07-19 10:06:09 -0700439 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200440
Sascha Hauer1bc99182010-08-06 15:53:08 +0200441 writew(addr, NFC_V1_V2_FLASH_ADDR);
442 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200443
444 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200445 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200446}
447
Sascha Hauer71ec5152010-08-06 15:53:11 +0200448static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
449{
450 struct nand_chip *nand_chip = mtd->priv;
451 struct mxc_nand_host *host = nand_chip->priv;
452 uint32_t tmp;
453
454 tmp = readl(NFC_V3_CONFIG1);
455 tmp &= ~(7 << 4);
456 writel(tmp, NFC_V3_CONFIG1);
457
458 /* transfer data from NFC ram to nand */
459 writel(ops, NFC_V3_LAUNCH);
460
461 wait_op_done(host, false);
462}
463
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200464static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
465{
466 struct nand_chip *nand_chip = mtd->priv;
467 struct mxc_nand_host *host = nand_chip->priv;
468
469 /* NANDFC buffer 0 is used for page read/write */
470 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
471
472 writew(ops, NFC_V1_V2_CONFIG2);
473
474 /* Wait for operation to complete */
475 wait_op_done(host, true);
476}
477
478static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200479{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200480 struct nand_chip *nand_chip = mtd->priv;
481 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200482 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200483
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200484 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200485 bufs = 4;
486 else
487 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200488
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200489 for (i = 0; i < bufs; i++) {
490
491 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200492 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200493
Sascha Hauer1bc99182010-08-06 15:53:08 +0200494 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200495
496 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200497 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200498 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200499}
500
Sascha Hauer71ec5152010-08-06 15:53:11 +0200501static void send_read_id_v3(struct mxc_nand_host *host)
502{
503 /* Read ID into main buffer */
504 writel(NFC_ID, NFC_V3_LAUNCH);
505
506 wait_op_done(host, true);
507
508 memcpy(host->data_buf, host->main_area0, 16);
509}
510
Sascha Hauer34f6e152008-09-02 17:16:59 +0200511/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200512static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200513{
514 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200515
516 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200517 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200518
Sascha Hauer1bc99182010-08-06 15:53:08 +0200519 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200520
521 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200522 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200523
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200524 memcpy(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200525
526 if (this->options & NAND_BUSWIDTH_16) {
527 /* compress the ID info */
528 host->data_buf[1] = host->data_buf[2];
529 host->data_buf[2] = host->data_buf[4];
530 host->data_buf[3] = host->data_buf[6];
531 host->data_buf[4] = host->data_buf[8];
532 host->data_buf[5] = host->data_buf[10];
533 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200534}
535
Sascha Hauer71ec5152010-08-06 15:53:11 +0200536static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200537{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200538 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200539 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200540
Sascha Hauer71ec5152010-08-06 15:53:11 +0200541 return readl(NFC_V3_CONFIG1) >> 16;
542}
543
Sascha Hauer34f6e152008-09-02 17:16:59 +0200544/* This function requests the NANDFC to perform a read of the
545 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200546static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200547{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200548 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200549 uint32_t store;
550 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551
Baruch Siachd178e3e2011-03-14 09:01:56 +0200552 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200553
554 /*
555 * The device status is stored in main_area0. To
556 * prevent corruption of the buffer save the value
557 * and restore it afterwards.
558 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200559 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200560
Sascha Hauer1bc99182010-08-06 15:53:08 +0200561 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200562 wait_op_done(host, true);
563
Sascha Hauer34f6e152008-09-02 17:16:59 +0200564 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200565
Sascha Hauer34f6e152008-09-02 17:16:59 +0200566 writel(store, main_buf);
567
568 return ret;
569}
570
571/* This functions is used by upper layer to checks if device is ready */
572static int mxc_nand_dev_ready(struct mtd_info *mtd)
573{
574 /*
575 * NFC handles R/B internally. Therefore, this function
576 * always returns status as ready.
577 */
578 return 1;
579}
580
581static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
582{
583 /*
584 * If HW ECC is enabled, we turn it on during init. There is
585 * no need to enable again here.
586 */
587}
588
Sascha Hauer94f77e52010-08-06 15:53:09 +0200589static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200590 u_char *read_ecc, u_char *calc_ecc)
591{
592 struct nand_chip *nand_chip = mtd->priv;
593 struct mxc_nand_host *host = nand_chip->priv;
594
595 /*
596 * 1-Bit errors are automatically corrected in HW. No need for
597 * additional correction. 2-Bit errors cannot be corrected by
598 * HW ECC, so we need to return failure
599 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200600 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200601
602 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700603 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200604 return -1;
605 }
606
607 return 0;
608}
609
Sascha Hauer94f77e52010-08-06 15:53:09 +0200610static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
611 u_char *read_ecc, u_char *calc_ecc)
612{
613 struct nand_chip *nand_chip = mtd->priv;
614 struct mxc_nand_host *host = nand_chip->priv;
615 u32 ecc_stat, err;
616 int no_subpages = 1;
617 int ret = 0;
618 u8 ecc_bit_mask, err_limit;
619
620 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
621 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
622
623 no_subpages = mtd->writesize >> 9;
624
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200625 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200626
627 do {
628 err = ecc_stat & ecc_bit_mask;
629 if (err > err_limit) {
630 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
631 return -1;
632 } else {
633 ret += err;
634 }
635 ecc_stat >>= 4;
636 } while (--no_subpages);
637
638 mtd->ecc_stats.corrected += ret;
639 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
640
641 return ret;
642}
643
Sascha Hauer34f6e152008-09-02 17:16:59 +0200644static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
645 u_char *ecc_code)
646{
647 return 0;
648}
649
650static u_char mxc_nand_read_byte(struct mtd_info *mtd)
651{
652 struct nand_chip *nand_chip = mtd->priv;
653 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200654 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200655
656 /* Check for status request */
657 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200658 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200659
Sascha Hauerf8f96082009-06-04 17:12:26 +0200660 ret = *(uint8_t *)(host->data_buf + host->buf_start);
661 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200662
663 return ret;
664}
665
666static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
667{
668 struct nand_chip *nand_chip = mtd->priv;
669 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200670 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200671
Sascha Hauerf8f96082009-06-04 17:12:26 +0200672 ret = *(uint16_t *)(host->data_buf + host->buf_start);
673 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200674
675 return ret;
676}
677
678/* Write data of length len to buffer buf. The data to be
679 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
680 * Operation by the NFC, the data is written to NAND Flash */
681static void mxc_nand_write_buf(struct mtd_info *mtd,
682 const u_char *buf, int len)
683{
684 struct nand_chip *nand_chip = mtd->priv;
685 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200686 u16 col = host->buf_start;
687 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200688
Sascha Hauerf8f96082009-06-04 17:12:26 +0200689 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200690
Sascha Hauerf8f96082009-06-04 17:12:26 +0200691 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200692
Sascha Hauerf8f96082009-06-04 17:12:26 +0200693 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200694}
695
696/* Read the data buffer from the NAND Flash. To read the data from NAND
697 * Flash first the data output cycle is initiated by the NFC, which copies
698 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
699 */
700static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
701{
702 struct nand_chip *nand_chip = mtd->priv;
703 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200704 u16 col = host->buf_start;
705 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200706
Sascha Hauerf8f96082009-06-04 17:12:26 +0200707 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200708
Baruch Siach5d9d9932011-03-02 16:47:55 +0200709 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200710
Baruch Siach5d9d9932011-03-02 16:47:55 +0200711 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200712}
713
714/* Used by the upper layer to verify the data in NAND Flash
715 * with the data in the buf. */
716static int mxc_nand_verify_buf(struct mtd_info *mtd,
717 const u_char *buf, int len)
718{
719 return -EFAULT;
720}
721
722/* This function is used by upper layer for select and
723 * deselect of the NAND chip */
724static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
725{
726 struct nand_chip *nand_chip = mtd->priv;
727 struct mxc_nand_host *host = nand_chip->priv;
728
Baruch Siachd178e3e2011-03-14 09:01:56 +0200729 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200730 /* Disable the NFC clock */
731 if (host->clk_act) {
732 clk_disable(host->clk);
733 host->clk_act = 0;
734 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200735 return;
736 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200737
Baruch Siachd178e3e2011-03-14 09:01:56 +0200738 if (!host->clk_act) {
739 /* Enable the NFC clock */
740 clk_enable(host->clk);
741 host->clk_act = 1;
742 }
743
744 if (nfc_is_v21()) {
745 host->active_cs = chip;
746 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200747 }
748}
749
Sascha Hauerf8f96082009-06-04 17:12:26 +0200750/*
751 * Function to transfer data to/from spare area.
752 */
753static void copy_spare(struct mtd_info *mtd, bool bfrom)
754{
755 struct nand_chip *this = mtd->priv;
756 struct mxc_nand_host *host = this->priv;
757 u16 i, j;
758 u16 n = mtd->writesize >> 9;
759 u8 *d = host->data_buf + mtd->writesize;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200760 u8 *s = host->spare0;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200761 u16 t = host->spare_len;
762
763 j = (mtd->oobsize / n >> 1) << 1;
764
765 if (bfrom) {
766 for (i = 0; i < n - 1; i++)
767 memcpy(d + i * j, s + i * t, j);
768
769 /* the last section */
770 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
771 } else {
772 for (i = 0; i < n - 1; i++)
773 memcpy(&s[i * t], &d[i * j], j);
774
775 /* the last section */
776 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
777 }
778}
779
Sascha Hauera3e65b62009-06-02 11:47:59 +0200780static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200781{
782 struct nand_chip *nand_chip = mtd->priv;
783 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200784
785 /* Write out column address, if necessary */
786 if (column != -1) {
787 /*
788 * MXC NANDFC can only perform full page+spare or
789 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100790 * perform a read/write buf operation, the saved column
791 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200792 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200793 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200794 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200795 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200796 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200797 }
798
799 /* Write out page address, if necessary */
800 if (page_addr != -1) {
801 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200802 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200803
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200804 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400805 if (mtd->size >= 0x10000000) {
806 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200807 host->devtype_data->send_addr(host,
808 (page_addr >> 8) & 0xff,
809 false);
810 host->devtype_data->send_addr(host,
811 (page_addr >> 16) & 0xff,
812 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400813 } else
814 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200815 host->devtype_data->send_addr(host,
816 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200817 } else {
818 /* One more address cycle for higher density devices */
819 if (mtd->size >= 0x4000000) {
820 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200821 host->devtype_data->send_addr(host,
822 (page_addr >> 8) & 0xff,
823 false);
824 host->devtype_data->send_addr(host,
825 (page_addr >> 16) & 0xff,
826 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200827 } else
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, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200831 }
832 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200833}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200834
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200835/*
836 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
837 * on how much oob the nand chip has. For 8bit ecc we need at least
838 * 26 bytes of oob data per 512 byte block.
839 */
840static int get_eccsize(struct mtd_info *mtd)
841{
842 int oobbytes_per_512 = 0;
843
844 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
845
846 if (oobbytes_per_512 < 26)
847 return 4;
848 else
849 return 8;
850}
851
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200852static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200853{
854 struct nand_chip *nand_chip = mtd->priv;
855 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200856 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200857
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200858 if (nand_chip->ecc.mode == NAND_ECC_HW)
859 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
860
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200861 if (!host->irqpending_quirk)
862 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
863
864 host->eccsize = 1;
865
866 writew(config1, NFC_V1_V2_CONFIG1);
867 /* preset operation */
868
869 /* Unlock the internal RAM Buffer */
870 writew(0x2, NFC_V1_V2_CONFIG);
871
872 /* Blocks to be unlocked */
873 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
874 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
875
876 /* Unlock Block Command for given address range */
877 writew(0x4, NFC_V1_V2_WRPROT);
878}
879
880static void preset_v2(struct mtd_info *mtd)
881{
882 struct nand_chip *nand_chip = mtd->priv;
883 struct mxc_nand_host *host = nand_chip->priv;
884 uint16_t config1 = 0;
885
886 if (nand_chip->ecc.mode == NAND_ECC_HW)
887 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
888
889 config1 |= NFC_V2_CONFIG1_FP_INT;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200890
Uwe Kleine-König85569582012-04-23 11:23:34 +0200891 if (!host->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200892 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200893
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200894 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200895 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
896
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200897 host->eccsize = get_eccsize(mtd);
898 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200899 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
900
901 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200902 } else {
903 host->eccsize = 1;
904 }
905
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200906 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200907 /* preset operation */
908
909 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200910 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200911
912 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200913 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
914 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
915 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
916 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
917 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
918 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
919 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
920 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200921
922 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200923 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200924}
925
Sascha Hauer71ec5152010-08-06 15:53:11 +0200926static void preset_v3(struct mtd_info *mtd)
927{
928 struct nand_chip *chip = mtd->priv;
929 struct mxc_nand_host *host = chip->priv;
930 uint32_t config2, config3;
931 int i, addr_phases;
932
933 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
934 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
935
936 /* Unlock the internal RAM Buffer */
937 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
938 NFC_V3_WRPROT);
939
940 /* Blocks to be unlocked */
941 for (i = 0; i < NAND_MAX_CHIPS; i++)
942 writel(0x0 | (0xffff << 16),
943 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
944
945 writel(0, NFC_V3_IPC);
946
947 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
948 NFC_V3_CONFIG2_2CMD_PHASES |
949 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
950 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +0200951 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +0200952 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
953
954 if (chip->ecc.mode == NAND_ECC_HW)
955 config2 |= NFC_V3_CONFIG2_ECC_EN;
956
957 addr_phases = fls(chip->pagemask) >> 3;
958
959 if (mtd->writesize == 2048) {
960 config2 |= NFC_V3_CONFIG2_PS_2048;
961 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
962 } else if (mtd->writesize == 4096) {
963 config2 |= NFC_V3_CONFIG2_PS_4096;
964 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
965 } else {
966 config2 |= NFC_V3_CONFIG2_PS_512;
967 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
968 }
969
970 if (mtd->writesize) {
971 config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
972 host->eccsize = get_eccsize(mtd);
973 if (host->eccsize == 8)
974 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
975 }
976
977 writel(config2, NFC_V3_CONFIG2);
978
979 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
980 NFC_V3_CONFIG3_NO_SDMA |
981 NFC_V3_CONFIG3_RBB_MODE |
982 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
983 NFC_V3_CONFIG3_ADD_OP(0);
984
985 if (!(chip->options & NAND_BUSWIDTH_16))
986 config3 |= NFC_V3_CONFIG3_FW8;
987
988 writel(config3, NFC_V3_CONFIG3);
989
990 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200991}
992
Sascha Hauer34f6e152008-09-02 17:16:59 +0200993/* Used by the upper layer to write command to NAND Flash for
994 * different operations to be carried out on NAND Flash */
995static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
996 int column, int page_addr)
997{
998 struct nand_chip *nand_chip = mtd->priv;
999 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001000
Brian Norris289c0522011-07-19 10:06:09 -07001001 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001002 command, column, page_addr);
1003
1004 /* Reset command state information */
1005 host->status_request = false;
1006
1007 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001008 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001009 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001010 host->devtype_data->preset(mtd);
1011 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001012 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001013
Sascha Hauer34f6e152008-09-02 17:16:59 +02001014 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001015 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001016 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001017
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001018 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001019 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001020 break;
1021
Sascha Hauer34f6e152008-09-02 17:16:59 +02001022 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001023 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001024 if (command == NAND_CMD_READ0)
1025 host->buf_start = column;
1026 else
1027 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001028
Sascha Hauer5ea32022010-04-27 15:24:01 +02001029 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001030
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001031 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001032 mxc_do_addr_cycle(mtd, column, page_addr);
1033
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001034 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001035 host->devtype_data->send_cmd(host,
1036 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001037
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001038 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001039
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001040 memcpy(host->data_buf, host->main_area0, mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001041 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001042 break;
1043
Sascha Hauer34f6e152008-09-02 17:16:59 +02001044 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001045 if (column >= mtd->writesize)
1046 /* call ourself to read a page */
1047 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001048
Sascha Hauer5ea32022010-04-27 15:24:01 +02001049 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001050
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001051 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001052 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001053 break;
1054
1055 case NAND_CMD_PAGEPROG:
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001056 memcpy(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001057 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001058 host->devtype_data->send_page(mtd, NFC_INPUT);
1059 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001060 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001061 break;
1062
Sascha Hauer34f6e152008-09-02 17:16:59 +02001063 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001064 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001065 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001066 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001067 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001068 break;
1069
Sascha Hauer89121a62009-06-04 17:18:01 +02001070 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001071 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001072 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001073 mxc_do_addr_cycle(mtd, column, page_addr);
1074
Sascha Hauer34f6e152008-09-02 17:16:59 +02001075 break;
1076 }
1077}
1078
Sascha Hauerf1372052009-10-21 14:25:27 +02001079/*
1080 * The generic flash bbt decriptors overlap with our ecc
1081 * hardware, so define some i.MX specific ones.
1082 */
1083static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1084static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1085
1086static struct nand_bbt_descr bbt_main_descr = {
1087 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1088 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1089 .offs = 0,
1090 .len = 4,
1091 .veroffs = 4,
1092 .maxblocks = 4,
1093 .pattern = bbt_pattern,
1094};
1095
1096static struct nand_bbt_descr bbt_mirror_descr = {
1097 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1098 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1099 .offs = 0,
1100 .len = 4,
1101 .veroffs = 4,
1102 .maxblocks = 4,
1103 .pattern = mirror_pattern,
1104};
1105
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001106/* v1: i.MX21, i.MX27, i.MX31 */
1107static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001108 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001109 .send_cmd = send_cmd_v1_v2,
1110 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001111 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001112 .send_read_id = send_read_id_v1_v2,
1113 .get_dev_status = get_dev_status_v1_v2,
1114 .check_int = check_int_v1_v2,
1115 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001116 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001117 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1118 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1119 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001120};
1121
1122/* v21: i.MX25, i.MX35 */
1123static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001124 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001125 .send_cmd = send_cmd_v1_v2,
1126 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001127 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001128 .send_read_id = send_read_id_v1_v2,
1129 .get_dev_status = get_dev_status_v1_v2,
1130 .check_int = check_int_v1_v2,
1131 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001132 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001133 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1134 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1135 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001136};
1137
1138/* v3: i.MX51, i.MX53 */
1139static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1140 .preset = preset_v3,
1141 .send_cmd = send_cmd_v3,
1142 .send_addr = send_addr_v3,
1143 .send_page = send_page_v3,
1144 .send_read_id = send_read_id_v3,
1145 .get_dev_status = get_dev_status_v3,
1146 .check_int = check_int_v3,
1147 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001148 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001149 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1150 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1151 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001152};
1153
Sascha Hauer34f6e152008-09-02 17:16:59 +02001154static int __init mxcnd_probe(struct platform_device *pdev)
1155{
1156 struct nand_chip *this;
1157 struct mtd_info *mtd;
1158 struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
1159 struct mxc_nand_host *host;
1160 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001161 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001162
1163 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +02001164 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
1165 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001166 if (!host)
1167 return -ENOMEM;
1168
Sascha Hauerf8f96082009-06-04 17:12:26 +02001169 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001170
Sascha Hauer34f6e152008-09-02 17:16:59 +02001171 host->dev = &pdev->dev;
1172 /* structures must be linked */
1173 this = &host->nand;
1174 mtd = &host->mtd;
1175 mtd->priv = this;
1176 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001177 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001178 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001179
1180 /* 50 us command delay time */
1181 this->chip_delay = 5;
1182
1183 this->priv = host;
1184 this->dev_ready = mxc_nand_dev_ready;
1185 this->cmdfunc = mxc_nand_command;
1186 this->select_chip = mxc_nand_select_chip;
1187 this->read_byte = mxc_nand_read_byte;
1188 this->read_word = mxc_nand_read_word;
1189 this->write_buf = mxc_nand_write_buf;
1190 this->read_buf = mxc_nand_read_buf;
1191 this->verify_buf = mxc_nand_verify_buf;
1192
Sascha Hauere65fb002009-02-16 14:29:10 +01001193 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +04001194 if (IS_ERR(host->clk)) {
1195 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001196 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +04001197 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001198
1199 clk_enable(host->clk);
1200 host->clk_act = 1;
1201
1202 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1203 if (!res) {
1204 err = -ENODEV;
1205 goto eres;
1206 }
1207
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001208 host->base = ioremap(res->start, resource_size(res));
1209 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +04001210 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001211 goto eres;
1212 }
1213
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001214 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001215
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001216 if (nfc_is_v1()) {
1217 host->devtype_data = &imx21_nand_devtype_data;
Sascha Hauer63f14742010-10-18 10:16:26 +02001218 if (cpu_is_mx21())
Uwe Kleine-König85569582012-04-23 11:23:34 +02001219 host->irqpending_quirk = 1;
Sascha Hauer938cf992010-08-06 15:53:04 +02001220 host->regs = host->base + 0xe00;
Sascha Hauer94671142009-10-05 12:14:21 +02001221 host->spare0 = host->base + 0x800;
1222 host->spare_len = 16;
Sascha Hauer94671142009-10-05 12:14:21 +02001223 this->ecc.bytes = 3;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001224 host->eccsize = 1;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001225 } else if (nfc_is_v21()) {
1226 host->devtype_data = &imx25_nand_devtype_data;
1227 host->regs = host->base + 0x1e00;
1228 host->spare0 = host->base + 0x1000;
1229 host->spare_len = 64;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001230 this->ecc.bytes = 9;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001231 } else if (nfc_is_v3_2()) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001232 host->devtype_data = &imx51_nand_devtype_data;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001233 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1234 if (!res) {
1235 err = -ENODEV;
1236 goto eirq;
1237 }
1238 host->regs_ip = ioremap(res->start, resource_size(res));
1239 if (!host->regs_ip) {
1240 err = -ENOMEM;
1241 goto eirq;
1242 }
1243 host->regs_axi = host->base + 0x1e00;
1244 host->spare0 = host->base + 0x1000;
1245 host->spare_len = 64;
Sascha Hauer94671142009-10-05 12:14:21 +02001246 } else
1247 BUG();
Sascha Hauer34f6e152008-09-02 17:16:59 +02001248
Sascha Hauer13e1add2009-10-21 10:39:05 +02001249 this->ecc.size = 512;
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001250 this->ecc.layout = host->devtype_data->ecclayout_512;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001251
1252 if (pdata->hw_ecc) {
1253 this->ecc.calculate = mxc_nand_calculate_ecc;
1254 this->ecc.hwctl = mxc_nand_enable_hwecc;
Sascha Hauer94f77e52010-08-06 15:53:09 +02001255 if (nfc_is_v1())
1256 this->ecc.correct = mxc_nand_correct_data_v1;
1257 else
1258 this->ecc.correct = mxc_nand_correct_data_v2_v3;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001259 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001260 } else {
1261 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001262 }
1263
Sascha Hauer34f6e152008-09-02 17:16:59 +02001264 /* NAND bus width determines access funtions used by upper layer */
Sascha Hauer13e1add2009-10-21 10:39:05 +02001265 if (pdata->width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001266 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001267
Sascha Hauerf1372052009-10-21 14:25:27 +02001268 if (pdata->flash_bbt) {
1269 this->bbt_td = &bbt_main_descr;
1270 this->bbt_md = &bbt_mirror_descr;
1271 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001272 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001273 }
1274
Sascha Hauer63f14742010-10-18 10:16:26 +02001275 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001276
1277 host->irq = platform_get_irq(pdev, 0);
1278
Sascha Hauer63f14742010-10-18 10:16:26 +02001279 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001280 * Use host->devtype_data->irq_control() here instead of irq_control()
1281 * because we must not disable_irq_nosync without having requested the
1282 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001283 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001284 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001285
Ivo Claryssea47bfd22010-04-08 16:16:51 +02001286 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001287 if (err)
1288 goto eirq;
1289
Sascha Hauer63f14742010-10-18 10:16:26 +02001290 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001291 * Now that we "own" the interrupt make sure the interrupt mask bit is
1292 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1293 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001294 */
Uwe Kleine-König85569582012-04-23 11:23:34 +02001295 if (host->irqpending_quirk) {
1296 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001297 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001298 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001299
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001300 /* first scan to find the device and get the page size */
Baruch Siachd178e3e2011-03-14 09:01:56 +02001301 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001302 err = -ENXIO;
1303 goto escan;
1304 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001305
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001306 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001307 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001308
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001309 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001310 this->ecc.layout = host->devtype_data->ecclayout_2k;
1311 else if (mtd->writesize == 4096)
1312 this->ecc.layout = host->devtype_data->ecclayout_4k;
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001313
1314 /* second phase scan */
1315 if (nand_scan_tail(mtd)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +02001316 err = -ENXIO;
1317 goto escan;
1318 }
1319
Mike Dunn6a918ba2012-03-11 14:21:11 -07001320 if (this->ecc.mode == NAND_ECC_HW) {
1321 if (nfc_is_v1())
1322 this->ecc.strength = 1;
1323 else
1324 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1325 }
1326
Sascha Hauer34f6e152008-09-02 17:16:59 +02001327 /* Register the partitions */
Artem Bityutskiy42d7fbe2012-03-09 19:24:26 +02001328 mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts,
1329 pdata->nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001330
1331 platform_set_drvdata(pdev, host);
1332
1333 return 0;
1334
1335escan:
Magnus Liljab258fd82009-05-08 21:57:47 +02001336 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001337eirq:
Sascha Hauer71ec5152010-08-06 15:53:11 +02001338 if (host->regs_ip)
1339 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001340 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001341eres:
1342 clk_put(host->clk);
1343eclk:
1344 kfree(host);
1345
1346 return err;
1347}
1348
Uwe Kleine-König51eeb872009-12-07 09:44:05 +00001349static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001350{
1351 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1352
1353 clk_put(host->clk);
1354
1355 platform_set_drvdata(pdev, NULL);
1356
1357 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +02001358 free_irq(host->irq, host);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001359 if (host->regs_ip)
1360 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001361 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001362 kfree(host);
1363
1364 return 0;
1365}
1366
Sascha Hauer34f6e152008-09-02 17:16:59 +02001367static struct platform_driver mxcnd_driver = {
1368 .driver = {
1369 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001370 .owner = THIS_MODULE,
Eric Bénard04dd0d32010-06-17 20:59:04 +02001371 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +01001372 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +02001373};
1374
1375static int __init mxc_nd_init(void)
1376{
Vladimir Barinov8541c112009-04-23 15:47:22 +04001377 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001378}
1379
1380static void __exit mxc_nd_cleanup(void)
1381{
1382 /* Unregister the device structure */
1383 platform_driver_unregister(&mxcnd_driver);
1384}
1385
1386module_init(mxc_nd_init);
1387module_exit(mxc_nd_cleanup);
1388
1389MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1390MODULE_DESCRIPTION("MXC NAND MTD driver");
1391MODULE_LICENSE("GPL");