blob: 9896b636c4eb61d039eb030900d1ad48bf9eb1c2 [file] [log] [blame]
Sascha Hauer34f6e152008-09-02 17:16:59 +02001/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#include <linux/delay.h>
21#include <linux/slab.h>
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/mtd/mtd.h>
25#include <linux/mtd/nand.h>
26#include <linux/mtd/partitions.h>
27#include <linux/interrupt.h>
28#include <linux/device.h>
29#include <linux/platform_device.h>
30#include <linux/clk.h>
31#include <linux/err.h>
32#include <linux/io.h>
Sascha Hauer63f14742010-10-18 10:16:26 +020033#include <linux/irq.h>
34#include <linux/completion.h>
Uwe Kleine-König64363562012-04-23 11:23:41 +020035#include <linux/of_device.h>
36#include <linux/of_mtd.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020037
38#include <asm/mach/flash.h>
Arnd Bergmann82906b12012-08-24 15:14:29 +020039#include <linux/platform_data/mtd-mxc_nand.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020040
41#define DRIVER_NAME "mxc_nand"
42
43/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020044#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
45#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
46#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
47#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
48#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
49#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
50#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
51#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
52#define NFC_V1_V2_WRPROT (host->regs + 0x12)
53#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
54#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
Baruch Siachd178e3e2011-03-14 09:01:56 +020055#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
56#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
57#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
58#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
59#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
60#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
61#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
62#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
Sascha Hauer1bc99182010-08-06 15:53:08 +020063#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
64#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
65#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020066
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020067#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020068#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
69#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
70#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
71#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
72#define NFC_V1_V2_CONFIG1_RST (1 << 6)
73#define NFC_V1_V2_CONFIG1_CE (1 << 7)
Sascha Hauerb8db2f52010-08-09 15:04:19 +020074#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
75#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
76#define NFC_V2_CONFIG1_FP_INT (1 << 11)
Sascha Hauer34f6e152008-09-02 17:16:59 +020077
Sascha Hauer1bc99182010-08-06 15:53:08 +020078#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020079
Sascha Hauer1bc99182010-08-06 15:53:08 +020080/*
81 * Operation modes for the NFC. Valid for v1, v2 and v3
82 * type controllers.
83 */
84#define NFC_CMD (1 << 0)
85#define NFC_ADDR (1 << 1)
86#define NFC_INPUT (1 << 2)
87#define NFC_OUTPUT (1 << 3)
88#define NFC_ID (1 << 4)
89#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020090
Sascha Hauer71ec5152010-08-06 15:53:11 +020091#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
92#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
Sascha Hauer34f6e152008-09-02 17:16:59 +020093
Sascha Hauer71ec5152010-08-06 15:53:11 +020094#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
95#define NFC_V3_CONFIG1_SP_EN (1 << 0)
96#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
Sascha Hauer34f6e152008-09-02 17:16:59 +020097
Sascha Hauer71ec5152010-08-06 15:53:11 +020098#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
Sascha Hauer34f6e152008-09-02 17:16:59 +020099
Sascha Hauer71ec5152010-08-06 15:53:11 +0200100#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200101
Sascha Hauer71ec5152010-08-06 15:53:11 +0200102#define NFC_V3_WRPROT (host->regs_ip + 0x0)
103#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
104#define NFC_V3_WRPROT_LOCK (1 << 1)
105#define NFC_V3_WRPROT_UNLOCK (1 << 2)
106#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
107
108#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
109
110#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
111#define NFC_V3_CONFIG2_PS_512 (0 << 0)
112#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
113#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
114#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
115#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
116#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
117#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
118#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200119#define NFC_V3_CONFIG2_PPB(x, shift) (((x) & 0x3) << shift)
Sascha Hauer71ec5152010-08-06 15:53:11 +0200120#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
121#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
122#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
123#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
124
125#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
126#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
127#define NFC_V3_CONFIG3_FW8 (1 << 3)
128#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
129#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
130#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
131#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
132
133#define NFC_V3_IPC (host->regs_ip + 0x2C)
134#define NFC_V3_IPC_CREQ (1 << 0)
135#define NFC_V3_IPC_INT (1 << 31)
136
137#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200138
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200139struct mxc_nand_host;
140
141struct mxc_nand_devtype_data {
142 void (*preset)(struct mtd_info *);
143 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
144 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
145 void (*send_page)(struct mtd_info *, unsigned int);
146 void (*send_read_id)(struct mxc_nand_host *);
147 uint16_t (*get_dev_status)(struct mxc_nand_host *);
148 int (*check_int)(struct mxc_nand_host *);
149 void (*irq_control)(struct mxc_nand_host *, int);
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200150 u32 (*get_ecc_status)(struct mxc_nand_host *);
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +0200151 struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k;
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200152 void (*select_chip)(struct mtd_info *mtd, int chip);
Uwe Kleine-König69d023b2012-04-23 11:23:39 +0200153 int (*correct_data)(struct mtd_info *mtd, u_char *dat,
154 u_char *read_ecc, u_char *calc_ecc);
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200155
156 /*
157 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
158 * (CONFIG1:INT_MSK is set). To handle this the driver uses
159 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
160 */
161 int irqpending_quirk;
162 int needs_ip;
163
164 size_t regs_offset;
165 size_t spare0_offset;
166 size_t axi_offset;
167
168 int spare_len;
169 int eccbytes;
170 int eccsize;
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200171 int ppb_shift;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200172};
173
Sascha Hauer34f6e152008-09-02 17:16:59 +0200174struct mxc_nand_host {
175 struct mtd_info mtd;
176 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200177 struct device *dev;
178
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200179 void __iomem *spare0;
180 void __iomem *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200181
182 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200183 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200184 void __iomem *regs_axi;
185 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200186 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200187 struct clk *clk;
188 int clk_act;
189 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200190 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200191 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200192
Sascha Hauer63f14742010-10-18 10:16:26 +0200193 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200194
195 uint8_t *data_buf;
196 unsigned int buf_start;
Sascha Hauer5f973042010-08-06 15:53:06 +0200197
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200198 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König64363562012-04-23 11:23:41 +0200199 struct mxc_nand_platform_data pdata;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200200};
201
Sascha Hauer34f6e152008-09-02 17:16:59 +0200202/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200203static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200204 .eccbytes = 5,
205 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200206 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200207};
208
Sascha Hauer94671142009-10-05 12:14:21 +0200209static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400210 .eccbytes = 20,
211 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
212 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
213 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200214};
215
Sascha Hauer94671142009-10-05 12:14:21 +0200216/* OOB description for 512 byte pages with 16 byte OOB */
217static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
218 .eccbytes = 1 * 9,
219 .eccpos = {
220 7, 8, 9, 10, 11, 12, 13, 14, 15
221 },
222 .oobfree = {
223 {.offset = 0, .length = 5}
224 }
225};
226
227/* OOB description for 2048 byte pages with 64 byte OOB */
228static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
229 .eccbytes = 4 * 9,
230 .eccpos = {
231 7, 8, 9, 10, 11, 12, 13, 14, 15,
232 23, 24, 25, 26, 27, 28, 29, 30, 31,
233 39, 40, 41, 42, 43, 44, 45, 46, 47,
234 55, 56, 57, 58, 59, 60, 61, 62, 63
235 },
236 .oobfree = {
237 {.offset = 2, .length = 4},
238 {.offset = 16, .length = 7},
239 {.offset = 32, .length = 7},
240 {.offset = 48, .length = 7}
241 }
242};
243
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200244/* OOB description for 4096 byte pages with 128 byte OOB */
245static struct nand_ecclayout nandv2_hw_eccoob_4k = {
246 .eccbytes = 8 * 9,
247 .eccpos = {
248 7, 8, 9, 10, 11, 12, 13, 14, 15,
249 23, 24, 25, 26, 27, 28, 29, 30, 31,
250 39, 40, 41, 42, 43, 44, 45, 46, 47,
251 55, 56, 57, 58, 59, 60, 61, 62, 63,
252 71, 72, 73, 74, 75, 76, 77, 78, 79,
253 87, 88, 89, 90, 91, 92, 93, 94, 95,
254 103, 104, 105, 106, 107, 108, 109, 110, 111,
255 119, 120, 121, 122, 123, 124, 125, 126, 127,
256 },
257 .oobfree = {
258 {.offset = 2, .length = 4},
259 {.offset = 16, .length = 7},
260 {.offset = 32, .length = 7},
261 {.offset = 48, .length = 7},
262 {.offset = 64, .length = 7},
263 {.offset = 80, .length = 7},
264 {.offset = 96, .length = 7},
265 {.offset = 112, .length = 7},
266 }
267};
268
Lothar Waßmann740bb0c2012-12-06 08:42:28 +0100269static const char const *part_probes[] = {
270 "cmdlinepart", "RedBoot", "ofpart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200271
Sascha Hauer096bcc22012-05-29 10:16:09 +0200272static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
273{
274 int i;
275 u32 *t = trg;
276 const __iomem u32 *s = src;
277
278 for (i = 0; i < (size >> 2); i++)
279 *t++ = __raw_readl(s++);
280}
281
282static void memcpy32_toio(void __iomem *trg, const void *src, int size)
283{
284 int i;
285 u32 __iomem *t = trg;
286 const u32 *s = src;
287
288 for (i = 0; i < (size >> 2); i++)
289 __raw_writel(*s++, t++);
290}
291
Sascha Hauer71ec5152010-08-06 15:53:11 +0200292static int check_int_v3(struct mxc_nand_host *host)
293{
294 uint32_t tmp;
295
296 tmp = readl(NFC_V3_IPC);
297 if (!(tmp & NFC_V3_IPC_INT))
298 return 0;
299
300 tmp &= ~NFC_V3_IPC_INT;
301 writel(tmp, NFC_V3_IPC);
302
303 return 1;
304}
305
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200306static int check_int_v1_v2(struct mxc_nand_host *host)
307{
308 uint32_t tmp;
309
Sascha Hauer1bc99182010-08-06 15:53:08 +0200310 tmp = readw(NFC_V1_V2_CONFIG2);
311 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200312 return 0;
313
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200314 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200315 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200316
317 return 1;
318}
319
Sascha Hauer63f14742010-10-18 10:16:26 +0200320static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
321{
322 uint16_t tmp;
323
324 tmp = readw(NFC_V1_V2_CONFIG1);
325
326 if (activate)
327 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
328 else
329 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
330
331 writew(tmp, NFC_V1_V2_CONFIG1);
332}
333
334static void irq_control_v3(struct mxc_nand_host *host, int activate)
335{
336 uint32_t tmp;
337
338 tmp = readl(NFC_V3_CONFIG2);
339
340 if (activate)
341 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
342 else
343 tmp |= NFC_V3_CONFIG2_INT_MSK;
344
345 writel(tmp, NFC_V3_CONFIG2);
346}
347
Uwe Kleine-König85569582012-04-23 11:23:34 +0200348static void irq_control(struct mxc_nand_host *host, int activate)
349{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200350 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200351 if (activate)
352 enable_irq(host->irq);
353 else
354 disable_irq_nosync(host->irq);
355 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200356 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200357 }
358}
359
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200360static u32 get_ecc_status_v1(struct mxc_nand_host *host)
361{
362 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
363}
364
365static u32 get_ecc_status_v2(struct mxc_nand_host *host)
366{
367 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
368}
369
370static u32 get_ecc_status_v3(struct mxc_nand_host *host)
371{
372 return readl(NFC_V3_ECC_STATUS_RESULT);
373}
374
Uwe Kleine-König85569582012-04-23 11:23:34 +0200375static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
376{
377 struct mxc_nand_host *host = dev_id;
378
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200379 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200380 return IRQ_NONE;
381
382 irq_control(host, 0);
383
384 complete(&host->op_completion);
385
386 return IRQ_HANDLED;
387}
388
Sascha Hauer34f6e152008-09-02 17:16:59 +0200389/* This function polls the NANDFC to wait for the basic operation to
390 * complete by checking the INT bit of config2 register.
391 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200392static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200393{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200394 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200395
396 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200397 if (!host->devtype_data->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200398 INIT_COMPLETION(host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200399 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200400 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200401 }
402 } else {
403 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200404 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200405 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200406
Sascha Hauer34f6e152008-09-02 17:16:59 +0200407 udelay(1);
408 }
Roel Kluin43950a62009-06-04 16:24:59 +0200409 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700410 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200411 }
412}
413
Sascha Hauer71ec5152010-08-06 15:53:11 +0200414static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
415{
416 /* fill command */
417 writel(cmd, NFC_V3_FLASH_CMD);
418
419 /* send out command */
420 writel(NFC_CMD, NFC_V3_LAUNCH);
421
422 /* Wait for operation to complete */
423 wait_op_done(host, useirq);
424}
425
Sascha Hauer34f6e152008-09-02 17:16:59 +0200426/* This function issues the specified command to the NAND device and
427 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200428static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200429{
Brian Norris289c0522011-07-19 10:06:09 -0700430 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200431
Sascha Hauer1bc99182010-08-06 15:53:08 +0200432 writew(cmd, NFC_V1_V2_FLASH_CMD);
433 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200434
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200435 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200436 int max_retries = 100;
437 /* Reset completion is indicated by NFC_CONFIG2 */
438 /* being set to 0 */
439 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200440 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200441 break;
442 }
443 udelay(1);
444 }
445 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700446 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200447 } else {
448 /* Wait for operation to complete */
449 wait_op_done(host, useirq);
450 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200451}
452
Sascha Hauer71ec5152010-08-06 15:53:11 +0200453static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
454{
455 /* fill address */
456 writel(addr, NFC_V3_FLASH_ADDR0);
457
458 /* send out address */
459 writel(NFC_ADDR, NFC_V3_LAUNCH);
460
461 wait_op_done(host, 0);
462}
463
Sascha Hauer34f6e152008-09-02 17:16:59 +0200464/* This function sends an address (or partial address) to the
465 * NAND device. The address is used to select the source/destination for
466 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200467static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200468{
Brian Norris289c0522011-07-19 10:06:09 -0700469 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200470
Sascha Hauer1bc99182010-08-06 15:53:08 +0200471 writew(addr, NFC_V1_V2_FLASH_ADDR);
472 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200473
474 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200475 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200476}
477
Sascha Hauer71ec5152010-08-06 15:53:11 +0200478static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
479{
480 struct nand_chip *nand_chip = mtd->priv;
481 struct mxc_nand_host *host = nand_chip->priv;
482 uint32_t tmp;
483
484 tmp = readl(NFC_V3_CONFIG1);
485 tmp &= ~(7 << 4);
486 writel(tmp, NFC_V3_CONFIG1);
487
488 /* transfer data from NFC ram to nand */
489 writel(ops, NFC_V3_LAUNCH);
490
491 wait_op_done(host, false);
492}
493
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200494static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
495{
496 struct nand_chip *nand_chip = mtd->priv;
497 struct mxc_nand_host *host = nand_chip->priv;
498
499 /* NANDFC buffer 0 is used for page read/write */
500 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
501
502 writew(ops, NFC_V1_V2_CONFIG2);
503
504 /* Wait for operation to complete */
505 wait_op_done(host, true);
506}
507
508static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200509{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200510 struct nand_chip *nand_chip = mtd->priv;
511 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200512 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200513
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200514 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200515 bufs = 4;
516 else
517 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200518
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200519 for (i = 0; i < bufs; i++) {
520
521 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200522 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200523
Sascha Hauer1bc99182010-08-06 15:53:08 +0200524 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200525
526 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200527 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200528 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200529}
530
Sascha Hauer71ec5152010-08-06 15:53:11 +0200531static void send_read_id_v3(struct mxc_nand_host *host)
532{
Roman Schneidera8459f22013-01-15 16:56:24 +0100533 struct nand_chip *this = &host->nand;
534
Sascha Hauer71ec5152010-08-06 15:53:11 +0200535 /* Read ID into main buffer */
536 writel(NFC_ID, NFC_V3_LAUNCH);
537
538 wait_op_done(host, true);
539
Sascha Hauer096bcc22012-05-29 10:16:09 +0200540 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Roman Schneidera8459f22013-01-15 16:56:24 +0100541
542 if (this->options & NAND_BUSWIDTH_16) {
543 /* compress the ID info */
544 host->data_buf[1] = host->data_buf[2];
545 host->data_buf[2] = host->data_buf[4];
546 host->data_buf[3] = host->data_buf[6];
547 host->data_buf[4] = host->data_buf[8];
548 host->data_buf[5] = host->data_buf[10];
549 }
Sascha Hauer71ec5152010-08-06 15:53:11 +0200550}
551
Sascha Hauer34f6e152008-09-02 17:16:59 +0200552/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200553static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200554{
555 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200556
557 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200558 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200559
Sascha Hauer1bc99182010-08-06 15:53:08 +0200560 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200561
562 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200563 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200564
Sascha Hauer096bcc22012-05-29 10:16:09 +0200565 memcpy32_fromio(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200566
567 if (this->options & NAND_BUSWIDTH_16) {
568 /* compress the ID info */
569 host->data_buf[1] = host->data_buf[2];
570 host->data_buf[2] = host->data_buf[4];
571 host->data_buf[3] = host->data_buf[6];
572 host->data_buf[4] = host->data_buf[8];
573 host->data_buf[5] = host->data_buf[10];
574 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200575}
576
Sascha Hauer71ec5152010-08-06 15:53:11 +0200577static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200578{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200579 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200580 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200581
Sascha Hauer71ec5152010-08-06 15:53:11 +0200582 return readl(NFC_V3_CONFIG1) >> 16;
583}
584
Sascha Hauer34f6e152008-09-02 17:16:59 +0200585/* This function requests the NANDFC to perform a read of the
586 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200587static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200588{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200589 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200590 uint32_t store;
591 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200592
Baruch Siachd178e3e2011-03-14 09:01:56 +0200593 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200594
595 /*
596 * The device status is stored in main_area0. To
597 * prevent corruption of the buffer save the value
598 * and restore it afterwards.
599 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200600 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200601
Sascha Hauer1bc99182010-08-06 15:53:08 +0200602 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200603 wait_op_done(host, true);
604
Sascha Hauer34f6e152008-09-02 17:16:59 +0200605 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200606
Sascha Hauer34f6e152008-09-02 17:16:59 +0200607 writel(store, main_buf);
608
609 return ret;
610}
611
612/* This functions is used by upper layer to checks if device is ready */
613static int mxc_nand_dev_ready(struct mtd_info *mtd)
614{
615 /*
616 * NFC handles R/B internally. Therefore, this function
617 * always returns status as ready.
618 */
619 return 1;
620}
621
622static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
623{
624 /*
625 * If HW ECC is enabled, we turn it on during init. There is
626 * no need to enable again here.
627 */
628}
629
Sascha Hauer94f77e52010-08-06 15:53:09 +0200630static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200631 u_char *read_ecc, u_char *calc_ecc)
632{
633 struct nand_chip *nand_chip = mtd->priv;
634 struct mxc_nand_host *host = nand_chip->priv;
635
636 /*
637 * 1-Bit errors are automatically corrected in HW. No need for
638 * additional correction. 2-Bit errors cannot be corrected by
639 * HW ECC, so we need to return failure
640 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200641 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200642
643 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700644 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200645 return -1;
646 }
647
648 return 0;
649}
650
Sascha Hauer94f77e52010-08-06 15:53:09 +0200651static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
652 u_char *read_ecc, u_char *calc_ecc)
653{
654 struct nand_chip *nand_chip = mtd->priv;
655 struct mxc_nand_host *host = nand_chip->priv;
656 u32 ecc_stat, err;
657 int no_subpages = 1;
658 int ret = 0;
659 u8 ecc_bit_mask, err_limit;
660
661 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
662 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
663
664 no_subpages = mtd->writesize >> 9;
665
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200666 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200667
668 do {
669 err = ecc_stat & ecc_bit_mask;
670 if (err > err_limit) {
671 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
672 return -1;
673 } else {
674 ret += err;
675 }
676 ecc_stat >>= 4;
677 } while (--no_subpages);
678
Sascha Hauer94f77e52010-08-06 15:53:09 +0200679 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
680
681 return ret;
682}
683
Sascha Hauer34f6e152008-09-02 17:16:59 +0200684static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
685 u_char *ecc_code)
686{
687 return 0;
688}
689
690static u_char mxc_nand_read_byte(struct mtd_info *mtd)
691{
692 struct nand_chip *nand_chip = mtd->priv;
693 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200694 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200695
696 /* Check for status request */
697 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200698 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200699
Sascha Hauerf8f96082009-06-04 17:12:26 +0200700 ret = *(uint8_t *)(host->data_buf + host->buf_start);
701 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200702
703 return ret;
704}
705
706static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
707{
708 struct nand_chip *nand_chip = mtd->priv;
709 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200710 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200711
Sascha Hauerf8f96082009-06-04 17:12:26 +0200712 ret = *(uint16_t *)(host->data_buf + host->buf_start);
713 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200714
715 return ret;
716}
717
718/* Write data of length len to buffer buf. The data to be
719 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
720 * Operation by the NFC, the data is written to NAND Flash */
721static void mxc_nand_write_buf(struct mtd_info *mtd,
722 const u_char *buf, int len)
723{
724 struct nand_chip *nand_chip = mtd->priv;
725 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200726 u16 col = host->buf_start;
727 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200728
Sascha Hauerf8f96082009-06-04 17:12:26 +0200729 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200730
Sascha Hauerf8f96082009-06-04 17:12:26 +0200731 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200732
Sascha Hauerf8f96082009-06-04 17:12:26 +0200733 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200734}
735
736/* Read the data buffer from the NAND Flash. To read the data from NAND
737 * Flash first the data output cycle is initiated by the NFC, which copies
738 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
739 */
740static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
741{
742 struct nand_chip *nand_chip = mtd->priv;
743 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200744 u16 col = host->buf_start;
745 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200746
Sascha Hauerf8f96082009-06-04 17:12:26 +0200747 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200748
Baruch Siach5d9d9932011-03-02 16:47:55 +0200749 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200750
Baruch Siach5d9d9932011-03-02 16:47:55 +0200751 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200752}
753
Sascha Hauer34f6e152008-09-02 17:16:59 +0200754/* This function is used by upper layer for select and
755 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200756static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200757{
758 struct nand_chip *nand_chip = mtd->priv;
759 struct mxc_nand_host *host = nand_chip->priv;
760
Baruch Siachd178e3e2011-03-14 09:01:56 +0200761 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200762 /* Disable the NFC clock */
763 if (host->clk_act) {
Sascha Hauer97c32132012-03-07 20:56:35 +0100764 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200765 host->clk_act = 0;
766 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200767 return;
768 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200769
Baruch Siachd178e3e2011-03-14 09:01:56 +0200770 if (!host->clk_act) {
771 /* Enable the NFC clock */
Sascha Hauer97c32132012-03-07 20:56:35 +0100772 clk_prepare_enable(host->clk);
Baruch Siachd178e3e2011-03-14 09:01:56 +0200773 host->clk_act = 1;
774 }
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200775}
Baruch Siachd178e3e2011-03-14 09:01:56 +0200776
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200777static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200778{
779 struct nand_chip *nand_chip = mtd->priv;
780 struct mxc_nand_host *host = nand_chip->priv;
781
782 if (chip == -1) {
783 /* Disable the NFC clock */
784 if (host->clk_act) {
Fabio Estevam3d059692012-05-25 20:14:50 -0300785 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200786 host->clk_act = 0;
787 }
788 return;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200789 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200790
791 if (!host->clk_act) {
792 /* Enable the NFC clock */
Fabio Estevam3d059692012-05-25 20:14:50 -0300793 clk_prepare_enable(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200794 host->clk_act = 1;
795 }
796
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200797 host->active_cs = chip;
798 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200799}
800
Sascha Hauerf8f96082009-06-04 17:12:26 +0200801/*
802 * Function to transfer data to/from spare area.
803 */
804static void copy_spare(struct mtd_info *mtd, bool bfrom)
805{
806 struct nand_chip *this = mtd->priv;
807 struct mxc_nand_host *host = this->priv;
808 u16 i, j;
809 u16 n = mtd->writesize >> 9;
810 u8 *d = host->data_buf + mtd->writesize;
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200811 u8 __iomem *s = host->spare0;
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200812 u16 t = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200813
814 j = (mtd->oobsize / n >> 1) << 1;
815
816 if (bfrom) {
817 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200818 memcpy32_fromio(d + i * j, s + i * t, j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200819
820 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200821 memcpy32_fromio(d + i * j, s + i * t, mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200822 } else {
823 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200824 memcpy32_toio(&s[i * t], &d[i * j], j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200825
826 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200827 memcpy32_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200828 }
829}
830
Sascha Hauera3e65b62009-06-02 11:47:59 +0200831static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200832{
833 struct nand_chip *nand_chip = mtd->priv;
834 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200835
836 /* Write out column address, if necessary */
837 if (column != -1) {
838 /*
839 * MXC NANDFC can only perform full page+spare or
840 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100841 * perform a read/write buf operation, the saved column
842 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200843 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200844 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200845 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200846 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200847 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200848 }
849
850 /* Write out page address, if necessary */
851 if (page_addr != -1) {
852 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200853 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200854
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200855 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400856 if (mtd->size >= 0x10000000) {
857 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200858 host->devtype_data->send_addr(host,
859 (page_addr >> 8) & 0xff,
860 false);
861 host->devtype_data->send_addr(host,
862 (page_addr >> 16) & 0xff,
863 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400864 } else
865 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200866 host->devtype_data->send_addr(host,
867 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200868 } else {
869 /* One more address cycle for higher density devices */
870 if (mtd->size >= 0x4000000) {
871 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200872 host->devtype_data->send_addr(host,
873 (page_addr >> 8) & 0xff,
874 false);
875 host->devtype_data->send_addr(host,
876 (page_addr >> 16) & 0xff,
877 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200878 } else
879 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200880 host->devtype_data->send_addr(host,
881 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200882 }
883 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200884}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200885
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200886/*
887 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
888 * on how much oob the nand chip has. For 8bit ecc we need at least
889 * 26 bytes of oob data per 512 byte block.
890 */
891static int get_eccsize(struct mtd_info *mtd)
892{
893 int oobbytes_per_512 = 0;
894
895 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
896
897 if (oobbytes_per_512 < 26)
898 return 4;
899 else
900 return 8;
901}
902
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200903static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200904{
905 struct nand_chip *nand_chip = mtd->priv;
906 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200907 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200908
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200909 if (nand_chip->ecc.mode == NAND_ECC_HW)
910 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
911
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200912 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200913 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200914
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200915 host->eccsize = 1;
916
917 writew(config1, NFC_V1_V2_CONFIG1);
918 /* preset operation */
919
920 /* Unlock the internal RAM Buffer */
921 writew(0x2, NFC_V1_V2_CONFIG);
922
923 /* Blocks to be unlocked */
924 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
925 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
926
927 /* Unlock Block Command for given address range */
928 writew(0x4, NFC_V1_V2_WRPROT);
929}
930
931static void preset_v2(struct mtd_info *mtd)
932{
933 struct nand_chip *nand_chip = mtd->priv;
934 struct mxc_nand_host *host = nand_chip->priv;
935 uint16_t config1 = 0;
936
937 if (nand_chip->ecc.mode == NAND_ECC_HW)
938 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
939
940 config1 |= NFC_V2_CONFIG1_FP_INT;
Ivo Claryssed4840182010-04-08 16:14:44 +0200941
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200942 if (!host->devtype_data->irqpending_quirk)
Ivo Claryssed4840182010-04-08 16:14:44 +0200943 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200944
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200945 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200946 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
947
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200948 host->eccsize = get_eccsize(mtd);
949 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200950 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
951
952 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200953 } else {
954 host->eccsize = 1;
955 }
956
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200957 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200958 /* preset operation */
959
960 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200961 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200962
963 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200964 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
965 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
966 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
967 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
968 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
969 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
970 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
971 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200972
973 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200974 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200975}
976
Sascha Hauer71ec5152010-08-06 15:53:11 +0200977static void preset_v3(struct mtd_info *mtd)
978{
979 struct nand_chip *chip = mtd->priv;
980 struct mxc_nand_host *host = chip->priv;
981 uint32_t config2, config3;
982 int i, addr_phases;
983
984 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
985 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
986
987 /* Unlock the internal RAM Buffer */
988 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
989 NFC_V3_WRPROT);
990
991 /* Blocks to be unlocked */
992 for (i = 0; i < NAND_MAX_CHIPS; i++)
993 writel(0x0 | (0xffff << 16),
994 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
995
996 writel(0, NFC_V3_IPC);
997
998 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
999 NFC_V3_CONFIG2_2CMD_PHASES |
1000 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
1001 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +02001002 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +02001003 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
1004
1005 if (chip->ecc.mode == NAND_ECC_HW)
1006 config2 |= NFC_V3_CONFIG2_ECC_EN;
1007
1008 addr_phases = fls(chip->pagemask) >> 3;
1009
1010 if (mtd->writesize == 2048) {
1011 config2 |= NFC_V3_CONFIG2_PS_2048;
1012 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1013 } else if (mtd->writesize == 4096) {
1014 config2 |= NFC_V3_CONFIG2_PS_4096;
1015 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1016 } else {
1017 config2 |= NFC_V3_CONFIG2_PS_512;
1018 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1019 }
1020
1021 if (mtd->writesize) {
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001022 config2 |= NFC_V3_CONFIG2_PPB(
1023 ffs(mtd->erasesize / mtd->writesize) - 6,
1024 host->devtype_data->ppb_shift);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001025 host->eccsize = get_eccsize(mtd);
1026 if (host->eccsize == 8)
1027 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
1028 }
1029
1030 writel(config2, NFC_V3_CONFIG2);
1031
1032 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1033 NFC_V3_CONFIG3_NO_SDMA |
1034 NFC_V3_CONFIG3_RBB_MODE |
1035 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1036 NFC_V3_CONFIG3_ADD_OP(0);
1037
1038 if (!(chip->options & NAND_BUSWIDTH_16))
1039 config3 |= NFC_V3_CONFIG3_FW8;
1040
1041 writel(config3, NFC_V3_CONFIG3);
1042
1043 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001044}
1045
Sascha Hauer34f6e152008-09-02 17:16:59 +02001046/* Used by the upper layer to write command to NAND Flash for
1047 * different operations to be carried out on NAND Flash */
1048static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1049 int column, int page_addr)
1050{
1051 struct nand_chip *nand_chip = mtd->priv;
1052 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001053
Brian Norris289c0522011-07-19 10:06:09 -07001054 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001055 command, column, page_addr);
1056
1057 /* Reset command state information */
1058 host->status_request = false;
1059
1060 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001061 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001062 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001063 host->devtype_data->preset(mtd);
1064 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001065 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001066
Sascha Hauer34f6e152008-09-02 17:16:59 +02001067 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001068 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001069 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001070
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001071 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001072 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001073 break;
1074
Sascha Hauer34f6e152008-09-02 17:16:59 +02001075 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001076 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001077 if (command == NAND_CMD_READ0)
1078 host->buf_start = column;
1079 else
1080 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001081
Sascha Hauer5ea32022010-04-27 15:24:01 +02001082 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001083
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001084 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001085 mxc_do_addr_cycle(mtd, column, page_addr);
1086
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001087 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001088 host->devtype_data->send_cmd(host,
1089 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001090
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001091 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001092
Sascha Hauer096bcc22012-05-29 10:16:09 +02001093 memcpy32_fromio(host->data_buf, host->main_area0,
1094 mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001095 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001096 break;
1097
Sascha Hauer34f6e152008-09-02 17:16:59 +02001098 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001099 if (column >= mtd->writesize)
1100 /* call ourself to read a page */
1101 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001102
Sascha Hauer5ea32022010-04-27 15:24:01 +02001103 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001104
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001105 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001106 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001107 break;
1108
1109 case NAND_CMD_PAGEPROG:
Sascha Hauer096bcc22012-05-29 10:16:09 +02001110 memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001111 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001112 host->devtype_data->send_page(mtd, NFC_INPUT);
1113 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001114 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001115 break;
1116
Sascha Hauer34f6e152008-09-02 17:16:59 +02001117 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001118 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001119 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001120 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001121 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001122 break;
1123
Sascha Hauer89121a62009-06-04 17:18:01 +02001124 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001125 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001126 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001127 mxc_do_addr_cycle(mtd, column, page_addr);
1128
Sascha Hauer34f6e152008-09-02 17:16:59 +02001129 break;
1130 }
1131}
1132
Sascha Hauerf1372052009-10-21 14:25:27 +02001133/*
1134 * The generic flash bbt decriptors overlap with our ecc
1135 * hardware, so define some i.MX specific ones.
1136 */
1137static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1138static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1139
1140static struct nand_bbt_descr bbt_main_descr = {
1141 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1142 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1143 .offs = 0,
1144 .len = 4,
1145 .veroffs = 4,
1146 .maxblocks = 4,
1147 .pattern = bbt_pattern,
1148};
1149
1150static struct nand_bbt_descr bbt_mirror_descr = {
1151 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1152 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1153 .offs = 0,
1154 .len = 4,
1155 .veroffs = 4,
1156 .maxblocks = 4,
1157 .pattern = mirror_pattern,
1158};
1159
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001160/* v1 + irqpending_quirk: i.MX21 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001161static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001162 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001163 .send_cmd = send_cmd_v1_v2,
1164 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001165 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001166 .send_read_id = send_read_id_v1_v2,
1167 .get_dev_status = get_dev_status_v1_v2,
1168 .check_int = check_int_v1_v2,
1169 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001170 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001171 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1172 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1173 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001174 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001175 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001176 .irqpending_quirk = 1,
1177 .needs_ip = 0,
1178 .regs_offset = 0xe00,
1179 .spare0_offset = 0x800,
1180 .spare_len = 16,
1181 .eccbytes = 3,
1182 .eccsize = 1,
1183};
1184
1185/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1186static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1187 .preset = preset_v1,
1188 .send_cmd = send_cmd_v1_v2,
1189 .send_addr = send_addr_v1_v2,
1190 .send_page = send_page_v1,
1191 .send_read_id = send_read_id_v1_v2,
1192 .get_dev_status = get_dev_status_v1_v2,
1193 .check_int = check_int_v1_v2,
1194 .irq_control = irq_control_v1_v2,
1195 .get_ecc_status = get_ecc_status_v1,
1196 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1197 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1198 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1199 .select_chip = mxc_nand_select_chip_v1_v3,
1200 .correct_data = mxc_nand_correct_data_v1,
1201 .irqpending_quirk = 0,
1202 .needs_ip = 0,
1203 .regs_offset = 0xe00,
1204 .spare0_offset = 0x800,
1205 .axi_offset = 0,
1206 .spare_len = 16,
1207 .eccbytes = 3,
1208 .eccsize = 1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001209};
1210
1211/* v21: i.MX25, i.MX35 */
1212static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001213 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001214 .send_cmd = send_cmd_v1_v2,
1215 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001216 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001217 .send_read_id = send_read_id_v1_v2,
1218 .get_dev_status = get_dev_status_v1_v2,
1219 .check_int = check_int_v1_v2,
1220 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001221 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001222 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1223 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1224 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001225 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001226 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001227 .irqpending_quirk = 0,
1228 .needs_ip = 0,
1229 .regs_offset = 0x1e00,
1230 .spare0_offset = 0x1000,
1231 .axi_offset = 0,
1232 .spare_len = 64,
1233 .eccbytes = 9,
1234 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001235};
1236
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001237/* v3.2a: i.MX51 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001238static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1239 .preset = preset_v3,
1240 .send_cmd = send_cmd_v3,
1241 .send_addr = send_addr_v3,
1242 .send_page = send_page_v3,
1243 .send_read_id = send_read_id_v3,
1244 .get_dev_status = get_dev_status_v3,
1245 .check_int = check_int_v3,
1246 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001247 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001248 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1249 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1250 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001251 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001252 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001253 .irqpending_quirk = 0,
1254 .needs_ip = 1,
1255 .regs_offset = 0,
1256 .spare0_offset = 0x1000,
1257 .axi_offset = 0x1e00,
1258 .spare_len = 64,
1259 .eccbytes = 0,
1260 .eccsize = 0,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001261 .ppb_shift = 7,
1262};
1263
1264/* v3.2b: i.MX53 */
1265static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
1266 .preset = preset_v3,
1267 .send_cmd = send_cmd_v3,
1268 .send_addr = send_addr_v3,
1269 .send_page = send_page_v3,
1270 .send_read_id = send_read_id_v3,
1271 .get_dev_status = get_dev_status_v3,
1272 .check_int = check_int_v3,
1273 .irq_control = irq_control_v3,
1274 .get_ecc_status = get_ecc_status_v3,
1275 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1276 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1277 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1278 .select_chip = mxc_nand_select_chip_v1_v3,
1279 .correct_data = mxc_nand_correct_data_v2_v3,
1280 .irqpending_quirk = 0,
1281 .needs_ip = 1,
1282 .regs_offset = 0,
1283 .spare0_offset = 0x1000,
1284 .axi_offset = 0x1e00,
1285 .spare_len = 64,
1286 .eccbytes = 0,
1287 .eccsize = 0,
1288 .ppb_shift = 8,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001289};
1290
Shawn Guo4d624352012-09-15 13:34:09 +08001291static inline int is_imx21_nfc(struct mxc_nand_host *host)
1292{
1293 return host->devtype_data == &imx21_nand_devtype_data;
1294}
1295
1296static inline int is_imx27_nfc(struct mxc_nand_host *host)
1297{
1298 return host->devtype_data == &imx27_nand_devtype_data;
1299}
1300
1301static inline int is_imx25_nfc(struct mxc_nand_host *host)
1302{
1303 return host->devtype_data == &imx25_nand_devtype_data;
1304}
1305
1306static inline int is_imx51_nfc(struct mxc_nand_host *host)
1307{
1308 return host->devtype_data == &imx51_nand_devtype_data;
1309}
1310
1311static inline int is_imx53_nfc(struct mxc_nand_host *host)
1312{
1313 return host->devtype_data == &imx53_nand_devtype_data;
1314}
1315
1316static struct platform_device_id mxcnd_devtype[] = {
1317 {
1318 .name = "imx21-nand",
1319 .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
1320 }, {
1321 .name = "imx27-nand",
1322 .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
1323 }, {
1324 .name = "imx25-nand",
1325 .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
1326 }, {
1327 .name = "imx51-nand",
1328 .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
1329 }, {
1330 .name = "imx53-nand",
1331 .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
1332 }, {
1333 /* sentinel */
1334 }
1335};
1336MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
1337
Uwe Kleine-König64363562012-04-23 11:23:41 +02001338#ifdef CONFIG_OF_MTD
1339static const struct of_device_id mxcnd_dt_ids[] = {
1340 {
1341 .compatible = "fsl,imx21-nand",
1342 .data = &imx21_nand_devtype_data,
1343 }, {
1344 .compatible = "fsl,imx27-nand",
1345 .data = &imx27_nand_devtype_data,
1346 }, {
1347 .compatible = "fsl,imx25-nand",
1348 .data = &imx25_nand_devtype_data,
1349 }, {
1350 .compatible = "fsl,imx51-nand",
1351 .data = &imx51_nand_devtype_data,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001352 }, {
1353 .compatible = "fsl,imx53-nand",
1354 .data = &imx53_nand_devtype_data,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001355 },
1356 { /* sentinel */ }
1357};
1358
1359static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1360{
1361 struct device_node *np = host->dev->of_node;
1362 struct mxc_nand_platform_data *pdata = &host->pdata;
1363 const struct of_device_id *of_id =
1364 of_match_device(mxcnd_dt_ids, host->dev);
1365 int buswidth;
1366
1367 if (!np)
1368 return 1;
1369
1370 if (of_get_nand_ecc_mode(np) >= 0)
1371 pdata->hw_ecc = 1;
1372
1373 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1374
1375 buswidth = of_get_nand_bus_width(np);
1376 if (buswidth < 0)
1377 return buswidth;
1378
1379 pdata->width = buswidth / 8;
1380
1381 host->devtype_data = of_id->data;
1382
1383 return 0;
1384}
1385#else
1386static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1387{
1388 return 1;
1389}
1390#endif
1391
Bill Pemberton06f25512012-11-19 13:23:07 -05001392static int mxcnd_probe(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001393{
1394 struct nand_chip *this;
1395 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001396 struct mxc_nand_host *host;
1397 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001398 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001399
1400 /* Allocate memory for MTD device structure and private data */
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001401 host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host) +
1402 NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001403 if (!host)
1404 return -ENOMEM;
1405
Sascha Hauerf8f96082009-06-04 17:12:26 +02001406 host->data_buf = (uint8_t *)(host + 1);
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) {
1434 struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
1435 if (pdata) {
1436 host->pdata = *pdata;
1437 host->devtype_data = (struct mxc_nand_devtype_data *)
1438 pdev->id_entry->driver_data;
1439 } else {
1440 err = -ENODEV;
1441 }
1442 }
Sascha Hauer71885b62012-06-06 12:33:14 +02001443 if (err < 0)
1444 return err;
1445
1446 if (host->devtype_data->needs_ip) {
1447 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1448 if (!res)
1449 return -ENODEV;
Thierry Redingb0de7742013-01-21 11:09:12 +01001450 host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
1451 if (IS_ERR(host->regs_ip))
1452 return PTR_ERR(host->regs_ip);
Sascha Hauer71885b62012-06-06 12:33:14 +02001453
1454 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1455 } else {
1456 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1457 }
1458
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001459 if (!res)
1460 return -ENODEV;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001461
Thierry Redingb0de7742013-01-21 11:09:12 +01001462 host->base = devm_ioremap_resource(&pdev->dev, res);
1463 if (IS_ERR(host->base))
1464 return PTR_ERR(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001465
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001466 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001467
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001468 if (host->devtype_data->regs_offset)
1469 host->regs = host->base + host->devtype_data->regs_offset;
1470 host->spare0 = host->base + host->devtype_data->spare0_offset;
1471 if (host->devtype_data->axi_offset)
1472 host->regs_axi = host->base + host->devtype_data->axi_offset;
1473
1474 this->ecc.bytes = host->devtype_data->eccbytes;
1475 host->eccsize = host->devtype_data->eccsize;
1476
1477 this->select_chip = host->devtype_data->select_chip;
1478 this->ecc.size = 512;
1479 this->ecc.layout = host->devtype_data->ecclayout_512;
1480
Uwe Kleine-König64363562012-04-23 11:23:41 +02001481 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001482 this->ecc.calculate = mxc_nand_calculate_ecc;
1483 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001484 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001485 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001486 } else {
1487 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001488 }
1489
Uwe Kleine-König64363562012-04-23 11:23:41 +02001490 /* NAND bus width determines access functions used by upper layer */
1491 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001492 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001493
Uwe Kleine-König64363562012-04-23 11:23:41 +02001494 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001495 this->bbt_td = &bbt_main_descr;
1496 this->bbt_md = &bbt_mirror_descr;
1497 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001498 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001499 }
1500
Sascha Hauer63f14742010-10-18 10:16:26 +02001501 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001502
1503 host->irq = platform_get_irq(pdev, 0);
1504
Sascha Hauer63f14742010-10-18 10:16:26 +02001505 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001506 * Use host->devtype_data->irq_control() here instead of irq_control()
1507 * because we must not disable_irq_nosync without having requested the
1508 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001509 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001510 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001511
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001512 err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
1513 IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001514 if (err)
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001515 return err;
1516
1517 clk_prepare_enable(host->clk);
1518 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
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001536 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001537 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001538
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001539 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001540 this->ecc.layout = host->devtype_data->ecclayout_2k;
1541 else if (mtd->writesize == 4096)
1542 this->ecc.layout = host->devtype_data->ecclayout_4k;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001543
Mike Dunn6a918ba2012-03-11 14:21:11 -07001544 if (this->ecc.mode == NAND_ECC_HW) {
Shawn Guo4d624352012-09-15 13:34:09 +08001545 if (is_imx21_nfc(host) || is_imx27_nfc(host))
Mike Dunn6a918ba2012-03-11 14:21:11 -07001546 this->ecc.strength = 1;
1547 else
1548 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1549 }
1550
Sascha Hauer4a43faf2012-05-25 16:22:42 +02001551 /* second phase scan */
1552 if (nand_scan_tail(mtd)) {
1553 err = -ENXIO;
1554 goto escan;
1555 }
1556
Sascha Hauer34f6e152008-09-02 17:16:59 +02001557 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001558 mtd_device_parse_register(mtd, part_probes,
1559 &(struct mtd_part_parser_data){
1560 .of_node = pdev->dev.of_node,
1561 },
1562 host->pdata.parts,
1563 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001564
1565 platform_set_drvdata(pdev, host);
1566
1567 return 0;
1568
1569escan:
Lothar Waßmannc10d8ee2012-12-06 08:42:27 +01001570 if (host->clk_act)
1571 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001572
1573 return err;
1574}
1575
Bill Pemberton810b7e02012-11-19 13:26:04 -05001576static int mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001577{
1578 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1579
Sascha Hauer34f6e152008-09-02 17:16:59 +02001580 platform_set_drvdata(pdev, NULL);
1581
1582 nand_release(&host->mtd);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001583
1584 return 0;
1585}
1586
Sascha Hauer34f6e152008-09-02 17:16:59 +02001587static struct platform_driver mxcnd_driver = {
1588 .driver = {
1589 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001590 .owner = THIS_MODULE,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001591 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001592 },
Shawn Guo4d624352012-09-15 13:34:09 +08001593 .id_table = mxcnd_devtype,
Fabio Estevamddf16d62012-09-05 11:35:25 -03001594 .probe = mxcnd_probe,
Bill Pemberton5153b882012-11-19 13:21:24 -05001595 .remove = mxcnd_remove,
Sascha Hauer34f6e152008-09-02 17:16:59 +02001596};
Fabio Estevamddf16d62012-09-05 11:35:25 -03001597module_platform_driver(mxcnd_driver);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001598
1599MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1600MODULE_DESCRIPTION("MXC NAND MTD driver");
1601MODULE_LICENSE("GPL");