blob: ceeb61cad7d458bb00092e542e35fd6e5baaa9db [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 Siach7e7e4732015-05-13 11:17:37 +0300192 int used_oobsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200193 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200194
Sascha Hauer63f14742010-10-18 10:16:26 +0200195 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200196
197 uint8_t *data_buf;
198 unsigned int buf_start;
Sascha Hauer5f973042010-08-06 15:53:06 +0200199
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200200 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König64363562012-04-23 11:23:41 +0200201 struct mxc_nand_platform_data pdata;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200202};
203
Sascha Hauer34f6e152008-09-02 17:16:59 +0200204/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200205static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200206 .eccbytes = 5,
207 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200208 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200209};
210
Sascha Hauer94671142009-10-05 12:14:21 +0200211static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400212 .eccbytes = 20,
213 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
214 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
215 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200216};
217
Sascha Hauer94671142009-10-05 12:14:21 +0200218/* OOB description for 512 byte pages with 16 byte OOB */
219static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
220 .eccbytes = 1 * 9,
221 .eccpos = {
222 7, 8, 9, 10, 11, 12, 13, 14, 15
223 },
224 .oobfree = {
225 {.offset = 0, .length = 5}
226 }
227};
228
229/* OOB description for 2048 byte pages with 64 byte OOB */
230static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
231 .eccbytes = 4 * 9,
232 .eccpos = {
233 7, 8, 9, 10, 11, 12, 13, 14, 15,
234 23, 24, 25, 26, 27, 28, 29, 30, 31,
235 39, 40, 41, 42, 43, 44, 45, 46, 47,
236 55, 56, 57, 58, 59, 60, 61, 62, 63
237 },
238 .oobfree = {
239 {.offset = 2, .length = 4},
240 {.offset = 16, .length = 7},
241 {.offset = 32, .length = 7},
242 {.offset = 48, .length = 7}
243 }
244};
245
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200246/* OOB description for 4096 byte pages with 128 byte OOB */
247static struct nand_ecclayout nandv2_hw_eccoob_4k = {
248 .eccbytes = 8 * 9,
249 .eccpos = {
250 7, 8, 9, 10, 11, 12, 13, 14, 15,
251 23, 24, 25, 26, 27, 28, 29, 30, 31,
252 39, 40, 41, 42, 43, 44, 45, 46, 47,
253 55, 56, 57, 58, 59, 60, 61, 62, 63,
254 71, 72, 73, 74, 75, 76, 77, 78, 79,
255 87, 88, 89, 90, 91, 92, 93, 94, 95,
256 103, 104, 105, 106, 107, 108, 109, 110, 111,
257 119, 120, 121, 122, 123, 124, 125, 126, 127,
258 },
259 .oobfree = {
260 {.offset = 2, .length = 4},
261 {.offset = 16, .length = 7},
262 {.offset = 32, .length = 7},
263 {.offset = 48, .length = 7},
264 {.offset = 64, .length = 7},
265 {.offset = 80, .length = 7},
266 {.offset = 96, .length = 7},
267 {.offset = 112, .length = 7},
268 }
269};
270
Jingoo Hanb2ac0372013-08-07 16:18:52 +0900271static const char * const part_probes[] = {
Lothar Waßmann740bb0c2012-12-06 08:42:28 +0100272 "cmdlinepart", "RedBoot", "ofpart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200273
Sascha Hauer096bcc22012-05-29 10:16:09 +0200274static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
275{
276 int i;
277 u32 *t = trg;
278 const __iomem u32 *s = src;
279
280 for (i = 0; i < (size >> 2); i++)
281 *t++ = __raw_readl(s++);
282}
283
Koul, Vinod33a87a12014-10-20 21:36:13 +0530284static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200285{
Koul, Vinod33a87a12014-10-20 21:36:13 +0530286 /* __iowrite32_copy use 32bit size values so divide by 4 */
287 __iowrite32_copy(trg, src, size / 4);
Sascha Hauer096bcc22012-05-29 10:16:09 +0200288}
289
Sascha Hauer71ec5152010-08-06 15:53:11 +0200290static int check_int_v3(struct mxc_nand_host *host)
291{
292 uint32_t tmp;
293
294 tmp = readl(NFC_V3_IPC);
295 if (!(tmp & NFC_V3_IPC_INT))
296 return 0;
297
298 tmp &= ~NFC_V3_IPC_INT;
299 writel(tmp, NFC_V3_IPC);
300
301 return 1;
302}
303
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200304static int check_int_v1_v2(struct mxc_nand_host *host)
305{
306 uint32_t tmp;
307
Sascha Hauer1bc99182010-08-06 15:53:08 +0200308 tmp = readw(NFC_V1_V2_CONFIG2);
309 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200310 return 0;
311
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200312 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200313 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200314
315 return 1;
316}
317
Sascha Hauer63f14742010-10-18 10:16:26 +0200318static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
319{
320 uint16_t tmp;
321
322 tmp = readw(NFC_V1_V2_CONFIG1);
323
324 if (activate)
325 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
326 else
327 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
328
329 writew(tmp, NFC_V1_V2_CONFIG1);
330}
331
332static void irq_control_v3(struct mxc_nand_host *host, int activate)
333{
334 uint32_t tmp;
335
336 tmp = readl(NFC_V3_CONFIG2);
337
338 if (activate)
339 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
340 else
341 tmp |= NFC_V3_CONFIG2_INT_MSK;
342
343 writel(tmp, NFC_V3_CONFIG2);
344}
345
Uwe Kleine-König85569582012-04-23 11:23:34 +0200346static void irq_control(struct mxc_nand_host *host, int activate)
347{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200348 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200349 if (activate)
350 enable_irq(host->irq);
351 else
352 disable_irq_nosync(host->irq);
353 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200354 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200355 }
356}
357
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200358static u32 get_ecc_status_v1(struct mxc_nand_host *host)
359{
360 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
361}
362
363static u32 get_ecc_status_v2(struct mxc_nand_host *host)
364{
365 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
366}
367
368static u32 get_ecc_status_v3(struct mxc_nand_host *host)
369{
370 return readl(NFC_V3_ECC_STATUS_RESULT);
371}
372
Uwe Kleine-König85569582012-04-23 11:23:34 +0200373static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
374{
375 struct mxc_nand_host *host = dev_id;
376
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200377 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200378 return IRQ_NONE;
379
380 irq_control(host, 0);
381
382 complete(&host->op_completion);
383
384 return IRQ_HANDLED;
385}
386
Sascha Hauer34f6e152008-09-02 17:16:59 +0200387/* This function polls the NANDFC to wait for the basic operation to
388 * complete by checking the INT bit of config2 register.
389 */
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100390static int wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200391{
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100392 int ret = 0;
393
394 /*
395 * If operation is already complete, don't bother to setup an irq or a
396 * loop.
397 */
398 if (host->devtype_data->check_int(host))
399 return 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200400
401 if (useirq) {
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100402 unsigned long timeout;
403
404 reinit_completion(&host->op_completion);
405
406 irq_control(host, 1);
407
408 timeout = wait_for_completion_timeout(&host->op_completion, HZ);
409 if (!timeout && !host->devtype_data->check_int(host)) {
410 dev_dbg(host->dev, "timeout waiting for irq\n");
411 ret = -ETIMEDOUT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200412 }
413 } else {
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100414 int max_retries = 8000;
415 int done;
416
417 do {
418 udelay(1);
419
420 done = host->devtype_data->check_int(host);
421 if (done)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200422 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200423
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100424 } while (--max_retries);
425
426 if (!done) {
427 dev_dbg(host->dev, "timeout polling for completion\n");
428 ret = -ETIMEDOUT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200429 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200430 }
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100431
432 WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq);
433
434 return ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200435}
436
Sascha Hauer71ec5152010-08-06 15:53:11 +0200437static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
438{
439 /* fill command */
440 writel(cmd, NFC_V3_FLASH_CMD);
441
442 /* send out command */
443 writel(NFC_CMD, NFC_V3_LAUNCH);
444
445 /* Wait for operation to complete */
446 wait_op_done(host, useirq);
447}
448
Sascha Hauer34f6e152008-09-02 17:16:59 +0200449/* This function issues the specified command to the NAND device and
450 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200451static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200452{
Brian Norris289c0522011-07-19 10:06:09 -0700453 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200454
Sascha Hauer1bc99182010-08-06 15:53:08 +0200455 writew(cmd, NFC_V1_V2_FLASH_CMD);
456 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200457
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200458 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200459 int max_retries = 100;
460 /* Reset completion is indicated by NFC_CONFIG2 */
461 /* being set to 0 */
462 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200463 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200464 break;
465 }
466 udelay(1);
467 }
468 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700469 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200470 } else {
471 /* Wait for operation to complete */
472 wait_op_done(host, useirq);
473 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200474}
475
Sascha Hauer71ec5152010-08-06 15:53:11 +0200476static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
477{
478 /* fill address */
479 writel(addr, NFC_V3_FLASH_ADDR0);
480
481 /* send out address */
482 writel(NFC_ADDR, NFC_V3_LAUNCH);
483
484 wait_op_done(host, 0);
485}
486
Sascha Hauer34f6e152008-09-02 17:16:59 +0200487/* This function sends an address (or partial address) to the
488 * NAND device. The address is used to select the source/destination for
489 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200490static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200491{
Brian Norris289c0522011-07-19 10:06:09 -0700492 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200493
Sascha Hauer1bc99182010-08-06 15:53:08 +0200494 writew(addr, NFC_V1_V2_FLASH_ADDR);
495 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200496
497 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200498 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200499}
500
Sascha Hauer71ec5152010-08-06 15:53:11 +0200501static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
502{
503 struct nand_chip *nand_chip = mtd->priv;
504 struct mxc_nand_host *host = nand_chip->priv;
505 uint32_t tmp;
506
507 tmp = readl(NFC_V3_CONFIG1);
508 tmp &= ~(7 << 4);
509 writel(tmp, NFC_V3_CONFIG1);
510
511 /* transfer data from NFC ram to nand */
512 writel(ops, NFC_V3_LAUNCH);
513
514 wait_op_done(host, false);
515}
516
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200517static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
518{
519 struct nand_chip *nand_chip = mtd->priv;
520 struct mxc_nand_host *host = nand_chip->priv;
521
522 /* NANDFC buffer 0 is used for page read/write */
523 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
524
525 writew(ops, NFC_V1_V2_CONFIG2);
526
527 /* Wait for operation to complete */
528 wait_op_done(host, true);
529}
530
531static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200532{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200533 struct nand_chip *nand_chip = mtd->priv;
534 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200535 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200536
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200537 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200538 bufs = 4;
539 else
540 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200541
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200542 for (i = 0; i < bufs; i++) {
543
544 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200545 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200546
Sascha Hauer1bc99182010-08-06 15:53:08 +0200547 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200548
549 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200550 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200552}
553
Sascha Hauer71ec5152010-08-06 15:53:11 +0200554static void send_read_id_v3(struct mxc_nand_host *host)
555{
556 /* Read ID into main buffer */
557 writel(NFC_ID, NFC_V3_LAUNCH);
558
559 wait_op_done(host, true);
560
Sascha Hauer096bcc22012-05-29 10:16:09 +0200561 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Sascha Hauer71ec5152010-08-06 15:53:11 +0200562}
563
Sascha Hauer34f6e152008-09-02 17:16:59 +0200564/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200565static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200566{
Sascha Hauer34f6e152008-09-02 17:16:59 +0200567 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200568 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200569
Sascha Hauer1bc99182010-08-06 15:53:08 +0200570 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200571
572 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200573 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200574
Sascha Hauer096bcc22012-05-29 10:16:09 +0200575 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200576}
577
Sascha Hauer71ec5152010-08-06 15:53:11 +0200578static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200579{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200580 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200581 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200582
Sascha Hauer71ec5152010-08-06 15:53:11 +0200583 return readl(NFC_V3_CONFIG1) >> 16;
584}
585
Sascha Hauer34f6e152008-09-02 17:16:59 +0200586/* This function requests the NANDFC to perform a read of the
587 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200588static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200589{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200590 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200591 uint32_t store;
592 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200593
Baruch Siachd178e3e2011-03-14 09:01:56 +0200594 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200595
596 /*
597 * The device status is stored in main_area0. To
598 * prevent corruption of the buffer save the value
599 * and restore it afterwards.
600 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200601 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200602
Sascha Hauer1bc99182010-08-06 15:53:08 +0200603 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200604 wait_op_done(host, true);
605
Sascha Hauer34f6e152008-09-02 17:16:59 +0200606 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200607
Sascha Hauer34f6e152008-09-02 17:16:59 +0200608 writel(store, main_buf);
609
610 return ret;
611}
612
613/* This functions is used by upper layer to checks if device is ready */
614static int mxc_nand_dev_ready(struct mtd_info *mtd)
615{
616 /*
617 * NFC handles R/B internally. Therefore, this function
618 * always returns status as ready.
619 */
620 return 1;
621}
622
623static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
624{
625 /*
626 * If HW ECC is enabled, we turn it on during init. There is
627 * no need to enable again here.
628 */
629}
630
Sascha Hauer94f77e52010-08-06 15:53:09 +0200631static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200632 u_char *read_ecc, u_char *calc_ecc)
633{
634 struct nand_chip *nand_chip = mtd->priv;
635 struct mxc_nand_host *host = nand_chip->priv;
636
637 /*
638 * 1-Bit errors are automatically corrected in HW. No need for
639 * additional correction. 2-Bit errors cannot be corrected by
640 * HW ECC, so we need to return failure
641 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200642 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200643
644 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700645 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200646 return -1;
647 }
648
649 return 0;
650}
651
Sascha Hauer94f77e52010-08-06 15:53:09 +0200652static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
653 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 u32 ecc_stat, err;
658 int no_subpages = 1;
659 int ret = 0;
660 u8 ecc_bit_mask, err_limit;
661
662 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
663 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
664
665 no_subpages = mtd->writesize >> 9;
666
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200667 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200668
669 do {
670 err = ecc_stat & ecc_bit_mask;
671 if (err > err_limit) {
672 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
673 return -1;
674 } else {
675 ret += err;
676 }
677 ecc_stat >>= 4;
678 } while (--no_subpages);
679
Sascha Hauer94f77e52010-08-06 15:53:09 +0200680 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
681
682 return ret;
683}
684
Sascha Hauer34f6e152008-09-02 17:16:59 +0200685static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
686 u_char *ecc_code)
687{
688 return 0;
689}
690
691static u_char mxc_nand_read_byte(struct mtd_info *mtd)
692{
693 struct nand_chip *nand_chip = mtd->priv;
694 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200695 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200696
697 /* Check for status request */
698 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200699 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200700
Uwe Kleine-König3f410692015-02-10 19:59:57 +0100701 if (nand_chip->options & NAND_BUSWIDTH_16) {
702 /* only take the lower byte of each word */
703 ret = *(uint16_t *)(host->data_buf + host->buf_start);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200704
Uwe Kleine-König3f410692015-02-10 19:59:57 +0100705 host->buf_start += 2;
706 } else {
707 ret = *(uint8_t *)(host->data_buf + host->buf_start);
708 host->buf_start++;
709 }
710
711 pr_debug("%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200712 return ret;
713}
714
715static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
716{
717 struct nand_chip *nand_chip = mtd->priv;
718 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200719 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200720
Sascha Hauerf8f96082009-06-04 17:12:26 +0200721 ret = *(uint16_t *)(host->data_buf + host->buf_start);
722 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200723
724 return ret;
725}
726
727/* Write data of length len to buffer buf. The data to be
728 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
729 * Operation by the NFC, the data is written to NAND Flash */
730static void mxc_nand_write_buf(struct mtd_info *mtd,
731 const u_char *buf, int len)
732{
733 struct nand_chip *nand_chip = mtd->priv;
734 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200735 u16 col = host->buf_start;
736 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200737
Sascha Hauerf8f96082009-06-04 17:12:26 +0200738 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200739
Sascha Hauerf8f96082009-06-04 17:12:26 +0200740 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200741
Sascha Hauerf8f96082009-06-04 17:12:26 +0200742 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200743}
744
745/* Read the data buffer from the NAND Flash. To read the data from NAND
746 * Flash first the data output cycle is initiated by the NFC, which copies
747 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
748 */
749static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
750{
751 struct nand_chip *nand_chip = mtd->priv;
752 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200753 u16 col = host->buf_start;
754 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200755
Sascha Hauerf8f96082009-06-04 17:12:26 +0200756 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200757
Baruch Siach5d9d9932011-03-02 16:47:55 +0200758 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200759
Baruch Siach5d9d9932011-03-02 16:47:55 +0200760 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200761}
762
Sascha Hauer34f6e152008-09-02 17:16:59 +0200763/* This function is used by upper layer for select and
764 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200765static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200766{
767 struct nand_chip *nand_chip = mtd->priv;
768 struct mxc_nand_host *host = nand_chip->priv;
769
Baruch Siachd178e3e2011-03-14 09:01:56 +0200770 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200771 /* Disable the NFC clock */
772 if (host->clk_act) {
Sascha Hauer97c32132012-03-07 20:56:35 +0100773 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200774 host->clk_act = 0;
775 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200776 return;
777 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200778
Baruch Siachd178e3e2011-03-14 09:01:56 +0200779 if (!host->clk_act) {
780 /* Enable the NFC clock */
Sascha Hauer97c32132012-03-07 20:56:35 +0100781 clk_prepare_enable(host->clk);
Baruch Siachd178e3e2011-03-14 09:01:56 +0200782 host->clk_act = 1;
783 }
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200784}
Baruch Siachd178e3e2011-03-14 09:01:56 +0200785
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200786static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200787{
788 struct nand_chip *nand_chip = mtd->priv;
789 struct mxc_nand_host *host = nand_chip->priv;
790
791 if (chip == -1) {
792 /* Disable the NFC clock */
793 if (host->clk_act) {
Fabio Estevam3d059692012-05-25 20:14:50 -0300794 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200795 host->clk_act = 0;
796 }
797 return;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200798 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200799
800 if (!host->clk_act) {
801 /* Enable the NFC clock */
Fabio Estevam3d059692012-05-25 20:14:50 -0300802 clk_prepare_enable(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200803 host->clk_act = 1;
804 }
805
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200806 host->active_cs = chip;
807 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200808}
809
Sascha Hauerf8f96082009-06-04 17:12:26 +0200810/*
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300811 * The controller splits a page into data chunks of 512 bytes + partial oob.
812 * There are writesize / 512 such chunks, the size of the partial oob parts is
813 * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then
814 * contains additionally the byte lost by rounding (if any).
815 * This function handles the needed shuffling between host->data_buf (which
816 * holds a page in natural order, i.e. writesize bytes data + oobsize bytes
817 * spare) and the NFC buffer.
Sascha Hauerf8f96082009-06-04 17:12:26 +0200818 */
819static void copy_spare(struct mtd_info *mtd, bool bfrom)
820{
821 struct nand_chip *this = mtd->priv;
822 struct mxc_nand_host *host = this->priv;
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300823 u16 i, oob_chunk_size;
824 u16 num_chunks = mtd->writesize / 512;
825
Sascha Hauerf8f96082009-06-04 17:12:26 +0200826 u8 *d = host->data_buf + mtd->writesize;
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200827 u8 __iomem *s = host->spare0;
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300828 u16 sparebuf_size = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200829
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300830 /* size of oob chunk for all but possibly the last one */
Baruch Siach7e7e4732015-05-13 11:17:37 +0300831 oob_chunk_size = (host->used_oobsize / num_chunks) & ~1;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200832
833 if (bfrom) {
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300834 for (i = 0; i < num_chunks - 1; i++)
835 memcpy32_fromio(d + i * oob_chunk_size,
836 s + i * sparebuf_size,
837 oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200838
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300839 /* the last chunk */
840 memcpy32_fromio(d + i * oob_chunk_size,
841 s + i * sparebuf_size,
Baruch Siach7e7e4732015-05-13 11:17:37 +0300842 host->used_oobsize - i * oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200843 } else {
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300844 for (i = 0; i < num_chunks - 1; i++)
845 memcpy32_toio(&s[i * sparebuf_size],
846 &d[i * oob_chunk_size],
847 oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200848
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300849 /* the last chunk */
850 memcpy32_toio(&s[oob_chunk_size * sparebuf_size],
851 &d[i * oob_chunk_size],
Baruch Siach7e7e4732015-05-13 11:17:37 +0300852 host->used_oobsize - i * oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200853 }
854}
855
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100856/*
857 * MXC NANDFC can only perform full page+spare or spare-only read/write. When
858 * the upper layers perform a read/write buf operation, the saved column address
859 * is used to index into the full page. So usually this function is called with
860 * column == 0 (unless no column cycle is needed indicated by column == -1)
861 */
Sascha Hauera3e65b62009-06-02 11:47:59 +0200862static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200863{
864 struct nand_chip *nand_chip = mtd->priv;
865 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200866
867 /* Write out column address, if necessary */
868 if (column != -1) {
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100869 host->devtype_data->send_addr(host, column & 0xff,
870 page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200871 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200872 /* another col addr cycle for 2k page */
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100873 host->devtype_data->send_addr(host,
874 (column >> 8) & 0xff,
875 false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200876 }
877
878 /* Write out page address, if necessary */
879 if (page_addr != -1) {
880 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200881 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200882
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200883 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400884 if (mtd->size >= 0x10000000) {
885 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200886 host->devtype_data->send_addr(host,
887 (page_addr >> 8) & 0xff,
888 false);
889 host->devtype_data->send_addr(host,
890 (page_addr >> 16) & 0xff,
891 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400892 } else
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, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200896 } else {
897 /* One more address cycle for higher density devices */
898 if (mtd->size >= 0x4000000) {
899 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200900 host->devtype_data->send_addr(host,
901 (page_addr >> 8) & 0xff,
902 false);
903 host->devtype_data->send_addr(host,
904 (page_addr >> 16) & 0xff,
905 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200906 } else
907 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200908 host->devtype_data->send_addr(host,
909 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200910 }
911 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200912}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200913
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200914/*
915 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
916 * on how much oob the nand chip has. For 8bit ecc we need at least
917 * 26 bytes of oob data per 512 byte block.
918 */
919static int get_eccsize(struct mtd_info *mtd)
920{
921 int oobbytes_per_512 = 0;
922
923 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
924
925 if (oobbytes_per_512 < 26)
926 return 4;
927 else
928 return 8;
929}
930
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200931static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200932{
933 struct nand_chip *nand_chip = mtd->priv;
934 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200935 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200936
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +0100937 if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200938 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
939
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200940 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200941 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200942
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200943 host->eccsize = 1;
944
945 writew(config1, NFC_V1_V2_CONFIG1);
946 /* preset operation */
947
948 /* Unlock the internal RAM Buffer */
949 writew(0x2, NFC_V1_V2_CONFIG);
950
951 /* Blocks to be unlocked */
952 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
953 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
954
955 /* Unlock Block Command for given address range */
956 writew(0x4, NFC_V1_V2_WRPROT);
957}
958
959static void preset_v2(struct mtd_info *mtd)
960{
961 struct nand_chip *nand_chip = mtd->priv;
962 struct mxc_nand_host *host = nand_chip->priv;
963 uint16_t config1 = 0;
964
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200965 config1 |= NFC_V2_CONFIG1_FP_INT;
Ivo Claryssed4840182010-04-08 16:14:44 +0200966
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200967 if (!host->devtype_data->irqpending_quirk)
Ivo Claryssed4840182010-04-08 16:14:44 +0200968 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200969
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200970 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200971 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
972
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +0100973 if (nand_chip->ecc.mode == NAND_ECC_HW)
974 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
975
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200976 host->eccsize = get_eccsize(mtd);
977 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200978 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
979
980 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200981 } else {
982 host->eccsize = 1;
983 }
984
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200985 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200986 /* preset operation */
987
988 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200989 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200990
991 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200992 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
993 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
994 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
995 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
996 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
997 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
998 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
999 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +02001000
1001 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +02001002 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +02001003}
1004
Sascha Hauer71ec5152010-08-06 15:53:11 +02001005static void preset_v3(struct mtd_info *mtd)
1006{
1007 struct nand_chip *chip = mtd->priv;
1008 struct mxc_nand_host *host = chip->priv;
1009 uint32_t config2, config3;
1010 int i, addr_phases;
1011
1012 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
1013 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
1014
1015 /* Unlock the internal RAM Buffer */
1016 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
1017 NFC_V3_WRPROT);
1018
1019 /* Blocks to be unlocked */
1020 for (i = 0; i < NAND_MAX_CHIPS; i++)
1021 writel(0x0 | (0xffff << 16),
1022 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
1023
1024 writel(0, NFC_V3_IPC);
1025
1026 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
1027 NFC_V3_CONFIG2_2CMD_PHASES |
1028 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
1029 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +02001030 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +02001031 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
1032
Sascha Hauer71ec5152010-08-06 15:53:11 +02001033 addr_phases = fls(chip->pagemask) >> 3;
1034
1035 if (mtd->writesize == 2048) {
1036 config2 |= NFC_V3_CONFIG2_PS_2048;
1037 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1038 } else if (mtd->writesize == 4096) {
1039 config2 |= NFC_V3_CONFIG2_PS_4096;
1040 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1041 } else {
1042 config2 |= NFC_V3_CONFIG2_PS_512;
1043 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1044 }
1045
1046 if (mtd->writesize) {
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +01001047 if (chip->ecc.mode == NAND_ECC_HW)
1048 config2 |= NFC_V3_CONFIG2_ECC_EN;
1049
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001050 config2 |= NFC_V3_CONFIG2_PPB(
1051 ffs(mtd->erasesize / mtd->writesize) - 6,
1052 host->devtype_data->ppb_shift);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001053 host->eccsize = get_eccsize(mtd);
1054 if (host->eccsize == 8)
1055 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
1056 }
1057
1058 writel(config2, NFC_V3_CONFIG2);
1059
1060 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1061 NFC_V3_CONFIG3_NO_SDMA |
1062 NFC_V3_CONFIG3_RBB_MODE |
1063 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1064 NFC_V3_CONFIG3_ADD_OP(0);
1065
1066 if (!(chip->options & NAND_BUSWIDTH_16))
1067 config3 |= NFC_V3_CONFIG3_FW8;
1068
1069 writel(config3, NFC_V3_CONFIG3);
1070
1071 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001072}
1073
Sascha Hauer34f6e152008-09-02 17:16:59 +02001074/* Used by the upper layer to write command to NAND Flash for
1075 * different operations to be carried out on NAND Flash */
1076static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1077 int column, int page_addr)
1078{
1079 struct nand_chip *nand_chip = mtd->priv;
1080 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001081
Brian Norris289c0522011-07-19 10:06:09 -07001082 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001083 command, column, page_addr);
1084
1085 /* Reset command state information */
1086 host->status_request = false;
1087
1088 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001089 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001090 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001091 host->devtype_data->preset(mtd);
1092 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001093 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001094
Sascha Hauer34f6e152008-09-02 17:16:59 +02001095 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001096 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001097 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001098
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001099 host->devtype_data->send_cmd(host, command, true);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001100 WARN_ONCE(column != -1 || page_addr != -1,
1101 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1102 command, column, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001103 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001104 break;
1105
Sascha Hauer34f6e152008-09-02 17:16:59 +02001106 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001107 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001108 if (command == NAND_CMD_READ0)
1109 host->buf_start = column;
1110 else
1111 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001112
Sascha Hauer5ea32022010-04-27 15:24:01 +02001113 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001114
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001115 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001116 WARN_ONCE(column < 0,
1117 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1118 command, column, page_addr);
1119 mxc_do_addr_cycle(mtd, 0, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001120
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001121 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001122 host->devtype_data->send_cmd(host,
1123 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001124
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001125 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001126
Sascha Hauer096bcc22012-05-29 10:16:09 +02001127 memcpy32_fromio(host->data_buf, host->main_area0,
1128 mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001129 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001130 break;
1131
Sascha Hauer34f6e152008-09-02 17:16:59 +02001132 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001133 if (column >= mtd->writesize)
1134 /* call ourself to read a page */
1135 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001136
Sascha Hauer5ea32022010-04-27 15:24:01 +02001137 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001138
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001139 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001140 WARN_ONCE(column < -1,
1141 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1142 command, column, page_addr);
1143 mxc_do_addr_cycle(mtd, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001144 break;
1145
1146 case NAND_CMD_PAGEPROG:
Sascha Hauer096bcc22012-05-29 10:16:09 +02001147 memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001148 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001149 host->devtype_data->send_page(mtd, NFC_INPUT);
1150 host->devtype_data->send_cmd(host, command, true);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001151 WARN_ONCE(column != -1 || page_addr != -1,
1152 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1153 command, column, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001154 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001155 break;
1156
Sascha Hauer34f6e152008-09-02 17:16:59 +02001157 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001158 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001159 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001160 host->devtype_data->send_read_id(host);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001161 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001162 break;
1163
Sascha Hauer89121a62009-06-04 17:18:01 +02001164 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001165 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001166 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001167 WARN_ONCE(column != -1,
1168 "Unexpected column value (cmd=%u, col=%d)\n",
1169 command, column);
Sascha Hauer89121a62009-06-04 17:18:01 +02001170 mxc_do_addr_cycle(mtd, column, page_addr);
1171
Sascha Hauer34f6e152008-09-02 17:16:59 +02001172 break;
Uwe Kleine-König3d6e81c2015-02-10 19:59:59 +01001173 case NAND_CMD_PARAM:
1174 host->devtype_data->send_cmd(host, command, false);
1175 mxc_do_addr_cycle(mtd, column, page_addr);
1176 host->devtype_data->send_page(mtd, NFC_OUTPUT);
1177 memcpy32_fromio(host->data_buf, host->main_area0, 512);
1178 host->buf_start = 0;
1179 break;
Uwe Kleine-König98ebb522015-02-10 20:00:00 +01001180 default:
1181 WARN_ONCE(1, "Unimplemented command (cmd=%u)\n",
1182 command);
1183 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001184 }
1185}
1186
Sascha Hauerf1372052009-10-21 14:25:27 +02001187/*
1188 * The generic flash bbt decriptors overlap with our ecc
1189 * hardware, so define some i.MX specific ones.
1190 */
1191static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1192static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1193
1194static struct nand_bbt_descr bbt_main_descr = {
1195 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1196 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1197 .offs = 0,
1198 .len = 4,
1199 .veroffs = 4,
1200 .maxblocks = 4,
1201 .pattern = bbt_pattern,
1202};
1203
1204static struct nand_bbt_descr bbt_mirror_descr = {
1205 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1206 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1207 .offs = 0,
1208 .len = 4,
1209 .veroffs = 4,
1210 .maxblocks = 4,
1211 .pattern = mirror_pattern,
1212};
1213
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001214/* v1 + irqpending_quirk: i.MX21 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001215static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001216 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001217 .send_cmd = send_cmd_v1_v2,
1218 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001219 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001220 .send_read_id = send_read_id_v1_v2,
1221 .get_dev_status = get_dev_status_v1_v2,
1222 .check_int = check_int_v1_v2,
1223 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001224 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001225 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1226 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1227 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001228 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001229 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001230 .irqpending_quirk = 1,
1231 .needs_ip = 0,
1232 .regs_offset = 0xe00,
1233 .spare0_offset = 0x800,
1234 .spare_len = 16,
1235 .eccbytes = 3,
1236 .eccsize = 1,
1237};
1238
1239/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1240static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1241 .preset = preset_v1,
1242 .send_cmd = send_cmd_v1_v2,
1243 .send_addr = send_addr_v1_v2,
1244 .send_page = send_page_v1,
1245 .send_read_id = send_read_id_v1_v2,
1246 .get_dev_status = get_dev_status_v1_v2,
1247 .check_int = check_int_v1_v2,
1248 .irq_control = irq_control_v1_v2,
1249 .get_ecc_status = get_ecc_status_v1,
1250 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1251 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1252 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1253 .select_chip = mxc_nand_select_chip_v1_v3,
1254 .correct_data = mxc_nand_correct_data_v1,
1255 .irqpending_quirk = 0,
1256 .needs_ip = 0,
1257 .regs_offset = 0xe00,
1258 .spare0_offset = 0x800,
1259 .axi_offset = 0,
1260 .spare_len = 16,
1261 .eccbytes = 3,
1262 .eccsize = 1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001263};
1264
1265/* v21: i.MX25, i.MX35 */
1266static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001267 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001268 .send_cmd = send_cmd_v1_v2,
1269 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001270 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001271 .send_read_id = send_read_id_v1_v2,
1272 .get_dev_status = get_dev_status_v1_v2,
1273 .check_int = check_int_v1_v2,
1274 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001275 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001276 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1277 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1278 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001279 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001280 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001281 .irqpending_quirk = 0,
1282 .needs_ip = 0,
1283 .regs_offset = 0x1e00,
1284 .spare0_offset = 0x1000,
1285 .axi_offset = 0,
1286 .spare_len = 64,
1287 .eccbytes = 9,
1288 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001289};
1290
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001291/* v3.2a: i.MX51 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001292static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1293 .preset = preset_v3,
1294 .send_cmd = send_cmd_v3,
1295 .send_addr = send_addr_v3,
1296 .send_page = send_page_v3,
1297 .send_read_id = send_read_id_v3,
1298 .get_dev_status = get_dev_status_v3,
1299 .check_int = check_int_v3,
1300 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001301 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001302 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1303 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1304 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001305 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001306 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001307 .irqpending_quirk = 0,
1308 .needs_ip = 1,
1309 .regs_offset = 0,
1310 .spare0_offset = 0x1000,
1311 .axi_offset = 0x1e00,
1312 .spare_len = 64,
1313 .eccbytes = 0,
1314 .eccsize = 0,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001315 .ppb_shift = 7,
1316};
1317
1318/* v3.2b: i.MX53 */
1319static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
1320 .preset = preset_v3,
1321 .send_cmd = send_cmd_v3,
1322 .send_addr = send_addr_v3,
1323 .send_page = send_page_v3,
1324 .send_read_id = send_read_id_v3,
1325 .get_dev_status = get_dev_status_v3,
1326 .check_int = check_int_v3,
1327 .irq_control = irq_control_v3,
1328 .get_ecc_status = get_ecc_status_v3,
1329 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1330 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1331 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1332 .select_chip = mxc_nand_select_chip_v1_v3,
1333 .correct_data = mxc_nand_correct_data_v2_v3,
1334 .irqpending_quirk = 0,
1335 .needs_ip = 1,
1336 .regs_offset = 0,
1337 .spare0_offset = 0x1000,
1338 .axi_offset = 0x1e00,
1339 .spare_len = 64,
1340 .eccbytes = 0,
1341 .eccsize = 0,
1342 .ppb_shift = 8,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001343};
1344
Shawn Guo4d624352012-09-15 13:34:09 +08001345static inline int is_imx21_nfc(struct mxc_nand_host *host)
1346{
1347 return host->devtype_data == &imx21_nand_devtype_data;
1348}
1349
1350static inline int is_imx27_nfc(struct mxc_nand_host *host)
1351{
1352 return host->devtype_data == &imx27_nand_devtype_data;
1353}
1354
1355static inline int is_imx25_nfc(struct mxc_nand_host *host)
1356{
1357 return host->devtype_data == &imx25_nand_devtype_data;
1358}
1359
1360static inline int is_imx51_nfc(struct mxc_nand_host *host)
1361{
1362 return host->devtype_data == &imx51_nand_devtype_data;
1363}
1364
1365static inline int is_imx53_nfc(struct mxc_nand_host *host)
1366{
1367 return host->devtype_data == &imx53_nand_devtype_data;
1368}
1369
Krzysztof Kozlowski8d1e5682015-05-02 00:50:01 +09001370static const struct platform_device_id mxcnd_devtype[] = {
Shawn Guo4d624352012-09-15 13:34:09 +08001371 {
1372 .name = "imx21-nand",
1373 .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
1374 }, {
1375 .name = "imx27-nand",
1376 .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
1377 }, {
1378 .name = "imx25-nand",
1379 .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
1380 }, {
1381 .name = "imx51-nand",
1382 .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
1383 }, {
1384 .name = "imx53-nand",
1385 .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
1386 }, {
1387 /* sentinel */
1388 }
1389};
1390MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
1391
Uwe Kleine-König64363562012-04-23 11:23:41 +02001392#ifdef CONFIG_OF_MTD
1393static const struct of_device_id mxcnd_dt_ids[] = {
1394 {
1395 .compatible = "fsl,imx21-nand",
1396 .data = &imx21_nand_devtype_data,
1397 }, {
1398 .compatible = "fsl,imx27-nand",
1399 .data = &imx27_nand_devtype_data,
1400 }, {
1401 .compatible = "fsl,imx25-nand",
1402 .data = &imx25_nand_devtype_data,
1403 }, {
1404 .compatible = "fsl,imx51-nand",
1405 .data = &imx51_nand_devtype_data,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001406 }, {
1407 .compatible = "fsl,imx53-nand",
1408 .data = &imx53_nand_devtype_data,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001409 },
1410 { /* sentinel */ }
1411};
1412
1413static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1414{
1415 struct device_node *np = host->dev->of_node;
1416 struct mxc_nand_platform_data *pdata = &host->pdata;
1417 const struct of_device_id *of_id =
1418 of_match_device(mxcnd_dt_ids, host->dev);
1419 int buswidth;
1420
1421 if (!np)
1422 return 1;
1423
1424 if (of_get_nand_ecc_mode(np) >= 0)
1425 pdata->hw_ecc = 1;
1426
1427 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1428
1429 buswidth = of_get_nand_bus_width(np);
1430 if (buswidth < 0)
1431 return buswidth;
1432
1433 pdata->width = buswidth / 8;
1434
1435 host->devtype_data = of_id->data;
1436
1437 return 0;
1438}
1439#else
1440static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1441{
1442 return 1;
1443}
1444#endif
1445
Bill Pemberton06f25512012-11-19 13:23:07 -05001446static int mxcnd_probe(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001447{
1448 struct nand_chip *this;
1449 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001450 struct mxc_nand_host *host;
1451 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001452 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001453
1454 /* Allocate memory for MTD device structure and private data */
Huang Shijiea5900552013-12-21 00:02:27 +08001455 host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
1456 GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001457 if (!host)
1458 return -ENOMEM;
1459
Huang Shijiea5900552013-12-21 00:02:27 +08001460 /* allocate a temporary buffer for the nand_scan_ident() */
1461 host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
1462 if (!host->data_buf)
1463 return -ENOMEM;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001464
Sascha Hauer34f6e152008-09-02 17:16:59 +02001465 host->dev = &pdev->dev;
1466 /* structures must be linked */
1467 this = &host->nand;
1468 mtd = &host->mtd;
1469 mtd->priv = this;
1470 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001471 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001472 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001473
1474 /* 50 us command delay time */
1475 this->chip_delay = 5;
1476
1477 this->priv = host;
1478 this->dev_ready = mxc_nand_dev_ready;
1479 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001480 this->read_byte = mxc_nand_read_byte;
1481 this->read_word = mxc_nand_read_word;
1482 this->write_buf = mxc_nand_write_buf;
1483 this->read_buf = mxc_nand_read_buf;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001484
Fabio Estevam24b82d32012-09-05 11:52:27 -03001485 host->clk = devm_clk_get(&pdev->dev, NULL);
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001486 if (IS_ERR(host->clk))
1487 return PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001488
Sascha Hauer71885b62012-06-06 12:33:14 +02001489 err = mxcnd_probe_dt(host);
Shawn Guo4d624352012-09-15 13:34:09 +08001490 if (err > 0) {
Jingoo Han453810b2013-07-30 17:18:33 +09001491 struct mxc_nand_platform_data *pdata =
1492 dev_get_platdata(&pdev->dev);
Shawn Guo4d624352012-09-15 13:34:09 +08001493 if (pdata) {
1494 host->pdata = *pdata;
1495 host->devtype_data = (struct mxc_nand_devtype_data *)
1496 pdev->id_entry->driver_data;
1497 } else {
1498 err = -ENODEV;
1499 }
1500 }
Sascha Hauer71885b62012-06-06 12:33:14 +02001501 if (err < 0)
1502 return err;
1503
1504 if (host->devtype_data->needs_ip) {
1505 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Thierry Redingb0de7742013-01-21 11:09:12 +01001506 host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
1507 if (IS_ERR(host->regs_ip))
1508 return PTR_ERR(host->regs_ip);
Sascha Hauer71885b62012-06-06 12:33:14 +02001509
1510 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1511 } else {
1512 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1513 }
1514
Thierry Redingb0de7742013-01-21 11:09:12 +01001515 host->base = devm_ioremap_resource(&pdev->dev, res);
1516 if (IS_ERR(host->base))
1517 return PTR_ERR(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001518
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001519 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001520
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001521 if (host->devtype_data->regs_offset)
1522 host->regs = host->base + host->devtype_data->regs_offset;
1523 host->spare0 = host->base + host->devtype_data->spare0_offset;
1524 if (host->devtype_data->axi_offset)
1525 host->regs_axi = host->base + host->devtype_data->axi_offset;
1526
1527 this->ecc.bytes = host->devtype_data->eccbytes;
1528 host->eccsize = host->devtype_data->eccsize;
1529
1530 this->select_chip = host->devtype_data->select_chip;
1531 this->ecc.size = 512;
1532 this->ecc.layout = host->devtype_data->ecclayout_512;
1533
Uwe Kleine-König64363562012-04-23 11:23:41 +02001534 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001535 this->ecc.calculate = mxc_nand_calculate_ecc;
1536 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001537 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001538 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001539 } else {
1540 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001541 }
1542
Uwe Kleine-König64363562012-04-23 11:23:41 +02001543 /* NAND bus width determines access functions used by upper layer */
1544 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001545 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001546
Uwe Kleine-König64363562012-04-23 11:23:41 +02001547 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001548 this->bbt_td = &bbt_main_descr;
1549 this->bbt_md = &bbt_mirror_descr;
1550 /* update flash based bbt */
Brian Norrisbb9ebd4e2011-05-31 16:31:23 -07001551 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001552 }
1553
Sascha Hauer63f14742010-10-18 10:16:26 +02001554 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001555
1556 host->irq = platform_get_irq(pdev, 0);
Fabio Estevam26fbf482014-02-14 01:09:34 -02001557 if (host->irq < 0)
1558 return host->irq;
Ivo Claryssed4840182010-04-08 16:14:44 +02001559
Sascha Hauer63f14742010-10-18 10:16:26 +02001560 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001561 * Use host->devtype_data->irq_control() here instead of irq_control()
1562 * because we must not disable_irq_nosync without having requested the
1563 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001564 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001565 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001566
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001567 err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
Michael Opdenackerb1eb2342013-10-13 08:21:32 +02001568 0, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001569 if (err)
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001570 return err;
1571
Fabio Estevamdcedf622013-12-02 00:50:02 -02001572 err = clk_prepare_enable(host->clk);
1573 if (err)
1574 return err;
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001575 host->clk_act = 1;
Ivo Claryssed4840182010-04-08 16:14:44 +02001576
Sascha Hauer63f14742010-10-18 10:16:26 +02001577 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001578 * Now that we "own" the interrupt make sure the interrupt mask bit is
1579 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1580 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001581 */
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001582 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +02001583 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001584 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001585 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001586
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001587 /* first scan to find the device and get the page size */
Shawn Guo4d624352012-09-15 13:34:09 +08001588 if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001589 err = -ENXIO;
1590 goto escan;
1591 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001592
Huang Shijiea5900552013-12-21 00:02:27 +08001593 /* allocate the right size buffer now */
1594 devm_kfree(&pdev->dev, (void *)host->data_buf);
1595 host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
1596 GFP_KERNEL);
1597 if (!host->data_buf) {
1598 err = -ENOMEM;
1599 goto escan;
1600 }
1601
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001602 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001603 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001604
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001605 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001606 this->ecc.layout = host->devtype_data->ecclayout_2k;
1607 else if (mtd->writesize == 4096)
1608 this->ecc.layout = host->devtype_data->ecclayout_4k;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001609
Baruch Siach7e7e4732015-05-13 11:17:37 +03001610 /*
1611 * Experimentation shows that i.MX NFC can only handle up to 218 oob
1612 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
1613 * into copying invalid data to/from the spare IO buffer, as this
1614 * might cause ECC data corruption when doing sub-page write to a
1615 * partially written page.
1616 */
1617 host->used_oobsize = min(mtd->oobsize, 218U);
1618
Mike Dunn6a918ba2012-03-11 14:21:11 -07001619 if (this->ecc.mode == NAND_ECC_HW) {
Shawn Guo4d624352012-09-15 13:34:09 +08001620 if (is_imx21_nfc(host) || is_imx27_nfc(host))
Mike Dunn6a918ba2012-03-11 14:21:11 -07001621 this->ecc.strength = 1;
1622 else
1623 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1624 }
1625
Sascha Hauer4a43faf2012-05-25 16:22:42 +02001626 /* second phase scan */
1627 if (nand_scan_tail(mtd)) {
1628 err = -ENXIO;
1629 goto escan;
1630 }
1631
Sascha Hauer34f6e152008-09-02 17:16:59 +02001632 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001633 mtd_device_parse_register(mtd, part_probes,
1634 &(struct mtd_part_parser_data){
1635 .of_node = pdev->dev.of_node,
1636 },
1637 host->pdata.parts,
1638 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001639
1640 platform_set_drvdata(pdev, host);
1641
1642 return 0;
1643
1644escan:
Lothar Waßmannc10d8ee2012-12-06 08:42:27 +01001645 if (host->clk_act)
1646 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001647
1648 return err;
1649}
1650
Bill Pemberton810b7e02012-11-19 13:26:04 -05001651static int mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001652{
1653 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1654
Sascha Hauer34f6e152008-09-02 17:16:59 +02001655 nand_release(&host->mtd);
Wei Yongjun8bfd4f72013-12-17 11:35:35 +08001656 if (host->clk_act)
1657 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001658
1659 return 0;
1660}
1661
Sascha Hauer34f6e152008-09-02 17:16:59 +02001662static struct platform_driver mxcnd_driver = {
1663 .driver = {
1664 .name = DRIVER_NAME,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001665 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001666 },
Shawn Guo4d624352012-09-15 13:34:09 +08001667 .id_table = mxcnd_devtype,
Fabio Estevamddf16d62012-09-05 11:35:25 -03001668 .probe = mxcnd_probe,
Bill Pemberton5153b882012-11-19 13:21:24 -05001669 .remove = mxcnd_remove,
Sascha Hauer34f6e152008-09-02 17:16:59 +02001670};
Fabio Estevamddf16d62012-09-05 11:35:25 -03001671module_platform_driver(mxcnd_driver);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001672
1673MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1674MODULE_DESCRIPTION("MXC NAND MTD driver");
1675MODULE_LICENSE("GPL");