blob: b4efdb704ed2061eb81e2daa40869cee07d67dc2 [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>
Sascha Hauer34f6e152008-09-02 17:16:59 +020035
36#include <asm/mach/flash.h>
37#include <mach/mxc_nand.h>
Sascha Hauer94671142009-10-05 12:14:21 +020038#include <mach/hardware.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020039
40#define DRIVER_NAME "mxc_nand"
41
Sascha Hauer94671142009-10-05 12:14:21 +020042#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
Ivo Claryssea47bfd22010-04-08 16:16:51 +020043#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
Sascha Hauer71ec5152010-08-06 15:53:11 +020044#define nfc_is_v3_2() cpu_is_mx51()
45#define nfc_is_v3() nfc_is_v3_2()
Sascha Hauer94671142009-10-05 12:14:21 +020046
Sascha Hauer34f6e152008-09-02 17:16:59 +020047/* Addresses for NFC registers */
Sascha Hauer1bc99182010-08-06 15:53:08 +020048#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
49#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
50#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
51#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
52#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
53#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
54#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
55#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
56#define NFC_V1_V2_WRPROT (host->regs + 0x12)
57#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
58#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
Baruch Siachd178e3e2011-03-14 09:01:56 +020059#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
60#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
61#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
62#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
63#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
64#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
65#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
66#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
Sascha Hauer1bc99182010-08-06 15:53:08 +020067#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
68#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
69#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
Sascha Hauer34f6e152008-09-02 17:16:59 +020070
Sascha Hauer6e85dfd2010-08-06 15:53:10 +020071#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
Sascha Hauer1bc99182010-08-06 15:53:08 +020072#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
73#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
74#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
75#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
76#define NFC_V1_V2_CONFIG1_RST (1 << 6)
77#define NFC_V1_V2_CONFIG1_CE (1 << 7)
Sascha Hauerb8db2f52010-08-09 15:04:19 +020078#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
79#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
80#define NFC_V2_CONFIG1_FP_INT (1 << 11)
Sascha Hauer34f6e152008-09-02 17:16:59 +020081
Sascha Hauer1bc99182010-08-06 15:53:08 +020082#define NFC_V1_V2_CONFIG2_INT (1 << 15)
Sascha Hauer34f6e152008-09-02 17:16:59 +020083
Sascha Hauer1bc99182010-08-06 15:53:08 +020084/*
85 * Operation modes for the NFC. Valid for v1, v2 and v3
86 * type controllers.
87 */
88#define NFC_CMD (1 << 0)
89#define NFC_ADDR (1 << 1)
90#define NFC_INPUT (1 << 2)
91#define NFC_OUTPUT (1 << 3)
92#define NFC_ID (1 << 4)
93#define NFC_STATUS (1 << 5)
Sascha Hauer34f6e152008-09-02 17:16:59 +020094
Sascha Hauer71ec5152010-08-06 15:53:11 +020095#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
96#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
Sascha Hauer34f6e152008-09-02 17:16:59 +020097
Sascha Hauer71ec5152010-08-06 15:53:11 +020098#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
99#define NFC_V3_CONFIG1_SP_EN (1 << 0)
100#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200101
Sascha Hauer71ec5152010-08-06 15:53:11 +0200102#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200103
Sascha Hauer71ec5152010-08-06 15:53:11 +0200104#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200105
Sascha Hauer71ec5152010-08-06 15:53:11 +0200106#define NFC_V3_WRPROT (host->regs_ip + 0x0)
107#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
108#define NFC_V3_WRPROT_LOCK (1 << 1)
109#define NFC_V3_WRPROT_UNLOCK (1 << 2)
110#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
111
112#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
113
114#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
115#define NFC_V3_CONFIG2_PS_512 (0 << 0)
116#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
117#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
118#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
119#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
120#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
121#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
122#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
123#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7)
124#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
125#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
126#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
127#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
128
129#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
130#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
131#define NFC_V3_CONFIG3_FW8 (1 << 3)
132#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
133#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
134#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
135#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
136
137#define NFC_V3_IPC (host->regs_ip + 0x2C)
138#define NFC_V3_IPC_CREQ (1 << 0)
139#define NFC_V3_IPC_INT (1 << 31)
140
141#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200142
143struct mxc_nand_host {
144 struct mtd_info mtd;
145 struct nand_chip nand;
146 struct mtd_partition *parts;
147 struct device *dev;
148
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200149 void *spare0;
150 void *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200151
152 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200153 void __iomem *regs;
Sascha Hauer71ec5152010-08-06 15:53:11 +0200154 void __iomem *regs_axi;
155 void __iomem *regs_ip;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200156 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200157 struct clk *clk;
158 int clk_act;
159 int irq;
Sascha Hauer94f77e52010-08-06 15:53:09 +0200160 int eccsize;
Baruch Siachd178e3e2011-03-14 09:01:56 +0200161 int active_cs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200162
Sascha Hauer63f14742010-10-18 10:16:26 +0200163 struct completion op_completion;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200164
165 uint8_t *data_buf;
166 unsigned int buf_start;
167 int spare_len;
Sascha Hauer5f973042010-08-06 15:53:06 +0200168
169 void (*preset)(struct mtd_info *);
170 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
171 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
172 void (*send_page)(struct mtd_info *, unsigned int);
173 void (*send_read_id)(struct mxc_nand_host *);
174 uint16_t (*get_dev_status)(struct mxc_nand_host *);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200175 int (*check_int)(struct mxc_nand_host *);
Sascha Hauer63f14742010-10-18 10:16:26 +0200176 void (*irq_control)(struct mxc_nand_host *, int);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200177};
178
Sascha Hauer34f6e152008-09-02 17:16:59 +0200179/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200180static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200181 .eccbytes = 5,
182 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200183 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200184};
185
Sascha Hauer94671142009-10-05 12:14:21 +0200186static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400187 .eccbytes = 20,
188 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
189 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
190 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200191};
192
Sascha Hauer94671142009-10-05 12:14:21 +0200193/* OOB description for 512 byte pages with 16 byte OOB */
194static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
195 .eccbytes = 1 * 9,
196 .eccpos = {
197 7, 8, 9, 10, 11, 12, 13, 14, 15
198 },
199 .oobfree = {
200 {.offset = 0, .length = 5}
201 }
202};
203
204/* OOB description for 2048 byte pages with 64 byte OOB */
205static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
206 .eccbytes = 4 * 9,
207 .eccpos = {
208 7, 8, 9, 10, 11, 12, 13, 14, 15,
209 23, 24, 25, 26, 27, 28, 29, 30, 31,
210 39, 40, 41, 42, 43, 44, 45, 46, 47,
211 55, 56, 57, 58, 59, 60, 61, 62, 63
212 },
213 .oobfree = {
214 {.offset = 2, .length = 4},
215 {.offset = 16, .length = 7},
216 {.offset = 32, .length = 7},
217 {.offset = 48, .length = 7}
218 }
219};
220
Baruch Siach2c1c5f12011-03-09 16:12:20 +0200221/* OOB description for 4096 byte pages with 128 byte OOB */
222static struct nand_ecclayout nandv2_hw_eccoob_4k = {
223 .eccbytes = 8 * 9,
224 .eccpos = {
225 7, 8, 9, 10, 11, 12, 13, 14, 15,
226 23, 24, 25, 26, 27, 28, 29, 30, 31,
227 39, 40, 41, 42, 43, 44, 45, 46, 47,
228 55, 56, 57, 58, 59, 60, 61, 62, 63,
229 71, 72, 73, 74, 75, 76, 77, 78, 79,
230 87, 88, 89, 90, 91, 92, 93, 94, 95,
231 103, 104, 105, 106, 107, 108, 109, 110, 111,
232 119, 120, 121, 122, 123, 124, 125, 126, 127,
233 },
234 .oobfree = {
235 {.offset = 2, .length = 4},
236 {.offset = 16, .length = 7},
237 {.offset = 32, .length = 7},
238 {.offset = 48, .length = 7},
239 {.offset = 64, .length = 7},
240 {.offset = 80, .length = 7},
241 {.offset = 96, .length = 7},
242 {.offset = 112, .length = 7},
243 }
244};
245
Sascha Hauer34f6e152008-09-02 17:16:59 +0200246#ifdef CONFIG_MTD_PARTITIONS
247static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
248#endif
249
250static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
251{
252 struct mxc_nand_host *host = dev_id;
253
Sascha Hauer63f14742010-10-18 10:16:26 +0200254 if (!host->check_int(host))
255 return IRQ_NONE;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200256
Sascha Hauer63f14742010-10-18 10:16:26 +0200257 host->irq_control(host, 0);
258
259 complete(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200260
261 return IRQ_HANDLED;
262}
263
Sascha Hauer71ec5152010-08-06 15:53:11 +0200264static int check_int_v3(struct mxc_nand_host *host)
265{
266 uint32_t tmp;
267
268 tmp = readl(NFC_V3_IPC);
269 if (!(tmp & NFC_V3_IPC_INT))
270 return 0;
271
272 tmp &= ~NFC_V3_IPC_INT;
273 writel(tmp, NFC_V3_IPC);
274
275 return 1;
276}
277
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200278static int check_int_v1_v2(struct mxc_nand_host *host)
279{
280 uint32_t tmp;
281
Sascha Hauer1bc99182010-08-06 15:53:08 +0200282 tmp = readw(NFC_V1_V2_CONFIG2);
283 if (!(tmp & NFC_V1_V2_CONFIG2_INT))
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200284 return 0;
285
Sascha Hauer63f14742010-10-18 10:16:26 +0200286 if (!cpu_is_mx21())
287 writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200288
289 return 1;
290}
291
Sascha Hauer63f14742010-10-18 10:16:26 +0200292/*
293 * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit
294 * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the
295 * driver can enable/disable the irq line rather than simply masking the
296 * interrupts.
297 */
298static void irq_control_mx21(struct mxc_nand_host *host, int activate)
299{
300 if (activate)
301 enable_irq(host->irq);
302 else
303 disable_irq_nosync(host->irq);
304}
305
306static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
307{
308 uint16_t tmp;
309
310 tmp = readw(NFC_V1_V2_CONFIG1);
311
312 if (activate)
313 tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
314 else
315 tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
316
317 writew(tmp, NFC_V1_V2_CONFIG1);
318}
319
320static void irq_control_v3(struct mxc_nand_host *host, int activate)
321{
322 uint32_t tmp;
323
324 tmp = readl(NFC_V3_CONFIG2);
325
326 if (activate)
327 tmp &= ~NFC_V3_CONFIG2_INT_MSK;
328 else
329 tmp |= NFC_V3_CONFIG2_INT_MSK;
330
331 writel(tmp, NFC_V3_CONFIG2);
332}
333
Sascha Hauer34f6e152008-09-02 17:16:59 +0200334/* This function polls the NANDFC to wait for the basic operation to
335 * complete by checking the INT bit of config2 register.
336 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200337static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200338{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200339 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200340
341 if (useirq) {
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200342 if (!host->check_int(host)) {
Sascha Hauer63f14742010-10-18 10:16:26 +0200343 INIT_COMPLETION(host->op_completion);
344 host->irq_control(host, 1);
345 wait_for_completion(&host->op_completion);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200346 }
347 } else {
348 while (max_retries-- > 0) {
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200349 if (host->check_int(host))
Sascha Hauer34f6e152008-09-02 17:16:59 +0200350 break;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +0200351
Sascha Hauer34f6e152008-09-02 17:16:59 +0200352 udelay(1);
353 }
Roel Kluin43950a62009-06-04 16:24:59 +0200354 if (max_retries < 0)
Sascha Hauer62465492009-06-04 15:57:20 +0200355 DEBUG(MTD_DEBUG_LEVEL0, "%s: INT not set\n",
356 __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200357 }
358}
359
Sascha Hauer71ec5152010-08-06 15:53:11 +0200360static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
361{
362 /* fill command */
363 writel(cmd, NFC_V3_FLASH_CMD);
364
365 /* send out command */
366 writel(NFC_CMD, NFC_V3_LAUNCH);
367
368 /* Wait for operation to complete */
369 wait_op_done(host, useirq);
370}
371
Sascha Hauer34f6e152008-09-02 17:16:59 +0200372/* This function issues the specified command to the NAND device and
373 * waits for completion. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200374static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200375{
376 DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
377
Sascha Hauer1bc99182010-08-06 15:53:08 +0200378 writew(cmd, NFC_V1_V2_FLASH_CMD);
379 writew(NFC_CMD, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200380
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200381 if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
382 int max_retries = 100;
383 /* Reset completion is indicated by NFC_CONFIG2 */
384 /* being set to 0 */
385 while (max_retries-- > 0) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200386 if (readw(NFC_V1_V2_CONFIG2) == 0) {
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200387 break;
388 }
389 udelay(1);
390 }
391 if (max_retries < 0)
392 DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n",
393 __func__);
394 } else {
395 /* Wait for operation to complete */
396 wait_op_done(host, useirq);
397 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200398}
399
Sascha Hauer71ec5152010-08-06 15:53:11 +0200400static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
401{
402 /* fill address */
403 writel(addr, NFC_V3_FLASH_ADDR0);
404
405 /* send out address */
406 writel(NFC_ADDR, NFC_V3_LAUNCH);
407
408 wait_op_done(host, 0);
409}
410
Sascha Hauer34f6e152008-09-02 17:16:59 +0200411/* This function sends an address (or partial address) to the
412 * NAND device. The address is used to select the source/destination for
413 * a NAND command. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200414static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200415{
416 DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
417
Sascha Hauer1bc99182010-08-06 15:53:08 +0200418 writew(addr, NFC_V1_V2_FLASH_ADDR);
419 writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200420
421 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200422 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200423}
424
Sascha Hauer71ec5152010-08-06 15:53:11 +0200425static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
426{
427 struct nand_chip *nand_chip = mtd->priv;
428 struct mxc_nand_host *host = nand_chip->priv;
429 uint32_t tmp;
430
431 tmp = readl(NFC_V3_CONFIG1);
432 tmp &= ~(7 << 4);
433 writel(tmp, NFC_V3_CONFIG1);
434
435 /* transfer data from NFC ram to nand */
436 writel(ops, NFC_V3_LAUNCH);
437
438 wait_op_done(host, false);
439}
440
Sascha Hauer5f973042010-08-06 15:53:06 +0200441static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200442{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200443 struct nand_chip *nand_chip = mtd->priv;
444 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200445 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200446
Sascha Hauer94671142009-10-05 12:14:21 +0200447 if (nfc_is_v1() && mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200448 bufs = 4;
449 else
450 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200451
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200452 for (i = 0; i < bufs; i++) {
453
454 /* NANDFC buffer 0 is used for page read/write */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200455 writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200456
Sascha Hauer1bc99182010-08-06 15:53:08 +0200457 writew(ops, NFC_V1_V2_CONFIG2);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200458
459 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200460 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200461 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200462}
463
Sascha Hauer71ec5152010-08-06 15:53:11 +0200464static void send_read_id_v3(struct mxc_nand_host *host)
465{
466 /* Read ID into main buffer */
467 writel(NFC_ID, NFC_V3_LAUNCH);
468
469 wait_op_done(host, true);
470
471 memcpy(host->data_buf, host->main_area0, 16);
472}
473
Sascha Hauer34f6e152008-09-02 17:16:59 +0200474/* Request the NANDFC to perform a read of the NAND device ID. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200475static void send_read_id_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200476{
477 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200478
479 /* NANDFC buffer 0 is used for device ID output */
Baruch Siachd178e3e2011-03-14 09:01:56 +0200480 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200481
Sascha Hauer1bc99182010-08-06 15:53:08 +0200482 writew(NFC_ID, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200483
484 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200485 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200486
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200487 memcpy(host->data_buf, host->main_area0, 16);
John Ognessf7b66e52010-06-18 18:59:47 +0200488
489 if (this->options & NAND_BUSWIDTH_16) {
490 /* compress the ID info */
491 host->data_buf[1] = host->data_buf[2];
492 host->data_buf[2] = host->data_buf[4];
493 host->data_buf[3] = host->data_buf[6];
494 host->data_buf[4] = host->data_buf[8];
495 host->data_buf[5] = host->data_buf[10];
496 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200497}
498
Sascha Hauer71ec5152010-08-06 15:53:11 +0200499static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200500{
Sascha Hauer71ec5152010-08-06 15:53:11 +0200501 writew(NFC_STATUS, NFC_V3_LAUNCH);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200502 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200503
Sascha Hauer71ec5152010-08-06 15:53:11 +0200504 return readl(NFC_V3_CONFIG1) >> 16;
505}
506
Sascha Hauer34f6e152008-09-02 17:16:59 +0200507/* This function requests the NANDFC to perform a read of the
508 * NAND device status and returns the current status. */
Sascha Hauer5f973042010-08-06 15:53:06 +0200509static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200510{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200511 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200512 uint32_t store;
513 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200514
Baruch Siachd178e3e2011-03-14 09:01:56 +0200515 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200516
517 /*
518 * The device status is stored in main_area0. To
519 * prevent corruption of the buffer save the value
520 * and restore it afterwards.
521 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200522 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200523
Sascha Hauer1bc99182010-08-06 15:53:08 +0200524 writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200525 wait_op_done(host, true);
526
Sascha Hauer34f6e152008-09-02 17:16:59 +0200527 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200528
Sascha Hauer34f6e152008-09-02 17:16:59 +0200529 writel(store, main_buf);
530
531 return ret;
532}
533
534/* This functions is used by upper layer to checks if device is ready */
535static int mxc_nand_dev_ready(struct mtd_info *mtd)
536{
537 /*
538 * NFC handles R/B internally. Therefore, this function
539 * always returns status as ready.
540 */
541 return 1;
542}
543
544static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
545{
546 /*
547 * If HW ECC is enabled, we turn it on during init. There is
548 * no need to enable again here.
549 */
550}
551
Sascha Hauer94f77e52010-08-06 15:53:09 +0200552static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
Sascha Hauer34f6e152008-09-02 17:16:59 +0200553 u_char *read_ecc, u_char *calc_ecc)
554{
555 struct nand_chip *nand_chip = mtd->priv;
556 struct mxc_nand_host *host = nand_chip->priv;
557
558 /*
559 * 1-Bit errors are automatically corrected in HW. No need for
560 * additional correction. 2-Bit errors cannot be corrected by
561 * HW ECC, so we need to return failure
562 */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200563 uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200564
565 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
566 DEBUG(MTD_DEBUG_LEVEL0,
567 "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
568 return -1;
569 }
570
571 return 0;
572}
573
Sascha Hauer94f77e52010-08-06 15:53:09 +0200574static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
575 u_char *read_ecc, u_char *calc_ecc)
576{
577 struct nand_chip *nand_chip = mtd->priv;
578 struct mxc_nand_host *host = nand_chip->priv;
579 u32 ecc_stat, err;
580 int no_subpages = 1;
581 int ret = 0;
582 u8 ecc_bit_mask, err_limit;
583
584 ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
585 err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
586
587 no_subpages = mtd->writesize >> 9;
588
Sascha Hauer71ec5152010-08-06 15:53:11 +0200589 if (nfc_is_v21())
590 ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT);
591 else
592 ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT);
Sascha Hauer94f77e52010-08-06 15:53:09 +0200593
594 do {
595 err = ecc_stat & ecc_bit_mask;
596 if (err > err_limit) {
597 printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
598 return -1;
599 } else {
600 ret += err;
601 }
602 ecc_stat >>= 4;
603 } while (--no_subpages);
604
605 mtd->ecc_stats.corrected += ret;
606 pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
607
608 return ret;
609}
610
Sascha Hauer34f6e152008-09-02 17:16:59 +0200611static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
612 u_char *ecc_code)
613{
614 return 0;
615}
616
617static u_char mxc_nand_read_byte(struct mtd_info *mtd)
618{
619 struct nand_chip *nand_chip = mtd->priv;
620 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200621 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200622
623 /* Check for status request */
624 if (host->status_request)
Sascha Hauer5f973042010-08-06 15:53:06 +0200625 return host->get_dev_status(host) & 0xFF;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200626
Sascha Hauerf8f96082009-06-04 17:12:26 +0200627 ret = *(uint8_t *)(host->data_buf + host->buf_start);
628 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200629
630 return ret;
631}
632
633static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
634{
635 struct nand_chip *nand_chip = mtd->priv;
636 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200637 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200638
Sascha Hauerf8f96082009-06-04 17:12:26 +0200639 ret = *(uint16_t *)(host->data_buf + host->buf_start);
640 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200641
642 return ret;
643}
644
645/* Write data of length len to buffer buf. The data to be
646 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
647 * Operation by the NFC, the data is written to NAND Flash */
648static void mxc_nand_write_buf(struct mtd_info *mtd,
649 const u_char *buf, int len)
650{
651 struct nand_chip *nand_chip = mtd->priv;
652 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200653 u16 col = host->buf_start;
654 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200655
Sascha Hauerf8f96082009-06-04 17:12:26 +0200656 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200657
Sascha Hauerf8f96082009-06-04 17:12:26 +0200658 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200659
Sascha Hauerf8f96082009-06-04 17:12:26 +0200660 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200661}
662
663/* Read the data buffer from the NAND Flash. To read the data from NAND
664 * Flash first the data output cycle is initiated by the NFC, which copies
665 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
666 */
667static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
668{
669 struct nand_chip *nand_chip = mtd->priv;
670 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200671 u16 col = host->buf_start;
672 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200673
Sascha Hauerf8f96082009-06-04 17:12:26 +0200674 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200675
Baruch Siach5d9d9932011-03-02 16:47:55 +0200676 memcpy(buf, host->data_buf + col, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200677
Baruch Siach5d9d9932011-03-02 16:47:55 +0200678 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200679}
680
681/* Used by the upper layer to verify the data in NAND Flash
682 * with the data in the buf. */
683static int mxc_nand_verify_buf(struct mtd_info *mtd,
684 const u_char *buf, int len)
685{
686 return -EFAULT;
687}
688
689/* This function is used by upper layer for select and
690 * deselect of the NAND chip */
691static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
692{
693 struct nand_chip *nand_chip = mtd->priv;
694 struct mxc_nand_host *host = nand_chip->priv;
695
Baruch Siachd178e3e2011-03-14 09:01:56 +0200696 if (chip == -1) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200697 /* Disable the NFC clock */
698 if (host->clk_act) {
699 clk_disable(host->clk);
700 host->clk_act = 0;
701 }
Baruch Siachd178e3e2011-03-14 09:01:56 +0200702 return;
703 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200704
Baruch Siachd178e3e2011-03-14 09:01:56 +0200705 if (!host->clk_act) {
706 /* Enable the NFC clock */
707 clk_enable(host->clk);
708 host->clk_act = 1;
709 }
710
711 if (nfc_is_v21()) {
712 host->active_cs = chip;
713 writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200714 }
715}
716
Sascha Hauerf8f96082009-06-04 17:12:26 +0200717/*
718 * Function to transfer data to/from spare area.
719 */
720static void copy_spare(struct mtd_info *mtd, bool bfrom)
721{
722 struct nand_chip *this = mtd->priv;
723 struct mxc_nand_host *host = this->priv;
724 u16 i, j;
725 u16 n = mtd->writesize >> 9;
726 u8 *d = host->data_buf + mtd->writesize;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200727 u8 *s = host->spare0;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200728 u16 t = host->spare_len;
729
730 j = (mtd->oobsize / n >> 1) << 1;
731
732 if (bfrom) {
733 for (i = 0; i < n - 1; i++)
734 memcpy(d + i * j, s + i * t, j);
735
736 /* the last section */
737 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
738 } else {
739 for (i = 0; i < n - 1; i++)
740 memcpy(&s[i * t], &d[i * j], j);
741
742 /* the last section */
743 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
744 }
745}
746
Sascha Hauera3e65b62009-06-02 11:47:59 +0200747static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200748{
749 struct nand_chip *nand_chip = mtd->priv;
750 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200751
752 /* Write out column address, if necessary */
753 if (column != -1) {
754 /*
755 * MXC NANDFC can only perform full page+spare or
756 * spare-only read/write. When the upper layers
Gilles Espinasse177b2412011-01-09 08:59:49 +0100757 * perform a read/write buf operation, the saved column
758 * address is used to index into the full page.
Sascha Hauer34f6e152008-09-02 17:16:59 +0200759 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200760 host->send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200761 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200762 /* another col addr cycle for 2k page */
Sascha Hauer5f973042010-08-06 15:53:06 +0200763 host->send_addr(host, 0, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200764 }
765
766 /* Write out page address, if necessary */
767 if (page_addr != -1) {
768 /* paddr_0 - p_addr_7 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200769 host->send_addr(host, (page_addr & 0xff), false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200770
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200771 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400772 if (mtd->size >= 0x10000000) {
773 /* paddr_8 - paddr_15 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200774 host->send_addr(host, (page_addr >> 8) & 0xff, false);
775 host->send_addr(host, (page_addr >> 16) & 0xff, true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400776 } else
777 /* paddr_8 - paddr_15 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200778 host->send_addr(host, (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200779 } else {
780 /* One more address cycle for higher density devices */
781 if (mtd->size >= 0x4000000) {
782 /* paddr_8 - paddr_15 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200783 host->send_addr(host, (page_addr >> 8) & 0xff, false);
784 host->send_addr(host, (page_addr >> 16) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200785 } else
786 /* paddr_8 - paddr_15 */
Sascha Hauer5f973042010-08-06 15:53:06 +0200787 host->send_addr(host, (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200788 }
789 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200790}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200791
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200792/*
793 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
794 * on how much oob the nand chip has. For 8bit ecc we need at least
795 * 26 bytes of oob data per 512 byte block.
796 */
797static int get_eccsize(struct mtd_info *mtd)
798{
799 int oobbytes_per_512 = 0;
800
801 oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
802
803 if (oobbytes_per_512 < 26)
804 return 4;
805 else
806 return 8;
807}
808
Sascha Hauer5f973042010-08-06 15:53:06 +0200809static void preset_v1_v2(struct mtd_info *mtd)
Ivo Claryssed4840182010-04-08 16:14:44 +0200810{
811 struct nand_chip *nand_chip = mtd->priv;
812 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200813 uint16_t config1 = 0;
Ivo Claryssed4840182010-04-08 16:14:44 +0200814
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200815 if (nand_chip->ecc.mode == NAND_ECC_HW)
816 config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
817
818 if (nfc_is_v21())
819 config1 |= NFC_V2_CONFIG1_FP_INT;
820
821 if (!cpu_is_mx21())
822 config1 |= NFC_V1_V2_CONFIG1_INT_MSK;
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200823
824 if (nfc_is_v21() && mtd->writesize) {
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200825 uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
826
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200827 host->eccsize = get_eccsize(mtd);
828 if (host->eccsize == 4)
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200829 config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
830
831 config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
Sascha Hauer6e85dfd2010-08-06 15:53:10 +0200832 } else {
833 host->eccsize = 1;
834 }
835
Sascha Hauerb8db2f52010-08-09 15:04:19 +0200836 writew(config1, NFC_V1_V2_CONFIG1);
Ivo Claryssed4840182010-04-08 16:14:44 +0200837 /* preset operation */
838
839 /* Unlock the internal RAM Buffer */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200840 writew(0x2, NFC_V1_V2_CONFIG);
Ivo Claryssed4840182010-04-08 16:14:44 +0200841
842 /* Blocks to be unlocked */
843 if (nfc_is_v21()) {
Baruch Siachd178e3e2011-03-14 09:01:56 +0200844 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0);
845 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1);
846 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2);
847 writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3);
848 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0);
849 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1);
850 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2);
851 writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3);
Ivo Claryssed4840182010-04-08 16:14:44 +0200852 } else if (nfc_is_v1()) {
Sascha Hauer1bc99182010-08-06 15:53:08 +0200853 writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
854 writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
Ivo Claryssed4840182010-04-08 16:14:44 +0200855 } else
856 BUG();
857
858 /* Unlock Block Command for given address range */
Sascha Hauer1bc99182010-08-06 15:53:08 +0200859 writew(0x4, NFC_V1_V2_WRPROT);
Ivo Claryssed4840182010-04-08 16:14:44 +0200860}
861
Sascha Hauer71ec5152010-08-06 15:53:11 +0200862static void preset_v3(struct mtd_info *mtd)
863{
864 struct nand_chip *chip = mtd->priv;
865 struct mxc_nand_host *host = chip->priv;
866 uint32_t config2, config3;
867 int i, addr_phases;
868
869 writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
870 writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
871
872 /* Unlock the internal RAM Buffer */
873 writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
874 NFC_V3_WRPROT);
875
876 /* Blocks to be unlocked */
877 for (i = 0; i < NAND_MAX_CHIPS; i++)
878 writel(0x0 | (0xffff << 16),
879 NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
880
881 writel(0, NFC_V3_IPC);
882
883 config2 = NFC_V3_CONFIG2_ONE_CYCLE |
884 NFC_V3_CONFIG2_2CMD_PHASES |
885 NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
886 NFC_V3_CONFIG2_ST_CMD(0x70) |
Sascha Hauer63f14742010-10-18 10:16:26 +0200887 NFC_V3_CONFIG2_INT_MSK |
Sascha Hauer71ec5152010-08-06 15:53:11 +0200888 NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
889
890 if (chip->ecc.mode == NAND_ECC_HW)
891 config2 |= NFC_V3_CONFIG2_ECC_EN;
892
893 addr_phases = fls(chip->pagemask) >> 3;
894
895 if (mtd->writesize == 2048) {
896 config2 |= NFC_V3_CONFIG2_PS_2048;
897 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
898 } else if (mtd->writesize == 4096) {
899 config2 |= NFC_V3_CONFIG2_PS_4096;
900 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
901 } else {
902 config2 |= NFC_V3_CONFIG2_PS_512;
903 config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
904 }
905
906 if (mtd->writesize) {
907 config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
908 host->eccsize = get_eccsize(mtd);
909 if (host->eccsize == 8)
910 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
911 }
912
913 writel(config2, NFC_V3_CONFIG2);
914
915 config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
916 NFC_V3_CONFIG3_NO_SDMA |
917 NFC_V3_CONFIG3_RBB_MODE |
918 NFC_V3_CONFIG3_SBB(6) | /* Reset default */
919 NFC_V3_CONFIG3_ADD_OP(0);
920
921 if (!(chip->options & NAND_BUSWIDTH_16))
922 config3 |= NFC_V3_CONFIG3_FW8;
923
924 writel(config3, NFC_V3_CONFIG3);
925
926 writel(0, NFC_V3_DELAY_LINE);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200927}
928
Sascha Hauer34f6e152008-09-02 17:16:59 +0200929/* Used by the upper layer to write command to NAND Flash for
930 * different operations to be carried out on NAND Flash */
931static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
932 int column, int page_addr)
933{
934 struct nand_chip *nand_chip = mtd->priv;
935 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200936
937 DEBUG(MTD_DEBUG_LEVEL3,
938 "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
939 command, column, page_addr);
940
941 /* Reset command state information */
942 host->status_request = false;
943
944 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200945 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +0200946 case NAND_CMD_RESET:
Sascha Hauer5f973042010-08-06 15:53:06 +0200947 host->preset(mtd);
948 host->send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +0200949 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200950
Sascha Hauer34f6e152008-09-02 17:16:59 +0200951 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +0200952 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200953 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +0200954
Sascha Hauer5f973042010-08-06 15:53:06 +0200955 host->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +0200956 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200957 break;
958
Sascha Hauer34f6e152008-09-02 17:16:59 +0200959 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +0200960 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +0200961 if (command == NAND_CMD_READ0)
962 host->buf_start = column;
963 else
964 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200965
Sascha Hauer5ea32022010-04-27 15:24:01 +0200966 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +0200967
Sascha Hauer5f973042010-08-06 15:53:06 +0200968 host->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +0200969 mxc_do_addr_cycle(mtd, column, page_addr);
970
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200971 if (mtd->writesize > 512)
Sascha Hauer5f973042010-08-06 15:53:06 +0200972 host->send_cmd(host, NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200973
Sascha Hauer5f973042010-08-06 15:53:06 +0200974 host->send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +0200975
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200976 memcpy(host->data_buf, host->main_area0, mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +0200977 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200978 break;
979
Sascha Hauer34f6e152008-09-02 17:16:59 +0200980 case NAND_CMD_SEQIN:
Sascha Hauer5ea32022010-04-27 15:24:01 +0200981 if (column >= mtd->writesize)
982 /* call ourself to read a page */
983 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200984
Sascha Hauer5ea32022010-04-27 15:24:01 +0200985 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +0200986
Sascha Hauer5f973042010-08-06 15:53:06 +0200987 host->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +0200988 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200989 break;
990
991 case NAND_CMD_PAGEPROG:
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200992 memcpy(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200993 copy_spare(mtd, false);
Sascha Hauer5f973042010-08-06 15:53:06 +0200994 host->send_page(mtd, NFC_INPUT);
995 host->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +0200996 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200997 break;
998
Sascha Hauer34f6e152008-09-02 17:16:59 +0200999 case NAND_CMD_READID:
Sascha Hauer5f973042010-08-06 15:53:06 +02001000 host->send_cmd(host, command, true);
Sascha Hauer89121a62009-06-04 17:18:01 +02001001 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer5f973042010-08-06 15:53:06 +02001002 host->send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +02001003 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001004 break;
1005
Sascha Hauer89121a62009-06-04 17:18:01 +02001006 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +02001007 case NAND_CMD_ERASE2:
Sascha Hauer5f973042010-08-06 15:53:06 +02001008 host->send_cmd(host, command, false);
Sascha Hauer89121a62009-06-04 17:18:01 +02001009 mxc_do_addr_cycle(mtd, column, page_addr);
1010
Sascha Hauer34f6e152008-09-02 17:16:59 +02001011 break;
1012 }
1013}
1014
Sascha Hauerf1372052009-10-21 14:25:27 +02001015/*
1016 * The generic flash bbt decriptors overlap with our ecc
1017 * hardware, so define some i.MX specific ones.
1018 */
1019static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
1020static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
1021
1022static struct nand_bbt_descr bbt_main_descr = {
1023 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1024 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1025 .offs = 0,
1026 .len = 4,
1027 .veroffs = 4,
1028 .maxblocks = 4,
1029 .pattern = bbt_pattern,
1030};
1031
1032static struct nand_bbt_descr bbt_mirror_descr = {
1033 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
1034 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
1035 .offs = 0,
1036 .len = 4,
1037 .veroffs = 4,
1038 .maxblocks = 4,
1039 .pattern = mirror_pattern,
1040};
1041
Sascha Hauer34f6e152008-09-02 17:16:59 +02001042static int __init mxcnd_probe(struct platform_device *pdev)
1043{
1044 struct nand_chip *this;
1045 struct mtd_info *mtd;
1046 struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
1047 struct mxc_nand_host *host;
1048 struct resource *res;
Fabio Estevam2ebf0622010-11-23 17:02:13 -02001049 int err = 0, __maybe_unused nr_parts = 0;
Sascha Hauer94671142009-10-05 12:14:21 +02001050 struct nand_ecclayout *oob_smallpage, *oob_largepage;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001051
1052 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +02001053 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
1054 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001055 if (!host)
1056 return -ENOMEM;
1057
Sascha Hauerf8f96082009-06-04 17:12:26 +02001058 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +02001059
Sascha Hauer34f6e152008-09-02 17:16:59 +02001060 host->dev = &pdev->dev;
1061 /* structures must be linked */
1062 this = &host->nand;
1063 mtd = &host->mtd;
1064 mtd->priv = this;
1065 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -07001066 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +02001067 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001068
1069 /* 50 us command delay time */
1070 this->chip_delay = 5;
1071
1072 this->priv = host;
1073 this->dev_ready = mxc_nand_dev_ready;
1074 this->cmdfunc = mxc_nand_command;
1075 this->select_chip = mxc_nand_select_chip;
1076 this->read_byte = mxc_nand_read_byte;
1077 this->read_word = mxc_nand_read_word;
1078 this->write_buf = mxc_nand_write_buf;
1079 this->read_buf = mxc_nand_read_buf;
1080 this->verify_buf = mxc_nand_verify_buf;
1081
Sascha Hauere65fb002009-02-16 14:29:10 +01001082 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +04001083 if (IS_ERR(host->clk)) {
1084 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001085 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +04001086 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001087
1088 clk_enable(host->clk);
1089 host->clk_act = 1;
1090
1091 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1092 if (!res) {
1093 err = -ENODEV;
1094 goto eres;
1095 }
1096
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001097 host->base = ioremap(res->start, resource_size(res));
1098 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +04001099 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001100 goto eres;
1101 }
1102
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001103 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +02001104
Sascha Hauer5f973042010-08-06 15:53:06 +02001105 if (nfc_is_v1() || nfc_is_v21()) {
1106 host->preset = preset_v1_v2;
1107 host->send_cmd = send_cmd_v1_v2;
1108 host->send_addr = send_addr_v1_v2;
1109 host->send_page = send_page_v1_v2;
1110 host->send_read_id = send_read_id_v1_v2;
1111 host->get_dev_status = get_dev_status_v1_v2;
Sascha Hauer7aaf28a2010-08-06 15:53:07 +02001112 host->check_int = check_int_v1_v2;
Sascha Hauer63f14742010-10-18 10:16:26 +02001113 if (cpu_is_mx21())
1114 host->irq_control = irq_control_mx21;
1115 else
1116 host->irq_control = irq_control_v1_v2;
Sascha Hauer5f973042010-08-06 15:53:06 +02001117 }
Sascha Hauer94671142009-10-05 12:14:21 +02001118
1119 if (nfc_is_v21()) {
Sascha Hauer938cf992010-08-06 15:53:04 +02001120 host->regs = host->base + 0x1e00;
Sascha Hauer94671142009-10-05 12:14:21 +02001121 host->spare0 = host->base + 0x1000;
1122 host->spare_len = 64;
1123 oob_smallpage = &nandv2_hw_eccoob_smallpage;
1124 oob_largepage = &nandv2_hw_eccoob_largepage;
Ivo Claryssed4840182010-04-08 16:14:44 +02001125 this->ecc.bytes = 9;
Sascha Hauer94671142009-10-05 12:14:21 +02001126 } else if (nfc_is_v1()) {
Sascha Hauer938cf992010-08-06 15:53:04 +02001127 host->regs = host->base + 0xe00;
Sascha Hauer94671142009-10-05 12:14:21 +02001128 host->spare0 = host->base + 0x800;
1129 host->spare_len = 16;
1130 oob_smallpage = &nandv1_hw_eccoob_smallpage;
1131 oob_largepage = &nandv1_hw_eccoob_largepage;
Sascha Hauer94671142009-10-05 12:14:21 +02001132 this->ecc.bytes = 3;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001133 host->eccsize = 1;
1134 } else if (nfc_is_v3_2()) {
1135 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1136 if (!res) {
1137 err = -ENODEV;
1138 goto eirq;
1139 }
1140 host->regs_ip = ioremap(res->start, resource_size(res));
1141 if (!host->regs_ip) {
1142 err = -ENOMEM;
1143 goto eirq;
1144 }
1145 host->regs_axi = host->base + 0x1e00;
1146 host->spare0 = host->base + 0x1000;
1147 host->spare_len = 64;
1148 host->preset = preset_v3;
1149 host->send_cmd = send_cmd_v3;
1150 host->send_addr = send_addr_v3;
1151 host->send_page = send_page_v3;
1152 host->send_read_id = send_read_id_v3;
1153 host->check_int = check_int_v3;
1154 host->get_dev_status = get_dev_status_v3;
Sascha Hauer63f14742010-10-18 10:16:26 +02001155 host->irq_control = irq_control_v3;
Sascha Hauer71ec5152010-08-06 15:53:11 +02001156 oob_smallpage = &nandv2_hw_eccoob_smallpage;
1157 oob_largepage = &nandv2_hw_eccoob_largepage;
Sascha Hauer94671142009-10-05 12:14:21 +02001158 } else
1159 BUG();
Sascha Hauer34f6e152008-09-02 17:16:59 +02001160
Sascha Hauer13e1add2009-10-21 10:39:05 +02001161 this->ecc.size = 512;
Sascha Hauer94671142009-10-05 12:14:21 +02001162 this->ecc.layout = oob_smallpage;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001163
1164 if (pdata->hw_ecc) {
1165 this->ecc.calculate = mxc_nand_calculate_ecc;
1166 this->ecc.hwctl = mxc_nand_enable_hwecc;
Sascha Hauer94f77e52010-08-06 15:53:09 +02001167 if (nfc_is_v1())
1168 this->ecc.correct = mxc_nand_correct_data_v1;
1169 else
1170 this->ecc.correct = mxc_nand_correct_data_v2_v3;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001171 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001172 } else {
1173 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001174 }
1175
Sascha Hauer34f6e152008-09-02 17:16:59 +02001176 /* NAND bus width determines access funtions used by upper layer */
Sascha Hauer13e1add2009-10-21 10:39:05 +02001177 if (pdata->width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001178 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +02001179
Sascha Hauerf1372052009-10-21 14:25:27 +02001180 if (pdata->flash_bbt) {
1181 this->bbt_td = &bbt_main_descr;
1182 this->bbt_md = &bbt_mirror_descr;
1183 /* update flash based bbt */
1184 this->options |= NAND_USE_FLASH_BBT;
Sascha Hauer34f6e152008-09-02 17:16:59 +02001185 }
1186
Sascha Hauer63f14742010-10-18 10:16:26 +02001187 init_completion(&host->op_completion);
Ivo Claryssed4840182010-04-08 16:14:44 +02001188
1189 host->irq = platform_get_irq(pdev, 0);
1190
Sascha Hauer63f14742010-10-18 10:16:26 +02001191 /*
1192 * mask the interrupt. For i.MX21 explicitely call
1193 * irq_control_v1_v2 to use the mask bit. We can't call
1194 * disable_irq_nosync() for an interrupt we do not own yet.
1195 */
1196 if (cpu_is_mx21())
1197 irq_control_v1_v2(host, 0);
1198 else
1199 host->irq_control(host, 0);
1200
Ivo Claryssea47bfd22010-04-08 16:16:51 +02001201 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +02001202 if (err)
1203 goto eirq;
1204
Sascha Hauer63f14742010-10-18 10:16:26 +02001205 host->irq_control(host, 0);
1206
1207 /*
1208 * Now that the interrupt is disabled make sure the interrupt
1209 * mask bit is cleared on i.MX21. Otherwise we can't read
1210 * the interrupt status bit on this machine.
1211 */
1212 if (cpu_is_mx21())
1213 irq_control_v1_v2(host, 1);
1214
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001215 /* first scan to find the device and get the page size */
Baruch Siachd178e3e2011-03-14 09:01:56 +02001216 if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001217 err = -ENXIO;
1218 goto escan;
1219 }
Sascha Hauer34f6e152008-09-02 17:16:59 +02001220
Sascha Hauer6e85dfd2010-08-06 15:53:10 +02001221 /* Call preset again, with correct writesize this time */
1222 host->preset(mtd);
1223
Sascha Hauer2d69c7f2009-10-05 11:24:02 +02001224 if (mtd->writesize == 2048)
Sascha Hauer94671142009-10-05 12:14:21 +02001225 this->ecc.layout = oob_largepage;
Baruch Siach2c1c5f12011-03-09 16:12:20 +02001226 if (nfc_is_v21() && mtd->writesize == 4096)
1227 this->ecc.layout = &nandv2_hw_eccoob_4k;
Vladimir Barinovbd3fd622009-05-25 13:06:17 +04001228
1229 /* second phase scan */
1230 if (nand_scan_tail(mtd)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +02001231 err = -ENXIO;
1232 goto escan;
1233 }
1234
1235 /* Register the partitions */
1236#ifdef CONFIG_MTD_PARTITIONS
1237 nr_parts =
1238 parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
1239 if (nr_parts > 0)
1240 add_mtd_partitions(mtd, host->parts, nr_parts);
Baruch Siachcce02462010-05-31 08:49:40 +03001241 else if (pdata->parts)
1242 add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001243 else
1244#endif
1245 {
1246 pr_info("Registering %s as whole device\n", mtd->name);
1247 add_mtd_device(mtd);
1248 }
1249
1250 platform_set_drvdata(pdev, host);
1251
1252 return 0;
1253
1254escan:
Magnus Liljab258fd82009-05-08 21:57:47 +02001255 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001256eirq:
Sascha Hauer71ec5152010-08-06 15:53:11 +02001257 if (host->regs_ip)
1258 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001259 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001260eres:
1261 clk_put(host->clk);
1262eclk:
1263 kfree(host);
1264
1265 return err;
1266}
1267
Uwe Kleine-König51eeb872009-12-07 09:44:05 +00001268static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +02001269{
1270 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1271
1272 clk_put(host->clk);
1273
1274 platform_set_drvdata(pdev, NULL);
1275
1276 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +02001277 free_irq(host->irq, host);
Sascha Hauer71ec5152010-08-06 15:53:11 +02001278 if (host->regs_ip)
1279 iounmap(host->regs_ip);
Sascha Hauerc6de7e12009-10-05 11:14:35 +02001280 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001281 kfree(host);
1282
1283 return 0;
1284}
1285
Sascha Hauer34f6e152008-09-02 17:16:59 +02001286static struct platform_driver mxcnd_driver = {
1287 .driver = {
1288 .name = DRIVER_NAME,
Eric Bénard04dd0d32010-06-17 20:59:04 +02001289 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +01001290 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +02001291};
1292
1293static int __init mxc_nd_init(void)
1294{
Vladimir Barinov8541c112009-04-23 15:47:22 +04001295 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +02001296}
1297
1298static void __exit mxc_nd_cleanup(void)
1299{
1300 /* Unregister the device structure */
1301 platform_driver_unregister(&mxcnd_driver);
1302}
1303
1304module_init(mxc_nd_init);
1305module_exit(mxc_nd_cleanup);
1306
1307MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1308MODULE_DESCRIPTION("MXC NAND MTD driver");
1309MODULE_LICENSE("GPL");