blob: 9f10778a65243f6e8580051cd849e2c9cc144e32 [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>
Uwe Kleine-König64363562012-04-23 11:23:41 +020035#include <linux/of_device.h>
36#include <linux/of_mtd.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020037
38#include <asm/mach/flash.h>
Arnd Bergmann82906b12012-08-24 15:14:29 +020039#include <linux/platform_data/mtd-mxc_nand.h>
Sascha Hauer94671142009-10-05 12:14:21 +020040#include <mach/hardware.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020041
42#define DRIVER_NAME "mxc_nand"
43
Sascha Hauer94671142009-10-05 12:14:21 +020044#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
Ivo Claryssea47bfd22010-04-08 16:16:51 +020045#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
Sascha Hauer71718a8e2012-06-06 12:33:15 +020046#define nfc_is_v3_2a() cpu_is_mx51()
47#define nfc_is_v3_2b() cpu_is_mx53()
Sascha Hauer94671142009-10-05 12:14:21 +020048
Sascha Hauer34f6e152008-09-02 17:16:59 +020049/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020050#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
51#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
52#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
53#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
54#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
55#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
56#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
57#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
58#define NFC_V1_V2_WRPROT (host->regs + 0x12)
59#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
60#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
Baruch Siachd178e3e2011-03-14 09:01:56 +020061#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
62#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
63#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
64#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
65#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
66#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
67#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
68#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
Sascha Hauer1bc99182010-08-06 15:53:08 +020069#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
70#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
71#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020072
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020073#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020074#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
75#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
76#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
77#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
78#define NFC_V1_V2_CONFIG1_RST (1 << 6)
79#define NFC_V1_V2_CONFIG1_CE (1 << 7)
Sascha Hauerb8db2f52010-08-09 15:04:19 +020080#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
81#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
82#define NFC_V2_CONFIG1_FP_INT (1 << 11)
Sascha Hauer34f6e152008-09-02 17:16:59 +020083
Sascha Hauer1bc99182010-08-06 15:53:08 +020084#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020085
Sascha Hauer1bc99182010-08-06 15:53:08 +020086/*
87 * Operation modes for the NFC. Valid for v1, v2 and v3
88 * type controllers.
89 */
90#define NFC_CMD (1 << 0)
91#define NFC_ADDR (1 << 1)
92#define NFC_INPUT (1 << 2)
93#define NFC_OUTPUT (1 << 3)
94#define NFC_ID (1 << 4)
95#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020096
Sascha Hauer71ec5152010-08-06 15:53:11 +020097#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
98#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
Sascha Hauer34f6e152008-09-02 17:16:59 +020099
Sascha Hauer71ec5152010-08-06 15:53:11 +0200100#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
101#define NFC_V3_CONFIG1_SP_EN (1 << 0)
102#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200103
Sascha Hauer71ec5152010-08-06 15:53:11 +0200104#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200105
Sascha Hauer71ec5152010-08-06 15:53:11 +0200106#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200107
Sascha Hauer71ec5152010-08-06 15:53:11 +0200108#define NFC_V3_WRPROT (host->regs_ip + 0x0)
109#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
110#define NFC_V3_WRPROT_LOCK (1 << 1)
111#define NFC_V3_WRPROT_UNLOCK (1 << 2)
112#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
113
114#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
115
116#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
117#define NFC_V3_CONFIG2_PS_512 (0 << 0)
118#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
119#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
120#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
121#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
122#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
123#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
124#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200125#define NFC_V3_CONFIG2_PPB(x, shift) (((x) & 0x3) << shift)
Sascha Hauer71ec5152010-08-06 15:53:11 +0200126#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
127#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
128#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
129#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
130
131#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
132#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
133#define NFC_V3_CONFIG3_FW8 (1 << 3)
134#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
135#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
136#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
137#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
138
139#define NFC_V3_IPC (host->regs_ip + 0x2C)
140#define NFC_V3_IPC_CREQ (1 << 0)
141#define NFC_V3_IPC_INT (1 << 31)
142
143#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200144
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200145struct mxc_nand_host;
146
147struct mxc_nand_devtype_data {
148 void (*preset)(struct mtd_info *);
149 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
150 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
151 void (*send_page)(struct mtd_info *, unsigned int);
152 void (*send_read_id)(struct mxc_nand_host *);
153 uint16_t (*get_dev_status)(struct mxc_nand_host *);
154 int (*check_int)(struct mxc_nand_host *);
155 void (*irq_control)(struct mxc_nand_host *, int);
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200156 u32 (*get_ecc_status)(struct mxc_nand_host *);
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +0200157 struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k;
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200158 void (*select_chip)(struct mtd_info *mtd, int chip);
Uwe Kleine-König69d023b2012-04-23 11:23:39 +0200159 int (*correct_data)(struct mtd_info *mtd, u_char *dat,
160 u_char *read_ecc, u_char *calc_ecc);
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200161
162 /*
163 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
164 * (CONFIG1:INT_MSK is set). To handle this the driver uses
165 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
166 */
167 int irqpending_quirk;
168 int needs_ip;
169
170 size_t regs_offset;
171 size_t spare0_offset;
172 size_t axi_offset;
173
174 int spare_len;
175 int eccbytes;
176 int eccsize;
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200177 int ppb_shift;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200178};
179
Sascha Hauer34f6e152008-09-02 17:16:59 +0200180struct mxc_nand_host {
181 struct mtd_info mtd;
182 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200183 struct device *dev;
184
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200185 void __iomem *spare0;
186 void __iomem *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200187
188 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200189 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200190 void __iomem *regs_axi;
191 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200192 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200193 struct clk *clk;
194 int clk_act;
195 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200196 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200197 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200198
Sascha Hauer63f14742010-10-18 10:16:26 +0200199 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200200
201 uint8_t *data_buf;
202 unsigned int buf_start;
Sascha Hauer5f973042010-08-06 15:53:06 +0200203
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200204 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König64363562012-04-23 11:23:41 +0200205 struct mxc_nand_platform_data pdata;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200206};
207
Sascha Hauer34f6e152008-09-02 17:16:59 +0200208/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200209static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200210 .eccbytes = 5,
211 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200212 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200213};
214
Sascha Hauer94671142009-10-05 12:14:21 +0200215static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400216 .eccbytes = 20,
217 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
218 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
219 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200220};
221
Sascha Hauer94671142009-10-05 12:14:21 +0200222/* OOB description for 512 byte pages with 16 byte OOB */
223static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
224 .eccbytes = 1 * 9,
225 .eccpos = {
226 7, 8, 9, 10, 11, 12, 13, 14, 15
227 },
228 .oobfree = {
229 {.offset = 0, .length = 5}
230 }
231};
232
233/* OOB description for 2048 byte pages with 64 byte OOB */
234static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
235 .eccbytes = 4 * 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 },
242 .oobfree = {
243 {.offset = 2, .length = 4},
244 {.offset = 16, .length = 7},
245 {.offset = 32, .length = 7},
246 {.offset = 48, .length = 7}
247 }
248};
249
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200250/* OOB description for 4096 byte pages with 128 byte OOB */
251static struct nand_ecclayout nandv2_hw_eccoob_4k = {
252 .eccbytes = 8 * 9,
253 .eccpos = {
254 7, 8, 9, 10, 11, 12, 13, 14, 15,
255 23, 24, 25, 26, 27, 28, 29, 30, 31,
256 39, 40, 41, 42, 43, 44, 45, 46, 47,
257 55, 56, 57, 58, 59, 60, 61, 62, 63,
258 71, 72, 73, 74, 75, 76, 77, 78, 79,
259 87, 88, 89, 90, 91, 92, 93, 94, 95,
260 103, 104, 105, 106, 107, 108, 109, 110, 111,
261 119, 120, 121, 122, 123, 124, 125, 126, 127,
262 },
263 .oobfree = {
264 {.offset = 2, .length = 4},
265 {.offset = 16, .length = 7},
266 {.offset = 32, .length = 7},
267 {.offset = 48, .length = 7},
268 {.offset = 64, .length = 7},
269 {.offset = 80, .length = 7},
270 {.offset = 96, .length = 7},
271 {.offset = 112, .length = 7},
272 }
273};
274
Lothar Waßmann740bb0c2012-12-06 08:42:28 +0100275static const char const *part_probes[] = {
276 "cmdlinepart", "RedBoot", "ofpart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200277
Sascha Hauer096bcc22012-05-29 10:16:09 +0200278static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
279{
280 int i;
281 u32 *t = trg;
282 const __iomem u32 *s = src;
283
284 for (i = 0; i < (size >> 2); i++)
285 *t++ = __raw_readl(s++);
286}
287
288static void memcpy32_toio(void __iomem *trg, const void *src, int size)
289{
290 int i;
291 u32 __iomem *t = trg;
292 const u32 *s = src;
293
294 for (i = 0; i < (size >> 2); i++)
295 __raw_writel(*s++, t++);
296}
297
Sascha Hauer71ec5152010-08-06 15:53:11 +0200298static int check_int_v3(struct mxc_nand_host *host)
299{
300 uint32_t tmp;
301
302 tmp = readl(NFC_V3_IPC);
303 if (!(tmp & NFC_V3_IPC_INT))
304 return 0;
305
306 tmp &= ~NFC_V3_IPC_INT;
307 writel(tmp, NFC_V3_IPC);
308
309 return 1;
310}
311
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200312static int check_int_v1_v2(struct mxc_nand_host *host)
313{
314 uint32_t tmp;
315
Sascha Hauer1bc99182010-08-06 15:53:08 +0200316 tmp = readw(NFC_V1_V2_CONFIG2);
317 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200318 return 0;
319
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200320 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200321 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200322
323 return 1;
324}
325
Sascha Hauer63f14742010-10-18 10:16:26 +0200326static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
327{
328 uint16_t tmp;
329
330 tmp = readw(NFC_V1_V2_CONFIG1);
331
332 if (activate)
333 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
334 else
335 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
336
337 writew(tmp, NFC_V1_V2_CONFIG1);
338}
339
340static void irq_control_v3(struct mxc_nand_host *host, int activate)
341{
342 uint32_t tmp;
343
344 tmp = readl(NFC_V3_CONFIG2);
345
346 if (activate)
347 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
348 else
349 tmp |= NFC_V3_CONFIG2_INT_MSK;
350
351 writel(tmp, NFC_V3_CONFIG2);
352}
353
Uwe Kleine-König85569582012-04-23 11:23:34 +0200354static void irq_control(struct mxc_nand_host *host, int activate)
355{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200356 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200357 if (activate)
358 enable_irq(host->irq);
359 else
360 disable_irq_nosync(host->irq);
361 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200362 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200363 }
364}
365
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200366static u32 get_ecc_status_v1(struct mxc_nand_host *host)
367{
368 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
369}
370
371static u32 get_ecc_status_v2(struct mxc_nand_host *host)
372{
373 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
374}
375
376static u32 get_ecc_status_v3(struct mxc_nand_host *host)
377{
378 return readl(NFC_V3_ECC_STATUS_RESULT);
379}
380
Uwe Kleine-König85569582012-04-23 11:23:34 +0200381static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
382{
383 struct mxc_nand_host *host = dev_id;
384
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200385 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200386 return IRQ_NONE;
387
388 irq_control(host, 0);
389
390 complete(&host->op_completion);
391
392 return IRQ_HANDLED;
393}
394
Sascha Hauer34f6e152008-09-02 17:16:59 +0200395/* This function polls the NANDFC to wait for the basic operation to
396 * complete by checking the INT bit of config2 register.
397 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200398static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200399{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200400 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200401
402 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200403 if (!host->devtype_data->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200404 INIT_COMPLETION(host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200405 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200406 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200407 }
408 } else {
409 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200410 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200411 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200412
Sascha Hauer34f6e152008-09-02 17:16:59 +0200413 udelay(1);
414 }
Roel Kluin43950a62009-06-04 16:24:59 +0200415 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700416 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200417 }
418}
419
Sascha Hauer71ec5152010-08-06 15:53:11 +0200420static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
421{
422 /* fill command */
423 writel(cmd, NFC_V3_FLASH_CMD);
424
425 /* send out command */
426 writel(NFC_CMD, NFC_V3_LAUNCH);
427
428 /* Wait for operation to complete */
429 wait_op_done(host, useirq);
430}
431
Sascha Hauer34f6e152008-09-02 17:16:59 +0200432/* This function issues the specified command to the NAND device and
433 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200434static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200435{
Brian Norris289c0522011-07-19 10:06:09 -0700436 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200437
Sascha Hauer1bc99182010-08-06 15:53:08 +0200438 writew(cmd, NFC_V1_V2_FLASH_CMD);
439 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200440
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200441 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200442 int max_retries = 100;
443 /* Reset completion is indicated by NFC_CONFIG2 */
444 /* being set to 0 */
445 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200446 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200447 break;
448 }
449 udelay(1);
450 }
451 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700452 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200453 } else {
454 /* Wait for operation to complete */
455 wait_op_done(host, useirq);
456 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200457}
458
Sascha Hauer71ec5152010-08-06 15:53:11 +0200459static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
460{
461 /* fill address */
462 writel(addr, NFC_V3_FLASH_ADDR0);
463
464 /* send out address */
465 writel(NFC_ADDR, NFC_V3_LAUNCH);
466
467 wait_op_done(host, 0);
468}
469
Sascha Hauer34f6e152008-09-02 17:16:59 +0200470/* This function sends an address (or partial address) to the
471 * NAND device. The address is used to select the source/destination for
472 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200473static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200474{
Brian Norris289c0522011-07-19 10:06:09 -0700475 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200476
Sascha Hauer1bc99182010-08-06 15:53:08 +0200477 writew(addr, NFC_V1_V2_FLASH_ADDR);
478 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200479
480 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200481 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200482}
483
Sascha Hauer71ec5152010-08-06 15:53:11 +0200484static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
485{
486 struct nand_chip *nand_chip = mtd->priv;
487 struct mxc_nand_host *host = nand_chip->priv;
488 uint32_t tmp;
489
490 tmp = readl(NFC_V3_CONFIG1);
491 tmp &= ~(7 << 4);
492 writel(tmp, NFC_V3_CONFIG1);
493
494 /* transfer data from NFC ram to nand */
495 writel(ops, NFC_V3_LAUNCH);
496
497 wait_op_done(host, false);
498}
499
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200500static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
501{
502 struct nand_chip *nand_chip = mtd->priv;
503 struct mxc_nand_host *host = nand_chip->priv;
504
505 /* NANDFC buffer 0 is used for page read/write */
506 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
507
508 writew(ops, NFC_V1_V2_CONFIG2);
509
510 /* Wait for operation to complete */
511 wait_op_done(host, true);
512}
513
514static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200515{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200516 struct nand_chip *nand_chip = mtd->priv;
517 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200518 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200519
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200520 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200521 bufs = 4;
522 else
523 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200524
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200525 for (i = 0; i < bufs; i++) {
526
527 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200528 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200529
Sascha Hauer1bc99182010-08-06 15:53:08 +0200530 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200531
532 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200533 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200534 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200535}
536
Sascha Hauer71ec5152010-08-06 15:53:11 +0200537static void send_read_id_v3(struct mxc_nand_host *host)
538{
539 /* Read ID into main buffer */
540 writel(NFC_ID, NFC_V3_LAUNCH);
541
542 wait_op_done(host, true);
543
Sascha Hauer096bcc22012-05-29 10:16:09 +0200544 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Sascha Hauer71ec5152010-08-06 15:53:11 +0200545}
546
Sascha Hauer34f6e152008-09-02 17:16:59 +0200547/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200548static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200549{
550 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551
552 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200553 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200554
Sascha Hauer1bc99182010-08-06 15:53:08 +0200555 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200556
557 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200558 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200559
Sascha Hauer096bcc22012-05-29 10:16:09 +0200560 memcpy32_fromio(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200561
562 if (this->options & NAND_BUSWIDTH_16) {
563 /* compress the ID info */
564 host->data_buf[1] = host->data_buf[2];
565 host->data_buf[2] = host->data_buf[4];
566 host->data_buf[3] = host->data_buf[6];
567 host->data_buf[4] = host->data_buf[8];
568 host->data_buf[5] = host->data_buf[10];
569 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200570}
571
Sascha Hauer71ec5152010-08-06 15:53:11 +0200572static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200573{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200574 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200575 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200576
Sascha Hauer71ec5152010-08-06 15:53:11 +0200577 return readl(NFC_V3_CONFIG1) >> 16;
578}
579
Sascha Hauer34f6e152008-09-02 17:16:59 +0200580/* This function requests the NANDFC to perform a read of the
581 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200582static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200583{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200584 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200585 uint32_t store;
586 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200587
Baruch Siachd178e3e2011-03-14 09:01:56 +0200588 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200589
590 /*
591 * The device status is stored in main_area0. To
592 * prevent corruption of the buffer save the value
593 * and restore it afterwards.
594 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200595 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200596
Sascha Hauer1bc99182010-08-06 15:53:08 +0200597 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200598 wait_op_done(host, true);
599
Sascha Hauer34f6e152008-09-02 17:16:59 +0200600 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200601
Sascha Hauer34f6e152008-09-02 17:16:59 +0200602 writel(store, main_buf);
603
604 return ret;
605}
606
607/* This functions is used by upper layer to checks if device is ready */
608static int mxc_nand_dev_ready(struct mtd_info *mtd)
609{
610 /*
611 * NFC handles R/B internally. Therefore, this function
612 * always returns status as ready.
613 */
614 return 1;
615}
616
617static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
618{
619 /*
620 * If HW ECC is enabled, we turn it on during init. There is
621 * no need to enable again here.
622 */
623}
624
Sascha Hauer94f77e52010-08-06 15:53:09 +0200625static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200626 u_char *read_ecc, u_char *calc_ecc)
627{
628 struct nand_chip *nand_chip = mtd->priv;
629 struct mxc_nand_host *host = nand_chip->priv;
630
631 /*
632 * 1-Bit errors are automatically corrected in HW. No need for
633 * additional correction. 2-Bit errors cannot be corrected by
634 * HW ECC, so we need to return failure
635 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200636 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200637
638 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700639 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200640 return -1;
641 }
642
643 return 0;
644}
645
Sascha Hauer94f77e52010-08-06 15:53:09 +0200646static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
647 u_char *read_ecc, u_char *calc_ecc)
648{
649 struct nand_chip *nand_chip = mtd->priv;
650 struct mxc_nand_host *host = nand_chip->priv;
651 u32 ecc_stat, err;
652 int no_subpages = 1;
653 int ret = 0;
654 u8 ecc_bit_mask, err_limit;
655
656 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
657 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
658
659 no_subpages = mtd->writesize >> 9;
660
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200661 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200662
663 do {
664 err = ecc_stat & ecc_bit_mask;
665 if (err > err_limit) {
666 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
667 return -1;
668 } else {
669 ret += err;
670 }
671 ecc_stat >>= 4;
672 } while (--no_subpages);
673
674 mtd->ecc_stats.corrected += ret;
675 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
676
677 return ret;
678}
679
Sascha Hauer34f6e152008-09-02 17:16:59 +0200680static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
681 u_char *ecc_code)
682{
683 return 0;
684}
685
686static u_char mxc_nand_read_byte(struct mtd_info *mtd)
687{
688 struct nand_chip *nand_chip = mtd->priv;
689 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200690 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200691
692 /* Check for status request */
693 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200694 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200695
Sascha Hauerf8f96082009-06-04 17:12:26 +0200696 ret = *(uint8_t *)(host->data_buf + host->buf_start);
697 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200698
699 return ret;
700}
701
702static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
703{
704 struct nand_chip *nand_chip = mtd->priv;
705 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200706 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200707
Sascha Hauerf8f96082009-06-04 17:12:26 +0200708 ret = *(uint16_t *)(host->data_buf + host->buf_start);
709 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200710
711 return ret;
712}
713
714/* Write data of length len to buffer buf. The data to be
715 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
716 * Operation by the NFC, the data is written to NAND Flash */
717static void mxc_nand_write_buf(struct mtd_info *mtd,
718 const u_char *buf, int len)
719{
720 struct nand_chip *nand_chip = mtd->priv;
721 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200722 u16 col = host->buf_start;
723 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200724
Sascha Hauerf8f96082009-06-04 17:12:26 +0200725 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200726
Sascha Hauerf8f96082009-06-04 17:12:26 +0200727 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200728
Sascha Hauerf8f96082009-06-04 17:12:26 +0200729 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200730}
731
732/* Read the data buffer from the NAND Flash. To read the data from NAND
733 * Flash first the data output cycle is initiated by the NFC, which copies
734 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
735 */
736static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
737{
738 struct nand_chip *nand_chip = mtd->priv;
739 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200740 u16 col = host->buf_start;
741 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200742
Sascha Hauerf8f96082009-06-04 17:12:26 +0200743 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200744
Baruch Siach5d9d9932011-03-02 16:47:55 +0200745 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200746
Baruch Siach5d9d9932011-03-02 16:47:55 +0200747 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200748}
749
Sascha Hauer34f6e152008-09-02 17:16:59 +0200750/* This function is used by upper layer for select and
751 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200752static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
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;
756
Baruch Siachd178e3e2011-03-14 09:01:56 +0200757 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200758 /* Disable the NFC clock */
759 if (host->clk_act) {
Sascha Hauer97c32132012-03-07 20:56:35 +0100760 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200761 host->clk_act = 0;
762 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200763 return;
764 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200765
Baruch Siachd178e3e2011-03-14 09:01:56 +0200766 if (!host->clk_act) {
767 /* Enable the NFC clock */
Sascha Hauer97c32132012-03-07 20:56:35 +0100768 clk_prepare_enable(host->clk);
Baruch Siachd178e3e2011-03-14 09:01:56 +0200769 host->clk_act = 1;
770 }
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200771}
Baruch Siachd178e3e2011-03-14 09:01:56 +0200772
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200773static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200774{
775 struct nand_chip *nand_chip = mtd->priv;
776 struct mxc_nand_host *host = nand_chip->priv;
777
778 if (chip == -1) {
779 /* Disable the NFC clock */
780 if (host->clk_act) {
Fabio Estevam3d059692012-05-25 20:14:50 -0300781 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200782 host->clk_act = 0;
783 }
784 return;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200785 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200786
787 if (!host->clk_act) {
788 /* Enable the NFC clock */
Fabio Estevam3d059692012-05-25 20:14:50 -0300789 clk_prepare_enable(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200790 host->clk_act = 1;
791 }
792
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200793 host->active_cs = chip;
794 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200795}
796
Sascha Hauerf8f96082009-06-04 17:12:26 +0200797/*
798 * Function to transfer data to/from spare area.
799 */
800static void copy_spare(struct mtd_info *mtd, bool bfrom)
801{
802 struct nand_chip *this = mtd->priv;
803 struct mxc_nand_host *host = this->priv;
804 u16 i, j;
805 u16 n = mtd->writesize >> 9;
806 u8 *d = host->data_buf + mtd->writesize;
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200807 u8 __iomem *s = host->spare0;
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200808 u16 t = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200809
810 j = (mtd->oobsize / n >> 1) << 1;
811
812 if (bfrom) {
813 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200814 memcpy32_fromio(d + i * j, s + i * t, j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200815
816 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200817 memcpy32_fromio(d + i * j, s + i * t, mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200818 } else {
819 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200820 memcpy32_toio(&s[i * t], &d[i * j], j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200821
822 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200823 memcpy32_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200824 }
825}
826
Sascha Hauera3e65b62009-06-02 11:47:59 +0200827static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200828{
829 struct nand_chip *nand_chip = mtd->priv;
830 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200831
832 /* Write out column address, if necessary */
833 if (column != -1) {
834 /*
835 * MXC NANDFC can only perform full page+spare or
836 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100837 * perform a read/write buf operation, the saved column
838 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200839 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200840 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200841 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200842 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200843 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200844 }
845
846 /* Write out page address, if necessary */
847 if (page_addr != -1) {
848 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200849 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200850
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200851 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400852 if (mtd->size >= 0x10000000) {
853 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200854 host->devtype_data->send_addr(host,
855 (page_addr >> 8) & 0xff,
856 false);
857 host->devtype_data->send_addr(host,
858 (page_addr >> 16) & 0xff,
859 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400860 } else
861 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200862 host->devtype_data->send_addr(host,
863 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200864 } else {
865 /* One more address cycle for higher density devices */
866 if (mtd->size >= 0x4000000) {
867 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200868 host->devtype_data->send_addr(host,
869 (page_addr >> 8) & 0xff,
870 false);
871 host->devtype_data->send_addr(host,
872 (page_addr >> 16) & 0xff,
873 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200874 } else
875 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200876 host->devtype_data->send_addr(host,
877 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200878 }
879 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200880}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200881
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200882/*
883 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
884 * on how much oob the nand chip has. For 8bit ecc we need at least
885 * 26 bytes of oob data per 512 byte block.
886 */
887static int get_eccsize(struct mtd_info *mtd)
888{
889 int oobbytes_per_512 = 0;
890
891 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
892
893 if (oobbytes_per_512 < 26)
894 return 4;
895 else
896 return 8;
897}
898
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200899static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200900{
901 struct nand_chip *nand_chip = mtd->priv;
902 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200903 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200904
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200905 if (nand_chip->ecc.mode == NAND_ECC_HW)
906 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
907
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200908 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200909 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200910
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200911 host->eccsize = 1;
912
913 writew(config1, NFC_V1_V2_CONFIG1);
914 /* preset operation */
915
916 /* Unlock the internal RAM Buffer */
917 writew(0x2, NFC_V1_V2_CONFIG);
918
919 /* Blocks to be unlocked */
920 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
921 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
922
923 /* Unlock Block Command for given address range */
924 writew(0x4, NFC_V1_V2_WRPROT);
925}
926
927static void preset_v2(struct mtd_info *mtd)
928{
929 struct nand_chip *nand_chip = mtd->priv;
930 struct mxc_nand_host *host = nand_chip->priv;
931 uint16_t config1 = 0;
932
933 if (nand_chip->ecc.mode == NAND_ECC_HW)
934 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
935
936 config1 |= NFC_V2_CONFIG1_FP_INT;
Ivo Claryssed4840182010-04-08 16:14:44 +0200937
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200938 if (!host->devtype_data->irqpending_quirk)
Ivo Claryssed4840182010-04-08 16:14:44 +0200939 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200940
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200941 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200942 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
943
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200944 host->eccsize = get_eccsize(mtd);
945 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200946 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
947
948 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200949 } else {
950 host->eccsize = 1;
951 }
952
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200953 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200954 /* preset operation */
955
956 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200957 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200958
959 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200960 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
961 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
962 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
963 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
964 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
965 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
966 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
967 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200968
969 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200970 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200971}
972
Sascha Hauer71ec5152010-08-06 15:53:11 +0200973static void preset_v3(struct mtd_info *mtd)
974{
975 struct nand_chip *chip = mtd->priv;
976 struct mxc_nand_host *host = chip->priv;
977 uint32_t config2, config3;
978 int i, addr_phases;
979
980 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
981 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
982
983 /* Unlock the internal RAM Buffer */
984 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
985 NFC_V3_WRPROT);
986
987 /* Blocks to be unlocked */
988 for (i = 0; i < NAND_MAX_CHIPS; i++)
989 writel(0x0 | (0xffff << 16),
990 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
991
992 writel(0, NFC_V3_IPC);
993
994 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
995 NFC_V3_CONFIG2_2CMD_PHASES |
996 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
997 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +0200998 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +0200999 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
1000
1001 if (chip->ecc.mode == NAND_ECC_HW)
1002 config2 |= NFC_V3_CONFIG2_ECC_EN;
1003
1004 addr_phases = fls(chip->pagemask) >> 3;
1005
1006 if (mtd->writesize == 2048) {
1007 config2 |= NFC_V3_CONFIG2_PS_2048;
1008 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1009 } else if (mtd->writesize == 4096) {
1010 config2 |= NFC_V3_CONFIG2_PS_4096;
1011 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1012 } else {
1013 config2 |= NFC_V3_CONFIG2_PS_512;
1014 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1015 }
1016
1017 if (mtd->writesize) {
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001018 config2 |= NFC_V3_CONFIG2_PPB(
1019 ffs(mtd->erasesize / mtd->writesize) - 6,
1020 host->devtype_data->ppb_shift);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001021 host->eccsize = get_eccsize(mtd);
1022 if (host->eccsize == 8)
1023 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
1024 }
1025
1026 writel(config2, NFC_V3_CONFIG2);
1027
1028 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1029 NFC_V3_CONFIG3_NO_SDMA |
1030 NFC_V3_CONFIG3_RBB_MODE |
1031 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1032 NFC_V3_CONFIG3_ADD_OP(0);
1033
1034 if (!(chip->options & NAND_BUSWIDTH_16))
1035 config3 |= NFC_V3_CONFIG3_FW8;
1036
1037 writel(config3, NFC_V3_CONFIG3);
1038
1039 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001040}
1041
Sascha Hauer34f6e152008-09-02 17:16:59 +02001042/* Used by the upper layer to write command to NAND Flash for
1043 * different operations to be carried out on NAND Flash */
1044static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1045 int column, int page_addr)
1046{
1047 struct nand_chip *nand_chip = mtd->priv;
1048 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001049
Brian Norris289c0522011-07-19 10:06:09 -07001050 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001051 command, column, page_addr);
1052
1053 /* Reset command state information */
1054 host->status_request = false;
1055
1056 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001057 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001058 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001059 host->devtype_data->preset(mtd);
1060 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001061 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001062
Sascha Hauer34f6e152008-09-02 17:16:59 +02001063 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001064 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001065 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001066
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001067 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001068 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001069 break;
1070
Sascha Hauer34f6e152008-09-02 17:16:59 +02001071 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001072 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001073 if (command == NAND_CMD_READ0)
1074 host->buf_start = column;
1075 else
1076 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001077
Sascha Hauer5ea32022010-04-27 15:24:01 +02001078 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001079
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001080 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001081 mxc_do_addr_cycle(mtd, column, page_addr);
1082
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001083 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001084 host->devtype_data->send_cmd(host,
1085 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001086
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001087 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001088
Sascha Hauer096bcc22012-05-29 10:16:09 +02001089 memcpy32_fromio(host->data_buf, host->main_area0,
1090 mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001091 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001092 break;
1093
Sascha Hauer34f6e152008-09-02 17:16:59 +02001094 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001095 if (column >= mtd->writesize)
1096 /* call ourself to read a page */
1097 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001098
Sascha Hauer5ea32022010-04-27 15:24:01 +02001099 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001100
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001101 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001102 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001103 break;
1104
1105 case NAND_CMD_PAGEPROG:
Sascha Hauer096bcc22012-05-29 10:16:09 +02001106 memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001107 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001108 host->devtype_data->send_page(mtd, NFC_INPUT);
1109 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001110 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001111 break;
1112
Sascha Hauer34f6e152008-09-02 17:16:59 +02001113 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001114 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001115 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001116 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001117 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001118 break;
1119
Sascha Hauer89121a62009-06-04 17:18:01 +02001120 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001121 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001122 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001123 mxc_do_addr_cycle(mtd, column, page_addr);
1124
Sascha Hauer34f6e152008-09-02 17:16:59 +02001125 break;
1126 }
1127}
1128
Sascha Hauerf1372052009-10-21 14:25:27 +02001129/*
1130 * The generic flash bbt decriptors overlap with our ecc
1131 * hardware, so define some i.MX specific ones.
1132 */
1133static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1134static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1135
1136static struct nand_bbt_descr bbt_main_descr = {
1137 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1138 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1139 .offs = 0,
1140 .len = 4,
1141 .veroffs = 4,
1142 .maxblocks = 4,
1143 .pattern = bbt_pattern,
1144};
1145
1146static struct nand_bbt_descr bbt_mirror_descr = {
1147 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1148 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1149 .offs = 0,
1150 .len = 4,
1151 .veroffs = 4,
1152 .maxblocks = 4,
1153 .pattern = mirror_pattern,
1154};
1155
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001156/* v1 + irqpending_quirk: i.MX21 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001157static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001158 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001159 .send_cmd = send_cmd_v1_v2,
1160 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001161 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001162 .send_read_id = send_read_id_v1_v2,
1163 .get_dev_status = get_dev_status_v1_v2,
1164 .check_int = check_int_v1_v2,
1165 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001166 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001167 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1168 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1169 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001170 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001171 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001172 .irqpending_quirk = 1,
1173 .needs_ip = 0,
1174 .regs_offset = 0xe00,
1175 .spare0_offset = 0x800,
1176 .spare_len = 16,
1177 .eccbytes = 3,
1178 .eccsize = 1,
1179};
1180
1181/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1182static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1183 .preset = preset_v1,
1184 .send_cmd = send_cmd_v1_v2,
1185 .send_addr = send_addr_v1_v2,
1186 .send_page = send_page_v1,
1187 .send_read_id = send_read_id_v1_v2,
1188 .get_dev_status = get_dev_status_v1_v2,
1189 .check_int = check_int_v1_v2,
1190 .irq_control = irq_control_v1_v2,
1191 .get_ecc_status = get_ecc_status_v1,
1192 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1193 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1194 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1195 .select_chip = mxc_nand_select_chip_v1_v3,
1196 .correct_data = mxc_nand_correct_data_v1,
1197 .irqpending_quirk = 0,
1198 .needs_ip = 0,
1199 .regs_offset = 0xe00,
1200 .spare0_offset = 0x800,
1201 .axi_offset = 0,
1202 .spare_len = 16,
1203 .eccbytes = 3,
1204 .eccsize = 1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001205};
1206
1207/* v21: i.MX25, i.MX35 */
1208static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001209 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001210 .send_cmd = send_cmd_v1_v2,
1211 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001212 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001213 .send_read_id = send_read_id_v1_v2,
1214 .get_dev_status = get_dev_status_v1_v2,
1215 .check_int = check_int_v1_v2,
1216 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001217 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001218 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1219 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1220 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001221 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001222 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001223 .irqpending_quirk = 0,
1224 .needs_ip = 0,
1225 .regs_offset = 0x1e00,
1226 .spare0_offset = 0x1000,
1227 .axi_offset = 0,
1228 .spare_len = 64,
1229 .eccbytes = 9,
1230 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001231};
1232
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001233/* v3.2a: i.MX51 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001234static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1235 .preset = preset_v3,
1236 .send_cmd = send_cmd_v3,
1237 .send_addr = send_addr_v3,
1238 .send_page = send_page_v3,
1239 .send_read_id = send_read_id_v3,
1240 .get_dev_status = get_dev_status_v3,
1241 .check_int = check_int_v3,
1242 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001243 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001244 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1245 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1246 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001247 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001248 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001249 .irqpending_quirk = 0,
1250 .needs_ip = 1,
1251 .regs_offset = 0,
1252 .spare0_offset = 0x1000,
1253 .axi_offset = 0x1e00,
1254 .spare_len = 64,
1255 .eccbytes = 0,
1256 .eccsize = 0,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001257 .ppb_shift = 7,
1258};
1259
1260/* v3.2b: i.MX53 */
1261static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
1262 .preset = preset_v3,
1263 .send_cmd = send_cmd_v3,
1264 .send_addr = send_addr_v3,
1265 .send_page = send_page_v3,
1266 .send_read_id = send_read_id_v3,
1267 .get_dev_status = get_dev_status_v3,
1268 .check_int = check_int_v3,
1269 .irq_control = irq_control_v3,
1270 .get_ecc_status = get_ecc_status_v3,
1271 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1272 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1273 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1274 .select_chip = mxc_nand_select_chip_v1_v3,
1275 .correct_data = mxc_nand_correct_data_v2_v3,
1276 .irqpending_quirk = 0,
1277 .needs_ip = 1,
1278 .regs_offset = 0,
1279 .spare0_offset = 0x1000,
1280 .axi_offset = 0x1e00,
1281 .spare_len = 64,
1282 .eccbytes = 0,
1283 .eccsize = 0,
1284 .ppb_shift = 8,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001285};
1286
Uwe Kleine-König64363562012-04-23 11:23:41 +02001287#ifdef CONFIG_OF_MTD
1288static const struct of_device_id mxcnd_dt_ids[] = {
1289 {
1290 .compatible = "fsl,imx21-nand",
1291 .data = &imx21_nand_devtype_data,
1292 }, {
1293 .compatible = "fsl,imx27-nand",
1294 .data = &imx27_nand_devtype_data,
1295 }, {
1296 .compatible = "fsl,imx25-nand",
1297 .data = &imx25_nand_devtype_data,
1298 }, {
1299 .compatible = "fsl,imx51-nand",
1300 .data = &imx51_nand_devtype_data,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001301 }, {
1302 .compatible = "fsl,imx53-nand",
1303 .data = &imx53_nand_devtype_data,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001304 },
1305 { /* sentinel */ }
1306};
1307
1308static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1309{
1310 struct device_node *np = host->dev->of_node;
1311 struct mxc_nand_platform_data *pdata = &host->pdata;
1312 const struct of_device_id *of_id =
1313 of_match_device(mxcnd_dt_ids, host->dev);
1314 int buswidth;
1315
1316 if (!np)
1317 return 1;
1318
1319 if (of_get_nand_ecc_mode(np) >= 0)
1320 pdata->hw_ecc = 1;
1321
1322 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1323
1324 buswidth = of_get_nand_bus_width(np);
1325 if (buswidth < 0)
1326 return buswidth;
1327
1328 pdata->width = buswidth / 8;
1329
1330 host->devtype_data = of_id->data;
1331
1332 return 0;
1333}
1334#else
1335static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1336{
1337 return 1;
1338}
1339#endif
1340
1341static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
1342{
1343 struct mxc_nand_platform_data *pdata = host->dev->platform_data;
1344
1345 if (!pdata)
1346 return -ENODEV;
1347
1348 host->pdata = *pdata;
1349
1350 if (nfc_is_v1()) {
1351 if (cpu_is_mx21())
1352 host->devtype_data = &imx21_nand_devtype_data;
1353 else
1354 host->devtype_data = &imx27_nand_devtype_data;
1355 } else if (nfc_is_v21()) {
1356 host->devtype_data = &imx25_nand_devtype_data;
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001357 } else if (nfc_is_v3_2a()) {
Uwe Kleine-König64363562012-04-23 11:23:41 +02001358 host->devtype_data = &imx51_nand_devtype_data;
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001359 } else if (nfc_is_v3_2b()) {
1360 host->devtype_data = &imx53_nand_devtype_data;
Uwe Kleine-König64363562012-04-23 11:23:41 +02001361 } else
1362 BUG();
1363
1364 return 0;
1365}
1366
Bill Pemberton06f25512012-11-19 13:23:07 -05001367static int mxcnd_probe(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001368{
1369 struct nand_chip *this;
1370 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001371 struct mxc_nand_host *host;
1372 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001373 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001374
1375 /* Allocate memory for MTD device structure and private data */
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001376 host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host) +
1377 NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001378 if (!host)
1379 return -ENOMEM;
1380
Sascha Hauerf8f96082009-06-04 17:12:26 +02001381 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001382
Sascha Hauer34f6e152008-09-02 17:16:59 +02001383 host->dev = &pdev->dev;
1384 /* structures must be linked */
1385 this = &host->nand;
1386 mtd = &host->mtd;
1387 mtd->priv = this;
1388 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001389 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001390 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001391
1392 /* 50 us command delay time */
1393 this->chip_delay = 5;
1394
1395 this->priv = host;
1396 this->dev_ready = mxc_nand_dev_ready;
1397 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001398 this->read_byte = mxc_nand_read_byte;
1399 this->read_word = mxc_nand_read_word;
1400 this->write_buf = mxc_nand_write_buf;
1401 this->read_buf = mxc_nand_read_buf;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001402
Fabio Estevam24b82d32012-09-05 11:52:27 -03001403 host->clk = devm_clk_get(&pdev->dev, NULL);
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001404 if (IS_ERR(host->clk))
1405 return PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001406
Sascha Hauer71885b62012-06-06 12:33:14 +02001407 err = mxcnd_probe_dt(host);
1408 if (err > 0)
1409 err = mxcnd_probe_pdata(host);
1410 if (err < 0)
1411 return err;
1412
1413 if (host->devtype_data->needs_ip) {
1414 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1415 if (!res)
1416 return -ENODEV;
1417 host->regs_ip = devm_request_and_ioremap(&pdev->dev, res);
1418 if (!host->regs_ip)
1419 return -ENOMEM;
1420
1421 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1422 } else {
1423 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1424 }
1425
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001426 if (!res)
1427 return -ENODEV;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001428
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001429 host->base = devm_request_and_ioremap(&pdev->dev, res);
1430 if (!host->base)
1431 return -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001432
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001433 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001434
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001435 if (host->devtype_data->regs_offset)
1436 host->regs = host->base + host->devtype_data->regs_offset;
1437 host->spare0 = host->base + host->devtype_data->spare0_offset;
1438 if (host->devtype_data->axi_offset)
1439 host->regs_axi = host->base + host->devtype_data->axi_offset;
1440
1441 this->ecc.bytes = host->devtype_data->eccbytes;
1442 host->eccsize = host->devtype_data->eccsize;
1443
1444 this->select_chip = host->devtype_data->select_chip;
1445 this->ecc.size = 512;
1446 this->ecc.layout = host->devtype_data->ecclayout_512;
1447
Uwe Kleine-König64363562012-04-23 11:23:41 +02001448 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001449 this->ecc.calculate = mxc_nand_calculate_ecc;
1450 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001451 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001452 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001453 } else {
1454 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001455 }
1456
Uwe Kleine-König64363562012-04-23 11:23:41 +02001457 /* NAND bus width determines access functions used by upper layer */
1458 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001459 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001460
Uwe Kleine-König64363562012-04-23 11:23:41 +02001461 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001462 this->bbt_td = &bbt_main_descr;
1463 this->bbt_md = &bbt_mirror_descr;
1464 /* update flash based bbt */
Brian Norrisbb9ebd4e2011-05-31 16:31:23 -07001465 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001466 }
1467
Sascha Hauer63f14742010-10-18 10:16:26 +02001468 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001469
1470 host->irq = platform_get_irq(pdev, 0);
1471
Sascha Hauer63f14742010-10-18 10:16:26 +02001472 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001473 * Use host->devtype_data->irq_control() here instead of irq_control()
1474 * because we must not disable_irq_nosync without having requested the
1475 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001476 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001477 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001478
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001479 err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
1480 IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001481 if (err)
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001482 return err;
1483
1484 clk_prepare_enable(host->clk);
1485 host->clk_act = 1;
Ivo Claryssed4840182010-04-08 16:14:44 +02001486
Sascha Hauer63f14742010-10-18 10:16:26 +02001487 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001488 * Now that we "own" the interrupt make sure the interrupt mask bit is
1489 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1490 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001491 */
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001492 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +02001493 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001494 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001495 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001496
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001497 /* first scan to find the device and get the page size */
Baruch Siachd178e3e2011-03-14 09:01:56 +02001498 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001499 err = -ENXIO;
1500 goto escan;
1501 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001502
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001503 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001504 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001505
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001506 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001507 this->ecc.layout = host->devtype_data->ecclayout_2k;
1508 else if (mtd->writesize == 4096)
1509 this->ecc.layout = host->devtype_data->ecclayout_4k;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001510
Mike Dunn6a918ba2012-03-11 14:21:11 -07001511 if (this->ecc.mode == NAND_ECC_HW) {
1512 if (nfc_is_v1())
1513 this->ecc.strength = 1;
1514 else
1515 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1516 }
1517
Sascha Hauer4a43faf2012-05-25 16:22:42 +02001518 /* second phase scan */
1519 if (nand_scan_tail(mtd)) {
1520 err = -ENXIO;
1521 goto escan;
1522 }
1523
Sascha Hauer34f6e152008-09-02 17:16:59 +02001524 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001525 mtd_device_parse_register(mtd, part_probes,
1526 &(struct mtd_part_parser_data){
1527 .of_node = pdev->dev.of_node,
1528 },
1529 host->pdata.parts,
1530 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001531
1532 platform_set_drvdata(pdev, host);
1533
1534 return 0;
1535
1536escan:
Lothar Waßmannc10d8ee2012-12-06 08:42:27 +01001537 if (host->clk_act)
1538 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001539
1540 return err;
1541}
1542
Bill Pemberton810b7e02012-11-19 13:26:04 -05001543static int mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001544{
1545 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1546
Sascha Hauer34f6e152008-09-02 17:16:59 +02001547 platform_set_drvdata(pdev, NULL);
1548
1549 nand_release(&host->mtd);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001550
1551 return 0;
1552}
1553
Sascha Hauer34f6e152008-09-02 17:16:59 +02001554static struct platform_driver mxcnd_driver = {
1555 .driver = {
1556 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001557 .owner = THIS_MODULE,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001558 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001559 },
Fabio Estevamddf16d62012-09-05 11:35:25 -03001560 .probe = mxcnd_probe,
Bill Pemberton5153b882012-11-19 13:21:24 -05001561 .remove = mxcnd_remove,
Sascha Hauer34f6e152008-09-02 17:16:59 +02001562};
Fabio Estevamddf16d62012-09-05 11:35:25 -03001563module_platform_driver(mxcnd_driver);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001564
1565MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1566MODULE_DESCRIPTION("MXC NAND MTD driver");
1567MODULE_LICENSE("GPL");