blob: 1041bb134628afa84b172e2c4b5e7cb0b270921b [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>
39#include <mach/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
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200184 void *spare0;
185 void *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 Hauer71ec5152010-08-06 15:53:11 +0200276static int check_int_v3(struct mxc_nand_host *host)
277{
278 uint32_t tmp;
279
280 tmp = readl(NFC_V3_IPC);
281 if (!(tmp & NFC_V3_IPC_INT))
282 return 0;
283
284 tmp &= ~NFC_V3_IPC_INT;
285 writel(tmp, NFC_V3_IPC);
286
287 return 1;
288}
289
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200290static int check_int_v1_v2(struct mxc_nand_host *host)
291{
292 uint32_t tmp;
293
Sascha Hauer1bc99182010-08-06 15:53:08 +0200294 tmp = readw(NFC_V1_V2_CONFIG2);
295 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200296 return 0;
297
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200298 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200299 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200300
301 return 1;
302}
303
Sascha Hauer63f14742010-10-18 10:16:26 +0200304static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
305{
306 uint16_t tmp;
307
308 tmp = readw(NFC_V1_V2_CONFIG1);
309
310 if (activate)
311 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
312 else
313 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
314
315 writew(tmp, NFC_V1_V2_CONFIG1);
316}
317
318static void irq_control_v3(struct mxc_nand_host *host, int activate)
319{
320 uint32_t tmp;
321
322 tmp = readl(NFC_V3_CONFIG2);
323
324 if (activate)
325 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
326 else
327 tmp |= NFC_V3_CONFIG2_INT_MSK;
328
329 writel(tmp, NFC_V3_CONFIG2);
330}
331
Uwe Kleine-König85569582012-04-23 11:23:34 +0200332static void irq_control(struct mxc_nand_host *host, int activate)
333{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200334 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200335 if (activate)
336 enable_irq(host->irq);
337 else
338 disable_irq_nosync(host->irq);
339 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200340 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200341 }
342}
343
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200344static u32 get_ecc_status_v1(struct mxc_nand_host *host)
345{
346 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
347}
348
349static u32 get_ecc_status_v2(struct mxc_nand_host *host)
350{
351 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
352}
353
354static u32 get_ecc_status_v3(struct mxc_nand_host *host)
355{
356 return readl(NFC_V3_ECC_STATUS_RESULT);
357}
358
Uwe Kleine-König85569582012-04-23 11:23:34 +0200359static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
360{
361 struct mxc_nand_host *host = dev_id;
362
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200363 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200364 return IRQ_NONE;
365
366 irq_control(host, 0);
367
368 complete(&host->op_completion);
369
370 return IRQ_HANDLED;
371}
372
Sascha Hauer34f6e152008-09-02 17:16:59 +0200373/* This function polls the NANDFC to wait for the basic operation to
374 * complete by checking the INT bit of config2 register.
375 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200376static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200377{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200378 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200379
380 if (useirq) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200381 if (!host->devtype_data->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200382 INIT_COMPLETION(host->op_completion);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200383 irq_control(host, 1);
Sascha Hauer63f14742010-10-18 10:16:26 +0200384 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200385 }
386 } else {
387 while (max_retries-- > 0) {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200388 if (host->devtype_data->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200389 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200390
Sascha Hauer34f6e152008-09-02 17:16:59 +0200391 udelay(1);
392 }
Roel Kluin43950a62009-06-04 16:24:59 +0200393 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700394 pr_debug("%s: INT not set\n", __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200395 }
396}
397
Sascha Hauer71ec5152010-08-06 15:53:11 +0200398static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
399{
400 /* fill command */
401 writel(cmd, NFC_V3_FLASH_CMD);
402
403 /* send out command */
404 writel(NFC_CMD, NFC_V3_LAUNCH);
405
406 /* Wait for operation to complete */
407 wait_op_done(host, useirq);
408}
409
Sascha Hauer34f6e152008-09-02 17:16:59 +0200410/* This function issues the specified command to the NAND device and
411 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200412static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200413{
Brian Norris289c0522011-07-19 10:06:09 -0700414 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200415
Sascha Hauer1bc99182010-08-06 15:53:08 +0200416 writew(cmd, NFC_V1_V2_FLASH_CMD);
417 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200418
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200419 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200420 int max_retries = 100;
421 /* Reset completion is indicated by NFC_CONFIG2 */
422 /* being set to 0 */
423 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200424 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200425 break;
426 }
427 udelay(1);
428 }
429 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700430 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200431 } else {
432 /* Wait for operation to complete */
433 wait_op_done(host, useirq);
434 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200435}
436
Sascha Hauer71ec5152010-08-06 15:53:11 +0200437static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
438{
439 /* fill address */
440 writel(addr, NFC_V3_FLASH_ADDR0);
441
442 /* send out address */
443 writel(NFC_ADDR, NFC_V3_LAUNCH);
444
445 wait_op_done(host, 0);
446}
447
Sascha Hauer34f6e152008-09-02 17:16:59 +0200448/* This function sends an address (or partial address) to the
449 * NAND device. The address is used to select the source/destination for
450 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200451static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200452{
Brian Norris289c0522011-07-19 10:06:09 -0700453 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200454
Sascha Hauer1bc99182010-08-06 15:53:08 +0200455 writew(addr, NFC_V1_V2_FLASH_ADDR);
456 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200457
458 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200459 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200460}
461
Sascha Hauer71ec5152010-08-06 15:53:11 +0200462static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
463{
464 struct nand_chip *nand_chip = mtd->priv;
465 struct mxc_nand_host *host = nand_chip->priv;
466 uint32_t tmp;
467
468 tmp = readl(NFC_V3_CONFIG1);
469 tmp &= ~(7 << 4);
470 writel(tmp, NFC_V3_CONFIG1);
471
472 /* transfer data from NFC ram to nand */
473 writel(ops, NFC_V3_LAUNCH);
474
475 wait_op_done(host, false);
476}
477
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200478static void send_page_v2(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
483 /* NANDFC buffer 0 is used for page read/write */
484 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
485
486 writew(ops, NFC_V1_V2_CONFIG2);
487
488 /* Wait for operation to complete */
489 wait_op_done(host, true);
490}
491
492static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200493{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200494 struct nand_chip *nand_chip = mtd->priv;
495 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200496 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200497
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200498 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200499 bufs = 4;
500 else
501 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200502
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200503 for (i = 0; i < bufs; i++) {
504
505 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200506 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200507
Sascha Hauer1bc99182010-08-06 15:53:08 +0200508 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200509
510 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200511 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200512 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200513}
514
Sascha Hauer71ec5152010-08-06 15:53:11 +0200515static void send_read_id_v3(struct mxc_nand_host *host)
516{
517 /* Read ID into main buffer */
518 writel(NFC_ID, NFC_V3_LAUNCH);
519
520 wait_op_done(host, true);
521
522 memcpy(host->data_buf, host->main_area0, 16);
523}
524
Sascha Hauer34f6e152008-09-02 17:16:59 +0200525/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200526static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200527{
528 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200529
530 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200531 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200532
Sascha Hauer1bc99182010-08-06 15:53:08 +0200533 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200534
535 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200536 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200537
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200538 memcpy(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200539
540 if (this->options & NAND_BUSWIDTH_16) {
541 /* compress the ID info */
542 host->data_buf[1] = host->data_buf[2];
543 host->data_buf[2] = host->data_buf[4];
544 host->data_buf[3] = host->data_buf[6];
545 host->data_buf[4] = host->data_buf[8];
546 host->data_buf[5] = host->data_buf[10];
547 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200548}
549
Sascha Hauer71ec5152010-08-06 15:53:11 +0200550static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200552 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200553 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200554
Sascha Hauer71ec5152010-08-06 15:53:11 +0200555 return readl(NFC_V3_CONFIG1) >> 16;
556}
557
Sascha Hauer34f6e152008-09-02 17:16:59 +0200558/* This function requests the NANDFC to perform a read of the
559 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200560static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200561{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200562 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200563 uint32_t store;
564 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200565
Baruch Siachd178e3e2011-03-14 09:01:56 +0200566 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200567
568 /*
569 * The device status is stored in main_area0. To
570 * prevent corruption of the buffer save the value
571 * and restore it afterwards.
572 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200573 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200574
Sascha Hauer1bc99182010-08-06 15:53:08 +0200575 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200576 wait_op_done(host, true);
577
Sascha Hauer34f6e152008-09-02 17:16:59 +0200578 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200579
Sascha Hauer34f6e152008-09-02 17:16:59 +0200580 writel(store, main_buf);
581
582 return ret;
583}
584
585/* This functions is used by upper layer to checks if device is ready */
586static int mxc_nand_dev_ready(struct mtd_info *mtd)
587{
588 /*
589 * NFC handles R/B internally. Therefore, this function
590 * always returns status as ready.
591 */
592 return 1;
593}
594
595static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
596{
597 /*
598 * If HW ECC is enabled, we turn it on during init. There is
599 * no need to enable again here.
600 */
601}
602
Sascha Hauer94f77e52010-08-06 15:53:09 +0200603static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200604 u_char *read_ecc, u_char *calc_ecc)
605{
606 struct nand_chip *nand_chip = mtd->priv;
607 struct mxc_nand_host *host = nand_chip->priv;
608
609 /*
610 * 1-Bit errors are automatically corrected in HW. No need for
611 * additional correction. 2-Bit errors cannot be corrected by
612 * HW ECC, so we need to return failure
613 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200614 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200615
616 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700617 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200618 return -1;
619 }
620
621 return 0;
622}
623
Sascha Hauer94f77e52010-08-06 15:53:09 +0200624static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
625 u_char *read_ecc, u_char *calc_ecc)
626{
627 struct nand_chip *nand_chip = mtd->priv;
628 struct mxc_nand_host *host = nand_chip->priv;
629 u32 ecc_stat, err;
630 int no_subpages = 1;
631 int ret = 0;
632 u8 ecc_bit_mask, err_limit;
633
634 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
635 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
636
637 no_subpages = mtd->writesize >> 9;
638
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200639 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200640
641 do {
642 err = ecc_stat & ecc_bit_mask;
643 if (err > err_limit) {
644 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
645 return -1;
646 } else {
647 ret += err;
648 }
649 ecc_stat >>= 4;
650 } while (--no_subpages);
651
652 mtd->ecc_stats.corrected += ret;
653 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
654
655 return ret;
656}
657
Sascha Hauer34f6e152008-09-02 17:16:59 +0200658static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
659 u_char *ecc_code)
660{
661 return 0;
662}
663
664static u_char mxc_nand_read_byte(struct mtd_info *mtd)
665{
666 struct nand_chip *nand_chip = mtd->priv;
667 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200668 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200669
670 /* Check for status request */
671 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200672 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200673
Sascha Hauerf8f96082009-06-04 17:12:26 +0200674 ret = *(uint8_t *)(host->data_buf + host->buf_start);
675 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200676
677 return ret;
678}
679
680static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
681{
682 struct nand_chip *nand_chip = mtd->priv;
683 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200684 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200685
Sascha Hauerf8f96082009-06-04 17:12:26 +0200686 ret = *(uint16_t *)(host->data_buf + host->buf_start);
687 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200688
689 return ret;
690}
691
692/* Write data of length len to buffer buf. The data to be
693 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
694 * Operation by the NFC, the data is written to NAND Flash */
695static void mxc_nand_write_buf(struct mtd_info *mtd,
696 const u_char *buf, int len)
697{
698 struct nand_chip *nand_chip = mtd->priv;
699 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200700 u16 col = host->buf_start;
701 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200702
Sascha Hauerf8f96082009-06-04 17:12:26 +0200703 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200704
Sascha Hauerf8f96082009-06-04 17:12:26 +0200705 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200706
Sascha Hauerf8f96082009-06-04 17:12:26 +0200707 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200708}
709
710/* Read the data buffer from the NAND Flash. To read the data from NAND
711 * Flash first the data output cycle is initiated by the NFC, which copies
712 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
713 */
714static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
715{
716 struct nand_chip *nand_chip = mtd->priv;
717 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200718 u16 col = host->buf_start;
719 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200720
Sascha Hauerf8f96082009-06-04 17:12:26 +0200721 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200722
Baruch Siach5d9d9932011-03-02 16:47:55 +0200723 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200724
Baruch Siach5d9d9932011-03-02 16:47:55 +0200725 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200726}
727
728/* Used by the upper layer to verify the data in NAND Flash
729 * with the data in the buf. */
730static int mxc_nand_verify_buf(struct mtd_info *mtd,
731 const u_char *buf, int len)
732{
733 return -EFAULT;
734}
735
736/* This function is used by upper layer for select and
737 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200738static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
739{
740 struct nand_chip *nand_chip = mtd->priv;
741 struct mxc_nand_host *host = nand_chip->priv;
742
743 if (chip == -1) {
744 /* Disable the NFC clock */
745 if (host->clk_act) {
746 clk_disable(host->clk);
747 host->clk_act = 0;
748 }
749 return;
750 }
751
752 if (!host->clk_act) {
753 /* Enable the NFC clock */
754 clk_enable(host->clk);
755 host->clk_act = 1;
756 }
757}
758
759static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200760{
761 struct nand_chip *nand_chip = mtd->priv;
762 struct mxc_nand_host *host = nand_chip->priv;
763
Baruch Siachd178e3e2011-03-14 09:01:56 +0200764 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200765 /* Disable the NFC clock */
766 if (host->clk_act) {
767 clk_disable(host->clk);
768 host->clk_act = 0;
769 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200770 return;
771 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200772
Baruch Siachd178e3e2011-03-14 09:01:56 +0200773 if (!host->clk_act) {
774 /* Enable the NFC clock */
775 clk_enable(host->clk);
776 host->clk_act = 1;
777 }
778
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +0200779 host->active_cs = chip;
780 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200781}
782
Sascha Hauerf8f96082009-06-04 17:12:26 +0200783/*
784 * Function to transfer data to/from spare area.
785 */
786static void copy_spare(struct mtd_info *mtd, bool bfrom)
787{
788 struct nand_chip *this = mtd->priv;
789 struct mxc_nand_host *host = this->priv;
790 u16 i, j;
791 u16 n = mtd->writesize >> 9;
792 u8 *d = host->data_buf + mtd->writesize;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200793 u8 *s = host->spare0;
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200794 u16 t = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200795
796 j = (mtd->oobsize / n >> 1) << 1;
797
798 if (bfrom) {
799 for (i = 0; i < n - 1; i++)
800 memcpy(d + i * j, s + i * t, j);
801
802 /* the last section */
803 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
804 } else {
805 for (i = 0; i < n - 1; i++)
806 memcpy(&s[i * t], &d[i * j], j);
807
808 /* the last section */
809 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
810 }
811}
812
Sascha Hauera3e65b62009-06-02 11:47:59 +0200813static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200814{
815 struct nand_chip *nand_chip = mtd->priv;
816 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200817
818 /* Write out column address, if necessary */
819 if (column != -1) {
820 /*
821 * MXC NANDFC can only perform full page+spare or
822 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100823 * perform a read/write buf operation, the saved column
824 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200825 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200826 host->devtype_data->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200827 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200828 /* another col addr cycle for 2k page */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200829 host->devtype_data->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200830 }
831
832 /* Write out page address, if necessary */
833 if (page_addr != -1) {
834 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200835 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200836
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200837 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400838 if (mtd->size >= 0x10000000) {
839 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200840 host->devtype_data->send_addr(host,
841 (page_addr >> 8) & 0xff,
842 false);
843 host->devtype_data->send_addr(host,
844 (page_addr >> 16) & 0xff,
845 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400846 } else
847 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200848 host->devtype_data->send_addr(host,
849 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200850 } else {
851 /* One more address cycle for higher density devices */
852 if (mtd->size >= 0x4000000) {
853 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200854 host->devtype_data->send_addr(host,
855 (page_addr >> 8) & 0xff,
856 false);
857 host->devtype_data->send_addr(host,
858 (page_addr >> 16) & 0xff,
859 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200860 } else
861 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200862 host->devtype_data->send_addr(host,
863 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200864 }
865 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200866}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200867
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200868/*
869 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
870 * on how much oob the nand chip has. For 8bit ecc we need at least
871 * 26 bytes of oob data per 512 byte block.
872 */
873static int get_eccsize(struct mtd_info *mtd)
874{
875 int oobbytes_per_512 = 0;
876
877 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
878
879 if (oobbytes_per_512 < 26)
880 return 4;
881 else
882 return 8;
883}
884
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200885static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200886{
887 struct nand_chip *nand_chip = mtd->priv;
888 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200889 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200890
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200891 if (nand_chip->ecc.mode == NAND_ECC_HW)
892 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
893
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200894 if (!host->devtype_data->irqpending_quirk)
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200895 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
896
897 host->eccsize = 1;
898
899 writew(config1, NFC_V1_V2_CONFIG1);
900 /* preset operation */
901
902 /* Unlock the internal RAM Buffer */
903 writew(0x2, NFC_V1_V2_CONFIG);
904
905 /* Blocks to be unlocked */
906 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
907 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
908
909 /* Unlock Block Command for given address range */
910 writew(0x4, NFC_V1_V2_WRPROT);
911}
912
913static void preset_v2(struct mtd_info *mtd)
914{
915 struct nand_chip *nand_chip = mtd->priv;
916 struct mxc_nand_host *host = nand_chip->priv;
917 uint16_t config1 = 0;
918
919 if (nand_chip->ecc.mode == NAND_ECC_HW)
920 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
921
922 config1 |= NFC_V2_CONFIG1_FP_INT;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200923
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200924 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200925 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200926
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200927 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200928 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
929
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200930 host->eccsize = get_eccsize(mtd);
931 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200932 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
933
934 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200935 } else {
936 host->eccsize = 1;
937 }
938
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200939 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200940 /* preset operation */
941
942 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200943 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200944
945 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200946 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
947 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
948 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
949 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
950 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
951 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
952 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
953 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200954
955 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200956 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200957}
958
Sascha Hauer71ec5152010-08-06 15:53:11 +0200959static void preset_v3(struct mtd_info *mtd)
960{
961 struct nand_chip *chip = mtd->priv;
962 struct mxc_nand_host *host = chip->priv;
963 uint32_t config2, config3;
964 int i, addr_phases;
965
966 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
967 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
968
969 /* Unlock the internal RAM Buffer */
970 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
971 NFC_V3_WRPROT);
972
973 /* Blocks to be unlocked */
974 for (i = 0; i < NAND_MAX_CHIPS; i++)
975 writel(0x0 | (0xffff << 16),
976 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
977
978 writel(0, NFC_V3_IPC);
979
980 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
981 NFC_V3_CONFIG2_2CMD_PHASES |
982 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
983 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +0200984 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +0200985 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
986
987 if (chip->ecc.mode == NAND_ECC_HW)
988 config2 |= NFC_V3_CONFIG2_ECC_EN;
989
990 addr_phases = fls(chip->pagemask) >> 3;
991
992 if (mtd->writesize == 2048) {
993 config2 |= NFC_V3_CONFIG2_PS_2048;
994 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
995 } else if (mtd->writesize == 4096) {
996 config2 |= NFC_V3_CONFIG2_PS_4096;
997 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
998 } else {
999 config2 |= NFC_V3_CONFIG2_PS_512;
1000 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1001 }
1002
1003 if (mtd->writesize) {
1004 config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
1005 host->eccsize = get_eccsize(mtd);
1006 if (host->eccsize == 8)
1007 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
1008 }
1009
1010 writel(config2, NFC_V3_CONFIG2);
1011
1012 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1013 NFC_V3_CONFIG3_NO_SDMA |
1014 NFC_V3_CONFIG3_RBB_MODE |
1015 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1016 NFC_V3_CONFIG3_ADD_OP(0);
1017
1018 if (!(chip->options & NAND_BUSWIDTH_16))
1019 config3 |= NFC_V3_CONFIG3_FW8;
1020
1021 writel(config3, NFC_V3_CONFIG3);
1022
1023 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001024}
1025
Sascha Hauer34f6e152008-09-02 17:16:59 +02001026/* Used by the upper layer to write command to NAND Flash for
1027 * different operations to be carried out on NAND Flash */
1028static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1029 int column, int page_addr)
1030{
1031 struct nand_chip *nand_chip = mtd->priv;
1032 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001033
Brian Norris289c0522011-07-19 10:06:09 -07001034 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001035 command, column, page_addr);
1036
1037 /* Reset command state information */
1038 host->status_request = false;
1039
1040 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001041 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001042 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001043 host->devtype_data->preset(mtd);
1044 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001045 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001046
Sascha Hauer34f6e152008-09-02 17:16:59 +02001047 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001048 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001049 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001050
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001051 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001052 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001053 break;
1054
Sascha Hauer34f6e152008-09-02 17:16:59 +02001055 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001056 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001057 if (command == NAND_CMD_READ0)
1058 host->buf_start = column;
1059 else
1060 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001061
Sascha Hauer5ea32022010-04-27 15:24:01 +02001062 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001063
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001064 host->devtype_data->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001065 mxc_do_addr_cycle(mtd, column, page_addr);
1066
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001067 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001068 host->devtype_data->send_cmd(host,
1069 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001070
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001071 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001072
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001073 memcpy(host->data_buf, host->main_area0, mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001074 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001075 break;
1076
Sascha Hauer34f6e152008-09-02 17:16:59 +02001077 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001078 if (column >= mtd->writesize)
1079 /* call ourself to read a page */
1080 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001081
Sascha Hauer5ea32022010-04-27 15:24:01 +02001082 host->buf_start = column;
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);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001086 break;
1087
1088 case NAND_CMD_PAGEPROG:
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001089 memcpy(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001090 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001091 host->devtype_data->send_page(mtd, NFC_INPUT);
1092 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001093 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001094 break;
1095
Sascha Hauer34f6e152008-09-02 17:16:59 +02001096 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001097 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001098 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001099 host->devtype_data->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001100 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001101 break;
1102
Sascha Hauer89121a62009-06-04 17:18:01 +02001103 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001104 case NAND_CMD_ERASE2:
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);
1107
Sascha Hauer34f6e152008-09-02 17:16:59 +02001108 break;
1109 }
1110}
1111
Sascha Hauerf1372052009-10-21 14:25:27 +02001112/*
1113 * The generic flash bbt decriptors overlap with our ecc
1114 * hardware, so define some i.MX specific ones.
1115 */
1116static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1117static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1118
1119static struct nand_bbt_descr bbt_main_descr = {
1120 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1121 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1122 .offs = 0,
1123 .len = 4,
1124 .veroffs = 4,
1125 .maxblocks = 4,
1126 .pattern = bbt_pattern,
1127};
1128
1129static struct nand_bbt_descr bbt_mirror_descr = {
1130 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1131 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1132 .offs = 0,
1133 .len = 4,
1134 .veroffs = 4,
1135 .maxblocks = 4,
1136 .pattern = mirror_pattern,
1137};
1138
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001139/* v1 + irqpending_quirk: i.MX21 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001140static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001141 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001142 .send_cmd = send_cmd_v1_v2,
1143 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001144 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001145 .send_read_id = send_read_id_v1_v2,
1146 .get_dev_status = get_dev_status_v1_v2,
1147 .check_int = check_int_v1_v2,
1148 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001149 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001150 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1151 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1152 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001153 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001154 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001155 .irqpending_quirk = 1,
1156 .needs_ip = 0,
1157 .regs_offset = 0xe00,
1158 .spare0_offset = 0x800,
1159 .spare_len = 16,
1160 .eccbytes = 3,
1161 .eccsize = 1,
1162};
1163
1164/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1165static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1166 .preset = preset_v1,
1167 .send_cmd = send_cmd_v1_v2,
1168 .send_addr = send_addr_v1_v2,
1169 .send_page = send_page_v1,
1170 .send_read_id = send_read_id_v1_v2,
1171 .get_dev_status = get_dev_status_v1_v2,
1172 .check_int = check_int_v1_v2,
1173 .irq_control = irq_control_v1_v2,
1174 .get_ecc_status = get_ecc_status_v1,
1175 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1176 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1177 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1178 .select_chip = mxc_nand_select_chip_v1_v3,
1179 .correct_data = mxc_nand_correct_data_v1,
1180 .irqpending_quirk = 0,
1181 .needs_ip = 0,
1182 .regs_offset = 0xe00,
1183 .spare0_offset = 0x800,
1184 .axi_offset = 0,
1185 .spare_len = 16,
1186 .eccbytes = 3,
1187 .eccsize = 1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001188};
1189
1190/* v21: i.MX25, i.MX35 */
1191static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001192 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001193 .send_cmd = send_cmd_v1_v2,
1194 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001195 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001196 .send_read_id = send_read_id_v1_v2,
1197 .get_dev_status = get_dev_status_v1_v2,
1198 .check_int = check_int_v1_v2,
1199 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001200 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001201 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1202 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1203 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001204 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001205 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001206 .irqpending_quirk = 0,
1207 .needs_ip = 0,
1208 .regs_offset = 0x1e00,
1209 .spare0_offset = 0x1000,
1210 .axi_offset = 0,
1211 .spare_len = 64,
1212 .eccbytes = 9,
1213 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001214};
1215
1216/* v3: i.MX51, i.MX53 */
1217static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1218 .preset = preset_v3,
1219 .send_cmd = send_cmd_v3,
1220 .send_addr = send_addr_v3,
1221 .send_page = send_page_v3,
1222 .send_read_id = send_read_id_v3,
1223 .get_dev_status = get_dev_status_v3,
1224 .check_int = check_int_v3,
1225 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001226 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001227 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1228 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1229 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d62012-04-23 11:23:38 +02001230 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001231 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001232 .irqpending_quirk = 0,
1233 .needs_ip = 1,
1234 .regs_offset = 0,
1235 .spare0_offset = 0x1000,
1236 .axi_offset = 0x1e00,
1237 .spare_len = 64,
1238 .eccbytes = 0,
1239 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001240};
1241
Uwe Kleine-König64363562012-04-23 11:23:41 +02001242#ifdef CONFIG_OF_MTD
1243static const struct of_device_id mxcnd_dt_ids[] = {
1244 {
1245 .compatible = "fsl,imx21-nand",
1246 .data = &imx21_nand_devtype_data,
1247 }, {
1248 .compatible = "fsl,imx27-nand",
1249 .data = &imx27_nand_devtype_data,
1250 }, {
1251 .compatible = "fsl,imx25-nand",
1252 .data = &imx25_nand_devtype_data,
1253 }, {
1254 .compatible = "fsl,imx51-nand",
1255 .data = &imx51_nand_devtype_data,
1256 },
1257 { /* sentinel */ }
1258};
1259
1260static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1261{
1262 struct device_node *np = host->dev->of_node;
1263 struct mxc_nand_platform_data *pdata = &host->pdata;
1264 const struct of_device_id *of_id =
1265 of_match_device(mxcnd_dt_ids, host->dev);
1266 int buswidth;
1267
1268 if (!np)
1269 return 1;
1270
1271 if (of_get_nand_ecc_mode(np) >= 0)
1272 pdata->hw_ecc = 1;
1273
1274 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1275
1276 buswidth = of_get_nand_bus_width(np);
1277 if (buswidth < 0)
1278 return buswidth;
1279
1280 pdata->width = buswidth / 8;
1281
1282 host->devtype_data = of_id->data;
1283
1284 return 0;
1285}
1286#else
1287static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1288{
1289 return 1;
1290}
1291#endif
1292
1293static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
1294{
1295 struct mxc_nand_platform_data *pdata = host->dev->platform_data;
1296
1297 if (!pdata)
1298 return -ENODEV;
1299
1300 host->pdata = *pdata;
1301
1302 if (nfc_is_v1()) {
1303 if (cpu_is_mx21())
1304 host->devtype_data = &imx21_nand_devtype_data;
1305 else
1306 host->devtype_data = &imx27_nand_devtype_data;
1307 } else if (nfc_is_v21()) {
1308 host->devtype_data = &imx25_nand_devtype_data;
1309 } else if (nfc_is_v3_2()) {
1310 host->devtype_data = &imx51_nand_devtype_data;
1311 } else
1312 BUG();
1313
1314 return 0;
1315}
1316
Sascha Hauer34f6e152008-09-02 17:16:59 +02001317static int __init mxcnd_probe(struct platform_device *pdev)
1318{
1319 struct nand_chip *this;
1320 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001321 struct mxc_nand_host *host;
1322 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001323 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001324
1325 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +02001326 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
1327 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001328 if (!host)
1329 return -ENOMEM;
1330
Sascha Hauerf8f96082009-06-04 17:12:26 +02001331 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001332
Sascha Hauer34f6e152008-09-02 17:16:59 +02001333 host->dev = &pdev->dev;
1334 /* structures must be linked */
1335 this = &host->nand;
1336 mtd = &host->mtd;
1337 mtd->priv = this;
1338 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001339 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001340 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001341
1342 /* 50 us command delay time */
1343 this->chip_delay = 5;
1344
1345 this->priv = host;
1346 this->dev_ready = mxc_nand_dev_ready;
1347 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001348 this->read_byte = mxc_nand_read_byte;
1349 this->read_word = mxc_nand_read_word;
1350 this->write_buf = mxc_nand_write_buf;
1351 this->read_buf = mxc_nand_read_buf;
1352 this->verify_buf = mxc_nand_verify_buf;
1353
Sascha Hauere65fb002009-02-16 14:29:10 +01001354 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +04001355 if (IS_ERR(host->clk)) {
1356 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001357 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +04001358 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001359
1360 clk_enable(host->clk);
1361 host->clk_act = 1;
1362
1363 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1364 if (!res) {
1365 err = -ENODEV;
1366 goto eres;
1367 }
1368
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001369 host->base = ioremap(res->start, resource_size(res));
1370 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +04001371 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001372 goto eres;
1373 }
1374
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001375 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001376
Uwe Kleine-König64363562012-04-23 11:23:41 +02001377 err = mxcnd_probe_dt(host);
1378 if (err > 0)
1379 err = mxcnd_probe_pdata(host);
1380 if (err < 0)
1381 goto eirq;
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001382
1383 if (host->devtype_data->regs_offset)
1384 host->regs = host->base + host->devtype_data->regs_offset;
1385 host->spare0 = host->base + host->devtype_data->spare0_offset;
1386 if (host->devtype_data->axi_offset)
1387 host->regs_axi = host->base + host->devtype_data->axi_offset;
1388
1389 this->ecc.bytes = host->devtype_data->eccbytes;
1390 host->eccsize = host->devtype_data->eccsize;
1391
1392 this->select_chip = host->devtype_data->select_chip;
1393 this->ecc.size = 512;
1394 this->ecc.layout = host->devtype_data->ecclayout_512;
1395
1396 if (host->devtype_data->needs_ip) {
Sascha Hauer71ec5152010-08-06 15:53:11 +02001397 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1398 if (!res) {
1399 err = -ENODEV;
1400 goto eirq;
1401 }
1402 host->regs_ip = ioremap(res->start, resource_size(res));
1403 if (!host->regs_ip) {
1404 err = -ENOMEM;
1405 goto eirq;
1406 }
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001407 }
Sascha Hauer13e1add2009-10-21 10:39:05 +02001408
Uwe Kleine-König64363562012-04-23 11:23:41 +02001409 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001410 this->ecc.calculate = mxc_nand_calculate_ecc;
1411 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001412 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001413 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001414 } else {
1415 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001416 }
1417
Uwe Kleine-König64363562012-04-23 11:23:41 +02001418 /* NAND bus width determines access functions used by upper layer */
1419 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001420 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001421
Uwe Kleine-König64363562012-04-23 11:23:41 +02001422 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001423 this->bbt_td = &bbt_main_descr;
1424 this->bbt_md = &bbt_mirror_descr;
1425 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001426 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001427 }
1428
Sascha Hauer63f14742010-10-18 10:16:26 +02001429 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001430
1431 host->irq = platform_get_irq(pdev, 0);
1432
Sascha Hauer63f14742010-10-18 10:16:26 +02001433 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001434 * Use host->devtype_data->irq_control() here instead of irq_control()
1435 * because we must not disable_irq_nosync without having requested the
1436 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001437 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001438 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001439
Ivo Claryssea47bfd22010-04-08 16:16:51 +02001440 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001441 if (err)
1442 goto eirq;
1443
Sascha Hauer63f14742010-10-18 10:16:26 +02001444 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001445 * Now that we "own" the interrupt make sure the interrupt mask bit is
1446 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1447 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001448 */
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001449 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +02001450 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001451 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001452 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001453
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001454 /* first scan to find the device and get the page size */
Baruch Siachd178e3e2011-03-14 09:01:56 +02001455 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001456 err = -ENXIO;
1457 goto escan;
1458 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001459
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001460 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001461 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001462
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001463 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001464 this->ecc.layout = host->devtype_data->ecclayout_2k;
1465 else if (mtd->writesize == 4096)
1466 this->ecc.layout = host->devtype_data->ecclayout_4k;
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001467
1468 /* second phase scan */
1469 if (nand_scan_tail(mtd)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +02001470 err = -ENXIO;
1471 goto escan;
1472 }
1473
Mike Dunn6a918ba2012-03-11 14:21:11 -07001474 if (this->ecc.mode == NAND_ECC_HW) {
1475 if (nfc_is_v1())
1476 this->ecc.strength = 1;
1477 else
1478 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1479 }
1480
Sascha Hauer34f6e152008-09-02 17:16:59 +02001481 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001482 mtd_device_parse_register(mtd, part_probes,
1483 &(struct mtd_part_parser_data){
1484 .of_node = pdev->dev.of_node,
1485 },
1486 host->pdata.parts,
1487 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001488
1489 platform_set_drvdata(pdev, host);
1490
1491 return 0;
1492
1493escan:
Magnus Liljab258fd82009-05-08 21:57:47 +02001494 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001495eirq:
Sascha Hauer71ec5152010-08-06 15:53:11 +02001496 if (host->regs_ip)
1497 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001498 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001499eres:
1500 clk_put(host->clk);
1501eclk:
1502 kfree(host);
1503
1504 return err;
1505}
1506
Uwe Kleine-König51eeb872009-12-07 09:44:05 +00001507static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001508{
1509 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1510
1511 clk_put(host->clk);
1512
1513 platform_set_drvdata(pdev, NULL);
1514
1515 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +02001516 free_irq(host->irq, host);
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 +02001520 kfree(host);
1521
1522 return 0;
1523}
1524
Sascha Hauer34f6e152008-09-02 17:16:59 +02001525static struct platform_driver mxcnd_driver = {
1526 .driver = {
1527 .name = DRIVER_NAME,
Uwe Kleine-König8d1fd162012-04-23 11:23:33 +02001528 .owner = THIS_MODULE,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001529 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001530 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +01001531 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +02001532};
1533
1534static int __init mxc_nd_init(void)
1535{
Vladimir Barinov8541c112009-04-23 15:47:22 +04001536 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001537}
1538
1539static void __exit mxc_nd_cleanup(void)
1540{
1541 /* Unregister the device structure */
1542 platform_driver_unregister(&mxcnd_driver);
1543}
1544
1545module_init(mxc_nd_init);
1546module_exit(mxc_nd_cleanup);
1547
1548MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1549MODULE_DESCRIPTION("MXC NAND MTD driver");
1550MODULE_LICENSE("GPL");