blob: 23e075428dc48bdea316f69a93a9d7a6a7c37d63 [file] [log] [blame]
Sascha Hauer34f6e152008-09-02 17:16:59 +02001/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#include <linux/delay.h>
21#include <linux/slab.h>
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/mtd/mtd.h>
25#include <linux/mtd/nand.h>
26#include <linux/mtd/partitions.h>
27#include <linux/interrupt.h>
28#include <linux/device.h>
29#include <linux/platform_device.h>
30#include <linux/clk.h>
31#include <linux/err.h>
32#include <linux/io.h>
Sascha Hauer63f14742010-10-18 10:16:26 +020033#include <linux/irq.h>
34#include <linux/completion.h>
Sachin Kamatd367e372013-10-18 16:16:35 +053035#include <linux/of.h>
Uwe Kleine-König64363562012-04-23 11:23:41 +020036#include <linux/of_device.h>
37#include <linux/of_mtd.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020038
39#include <asm/mach/flash.h>
Arnd Bergmann82906b12012-08-24 15:14:29 +020040#include <linux/platform_data/mtd-mxc_nand.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020041
42#define DRIVER_NAME "mxc_nand"
43
44/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020045#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
46#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
47#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
48#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
49#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
50#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
51#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
52#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
53#define NFC_V1_V2_WRPROT (host->regs + 0x12)
54#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
55#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
Baruch Siachd178e3e2011-03-14 09:01:56 +020056#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
57#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
58#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
59#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
60#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
61#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
62#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
63#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
Sascha Hauer1bc99182010-08-06 15:53:08 +020064#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
65#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
66#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020067
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020068#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020069#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
70#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
71#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
72#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
73#define NFC_V1_V2_CONFIG1_RST (1 << 6)
74#define NFC_V1_V2_CONFIG1_CE (1 << 7)
Sascha Hauerb8db2f52010-08-09 15:04:19 +020075#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
76#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
77#define NFC_V2_CONFIG1_FP_INT (1 << 11)
Sascha Hauer34f6e152008-09-02 17:16:59 +020078
Sascha Hauer1bc99182010-08-06 15:53:08 +020079#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020080
Sascha Hauer1bc99182010-08-06 15:53:08 +020081/*
82 * Operation modes for the NFC. Valid for v1, v2 and v3
83 * type controllers.
84 */
85#define NFC_CMD (1 << 0)
86#define NFC_ADDR (1 << 1)
87#define NFC_INPUT (1 << 2)
88#define NFC_OUTPUT (1 << 3)
89#define NFC_ID (1 << 4)
90#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020091
Sascha Hauer71ec5152010-08-06 15:53:11 +020092#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
93#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
Sascha Hauer34f6e152008-09-02 17:16:59 +020094
Sascha Hauer71ec5152010-08-06 15:53:11 +020095#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
96#define NFC_V3_CONFIG1_SP_EN (1 << 0)
97#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
Sascha Hauer34f6e152008-09-02 17:16:59 +020098
Sascha Hauer71ec5152010-08-06 15:53:11 +020099#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200100
Sascha Hauer71ec5152010-08-06 15:53:11 +0200101#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200102
Sascha Hauer71ec5152010-08-06 15:53:11 +0200103#define NFC_V3_WRPROT (host->regs_ip + 0x0)
104#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
105#define NFC_V3_WRPROT_LOCK (1 << 1)
106#define NFC_V3_WRPROT_UNLOCK (1 << 2)
107#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
108
109#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
110
111#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
112#define NFC_V3_CONFIG2_PS_512 (0 << 0)
113#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
114#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
115#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
116#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
117#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
118#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
119#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200120#define NFC_V3_CONFIG2_PPB(x, shift) (((x) & 0x3) << shift)
Sascha Hauer71ec5152010-08-06 15:53:11 +0200121#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
122#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
123#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
124#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
125
126#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
127#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
128#define NFC_V3_CONFIG3_FW8 (1 << 3)
129#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
130#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
131#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
132#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
133
134#define NFC_V3_IPC (host->regs_ip + 0x2C)
135#define NFC_V3_IPC_CREQ (1 << 0)
136#define NFC_V3_IPC_INT (1 << 31)
137
138#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200139
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200140struct mxc_nand_host;
141
142struct mxc_nand_devtype_data {
143 void (*preset)(struct mtd_info *);
144 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
145 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
146 void (*send_page)(struct mtd_info *, unsigned int);
147 void (*send_read_id)(struct mxc_nand_host *);
148 uint16_t (*get_dev_status)(struct mxc_nand_host *);
149 int (*check_int)(struct mxc_nand_host *);
150 void (*irq_control)(struct mxc_nand_host *, int);
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200151 u32 (*get_ecc_status)(struct mxc_nand_host *);
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +0200152 struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k;
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200153 void (*select_chip)(struct mtd_info *mtd, int chip);
Uwe Kleine-König69d023b2012-04-23 11:23:39 +0200154 int (*correct_data)(struct mtd_info *mtd, u_char *dat,
155 u_char *read_ecc, u_char *calc_ecc);
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200156
157 /*
158 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
159 * (CONFIG1:INT_MSK is set). To handle this the driver uses
160 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
161 */
162 int irqpending_quirk;
163 int needs_ip;
164
165 size_t regs_offset;
166 size_t spare0_offset;
167 size_t axi_offset;
168
169 int spare_len;
170 int eccbytes;
171 int eccsize;
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200172 int ppb_shift;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200173};
174
Sascha Hauer34f6e152008-09-02 17:16:59 +0200175struct mxc_nand_host {
176 struct mtd_info mtd;
177 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200178 struct device *dev;
179
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200180 void __iomem *spare0;
181 void __iomem *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200182
183 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200184 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200185 void __iomem *regs_axi;
186 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200187 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200188 struct clk *clk;
189 int clk_act;
190 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200191 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200192 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200193
Sascha Hauer63f14742010-10-18 10:16:26 +0200194 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200195
196 uint8_t *data_buf;
197 unsigned int buf_start;
Sascha Hauer5f973042010-08-06 15:53:06 +0200198
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200199 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König64363562012-04-23 11:23:41 +0200200 struct mxc_nand_platform_data pdata;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200201};
202
Sascha Hauer34f6e152008-09-02 17:16:59 +0200203/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200204static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200205 .eccbytes = 5,
206 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200207 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200208};
209
Sascha Hauer94671142009-10-05 12:14:21 +0200210static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400211 .eccbytes = 20,
212 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
213 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
214 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200215};
216
Sascha Hauer94671142009-10-05 12:14:21 +0200217/* OOB description for 512 byte pages with 16 byte OOB */
218static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
219 .eccbytes = 1 * 9,
220 .eccpos = {
221 7, 8, 9, 10, 11, 12, 13, 14, 15
222 },
223 .oobfree = {
224 {.offset = 0, .length = 5}
225 }
226};
227
228/* OOB description for 2048 byte pages with 64 byte OOB */
229static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
230 .eccbytes = 4 * 9,
231 .eccpos = {
232 7, 8, 9, 10, 11, 12, 13, 14, 15,
233 23, 24, 25, 26, 27, 28, 29, 30, 31,
234 39, 40, 41, 42, 43, 44, 45, 46, 47,
235 55, 56, 57, 58, 59, 60, 61, 62, 63
236 },
237 .oobfree = {
238 {.offset = 2, .length = 4},
239 {.offset = 16, .length = 7},
240 {.offset = 32, .length = 7},
241 {.offset = 48, .length = 7}
242 }
243};
244
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200245/* OOB description for 4096 byte pages with 128 byte OOB */
246static struct nand_ecclayout nandv2_hw_eccoob_4k = {
247 .eccbytes = 8 * 9,
248 .eccpos = {
249 7, 8, 9, 10, 11, 12, 13, 14, 15,
250 23, 24, 25, 26, 27, 28, 29, 30, 31,
251 39, 40, 41, 42, 43, 44, 45, 46, 47,
252 55, 56, 57, 58, 59, 60, 61, 62, 63,
253 71, 72, 73, 74, 75, 76, 77, 78, 79,
254 87, 88, 89, 90, 91, 92, 93, 94, 95,
255 103, 104, 105, 106, 107, 108, 109, 110, 111,
256 119, 120, 121, 122, 123, 124, 125, 126, 127,
257 },
258 .oobfree = {
259 {.offset = 2, .length = 4},
260 {.offset = 16, .length = 7},
261 {.offset = 32, .length = 7},
262 {.offset = 48, .length = 7},
263 {.offset = 64, .length = 7},
264 {.offset = 80, .length = 7},
265 {.offset = 96, .length = 7},
266 {.offset = 112, .length = 7},
267 }
268};
269
Jingoo Hanb2ac0372013-08-07 16:18:52 +0900270static const char * const part_probes[] = {
Lothar Waßmann740bb0c2012-12-06 08:42:28 +0100271 "cmdlinepart", "RedBoot", "ofpart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200272
Sascha Hauer096bcc22012-05-29 10:16:09 +0200273static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
274{
275 int i;
276 u32 *t = trg;
277 const __iomem u32 *s = src;
278
279 for (i = 0; i < (size >> 2); i++)
280 *t++ = __raw_readl(s++);
281}
282
Koul, Vinod33a87a12014-10-20 21:36:13 +0530283static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200284{
Koul, Vinod33a87a12014-10-20 21:36:13 +0530285 /* __iowrite32_copy use 32bit size values so divide by 4 */
286 __iowrite32_copy(trg, src, size / 4);
Sascha Hauer096bcc22012-05-29 10:16:09 +0200287}
288
Sascha Hauer71ec5152010-08-06 15:53:11 +0200289static int check_int_v3(struct mxc_nand_host *host)
290{
291 uint32_t tmp;
292
293 tmp = readl(NFC_V3_IPC);
294 if (!(tmp & NFC_V3_IPC_INT))
295 return 0;
296
297 tmp &= ~NFC_V3_IPC_INT;
298 writel(tmp, NFC_V3_IPC);
299
300 return 1;
301}
302
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200303static int check_int_v1_v2(struct mxc_nand_host *host)
304{
305 uint32_t tmp;
306
Sascha Hauer1bc99182010-08-06 15:53:08 +0200307 tmp = readw(NFC_V1_V2_CONFIG2);
308 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200309 return 0;
310
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200311 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200312 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200313
314 return 1;
315}
316
Sascha Hauer63f14742010-10-18 10:16:26 +0200317static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
318{
319 uint16_t tmp;
320
321 tmp = readw(NFC_V1_V2_CONFIG1);
322
323 if (activate)
324 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
325 else
326 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
327
328 writew(tmp, NFC_V1_V2_CONFIG1);
329}
330
331static void irq_control_v3(struct mxc_nand_host *host, int activate)
332{
333 uint32_t tmp;
334
335 tmp = readl(NFC_V3_CONFIG2);
336
337 if (activate)
338 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
339 else
340 tmp |= NFC_V3_CONFIG2_INT_MSK;
341
342 writel(tmp, NFC_V3_CONFIG2);
343}
344
Uwe Kleine-König85569582012-04-23 11:23:34 +0200345static void irq_control(struct mxc_nand_host *host, int activate)
346{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200347 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200348 if (activate)
349 enable_irq(host->irq);
350 else
351 disable_irq_nosync(host->irq);
352 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200353 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200354 }
355}
356
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200357static u32 get_ecc_status_v1(struct mxc_nand_host *host)
358{
359 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
360}
361
362static u32 get_ecc_status_v2(struct mxc_nand_host *host)
363{
364 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
365}
366
367static u32 get_ecc_status_v3(struct mxc_nand_host *host)
368{
369 return readl(NFC_V3_ECC_STATUS_RESULT);
370}
371
Uwe Kleine-König85569582012-04-23 11:23:34 +0200372static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
373{
374 struct mxc_nand_host *host = dev_id;
375
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200376 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200377 return IRQ_NONE;
378
379 irq_control(host, 0);
380
381 complete(&host->op_completion);
382
383 return IRQ_HANDLED;
384}
385
Sascha Hauer34f6e152008-09-02 17:16:59 +0200386/* This function polls the NANDFC to wait for the basic operation to
387 * complete by checking the INT bit of config2 register.
388 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200389static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200390{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200391 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200392
393 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200394 if (!host->devtype_data->check_int(host)) {
Wolfram Sang16735d02013-11-14 14:32:02 -0800395 reinit_completion(&host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200396 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200397 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200398 }
399 } else {
400 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200401 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200402 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200403
Sascha Hauer34f6e152008-09-02 17:16:59 +0200404 udelay(1);
405 }
Roel Kluin43950a62009-06-04 16:24:59 +0200406 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700407 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200408 }
409}
410
Sascha Hauer71ec5152010-08-06 15:53:11 +0200411static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
412{
413 /* fill command */
414 writel(cmd, NFC_V3_FLASH_CMD);
415
416 /* send out command */
417 writel(NFC_CMD, NFC_V3_LAUNCH);
418
419 /* Wait for operation to complete */
420 wait_op_done(host, useirq);
421}
422
Sascha Hauer34f6e152008-09-02 17:16:59 +0200423/* This function issues the specified command to the NAND device and
424 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200425static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200426{
Brian Norris289c0522011-07-19 10:06:09 -0700427 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200428
Sascha Hauer1bc99182010-08-06 15:53:08 +0200429 writew(cmd, NFC_V1_V2_FLASH_CMD);
430 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200431
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200432 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200433 int max_retries = 100;
434 /* Reset completion is indicated by NFC_CONFIG2 */
435 /* being set to 0 */
436 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200437 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200438 break;
439 }
440 udelay(1);
441 }
442 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700443 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200444 } else {
445 /* Wait for operation to complete */
446 wait_op_done(host, useirq);
447 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200448}
449
Sascha Hauer71ec5152010-08-06 15:53:11 +0200450static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
451{
452 /* fill address */
453 writel(addr, NFC_V3_FLASH_ADDR0);
454
455 /* send out address */
456 writel(NFC_ADDR, NFC_V3_LAUNCH);
457
458 wait_op_done(host, 0);
459}
460
Sascha Hauer34f6e152008-09-02 17:16:59 +0200461/* This function sends an address (or partial address) to the
462 * NAND device. The address is used to select the source/destination for
463 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200464static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200465{
Brian Norris289c0522011-07-19 10:06:09 -0700466 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200467
Sascha Hauer1bc99182010-08-06 15:53:08 +0200468 writew(addr, NFC_V1_V2_FLASH_ADDR);
469 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200470
471 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200472 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200473}
474
Sascha Hauer71ec5152010-08-06 15:53:11 +0200475static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
476{
477 struct nand_chip *nand_chip = mtd->priv;
478 struct mxc_nand_host *host = nand_chip->priv;
479 uint32_t tmp;
480
481 tmp = readl(NFC_V3_CONFIG1);
482 tmp &= ~(7 << 4);
483 writel(tmp, NFC_V3_CONFIG1);
484
485 /* transfer data from NFC ram to nand */
486 writel(ops, NFC_V3_LAUNCH);
487
488 wait_op_done(host, false);
489}
490
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200491static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
492{
493 struct nand_chip *nand_chip = mtd->priv;
494 struct mxc_nand_host *host = nand_chip->priv;
495
496 /* NANDFC buffer 0 is used for page read/write */
497 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
498
499 writew(ops, NFC_V1_V2_CONFIG2);
500
501 /* Wait for operation to complete */
502 wait_op_done(host, true);
503}
504
505static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200506{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200507 struct nand_chip *nand_chip = mtd->priv;
508 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200509 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200510
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200511 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200512 bufs = 4;
513 else
514 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200515
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200516 for (i = 0; i < bufs; i++) {
517
518 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200519 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200520
Sascha Hauer1bc99182010-08-06 15:53:08 +0200521 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200522
523 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200524 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200525 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200526}
527
Sascha Hauer71ec5152010-08-06 15:53:11 +0200528static void send_read_id_v3(struct mxc_nand_host *host)
529{
Roman Schneidera8459f22013-01-15 16:56:24 +0100530 struct nand_chip *this = &host->nand;
531
Sascha Hauer71ec5152010-08-06 15:53:11 +0200532 /* Read ID into main buffer */
533 writel(NFC_ID, NFC_V3_LAUNCH);
534
535 wait_op_done(host, true);
536
Sascha Hauer096bcc22012-05-29 10:16:09 +0200537 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Roman Schneidera8459f22013-01-15 16:56:24 +0100538
539 if (this->options & NAND_BUSWIDTH_16) {
540 /* compress the ID info */
541 host->data_buf[1] = host->data_buf[2];
542 host->data_buf[2] = host->data_buf[4];
543 host->data_buf[3] = host->data_buf[6];
544 host->data_buf[4] = host->data_buf[8];
545 host->data_buf[5] = host->data_buf[10];
546 }
Sascha Hauer71ec5152010-08-06 15:53:11 +0200547}
548
Sascha Hauer34f6e152008-09-02 17:16:59 +0200549/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200550static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551{
552 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200553
554 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200555 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200556
Sascha Hauer1bc99182010-08-06 15:53:08 +0200557 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200558
559 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200560 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200561
Sascha Hauer096bcc22012-05-29 10:16:09 +0200562 memcpy32_fromio(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200563
564 if (this->options & NAND_BUSWIDTH_16) {
565 /* compress the ID info */
566 host->data_buf[1] = host->data_buf[2];
567 host->data_buf[2] = host->data_buf[4];
568 host->data_buf[3] = host->data_buf[6];
569 host->data_buf[4] = host->data_buf[8];
570 host->data_buf[5] = host->data_buf[10];
571 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200572}
573
Sascha Hauer71ec5152010-08-06 15:53:11 +0200574static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200575{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200576 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200577 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200578
Sascha Hauer71ec5152010-08-06 15:53:11 +0200579 return readl(NFC_V3_CONFIG1) >> 16;
580}
581
Sascha Hauer34f6e152008-09-02 17:16:59 +0200582/* This function requests the NANDFC to perform a read of the
583 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200584static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200585{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200586 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200587 uint32_t store;
588 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200589
Baruch Siachd178e3e2011-03-14 09:01:56 +0200590 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200591
592 /*
593 * The device status is stored in main_area0. To
594 * prevent corruption of the buffer save the value
595 * and restore it afterwards.
596 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200597 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200598
Sascha Hauer1bc99182010-08-06 15:53:08 +0200599 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200600 wait_op_done(host, true);
601
Sascha Hauer34f6e152008-09-02 17:16:59 +0200602 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200603
Sascha Hauer34f6e152008-09-02 17:16:59 +0200604 writel(store, main_buf);
605
606 return ret;
607}
608
609/* This functions is used by upper layer to checks if device is ready */
610static int mxc_nand_dev_ready(struct mtd_info *mtd)
611{
612 /*
613 * NFC handles R/B internally. Therefore, this function
614 * always returns status as ready.
615 */
616 return 1;
617}
618
619static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
620{
621 /*
622 * If HW ECC is enabled, we turn it on during init. There is
623 * no need to enable again here.
624 */
625}
626
Sascha Hauer94f77e52010-08-06 15:53:09 +0200627static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200628 u_char *read_ecc, u_char *calc_ecc)
629{
630 struct nand_chip *nand_chip = mtd->priv;
631 struct mxc_nand_host *host = nand_chip->priv;
632
633 /*
634 * 1-Bit errors are automatically corrected in HW. No need for
635 * additional correction. 2-Bit errors cannot be corrected by
636 * HW ECC, so we need to return failure
637 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200638 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200639
640 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700641 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200642 return -1;
643 }
644
645 return 0;
646}
647
Sascha Hauer94f77e52010-08-06 15:53:09 +0200648static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
649 u_char *read_ecc, u_char *calc_ecc)
650{
651 struct nand_chip *nand_chip = mtd->priv;
652 struct mxc_nand_host *host = nand_chip->priv;
653 u32 ecc_stat, err;
654 int no_subpages = 1;
655 int ret = 0;
656 u8 ecc_bit_mask, err_limit;
657
658 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
659 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
660
661 no_subpages = mtd->writesize >> 9;
662
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200663 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200664
665 do {
666 err = ecc_stat & ecc_bit_mask;
667 if (err > err_limit) {
668 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
669 return -1;
670 } else {
671 ret += err;
672 }
673 ecc_stat >>= 4;
674 } while (--no_subpages);
675
Sascha Hauer94f77e52010-08-06 15:53:09 +0200676 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
677
678 return ret;
679}
680
Sascha Hauer34f6e152008-09-02 17:16:59 +0200681static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
682 u_char *ecc_code)
683{
684 return 0;
685}
686
687static u_char mxc_nand_read_byte(struct mtd_info *mtd)
688{
689 struct nand_chip *nand_chip = mtd->priv;
690 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200691 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200692
693 /* Check for status request */
694 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200695 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200696
Sascha Hauerf8f96082009-06-04 17:12:26 +0200697 ret = *(uint8_t *)(host->data_buf + host->buf_start);
698 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200699
700 return ret;
701}
702
703static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
704{
705 struct nand_chip *nand_chip = mtd->priv;
706 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200707 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200708
Sascha Hauerf8f96082009-06-04 17:12:26 +0200709 ret = *(uint16_t *)(host->data_buf + host->buf_start);
710 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200711
712 return ret;
713}
714
715/* Write data of length len to buffer buf. The data to be
716 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
717 * Operation by the NFC, the data is written to NAND Flash */
718static void mxc_nand_write_buf(struct mtd_info *mtd,
719 const u_char *buf, int len)
720{
721 struct nand_chip *nand_chip = mtd->priv;
722 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200723 u16 col = host->buf_start;
724 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200725
Sascha Hauerf8f96082009-06-04 17:12:26 +0200726 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200727
Sascha Hauerf8f96082009-06-04 17:12:26 +0200728 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200729
Sascha Hauerf8f96082009-06-04 17:12:26 +0200730 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200731}
732
733/* Read the data buffer from the NAND Flash. To read the data from NAND
734 * Flash first the data output cycle is initiated by the NFC, which copies
735 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
736 */
737static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
738{
739 struct nand_chip *nand_chip = mtd->priv;
740 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200741 u16 col = host->buf_start;
742 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200743
Sascha Hauerf8f96082009-06-04 17:12:26 +0200744 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200745
Baruch Siach5d9d9932011-03-02 16:47:55 +0200746 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200747
Baruch Siach5d9d9932011-03-02 16:47:55 +0200748 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200749}
750
Sascha Hauer34f6e152008-09-02 17:16:59 +0200751/* This function is used by upper layer for select and
752 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200753static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200754{
755 struct nand_chip *nand_chip = mtd->priv;
756 struct mxc_nand_host *host = nand_chip->priv;
757
Baruch Siachd178e3e2011-03-14 09:01:56 +0200758 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200759 /* Disable the NFC clock */
760 if (host->clk_act) {
Sascha Hauer97c32132012-03-07 20:56:35 +0100761 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200762 host->clk_act = 0;
763 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200764 return;
765 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200766
Baruch Siachd178e3e2011-03-14 09:01:56 +0200767 if (!host->clk_act) {
768 /* Enable the NFC clock */
Sascha Hauer97c32132012-03-07 20:56:35 +0100769 clk_prepare_enable(host->clk);
Baruch Siachd178e3e2011-03-14 09:01:56 +0200770 host->clk_act = 1;
771 }
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200772}
Baruch Siachd178e3e2011-03-14 09:01:56 +0200773
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200774static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200775{
776 struct nand_chip *nand_chip = mtd->priv;
777 struct mxc_nand_host *host = nand_chip->priv;
778
779 if (chip == -1) {
780 /* Disable the NFC clock */
781 if (host->clk_act) {
Fabio Estevam3d059692012-05-25 20:14:50 -0300782 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200783 host->clk_act = 0;
784 }
785 return;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200786 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200787
788 if (!host->clk_act) {
789 /* Enable the NFC clock */
Fabio Estevam3d059692012-05-25 20:14:50 -0300790 clk_prepare_enable(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200791 host->clk_act = 1;
792 }
793
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200794 host->active_cs = chip;
795 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200796}
797
Sascha Hauerf8f96082009-06-04 17:12:26 +0200798/*
799 * Function to transfer data to/from spare area.
800 */
801static void copy_spare(struct mtd_info *mtd, bool bfrom)
802{
803 struct nand_chip *this = mtd->priv;
804 struct mxc_nand_host *host = this->priv;
805 u16 i, j;
806 u16 n = mtd->writesize >> 9;
807 u8 *d = host->data_buf + mtd->writesize;
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200808 u8 __iomem *s = host->spare0;
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200809 u16 t = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200810
811 j = (mtd->oobsize / n >> 1) << 1;
812
813 if (bfrom) {
814 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200815 memcpy32_fromio(d + i * j, s + i * t, j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200816
817 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200818 memcpy32_fromio(d + i * j, s + i * t, mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200819 } else {
820 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200821 memcpy32_toio(&s[i * t], &d[i * j], j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200822
823 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200824 memcpy32_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200825 }
826}
827
Sascha Hauera3e65b62009-06-02 11:47:59 +0200828static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200829{
830 struct nand_chip *nand_chip = mtd->priv;
831 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200832
833 /* Write out column address, if necessary */
834 if (column != -1) {
835 /*
836 * MXC NANDFC can only perform full page+spare or
837 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100838 * perform a read/write buf operation, the saved column
839 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200840 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200841 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200842 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200843 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200844 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200845 }
846
847 /* Write out page address, if necessary */
848 if (page_addr != -1) {
849 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200850 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200851
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200852 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400853 if (mtd->size >= 0x10000000) {
854 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200855 host->devtype_data->send_addr(host,
856 (page_addr >> 8) & 0xff,
857 false);
858 host->devtype_data->send_addr(host,
859 (page_addr >> 16) & 0xff,
860 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400861 } else
862 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200863 host->devtype_data->send_addr(host,
864 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200865 } else {
866 /* One more address cycle for higher density devices */
867 if (mtd->size >= 0x4000000) {
868 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200869 host->devtype_data->send_addr(host,
870 (page_addr >> 8) & 0xff,
871 false);
872 host->devtype_data->send_addr(host,
873 (page_addr >> 16) & 0xff,
874 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200875 } else
876 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200877 host->devtype_data->send_addr(host,
878 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200879 }
880 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200881}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200882
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200883/*
884 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
885 * on how much oob the nand chip has. For 8bit ecc we need at least
886 * 26 bytes of oob data per 512 byte block.
887 */
888static int get_eccsize(struct mtd_info *mtd)
889{
890 int oobbytes_per_512 = 0;
891
892 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
893
894 if (oobbytes_per_512 < 26)
895 return 4;
896 else
897 return 8;
898}
899
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200900static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200901{
902 struct nand_chip *nand_chip = mtd->priv;
903 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200904 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200905
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200906 if (nand_chip->ecc.mode == NAND_ECC_HW)
907 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
908
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200909 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200910 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200911
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200912 host->eccsize = 1;
913
914 writew(config1, NFC_V1_V2_CONFIG1);
915 /* preset operation */
916
917 /* Unlock the internal RAM Buffer */
918 writew(0x2, NFC_V1_V2_CONFIG);
919
920 /* Blocks to be unlocked */
921 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
922 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
923
924 /* Unlock Block Command for given address range */
925 writew(0x4, NFC_V1_V2_WRPROT);
926}
927
928static void preset_v2(struct mtd_info *mtd)
929{
930 struct nand_chip *nand_chip = mtd->priv;
931 struct mxc_nand_host *host = nand_chip->priv;
932 uint16_t config1 = 0;
933
934 if (nand_chip->ecc.mode == NAND_ECC_HW)
935 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
936
937 config1 |= NFC_V2_CONFIG1_FP_INT;
Ivo Claryssed4840182010-04-08 16:14:44 +0200938
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200939 if (!host->devtype_data->irqpending_quirk)
Ivo Claryssed4840182010-04-08 16:14:44 +0200940 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200941
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200942 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200943 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
944
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200945 host->eccsize = get_eccsize(mtd);
946 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200947 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
948
949 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200950 } else {
951 host->eccsize = 1;
952 }
953
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200954 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200955 /* preset operation */
956
957 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200958 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200959
960 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200961 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
962 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
963 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
964 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
965 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
966 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
967 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
968 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200969
970 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200971 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200972}
973
Sascha Hauer71ec5152010-08-06 15:53:11 +0200974static void preset_v3(struct mtd_info *mtd)
975{
976 struct nand_chip *chip = mtd->priv;
977 struct mxc_nand_host *host = chip->priv;
978 uint32_t config2, config3;
979 int i, addr_phases;
980
981 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
982 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
983
984 /* Unlock the internal RAM Buffer */
985 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
986 NFC_V3_WRPROT);
987
988 /* Blocks to be unlocked */
989 for (i = 0; i < NAND_MAX_CHIPS; i++)
990 writel(0x0 | (0xffff << 16),
991 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
992
993 writel(0, NFC_V3_IPC);
994
995 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
996 NFC_V3_CONFIG2_2CMD_PHASES |
997 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
998 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +0200999 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +02001000 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
1001
1002 if (chip->ecc.mode == NAND_ECC_HW)
1003 config2 |= NFC_V3_CONFIG2_ECC_EN;
1004
1005 addr_phases = fls(chip->pagemask) >> 3;
1006
1007 if (mtd->writesize == 2048) {
1008 config2 |= NFC_V3_CONFIG2_PS_2048;
1009 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1010 } else if (mtd->writesize == 4096) {
1011 config2 |= NFC_V3_CONFIG2_PS_4096;
1012 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1013 } else {
1014 config2 |= NFC_V3_CONFIG2_PS_512;
1015 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1016 }
1017
1018 if (mtd->writesize) {
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001019 config2 |= NFC_V3_CONFIG2_PPB(
1020 ffs(mtd->erasesize / mtd->writesize) - 6,
1021 host->devtype_data->ppb_shift);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001022 host->eccsize = get_eccsize(mtd);
1023 if (host->eccsize == 8)
1024 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
1025 }
1026
1027 writel(config2, NFC_V3_CONFIG2);
1028
1029 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1030 NFC_V3_CONFIG3_NO_SDMA |
1031 NFC_V3_CONFIG3_RBB_MODE |
1032 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1033 NFC_V3_CONFIG3_ADD_OP(0);
1034
1035 if (!(chip->options & NAND_BUSWIDTH_16))
1036 config3 |= NFC_V3_CONFIG3_FW8;
1037
1038 writel(config3, NFC_V3_CONFIG3);
1039
1040 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001041}
1042
Sascha Hauer34f6e152008-09-02 17:16:59 +02001043/* Used by the upper layer to write command to NAND Flash for
1044 * different operations to be carried out on NAND Flash */
1045static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1046 int column, int page_addr)
1047{
1048 struct nand_chip *nand_chip = mtd->priv;
1049 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001050
Brian Norris289c0522011-07-19 10:06:09 -07001051 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001052 command, column, page_addr);
1053
1054 /* Reset command state information */
1055 host->status_request = false;
1056
1057 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001058 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001059 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001060 host->devtype_data->preset(mtd);
1061 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001062 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001063
Sascha Hauer34f6e152008-09-02 17:16:59 +02001064 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001065 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001066 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001067
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001068 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001069 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001070 break;
1071
Sascha Hauer34f6e152008-09-02 17:16:59 +02001072 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001073 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001074 if (command == NAND_CMD_READ0)
1075 host->buf_start = column;
1076 else
1077 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001078
Sascha Hauer5ea32022010-04-27 15:24:01 +02001079 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001080
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001081 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001082 mxc_do_addr_cycle(mtd, column, page_addr);
1083
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001084 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001085 host->devtype_data->send_cmd(host,
1086 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001087
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001088 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001089
Sascha Hauer096bcc22012-05-29 10:16:09 +02001090 memcpy32_fromio(host->data_buf, host->main_area0,
1091 mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001092 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001093 break;
1094
Sascha Hauer34f6e152008-09-02 17:16:59 +02001095 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001096 if (column >= mtd->writesize)
1097 /* call ourself to read a page */
1098 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001099
Sascha Hauer5ea32022010-04-27 15:24:01 +02001100 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001101
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001102 host->devtype_data->send_cmd(host, command, false);
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
1106 case NAND_CMD_PAGEPROG:
Sascha Hauer096bcc22012-05-29 10:16:09 +02001107 memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001108 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001109 host->devtype_data->send_page(mtd, NFC_INPUT);
1110 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001111 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001112 break;
1113
Sascha Hauer34f6e152008-09-02 17:16:59 +02001114 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001115 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001116 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001117 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001118 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001119 break;
1120
Sascha Hauer89121a62009-06-04 17:18:01 +02001121 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001122 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001123 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001124 mxc_do_addr_cycle(mtd, column, page_addr);
1125
Sascha Hauer34f6e152008-09-02 17:16:59 +02001126 break;
1127 }
1128}
1129
Sascha Hauerf1372052009-10-21 14:25:27 +02001130/*
1131 * The generic flash bbt decriptors overlap with our ecc
1132 * hardware, so define some i.MX specific ones.
1133 */
1134static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1135static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1136
1137static struct nand_bbt_descr bbt_main_descr = {
1138 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1139 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1140 .offs = 0,
1141 .len = 4,
1142 .veroffs = 4,
1143 .maxblocks = 4,
1144 .pattern = bbt_pattern,
1145};
1146
1147static struct nand_bbt_descr bbt_mirror_descr = {
1148 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1149 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1150 .offs = 0,
1151 .len = 4,
1152 .veroffs = 4,
1153 .maxblocks = 4,
1154 .pattern = mirror_pattern,
1155};
1156
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001157/* v1 + irqpending_quirk: i.MX21 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001158static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001159 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001160 .send_cmd = send_cmd_v1_v2,
1161 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001162 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001163 .send_read_id = send_read_id_v1_v2,
1164 .get_dev_status = get_dev_status_v1_v2,
1165 .check_int = check_int_v1_v2,
1166 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001167 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001168 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1169 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1170 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001171 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001172 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001173 .irqpending_quirk = 1,
1174 .needs_ip = 0,
1175 .regs_offset = 0xe00,
1176 .spare0_offset = 0x800,
1177 .spare_len = 16,
1178 .eccbytes = 3,
1179 .eccsize = 1,
1180};
1181
1182/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1183static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1184 .preset = preset_v1,
1185 .send_cmd = send_cmd_v1_v2,
1186 .send_addr = send_addr_v1_v2,
1187 .send_page = send_page_v1,
1188 .send_read_id = send_read_id_v1_v2,
1189 .get_dev_status = get_dev_status_v1_v2,
1190 .check_int = check_int_v1_v2,
1191 .irq_control = irq_control_v1_v2,
1192 .get_ecc_status = get_ecc_status_v1,
1193 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1194 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1195 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1196 .select_chip = mxc_nand_select_chip_v1_v3,
1197 .correct_data = mxc_nand_correct_data_v1,
1198 .irqpending_quirk = 0,
1199 .needs_ip = 0,
1200 .regs_offset = 0xe00,
1201 .spare0_offset = 0x800,
1202 .axi_offset = 0,
1203 .spare_len = 16,
1204 .eccbytes = 3,
1205 .eccsize = 1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001206};
1207
1208/* v21: i.MX25, i.MX35 */
1209static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001210 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001211 .send_cmd = send_cmd_v1_v2,
1212 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001213 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001214 .send_read_id = send_read_id_v1_v2,
1215 .get_dev_status = get_dev_status_v1_v2,
1216 .check_int = check_int_v1_v2,
1217 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001218 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001219 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1220 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1221 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001222 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001223 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001224 .irqpending_quirk = 0,
1225 .needs_ip = 0,
1226 .regs_offset = 0x1e00,
1227 .spare0_offset = 0x1000,
1228 .axi_offset = 0,
1229 .spare_len = 64,
1230 .eccbytes = 9,
1231 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001232};
1233
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001234/* v3.2a: i.MX51 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001235static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1236 .preset = preset_v3,
1237 .send_cmd = send_cmd_v3,
1238 .send_addr = send_addr_v3,
1239 .send_page = send_page_v3,
1240 .send_read_id = send_read_id_v3,
1241 .get_dev_status = get_dev_status_v3,
1242 .check_int = check_int_v3,
1243 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001244 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001245 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1246 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1247 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001248 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001249 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001250 .irqpending_quirk = 0,
1251 .needs_ip = 1,
1252 .regs_offset = 0,
1253 .spare0_offset = 0x1000,
1254 .axi_offset = 0x1e00,
1255 .spare_len = 64,
1256 .eccbytes = 0,
1257 .eccsize = 0,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001258 .ppb_shift = 7,
1259};
1260
1261/* v3.2b: i.MX53 */
1262static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
1263 .preset = preset_v3,
1264 .send_cmd = send_cmd_v3,
1265 .send_addr = send_addr_v3,
1266 .send_page = send_page_v3,
1267 .send_read_id = send_read_id_v3,
1268 .get_dev_status = get_dev_status_v3,
1269 .check_int = check_int_v3,
1270 .irq_control = irq_control_v3,
1271 .get_ecc_status = get_ecc_status_v3,
1272 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1273 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1274 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1275 .select_chip = mxc_nand_select_chip_v1_v3,
1276 .correct_data = mxc_nand_correct_data_v2_v3,
1277 .irqpending_quirk = 0,
1278 .needs_ip = 1,
1279 .regs_offset = 0,
1280 .spare0_offset = 0x1000,
1281 .axi_offset = 0x1e00,
1282 .spare_len = 64,
1283 .eccbytes = 0,
1284 .eccsize = 0,
1285 .ppb_shift = 8,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001286};
1287
Shawn Guo4d624352012-09-15 13:34:09 +08001288static inline int is_imx21_nfc(struct mxc_nand_host *host)
1289{
1290 return host->devtype_data == &imx21_nand_devtype_data;
1291}
1292
1293static inline int is_imx27_nfc(struct mxc_nand_host *host)
1294{
1295 return host->devtype_data == &imx27_nand_devtype_data;
1296}
1297
1298static inline int is_imx25_nfc(struct mxc_nand_host *host)
1299{
1300 return host->devtype_data == &imx25_nand_devtype_data;
1301}
1302
1303static inline int is_imx51_nfc(struct mxc_nand_host *host)
1304{
1305 return host->devtype_data == &imx51_nand_devtype_data;
1306}
1307
1308static inline int is_imx53_nfc(struct mxc_nand_host *host)
1309{
1310 return host->devtype_data == &imx53_nand_devtype_data;
1311}
1312
1313static struct platform_device_id mxcnd_devtype[] = {
1314 {
1315 .name = "imx21-nand",
1316 .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
1317 }, {
1318 .name = "imx27-nand",
1319 .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
1320 }, {
1321 .name = "imx25-nand",
1322 .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
1323 }, {
1324 .name = "imx51-nand",
1325 .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
1326 }, {
1327 .name = "imx53-nand",
1328 .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
1329 }, {
1330 /* sentinel */
1331 }
1332};
1333MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
1334
Uwe Kleine-König64363562012-04-23 11:23:41 +02001335#ifdef CONFIG_OF_MTD
1336static const struct of_device_id mxcnd_dt_ids[] = {
1337 {
1338 .compatible = "fsl,imx21-nand",
1339 .data = &imx21_nand_devtype_data,
1340 }, {
1341 .compatible = "fsl,imx27-nand",
1342 .data = &imx27_nand_devtype_data,
1343 }, {
1344 .compatible = "fsl,imx25-nand",
1345 .data = &imx25_nand_devtype_data,
1346 }, {
1347 .compatible = "fsl,imx51-nand",
1348 .data = &imx51_nand_devtype_data,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001349 }, {
1350 .compatible = "fsl,imx53-nand",
1351 .data = &imx53_nand_devtype_data,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001352 },
1353 { /* sentinel */ }
1354};
1355
1356static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1357{
1358 struct device_node *np = host->dev->of_node;
1359 struct mxc_nand_platform_data *pdata = &host->pdata;
1360 const struct of_device_id *of_id =
1361 of_match_device(mxcnd_dt_ids, host->dev);
1362 int buswidth;
1363
1364 if (!np)
1365 return 1;
1366
1367 if (of_get_nand_ecc_mode(np) >= 0)
1368 pdata->hw_ecc = 1;
1369
1370 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1371
1372 buswidth = of_get_nand_bus_width(np);
1373 if (buswidth < 0)
1374 return buswidth;
1375
1376 pdata->width = buswidth / 8;
1377
1378 host->devtype_data = of_id->data;
1379
1380 return 0;
1381}
1382#else
1383static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1384{
1385 return 1;
1386}
1387#endif
1388
Bill Pemberton06f25512012-11-19 13:23:07 -05001389static int mxcnd_probe(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001390{
1391 struct nand_chip *this;
1392 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001393 struct mxc_nand_host *host;
1394 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001395 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001396
1397 /* Allocate memory for MTD device structure and private data */
Huang Shijiea5900552013-12-21 00:02:27 +08001398 host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
1399 GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001400 if (!host)
1401 return -ENOMEM;
1402
Huang Shijiea5900552013-12-21 00:02:27 +08001403 /* allocate a temporary buffer for the nand_scan_ident() */
1404 host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
1405 if (!host->data_buf)
1406 return -ENOMEM;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001407
Sascha Hauer34f6e152008-09-02 17:16:59 +02001408 host->dev = &pdev->dev;
1409 /* structures must be linked */
1410 this = &host->nand;
1411 mtd = &host->mtd;
1412 mtd->priv = this;
1413 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001414 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001415 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001416
1417 /* 50 us command delay time */
1418 this->chip_delay = 5;
1419
1420 this->priv = host;
1421 this->dev_ready = mxc_nand_dev_ready;
1422 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001423 this->read_byte = mxc_nand_read_byte;
1424 this->read_word = mxc_nand_read_word;
1425 this->write_buf = mxc_nand_write_buf;
1426 this->read_buf = mxc_nand_read_buf;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001427
Fabio Estevam24b82d32012-09-05 11:52:27 -03001428 host->clk = devm_clk_get(&pdev->dev, NULL);
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001429 if (IS_ERR(host->clk))
1430 return PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001431
Sascha Hauer71885b62012-06-06 12:33:14 +02001432 err = mxcnd_probe_dt(host);
Shawn Guo4d624352012-09-15 13:34:09 +08001433 if (err > 0) {
Jingoo Han453810b2013-07-30 17:18:33 +09001434 struct mxc_nand_platform_data *pdata =
1435 dev_get_platdata(&pdev->dev);
Shawn Guo4d624352012-09-15 13:34:09 +08001436 if (pdata) {
1437 host->pdata = *pdata;
1438 host->devtype_data = (struct mxc_nand_devtype_data *)
1439 pdev->id_entry->driver_data;
1440 } else {
1441 err = -ENODEV;
1442 }
1443 }
Sascha Hauer71885b62012-06-06 12:33:14 +02001444 if (err < 0)
1445 return err;
1446
1447 if (host->devtype_data->needs_ip) {
1448 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Thierry Redingb0de7742013-01-21 11:09:12 +01001449 host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
1450 if (IS_ERR(host->regs_ip))
1451 return PTR_ERR(host->regs_ip);
Sascha Hauer71885b62012-06-06 12:33:14 +02001452
1453 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1454 } else {
1455 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1456 }
1457
Thierry Redingb0de7742013-01-21 11:09:12 +01001458 host->base = devm_ioremap_resource(&pdev->dev, res);
1459 if (IS_ERR(host->base))
1460 return PTR_ERR(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001461
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001462 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001463
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001464 if (host->devtype_data->regs_offset)
1465 host->regs = host->base + host->devtype_data->regs_offset;
1466 host->spare0 = host->base + host->devtype_data->spare0_offset;
1467 if (host->devtype_data->axi_offset)
1468 host->regs_axi = host->base + host->devtype_data->axi_offset;
1469
1470 this->ecc.bytes = host->devtype_data->eccbytes;
1471 host->eccsize = host->devtype_data->eccsize;
1472
1473 this->select_chip = host->devtype_data->select_chip;
1474 this->ecc.size = 512;
1475 this->ecc.layout = host->devtype_data->ecclayout_512;
1476
Uwe Kleine-König64363562012-04-23 11:23:41 +02001477 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001478 this->ecc.calculate = mxc_nand_calculate_ecc;
1479 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001480 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001481 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001482 } else {
1483 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001484 }
1485
Uwe Kleine-König64363562012-04-23 11:23:41 +02001486 /* NAND bus width determines access functions used by upper layer */
1487 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001488 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001489
Uwe Kleine-König64363562012-04-23 11:23:41 +02001490 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001491 this->bbt_td = &bbt_main_descr;
1492 this->bbt_md = &bbt_mirror_descr;
1493 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001494 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001495 }
1496
Sascha Hauer63f14742010-10-18 10:16:26 +02001497 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001498
1499 host->irq = platform_get_irq(pdev, 0);
Fabio Estevam26fbf482014-02-14 01:09:34 -02001500 if (host->irq < 0)
1501 return host->irq;
Ivo Claryssed4840182010-04-08 16:14:44 +02001502
Sascha Hauer63f14742010-10-18 10:16:26 +02001503 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001504 * Use host->devtype_data->irq_control() here instead of irq_control()
1505 * because we must not disable_irq_nosync without having requested the
1506 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001507 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001508 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001509
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001510 err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
Michael Opdenackerb1eb2342013-10-13 08:21:32 +02001511 0, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001512 if (err)
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001513 return err;
1514
Fabio Estevamdcedf622013-12-02 00:50:02 -02001515 err = clk_prepare_enable(host->clk);
1516 if (err)
1517 return err;
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001518 host->clk_act = 1;
Ivo Claryssed4840182010-04-08 16:14:44 +02001519
Sascha Hauer63f14742010-10-18 10:16:26 +02001520 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001521 * Now that we "own" the interrupt make sure the interrupt mask bit is
1522 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1523 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001524 */
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001525 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +02001526 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001527 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001528 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001529
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001530 /* first scan to find the device and get the page size */
Shawn Guo4d624352012-09-15 13:34:09 +08001531 if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001532 err = -ENXIO;
1533 goto escan;
1534 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001535
Huang Shijiea5900552013-12-21 00:02:27 +08001536 /* allocate the right size buffer now */
1537 devm_kfree(&pdev->dev, (void *)host->data_buf);
1538 host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
1539 GFP_KERNEL);
1540 if (!host->data_buf) {
1541 err = -ENOMEM;
1542 goto escan;
1543 }
1544
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001545 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001546 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001547
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001548 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001549 this->ecc.layout = host->devtype_data->ecclayout_2k;
1550 else if (mtd->writesize == 4096)
1551 this->ecc.layout = host->devtype_data->ecclayout_4k;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001552
Mike Dunn6a918ba2012-03-11 14:21:11 -07001553 if (this->ecc.mode == NAND_ECC_HW) {
Shawn Guo4d624352012-09-15 13:34:09 +08001554 if (is_imx21_nfc(host) || is_imx27_nfc(host))
Mike Dunn6a918ba2012-03-11 14:21:11 -07001555 this->ecc.strength = 1;
1556 else
1557 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1558 }
1559
Sascha Hauer4a43faf2012-05-25 16:22:42 +02001560 /* second phase scan */
1561 if (nand_scan_tail(mtd)) {
1562 err = -ENXIO;
1563 goto escan;
1564 }
1565
Sascha Hauer34f6e152008-09-02 17:16:59 +02001566 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001567 mtd_device_parse_register(mtd, part_probes,
1568 &(struct mtd_part_parser_data){
1569 .of_node = pdev->dev.of_node,
1570 },
1571 host->pdata.parts,
1572 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001573
1574 platform_set_drvdata(pdev, host);
1575
1576 return 0;
1577
1578escan:
Lothar Waßmannc10d8ee2012-12-06 08:42:27 +01001579 if (host->clk_act)
1580 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001581
1582 return err;
1583}
1584
Bill Pemberton810b7e02012-11-19 13:26:04 -05001585static int mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001586{
1587 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1588
Sascha Hauer34f6e152008-09-02 17:16:59 +02001589 nand_release(&host->mtd);
Wei Yongjun8bfd4f72013-12-17 11:35:35 +08001590 if (host->clk_act)
1591 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001592
1593 return 0;
1594}
1595
Sascha Hauer34f6e152008-09-02 17:16:59 +02001596static struct platform_driver mxcnd_driver = {
1597 .driver = {
1598 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001599 .owner = THIS_MODULE,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001600 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001601 },
Shawn Guo4d624352012-09-15 13:34:09 +08001602 .id_table = mxcnd_devtype,
Fabio Estevamddf16d62012-09-05 11:35:25 -03001603 .probe = mxcnd_probe,
Bill Pemberton5153b882012-11-19 13:21:24 -05001604 .remove = mxcnd_remove,
Sascha Hauer34f6e152008-09-02 17:16:59 +02001605};
Fabio Estevamddf16d62012-09-05 11:35:25 -03001606module_platform_driver(mxcnd_driver);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001607
1608MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1609MODULE_DESCRIPTION("MXC NAND MTD driver");
1610MODULE_LICENSE("GPL");