blob: 5bbc1c5062bc6bc7bf9cdee3307ae8301d150e77 [file] [log] [blame]
Sascha Hauer34f6e152008-09-02 17:16:59 +02001/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#include <linux/delay.h>
21#include <linux/slab.h>
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/mtd/mtd.h>
25#include <linux/mtd/nand.h>
26#include <linux/mtd/partitions.h>
27#include <linux/interrupt.h>
28#include <linux/device.h>
29#include <linux/platform_device.h>
30#include <linux/clk.h>
31#include <linux/err.h>
32#include <linux/io.h>
Sascha Hauer63f14742010-10-18 10:16:26 +020033#include <linux/irq.h>
34#include <linux/completion.h>
Sachin Kamatd367e372013-10-18 16:16:35 +053035#include <linux/of.h>
Uwe Kleine-König64363562012-04-23 11:23:41 +020036#include <linux/of_device.h>
37#include <linux/of_mtd.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020038
39#include <asm/mach/flash.h>
Arnd Bergmann82906b12012-08-24 15:14:29 +020040#include <linux/platform_data/mtd-mxc_nand.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020041
42#define DRIVER_NAME "mxc_nand"
43
44/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020045#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
46#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
47#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
48#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
49#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
50#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
51#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
52#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
53#define NFC_V1_V2_WRPROT (host->regs + 0x12)
54#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
55#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
Baruch Siachd178e3e2011-03-14 09:01:56 +020056#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
57#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
58#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
59#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
60#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
61#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
62#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
63#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
Sascha Hauer1bc99182010-08-06 15:53:08 +020064#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
65#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
66#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020067
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020068#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020069#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
70#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
71#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
72#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
73#define NFC_V1_V2_CONFIG1_RST (1 << 6)
74#define NFC_V1_V2_CONFIG1_CE (1 << 7)
Sascha Hauerb8db2f52010-08-09 15:04:19 +020075#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
76#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
77#define NFC_V2_CONFIG1_FP_INT (1 << 11)
Sascha Hauer34f6e152008-09-02 17:16:59 +020078
Sascha Hauer1bc99182010-08-06 15:53:08 +020079#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020080
Sascha Hauer1bc99182010-08-06 15:53:08 +020081/*
82 * Operation modes for the NFC. Valid for v1, v2 and v3
83 * type controllers.
84 */
85#define NFC_CMD (1 << 0)
86#define NFC_ADDR (1 << 1)
87#define NFC_INPUT (1 << 2)
88#define NFC_OUTPUT (1 << 3)
89#define NFC_ID (1 << 4)
90#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020091
Sascha Hauer71ec5152010-08-06 15:53:11 +020092#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
93#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
Sascha Hauer34f6e152008-09-02 17:16:59 +020094
Sascha Hauer71ec5152010-08-06 15:53:11 +020095#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
96#define NFC_V3_CONFIG1_SP_EN (1 << 0)
97#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
Sascha Hauer34f6e152008-09-02 17:16:59 +020098
Sascha Hauer71ec5152010-08-06 15:53:11 +020099#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200100
Sascha Hauer71ec5152010-08-06 15:53:11 +0200101#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200102
Sascha Hauer71ec5152010-08-06 15:53:11 +0200103#define NFC_V3_WRPROT (host->regs_ip + 0x0)
104#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
105#define NFC_V3_WRPROT_LOCK (1 << 1)
106#define NFC_V3_WRPROT_UNLOCK (1 << 2)
107#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
108
109#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
110
111#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
112#define NFC_V3_CONFIG2_PS_512 (0 << 0)
113#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
114#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
115#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
116#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
117#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
118#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
119#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200120#define NFC_V3_CONFIG2_PPB(x, shift) (((x) & 0x3) << shift)
Sascha Hauer71ec5152010-08-06 15:53:11 +0200121#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
122#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
123#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
124#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
125
126#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
127#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
128#define NFC_V3_CONFIG3_FW8 (1 << 3)
129#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
130#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
131#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
132#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
133
134#define NFC_V3_IPC (host->regs_ip + 0x2C)
135#define NFC_V3_IPC_CREQ (1 << 0)
136#define NFC_V3_IPC_INT (1 << 31)
137
138#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200139
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200140struct mxc_nand_host;
141
142struct mxc_nand_devtype_data {
143 void (*preset)(struct mtd_info *);
144 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
145 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
146 void (*send_page)(struct mtd_info *, unsigned int);
147 void (*send_read_id)(struct mxc_nand_host *);
148 uint16_t (*get_dev_status)(struct mxc_nand_host *);
149 int (*check_int)(struct mxc_nand_host *);
150 void (*irq_control)(struct mxc_nand_host *, int);
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200151 u32 (*get_ecc_status)(struct mxc_nand_host *);
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +0200152 struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k;
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200153 void (*select_chip)(struct mtd_info *mtd, int chip);
Uwe Kleine-König69d023b2012-04-23 11:23:39 +0200154 int (*correct_data)(struct mtd_info *mtd, u_char *dat,
155 u_char *read_ecc, u_char *calc_ecc);
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200156
157 /*
158 * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked
159 * (CONFIG1:INT_MSK is set). To handle this the driver uses
160 * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK
161 */
162 int irqpending_quirk;
163 int needs_ip;
164
165 size_t regs_offset;
166 size_t spare0_offset;
167 size_t axi_offset;
168
169 int spare_len;
170 int eccbytes;
171 int eccsize;
Sascha Hauer71718a8e2012-06-06 12:33:15 +0200172 int ppb_shift;
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200173};
174
Sascha Hauer34f6e152008-09-02 17:16:59 +0200175struct mxc_nand_host {
176 struct mtd_info mtd;
177 struct nand_chip nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200178 struct device *dev;
179
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200180 void __iomem *spare0;
181 void __iomem *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200182
183 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200184 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200185 void __iomem *regs_axi;
186 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200187 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200188 struct clk *clk;
189 int clk_act;
190 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200191 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200192 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200193
Sascha Hauer63f14742010-10-18 10:16:26 +0200194 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200195
196 uint8_t *data_buf;
197 unsigned int buf_start;
Sascha Hauer5f973042010-08-06 15:53:06 +0200198
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200199 const struct mxc_nand_devtype_data *devtype_data;
Uwe Kleine-König64363562012-04-23 11:23:41 +0200200 struct mxc_nand_platform_data pdata;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200201};
202
Sascha Hauer34f6e152008-09-02 17:16:59 +0200203/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200204static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200205 .eccbytes = 5,
206 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200207 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200208};
209
Sascha Hauer94671142009-10-05 12:14:21 +0200210static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400211 .eccbytes = 20,
212 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
213 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
214 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200215};
216
Sascha Hauer94671142009-10-05 12:14:21 +0200217/* OOB description for 512 byte pages with 16 byte OOB */
218static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
219 .eccbytes = 1 * 9,
220 .eccpos = {
221 7, 8, 9, 10, 11, 12, 13, 14, 15
222 },
223 .oobfree = {
224 {.offset = 0, .length = 5}
225 }
226};
227
228/* OOB description for 2048 byte pages with 64 byte OOB */
229static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
230 .eccbytes = 4 * 9,
231 .eccpos = {
232 7, 8, 9, 10, 11, 12, 13, 14, 15,
233 23, 24, 25, 26, 27, 28, 29, 30, 31,
234 39, 40, 41, 42, 43, 44, 45, 46, 47,
235 55, 56, 57, 58, 59, 60, 61, 62, 63
236 },
237 .oobfree = {
238 {.offset = 2, .length = 4},
239 {.offset = 16, .length = 7},
240 {.offset = 32, .length = 7},
241 {.offset = 48, .length = 7}
242 }
243};
244
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200245/* OOB description for 4096 byte pages with 128 byte OOB */
246static struct nand_ecclayout nandv2_hw_eccoob_4k = {
247 .eccbytes = 8 * 9,
248 .eccpos = {
249 7, 8, 9, 10, 11, 12, 13, 14, 15,
250 23, 24, 25, 26, 27, 28, 29, 30, 31,
251 39, 40, 41, 42, 43, 44, 45, 46, 47,
252 55, 56, 57, 58, 59, 60, 61, 62, 63,
253 71, 72, 73, 74, 75, 76, 77, 78, 79,
254 87, 88, 89, 90, 91, 92, 93, 94, 95,
255 103, 104, 105, 106, 107, 108, 109, 110, 111,
256 119, 120, 121, 122, 123, 124, 125, 126, 127,
257 },
258 .oobfree = {
259 {.offset = 2, .length = 4},
260 {.offset = 16, .length = 7},
261 {.offset = 32, .length = 7},
262 {.offset = 48, .length = 7},
263 {.offset = 64, .length = 7},
264 {.offset = 80, .length = 7},
265 {.offset = 96, .length = 7},
266 {.offset = 112, .length = 7},
267 }
268};
269
Jingoo Hanb2ac0372013-08-07 16:18:52 +0900270static const char * const part_probes[] = {
Lothar Waßmann740bb0c2012-12-06 08:42:28 +0100271 "cmdlinepart", "RedBoot", "ofpart", NULL };
Sascha Hauer34f6e152008-09-02 17:16:59 +0200272
Sascha Hauer096bcc22012-05-29 10:16:09 +0200273static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size)
274{
275 int i;
276 u32 *t = trg;
277 const __iomem u32 *s = src;
278
279 for (i = 0; i < (size >> 2); i++)
280 *t++ = __raw_readl(s++);
281}
282
Koul, Vinod33a87a12014-10-20 21:36:13 +0530283static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
Sascha Hauer096bcc22012-05-29 10:16:09 +0200284{
Koul, Vinod33a87a12014-10-20 21:36:13 +0530285 /* __iowrite32_copy use 32bit size values so divide by 4 */
286 __iowrite32_copy(trg, src, size / 4);
Sascha Hauer096bcc22012-05-29 10:16:09 +0200287}
288
Sascha Hauer71ec5152010-08-06 15:53:11 +0200289static int check_int_v3(struct mxc_nand_host *host)
290{
291 uint32_t tmp;
292
293 tmp = readl(NFC_V3_IPC);
294 if (!(tmp & NFC_V3_IPC_INT))
295 return 0;
296
297 tmp &= ~NFC_V3_IPC_INT;
298 writel(tmp, NFC_V3_IPC);
299
300 return 1;
301}
302
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200303static int check_int_v1_v2(struct mxc_nand_host *host)
304{
305 uint32_t tmp;
306
Sascha Hauer1bc99182010-08-06 15:53:08 +0200307 tmp = readw(NFC_V1_V2_CONFIG2);
308 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200309 return 0;
310
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200311 if (!host->devtype_data->irqpending_quirk)
Sascha Hauer63f14742010-10-18 10:16:26 +0200312 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200313
314 return 1;
315}
316
Sascha Hauer63f14742010-10-18 10:16:26 +0200317static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
318{
319 uint16_t tmp;
320
321 tmp = readw(NFC_V1_V2_CONFIG1);
322
323 if (activate)
324 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
325 else
326 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
327
328 writew(tmp, NFC_V1_V2_CONFIG1);
329}
330
331static void irq_control_v3(struct mxc_nand_host *host, int activate)
332{
333 uint32_t tmp;
334
335 tmp = readl(NFC_V3_CONFIG2);
336
337 if (activate)
338 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
339 else
340 tmp |= NFC_V3_CONFIG2_INT_MSK;
341
342 writel(tmp, NFC_V3_CONFIG2);
343}
344
Uwe Kleine-König85569582012-04-23 11:23:34 +0200345static void irq_control(struct mxc_nand_host *host, int activate)
346{
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200347 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +0200348 if (activate)
349 enable_irq(host->irq);
350 else
351 disable_irq_nosync(host->irq);
352 } else {
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200353 host->devtype_data->irq_control(host, activate);
Uwe Kleine-König85569582012-04-23 11:23:34 +0200354 }
355}
356
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200357static u32 get_ecc_status_v1(struct mxc_nand_host *host)
358{
359 return readw(NFC_V1_V2_ECC_STATUS_RESULT);
360}
361
362static u32 get_ecc_status_v2(struct mxc_nand_host *host)
363{
364 return readl(NFC_V1_V2_ECC_STATUS_RESULT);
365}
366
367static u32 get_ecc_status_v3(struct mxc_nand_host *host)
368{
369 return readl(NFC_V3_ECC_STATUS_RESULT);
370}
371
Uwe Kleine-König85569582012-04-23 11:23:34 +0200372static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
373{
374 struct mxc_nand_host *host = dev_id;
375
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200376 if (!host->devtype_data->check_int(host))
Uwe Kleine-König85569582012-04-23 11:23:34 +0200377 return IRQ_NONE;
378
379 irq_control(host, 0);
380
381 complete(&host->op_completion);
382
383 return IRQ_HANDLED;
384}
385
Sascha Hauer34f6e152008-09-02 17:16:59 +0200386/* This function polls the NANDFC to wait for the basic operation to
387 * complete by checking the INT bit of config2 register.
388 */
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100389static int wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200390{
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100391 int ret = 0;
392
393 /*
394 * If operation is already complete, don't bother to setup an irq or a
395 * loop.
396 */
397 if (host->devtype_data->check_int(host))
398 return 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200399
400 if (useirq) {
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100401 unsigned long timeout;
402
403 reinit_completion(&host->op_completion);
404
405 irq_control(host, 1);
406
407 timeout = wait_for_completion_timeout(&host->op_completion, HZ);
408 if (!timeout && !host->devtype_data->check_int(host)) {
409 dev_dbg(host->dev, "timeout waiting for irq\n");
410 ret = -ETIMEDOUT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200411 }
412 } else {
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100413 int max_retries = 8000;
414 int done;
415
416 do {
417 udelay(1);
418
419 done = host->devtype_data->check_int(host);
420 if (done)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200421 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200422
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100423 } while (--max_retries);
424
425 if (!done) {
426 dev_dbg(host->dev, "timeout polling for completion\n");
427 ret = -ETIMEDOUT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200428 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200429 }
Uwe Kleine-Könige35d1d82015-02-10 19:59:55 +0100430
431 WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq);
432
433 return ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200434}
435
Sascha Hauer71ec5152010-08-06 15:53:11 +0200436static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
437{
438 /* fill command */
439 writel(cmd, NFC_V3_FLASH_CMD);
440
441 /* send out command */
442 writel(NFC_CMD, NFC_V3_LAUNCH);
443
444 /* Wait for operation to complete */
445 wait_op_done(host, useirq);
446}
447
Sascha Hauer34f6e152008-09-02 17:16:59 +0200448/* This function issues the specified command to the NAND device and
449 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200450static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200451{
Brian Norris289c0522011-07-19 10:06:09 -0700452 pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200453
Sascha Hauer1bc99182010-08-06 15:53:08 +0200454 writew(cmd, NFC_V1_V2_FLASH_CMD);
455 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200456
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200457 if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200458 int max_retries = 100;
459 /* Reset completion is indicated by NFC_CONFIG2 */
460 /* being set to 0 */
461 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200462 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200463 break;
464 }
465 udelay(1);
466 }
467 if (max_retries < 0)
Brian Norris0a32a102011-07-19 10:06:10 -0700468 pr_debug("%s: RESET failed\n", __func__);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200469 } else {
470 /* Wait for operation to complete */
471 wait_op_done(host, useirq);
472 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200473}
474
Sascha Hauer71ec5152010-08-06 15:53:11 +0200475static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
476{
477 /* fill address */
478 writel(addr, NFC_V3_FLASH_ADDR0);
479
480 /* send out address */
481 writel(NFC_ADDR, NFC_V3_LAUNCH);
482
483 wait_op_done(host, 0);
484}
485
Sascha Hauer34f6e152008-09-02 17:16:59 +0200486/* This function sends an address (or partial address) to the
487 * NAND device. The address is used to select the source/destination for
488 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200489static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200490{
Brian Norris289c0522011-07-19 10:06:09 -0700491 pr_debug("send_addr(host, 0x%x %d)\n", addr, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200492
Sascha Hauer1bc99182010-08-06 15:53:08 +0200493 writew(addr, NFC_V1_V2_FLASH_ADDR);
494 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200495
496 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200497 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200498}
499
Sascha Hauer71ec5152010-08-06 15:53:11 +0200500static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
501{
502 struct nand_chip *nand_chip = mtd->priv;
503 struct mxc_nand_host *host = nand_chip->priv;
504 uint32_t tmp;
505
506 tmp = readl(NFC_V3_CONFIG1);
507 tmp &= ~(7 << 4);
508 writel(tmp, NFC_V3_CONFIG1);
509
510 /* transfer data from NFC ram to nand */
511 writel(ops, NFC_V3_LAUNCH);
512
513 wait_op_done(host, false);
514}
515
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200516static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
517{
518 struct nand_chip *nand_chip = mtd->priv;
519 struct mxc_nand_host *host = nand_chip->priv;
520
521 /* NANDFC buffer 0 is used for page read/write */
522 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
523
524 writew(ops, NFC_V1_V2_CONFIG2);
525
526 /* Wait for operation to complete */
527 wait_op_done(host, true);
528}
529
530static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200531{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200532 struct nand_chip *nand_chip = mtd->priv;
533 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200534 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200535
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200536 if (mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200537 bufs = 4;
538 else
539 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200540
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200541 for (i = 0; i < bufs; i++) {
542
543 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200544 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200545
Sascha Hauer1bc99182010-08-06 15:53:08 +0200546 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200547
548 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200549 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200550 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551}
552
Sascha Hauer71ec5152010-08-06 15:53:11 +0200553static void send_read_id_v3(struct mxc_nand_host *host)
554{
555 /* Read ID into main buffer */
556 writel(NFC_ID, NFC_V3_LAUNCH);
557
558 wait_op_done(host, true);
559
Sascha Hauer096bcc22012-05-29 10:16:09 +0200560 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Sascha Hauer71ec5152010-08-06 15:53:11 +0200561}
562
Sascha Hauer34f6e152008-09-02 17:16:59 +0200563/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200564static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200565{
Sascha Hauer34f6e152008-09-02 17:16:59 +0200566 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200567 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200568
Sascha Hauer1bc99182010-08-06 15:53:08 +0200569 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200570
571 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200572 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200573
Sascha Hauer096bcc22012-05-29 10:16:09 +0200574 memcpy32_fromio(host->data_buf, host->main_area0, 16);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200575}
576
Sascha Hauer71ec5152010-08-06 15:53:11 +0200577static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200578{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200579 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200580 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200581
Sascha Hauer71ec5152010-08-06 15:53:11 +0200582 return readl(NFC_V3_CONFIG1) >> 16;
583}
584
Sascha Hauer34f6e152008-09-02 17:16:59 +0200585/* This function requests the NANDFC to perform a read of the
586 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200587static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200588{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200589 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200590 uint32_t store;
591 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200592
Baruch Siachd178e3e2011-03-14 09:01:56 +0200593 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200594
595 /*
596 * The device status is stored in main_area0. To
597 * prevent corruption of the buffer save the value
598 * and restore it afterwards.
599 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200600 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200601
Sascha Hauer1bc99182010-08-06 15:53:08 +0200602 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200603 wait_op_done(host, true);
604
Sascha Hauer34f6e152008-09-02 17:16:59 +0200605 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200606
Sascha Hauer34f6e152008-09-02 17:16:59 +0200607 writel(store, main_buf);
608
609 return ret;
610}
611
612/* This functions is used by upper layer to checks if device is ready */
613static int mxc_nand_dev_ready(struct mtd_info *mtd)
614{
615 /*
616 * NFC handles R/B internally. Therefore, this function
617 * always returns status as ready.
618 */
619 return 1;
620}
621
622static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
623{
624 /*
625 * If HW ECC is enabled, we turn it on during init. There is
626 * no need to enable again here.
627 */
628}
629
Sascha Hauer94f77e52010-08-06 15:53:09 +0200630static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200631 u_char *read_ecc, u_char *calc_ecc)
632{
633 struct nand_chip *nand_chip = mtd->priv;
634 struct mxc_nand_host *host = nand_chip->priv;
635
636 /*
637 * 1-Bit errors are automatically corrected in HW. No need for
638 * additional correction. 2-Bit errors cannot be corrected by
639 * HW ECC, so we need to return failure
640 */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200641 uint16_t ecc_status = get_ecc_status_v1(host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200642
643 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
Brian Norris289c0522011-07-19 10:06:09 -0700644 pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
Sascha Hauer34f6e152008-09-02 17:16:59 +0200645 return -1;
646 }
647
648 return 0;
649}
650
Sascha Hauer94f77e52010-08-06 15:53:09 +0200651static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
652 u_char *read_ecc, u_char *calc_ecc)
653{
654 struct nand_chip *nand_chip = mtd->priv;
655 struct mxc_nand_host *host = nand_chip->priv;
656 u32 ecc_stat, err;
657 int no_subpages = 1;
658 int ret = 0;
659 u8 ecc_bit_mask, err_limit;
660
661 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
662 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
663
664 no_subpages = mtd->writesize >> 9;
665
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200666 ecc_stat = host->devtype_data->get_ecc_status(host);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200667
668 do {
669 err = ecc_stat & ecc_bit_mask;
670 if (err > err_limit) {
671 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
672 return -1;
673 } else {
674 ret += err;
675 }
676 ecc_stat >>= 4;
677 } while (--no_subpages);
678
Sascha Hauer94f77e52010-08-06 15:53:09 +0200679 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
680
681 return ret;
682}
683
Sascha Hauer34f6e152008-09-02 17:16:59 +0200684static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
685 u_char *ecc_code)
686{
687 return 0;
688}
689
690static u_char mxc_nand_read_byte(struct mtd_info *mtd)
691{
692 struct nand_chip *nand_chip = mtd->priv;
693 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200694 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200695
696 /* Check for status request */
697 if (host->status_request)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200698 return host->devtype_data->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200699
Uwe Kleine-König3f410692015-02-10 19:59:57 +0100700 if (nand_chip->options & NAND_BUSWIDTH_16) {
701 /* only take the lower byte of each word */
702 ret = *(uint16_t *)(host->data_buf + host->buf_start);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200703
Uwe Kleine-König3f410692015-02-10 19:59:57 +0100704 host->buf_start += 2;
705 } else {
706 ret = *(uint8_t *)(host->data_buf + host->buf_start);
707 host->buf_start++;
708 }
709
710 pr_debug("%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200711 return ret;
712}
713
714static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
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 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200719
Sascha Hauerf8f96082009-06-04 17:12:26 +0200720 ret = *(uint16_t *)(host->data_buf + host->buf_start);
721 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200722
723 return ret;
724}
725
726/* Write data of length len to buffer buf. The data to be
727 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
728 * Operation by the NFC, the data is written to NAND Flash */
729static void mxc_nand_write_buf(struct mtd_info *mtd,
730 const u_char *buf, int len)
731{
732 struct nand_chip *nand_chip = mtd->priv;
733 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200734 u16 col = host->buf_start;
735 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200736
Sascha Hauerf8f96082009-06-04 17:12:26 +0200737 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200738
Sascha Hauerf8f96082009-06-04 17:12:26 +0200739 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200740
Sascha Hauerf8f96082009-06-04 17:12:26 +0200741 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200742}
743
744/* Read the data buffer from the NAND Flash. To read the data from NAND
745 * Flash first the data output cycle is initiated by the NFC, which copies
746 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
747 */
748static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
749{
750 struct nand_chip *nand_chip = mtd->priv;
751 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200752 u16 col = host->buf_start;
753 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200754
Sascha Hauerf8f96082009-06-04 17:12:26 +0200755 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200756
Baruch Siach5d9d9932011-03-02 16:47:55 +0200757 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200758
Baruch Siach5d9d9932011-03-02 16:47:55 +0200759 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200760}
761
Sascha Hauer34f6e152008-09-02 17:16:59 +0200762/* This function is used by upper layer for select and
763 * deselect of the NAND chip */
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200764static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200765{
766 struct nand_chip *nand_chip = mtd->priv;
767 struct mxc_nand_host *host = nand_chip->priv;
768
Baruch Siachd178e3e2011-03-14 09:01:56 +0200769 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200770 /* Disable the NFC clock */
771 if (host->clk_act) {
Sascha Hauer97c32132012-03-07 20:56:35 +0100772 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200773 host->clk_act = 0;
774 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200775 return;
776 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200777
Baruch Siachd178e3e2011-03-14 09:01:56 +0200778 if (!host->clk_act) {
779 /* Enable the NFC clock */
Sascha Hauer97c32132012-03-07 20:56:35 +0100780 clk_prepare_enable(host->clk);
Baruch Siachd178e3e2011-03-14 09:01:56 +0200781 host->clk_act = 1;
782 }
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200783}
Baruch Siachd178e3e2011-03-14 09:01:56 +0200784
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200785static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200786{
787 struct nand_chip *nand_chip = mtd->priv;
788 struct mxc_nand_host *host = nand_chip->priv;
789
790 if (chip == -1) {
791 /* Disable the NFC clock */
792 if (host->clk_act) {
Fabio Estevam3d059692012-05-25 20:14:50 -0300793 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200794 host->clk_act = 0;
795 }
796 return;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200797 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200798
799 if (!host->clk_act) {
800 /* Enable the NFC clock */
Fabio Estevam3d059692012-05-25 20:14:50 -0300801 clk_prepare_enable(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200802 host->clk_act = 1;
803 }
804
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +0200805 host->active_cs = chip;
806 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200807}
808
Sascha Hauerf8f96082009-06-04 17:12:26 +0200809/*
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300810 * The controller splits a page into data chunks of 512 bytes + partial oob.
811 * There are writesize / 512 such chunks, the size of the partial oob parts is
812 * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then
813 * contains additionally the byte lost by rounding (if any).
814 * This function handles the needed shuffling between host->data_buf (which
815 * holds a page in natural order, i.e. writesize bytes data + oobsize bytes
816 * spare) and the NFC buffer.
Sascha Hauerf8f96082009-06-04 17:12:26 +0200817 */
818static void copy_spare(struct mtd_info *mtd, bool bfrom)
819{
820 struct nand_chip *this = mtd->priv;
821 struct mxc_nand_host *host = this->priv;
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300822 u16 i, oob_chunk_size;
823 u16 num_chunks = mtd->writesize / 512;
824
Sascha Hauerf8f96082009-06-04 17:12:26 +0200825 u8 *d = host->data_buf + mtd->writesize;
Uwe Kleine-König4b6f05e2012-04-24 10:05:22 +0200826 u8 __iomem *s = host->spare0;
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300827 u16 sparebuf_size = host->devtype_data->spare_len;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200828
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300829 /* size of oob chunk for all but possibly the last one */
830 oob_chunk_size = (mtd->oobsize / num_chunks) & ~1;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200831
832 if (bfrom) {
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300833 for (i = 0; i < num_chunks - 1; i++)
834 memcpy32_fromio(d + i * oob_chunk_size,
835 s + i * sparebuf_size,
836 oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200837
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300838 /* the last chunk */
839 memcpy32_fromio(d + i * oob_chunk_size,
840 s + i * sparebuf_size,
841 mtd->oobsize - i * oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200842 } else {
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300843 for (i = 0; i < num_chunks - 1; i++)
844 memcpy32_toio(&s[i * sparebuf_size],
845 &d[i * oob_chunk_size],
846 oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200847
Uwe Kleine-König35d5d202015-05-13 11:17:36 +0300848 /* the last chunk */
849 memcpy32_toio(&s[oob_chunk_size * sparebuf_size],
850 &d[i * oob_chunk_size],
851 mtd->oobsize - i * oob_chunk_size);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200852 }
853}
854
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100855/*
856 * MXC NANDFC can only perform full page+spare or spare-only read/write. When
857 * the upper layers perform a read/write buf operation, the saved column address
858 * is used to index into the full page. So usually this function is called with
859 * column == 0 (unless no column cycle is needed indicated by column == -1)
860 */
Sascha Hauera3e65b62009-06-02 11:47:59 +0200861static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200862{
863 struct nand_chip *nand_chip = mtd->priv;
864 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200865
866 /* Write out column address, if necessary */
867 if (column != -1) {
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100868 host->devtype_data->send_addr(host, column & 0xff,
869 page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200870 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200871 /* another col addr cycle for 2k page */
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +0100872 host->devtype_data->send_addr(host,
873 (column >> 8) & 0xff,
874 false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200875 }
876
877 /* Write out page address, if necessary */
878 if (page_addr != -1) {
879 /* paddr_0 - p_addr_7 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200880 host->devtype_data->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200881
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200882 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400883 if (mtd->size >= 0x10000000) {
884 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200885 host->devtype_data->send_addr(host,
886 (page_addr >> 8) & 0xff,
887 false);
888 host->devtype_data->send_addr(host,
889 (page_addr >> 16) & 0xff,
890 true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400891 } else
892 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200893 host->devtype_data->send_addr(host,
894 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200895 } else {
896 /* One more address cycle for higher density devices */
897 if (mtd->size >= 0x4000000) {
898 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200899 host->devtype_data->send_addr(host,
900 (page_addr >> 8) & 0xff,
901 false);
902 host->devtype_data->send_addr(host,
903 (page_addr >> 16) & 0xff,
904 true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200905 } else
906 /* paddr_8 - paddr_15 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +0200907 host->devtype_data->send_addr(host,
908 (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200909 }
910 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200911}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200912
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200913/*
914 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
915 * on how much oob the nand chip has. For 8bit ecc we need at least
916 * 26 bytes of oob data per 512 byte block.
917 */
918static int get_eccsize(struct mtd_info *mtd)
919{
920 int oobbytes_per_512 = 0;
921
922 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
923
924 if (oobbytes_per_512 < 26)
925 return 4;
926 else
927 return 8;
928}
929
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200930static void preset_v1(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200931{
932 struct nand_chip *nand_chip = mtd->priv;
933 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200934 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200935
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +0100936 if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200937 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
938
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200939 if (!host->devtype_data->irqpending_quirk)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200940 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200941
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200942 host->eccsize = 1;
943
944 writew(config1, NFC_V1_V2_CONFIG1);
945 /* preset operation */
946
947 /* Unlock the internal RAM Buffer */
948 writew(0x2, NFC_V1_V2_CONFIG);
949
950 /* Blocks to be unlocked */
951 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
952 writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR);
953
954 /* Unlock Block Command for given address range */
955 writew(0x4, NFC_V1_V2_WRPROT);
956}
957
958static void preset_v2(struct mtd_info *mtd)
959{
960 struct nand_chip *nand_chip = mtd->priv;
961 struct mxc_nand_host *host = nand_chip->priv;
962 uint16_t config1 = 0;
963
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200964 config1 |= NFC_V2_CONFIG1_FP_INT;
Ivo Claryssed4840182010-04-08 16:14:44 +0200965
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +0200966 if (!host->devtype_data->irqpending_quirk)
Ivo Claryssed4840182010-04-08 16:14:44 +0200967 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200968
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200969 if (mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200970 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
971
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +0100972 if (nand_chip->ecc.mode == NAND_ECC_HW)
973 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
974
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200975 host->eccsize = get_eccsize(mtd);
976 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200977 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
978
979 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200980 } else {
981 host->eccsize = 1;
982 }
983
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200984 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200985 /* preset operation */
986
987 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200988 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200989
990 /* Blocks to be unlocked */
Uwe Kleine-König6d38af22012-04-23 11:23:36 +0200991 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
992 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
993 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
994 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
995 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
996 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
997 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
998 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200999
1000 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +02001001 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +02001002}
1003
Sascha Hauer71ec5152010-08-06 15:53:11 +02001004static void preset_v3(struct mtd_info *mtd)
1005{
1006 struct nand_chip *chip = mtd->priv;
1007 struct mxc_nand_host *host = chip->priv;
1008 uint32_t config2, config3;
1009 int i, addr_phases;
1010
1011 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
1012 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
1013
1014 /* Unlock the internal RAM Buffer */
1015 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
1016 NFC_V3_WRPROT);
1017
1018 /* Blocks to be unlocked */
1019 for (i = 0; i < NAND_MAX_CHIPS; i++)
1020 writel(0x0 | (0xffff << 16),
1021 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
1022
1023 writel(0, NFC_V3_IPC);
1024
1025 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
1026 NFC_V3_CONFIG2_2CMD_PHASES |
1027 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
1028 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +02001029 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +02001030 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
1031
Sascha Hauer71ec5152010-08-06 15:53:11 +02001032 addr_phases = fls(chip->pagemask) >> 3;
1033
1034 if (mtd->writesize == 2048) {
1035 config2 |= NFC_V3_CONFIG2_PS_2048;
1036 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1037 } else if (mtd->writesize == 4096) {
1038 config2 |= NFC_V3_CONFIG2_PS_4096;
1039 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
1040 } else {
1041 config2 |= NFC_V3_CONFIG2_PS_512;
1042 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
1043 }
1044
1045 if (mtd->writesize) {
Uwe Kleine-König1f42adc2015-02-10 19:59:56 +01001046 if (chip->ecc.mode == NAND_ECC_HW)
1047 config2 |= NFC_V3_CONFIG2_ECC_EN;
1048
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001049 config2 |= NFC_V3_CONFIG2_PPB(
1050 ffs(mtd->erasesize / mtd->writesize) - 6,
1051 host->devtype_data->ppb_shift);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001052 host->eccsize = get_eccsize(mtd);
1053 if (host->eccsize == 8)
1054 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
1055 }
1056
1057 writel(config2, NFC_V3_CONFIG2);
1058
1059 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
1060 NFC_V3_CONFIG3_NO_SDMA |
1061 NFC_V3_CONFIG3_RBB_MODE |
1062 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
1063 NFC_V3_CONFIG3_ADD_OP(0);
1064
1065 if (!(chip->options & NAND_BUSWIDTH_16))
1066 config3 |= NFC_V3_CONFIG3_FW8;
1067
1068 writel(config3, NFC_V3_CONFIG3);
1069
1070 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001071}
1072
Sascha Hauer34f6e152008-09-02 17:16:59 +02001073/* Used by the upper layer to write command to NAND Flash for
1074 * different operations to be carried out on NAND Flash */
1075static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
1076 int column, int page_addr)
1077{
1078 struct nand_chip *nand_chip = mtd->priv;
1079 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001080
Brian Norris289c0522011-07-19 10:06:09 -07001081 pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
Sascha Hauer34f6e152008-09-02 17:16:59 +02001082 command, column, page_addr);
1083
1084 /* Reset command state information */
1085 host->status_request = false;
1086
1087 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +02001088 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +02001089 case NAND_CMD_RESET:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001090 host->devtype_data->preset(mtd);
1091 host->devtype_data->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +02001092 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001093
Sascha Hauer34f6e152008-09-02 17:16:59 +02001094 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +02001095 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001096 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +02001097
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001098 host->devtype_data->send_cmd(host, command, true);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001099 WARN_ONCE(column != -1 || page_addr != -1,
1100 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1101 command, column, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001102 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001103 break;
1104
Sascha Hauer34f6e152008-09-02 17:16:59 +02001105 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001106 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +02001107 if (command == NAND_CMD_READ0)
1108 host->buf_start = column;
1109 else
1110 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001111
Sascha Hauer5ea32022010-04-27 15:24:01 +02001112 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +02001113
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001114 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001115 WARN_ONCE(column < 0,
1116 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1117 command, column, page_addr);
1118 mxc_do_addr_cycle(mtd, 0, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001119
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001120 if (mtd->writesize > 512)
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001121 host->devtype_data->send_cmd(host,
1122 NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +02001123
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001124 host->devtype_data->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +02001125
Sascha Hauer096bcc22012-05-29 10:16:09 +02001126 memcpy32_fromio(host->data_buf, host->main_area0,
1127 mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +02001128 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001129 break;
1130
Sascha Hauer34f6e152008-09-02 17:16:59 +02001131 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +02001132 if (column >= mtd->writesize)
1133 /* call ourself to read a page */
1134 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001135
Sascha Hauer5ea32022010-04-27 15:24:01 +02001136 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +02001137
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001138 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001139 WARN_ONCE(column < -1,
1140 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1141 command, column, page_addr);
1142 mxc_do_addr_cycle(mtd, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001143 break;
1144
1145 case NAND_CMD_PAGEPROG:
Sascha Hauer096bcc22012-05-29 10:16:09 +02001146 memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001147 copy_spare(mtd, false);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001148 host->devtype_data->send_page(mtd, NFC_INPUT);
1149 host->devtype_data->send_cmd(host, command, true);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001150 WARN_ONCE(column != -1 || page_addr != -1,
1151 "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
1152 command, column, page_addr);
Sascha Hauer89121a62009-06-04 17:18:01 +02001153 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001154 break;
1155
Sascha Hauer34f6e152008-09-02 17:16:59 +02001156 case NAND_CMD_READID:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001157 host->devtype_data->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001158 mxc_do_addr_cycle(mtd, column, page_addr);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001159 host->devtype_data->send_read_id(host);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001160 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001161 break;
1162
Sascha Hauer89121a62009-06-04 17:18:01 +02001163 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001164 case NAND_CMD_ERASE2:
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001165 host->devtype_data->send_cmd(host, command, false);
Uwe Kleine-Königc4ca3992015-02-10 19:59:58 +01001166 WARN_ONCE(column != -1,
1167 "Unexpected column value (cmd=%u, col=%d)\n",
1168 command, column);
Sascha Hauer89121a62009-06-04 17:18:01 +02001169 mxc_do_addr_cycle(mtd, column, page_addr);
1170
Sascha Hauer34f6e152008-09-02 17:16:59 +02001171 break;
Uwe Kleine-König3d6e81c2015-02-10 19:59:59 +01001172 case NAND_CMD_PARAM:
1173 host->devtype_data->send_cmd(host, command, false);
1174 mxc_do_addr_cycle(mtd, column, page_addr);
1175 host->devtype_data->send_page(mtd, NFC_OUTPUT);
1176 memcpy32_fromio(host->data_buf, host->main_area0, 512);
1177 host->buf_start = 0;
1178 break;
Uwe Kleine-König98ebb522015-02-10 20:00:00 +01001179 default:
1180 WARN_ONCE(1, "Unimplemented command (cmd=%u)\n",
1181 command);
1182 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001183 }
1184}
1185
Sascha Hauerf1372052009-10-21 14:25:27 +02001186/*
1187 * The generic flash bbt decriptors overlap with our ecc
1188 * hardware, so define some i.MX specific ones.
1189 */
1190static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1191static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1192
1193static struct nand_bbt_descr bbt_main_descr = {
1194 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1195 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1196 .offs = 0,
1197 .len = 4,
1198 .veroffs = 4,
1199 .maxblocks = 4,
1200 .pattern = bbt_pattern,
1201};
1202
1203static struct nand_bbt_descr bbt_mirror_descr = {
1204 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1205 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1206 .offs = 0,
1207 .len = 4,
1208 .veroffs = 4,
1209 .maxblocks = 4,
1210 .pattern = mirror_pattern,
1211};
1212
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001213/* v1 + irqpending_quirk: i.MX21 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001214static const struct mxc_nand_devtype_data imx21_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001215 .preset = preset_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001216 .send_cmd = send_cmd_v1_v2,
1217 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001218 .send_page = send_page_v1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001219 .send_read_id = send_read_id_v1_v2,
1220 .get_dev_status = get_dev_status_v1_v2,
1221 .check_int = check_int_v1_v2,
1222 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001223 .get_ecc_status = get_ecc_status_v1,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001224 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1225 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1226 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +02001227 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001228 .correct_data = mxc_nand_correct_data_v1,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001229 .irqpending_quirk = 1,
1230 .needs_ip = 0,
1231 .regs_offset = 0xe00,
1232 .spare0_offset = 0x800,
1233 .spare_len = 16,
1234 .eccbytes = 3,
1235 .eccsize = 1,
1236};
1237
1238/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
1239static const struct mxc_nand_devtype_data imx27_nand_devtype_data = {
1240 .preset = preset_v1,
1241 .send_cmd = send_cmd_v1_v2,
1242 .send_addr = send_addr_v1_v2,
1243 .send_page = send_page_v1,
1244 .send_read_id = send_read_id_v1_v2,
1245 .get_dev_status = get_dev_status_v1_v2,
1246 .check_int = check_int_v1_v2,
1247 .irq_control = irq_control_v1_v2,
1248 .get_ecc_status = get_ecc_status_v1,
1249 .ecclayout_512 = &nandv1_hw_eccoob_smallpage,
1250 .ecclayout_2k = &nandv1_hw_eccoob_largepage,
1251 .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */
1252 .select_chip = mxc_nand_select_chip_v1_v3,
1253 .correct_data = mxc_nand_correct_data_v1,
1254 .irqpending_quirk = 0,
1255 .needs_ip = 0,
1256 .regs_offset = 0xe00,
1257 .spare0_offset = 0x800,
1258 .axi_offset = 0,
1259 .spare_len = 16,
1260 .eccbytes = 3,
1261 .eccsize = 1,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001262};
1263
1264/* v21: i.MX25, i.MX35 */
1265static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001266 .preset = preset_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001267 .send_cmd = send_cmd_v1_v2,
1268 .send_addr = send_addr_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001269 .send_page = send_page_v2,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001270 .send_read_id = send_read_id_v1_v2,
1271 .get_dev_status = get_dev_status_v1_v2,
1272 .check_int = check_int_v1_v2,
1273 .irq_control = irq_control_v1_v2,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001274 .get_ecc_status = get_ecc_status_v2,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001275 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1276 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1277 .ecclayout_4k = &nandv2_hw_eccoob_4k,
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +02001278 .select_chip = mxc_nand_select_chip_v2,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001279 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001280 .irqpending_quirk = 0,
1281 .needs_ip = 0,
1282 .regs_offset = 0x1e00,
1283 .spare0_offset = 0x1000,
1284 .axi_offset = 0,
1285 .spare_len = 64,
1286 .eccbytes = 9,
1287 .eccsize = 0,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001288};
1289
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001290/* v3.2a: i.MX51 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001291static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1292 .preset = preset_v3,
1293 .send_cmd = send_cmd_v3,
1294 .send_addr = send_addr_v3,
1295 .send_page = send_page_v3,
1296 .send_read_id = send_read_id_v3,
1297 .get_dev_status = get_dev_status_v3,
1298 .check_int = check_int_v3,
1299 .irq_control = irq_control_v3,
Uwe Kleine-König6d38af22012-04-23 11:23:36 +02001300 .get_ecc_status = get_ecc_status_v3,
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001301 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1302 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1303 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
Uwe Kleine-König5e05a2d2012-04-23 11:23:38 +02001304 .select_chip = mxc_nand_select_chip_v1_v3,
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001305 .correct_data = mxc_nand_correct_data_v2_v3,
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001306 .irqpending_quirk = 0,
1307 .needs_ip = 1,
1308 .regs_offset = 0,
1309 .spare0_offset = 0x1000,
1310 .axi_offset = 0x1e00,
1311 .spare_len = 64,
1312 .eccbytes = 0,
1313 .eccsize = 0,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001314 .ppb_shift = 7,
1315};
1316
1317/* v3.2b: i.MX53 */
1318static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
1319 .preset = preset_v3,
1320 .send_cmd = send_cmd_v3,
1321 .send_addr = send_addr_v3,
1322 .send_page = send_page_v3,
1323 .send_read_id = send_read_id_v3,
1324 .get_dev_status = get_dev_status_v3,
1325 .check_int = check_int_v3,
1326 .irq_control = irq_control_v3,
1327 .get_ecc_status = get_ecc_status_v3,
1328 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1329 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1330 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1331 .select_chip = mxc_nand_select_chip_v1_v3,
1332 .correct_data = mxc_nand_correct_data_v2_v3,
1333 .irqpending_quirk = 0,
1334 .needs_ip = 1,
1335 .regs_offset = 0,
1336 .spare0_offset = 0x1000,
1337 .axi_offset = 0x1e00,
1338 .spare_len = 64,
1339 .eccbytes = 0,
1340 .eccsize = 0,
1341 .ppb_shift = 8,
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001342};
1343
Shawn Guo4d624352012-09-15 13:34:09 +08001344static inline int is_imx21_nfc(struct mxc_nand_host *host)
1345{
1346 return host->devtype_data == &imx21_nand_devtype_data;
1347}
1348
1349static inline int is_imx27_nfc(struct mxc_nand_host *host)
1350{
1351 return host->devtype_data == &imx27_nand_devtype_data;
1352}
1353
1354static inline int is_imx25_nfc(struct mxc_nand_host *host)
1355{
1356 return host->devtype_data == &imx25_nand_devtype_data;
1357}
1358
1359static inline int is_imx51_nfc(struct mxc_nand_host *host)
1360{
1361 return host->devtype_data == &imx51_nand_devtype_data;
1362}
1363
1364static inline int is_imx53_nfc(struct mxc_nand_host *host)
1365{
1366 return host->devtype_data == &imx53_nand_devtype_data;
1367}
1368
Krzysztof Kozlowski8d1e5682015-05-02 00:50:01 +09001369static const struct platform_device_id mxcnd_devtype[] = {
Shawn Guo4d624352012-09-15 13:34:09 +08001370 {
1371 .name = "imx21-nand",
1372 .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
1373 }, {
1374 .name = "imx27-nand",
1375 .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
1376 }, {
1377 .name = "imx25-nand",
1378 .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
1379 }, {
1380 .name = "imx51-nand",
1381 .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
1382 }, {
1383 .name = "imx53-nand",
1384 .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
1385 }, {
1386 /* sentinel */
1387 }
1388};
1389MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
1390
Uwe Kleine-König64363562012-04-23 11:23:41 +02001391#ifdef CONFIG_OF_MTD
1392static const struct of_device_id mxcnd_dt_ids[] = {
1393 {
1394 .compatible = "fsl,imx21-nand",
1395 .data = &imx21_nand_devtype_data,
1396 }, {
1397 .compatible = "fsl,imx27-nand",
1398 .data = &imx27_nand_devtype_data,
1399 }, {
1400 .compatible = "fsl,imx25-nand",
1401 .data = &imx25_nand_devtype_data,
1402 }, {
1403 .compatible = "fsl,imx51-nand",
1404 .data = &imx51_nand_devtype_data,
Sascha Hauer71718a8e2012-06-06 12:33:15 +02001405 }, {
1406 .compatible = "fsl,imx53-nand",
1407 .data = &imx53_nand_devtype_data,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001408 },
1409 { /* sentinel */ }
1410};
1411
1412static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1413{
1414 struct device_node *np = host->dev->of_node;
1415 struct mxc_nand_platform_data *pdata = &host->pdata;
1416 const struct of_device_id *of_id =
1417 of_match_device(mxcnd_dt_ids, host->dev);
1418 int buswidth;
1419
1420 if (!np)
1421 return 1;
1422
1423 if (of_get_nand_ecc_mode(np) >= 0)
1424 pdata->hw_ecc = 1;
1425
1426 pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
1427
1428 buswidth = of_get_nand_bus_width(np);
1429 if (buswidth < 0)
1430 return buswidth;
1431
1432 pdata->width = buswidth / 8;
1433
1434 host->devtype_data = of_id->data;
1435
1436 return 0;
1437}
1438#else
1439static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
1440{
1441 return 1;
1442}
1443#endif
1444
Bill Pemberton06f25512012-11-19 13:23:07 -05001445static int mxcnd_probe(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001446{
1447 struct nand_chip *this;
1448 struct mtd_info *mtd;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001449 struct mxc_nand_host *host;
1450 struct resource *res;
Dmitry Eremin-Solenikovd4ed8f12011-06-02 18:00:43 +04001451 int err = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001452
1453 /* Allocate memory for MTD device structure and private data */
Huang Shijiea5900552013-12-21 00:02:27 +08001454 host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
1455 GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001456 if (!host)
1457 return -ENOMEM;
1458
Huang Shijiea5900552013-12-21 00:02:27 +08001459 /* allocate a temporary buffer for the nand_scan_ident() */
1460 host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
1461 if (!host->data_buf)
1462 return -ENOMEM;
Sascha Hauerf8f96082009-06-04 17:12:26 +02001463
Sascha Hauer34f6e152008-09-02 17:16:59 +02001464 host->dev = &pdev->dev;
1465 /* structures must be linked */
1466 this = &host->nand;
1467 mtd = &host->mtd;
1468 mtd->priv = this;
1469 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001470 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001471 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001472
1473 /* 50 us command delay time */
1474 this->chip_delay = 5;
1475
1476 this->priv = host;
1477 this->dev_ready = mxc_nand_dev_ready;
1478 this->cmdfunc = mxc_nand_command;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001479 this->read_byte = mxc_nand_read_byte;
1480 this->read_word = mxc_nand_read_word;
1481 this->write_buf = mxc_nand_write_buf;
1482 this->read_buf = mxc_nand_read_buf;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001483
Fabio Estevam24b82d32012-09-05 11:52:27 -03001484 host->clk = devm_clk_get(&pdev->dev, NULL);
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001485 if (IS_ERR(host->clk))
1486 return PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001487
Sascha Hauer71885b62012-06-06 12:33:14 +02001488 err = mxcnd_probe_dt(host);
Shawn Guo4d624352012-09-15 13:34:09 +08001489 if (err > 0) {
Jingoo Han453810b2013-07-30 17:18:33 +09001490 struct mxc_nand_platform_data *pdata =
1491 dev_get_platdata(&pdev->dev);
Shawn Guo4d624352012-09-15 13:34:09 +08001492 if (pdata) {
1493 host->pdata = *pdata;
1494 host->devtype_data = (struct mxc_nand_devtype_data *)
1495 pdev->id_entry->driver_data;
1496 } else {
1497 err = -ENODEV;
1498 }
1499 }
Sascha Hauer71885b62012-06-06 12:33:14 +02001500 if (err < 0)
1501 return err;
1502
1503 if (host->devtype_data->needs_ip) {
1504 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Thierry Redingb0de7742013-01-21 11:09:12 +01001505 host->regs_ip = devm_ioremap_resource(&pdev->dev, res);
1506 if (IS_ERR(host->regs_ip))
1507 return PTR_ERR(host->regs_ip);
Sascha Hauer71885b62012-06-06 12:33:14 +02001508
1509 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1510 } else {
1511 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1512 }
1513
Thierry Redingb0de7742013-01-21 11:09:12 +01001514 host->base = devm_ioremap_resource(&pdev->dev, res);
1515 if (IS_ERR(host->base))
1516 return PTR_ERR(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001517
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001518 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001519
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001520 if (host->devtype_data->regs_offset)
1521 host->regs = host->base + host->devtype_data->regs_offset;
1522 host->spare0 = host->base + host->devtype_data->spare0_offset;
1523 if (host->devtype_data->axi_offset)
1524 host->regs_axi = host->base + host->devtype_data->axi_offset;
1525
1526 this->ecc.bytes = host->devtype_data->eccbytes;
1527 host->eccsize = host->devtype_data->eccsize;
1528
1529 this->select_chip = host->devtype_data->select_chip;
1530 this->ecc.size = 512;
1531 this->ecc.layout = host->devtype_data->ecclayout_512;
1532
Uwe Kleine-König64363562012-04-23 11:23:41 +02001533 if (host->pdata.hw_ecc) {
Sascha Hauer13e1add2009-10-21 10:39:05 +02001534 this->ecc.calculate = mxc_nand_calculate_ecc;
1535 this->ecc.hwctl = mxc_nand_enable_hwecc;
Uwe Kleine-König69d023b2012-04-23 11:23:39 +02001536 this->ecc.correct = host->devtype_data->correct_data;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001537 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001538 } else {
1539 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001540 }
1541
Uwe Kleine-König64363562012-04-23 11:23:41 +02001542 /* NAND bus width determines access functions used by upper layer */
1543 if (host->pdata.width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001544 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001545
Uwe Kleine-König64363562012-04-23 11:23:41 +02001546 if (host->pdata.flash_bbt) {
Sascha Hauerf1372052009-10-21 14:25:27 +02001547 this->bbt_td = &bbt_main_descr;
1548 this->bbt_md = &bbt_mirror_descr;
1549 /* update flash based bbt */
Brian Norrisbb9ebd42011-05-31 16:31:23 -07001550 this->bbt_options |= NAND_BBT_USE_FLASH;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001551 }
1552
Sascha Hauer63f14742010-10-18 10:16:26 +02001553 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001554
1555 host->irq = platform_get_irq(pdev, 0);
Fabio Estevam26fbf482014-02-14 01:09:34 -02001556 if (host->irq < 0)
1557 return host->irq;
Ivo Claryssed4840182010-04-08 16:14:44 +02001558
Sascha Hauer63f14742010-10-18 10:16:26 +02001559 /*
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001560 * Use host->devtype_data->irq_control() here instead of irq_control()
1561 * because we must not disable_irq_nosync without having requested the
1562 * irq.
Sascha Hauer63f14742010-10-18 10:16:26 +02001563 */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001564 host->devtype_data->irq_control(host, 0);
Sascha Hauer63f14742010-10-18 10:16:26 +02001565
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001566 err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
Michael Opdenackerb1eb2342013-10-13 08:21:32 +02001567 0, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001568 if (err)
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001569 return err;
1570
Fabio Estevamdcedf622013-12-02 00:50:02 -02001571 err = clk_prepare_enable(host->clk);
1572 if (err)
1573 return err;
Sascha Hauere4a09cb2012-06-06 12:33:13 +02001574 host->clk_act = 1;
Ivo Claryssed4840182010-04-08 16:14:44 +02001575
Sascha Hauer63f14742010-10-18 10:16:26 +02001576 /*
Uwe Kleine-König85569582012-04-23 11:23:34 +02001577 * Now that we "own" the interrupt make sure the interrupt mask bit is
1578 * cleared on i.MX21. Otherwise we can't read the interrupt status bit
1579 * on this machine.
Sascha Hauer63f14742010-10-18 10:16:26 +02001580 */
Uwe Kleine-Königf48d0f92012-04-23 11:23:40 +02001581 if (host->devtype_data->irqpending_quirk) {
Uwe Kleine-König85569582012-04-23 11:23:34 +02001582 disable_irq_nosync(host->irq);
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001583 host->devtype_data->irq_control(host, 1);
Uwe Kleine-König85569582012-04-23 11:23:34 +02001584 }
Sascha Hauer63f14742010-10-18 10:16:26 +02001585
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001586 /* first scan to find the device and get the page size */
Shawn Guo4d624352012-09-15 13:34:09 +08001587 if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001588 err = -ENXIO;
1589 goto escan;
1590 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001591
Huang Shijiea5900552013-12-21 00:02:27 +08001592 /* allocate the right size buffer now */
1593 devm_kfree(&pdev->dev, (void *)host->data_buf);
1594 host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
1595 GFP_KERNEL);
1596 if (!host->data_buf) {
1597 err = -ENOMEM;
1598 goto escan;
1599 }
1600
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001601 /* Call preset again, with correct writesize this time */
Uwe Kleine-Könige4303b22012-04-23 11:23:35 +02001602 host->devtype_data->preset(mtd);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001603
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001604 if (mtd->writesize == 2048)
Uwe Kleine-König6dcdf992012-04-23 11:23:37 +02001605 this->ecc.layout = host->devtype_data->ecclayout_2k;
1606 else if (mtd->writesize == 4096)
1607 this->ecc.layout = host->devtype_data->ecclayout_4k;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001608
Mike Dunn6a918ba2012-03-11 14:21:11 -07001609 if (this->ecc.mode == NAND_ECC_HW) {
Shawn Guo4d624352012-09-15 13:34:09 +08001610 if (is_imx21_nfc(host) || is_imx27_nfc(host))
Mike Dunn6a918ba2012-03-11 14:21:11 -07001611 this->ecc.strength = 1;
1612 else
1613 this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
1614 }
1615
Sascha Hauer4a43faf2012-05-25 16:22:42 +02001616 /* second phase scan */
1617 if (nand_scan_tail(mtd)) {
1618 err = -ENXIO;
1619 goto escan;
1620 }
1621
Sascha Hauer34f6e152008-09-02 17:16:59 +02001622 /* Register the partitions */
Uwe Kleine-König64363562012-04-23 11:23:41 +02001623 mtd_device_parse_register(mtd, part_probes,
1624 &(struct mtd_part_parser_data){
1625 .of_node = pdev->dev.of_node,
1626 },
1627 host->pdata.parts,
1628 host->pdata.nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001629
1630 platform_set_drvdata(pdev, host);
1631
1632 return 0;
1633
1634escan:
Lothar Waßmannc10d8ee2012-12-06 08:42:27 +01001635 if (host->clk_act)
1636 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001637
1638 return err;
1639}
1640
Bill Pemberton810b7e02012-11-19 13:26:04 -05001641static int mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001642{
1643 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1644
Sascha Hauer34f6e152008-09-02 17:16:59 +02001645 nand_release(&host->mtd);
Wei Yongjun8bfd4f72013-12-17 11:35:35 +08001646 if (host->clk_act)
1647 clk_disable_unprepare(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001648
1649 return 0;
1650}
1651
Sascha Hauer34f6e152008-09-02 17:16:59 +02001652static struct platform_driver mxcnd_driver = {
1653 .driver = {
1654 .name = DRIVER_NAME,
Uwe Kleine-König64363562012-04-23 11:23:41 +02001655 .of_match_table = of_match_ptr(mxcnd_dt_ids),
Eric Bénard04dd0d32010-06-17 20:59:04 +02001656 },
Shawn Guo4d624352012-09-15 13:34:09 +08001657 .id_table = mxcnd_devtype,
Fabio Estevamddf16d62012-09-05 11:35:25 -03001658 .probe = mxcnd_probe,
Bill Pemberton5153b882012-11-19 13:21:24 -05001659 .remove = mxcnd_remove,
Sascha Hauer34f6e152008-09-02 17:16:59 +02001660};
Fabio Estevamddf16d62012-09-05 11:35:25 -03001661module_platform_driver(mxcnd_driver);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001662
1663MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1664MODULE_DESCRIPTION("MXC NAND MTD driver");
1665MODULE_LICENSE("GPL");