blob: 5683604967d7687102bf97487d950a228ea8143a [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 Hauer94671142009-10-05 12:14:21 +020040#include <mach/hardware.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020041
42#define DRIVER_NAME "mxc_nand"
43
Sascha Hauer94671142009-10-05 12:14:21 +020044#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
Ivo Claryssea47bfd22010-04-08 16:16:51 +020045#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
Jason Liuc97926d2011-08-22 14:13:17 +080046#define nfc_is_v3_2() (cpu_is_mx51() || cpu_is_mx53())
Sascha Hauer71ec5152010-08-06 15:53:11 +020047#define nfc_is_v3() nfc_is_v3_2()
Sascha Hauer94671142009-10-05 12:14:21 +020048
Sascha Hauer34f6e152008-09-02 17:16:59 +020049/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020050#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
51#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
52#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
53#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
54#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
55#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
56#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
57#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
58#define NFC_V1_V2_WRPROT (host->regs + 0x12)
59#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
60#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
Baruch Siachd178e3e2011-03-14 09:01:56 +020061#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
62#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
63#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
64#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
65#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
66#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
67#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
68#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
Sascha Hauer1bc99182010-08-06 15:53:08 +020069#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
70#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
71#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020072
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020073#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020074#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
75#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
76#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
77#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
78#define NFC_V1_V2_CONFIG1_RST (1 << 6)
79#define NFC_V1_V2_CONFIG1_CE (1 << 7)
Sascha Hauerb8db2f52010-08-09 15:04:19 +020080#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
81#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
82#define NFC_V2_CONFIG1_FP_INT (1 << 11)
Sascha Hauer34f6e152008-09-02 17:16:59 +020083
Sascha Hauer1bc99182010-08-06 15:53:08 +020084#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020085
Sascha Hauer1bc99182010-08-06 15:53:08 +020086/*
87 * Operation modes for the NFC. Valid for v1, v2 and v3
88 * type controllers.
89 */
90#define NFC_CMD (1 << 0)
91#define NFC_ADDR (1 << 1)
92#define NFC_INPUT (1 << 2)
93#define NFC_OUTPUT (1 << 3)
94#define NFC_ID (1 << 4)
95#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020096
Sascha Hauer71ec5152010-08-06 15:53:11 +020097#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
98#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
Sascha Hauer34f6e152008-09-02 17:16:59 +020099
Sascha Hauer71ec5152010-08-06 15:53:11 +0200100#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
101#define NFC_V3_CONFIG1_SP_EN (1 << 0)
102#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200103
Sascha Hauer71ec5152010-08-06 15:53:11 +0200104#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200105
Sascha Hauer71ec5152010-08-06 15:53:11 +0200106#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200107
Sascha Hauer71ec5152010-08-06 15:53:11 +0200108#define NFC_V3_WRPROT (host->regs_ip + 0x0)
109#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
110#define NFC_V3_WRPROT_LOCK (1 << 1)
111#define NFC_V3_WRPROT_UNLOCK (1 << 2)
112#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
113
114#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
115
116#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
117#define NFC_V3_CONFIG2_PS_512 (0 << 0)
118#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
119#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
120#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
121#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
122#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
123#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
124#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
125#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7)
126#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
127#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
128#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
129#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
130
131#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
132#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
133#define NFC_V3_CONFIG3_FW8 (1 << 3)
134#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
135#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
136#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
137#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
138
139#define NFC_V3_IPC (host->regs_ip + 0x2C)
140#define NFC_V3_IPC_CREQ (1 << 0)
141#define NFC_V3_IPC_INT (1 << 31)
142
143#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200144
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200145struct mxc_nand_host;
146
147struct mxc_nand_devtype_data {
148 void (*preset)(struct mtd_info *);
149 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
150 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
151 void (*send_page)(struct mtd_info *, unsigned int);
152 void (*send_read_id)(struct mxc_nand_host *);
153 uint16_t (*get_dev_status)(struct mxc_nand_host *);
154 int (*check_int)(struct mxc_nand_host *);
155 void (*irq_control)(struct mxc_nand_host *, int);
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200156 u32 (*get_ecc_status)(struct mxc_nand_host *);
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +0200157 struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k;
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200158 void (*select_chip)(struct mtd_info *mtd, int chip);
Uwe Kleine-König69d023b2012-04-23 11:23:39 +0200159 int (*correct_data)(struct mtd_info *mtd, u_char *dat,
160 u_char *read_ecc, u_char *calc_ecc);
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200161
162 /*
163 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
164 * (CONFIG1:INT_MSK is set). To handle this the driver uses
165 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
166 */
167 int irqpending_quirk;
168 int needs_ip;
169
170 size_t regs_offset;
171 size_t spare0_offset;
172 size_t axi_offset;
173
174 int spare_len;
175 int eccbytes;
176 int eccsize;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200177};
178
Sascha Hauer34f6e152008-09-02 17:16:59 +0200179struct mxc_nand_host {
180 struct mtd_info mtd;
181 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200182 struct device *dev;
183
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200184 void __iomem *spare0;
185 void __iomem *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200186
187 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200188 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200189 void __iomem *regs_axi;
190 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200191 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200192 struct clk *clk;
193 int clk_act;
194 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200195 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200196 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200197
Sascha Hauer63f14742010-10-18 10:16:26 +0200198 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200199
200 uint8_t *data_buf;
201 unsigned int buf_start;
Sascha Hauer5f973042010-08-06 15:53:06 +0200202
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200203 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König64363562012-04-23 11:23:41 +0200204 struct mxc_nand_platform_data pdata;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200205};
206
Sascha Hauer34f6e152008-09-02 17:16:59 +0200207/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200208static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200209 .eccbytes = 5,
210 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200211 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200212};
213
Sascha Hauer94671142009-10-05 12:14:21 +0200214static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400215 .eccbytes = 20,
216 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
217 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
218 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200219};
220
Sascha Hauer94671142009-10-05 12:14:21 +0200221/* OOB description for 512 byte pages with 16 byte OOB */
222static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
223 .eccbytes = 1 * 9,
224 .eccpos = {
225 7, 8, 9, 10, 11, 12, 13, 14, 15
226 },
227 .oobfree = {
228 {.offset = 0, .length = 5}
229 }
230};
231
232/* OOB description for 2048 byte pages with 64 byte OOB */
233static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
234 .eccbytes = 4 * 9,
235 .eccpos = {
236 7, 8, 9, 10, 11, 12, 13, 14, 15,
237 23, 24, 25, 26, 27, 28, 29, 30, 31,
238 39, 40, 41, 42, 43, 44, 45, 46, 47,
239 55, 56, 57, 58, 59, 60, 61, 62, 63
240 },
241 .oobfree = {
242 {.offset = 2, .length = 4},
243 {.offset = 16, .length = 7},
244 {.offset = 32, .length = 7},
245 {.offset = 48, .length = 7}
246 }
247};
248
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200249/* OOB description for 4096 byte pages with 128 byte OOB */
250static struct nand_ecclayout nandv2_hw_eccoob_4k = {
251 .eccbytes = 8 * 9,
252 .eccpos = {
253 7, 8, 9, 10, 11, 12, 13, 14, 15,
254 23, 24, 25, 26, 27, 28, 29, 30, 31,
255 39, 40, 41, 42, 43, 44, 45, 46, 47,
256 55, 56, 57, 58, 59, 60, 61, 62, 63,
257 71, 72, 73, 74, 75, 76, 77, 78, 79,
258 87, 88, 89, 90, 91, 92, 93, 94, 95,
259 103, 104, 105, 106, 107, 108, 109, 110, 111,
260 119, 120, 121, 122, 123, 124, 125, 126, 127,
261 },
262 .oobfree = {
263 {.offset = 2, .length = 4},
264 {.offset = 16, .length = 7},
265 {.offset = 32, .length = 7},
266 {.offset = 48, .length = 7},
267 {.offset = 64, .length = 7},
268 {.offset = 80, .length = 7},
269 {.offset = 96, .length = 7},
270 {.offset = 112, .length = 7},
271 }
272};
273
Uwe Kleine-König64363562012-04-23 11:23:41 +0200274static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200275
Sascha Hauer096bcc22012-05-29 10:16:09 +0200276static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
277{
278 int i;
279 u32 *t = trg;
280 const __iomem u32 *s = src;
281
282 for (i = 0; i < (size >> 2); i++)
283 *t++ = __raw_readl(s++);
284}
285
286static void memcpy32_toio(void __iomem *trg, const void *src, int size)
287{
288 int i;
289 u32 __iomem *t = trg;
290 const u32 *s = src;
291
292 for (i = 0; i < (size >> 2); i++)
293 __raw_writel(*s++, t++);
294}
295
Sascha Hauer71ec5152010-08-06 15:53:11 +0200296static int check_int_v3(struct mxc_nand_host *host)
297{
298 uint32_t tmp;
299
300 tmp = readl(NFC_V3_IPC);
301 if (!(tmp & NFC_V3_IPC_INT))
302 return 0;
303
304 tmp &= ~NFC_V3_IPC_INT;
305 writel(tmp, NFC_V3_IPC);
306
307 return 1;
308}
309
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200310static int check_int_v1_v2(struct mxc_nand_host *host)
311{
312 uint32_t tmp;
313
Sascha Hauer1bc99182010-08-06 15:53:08 +0200314 tmp = readw(NFC_V1_V2_CONFIG2);
315 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200316 return 0;
317
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200318 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200319 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200320
321 return 1;
322}
323
Sascha Hauer63f14742010-10-18 10:16:26 +0200324static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
325{
326 uint16_t tmp;
327
328 tmp = readw(NFC_V1_V2_CONFIG1);
329
330 if (activate)
331 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
332 else
333 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
334
335 writew(tmp, NFC_V1_V2_CONFIG1);
336}
337
338static void irq_control_v3(struct mxc_nand_host *host, int activate)
339{
340 uint32_t tmp;
341
342 tmp = readl(NFC_V3_CONFIG2);
343
344 if (activate)
345 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
346 else
347 tmp |= NFC_V3_CONFIG2_INT_MSK;
348
349 writel(tmp, NFC_V3_CONFIG2);
350}
351
Uwe Kleine-König85569582012-04-23 11:23:34 +0200352static void irq_control(struct mxc_nand_host *host, int activate)
353{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200354 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200355 if (activate)
356 enable_irq(host->irq);
357 else
358 disable_irq_nosync(host->irq);
359 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200360 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200361 }
362}
363
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200364static u32 get_ecc_status_v1(struct mxc_nand_host *host)
365{
366 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
367}
368
369static u32 get_ecc_status_v2(struct mxc_nand_host *host)
370{
371 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
372}
373
374static u32 get_ecc_status_v3(struct mxc_nand_host *host)
375{
376 return readl(NFC_V3_ECC_STATUS_RESULT);
377}
378
Uwe Kleine-König85569582012-04-23 11:23:34 +0200379static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
380{
381 struct mxc_nand_host *host = dev_id;
382
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200383 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200384 return IRQ_NONE;
385
386 irq_control(host, 0);
387
388 complete(&host->op_completion);
389
390 return IRQ_HANDLED;
391}
392
Sascha Hauer34f6e152008-09-02 17:16:59 +0200393/* This function polls the NANDFC to wait for the basic operation to
394 * complete by checking the INT bit of config2 register.
395 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200396static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200397{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200398 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200399
400 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200401 if (!host->devtype_data->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200402 INIT_COMPLETION(host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200403 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200404 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200405 }
406 } else {
407 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200408 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200409 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200410
Sascha Hauer34f6e152008-09-02 17:16:59 +0200411 udelay(1);
412 }
Roel Kluin43950a62009-06-04 16:24:59 +0200413 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700414 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200415 }
416}
417
Sascha Hauer71ec5152010-08-06 15:53:11 +0200418static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
419{
420 /* fill command */
421 writel(cmd, NFC_V3_FLASH_CMD);
422
423 /* send out command */
424 writel(NFC_CMD, NFC_V3_LAUNCH);
425
426 /* Wait for operation to complete */
427 wait_op_done(host, useirq);
428}
429
Sascha Hauer34f6e152008-09-02 17:16:59 +0200430/* This function issues the specified command to the NAND device and
431 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200432static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200433{
Brian Norris289c0522011-07-19 10:06:09 -0700434 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200435
Sascha Hauer1bc99182010-08-06 15:53:08 +0200436 writew(cmd, NFC_V1_V2_FLASH_CMD);
437 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200438
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200439 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200440 int max_retries = 100;
441 /* Reset completion is indicated by NFC_CONFIG2 */
442 /* being set to 0 */
443 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200444 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200445 break;
446 }
447 udelay(1);
448 }
449 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700450 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200451 } else {
452 /* Wait for operation to complete */
453 wait_op_done(host, useirq);
454 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200455}
456
Sascha Hauer71ec5152010-08-06 15:53:11 +0200457static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
458{
459 /* fill address */
460 writel(addr, NFC_V3_FLASH_ADDR0);
461
462 /* send out address */
463 writel(NFC_ADDR, NFC_V3_LAUNCH);
464
465 wait_op_done(host, 0);
466}
467
Sascha Hauer34f6e152008-09-02 17:16:59 +0200468/* This function sends an address (or partial address) to the
469 * NAND device. The address is used to select the source/destination for
470 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200471static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200472{
Brian Norris289c0522011-07-19 10:06:09 -0700473 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200474
Sascha Hauer1bc99182010-08-06 15:53:08 +0200475 writew(addr, NFC_V1_V2_FLASH_ADDR);
476 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200477
478 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200479 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200480}
481
Sascha Hauer71ec5152010-08-06 15:53:11 +0200482static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
483{
484 struct nand_chip *nand_chip = mtd->priv;
485 struct mxc_nand_host *host = nand_chip->priv;
486 uint32_t tmp;
487
488 tmp = readl(NFC_V3_CONFIG1);
489 tmp &= ~(7 << 4);
490 writel(tmp, NFC_V3_CONFIG1);
491
492 /* transfer data from NFC ram to nand */
493 writel(ops, NFC_V3_LAUNCH);
494
495 wait_op_done(host, false);
496}
497
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200498static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
499{
500 struct nand_chip *nand_chip = mtd->priv;
501 struct mxc_nand_host *host = nand_chip->priv;
502
503 /* NANDFC buffer 0 is used for page read/write */
504 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
505
506 writew(ops, NFC_V1_V2_CONFIG2);
507
508 /* Wait for operation to complete */
509 wait_op_done(host, true);
510}
511
512static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200513{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200514 struct nand_chip *nand_chip = mtd->priv;
515 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200516 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200517
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200518 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200519 bufs = 4;
520 else
521 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200522
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200523 for (i = 0; i < bufs; i++) {
524
525 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200526 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200527
Sascha Hauer1bc99182010-08-06 15:53:08 +0200528 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200529
530 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200531 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200532 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200533}
534
Sascha Hauer71ec5152010-08-06 15:53:11 +0200535static void send_read_id_v3(struct mxc_nand_host *host)
536{
537 /* Read ID into main buffer */
538 writel(NFC_ID, NFC_V3_LAUNCH);
539
540 wait_op_done(host, true);
541
Sascha Hauer096bcc22012-05-29 10:16:09 +0200542 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Sascha Hauer71ec5152010-08-06 15:53:11 +0200543}
544
Sascha Hauer34f6e152008-09-02 17:16:59 +0200545/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200546static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200547{
548 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200549
550 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200551 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200552
Sascha Hauer1bc99182010-08-06 15:53:08 +0200553 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200554
555 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200556 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200557
Sascha Hauer096bcc22012-05-29 10:16:09 +0200558 memcpy32_fromio(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200559
560 if (this->options & NAND_BUSWIDTH_16) {
561 /* compress the ID info */
562 host->data_buf[1] = host->data_buf[2];
563 host->data_buf[2] = host->data_buf[4];
564 host->data_buf[3] = host->data_buf[6];
565 host->data_buf[4] = host->data_buf[8];
566 host->data_buf[5] = host->data_buf[10];
567 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200568}
569
Sascha Hauer71ec5152010-08-06 15:53:11 +0200570static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200571{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200572 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200573 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200574
Sascha Hauer71ec5152010-08-06 15:53:11 +0200575 return readl(NFC_V3_CONFIG1) >> 16;
576}
577
Sascha Hauer34f6e152008-09-02 17:16:59 +0200578/* This function requests the NANDFC to perform a read of the
579 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200580static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200581{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200582 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200583 uint32_t store;
584 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200585
Baruch Siachd178e3e2011-03-14 09:01:56 +0200586 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200587
588 /*
589 * The device status is stored in main_area0. To
590 * prevent corruption of the buffer save the value
591 * and restore it afterwards.
592 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200593 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200594
Sascha Hauer1bc99182010-08-06 15:53:08 +0200595 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200596 wait_op_done(host, true);
597
Sascha Hauer34f6e152008-09-02 17:16:59 +0200598 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200599
Sascha Hauer34f6e152008-09-02 17:16:59 +0200600 writel(store, main_buf);
601
602 return ret;
603}
604
605/* This functions is used by upper layer to checks if device is ready */
606static int mxc_nand_dev_ready(struct mtd_info *mtd)
607{
608 /*
609 * NFC handles R/B internally. Therefore, this function
610 * always returns status as ready.
611 */
612 return 1;
613}
614
615static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
616{
617 /*
618 * If HW ECC is enabled, we turn it on during init. There is
619 * no need to enable again here.
620 */
621}
622
Sascha Hauer94f77e52010-08-06 15:53:09 +0200623static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200624 u_char *read_ecc, u_char *calc_ecc)
625{
626 struct nand_chip *nand_chip = mtd->priv;
627 struct mxc_nand_host *host = nand_chip->priv;
628
629 /*
630 * 1-Bit errors are automatically corrected in HW. No need for
631 * additional correction. 2-Bit errors cannot be corrected by
632 * HW ECC, so we need to return failure
633 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200634 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200635
636 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700637 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200638 return -1;
639 }
640
641 return 0;
642}
643
Sascha Hauer94f77e52010-08-06 15:53:09 +0200644static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
645 u_char *read_ecc, u_char *calc_ecc)
646{
647 struct nand_chip *nand_chip = mtd->priv;
648 struct mxc_nand_host *host = nand_chip->priv;
649 u32 ecc_stat, err;
650 int no_subpages = 1;
651 int ret = 0;
652 u8 ecc_bit_mask, err_limit;
653
654 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
655 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
656
657 no_subpages = mtd->writesize >> 9;
658
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200659 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200660
661 do {
662 err = ecc_stat & ecc_bit_mask;
663 if (err > err_limit) {
664 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
665 return -1;
666 } else {
667 ret += err;
668 }
669 ecc_stat >>= 4;
670 } while (--no_subpages);
671
672 mtd->ecc_stats.corrected += ret;
673 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
674
675 return ret;
676}
677
Sascha Hauer34f6e152008-09-02 17:16:59 +0200678static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
679 u_char *ecc_code)
680{
681 return 0;
682}
683
684static u_char mxc_nand_read_byte(struct mtd_info *mtd)
685{
686 struct nand_chip *nand_chip = mtd->priv;
687 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200688 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200689
690 /* Check for status request */
691 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200692 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200693
Sascha Hauerf8f96082009-06-04 17:12:26 +0200694 ret = *(uint8_t *)(host->data_buf + host->buf_start);
695 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200696
697 return ret;
698}
699
700static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
701{
702 struct nand_chip *nand_chip = mtd->priv;
703 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200704 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200705
Sascha Hauerf8f96082009-06-04 17:12:26 +0200706 ret = *(uint16_t *)(host->data_buf + host->buf_start);
707 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200708
709 return ret;
710}
711
712/* Write data of length len to buffer buf. The data to be
713 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
714 * Operation by the NFC, the data is written to NAND Flash */
715static void mxc_nand_write_buf(struct mtd_info *mtd,
716 const u_char *buf, int len)
717{
718 struct nand_chip *nand_chip = mtd->priv;
719 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200720 u16 col = host->buf_start;
721 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200722
Sascha Hauerf8f96082009-06-04 17:12:26 +0200723 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200724
Sascha Hauerf8f96082009-06-04 17:12:26 +0200725 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200726
Sascha Hauerf8f96082009-06-04 17:12:26 +0200727 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200728}
729
730/* Read the data buffer from the NAND Flash. To read the data from NAND
731 * Flash first the data output cycle is initiated by the NFC, which copies
732 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
733 */
734static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
735{
736 struct nand_chip *nand_chip = mtd->priv;
737 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200738 u16 col = host->buf_start;
739 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200740
Sascha Hauerf8f96082009-06-04 17:12:26 +0200741 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200742
Baruch Siach5d9d9932011-03-02 16:47:55 +0200743 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200744
Baruch Siach5d9d9932011-03-02 16:47:55 +0200745 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200746}
747
748/* Used by the upper layer to verify the data in NAND Flash
749 * with the data in the buf. */
750static int mxc_nand_verify_buf(struct mtd_info *mtd,
751 const u_char *buf, int len)
752{
753 return -EFAULT;
754}
755
756/* This function is used by upper layer for select and
757 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200758static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200759{
760 struct nand_chip *nand_chip = mtd->priv;
761 struct mxc_nand_host *host = nand_chip->priv;
762
Baruch Siachd178e3e2011-03-14 09:01:56 +0200763 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200764 /* Disable the NFC clock */
765 if (host->clk_act) {
Sascha Hauer97c32132012-03-07 20:56:35 +0100766 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200767 host->clk_act = 0;
768 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200769 return;
770 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200771
Baruch Siachd178e3e2011-03-14 09:01:56 +0200772 if (!host->clk_act) {
773 /* Enable the NFC clock */
Sascha Hauer97c32132012-03-07 20:56:35 +0100774 clk_prepare_enable(host->clk);
Baruch Siachd178e3e2011-03-14 09:01:56 +0200775 host->clk_act = 1;
776 }
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200777}
Baruch Siachd178e3e2011-03-14 09:01:56 +0200778
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200779static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200780{
781 struct nand_chip *nand_chip = mtd->priv;
782 struct mxc_nand_host *host = nand_chip->priv;
783
784 if (chip == -1) {
785 /* Disable the NFC clock */
786 if (host->clk_act) {
787 clk_disable(host->clk);
788 host->clk_act = 0;
789 }
790 return;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200791 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200792
793 if (!host->clk_act) {
794 /* Enable the NFC clock */
795 clk_enable(host->clk);
796 host->clk_act = 1;
797 }
798
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200799 host->active_cs = chip;
800 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200801}
802
Sascha Hauerf8f96082009-06-04 17:12:26 +0200803/*
804 * Function to transfer data to/from spare area.
805 */
806static void copy_spare(struct mtd_info *mtd, bool bfrom)
807{
808 struct nand_chip *this = mtd->priv;
809 struct mxc_nand_host *host = this->priv;
810 u16 i, j;
811 u16 n = mtd->writesize >> 9;
812 u8 *d = host->data_buf + mtd->writesize;
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200813 u8 __iomem *s = host->spare0;
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200814 u16 t = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200815
816 j = (mtd->oobsize / n >> 1) << 1;
817
818 if (bfrom) {
819 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200820 memcpy32_fromio(d + i * j, s + i * t, j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200821
822 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200823 memcpy32_fromio(d + i * j, s + i * t, mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200824 } else {
825 for (i = 0; i < n - 1; i++)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200826 memcpy32_toio(&s[i * t], &d[i * j], j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200827
828 /* the last section */
Sascha Hauer096bcc22012-05-29 10:16:09 +0200829 memcpy32_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200830 }
831}
832
Sascha Hauera3e65b62009-06-02 11:47:59 +0200833static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200834{
835 struct nand_chip *nand_chip = mtd->priv;
836 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200837
838 /* Write out column address, if necessary */
839 if (column != -1) {
840 /*
841 * MXC NANDFC can only perform full page+spare or
842 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100843 * perform a read/write buf operation, the saved column
844 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200845 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200846 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200847 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200848 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200849 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200850 }
851
852 /* Write out page address, if necessary */
853 if (page_addr != -1) {
854 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200855 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200856
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200857 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400858 if (mtd->size >= 0x10000000) {
859 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200860 host->devtype_data->send_addr(host,
861 (page_addr >> 8) & 0xff,
862 false);
863 host->devtype_data->send_addr(host,
864 (page_addr >> 16) & 0xff,
865 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400866 } else
867 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200868 host->devtype_data->send_addr(host,
869 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200870 } else {
871 /* One more address cycle for higher density devices */
872 if (mtd->size >= 0x4000000) {
873 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200874 host->devtype_data->send_addr(host,
875 (page_addr >> 8) & 0xff,
876 false);
877 host->devtype_data->send_addr(host,
878 (page_addr >> 16) & 0xff,
879 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200880 } else
881 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200882 host->devtype_data->send_addr(host,
883 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200884 }
885 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200886}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200887
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200888/*
889 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
890 * on how much oob the nand chip has. For 8bit ecc we need at least
891 * 26 bytes of oob data per 512 byte block.
892 */
893static int get_eccsize(struct mtd_info *mtd)
894{
895 int oobbytes_per_512 = 0;
896
897 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
898
899 if (oobbytes_per_512 < 26)
900 return 4;
901 else
902 return 8;
903}
904
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200905static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200906{
907 struct nand_chip *nand_chip = mtd->priv;
908 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200909 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200910
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200911 if (nand_chip->ecc.mode == NAND_ECC_HW)
912 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
913
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200914 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200915 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200916
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200917 host->eccsize = 1;
918
919 writew(config1, NFC_V1_V2_CONFIG1);
920 /* preset operation */
921
922 /* Unlock the internal RAM Buffer */
923 writew(0x2, NFC_V1_V2_CONFIG);
924
925 /* Blocks to be unlocked */
926 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
927 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
928
929 /* Unlock Block Command for given address range */
930 writew(0x4, NFC_V1_V2_WRPROT);
931}
932
933static void preset_v2(struct mtd_info *mtd)
934{
935 struct nand_chip *nand_chip = mtd->priv;
936 struct mxc_nand_host *host = nand_chip->priv;
937 uint16_t config1 = 0;
938
939 if (nand_chip->ecc.mode == NAND_ECC_HW)
940 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
941
942 config1 |= NFC_V2_CONFIG1_FP_INT;
Ivo Claryssed4840182010-04-08 16:14:44 +0200943
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200944 if (!host->devtype_data->irqpending_quirk)
Ivo Claryssed4840182010-04-08 16:14:44 +0200945 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200946
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200947 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200948 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
949
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200950 host->eccsize = get_eccsize(mtd);
951 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200952 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
953
954 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200955 } else {
956 host->eccsize = 1;
957 }
958
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200959 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200960 /* preset operation */
961
962 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200963 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200964
965 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200966 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
967 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
968 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
969 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
970 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
971 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
972 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
973 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200974
975 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200976 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200977}
978
Sascha Hauer71ec5152010-08-06 15:53:11 +0200979static void preset_v3(struct mtd_info *mtd)
980{
981 struct nand_chip *chip = mtd->priv;
982 struct mxc_nand_host *host = chip->priv;
983 uint32_t config2, config3;
984 int i, addr_phases;
985
986 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
987 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
988
989 /* Unlock the internal RAM Buffer */
990 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
991 NFC_V3_WRPROT);
992
993 /* Blocks to be unlocked */
994 for (i = 0; i < NAND_MAX_CHIPS; i++)
995 writel(0x0 | (0xffff << 16),
996 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
997
998 writel(0, NFC_V3_IPC);
999
1000 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
1001 NFC_V3_CONFIG2_2CMD_PHASES |
1002 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
1003 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +02001004 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +02001005 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
1006
1007 if (chip->ecc.mode == NAND_ECC_HW)
1008 config2 |= NFC_V3_CONFIG2_ECC_EN;
1009
1010 addr_phases = fls(chip->pagemask) >> 3;
1011
1012 if (mtd->writesize == 2048) {
1013 config2 |= NFC_V3_CONFIG2_PS_2048;
1014 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1015 } else if (mtd->writesize == 4096) {
1016 config2 |= NFC_V3_CONFIG2_PS_4096;
1017 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1018 } else {
1019 config2 |= NFC_V3_CONFIG2_PS_512;
1020 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1021 }
1022
1023 if (mtd->writesize) {
1024 config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
1025 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
1237/* v3: i.MX51, i.MX53 */
1238static 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,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001261};
1262
Uwe Kleine-König64363562012-04-23 11:23:41 +02001263#ifdef CONFIG_OF_MTD
1264static const struct of_device_id mxcnd_dt_ids[] = {
1265 {
1266 .compatible = "fsl,imx21-nand",
1267 .data = &imx21_nand_devtype_data,
1268 }, {
1269 .compatible = "fsl,imx27-nand",
1270 .data = &imx27_nand_devtype_data,
1271 }, {
1272 .compatible = "fsl,imx25-nand",
1273 .data = &imx25_nand_devtype_data,
1274 }, {
1275 .compatible = "fsl,imx51-nand",
1276 .data = &imx51_nand_devtype_data,
1277 },
1278 { /* sentinel */ }
1279};
1280
1281static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1282{
1283 struct device_node *np = host->dev->of_node;
1284 struct mxc_nand_platform_data *pdata = &host->pdata;
1285 const struct of_device_id *of_id =
1286 of_match_device(mxcnd_dt_ids, host->dev);
1287 int buswidth;
1288
1289 if (!np)
1290 return 1;
1291
1292 if (of_get_nand_ecc_mode(np) >= 0)
1293 pdata->hw_ecc = 1;
1294
1295 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1296
1297 buswidth = of_get_nand_bus_width(np);
1298 if (buswidth < 0)
1299 return buswidth;
1300
1301 pdata->width = buswidth / 8;
1302
1303 host->devtype_data = of_id->data;
1304
1305 return 0;
1306}
1307#else
1308static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1309{
1310 return 1;
1311}
1312#endif
1313
1314static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
1315{
1316 struct mxc_nand_platform_data *pdata = host->dev->platform_data;
1317
1318 if (!pdata)
1319 return -ENODEV;
1320
1321 host->pdata = *pdata;
1322
1323 if (nfc_is_v1()) {
1324 if (cpu_is_mx21())
1325 host->devtype_data = &imx21_nand_devtype_data;
1326 else
1327 host->devtype_data = &imx27_nand_devtype_data;
1328 } else if (nfc_is_v21()) {
1329 host->devtype_data = &imx25_nand_devtype_data;
1330 } else if (nfc_is_v3_2()) {
1331 host->devtype_data = &imx51_nand_devtype_data;
1332 } else
1333 BUG();
1334
1335 return 0;
1336}
1337
Sascha Hauer34f6e152008-09-02 17:16:59 +02001338static int __init mxcnd_probe(struct platform_device *pdev)
1339{
1340 struct nand_chip *this;
1341 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001342 struct mxc_nand_host *host;
1343 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001344 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001345
1346 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +02001347 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
1348 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001349 if (!host)
1350 return -ENOMEM;
1351
Sascha Hauerf8f96082009-06-04 17:12:26 +02001352 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001353
Sascha Hauer34f6e152008-09-02 17:16:59 +02001354 host->dev = &pdev->dev;
1355 /* structures must be linked */
1356 this = &host->nand;
1357 mtd = &host->mtd;
1358 mtd->priv = this;
1359 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001360 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001361 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001362
1363 /* 50 us command delay time */
1364 this->chip_delay = 5;
1365
1366 this->priv = host;
1367 this->dev_ready = mxc_nand_dev_ready;
1368 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001369 this->read_byte = mxc_nand_read_byte;
1370 this->read_word = mxc_nand_read_word;
1371 this->write_buf = mxc_nand_write_buf;
1372 this->read_buf = mxc_nand_read_buf;
1373 this->verify_buf = mxc_nand_verify_buf;
1374
Sascha Hauere65fb002009-02-16 14:29:10 +01001375 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +04001376 if (IS_ERR(host->clk)) {
1377 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001378 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +04001379 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001380
Sascha Hauer97c32132012-03-07 20:56:35 +01001381 clk_prepare_enable(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001382 host->clk_act = 1;
1383
1384 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1385 if (!res) {
1386 err = -ENODEV;
1387 goto eres;
1388 }
1389
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001390 host->base = ioremap(res->start, resource_size(res));
1391 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +04001392 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001393 goto eres;
1394 }
1395
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001396 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001397
Uwe Kleine-König64363562012-04-23 11:23:41 +02001398 err = mxcnd_probe_dt(host);
1399 if (err > 0)
1400 err = mxcnd_probe_pdata(host);
1401 if (err < 0)
1402 goto eirq;
Sascha Hauer94671142009-10-05 12:14:21 +02001403
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001404 if (host->devtype_data->regs_offset)
1405 host->regs = host->base + host->devtype_data->regs_offset;
1406 host->spare0 = host->base + host->devtype_data->spare0_offset;
1407 if (host->devtype_data->axi_offset)
1408 host->regs_axi = host->base + host->devtype_data->axi_offset;
1409
1410 this->ecc.bytes = host->devtype_data->eccbytes;
1411 host->eccsize = host->devtype_data->eccsize;
1412
1413 this->select_chip = host->devtype_data->select_chip;
1414 this->ecc.size = 512;
1415 this->ecc.layout = host->devtype_data->ecclayout_512;
1416
1417 if (host->devtype_data->needs_ip) {
Sascha Hauer71ec5152010-08-06 15:53:11 +02001418 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1419 if (!res) {
1420 err = -ENODEV;
1421 goto eirq;
1422 }
1423 host->regs_ip = ioremap(res->start, resource_size(res));
1424 if (!host->regs_ip) {
1425 err = -ENOMEM;
1426 goto eirq;
1427 }
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001428 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001429
Uwe Kleine-König64363562012-04-23 11:23:41 +02001430 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001431 this->ecc.calculate = mxc_nand_calculate_ecc;
1432 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001433 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001434 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001435 } else {
1436 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001437 }
1438
Uwe Kleine-König64363562012-04-23 11:23:41 +02001439 /* NAND bus width determines access functions used by upper layer */
1440 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001441 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001442
Uwe Kleine-König64363562012-04-23 11:23:41 +02001443 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001444 this->bbt_td = &bbt_main_descr;
1445 this->bbt_md = &bbt_mirror_descr;
1446 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001447 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001448 }
1449
Sascha Hauer63f14742010-10-18 10:16:26 +02001450 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001451
1452 host->irq = platform_get_irq(pdev, 0);
1453
Sascha Hauer63f14742010-10-18 10:16:26 +02001454 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001455 * Use host->devtype_data->irq_control() here instead of irq_control()
1456 * because we must not disable_irq_nosync without having requested the
1457 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001458 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001459 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001460
Ivo Claryssea47bfd22010-04-08 16:16:51 +02001461 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001462 if (err)
1463 goto eirq;
1464
Sascha Hauer63f14742010-10-18 10:16:26 +02001465 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001466 * Now that we "own" the interrupt make sure the interrupt mask bit is
1467 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1468 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001469 */
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001470 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +02001471 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001472 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001473 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001474
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001475 /* first scan to find the device and get the page size */
Baruch Siachd178e3e2011-03-14 09:01:56 +02001476 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001477 err = -ENXIO;
1478 goto escan;
1479 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001480
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001481 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001482 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001483
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001484 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001485 this->ecc.layout = host->devtype_data->ecclayout_2k;
1486 else if (mtd->writesize == 4096)
1487 this->ecc.layout = host->devtype_data->ecclayout_4k;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001488
Mike Dunn6a918ba2012-03-11 14:21:11 -07001489 if (this->ecc.mode == NAND_ECC_HW) {
1490 if (nfc_is_v1())
1491 this->ecc.strength = 1;
1492 else
1493 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1494 }
1495
Sascha Hauer4a43faf2012-05-25 16:22:42 +02001496 /* second phase scan */
1497 if (nand_scan_tail(mtd)) {
1498 err = -ENXIO;
1499 goto escan;
1500 }
1501
Sascha Hauer34f6e152008-09-02 17:16:59 +02001502 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001503 mtd_device_parse_register(mtd, part_probes,
1504 &(struct mtd_part_parser_data){
1505 .of_node = pdev->dev.of_node,
1506 },
1507 host->pdata.parts,
1508 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001509
1510 platform_set_drvdata(pdev, host);
1511
1512 return 0;
1513
1514escan:
Magnus Liljab258fd82009-05-08 21:57:47 +02001515 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001516eirq:
Sascha Hauer71ec5152010-08-06 15:53:11 +02001517 if (host->regs_ip)
1518 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001519 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001520eres:
1521 clk_put(host->clk);
1522eclk:
1523 kfree(host);
1524
1525 return err;
1526}
1527
Uwe Kleine-König51eeb872009-12-07 09:44:05 +00001528static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001529{
1530 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1531
1532 clk_put(host->clk);
1533
1534 platform_set_drvdata(pdev, NULL);
1535
1536 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +02001537 free_irq(host->irq, host);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001538 if (host->regs_ip)
1539 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001540 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001541 kfree(host);
1542
1543 return 0;
1544}
1545
Sascha Hauer34f6e152008-09-02 17:16:59 +02001546static struct platform_driver mxcnd_driver = {
1547 .driver = {
1548 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001549 .owner = THIS_MODULE,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001550 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001551 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +01001552 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +02001553};
1554
1555static int __init mxc_nd_init(void)
1556{
Vladimir Barinov8541c112009-04-23 15:47:22 +04001557 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001558}
1559
1560static void __exit mxc_nd_cleanup(void)
1561{
1562 /* Unregister the device structure */
1563 platform_driver_unregister(&mxcnd_driver);
1564}
1565
1566module_init(mxc_nd_init);
1567module_exit(mxc_nd_cleanup);
1568
1569MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1570MODULE_DESCRIPTION("MXC NAND MTD driver");
1571MODULE_LICENSE("GPL");