blob: 27ba07c079661380e4b662a30151a2ded964dd9c [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>
Sachin Kamatd367e372013-10-18 16:16:35 +053035#include <linux/of.h>
Uwe Kleine-König64363562012-04-23 11:23:41 +020036#include <linux/of_device.h>
37#include <linux/of_mtd.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020038
39#include <asm/mach/flash.h>
Arnd Bergmann82906b12012-08-24 15:14:29 +020040#include <linux/platform_data/mtd-mxc_nand.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020041
42#define DRIVER_NAME "mxc_nand"
43
44/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020045#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
46#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
47#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
48#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
49#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
50#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
51#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
52#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
53#define NFC_V1_V2_WRPROT (host->regs + 0x12)
54#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
55#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
Baruch Siachd178e3e2011-03-14 09:01:56 +020056#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
57#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
58#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
59#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
60#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
61#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
62#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
63#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
Sascha Hauer1bc99182010-08-06 15:53:08 +020064#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
65#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
66#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020067
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020068#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020069#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
70#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
71#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
72#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
73#define NFC_V1_V2_CONFIG1_RST (1 << 6)
74#define NFC_V1_V2_CONFIG1_CE (1 << 7)
Sascha Hauerb8db2f52010-08-09 15:04:19 +020075#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
76#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
77#define NFC_V2_CONFIG1_FP_INT (1 << 11)
Sascha Hauer34f6e152008-09-02 17:16:59 +020078
Sascha Hauer1bc99182010-08-06 15:53:08 +020079#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020080
Sascha Hauer1bc99182010-08-06 15:53:08 +020081/*
82 * Operation modes for the NFC. Valid for v1, v2 and v3
83 * type controllers.
84 */
85#define NFC_CMD (1 << 0)
86#define NFC_ADDR (1 << 1)
87#define NFC_INPUT (1 << 2)
88#define NFC_OUTPUT (1 << 3)
89#define NFC_ID (1 << 4)
90#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020091
Sascha Hauer71ec5152010-08-06 15:53:11 +020092#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
93#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
Sascha Hauer34f6e152008-09-02 17:16:59 +020094
Sascha Hauer71ec5152010-08-06 15:53:11 +020095#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
96#define NFC_V3_CONFIG1_SP_EN (1 << 0)
97#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
Sascha Hauer34f6e152008-09-02 17:16:59 +020098
Sascha Hauer71ec5152010-08-06 15:53:11 +020099#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200100
Sascha Hauer71ec5152010-08-06 15:53:11 +0200101#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200102
Sascha Hauer71ec5152010-08-06 15:53:11 +0200103#define NFC_V3_WRPROT (host->regs_ip + 0x0)
104#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
105#define NFC_V3_WRPROT_LOCK (1 << 1)
106#define NFC_V3_WRPROT_UNLOCK (1 << 2)
107#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
108
109#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
110
111#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
112#define NFC_V3_CONFIG2_PS_512 (0 << 0)
113#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
114#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
115#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
116#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
117#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
118#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
119#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200120#define NFC_V3_CONFIG2_PPB(x, shift) (((x) & 0x3) << shift)
Sascha Hauer71ec5152010-08-06 15:53:11 +0200121#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
122#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
123#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
124#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
125
126#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
127#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
128#define NFC_V3_CONFIG3_FW8 (1 << 3)
129#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
130#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
131#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
132#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
133
134#define NFC_V3_IPC (host->regs_ip + 0x2C)
135#define NFC_V3_IPC_CREQ (1 << 0)
136#define NFC_V3_IPC_INT (1 << 31)
137
138#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200139
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200140struct mxc_nand_host;
141
142struct mxc_nand_devtype_data {
143 void (*preset)(struct mtd_info *);
144 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
145 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
146 void (*send_page)(struct mtd_info *, unsigned int);
147 void (*send_read_id)(struct mxc_nand_host *);
148 uint16_t (*get_dev_status)(struct mxc_nand_host *);
149 int (*check_int)(struct mxc_nand_host *);
150 void (*irq_control)(struct mxc_nand_host *, int);
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200151 u32 (*get_ecc_status)(struct mxc_nand_host *);
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +0200152 struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k;
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200153 void (*select_chip)(struct mtd_info *mtd, int chip);
Uwe Kleine-König69d023b2012-04-23 11:23:39 +0200154 int (*correct_data)(struct mtd_info *mtd, u_char *dat,
155 u_char *read_ecc, u_char *calc_ecc);
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200156
157 /*
158 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
159 * (CONFIG1:INT_MSK is set). To handle this the driver uses
160 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
161 */
162 int irqpending_quirk;
163 int needs_ip;
164
165 size_t regs_offset;
166 size_t spare0_offset;
167 size_t axi_offset;
168
169 int spare_len;
170 int eccbytes;
171 int eccsize;
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200172 int ppb_shift;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200173};
174
Sascha Hauer34f6e152008-09-02 17:16:59 +0200175struct mxc_nand_host {
176 struct mtd_info mtd;
177 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200178 struct device *dev;
179
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200180 void __iomem *spare0;
181 void __iomem *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200182
183 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200184 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200185 void __iomem *regs_axi;
186 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200187 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200188 struct clk *clk;
189 int clk_act;
190 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200191 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200192 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200193
Sascha Hauer63f14742010-10-18 10:16:26 +0200194 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200195
196 uint8_t *data_buf;
197 unsigned int buf_start;
Sascha Hauer5f973042010-08-06 15:53:06 +0200198
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200199 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König64363562012-04-23 11:23:41 +0200200 struct mxc_nand_platform_data pdata;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200201};
202
Sascha Hauer34f6e152008-09-02 17:16:59 +0200203/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200204static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200205 .eccbytes = 5,
206 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200207 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200208};
209
Sascha Hauer94671142009-10-05 12:14:21 +0200210static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400211 .eccbytes = 20,
212 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
213 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
214 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200215};
216
Sascha Hauer94671142009-10-05 12:14:21 +0200217/* OOB description for 512 byte pages with 16 byte OOB */
218static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
219 .eccbytes = 1 * 9,
220 .eccpos = {
221 7, 8, 9, 10, 11, 12, 13, 14, 15
222 },
223 .oobfree = {
224 {.offset = 0, .length = 5}
225 }
226};
227
228/* OOB description for 2048 byte pages with 64 byte OOB */
229static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
230 .eccbytes = 4 * 9,
231 .eccpos = {
232 7, 8, 9, 10, 11, 12, 13, 14, 15,
233 23, 24, 25, 26, 27, 28, 29, 30, 31,
234 39, 40, 41, 42, 43, 44, 45, 46, 47,
235 55, 56, 57, 58, 59, 60, 61, 62, 63
236 },
237 .oobfree = {
238 {.offset = 2, .length = 4},
239 {.offset = 16, .length = 7},
240 {.offset = 32, .length = 7},
241 {.offset = 48, .length = 7}
242 }
243};
244
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200245/* OOB description for 4096 byte pages with 128 byte OOB */
246static struct nand_ecclayout nandv2_hw_eccoob_4k = {
247 .eccbytes = 8 * 9,
248 .eccpos = {
249 7, 8, 9, 10, 11, 12, 13, 14, 15,
250 23, 24, 25, 26, 27, 28, 29, 30, 31,
251 39, 40, 41, 42, 43, 44, 45, 46, 47,
252 55, 56, 57, 58, 59, 60, 61, 62, 63,
253 71, 72, 73, 74, 75, 76, 77, 78, 79,
254 87, 88, 89, 90, 91, 92, 93, 94, 95,
255 103, 104, 105, 106, 107, 108, 109, 110, 111,
256 119, 120, 121, 122, 123, 124, 125, 126, 127,
257 },
258 .oobfree = {
259 {.offset = 2, .length = 4},
260 {.offset = 16, .length = 7},
261 {.offset = 32, .length = 7},
262 {.offset = 48, .length = 7},
263 {.offset = 64, .length = 7},
264 {.offset = 80, .length = 7},
265 {.offset = 96, .length = 7},
266 {.offset = 112, .length = 7},
267 }
268};
269
Jingoo Hanb2ac0372013-08-07 16:18:52 +0900270static const char * const part_probes[] = {
Lothar Waßmann740bb0c2012-12-06 08:42:28 +0100271 "cmdlinepart", "RedBoot", "ofpart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200272
Sascha Hauer096bcc22012-05-29 10:16:09 +0200273static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
274{
275 int i;
276 u32 *t = trg;
277 const __iomem u32 *s = src;
278
279 for (i = 0; i < (size >> 2); i++)
280 *t++ = __raw_readl(s++);
281}
282
Koul, Vinod33a87a12014-10-20 21:36:13 +0530283static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200284{
Koul, Vinod33a87a12014-10-20 21:36:13 +0530285 /* __iowrite32_copy use 32bit size values so divide by 4 */
286 __iowrite32_copy(trg, src, size / 4);
Sascha Hauer096bcc22012-05-29 10:16:09 +0200287}
288
Sascha Hauer71ec5152010-08-06 15:53:11 +0200289static int check_int_v3(struct mxc_nand_host *host)
290{
291 uint32_t tmp;
292
293 tmp = readl(NFC_V3_IPC);
294 if (!(tmp & NFC_V3_IPC_INT))
295 return 0;
296
297 tmp &= ~NFC_V3_IPC_INT;
298 writel(tmp, NFC_V3_IPC);
299
300 return 1;
301}
302
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200303static int check_int_v1_v2(struct mxc_nand_host *host)
304{
305 uint32_t tmp;
306
Sascha Hauer1bc99182010-08-06 15:53:08 +0200307 tmp = readw(NFC_V1_V2_CONFIG2);
308 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200309 return 0;
310
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200311 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200312 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200313
314 return 1;
315}
316
Sascha Hauer63f14742010-10-18 10:16:26 +0200317static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
318{
319 uint16_t tmp;
320
321 tmp = readw(NFC_V1_V2_CONFIG1);
322
323 if (activate)
324 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
325 else
326 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
327
328 writew(tmp, NFC_V1_V2_CONFIG1);
329}
330
331static void irq_control_v3(struct mxc_nand_host *host, int activate)
332{
333 uint32_t tmp;
334
335 tmp = readl(NFC_V3_CONFIG2);
336
337 if (activate)
338 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
339 else
340 tmp |= NFC_V3_CONFIG2_INT_MSK;
341
342 writel(tmp, NFC_V3_CONFIG2);
343}
344
Uwe Kleine-König85569582012-04-23 11:23:34 +0200345static void irq_control(struct mxc_nand_host *host, int activate)
346{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200347 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200348 if (activate)
349 enable_irq(host->irq);
350 else
351 disable_irq_nosync(host->irq);
352 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200353 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200354 }
355}
356
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200357static u32 get_ecc_status_v1(struct mxc_nand_host *host)
358{
359 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
360}
361
362static u32 get_ecc_status_v2(struct mxc_nand_host *host)
363{
364 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
365}
366
367static u32 get_ecc_status_v3(struct mxc_nand_host *host)
368{
369 return readl(NFC_V3_ECC_STATUS_RESULT);
370}
371
Uwe Kleine-König85569582012-04-23 11:23:34 +0200372static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
373{
374 struct mxc_nand_host *host = dev_id;
375
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200376 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200377 return IRQ_NONE;
378
379 irq_control(host, 0);
380
381 complete(&host->op_completion);
382
383 return IRQ_HANDLED;
384}
385
Sascha Hauer34f6e152008-09-02 17:16:59 +0200386/* This function polls the NANDFC to wait for the basic operation to
387 * complete by checking the INT bit of config2 register.
388 */
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100389static int wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200390{
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100391 int ret = 0;
392
393 /*
394 * If operation is already complete, don't bother to setup an irq or a
395 * loop.
396 */
397 if (host->devtype_data->check_int(host))
398 return 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200399
400 if (useirq) {
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100401 unsigned long timeout;
402
403 reinit_completion(&host->op_completion);
404
405 irq_control(host, 1);
406
407 timeout = wait_for_completion_timeout(&host->op_completion, HZ);
408 if (!timeout && !host->devtype_data->check_int(host)) {
409 dev_dbg(host->dev, "timeout waiting for irq\n");
410 ret = -ETIMEDOUT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200411 }
412 } else {
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100413 int max_retries = 8000;
414 int done;
415
416 do {
417 udelay(1);
418
419 done = host->devtype_data->check_int(host);
420 if (done)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200421 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200422
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100423 } while (--max_retries);
424
425 if (!done) {
426 dev_dbg(host->dev, "timeout polling for completion\n");
427 ret = -ETIMEDOUT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200428 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200429 }
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100430
431 WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq);
432
433 return ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200434}
435
Sascha Hauer71ec5152010-08-06 15:53:11 +0200436static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
437{
438 /* fill command */
439 writel(cmd, NFC_V3_FLASH_CMD);
440
441 /* send out command */
442 writel(NFC_CMD, NFC_V3_LAUNCH);
443
444 /* Wait for operation to complete */
445 wait_op_done(host, useirq);
446}
447
Sascha Hauer34f6e152008-09-02 17:16:59 +0200448/* This function issues the specified command to the NAND device and
449 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200450static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200451{
Brian Norris289c0522011-07-19 10:06:09 -0700452 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200453
Sascha Hauer1bc99182010-08-06 15:53:08 +0200454 writew(cmd, NFC_V1_V2_FLASH_CMD);
455 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200456
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200457 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200458 int max_retries = 100;
459 /* Reset completion is indicated by NFC_CONFIG2 */
460 /* being set to 0 */
461 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200462 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200463 break;
464 }
465 udelay(1);
466 }
467 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700468 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200469 } else {
470 /* Wait for operation to complete */
471 wait_op_done(host, useirq);
472 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200473}
474
Sascha Hauer71ec5152010-08-06 15:53:11 +0200475static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
476{
477 /* fill address */
478 writel(addr, NFC_V3_FLASH_ADDR0);
479
480 /* send out address */
481 writel(NFC_ADDR, NFC_V3_LAUNCH);
482
483 wait_op_done(host, 0);
484}
485
Sascha Hauer34f6e152008-09-02 17:16:59 +0200486/* This function sends an address (or partial address) to the
487 * NAND device. The address is used to select the source/destination for
488 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200489static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200490{
Brian Norris289c0522011-07-19 10:06:09 -0700491 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200492
Sascha Hauer1bc99182010-08-06 15:53:08 +0200493 writew(addr, NFC_V1_V2_FLASH_ADDR);
494 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200495
496 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200497 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200498}
499
Sascha Hauer71ec5152010-08-06 15:53:11 +0200500static void send_page_v3(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 uint32_t tmp;
505
506 tmp = readl(NFC_V3_CONFIG1);
507 tmp &= ~(7 << 4);
508 writel(tmp, NFC_V3_CONFIG1);
509
510 /* transfer data from NFC ram to nand */
511 writel(ops, NFC_V3_LAUNCH);
512
513 wait_op_done(host, false);
514}
515
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200516static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
517{
518 struct nand_chip *nand_chip = mtd->priv;
519 struct mxc_nand_host *host = nand_chip->priv;
520
521 /* NANDFC buffer 0 is used for page read/write */
522 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
523
524 writew(ops, NFC_V1_V2_CONFIG2);
525
526 /* Wait for operation to complete */
527 wait_op_done(host, true);
528}
529
530static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200531{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200532 struct nand_chip *nand_chip = mtd->priv;
533 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200534 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200535
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200536 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200537 bufs = 4;
538 else
539 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200540
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200541 for (i = 0; i < bufs; i++) {
542
543 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200544 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200545
Sascha Hauer1bc99182010-08-06 15:53:08 +0200546 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200547
548 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200549 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200550 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551}
552
Sascha Hauer71ec5152010-08-06 15:53:11 +0200553static void send_read_id_v3(struct mxc_nand_host *host)
554{
Roman Schneidera8459f22013-01-15 16:56:24 +0100555 struct nand_chip *this = &host->nand;
556
Sascha Hauer71ec5152010-08-06 15:53:11 +0200557 /* Read ID into main buffer */
558 writel(NFC_ID, NFC_V3_LAUNCH);
559
560 wait_op_done(host, true);
561
Sascha Hauer096bcc22012-05-29 10:16:09 +0200562 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Roman Schneidera8459f22013-01-15 16:56:24 +0100563
564 if (this->options & NAND_BUSWIDTH_16) {
565 /* compress the ID info */
566 host->data_buf[1] = host->data_buf[2];
567 host->data_buf[2] = host->data_buf[4];
568 host->data_buf[3] = host->data_buf[6];
569 host->data_buf[4] = host->data_buf[8];
570 host->data_buf[5] = host->data_buf[10];
571 }
Sascha Hauer71ec5152010-08-06 15:53:11 +0200572}
573
Sascha Hauer34f6e152008-09-02 17:16:59 +0200574/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200575static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200576{
577 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200578
579 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200580 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200581
Sascha Hauer1bc99182010-08-06 15:53:08 +0200582 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200583
584 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200585 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200586
Sascha Hauer096bcc22012-05-29 10:16:09 +0200587 memcpy32_fromio(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200588
589 if (this->options & NAND_BUSWIDTH_16) {
590 /* compress the ID info */
591 host->data_buf[1] = host->data_buf[2];
592 host->data_buf[2] = host->data_buf[4];
593 host->data_buf[3] = host->data_buf[6];
594 host->data_buf[4] = host->data_buf[8];
595 host->data_buf[5] = host->data_buf[10];
596 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200597}
598
Sascha Hauer71ec5152010-08-06 15:53:11 +0200599static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200600{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200601 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200602 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200603
Sascha Hauer71ec5152010-08-06 15:53:11 +0200604 return readl(NFC_V3_CONFIG1) >> 16;
605}
606
Sascha Hauer34f6e152008-09-02 17:16:59 +0200607/* This function requests the NANDFC to perform a read of the
608 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200609static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200610{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200611 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200612 uint32_t store;
613 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200614
Baruch Siachd178e3e2011-03-14 09:01:56 +0200615 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200616
617 /*
618 * The device status is stored in main_area0. To
619 * prevent corruption of the buffer save the value
620 * and restore it afterwards.
621 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200622 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200623
Sascha Hauer1bc99182010-08-06 15:53:08 +0200624 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200625 wait_op_done(host, true);
626
Sascha Hauer34f6e152008-09-02 17:16:59 +0200627 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200628
Sascha Hauer34f6e152008-09-02 17:16:59 +0200629 writel(store, main_buf);
630
631 return ret;
632}
633
634/* This functions is used by upper layer to checks if device is ready */
635static int mxc_nand_dev_ready(struct mtd_info *mtd)
636{
637 /*
638 * NFC handles R/B internally. Therefore, this function
639 * always returns status as ready.
640 */
641 return 1;
642}
643
644static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
645{
646 /*
647 * If HW ECC is enabled, we turn it on during init. There is
648 * no need to enable again here.
649 */
650}
651
Sascha Hauer94f77e52010-08-06 15:53:09 +0200652static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200653 u_char *read_ecc, u_char *calc_ecc)
654{
655 struct nand_chip *nand_chip = mtd->priv;
656 struct mxc_nand_host *host = nand_chip->priv;
657
658 /*
659 * 1-Bit errors are automatically corrected in HW. No need for
660 * additional correction. 2-Bit errors cannot be corrected by
661 * HW ECC, so we need to return failure
662 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200663 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200664
665 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700666 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200667 return -1;
668 }
669
670 return 0;
671}
672
Sascha Hauer94f77e52010-08-06 15:53:09 +0200673static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
674 u_char *read_ecc, u_char *calc_ecc)
675{
676 struct nand_chip *nand_chip = mtd->priv;
677 struct mxc_nand_host *host = nand_chip->priv;
678 u32 ecc_stat, err;
679 int no_subpages = 1;
680 int ret = 0;
681 u8 ecc_bit_mask, err_limit;
682
683 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
684 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
685
686 no_subpages = mtd->writesize >> 9;
687
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200688 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200689
690 do {
691 err = ecc_stat & ecc_bit_mask;
692 if (err > err_limit) {
693 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
694 return -1;
695 } else {
696 ret += err;
697 }
698 ecc_stat >>= 4;
699 } while (--no_subpages);
700
Sascha Hauer94f77e52010-08-06 15:53:09 +0200701 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
702
703 return ret;
704}
705
Sascha Hauer34f6e152008-09-02 17:16:59 +0200706static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
707 u_char *ecc_code)
708{
709 return 0;
710}
711
712static u_char mxc_nand_read_byte(struct mtd_info *mtd)
713{
714 struct nand_chip *nand_chip = mtd->priv;
715 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200716 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200717
718 /* Check for status request */
719 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200720 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200721
Sascha Hauerf8f96082009-06-04 17:12:26 +0200722 ret = *(uint8_t *)(host->data_buf + host->buf_start);
723 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200724
725 return ret;
726}
727
728static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
729{
730 struct nand_chip *nand_chip = mtd->priv;
731 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200732 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200733
Sascha Hauerf8f96082009-06-04 17:12:26 +0200734 ret = *(uint16_t *)(host->data_buf + host->buf_start);
735 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200736
737 return ret;
738}
739
740/* Write data of length len to buffer buf. The data to be
741 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
742 * Operation by the NFC, the data is written to NAND Flash */
743static void mxc_nand_write_buf(struct mtd_info *mtd,
744 const u_char *buf, int len)
745{
746 struct nand_chip *nand_chip = mtd->priv;
747 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200748 u16 col = host->buf_start;
749 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200750
Sascha Hauerf8f96082009-06-04 17:12:26 +0200751 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200752
Sascha Hauerf8f96082009-06-04 17:12:26 +0200753 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200754
Sascha Hauerf8f96082009-06-04 17:12:26 +0200755 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200756}
757
758/* Read the data buffer from the NAND Flash. To read the data from NAND
759 * Flash first the data output cycle is initiated by the NFC, which copies
760 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
761 */
762static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
763{
764 struct nand_chip *nand_chip = mtd->priv;
765 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200766 u16 col = host->buf_start;
767 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200768
Sascha Hauerf8f96082009-06-04 17:12:26 +0200769 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200770
Baruch Siach5d9d9932011-03-02 16:47:55 +0200771 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200772
Baruch Siach5d9d9932011-03-02 16:47:55 +0200773 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200774}
775
Sascha Hauer34f6e152008-09-02 17:16:59 +0200776/* This function is used by upper layer for select and
777 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200778static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200779{
780 struct nand_chip *nand_chip = mtd->priv;
781 struct mxc_nand_host *host = nand_chip->priv;
782
Baruch Siachd178e3e2011-03-14 09:01:56 +0200783 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200784 /* Disable the NFC clock */
785 if (host->clk_act) {
Sascha Hauer97c32132012-03-07 20:56:35 +0100786 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200787 host->clk_act = 0;
788 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200789 return;
790 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200791
Baruch Siachd178e3e2011-03-14 09:01:56 +0200792 if (!host->clk_act) {
793 /* Enable the NFC clock */
Sascha Hauer97c32132012-03-07 20:56:35 +0100794 clk_prepare_enable(host->clk);
Baruch Siachd178e3e2011-03-14 09:01:56 +0200795 host->clk_act = 1;
796 }
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200797}
Baruch Siachd178e3e2011-03-14 09:01:56 +0200798
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200799static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200800{
801 struct nand_chip *nand_chip = mtd->priv;
802 struct mxc_nand_host *host = nand_chip->priv;
803
804 if (chip == -1) {
805 /* Disable the NFC clock */
806 if (host->clk_act) {
Fabio Estevam3d059692012-05-25 20:14:50 -0300807 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200808 host->clk_act = 0;
809 }
810 return;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200811 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200812
813 if (!host->clk_act) {
814 /* Enable the NFC clock */
Fabio Estevam3d059692012-05-25 20:14:50 -0300815 clk_prepare_enable(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200816 host->clk_act = 1;
817 }
818
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200819 host->active_cs = chip;
820 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200821}
822
Sascha Hauerf8f96082009-06-04 17:12:26 +0200823/*
824 * Function to transfer data to/from spare area.
825 */
826static void copy_spare(struct mtd_info *mtd, bool bfrom)
827{
828 struct nand_chip *this = mtd->priv;
829 struct mxc_nand_host *host = this->priv;
830 u16 i, j;
831 u16 n = mtd->writesize >> 9;
832 u8 *d = host->data_buf + mtd->writesize;
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200833 u8 __iomem *s = host->spare0;
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200834 u16 t = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200835
836 j = (mtd->oobsize / n >> 1) << 1;
837
838 if (bfrom) {
839 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200840 memcpy32_fromio(d + i * j, s + i * t, j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200841
842 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200843 memcpy32_fromio(d + i * j, s + i * t, mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200844 } else {
845 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200846 memcpy32_toio(&s[i * t], &d[i * j], j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200847
848 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200849 memcpy32_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200850 }
851}
852
Sascha Hauera3e65b62009-06-02 11:47:59 +0200853static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200854{
855 struct nand_chip *nand_chip = mtd->priv;
856 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200857
858 /* Write out column address, if necessary */
859 if (column != -1) {
860 /*
861 * MXC NANDFC can only perform full page+spare or
862 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100863 * perform a read/write buf operation, the saved column
864 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200865 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200866 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200867 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200868 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200869 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200870 }
871
872 /* Write out page address, if necessary */
873 if (page_addr != -1) {
874 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200875 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200876
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200877 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400878 if (mtd->size >= 0x10000000) {
879 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200880 host->devtype_data->send_addr(host,
881 (page_addr >> 8) & 0xff,
882 false);
883 host->devtype_data->send_addr(host,
884 (page_addr >> 16) & 0xff,
885 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400886 } else
887 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200888 host->devtype_data->send_addr(host,
889 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200890 } else {
891 /* One more address cycle for higher density devices */
892 if (mtd->size >= 0x4000000) {
893 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200894 host->devtype_data->send_addr(host,
895 (page_addr >> 8) & 0xff,
896 false);
897 host->devtype_data->send_addr(host,
898 (page_addr >> 16) & 0xff,
899 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200900 } else
901 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200902 host->devtype_data->send_addr(host,
903 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200904 }
905 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200906}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200907
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200908/*
909 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
910 * on how much oob the nand chip has. For 8bit ecc we need at least
911 * 26 bytes of oob data per 512 byte block.
912 */
913static int get_eccsize(struct mtd_info *mtd)
914{
915 int oobbytes_per_512 = 0;
916
917 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
918
919 if (oobbytes_per_512 < 26)
920 return 4;
921 else
922 return 8;
923}
924
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200925static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200926{
927 struct nand_chip *nand_chip = mtd->priv;
928 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200929 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200930
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200931 if (nand_chip->ecc.mode == NAND_ECC_HW)
932 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
933
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200934 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200935 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200936
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200937 host->eccsize = 1;
938
939 writew(config1, NFC_V1_V2_CONFIG1);
940 /* preset operation */
941
942 /* Unlock the internal RAM Buffer */
943 writew(0x2, NFC_V1_V2_CONFIG);
944
945 /* Blocks to be unlocked */
946 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
947 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
948
949 /* Unlock Block Command for given address range */
950 writew(0x4, NFC_V1_V2_WRPROT);
951}
952
953static void preset_v2(struct mtd_info *mtd)
954{
955 struct nand_chip *nand_chip = mtd->priv;
956 struct mxc_nand_host *host = nand_chip->priv;
957 uint16_t config1 = 0;
958
959 if (nand_chip->ecc.mode == NAND_ECC_HW)
960 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
961
962 config1 |= NFC_V2_CONFIG1_FP_INT;
Ivo Claryssed4840182010-04-08 16:14:44 +0200963
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200964 if (!host->devtype_data->irqpending_quirk)
Ivo Claryssed4840182010-04-08 16:14:44 +0200965 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200966
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200967 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200968 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
969
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200970 host->eccsize = get_eccsize(mtd);
971 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200972 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
973
974 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200975 } else {
976 host->eccsize = 1;
977 }
978
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200979 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200980 /* preset operation */
981
982 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200983 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200984
985 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200986 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
987 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
988 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
989 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
990 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
991 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
992 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
993 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200994
995 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200996 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200997}
998
Sascha Hauer71ec5152010-08-06 15:53:11 +0200999static void preset_v3(struct mtd_info *mtd)
1000{
1001 struct nand_chip *chip = mtd->priv;
1002 struct mxc_nand_host *host = chip->priv;
1003 uint32_t config2, config3;
1004 int i, addr_phases;
1005
1006 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
1007 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
1008
1009 /* Unlock the internal RAM Buffer */
1010 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
1011 NFC_V3_WRPROT);
1012
1013 /* Blocks to be unlocked */
1014 for (i = 0; i < NAND_MAX_CHIPS; i++)
1015 writel(0x0 | (0xffff << 16),
1016 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
1017
1018 writel(0, NFC_V3_IPC);
1019
1020 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
1021 NFC_V3_CONFIG2_2CMD_PHASES |
1022 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
1023 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +02001024 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +02001025 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
1026
1027 if (chip->ecc.mode == NAND_ECC_HW)
1028 config2 |= NFC_V3_CONFIG2_ECC_EN;
1029
1030 addr_phases = fls(chip->pagemask) >> 3;
1031
1032 if (mtd->writesize == 2048) {
1033 config2 |= NFC_V3_CONFIG2_PS_2048;
1034 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1035 } else if (mtd->writesize == 4096) {
1036 config2 |= NFC_V3_CONFIG2_PS_4096;
1037 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1038 } else {
1039 config2 |= NFC_V3_CONFIG2_PS_512;
1040 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1041 }
1042
1043 if (mtd->writesize) {
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001044 config2 |= NFC_V3_CONFIG2_PPB(
1045 ffs(mtd->erasesize / mtd->writesize) - 6,
1046 host->devtype_data->ppb_shift);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001047 host->eccsize = get_eccsize(mtd);
1048 if (host->eccsize == 8)
1049 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
1050 }
1051
1052 writel(config2, NFC_V3_CONFIG2);
1053
1054 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1055 NFC_V3_CONFIG3_NO_SDMA |
1056 NFC_V3_CONFIG3_RBB_MODE |
1057 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1058 NFC_V3_CONFIG3_ADD_OP(0);
1059
1060 if (!(chip->options & NAND_BUSWIDTH_16))
1061 config3 |= NFC_V3_CONFIG3_FW8;
1062
1063 writel(config3, NFC_V3_CONFIG3);
1064
1065 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001066}
1067
Sascha Hauer34f6e152008-09-02 17:16:59 +02001068/* Used by the upper layer to write command to NAND Flash for
1069 * different operations to be carried out on NAND Flash */
1070static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1071 int column, int page_addr)
1072{
1073 struct nand_chip *nand_chip = mtd->priv;
1074 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001075
Brian Norris289c0522011-07-19 10:06:09 -07001076 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001077 command, column, page_addr);
1078
1079 /* Reset command state information */
1080 host->status_request = false;
1081
1082 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001083 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001084 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001085 host->devtype_data->preset(mtd);
1086 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001087 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001088
Sascha Hauer34f6e152008-09-02 17:16:59 +02001089 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001090 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001091 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001092
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001093 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001094 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001095 break;
1096
Sascha Hauer34f6e152008-09-02 17:16:59 +02001097 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001098 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001099 if (command == NAND_CMD_READ0)
1100 host->buf_start = column;
1101 else
1102 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001103
Sascha Hauer5ea32022010-04-27 15:24:01 +02001104 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001105
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001106 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001107 mxc_do_addr_cycle(mtd, column, page_addr);
1108
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001109 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001110 host->devtype_data->send_cmd(host,
1111 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001112
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001113 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001114
Sascha Hauer096bcc22012-05-29 10:16:09 +02001115 memcpy32_fromio(host->data_buf, host->main_area0,
1116 mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001117 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001118 break;
1119
Sascha Hauer34f6e152008-09-02 17:16:59 +02001120 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001121 if (column >= mtd->writesize)
1122 /* call ourself to read a page */
1123 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001124
Sascha Hauer5ea32022010-04-27 15:24:01 +02001125 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001126
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001127 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001128 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001129 break;
1130
1131 case NAND_CMD_PAGEPROG:
Sascha Hauer096bcc22012-05-29 10:16:09 +02001132 memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001133 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001134 host->devtype_data->send_page(mtd, NFC_INPUT);
1135 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001136 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001137 break;
1138
Sascha Hauer34f6e152008-09-02 17:16:59 +02001139 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001140 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001141 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001142 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001143 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001144 break;
1145
Sascha Hauer89121a62009-06-04 17:18:01 +02001146 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001147 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001148 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001149 mxc_do_addr_cycle(mtd, column, page_addr);
1150
Sascha Hauer34f6e152008-09-02 17:16:59 +02001151 break;
1152 }
1153}
1154
Sascha Hauerf1372052009-10-21 14:25:27 +02001155/*
1156 * The generic flash bbt decriptors overlap with our ecc
1157 * hardware, so define some i.MX specific ones.
1158 */
1159static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1160static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1161
1162static struct nand_bbt_descr bbt_main_descr = {
1163 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1164 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1165 .offs = 0,
1166 .len = 4,
1167 .veroffs = 4,
1168 .maxblocks = 4,
1169 .pattern = bbt_pattern,
1170};
1171
1172static struct nand_bbt_descr bbt_mirror_descr = {
1173 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1174 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1175 .offs = 0,
1176 .len = 4,
1177 .veroffs = 4,
1178 .maxblocks = 4,
1179 .pattern = mirror_pattern,
1180};
1181
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001182/* v1 + irqpending_quirk: i.MX21 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001183static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001184 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001185 .send_cmd = send_cmd_v1_v2,
1186 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001187 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001188 .send_read_id = send_read_id_v1_v2,
1189 .get_dev_status = get_dev_status_v1_v2,
1190 .check_int = check_int_v1_v2,
1191 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001192 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001193 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1194 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1195 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001196 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001197 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001198 .irqpending_quirk = 1,
1199 .needs_ip = 0,
1200 .regs_offset = 0xe00,
1201 .spare0_offset = 0x800,
1202 .spare_len = 16,
1203 .eccbytes = 3,
1204 .eccsize = 1,
1205};
1206
1207/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1208static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1209 .preset = preset_v1,
1210 .send_cmd = send_cmd_v1_v2,
1211 .send_addr = send_addr_v1_v2,
1212 .send_page = send_page_v1,
1213 .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,
1217 .get_ecc_status = get_ecc_status_v1,
1218 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1219 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1220 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1221 .select_chip = mxc_nand_select_chip_v1_v3,
1222 .correct_data = mxc_nand_correct_data_v1,
1223 .irqpending_quirk = 0,
1224 .needs_ip = 0,
1225 .regs_offset = 0xe00,
1226 .spare0_offset = 0x800,
1227 .axi_offset = 0,
1228 .spare_len = 16,
1229 .eccbytes = 3,
1230 .eccsize = 1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001231};
1232
1233/* v21: i.MX25, i.MX35 */
1234static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001235 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001236 .send_cmd = send_cmd_v1_v2,
1237 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001238 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001239 .send_read_id = send_read_id_v1_v2,
1240 .get_dev_status = get_dev_status_v1_v2,
1241 .check_int = check_int_v1_v2,
1242 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001243 .get_ecc_status = get_ecc_status_v2,
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_4k,
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001247 .select_chip = mxc_nand_select_chip_v2,
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 = 0,
1251 .regs_offset = 0x1e00,
1252 .spare0_offset = 0x1000,
1253 .axi_offset = 0,
1254 .spare_len = 64,
1255 .eccbytes = 9,
1256 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001257};
1258
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001259/* v3.2a: i.MX51 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001260static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1261 .preset = preset_v3,
1262 .send_cmd = send_cmd_v3,
1263 .send_addr = send_addr_v3,
1264 .send_page = send_page_v3,
1265 .send_read_id = send_read_id_v3,
1266 .get_dev_status = get_dev_status_v3,
1267 .check_int = check_int_v3,
1268 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001269 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001270 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1271 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1272 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001273 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001274 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001275 .irqpending_quirk = 0,
1276 .needs_ip = 1,
1277 .regs_offset = 0,
1278 .spare0_offset = 0x1000,
1279 .axi_offset = 0x1e00,
1280 .spare_len = 64,
1281 .eccbytes = 0,
1282 .eccsize = 0,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001283 .ppb_shift = 7,
1284};
1285
1286/* v3.2b: i.MX53 */
1287static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
1288 .preset = preset_v3,
1289 .send_cmd = send_cmd_v3,
1290 .send_addr = send_addr_v3,
1291 .send_page = send_page_v3,
1292 .send_read_id = send_read_id_v3,
1293 .get_dev_status = get_dev_status_v3,
1294 .check_int = check_int_v3,
1295 .irq_control = irq_control_v3,
1296 .get_ecc_status = get_ecc_status_v3,
1297 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1298 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1299 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1300 .select_chip = mxc_nand_select_chip_v1_v3,
1301 .correct_data = mxc_nand_correct_data_v2_v3,
1302 .irqpending_quirk = 0,
1303 .needs_ip = 1,
1304 .regs_offset = 0,
1305 .spare0_offset = 0x1000,
1306 .axi_offset = 0x1e00,
1307 .spare_len = 64,
1308 .eccbytes = 0,
1309 .eccsize = 0,
1310 .ppb_shift = 8,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001311};
1312
Shawn Guo4d624352012-09-15 13:34:09 +08001313static inline int is_imx21_nfc(struct mxc_nand_host *host)
1314{
1315 return host->devtype_data == &imx21_nand_devtype_data;
1316}
1317
1318static inline int is_imx27_nfc(struct mxc_nand_host *host)
1319{
1320 return host->devtype_data == &imx27_nand_devtype_data;
1321}
1322
1323static inline int is_imx25_nfc(struct mxc_nand_host *host)
1324{
1325 return host->devtype_data == &imx25_nand_devtype_data;
1326}
1327
1328static inline int is_imx51_nfc(struct mxc_nand_host *host)
1329{
1330 return host->devtype_data == &imx51_nand_devtype_data;
1331}
1332
1333static inline int is_imx53_nfc(struct mxc_nand_host *host)
1334{
1335 return host->devtype_data == &imx53_nand_devtype_data;
1336}
1337
1338static struct platform_device_id mxcnd_devtype[] = {
1339 {
1340 .name = "imx21-nand",
1341 .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
1342 }, {
1343 .name = "imx27-nand",
1344 .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
1345 }, {
1346 .name = "imx25-nand",
1347 .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
1348 }, {
1349 .name = "imx51-nand",
1350 .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
1351 }, {
1352 .name = "imx53-nand",
1353 .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
1354 }, {
1355 /* sentinel */
1356 }
1357};
1358MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
1359
Uwe Kleine-König64363562012-04-23 11:23:41 +02001360#ifdef CONFIG_OF_MTD
1361static const struct of_device_id mxcnd_dt_ids[] = {
1362 {
1363 .compatible = "fsl,imx21-nand",
1364 .data = &imx21_nand_devtype_data,
1365 }, {
1366 .compatible = "fsl,imx27-nand",
1367 .data = &imx27_nand_devtype_data,
1368 }, {
1369 .compatible = "fsl,imx25-nand",
1370 .data = &imx25_nand_devtype_data,
1371 }, {
1372 .compatible = "fsl,imx51-nand",
1373 .data = &imx51_nand_devtype_data,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001374 }, {
1375 .compatible = "fsl,imx53-nand",
1376 .data = &imx53_nand_devtype_data,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001377 },
1378 { /* sentinel */ }
1379};
1380
1381static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1382{
1383 struct device_node *np = host->dev->of_node;
1384 struct mxc_nand_platform_data *pdata = &host->pdata;
1385 const struct of_device_id *of_id =
1386 of_match_device(mxcnd_dt_ids, host->dev);
1387 int buswidth;
1388
1389 if (!np)
1390 return 1;
1391
1392 if (of_get_nand_ecc_mode(np) >= 0)
1393 pdata->hw_ecc = 1;
1394
1395 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1396
1397 buswidth = of_get_nand_bus_width(np);
1398 if (buswidth < 0)
1399 return buswidth;
1400
1401 pdata->width = buswidth / 8;
1402
1403 host->devtype_data = of_id->data;
1404
1405 return 0;
1406}
1407#else
1408static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1409{
1410 return 1;
1411}
1412#endif
1413
Bill Pemberton06f25512012-11-19 13:23:07 -05001414static int mxcnd_probe(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001415{
1416 struct nand_chip *this;
1417 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001418 struct mxc_nand_host *host;
1419 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001420 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001421
1422 /* Allocate memory for MTD device structure and private data */
Huang Shijiea5900552013-12-21 00:02:27 +08001423 host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
1424 GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001425 if (!host)
1426 return -ENOMEM;
1427
Huang Shijiea5900552013-12-21 00:02:27 +08001428 /* allocate a temporary buffer for the nand_scan_ident() */
1429 host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
1430 if (!host->data_buf)
1431 return -ENOMEM;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001432
Sascha Hauer34f6e152008-09-02 17:16:59 +02001433 host->dev = &pdev->dev;
1434 /* structures must be linked */
1435 this = &host->nand;
1436 mtd = &host->mtd;
1437 mtd->priv = this;
1438 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001439 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001440 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001441
1442 /* 50 us command delay time */
1443 this->chip_delay = 5;
1444
1445 this->priv = host;
1446 this->dev_ready = mxc_nand_dev_ready;
1447 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001448 this->read_byte = mxc_nand_read_byte;
1449 this->read_word = mxc_nand_read_word;
1450 this->write_buf = mxc_nand_write_buf;
1451 this->read_buf = mxc_nand_read_buf;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001452
Fabio Estevam24b82d32012-09-05 11:52:27 -03001453 host->clk = devm_clk_get(&pdev->dev, NULL);
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001454 if (IS_ERR(host->clk))
1455 return PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001456
Sascha Hauer71885b62012-06-06 12:33:14 +02001457 err = mxcnd_probe_dt(host);
Shawn Guo4d624352012-09-15 13:34:09 +08001458 if (err > 0) {
Jingoo Han453810b2013-07-30 17:18:33 +09001459 struct mxc_nand_platform_data *pdata =
1460 dev_get_platdata(&pdev->dev);
Shawn Guo4d624352012-09-15 13:34:09 +08001461 if (pdata) {
1462 host->pdata = *pdata;
1463 host->devtype_data = (struct mxc_nand_devtype_data *)
1464 pdev->id_entry->driver_data;
1465 } else {
1466 err = -ENODEV;
1467 }
1468 }
Sascha Hauer71885b62012-06-06 12:33:14 +02001469 if (err < 0)
1470 return err;
1471
1472 if (host->devtype_data->needs_ip) {
1473 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Thierry Redingb0de7742013-01-21 11:09:12 +01001474 host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
1475 if (IS_ERR(host->regs_ip))
1476 return PTR_ERR(host->regs_ip);
Sascha Hauer71885b62012-06-06 12:33:14 +02001477
1478 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1479 } else {
1480 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1481 }
1482
Thierry Redingb0de7742013-01-21 11:09:12 +01001483 host->base = devm_ioremap_resource(&pdev->dev, res);
1484 if (IS_ERR(host->base))
1485 return PTR_ERR(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001486
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001487 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001488
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001489 if (host->devtype_data->regs_offset)
1490 host->regs = host->base + host->devtype_data->regs_offset;
1491 host->spare0 = host->base + host->devtype_data->spare0_offset;
1492 if (host->devtype_data->axi_offset)
1493 host->regs_axi = host->base + host->devtype_data->axi_offset;
1494
1495 this->ecc.bytes = host->devtype_data->eccbytes;
1496 host->eccsize = host->devtype_data->eccsize;
1497
1498 this->select_chip = host->devtype_data->select_chip;
1499 this->ecc.size = 512;
1500 this->ecc.layout = host->devtype_data->ecclayout_512;
1501
Uwe Kleine-König64363562012-04-23 11:23:41 +02001502 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001503 this->ecc.calculate = mxc_nand_calculate_ecc;
1504 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001505 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001506 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001507 } else {
1508 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001509 }
1510
Uwe Kleine-König64363562012-04-23 11:23:41 +02001511 /* NAND bus width determines access functions used by upper layer */
1512 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001513 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001514
Uwe Kleine-König64363562012-04-23 11:23:41 +02001515 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001516 this->bbt_td = &bbt_main_descr;
1517 this->bbt_md = &bbt_mirror_descr;
1518 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001519 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001520 }
1521
Sascha Hauer63f14742010-10-18 10:16:26 +02001522 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001523
1524 host->irq = platform_get_irq(pdev, 0);
Fabio Estevam26fbf482014-02-14 01:09:34 -02001525 if (host->irq < 0)
1526 return host->irq;
Ivo Claryssed4840182010-04-08 16:14:44 +02001527
Sascha Hauer63f14742010-10-18 10:16:26 +02001528 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001529 * Use host->devtype_data->irq_control() here instead of irq_control()
1530 * because we must not disable_irq_nosync without having requested the
1531 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001532 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001533 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001534
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001535 err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
Michael Opdenackerb1eb2342013-10-13 08:21:32 +02001536 0, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001537 if (err)
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001538 return err;
1539
Fabio Estevamdcedf622013-12-02 00:50:02 -02001540 err = clk_prepare_enable(host->clk);
1541 if (err)
1542 return err;
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001543 host->clk_act = 1;
Ivo Claryssed4840182010-04-08 16:14:44 +02001544
Sascha Hauer63f14742010-10-18 10:16:26 +02001545 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001546 * Now that we "own" the interrupt make sure the interrupt mask bit is
1547 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1548 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001549 */
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001550 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +02001551 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001552 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001553 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001554
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001555 /* first scan to find the device and get the page size */
Shawn Guo4d624352012-09-15 13:34:09 +08001556 if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001557 err = -ENXIO;
1558 goto escan;
1559 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001560
Huang Shijiea5900552013-12-21 00:02:27 +08001561 /* allocate the right size buffer now */
1562 devm_kfree(&pdev->dev, (void *)host->data_buf);
1563 host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
1564 GFP_KERNEL);
1565 if (!host->data_buf) {
1566 err = -ENOMEM;
1567 goto escan;
1568 }
1569
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001570 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001571 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001572
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001573 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001574 this->ecc.layout = host->devtype_data->ecclayout_2k;
1575 else if (mtd->writesize == 4096)
1576 this->ecc.layout = host->devtype_data->ecclayout_4k;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001577
Mike Dunn6a918ba2012-03-11 14:21:11 -07001578 if (this->ecc.mode == NAND_ECC_HW) {
Shawn Guo4d624352012-09-15 13:34:09 +08001579 if (is_imx21_nfc(host) || is_imx27_nfc(host))
Mike Dunn6a918ba2012-03-11 14:21:11 -07001580 this->ecc.strength = 1;
1581 else
1582 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1583 }
1584
Sascha Hauer4a43faf2012-05-25 16:22:42 +02001585 /* second phase scan */
1586 if (nand_scan_tail(mtd)) {
1587 err = -ENXIO;
1588 goto escan;
1589 }
1590
Sascha Hauer34f6e152008-09-02 17:16:59 +02001591 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001592 mtd_device_parse_register(mtd, part_probes,
1593 &(struct mtd_part_parser_data){
1594 .of_node = pdev->dev.of_node,
1595 },
1596 host->pdata.parts,
1597 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001598
1599 platform_set_drvdata(pdev, host);
1600
1601 return 0;
1602
1603escan:
Lothar Waßmannc10d8ee2012-12-06 08:42:27 +01001604 if (host->clk_act)
1605 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001606
1607 return err;
1608}
1609
Bill Pemberton810b7e02012-11-19 13:26:04 -05001610static int mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001611{
1612 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1613
Sascha Hauer34f6e152008-09-02 17:16:59 +02001614 nand_release(&host->mtd);
Wei Yongjun8bfd4f72013-12-17 11:35:35 +08001615 if (host->clk_act)
1616 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001617
1618 return 0;
1619}
1620
Sascha Hauer34f6e152008-09-02 17:16:59 +02001621static struct platform_driver mxcnd_driver = {
1622 .driver = {
1623 .name = DRIVER_NAME,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001624 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001625 },
Shawn Guo4d624352012-09-15 13:34:09 +08001626 .id_table = mxcnd_devtype,
Fabio Estevamddf16d62012-09-05 11:35:25 -03001627 .probe = mxcnd_probe,
Bill Pemberton5153b882012-11-19 13:21:24 -05001628 .remove = mxcnd_remove,
Sascha Hauer34f6e152008-09-02 17:16:59 +02001629};
Fabio Estevamddf16d62012-09-05 11:35:25 -03001630module_platform_driver(mxcnd_driver);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001631
1632MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1633MODULE_DESCRIPTION("MXC NAND MTD driver");
1634MODULE_LICENSE("GPL");