blob: f04445b992f512c537018b81bf0d685a3ee2f62b [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önig5e05a2d2012-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
Baruch Siach0d17fc32015-05-13 11:17:38 +0300284static void memcpy16_fromio(void *trg, const void __iomem *src, size_t size)
285{
286 int i;
287 u16 *t = trg;
288 const __iomem u16 *s = src;
289
290 /* We assume that src (IO) is always 32bit aligned */
291 if (PTR_ALIGN(trg, 4) == trg && IS_ALIGNED(size, 4)) {
292 memcpy32_fromio(trg, src, size);
293 return;
294 }
295
296 for (i = 0; i < (size >> 1); i++)
297 *t++ = __raw_readw(s++);
298}
299
Koul, Vinod33a87a12014-10-20 21:36:13 +0530300static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200301{
Koul, Vinod33a87a12014-10-20 21:36:13 +0530302 /* __iowrite32_copy use 32bit size values so divide by 4 */
303 __iowrite32_copy(trg, src, size / 4);
Sascha Hauer096bcc22012-05-29 10:16:09 +0200304}
305
Baruch Siach0d17fc32015-05-13 11:17:38 +0300306static void memcpy16_toio(void __iomem *trg, const void *src, int size)
307{
308 int i;
309 __iomem u16 *t = trg;
310 const u16 *s = src;
311
312 /* We assume that trg (IO) is always 32bit aligned */
313 if (PTR_ALIGN(src, 4) == src && IS_ALIGNED(size, 4)) {
314 memcpy32_toio(trg, src, size);
315 return;
316 }
317
318 for (i = 0; i < (size >> 1); i++)
319 __raw_writew(*s++, t++);
320}
321
Sascha Hauer71ec5152010-08-06 15:53:11 +0200322static int check_int_v3(struct mxc_nand_host *host)
323{
324 uint32_t tmp;
325
326 tmp = readl(NFC_V3_IPC);
327 if (!(tmp & NFC_V3_IPC_INT))
328 return 0;
329
330 tmp &= ~NFC_V3_IPC_INT;
331 writel(tmp, NFC_V3_IPC);
332
333 return 1;
334}
335
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200336static int check_int_v1_v2(struct mxc_nand_host *host)
337{
338 uint32_t tmp;
339
Sascha Hauer1bc99182010-08-06 15:53:08 +0200340 tmp = readw(NFC_V1_V2_CONFIG2);
341 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200342 return 0;
343
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200344 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200345 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200346
347 return 1;
348}
349
Sascha Hauer63f14742010-10-18 10:16:26 +0200350static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
351{
352 uint16_t tmp;
353
354 tmp = readw(NFC_V1_V2_CONFIG1);
355
356 if (activate)
357 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
358 else
359 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
360
361 writew(tmp, NFC_V1_V2_CONFIG1);
362}
363
364static void irq_control_v3(struct mxc_nand_host *host, int activate)
365{
366 uint32_t tmp;
367
368 tmp = readl(NFC_V3_CONFIG2);
369
370 if (activate)
371 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
372 else
373 tmp |= NFC_V3_CONFIG2_INT_MSK;
374
375 writel(tmp, NFC_V3_CONFIG2);
376}
377
Uwe Kleine-König85569582012-04-23 11:23:34 +0200378static void irq_control(struct mxc_nand_host *host, int activate)
379{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200380 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200381 if (activate)
382 enable_irq(host->irq);
383 else
384 disable_irq_nosync(host->irq);
385 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200386 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200387 }
388}
389
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200390static u32 get_ecc_status_v1(struct mxc_nand_host *host)
391{
392 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
393}
394
395static u32 get_ecc_status_v2(struct mxc_nand_host *host)
396{
397 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
398}
399
400static u32 get_ecc_status_v3(struct mxc_nand_host *host)
401{
402 return readl(NFC_V3_ECC_STATUS_RESULT);
403}
404
Uwe Kleine-König85569582012-04-23 11:23:34 +0200405static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
406{
407 struct mxc_nand_host *host = dev_id;
408
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200409 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200410 return IRQ_NONE;
411
412 irq_control(host, 0);
413
414 complete(&host->op_completion);
415
416 return IRQ_HANDLED;
417}
418
Sascha Hauer34f6e152008-09-02 17:16:59 +0200419/* This function polls the NANDFC to wait for the basic operation to
420 * complete by checking the INT bit of config2 register.
421 */
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100422static int wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200423{
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100424 int ret = 0;
425
426 /*
427 * If operation is already complete, don't bother to setup an irq or a
428 * loop.
429 */
430 if (host->devtype_data->check_int(host))
431 return 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200432
433 if (useirq) {
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100434 unsigned long timeout;
435
436 reinit_completion(&host->op_completion);
437
438 irq_control(host, 1);
439
440 timeout = wait_for_completion_timeout(&host->op_completion, HZ);
441 if (!timeout && !host->devtype_data->check_int(host)) {
442 dev_dbg(host->dev, "timeout waiting for irq\n");
443 ret = -ETIMEDOUT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200444 }
445 } else {
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100446 int max_retries = 8000;
447 int done;
448
449 do {
450 udelay(1);
451
452 done = host->devtype_data->check_int(host);
453 if (done)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200454 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200455
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100456 } while (--max_retries);
457
458 if (!done) {
459 dev_dbg(host->dev, "timeout polling for completion\n");
460 ret = -ETIMEDOUT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200461 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200462 }
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100463
464 WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq);
465
466 return ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200467}
468
Sascha Hauer71ec5152010-08-06 15:53:11 +0200469static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
470{
471 /* fill command */
472 writel(cmd, NFC_V3_FLASH_CMD);
473
474 /* send out command */
475 writel(NFC_CMD, NFC_V3_LAUNCH);
476
477 /* Wait for operation to complete */
478 wait_op_done(host, useirq);
479}
480
Sascha Hauer34f6e152008-09-02 17:16:59 +0200481/* This function issues the specified command to the NAND device and
482 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200483static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200484{
Brian Norris289c0522011-07-19 10:06:09 -0700485 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200486
Sascha Hauer1bc99182010-08-06 15:53:08 +0200487 writew(cmd, NFC_V1_V2_FLASH_CMD);
488 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200489
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200490 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200491 int max_retries = 100;
492 /* Reset completion is indicated by NFC_CONFIG2 */
493 /* being set to 0 */
494 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200495 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200496 break;
497 }
498 udelay(1);
499 }
500 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700501 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200502 } else {
503 /* Wait for operation to complete */
504 wait_op_done(host, useirq);
505 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200506}
507
Sascha Hauer71ec5152010-08-06 15:53:11 +0200508static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
509{
510 /* fill address */
511 writel(addr, NFC_V3_FLASH_ADDR0);
512
513 /* send out address */
514 writel(NFC_ADDR, NFC_V3_LAUNCH);
515
516 wait_op_done(host, 0);
517}
518
Sascha Hauer34f6e152008-09-02 17:16:59 +0200519/* This function sends an address (or partial address) to the
520 * NAND device. The address is used to select the source/destination for
521 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200522static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200523{
Brian Norris289c0522011-07-19 10:06:09 -0700524 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200525
Sascha Hauer1bc99182010-08-06 15:53:08 +0200526 writew(addr, NFC_V1_V2_FLASH_ADDR);
527 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200528
529 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200530 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200531}
532
Sascha Hauer71ec5152010-08-06 15:53:11 +0200533static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
534{
535 struct nand_chip *nand_chip = mtd->priv;
536 struct mxc_nand_host *host = nand_chip->priv;
537 uint32_t tmp;
538
539 tmp = readl(NFC_V3_CONFIG1);
540 tmp &= ~(7 << 4);
541 writel(tmp, NFC_V3_CONFIG1);
542
543 /* transfer data from NFC ram to nand */
544 writel(ops, NFC_V3_LAUNCH);
545
546 wait_op_done(host, false);
547}
548
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200549static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
550{
551 struct nand_chip *nand_chip = mtd->priv;
552 struct mxc_nand_host *host = nand_chip->priv;
553
554 /* NANDFC buffer 0 is used for page read/write */
555 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
556
557 writew(ops, NFC_V1_V2_CONFIG2);
558
559 /* Wait for operation to complete */
560 wait_op_done(host, true);
561}
562
563static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200564{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200565 struct nand_chip *nand_chip = mtd->priv;
566 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200567 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200568
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200569 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200570 bufs = 4;
571 else
572 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200573
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200574 for (i = 0; i < bufs; i++) {
575
576 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200577 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200578
Sascha Hauer1bc99182010-08-06 15:53:08 +0200579 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200580
581 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200582 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200583 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200584}
585
Sascha Hauer71ec5152010-08-06 15:53:11 +0200586static void send_read_id_v3(struct mxc_nand_host *host)
587{
588 /* Read ID into main buffer */
589 writel(NFC_ID, NFC_V3_LAUNCH);
590
591 wait_op_done(host, true);
592
Sascha Hauer096bcc22012-05-29 10:16:09 +0200593 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Sascha Hauer71ec5152010-08-06 15:53:11 +0200594}
595
Sascha Hauer34f6e152008-09-02 17:16:59 +0200596/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200597static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200598{
Sascha Hauer34f6e152008-09-02 17:16:59 +0200599 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200600 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200601
Sascha Hauer1bc99182010-08-06 15:53:08 +0200602 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200603
604 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200605 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200606
Sascha Hauer096bcc22012-05-29 10:16:09 +0200607 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200608}
609
Sascha Hauer71ec5152010-08-06 15:53:11 +0200610static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200611{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200612 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200613 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200614
Sascha Hauer71ec5152010-08-06 15:53:11 +0200615 return readl(NFC_V3_CONFIG1) >> 16;
616}
617
Sascha Hauer34f6e152008-09-02 17:16:59 +0200618/* This function requests the NANDFC to perform a read of the
619 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200620static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200621{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200622 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200623 uint32_t store;
624 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200625
Baruch Siachd178e3e2011-03-14 09:01:56 +0200626 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200627
628 /*
629 * The device status is stored in main_area0. To
630 * prevent corruption of the buffer save the value
631 * and restore it afterwards.
632 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200633 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200634
Sascha Hauer1bc99182010-08-06 15:53:08 +0200635 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200636 wait_op_done(host, true);
637
Sascha Hauer34f6e152008-09-02 17:16:59 +0200638 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200639
Sascha Hauer34f6e152008-09-02 17:16:59 +0200640 writel(store, main_buf);
641
642 return ret;
643}
644
645/* This functions is used by upper layer to checks if device is ready */
646static int mxc_nand_dev_ready(struct mtd_info *mtd)
647{
648 /*
649 * NFC handles R/B internally. Therefore, this function
650 * always returns status as ready.
651 */
652 return 1;
653}
654
655static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
656{
657 /*
658 * If HW ECC is enabled, we turn it on during init. There is
659 * no need to enable again here.
660 */
661}
662
Sascha Hauer94f77e52010-08-06 15:53:09 +0200663static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200664 u_char *read_ecc, u_char *calc_ecc)
665{
666 struct nand_chip *nand_chip = mtd->priv;
667 struct mxc_nand_host *host = nand_chip->priv;
668
669 /*
670 * 1-Bit errors are automatically corrected in HW. No need for
671 * additional correction. 2-Bit errors cannot be corrected by
672 * HW ECC, so we need to return failure
673 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200674 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200675
676 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700677 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200678 return -1;
679 }
680
681 return 0;
682}
683
Sascha Hauer94f77e52010-08-06 15:53:09 +0200684static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
685 u_char *read_ecc, u_char *calc_ecc)
686{
687 struct nand_chip *nand_chip = mtd->priv;
688 struct mxc_nand_host *host = nand_chip->priv;
689 u32 ecc_stat, err;
690 int no_subpages = 1;
691 int ret = 0;
692 u8 ecc_bit_mask, err_limit;
693
694 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
695 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
696
697 no_subpages = mtd->writesize >> 9;
698
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200699 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200700
701 do {
702 err = ecc_stat & ecc_bit_mask;
703 if (err > err_limit) {
704 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
705 return -1;
706 } else {
707 ret += err;
708 }
709 ecc_stat >>= 4;
710 } while (--no_subpages);
711
Sascha Hauer94f77e52010-08-06 15:53:09 +0200712 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
713
714 return ret;
715}
716
Sascha Hauer34f6e152008-09-02 17:16:59 +0200717static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
718 u_char *ecc_code)
719{
720 return 0;
721}
722
723static u_char mxc_nand_read_byte(struct mtd_info *mtd)
724{
725 struct nand_chip *nand_chip = mtd->priv;
726 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200727 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200728
729 /* Check for status request */
730 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200731 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200732
Uwe Kleine-König3f410692015-02-10 19:59:57 +0100733 if (nand_chip->options & NAND_BUSWIDTH_16) {
734 /* only take the lower byte of each word */
735 ret = *(uint16_t *)(host->data_buf + host->buf_start);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200736
Uwe Kleine-König3f410692015-02-10 19:59:57 +0100737 host->buf_start += 2;
738 } else {
739 ret = *(uint8_t *)(host->data_buf + host->buf_start);
740 host->buf_start++;
741 }
742
743 pr_debug("%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200744 return ret;
745}
746
747static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
748{
749 struct nand_chip *nand_chip = mtd->priv;
750 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200751 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200752
Sascha Hauerf8f96082009-06-04 17:12:26 +0200753 ret = *(uint16_t *)(host->data_buf + host->buf_start);
754 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200755
756 return ret;
757}
758
759/* Write data of length len to buffer buf. The data to be
760 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
761 * Operation by the NFC, the data is written to NAND Flash */
762static void mxc_nand_write_buf(struct mtd_info *mtd,
763 const u_char *buf, int len)
764{
765 struct nand_chip *nand_chip = mtd->priv;
766 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200767 u16 col = host->buf_start;
768 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200769
Sascha Hauerf8f96082009-06-04 17:12:26 +0200770 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200771
Sascha Hauerf8f96082009-06-04 17:12:26 +0200772 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200773
Sascha Hauerf8f96082009-06-04 17:12:26 +0200774 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200775}
776
777/* Read the data buffer from the NAND Flash. To read the data from NAND
778 * Flash first the data output cycle is initiated by the NFC, which copies
779 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
780 */
781static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
782{
783 struct nand_chip *nand_chip = mtd->priv;
784 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200785 u16 col = host->buf_start;
786 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200787
Sascha Hauerf8f96082009-06-04 17:12:26 +0200788 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200789
Baruch Siach5d9d9932011-03-02 16:47:55 +0200790 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200791
Baruch Siach5d9d9932011-03-02 16:47:55 +0200792 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200793}
794
Sascha Hauer34f6e152008-09-02 17:16:59 +0200795/* This function is used by upper layer for select and
796 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200797static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200798{
799 struct nand_chip *nand_chip = mtd->priv;
800 struct mxc_nand_host *host = nand_chip->priv;
801
Baruch Siachd178e3e2011-03-14 09:01:56 +0200802 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200803 /* Disable the NFC clock */
804 if (host->clk_act) {
Sascha Hauer97c32132012-03-07 20:56:35 +0100805 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200806 host->clk_act = 0;
807 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200808 return;
809 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200810
Baruch Siachd178e3e2011-03-14 09:01:56 +0200811 if (!host->clk_act) {
812 /* Enable the NFC clock */
Sascha Hauer97c32132012-03-07 20:56:35 +0100813 clk_prepare_enable(host->clk);
Baruch Siachd178e3e2011-03-14 09:01:56 +0200814 host->clk_act = 1;
815 }
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200816}
Baruch Siachd178e3e2011-03-14 09:01:56 +0200817
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200818static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200819{
820 struct nand_chip *nand_chip = mtd->priv;
821 struct mxc_nand_host *host = nand_chip->priv;
822
823 if (chip == -1) {
824 /* Disable the NFC clock */
825 if (host->clk_act) {
Fabio Estevam3d059692012-05-25 20:14:50 -0300826 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200827 host->clk_act = 0;
828 }
829 return;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200830 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200831
832 if (!host->clk_act) {
833 /* Enable the NFC clock */
Fabio Estevam3d059692012-05-25 20:14:50 -0300834 clk_prepare_enable(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200835 host->clk_act = 1;
836 }
837
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200838 host->active_cs = chip;
839 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200840}
841
Sascha Hauerf8f96082009-06-04 17:12:26 +0200842/*
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300843 * The controller splits a page into data chunks of 512 bytes + partial oob.
844 * There are writesize / 512 such chunks, the size of the partial oob parts is
845 * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then
846 * contains additionally the byte lost by rounding (if any).
847 * This function handles the needed shuffling between host->data_buf (which
848 * holds a page in natural order, i.e. writesize bytes data + oobsize bytes
849 * spare) and the NFC buffer.
Sascha Hauerf8f96082009-06-04 17:12:26 +0200850 */
851static void copy_spare(struct mtd_info *mtd, bool bfrom)
852{
853 struct nand_chip *this = mtd->priv;
854 struct mxc_nand_host *host = this->priv;
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300855 u16 i, oob_chunk_size;
856 u16 num_chunks = mtd->writesize / 512;
857
Sascha Hauerf8f96082009-06-04 17:12:26 +0200858 u8 *d = host->data_buf + mtd->writesize;
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200859 u8 __iomem *s = host->spare0;
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300860 u16 sparebuf_size = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200861
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300862 /* size of oob chunk for all but possibly the last one */
Baruch Siach7e7e4732015-05-13 11:17:37 +0300863 oob_chunk_size = (host->used_oobsize / num_chunks) & ~1;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200864
865 if (bfrom) {
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300866 for (i = 0; i < num_chunks - 1; i++)
Baruch Siach0d17fc32015-05-13 11:17:38 +0300867 memcpy16_fromio(d + i * oob_chunk_size,
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300868 s + i * sparebuf_size,
869 oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200870
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300871 /* the last chunk */
Baruch Siach0d17fc32015-05-13 11:17:38 +0300872 memcpy16_fromio(d + i * oob_chunk_size,
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300873 s + i * sparebuf_size,
Baruch Siach7e7e4732015-05-13 11:17:37 +0300874 host->used_oobsize - i * oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200875 } else {
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300876 for (i = 0; i < num_chunks - 1; i++)
Baruch Siach0d17fc32015-05-13 11:17:38 +0300877 memcpy16_toio(&s[i * sparebuf_size],
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300878 &d[i * oob_chunk_size],
879 oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200880
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300881 /* the last chunk */
Eric Benarde5a5d922015-09-23 17:07:28 +0200882 memcpy16_toio(&s[i * sparebuf_size],
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300883 &d[i * oob_chunk_size],
Baruch Siach7e7e4732015-05-13 11:17:37 +0300884 host->used_oobsize - i * oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200885 }
886}
887
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100888/*
889 * MXC NANDFC can only perform full page+spare or spare-only read/write. When
890 * the upper layers perform a read/write buf operation, the saved column address
891 * is used to index into the full page. So usually this function is called with
892 * column == 0 (unless no column cycle is needed indicated by column == -1)
893 */
Sascha Hauera3e65b62009-06-02 11:47:59 +0200894static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200895{
896 struct nand_chip *nand_chip = mtd->priv;
897 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200898
899 /* Write out column address, if necessary */
900 if (column != -1) {
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100901 host->devtype_data->send_addr(host, column & 0xff,
902 page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200903 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200904 /* another col addr cycle for 2k page */
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100905 host->devtype_data->send_addr(host,
906 (column >> 8) & 0xff,
907 false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200908 }
909
910 /* Write out page address, if necessary */
911 if (page_addr != -1) {
912 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200913 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200914
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200915 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400916 if (mtd->size >= 0x10000000) {
917 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200918 host->devtype_data->send_addr(host,
919 (page_addr >> 8) & 0xff,
920 false);
921 host->devtype_data->send_addr(host,
922 (page_addr >> 16) & 0xff,
923 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400924 } else
925 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200926 host->devtype_data->send_addr(host,
927 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200928 } else {
929 /* One more address cycle for higher density devices */
930 if (mtd->size >= 0x4000000) {
931 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200932 host->devtype_data->send_addr(host,
933 (page_addr >> 8) & 0xff,
934 false);
935 host->devtype_data->send_addr(host,
936 (page_addr >> 16) & 0xff,
937 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200938 } else
939 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200940 host->devtype_data->send_addr(host,
941 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200942 }
943 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200944}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200945
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200946/*
947 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
948 * on how much oob the nand chip has. For 8bit ecc we need at least
949 * 26 bytes of oob data per 512 byte block.
950 */
951static int get_eccsize(struct mtd_info *mtd)
952{
953 int oobbytes_per_512 = 0;
954
955 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
956
957 if (oobbytes_per_512 < 26)
958 return 4;
959 else
960 return 8;
961}
962
Baruch Siach8eeb4c52015-05-13 11:17:39 +0300963static void ecc_8bit_layout_4k(struct nand_ecclayout *layout)
964{
965 int i, j;
966
967 layout->eccbytes = 8*18;
968 for (i = 0; i < 8; i++)
969 for (j = 0; j < 18; j++)
970 layout->eccpos[i*18 + j] = i*26 + j + 7;
971
972 layout->oobfree[0].offset = 2;
973 layout->oobfree[0].length = 4;
974 for (i = 1; i < 8; i++) {
975 layout->oobfree[i].offset = i*26;
976 layout->oobfree[i].length = 7;
977 }
978}
979
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200980static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200981{
982 struct nand_chip *nand_chip = mtd->priv;
983 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200984 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200985
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +0100986 if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200987 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
988
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200989 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200990 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200991
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200992 host->eccsize = 1;
993
994 writew(config1, NFC_V1_V2_CONFIG1);
995 /* preset operation */
996
997 /* Unlock the internal RAM Buffer */
998 writew(0x2, NFC_V1_V2_CONFIG);
999
1000 /* Blocks to be unlocked */
1001 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
1002 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
1003
1004 /* Unlock Block Command for given address range */
1005 writew(0x4, NFC_V1_V2_WRPROT);
1006}
1007
1008static void preset_v2(struct mtd_info *mtd)
1009{
1010 struct nand_chip *nand_chip = mtd->priv;
1011 struct mxc_nand_host *host = nand_chip->priv;
1012 uint16_t config1 = 0;
1013
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001014 config1 |= NFC_V2_CONFIG1_FP_INT;
Ivo Claryssed4840182010-04-08 16:14:44 +02001015
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001016 if (!host->devtype_data->irqpending_quirk)
Ivo Claryssed4840182010-04-08 16:14:44 +02001017 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001018
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001019 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +02001020 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
1021
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +01001022 if (nand_chip->ecc.mode == NAND_ECC_HW)
1023 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
1024
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001025 host->eccsize = get_eccsize(mtd);
1026 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +02001027 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
1028
1029 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001030 } else {
1031 host->eccsize = 1;
1032 }
1033
Sascha Hauerb8db2f52010-08-09 15:04:19 +02001034 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +02001035 /* preset operation */
1036
1037 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +02001038 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +02001039
1040 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001041 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
1042 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
1043 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
1044 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
1045 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
1046 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
1047 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
1048 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +02001049
1050 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +02001051 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +02001052}
1053
Sascha Hauer71ec5152010-08-06 15:53:11 +02001054static void preset_v3(struct mtd_info *mtd)
1055{
1056 struct nand_chip *chip = mtd->priv;
1057 struct mxc_nand_host *host = chip->priv;
1058 uint32_t config2, config3;
1059 int i, addr_phases;
1060
1061 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
1062 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
1063
1064 /* Unlock the internal RAM Buffer */
1065 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
1066 NFC_V3_WRPROT);
1067
1068 /* Blocks to be unlocked */
1069 for (i = 0; i < NAND_MAX_CHIPS; i++)
1070 writel(0x0 | (0xffff << 16),
1071 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
1072
1073 writel(0, NFC_V3_IPC);
1074
1075 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
1076 NFC_V3_CONFIG2_2CMD_PHASES |
1077 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
1078 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +02001079 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +02001080 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
1081
Sascha Hauer71ec5152010-08-06 15:53:11 +02001082 addr_phases = fls(chip->pagemask) >> 3;
1083
1084 if (mtd->writesize == 2048) {
1085 config2 |= NFC_V3_CONFIG2_PS_2048;
1086 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1087 } else if (mtd->writesize == 4096) {
1088 config2 |= NFC_V3_CONFIG2_PS_4096;
1089 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1090 } else {
1091 config2 |= NFC_V3_CONFIG2_PS_512;
1092 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1093 }
1094
1095 if (mtd->writesize) {
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +01001096 if (chip->ecc.mode == NAND_ECC_HW)
1097 config2 |= NFC_V3_CONFIG2_ECC_EN;
1098
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001099 config2 |= NFC_V3_CONFIG2_PPB(
1100 ffs(mtd->erasesize / mtd->writesize) - 6,
1101 host->devtype_data->ppb_shift);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001102 host->eccsize = get_eccsize(mtd);
1103 if (host->eccsize == 8)
1104 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
1105 }
1106
1107 writel(config2, NFC_V3_CONFIG2);
1108
1109 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1110 NFC_V3_CONFIG3_NO_SDMA |
1111 NFC_V3_CONFIG3_RBB_MODE |
1112 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1113 NFC_V3_CONFIG3_ADD_OP(0);
1114
1115 if (!(chip->options & NAND_BUSWIDTH_16))
1116 config3 |= NFC_V3_CONFIG3_FW8;
1117
1118 writel(config3, NFC_V3_CONFIG3);
1119
1120 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001121}
1122
Sascha Hauer34f6e152008-09-02 17:16:59 +02001123/* Used by the upper layer to write command to NAND Flash for
1124 * different operations to be carried out on NAND Flash */
1125static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1126 int column, int page_addr)
1127{
1128 struct nand_chip *nand_chip = mtd->priv;
1129 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001130
Brian Norris289c0522011-07-19 10:06:09 -07001131 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001132 command, column, page_addr);
1133
1134 /* Reset command state information */
1135 host->status_request = false;
1136
1137 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001138 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001139 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001140 host->devtype_data->preset(mtd);
1141 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001142 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001143
Sascha Hauer34f6e152008-09-02 17:16:59 +02001144 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001145 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001146 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001147
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001148 host->devtype_data->send_cmd(host, command, true);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001149 WARN_ONCE(column != -1 || page_addr != -1,
1150 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1151 command, column, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001152 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001153 break;
1154
Sascha Hauer34f6e152008-09-02 17:16:59 +02001155 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001156 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001157 if (command == NAND_CMD_READ0)
1158 host->buf_start = column;
1159 else
1160 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001161
Sascha Hauer5ea32022010-04-27 15:24:01 +02001162 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001163
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001164 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001165 WARN_ONCE(column < 0,
1166 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1167 command, column, page_addr);
1168 mxc_do_addr_cycle(mtd, 0, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001169
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001170 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001171 host->devtype_data->send_cmd(host,
1172 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001173
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001174 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001175
Sascha Hauer096bcc22012-05-29 10:16:09 +02001176 memcpy32_fromio(host->data_buf, host->main_area0,
1177 mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001178 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001179 break;
1180
Sascha Hauer34f6e152008-09-02 17:16:59 +02001181 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001182 if (column >= mtd->writesize)
1183 /* call ourself to read a page */
1184 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001185
Sascha Hauer5ea32022010-04-27 15:24:01 +02001186 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001187
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001188 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001189 WARN_ONCE(column < -1,
1190 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1191 command, column, page_addr);
1192 mxc_do_addr_cycle(mtd, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001193 break;
1194
1195 case NAND_CMD_PAGEPROG:
Sascha Hauer096bcc22012-05-29 10:16:09 +02001196 memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001197 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001198 host->devtype_data->send_page(mtd, NFC_INPUT);
1199 host->devtype_data->send_cmd(host, command, true);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001200 WARN_ONCE(column != -1 || page_addr != -1,
1201 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1202 command, column, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001203 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001204 break;
1205
Sascha Hauer34f6e152008-09-02 17:16:59 +02001206 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001207 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001208 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001209 host->devtype_data->send_read_id(host);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001210 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001211 break;
1212
Sascha Hauer89121a62009-06-04 17:18:01 +02001213 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001214 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001215 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001216 WARN_ONCE(column != -1,
1217 "Unexpected column value (cmd=%u, col=%d)\n",
1218 command, column);
Sascha Hauer89121a62009-06-04 17:18:01 +02001219 mxc_do_addr_cycle(mtd, column, page_addr);
1220
Sascha Hauer34f6e152008-09-02 17:16:59 +02001221 break;
Uwe Kleine-König3d6e81c2015-02-10 19:59:59 +01001222 case NAND_CMD_PARAM:
1223 host->devtype_data->send_cmd(host, command, false);
1224 mxc_do_addr_cycle(mtd, column, page_addr);
1225 host->devtype_data->send_page(mtd, NFC_OUTPUT);
1226 memcpy32_fromio(host->data_buf, host->main_area0, 512);
1227 host->buf_start = 0;
1228 break;
Uwe Kleine-König98ebb522015-02-10 20:00:00 +01001229 default:
1230 WARN_ONCE(1, "Unimplemented command (cmd=%u)\n",
1231 command);
1232 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001233 }
1234}
1235
Sascha Hauerf1372052009-10-21 14:25:27 +02001236/*
1237 * The generic flash bbt decriptors overlap with our ecc
1238 * hardware, so define some i.MX specific ones.
1239 */
1240static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1241static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1242
1243static struct nand_bbt_descr bbt_main_descr = {
1244 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1245 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1246 .offs = 0,
1247 .len = 4,
1248 .veroffs = 4,
1249 .maxblocks = 4,
1250 .pattern = bbt_pattern,
1251};
1252
1253static struct nand_bbt_descr bbt_mirror_descr = {
1254 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1255 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1256 .offs = 0,
1257 .len = 4,
1258 .veroffs = 4,
1259 .maxblocks = 4,
1260 .pattern = mirror_pattern,
1261};
1262
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001263/* v1 + irqpending_quirk: i.MX21 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001264static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001265 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001266 .send_cmd = send_cmd_v1_v2,
1267 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001268 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001269 .send_read_id = send_read_id_v1_v2,
1270 .get_dev_status = get_dev_status_v1_v2,
1271 .check_int = check_int_v1_v2,
1272 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001273 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001274 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1275 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1276 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +02001277 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001278 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001279 .irqpending_quirk = 1,
1280 .needs_ip = 0,
1281 .regs_offset = 0xe00,
1282 .spare0_offset = 0x800,
1283 .spare_len = 16,
1284 .eccbytes = 3,
1285 .eccsize = 1,
1286};
1287
1288/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1289static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1290 .preset = preset_v1,
1291 .send_cmd = send_cmd_v1_v2,
1292 .send_addr = send_addr_v1_v2,
1293 .send_page = send_page_v1,
1294 .send_read_id = send_read_id_v1_v2,
1295 .get_dev_status = get_dev_status_v1_v2,
1296 .check_int = check_int_v1_v2,
1297 .irq_control = irq_control_v1_v2,
1298 .get_ecc_status = get_ecc_status_v1,
1299 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1300 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1301 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1302 .select_chip = mxc_nand_select_chip_v1_v3,
1303 .correct_data = mxc_nand_correct_data_v1,
1304 .irqpending_quirk = 0,
1305 .needs_ip = 0,
1306 .regs_offset = 0xe00,
1307 .spare0_offset = 0x800,
1308 .axi_offset = 0,
1309 .spare_len = 16,
1310 .eccbytes = 3,
1311 .eccsize = 1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001312};
1313
1314/* v21: i.MX25, i.MX35 */
1315static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001316 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001317 .send_cmd = send_cmd_v1_v2,
1318 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001319 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001320 .send_read_id = send_read_id_v1_v2,
1321 .get_dev_status = get_dev_status_v1_v2,
1322 .check_int = check_int_v1_v2,
1323 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001324 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001325 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1326 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1327 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +02001328 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001329 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001330 .irqpending_quirk = 0,
1331 .needs_ip = 0,
1332 .regs_offset = 0x1e00,
1333 .spare0_offset = 0x1000,
1334 .axi_offset = 0,
1335 .spare_len = 64,
1336 .eccbytes = 9,
1337 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001338};
1339
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001340/* v3.2a: i.MX51 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001341static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1342 .preset = preset_v3,
1343 .send_cmd = send_cmd_v3,
1344 .send_addr = send_addr_v3,
1345 .send_page = send_page_v3,
1346 .send_read_id = send_read_id_v3,
1347 .get_dev_status = get_dev_status_v3,
1348 .check_int = check_int_v3,
1349 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001350 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001351 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1352 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1353 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +02001354 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001355 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001356 .irqpending_quirk = 0,
1357 .needs_ip = 1,
1358 .regs_offset = 0,
1359 .spare0_offset = 0x1000,
1360 .axi_offset = 0x1e00,
1361 .spare_len = 64,
1362 .eccbytes = 0,
1363 .eccsize = 0,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001364 .ppb_shift = 7,
1365};
1366
1367/* v3.2b: i.MX53 */
1368static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
1369 .preset = preset_v3,
1370 .send_cmd = send_cmd_v3,
1371 .send_addr = send_addr_v3,
1372 .send_page = send_page_v3,
1373 .send_read_id = send_read_id_v3,
1374 .get_dev_status = get_dev_status_v3,
1375 .check_int = check_int_v3,
1376 .irq_control = irq_control_v3,
1377 .get_ecc_status = get_ecc_status_v3,
1378 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1379 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1380 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1381 .select_chip = mxc_nand_select_chip_v1_v3,
1382 .correct_data = mxc_nand_correct_data_v2_v3,
1383 .irqpending_quirk = 0,
1384 .needs_ip = 1,
1385 .regs_offset = 0,
1386 .spare0_offset = 0x1000,
1387 .axi_offset = 0x1e00,
1388 .spare_len = 64,
1389 .eccbytes = 0,
1390 .eccsize = 0,
1391 .ppb_shift = 8,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001392};
1393
Shawn Guo4d624352012-09-15 13:34:09 +08001394static inline int is_imx21_nfc(struct mxc_nand_host *host)
1395{
1396 return host->devtype_data == &imx21_nand_devtype_data;
1397}
1398
1399static inline int is_imx27_nfc(struct mxc_nand_host *host)
1400{
1401 return host->devtype_data == &imx27_nand_devtype_data;
1402}
1403
1404static inline int is_imx25_nfc(struct mxc_nand_host *host)
1405{
1406 return host->devtype_data == &imx25_nand_devtype_data;
1407}
1408
1409static inline int is_imx51_nfc(struct mxc_nand_host *host)
1410{
1411 return host->devtype_data == &imx51_nand_devtype_data;
1412}
1413
1414static inline int is_imx53_nfc(struct mxc_nand_host *host)
1415{
1416 return host->devtype_data == &imx53_nand_devtype_data;
1417}
1418
Krzysztof Kozlowski8d1e5682015-05-02 00:50:01 +09001419static const struct platform_device_id mxcnd_devtype[] = {
Shawn Guo4d624352012-09-15 13:34:09 +08001420 {
1421 .name = "imx21-nand",
1422 .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
1423 }, {
1424 .name = "imx27-nand",
1425 .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
1426 }, {
1427 .name = "imx25-nand",
1428 .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
1429 }, {
1430 .name = "imx51-nand",
1431 .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
1432 }, {
1433 .name = "imx53-nand",
1434 .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
1435 }, {
1436 /* sentinel */
1437 }
1438};
1439MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
1440
Uwe Kleine-König64363562012-04-23 11:23:41 +02001441#ifdef CONFIG_OF_MTD
1442static const struct of_device_id mxcnd_dt_ids[] = {
1443 {
1444 .compatible = "fsl,imx21-nand",
1445 .data = &imx21_nand_devtype_data,
1446 }, {
1447 .compatible = "fsl,imx27-nand",
1448 .data = &imx27_nand_devtype_data,
1449 }, {
1450 .compatible = "fsl,imx25-nand",
1451 .data = &imx25_nand_devtype_data,
1452 }, {
1453 .compatible = "fsl,imx51-nand",
1454 .data = &imx51_nand_devtype_data,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001455 }, {
1456 .compatible = "fsl,imx53-nand",
1457 .data = &imx53_nand_devtype_data,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001458 },
1459 { /* sentinel */ }
1460};
1461
1462static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1463{
1464 struct device_node *np = host->dev->of_node;
1465 struct mxc_nand_platform_data *pdata = &host->pdata;
1466 const struct of_device_id *of_id =
1467 of_match_device(mxcnd_dt_ids, host->dev);
1468 int buswidth;
1469
1470 if (!np)
1471 return 1;
1472
1473 if (of_get_nand_ecc_mode(np) >= 0)
1474 pdata->hw_ecc = 1;
1475
1476 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1477
1478 buswidth = of_get_nand_bus_width(np);
1479 if (buswidth < 0)
1480 return buswidth;
1481
1482 pdata->width = buswidth / 8;
1483
1484 host->devtype_data = of_id->data;
1485
1486 return 0;
1487}
1488#else
1489static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1490{
1491 return 1;
1492}
1493#endif
1494
Bill Pemberton06f25512012-11-19 13:23:07 -05001495static int mxcnd_probe(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001496{
1497 struct nand_chip *this;
1498 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001499 struct mxc_nand_host *host;
1500 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001501 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001502
1503 /* Allocate memory for MTD device structure and private data */
Huang Shijiea5900552013-12-21 00:02:27 +08001504 host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
1505 GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001506 if (!host)
1507 return -ENOMEM;
1508
Huang Shijiea5900552013-12-21 00:02:27 +08001509 /* allocate a temporary buffer for the nand_scan_ident() */
1510 host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
1511 if (!host->data_buf)
1512 return -ENOMEM;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001513
Sascha Hauer34f6e152008-09-02 17:16:59 +02001514 host->dev = &pdev->dev;
1515 /* structures must be linked */
1516 this = &host->nand;
1517 mtd = &host->mtd;
1518 mtd->priv = this;
1519 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001520 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001521 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001522
1523 /* 50 us command delay time */
1524 this->chip_delay = 5;
1525
1526 this->priv = host;
1527 this->dev_ready = mxc_nand_dev_ready;
1528 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001529 this->read_byte = mxc_nand_read_byte;
1530 this->read_word = mxc_nand_read_word;
1531 this->write_buf = mxc_nand_write_buf;
1532 this->read_buf = mxc_nand_read_buf;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001533
Fabio Estevam24b82d32012-09-05 11:52:27 -03001534 host->clk = devm_clk_get(&pdev->dev, NULL);
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001535 if (IS_ERR(host->clk))
1536 return PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001537
Sascha Hauer71885b62012-06-06 12:33:14 +02001538 err = mxcnd_probe_dt(host);
Shawn Guo4d624352012-09-15 13:34:09 +08001539 if (err > 0) {
Jingoo Han453810b2013-07-30 17:18:33 +09001540 struct mxc_nand_platform_data *pdata =
1541 dev_get_platdata(&pdev->dev);
Shawn Guo4d624352012-09-15 13:34:09 +08001542 if (pdata) {
1543 host->pdata = *pdata;
1544 host->devtype_data = (struct mxc_nand_devtype_data *)
1545 pdev->id_entry->driver_data;
1546 } else {
1547 err = -ENODEV;
1548 }
1549 }
Sascha Hauer71885b62012-06-06 12:33:14 +02001550 if (err < 0)
1551 return err;
1552
1553 if (host->devtype_data->needs_ip) {
1554 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Thierry Redingb0de7742013-01-21 11:09:12 +01001555 host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
1556 if (IS_ERR(host->regs_ip))
1557 return PTR_ERR(host->regs_ip);
Sascha Hauer71885b62012-06-06 12:33:14 +02001558
1559 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1560 } else {
1561 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1562 }
1563
Thierry Redingb0de7742013-01-21 11:09:12 +01001564 host->base = devm_ioremap_resource(&pdev->dev, res);
1565 if (IS_ERR(host->base))
1566 return PTR_ERR(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001567
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001568 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001569
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001570 if (host->devtype_data->regs_offset)
1571 host->regs = host->base + host->devtype_data->regs_offset;
1572 host->spare0 = host->base + host->devtype_data->spare0_offset;
1573 if (host->devtype_data->axi_offset)
1574 host->regs_axi = host->base + host->devtype_data->axi_offset;
1575
1576 this->ecc.bytes = host->devtype_data->eccbytes;
1577 host->eccsize = host->devtype_data->eccsize;
1578
1579 this->select_chip = host->devtype_data->select_chip;
1580 this->ecc.size = 512;
1581 this->ecc.layout = host->devtype_data->ecclayout_512;
1582
Uwe Kleine-König64363562012-04-23 11:23:41 +02001583 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001584 this->ecc.calculate = mxc_nand_calculate_ecc;
1585 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001586 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001587 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001588 } else {
1589 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001590 }
1591
Uwe Kleine-König64363562012-04-23 11:23:41 +02001592 /* NAND bus width determines access functions used by upper layer */
1593 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001594 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001595
Uwe Kleine-König64363562012-04-23 11:23:41 +02001596 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001597 this->bbt_td = &bbt_main_descr;
1598 this->bbt_md = &bbt_mirror_descr;
1599 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001600 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001601 }
1602
Sascha Hauer63f14742010-10-18 10:16:26 +02001603 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001604
1605 host->irq = platform_get_irq(pdev, 0);
Fabio Estevam26fbf482014-02-14 01:09:34 -02001606 if (host->irq < 0)
1607 return host->irq;
Ivo Claryssed4840182010-04-08 16:14:44 +02001608
Sascha Hauer63f14742010-10-18 10:16:26 +02001609 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001610 * Use host->devtype_data->irq_control() here instead of irq_control()
1611 * because we must not disable_irq_nosync without having requested the
1612 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001613 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001614 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001615
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001616 err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
Michael Opdenackerb1eb2342013-10-13 08:21:32 +02001617 0, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001618 if (err)
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001619 return err;
1620
Fabio Estevamdcedf622013-12-02 00:50:02 -02001621 err = clk_prepare_enable(host->clk);
1622 if (err)
1623 return err;
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001624 host->clk_act = 1;
Ivo Claryssed4840182010-04-08 16:14:44 +02001625
Sascha Hauer63f14742010-10-18 10:16:26 +02001626 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001627 * Now that we "own" the interrupt make sure the interrupt mask bit is
1628 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1629 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001630 */
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001631 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +02001632 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001633 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001634 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001635
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001636 /* first scan to find the device and get the page size */
Shawn Guo4d624352012-09-15 13:34:09 +08001637 if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001638 err = -ENXIO;
1639 goto escan;
1640 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001641
Huang Shijiea5900552013-12-21 00:02:27 +08001642 /* allocate the right size buffer now */
1643 devm_kfree(&pdev->dev, (void *)host->data_buf);
1644 host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
1645 GFP_KERNEL);
1646 if (!host->data_buf) {
1647 err = -ENOMEM;
1648 goto escan;
1649 }
1650
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001651 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001652 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001653
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001654 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001655 this->ecc.layout = host->devtype_data->ecclayout_2k;
Baruch Siach8eeb4c52015-05-13 11:17:39 +03001656 else if (mtd->writesize == 4096) {
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001657 this->ecc.layout = host->devtype_data->ecclayout_4k;
Baruch Siach8eeb4c52015-05-13 11:17:39 +03001658 if (get_eccsize(mtd) == 8)
1659 ecc_8bit_layout_4k(this->ecc.layout);
1660 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001661
Baruch Siach7e7e4732015-05-13 11:17:37 +03001662 /*
1663 * Experimentation shows that i.MX NFC can only handle up to 218 oob
1664 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
1665 * into copying invalid data to/from the spare IO buffer, as this
1666 * might cause ECC data corruption when doing sub-page write to a
1667 * partially written page.
1668 */
1669 host->used_oobsize = min(mtd->oobsize, 218U);
1670
Mike Dunn6a918ba2012-03-11 14:21:11 -07001671 if (this->ecc.mode == NAND_ECC_HW) {
Shawn Guo4d624352012-09-15 13:34:09 +08001672 if (is_imx21_nfc(host) || is_imx27_nfc(host))
Mike Dunn6a918ba2012-03-11 14:21:11 -07001673 this->ecc.strength = 1;
1674 else
1675 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1676 }
1677
Sascha Hauer4a43faf2012-05-25 16:22:42 +02001678 /* second phase scan */
1679 if (nand_scan_tail(mtd)) {
1680 err = -ENXIO;
1681 goto escan;
1682 }
1683
Sascha Hauer34f6e152008-09-02 17:16:59 +02001684 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001685 mtd_device_parse_register(mtd, part_probes,
1686 &(struct mtd_part_parser_data){
1687 .of_node = pdev->dev.of_node,
1688 },
1689 host->pdata.parts,
1690 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001691
1692 platform_set_drvdata(pdev, host);
1693
1694 return 0;
1695
1696escan:
Lothar Waßmannc10d8ee2012-12-06 08:42:27 +01001697 if (host->clk_act)
1698 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001699
1700 return err;
1701}
1702
Bill Pemberton810b7e02012-11-19 13:26:04 -05001703static int mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001704{
1705 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1706
Sascha Hauer34f6e152008-09-02 17:16:59 +02001707 nand_release(&host->mtd);
Wei Yongjun8bfd4f72013-12-17 11:35:35 +08001708 if (host->clk_act)
1709 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001710
1711 return 0;
1712}
1713
Sascha Hauer34f6e152008-09-02 17:16:59 +02001714static struct platform_driver mxcnd_driver = {
1715 .driver = {
1716 .name = DRIVER_NAME,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001717 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001718 },
Shawn Guo4d624352012-09-15 13:34:09 +08001719 .id_table = mxcnd_devtype,
Fabio Estevamddf16d62012-09-05 11:35:25 -03001720 .probe = mxcnd_probe,
Bill Pemberton5153b882012-11-19 13:21:24 -05001721 .remove = mxcnd_remove,
Sascha Hauer34f6e152008-09-02 17:16:59 +02001722};
Fabio Estevamddf16d62012-09-05 11:35:25 -03001723module_platform_driver(mxcnd_driver);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001724
1725MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1726MODULE_DESCRIPTION("MXC NAND MTD driver");
1727MODULE_LICENSE("GPL");