blob: b6aa7e3a967a936be9cc9d424fb9054021c42641 [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>
33
34#include <asm/mach/flash.h>
35#include <mach/mxc_nand.h>
Sascha Hauer94671142009-10-05 12:14:21 +020036#include <mach/hardware.h>
Sascha Hauer34f6e152008-09-02 17:16:59 +020037
38#define DRIVER_NAME "mxc_nand"
39
Sascha Hauer94671142009-10-05 12:14:21 +020040#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
Ivo Claryssea47bfd22010-04-08 16:16:51 +020041#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
Sascha Hauer94671142009-10-05 12:14:21 +020042
Sascha Hauer34f6e152008-09-02 17:16:59 +020043/* Addresses for NFC registers */
Sascha Hauer938cf992010-08-06 15:53:04 +020044#define NFC_BUF_SIZE 0x00
45#define NFC_BUF_ADDR 0x04
46#define NFC_FLASH_ADDR 0x06
47#define NFC_FLASH_CMD 0x08
48#define NFC_CONFIG 0x0a
49#define NFC_ECC_STATUS_RESULT 0x0c
50#define NFC_RSLTMAIN_AREA 0x0e
51#define NFC_RSLTSPARE_AREA 0x10
52#define NFC_WRPROT 0x12
53#define NFC_V1_UNLOCKSTART_BLKADDR 0x14
54#define NFC_V1_UNLOCKEND_BLKADDR 0x16
55#define NFC_V21_UNLOCKSTART_BLKADDR 0x20
56#define NFC_V21_UNLOCKEND_BLKADDR 0x22
57#define NFC_NF_WRPRST 0x18
58#define NFC_CONFIG1 0x1a
59#define NFC_CONFIG2 0x1c
Sascha Hauer34f6e152008-09-02 17:16:59 +020060
Sascha Hauer34f6e152008-09-02 17:16:59 +020061/* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
62 * for Command operation */
63#define NFC_CMD 0x1
64
65/* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
66 * for Address operation */
67#define NFC_ADDR 0x2
68
69/* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
70 * for Input operation */
71#define NFC_INPUT 0x4
72
73/* Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
74 * for Data Output operation */
75#define NFC_OUTPUT 0x8
76
77/* Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
78 * for Read ID operation */
79#define NFC_ID 0x10
80
81/* Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
82 * for Read Status operation */
83#define NFC_STATUS 0x20
84
85/* Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
86 * Status operation */
87#define NFC_INT 0x8000
88
89#define NFC_SP_EN (1 << 2)
90#define NFC_ECC_EN (1 << 3)
91#define NFC_INT_MSK (1 << 4)
92#define NFC_BIG (1 << 5)
93#define NFC_RST (1 << 6)
94#define NFC_CE (1 << 7)
95#define NFC_ONE_CYCLE (1 << 8)
96
97struct mxc_nand_host {
98 struct mtd_info mtd;
99 struct nand_chip nand;
100 struct mtd_partition *parts;
101 struct device *dev;
102
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200103 void *spare0;
104 void *main_area0;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200105
106 void __iomem *base;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200107 void __iomem *regs;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200108 int status_request;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200109 struct clk *clk;
110 int clk_act;
111 int irq;
112
113 wait_queue_head_t irq_waitq;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200114
115 uint8_t *data_buf;
116 unsigned int buf_start;
117 int spare_len;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200118};
119
Sascha Hauer34f6e152008-09-02 17:16:59 +0200120/* OOB placement block for use with hardware ecc generation */
Sascha Hauer94671142009-10-05 12:14:21 +0200121static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200122 .eccbytes = 5,
123 .eccpos = {6, 7, 8, 9, 10},
Sascha Hauer8c1fd892009-10-21 10:22:01 +0200124 .oobfree = {{0, 5}, {12, 4}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200125};
126
Sascha Hauer94671142009-10-05 12:14:21 +0200127static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400128 .eccbytes = 20,
129 .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
130 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
131 .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200132};
133
Sascha Hauer94671142009-10-05 12:14:21 +0200134/* OOB description for 512 byte pages with 16 byte OOB */
135static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
136 .eccbytes = 1 * 9,
137 .eccpos = {
138 7, 8, 9, 10, 11, 12, 13, 14, 15
139 },
140 .oobfree = {
141 {.offset = 0, .length = 5}
142 }
143};
144
145/* OOB description for 2048 byte pages with 64 byte OOB */
146static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
147 .eccbytes = 4 * 9,
148 .eccpos = {
149 7, 8, 9, 10, 11, 12, 13, 14, 15,
150 23, 24, 25, 26, 27, 28, 29, 30, 31,
151 39, 40, 41, 42, 43, 44, 45, 46, 47,
152 55, 56, 57, 58, 59, 60, 61, 62, 63
153 },
154 .oobfree = {
155 {.offset = 2, .length = 4},
156 {.offset = 16, .length = 7},
157 {.offset = 32, .length = 7},
158 {.offset = 48, .length = 7}
159 }
160};
161
Sascha Hauer34f6e152008-09-02 17:16:59 +0200162#ifdef CONFIG_MTD_PARTITIONS
163static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
164#endif
165
166static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
167{
168 struct mxc_nand_host *host = dev_id;
169
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200170 disable_irq_nosync(irq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200171
172 wake_up(&host->irq_waitq);
173
174 return IRQ_HANDLED;
175}
176
177/* This function polls the NANDFC to wait for the basic operation to
178 * complete by checking the INT bit of config2 register.
179 */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200180static void wait_op_done(struct mxc_nand_host *host, int useirq)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200181{
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200182 uint16_t tmp;
183 int max_retries = 8000;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200184
185 if (useirq) {
186 if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
187
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200188 enable_irq(host->irq);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200189
190 wait_event(host->irq_waitq,
191 readw(host->regs + NFC_CONFIG2) & NFC_INT);
192
193 tmp = readw(host->regs + NFC_CONFIG2);
194 tmp &= ~NFC_INT;
195 writew(tmp, host->regs + NFC_CONFIG2);
196 }
197 } else {
198 while (max_retries-- > 0) {
199 if (readw(host->regs + NFC_CONFIG2) & NFC_INT) {
200 tmp = readw(host->regs + NFC_CONFIG2);
201 tmp &= ~NFC_INT;
202 writew(tmp, host->regs + NFC_CONFIG2);
203 break;
204 }
205 udelay(1);
206 }
Roel Kluin43950a62009-06-04 16:24:59 +0200207 if (max_retries < 0)
Sascha Hauer62465492009-06-04 15:57:20 +0200208 DEBUG(MTD_DEBUG_LEVEL0, "%s: INT not set\n",
209 __func__);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200210 }
211}
212
213/* This function issues the specified command to the NAND device and
214 * waits for completion. */
215static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
216{
217 DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
218
219 writew(cmd, host->regs + NFC_FLASH_CMD);
220 writew(NFC_CMD, host->regs + NFC_CONFIG2);
221
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200222 if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
223 int max_retries = 100;
224 /* Reset completion is indicated by NFC_CONFIG2 */
225 /* being set to 0 */
226 while (max_retries-- > 0) {
227 if (readw(host->regs + NFC_CONFIG2) == 0) {
228 break;
229 }
230 udelay(1);
231 }
232 if (max_retries < 0)
233 DEBUG(MTD_DEBUG_LEVEL0, "%s: RESET failed\n",
234 __func__);
235 } else {
236 /* Wait for operation to complete */
237 wait_op_done(host, useirq);
238 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200239}
240
241/* This function sends an address (or partial address) to the
242 * NAND device. The address is used to select the source/destination for
243 * a NAND command. */
244static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
245{
246 DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
247
248 writew(addr, host->regs + NFC_FLASH_ADDR);
249 writew(NFC_ADDR, host->regs + NFC_CONFIG2);
250
251 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200252 wait_op_done(host, islast);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200253}
254
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200255static void send_page(struct mtd_info *mtd, unsigned int ops)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200256{
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200257 struct nand_chip *nand_chip = mtd->priv;
258 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200259 int bufs, i;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200260
Sascha Hauer94671142009-10-05 12:14:21 +0200261 if (nfc_is_v1() && mtd->writesize > 512)
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200262 bufs = 4;
263 else
264 bufs = 1;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200265
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200266 for (i = 0; i < bufs; i++) {
267
268 /* NANDFC buffer 0 is used for page read/write */
269 writew(i, host->regs + NFC_BUF_ADDR);
270
271 writew(ops, host->regs + NFC_CONFIG2);
272
273 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200274 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200275 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200276}
277
278/* Request the NANDFC to perform a read of the NAND device ID. */
279static void send_read_id(struct mxc_nand_host *host)
280{
281 struct nand_chip *this = &host->nand;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200282
283 /* NANDFC buffer 0 is used for device ID output */
284 writew(0x0, host->regs + NFC_BUF_ADDR);
285
Sascha Hauer34f6e152008-09-02 17:16:59 +0200286 writew(NFC_ID, host->regs + NFC_CONFIG2);
287
288 /* Wait for operation to complete */
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200289 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200290
291 if (this->options & NAND_BUSWIDTH_16) {
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200292 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200293 /* compress the ID info */
294 writeb(readb(main_buf + 2), main_buf + 1);
295 writeb(readb(main_buf + 4), main_buf + 2);
296 writeb(readb(main_buf + 6), main_buf + 3);
297 writeb(readb(main_buf + 8), main_buf + 4);
298 writeb(readb(main_buf + 10), main_buf + 5);
299 }
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200300 memcpy(host->data_buf, host->main_area0, 16);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200301}
302
303/* This function requests the NANDFC to perform a read of the
304 * NAND device status and returns the current status. */
305static uint16_t get_dev_status(struct mxc_nand_host *host)
306{
Sascha Hauerc29c6072010-08-06 15:53:05 +0200307 void __iomem *main_buf = host->main_area0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200308 uint32_t store;
Sascha Hauerf06368f2009-10-05 17:18:42 +0200309 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200310
Sascha Hauerc29c6072010-08-06 15:53:05 +0200311 writew(0x0, NFC_V1_V2_BUF_ADDR);
312
313 /*
314 * The device status is stored in main_area0. To
315 * prevent corruption of the buffer save the value
316 * and restore it afterwards.
317 */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200318 store = readl(main_buf);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200319
Sascha Hauer34f6e152008-09-02 17:16:59 +0200320 writew(NFC_STATUS, host->regs + NFC_CONFIG2);
Sascha Hauerc110eaf2009-10-21 16:01:02 +0200321 wait_op_done(host, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200322
Sascha Hauer34f6e152008-09-02 17:16:59 +0200323 ret = readw(main_buf);
Sascha Hauerc29c6072010-08-06 15:53:05 +0200324
Sascha Hauer34f6e152008-09-02 17:16:59 +0200325 writel(store, main_buf);
326
327 return ret;
328}
329
330/* This functions is used by upper layer to checks if device is ready */
331static int mxc_nand_dev_ready(struct mtd_info *mtd)
332{
333 /*
334 * NFC handles R/B internally. Therefore, this function
335 * always returns status as ready.
336 */
337 return 1;
338}
339
340static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
341{
342 /*
343 * If HW ECC is enabled, we turn it on during init. There is
344 * no need to enable again here.
345 */
346}
347
348static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
349 u_char *read_ecc, u_char *calc_ecc)
350{
351 struct nand_chip *nand_chip = mtd->priv;
352 struct mxc_nand_host *host = nand_chip->priv;
353
354 /*
355 * 1-Bit errors are automatically corrected in HW. No need for
356 * additional correction. 2-Bit errors cannot be corrected by
357 * HW ECC, so we need to return failure
358 */
359 uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
360
361 if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
362 DEBUG(MTD_DEBUG_LEVEL0,
363 "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
364 return -1;
365 }
366
367 return 0;
368}
369
370static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
371 u_char *ecc_code)
372{
373 return 0;
374}
375
376static u_char mxc_nand_read_byte(struct mtd_info *mtd)
377{
378 struct nand_chip *nand_chip = mtd->priv;
379 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200380 uint8_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200381
382 /* Check for status request */
383 if (host->status_request)
384 return get_dev_status(host) & 0xFF;
385
Sascha Hauerf8f96082009-06-04 17:12:26 +0200386 ret = *(uint8_t *)(host->data_buf + host->buf_start);
387 host->buf_start++;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200388
389 return ret;
390}
391
392static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
393{
394 struct nand_chip *nand_chip = mtd->priv;
395 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200396 uint16_t ret;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200397
Sascha Hauerf8f96082009-06-04 17:12:26 +0200398 ret = *(uint16_t *)(host->data_buf + host->buf_start);
399 host->buf_start += 2;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200400
401 return ret;
402}
403
404/* Write data of length len to buffer buf. The data to be
405 * written on NAND Flash is first copied to RAMbuffer. After the Data Input
406 * Operation by the NFC, the data is written to NAND Flash */
407static void mxc_nand_write_buf(struct mtd_info *mtd,
408 const u_char *buf, int len)
409{
410 struct nand_chip *nand_chip = mtd->priv;
411 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200412 u16 col = host->buf_start;
413 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200414
Sascha Hauerf8f96082009-06-04 17:12:26 +0200415 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200416
Sascha Hauerf8f96082009-06-04 17:12:26 +0200417 memcpy(host->data_buf + col, buf, n);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200418
Sascha Hauerf8f96082009-06-04 17:12:26 +0200419 host->buf_start += n;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200420}
421
422/* Read the data buffer from the NAND Flash. To read the data from NAND
423 * Flash first the data output cycle is initiated by the NFC, which copies
424 * the data to RAMbuffer. This data of length len is then copied to buffer buf.
425 */
426static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
427{
428 struct nand_chip *nand_chip = mtd->priv;
429 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200430 u16 col = host->buf_start;
431 int n = mtd->oobsize + mtd->writesize - col;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200432
Sascha Hauerf8f96082009-06-04 17:12:26 +0200433 n = min(n, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200434
Sascha Hauerf8f96082009-06-04 17:12:26 +0200435 memcpy(buf, host->data_buf + col, len);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200436
Sascha Hauerf8f96082009-06-04 17:12:26 +0200437 host->buf_start += len;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200438}
439
440/* Used by the upper layer to verify the data in NAND Flash
441 * with the data in the buf. */
442static int mxc_nand_verify_buf(struct mtd_info *mtd,
443 const u_char *buf, int len)
444{
445 return -EFAULT;
446}
447
448/* This function is used by upper layer for select and
449 * deselect of the NAND chip */
450static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
451{
452 struct nand_chip *nand_chip = mtd->priv;
453 struct mxc_nand_host *host = nand_chip->priv;
454
Sascha Hauer34f6e152008-09-02 17:16:59 +0200455 switch (chip) {
456 case -1:
457 /* Disable the NFC clock */
458 if (host->clk_act) {
459 clk_disable(host->clk);
460 host->clk_act = 0;
461 }
462 break;
463 case 0:
464 /* Enable the NFC clock */
465 if (!host->clk_act) {
466 clk_enable(host->clk);
467 host->clk_act = 1;
468 }
469 break;
470
471 default:
472 break;
473 }
474}
475
Sascha Hauerf8f96082009-06-04 17:12:26 +0200476/*
477 * Function to transfer data to/from spare area.
478 */
479static void copy_spare(struct mtd_info *mtd, bool bfrom)
480{
481 struct nand_chip *this = mtd->priv;
482 struct mxc_nand_host *host = this->priv;
483 u16 i, j;
484 u16 n = mtd->writesize >> 9;
485 u8 *d = host->data_buf + mtd->writesize;
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200486 u8 *s = host->spare0;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200487 u16 t = host->spare_len;
488
489 j = (mtd->oobsize / n >> 1) << 1;
490
491 if (bfrom) {
492 for (i = 0; i < n - 1; i++)
493 memcpy(d + i * j, s + i * t, j);
494
495 /* the last section */
496 memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
497 } else {
498 for (i = 0; i < n - 1; i++)
499 memcpy(&s[i * t], &d[i * j], j);
500
501 /* the last section */
502 memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
503 }
504}
505
Sascha Hauera3e65b62009-06-02 11:47:59 +0200506static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200507{
508 struct nand_chip *nand_chip = mtd->priv;
509 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200510
511 /* Write out column address, if necessary */
512 if (column != -1) {
513 /*
514 * MXC NANDFC can only perform full page+spare or
515 * spare-only read/write. When the upper layers
516 * layers perform a read/write buf operation,
Daniel Mack3ad2f3f2010-02-03 08:01:28 +0800517 * we will used the saved column address to index into
Sascha Hauer34f6e152008-09-02 17:16:59 +0200518 * the full page.
519 */
520 send_addr(host, 0, page_addr == -1);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200521 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200522 /* another col addr cycle for 2k page */
523 send_addr(host, 0, false);
524 }
525
526 /* Write out page address, if necessary */
527 if (page_addr != -1) {
528 /* paddr_0 - p_addr_7 */
529 send_addr(host, (page_addr & 0xff), false);
530
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200531 if (mtd->writesize > 512) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400532 if (mtd->size >= 0x10000000) {
533 /* paddr_8 - paddr_15 */
534 send_addr(host, (page_addr >> 8) & 0xff, false);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200535 send_addr(host, (page_addr >> 16) & 0xff, true);
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400536 } else
537 /* paddr_8 - paddr_15 */
538 send_addr(host, (page_addr >> 8) & 0xff, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200539 } else {
540 /* One more address cycle for higher density devices */
541 if (mtd->size >= 0x4000000) {
542 /* paddr_8 - paddr_15 */
543 send_addr(host, (page_addr >> 8) & 0xff, false);
544 send_addr(host, (page_addr >> 16) & 0xff, true);
545 } else
546 /* paddr_8 - paddr_15 */
547 send_addr(host, (page_addr >> 8) & 0xff, true);
548 }
549 }
Sascha Hauera3e65b62009-06-02 11:47:59 +0200550}
Sascha Hauer34f6e152008-09-02 17:16:59 +0200551
Ivo Claryssed4840182010-04-08 16:14:44 +0200552static void preset(struct mtd_info *mtd)
553{
554 struct nand_chip *nand_chip = mtd->priv;
555 struct mxc_nand_host *host = nand_chip->priv;
556 uint16_t tmp;
557
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200558 /* enable interrupt, disable spare enable */
Ivo Claryssed4840182010-04-08 16:14:44 +0200559 tmp = readw(host->regs + NFC_CONFIG1);
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200560 tmp &= ~NFC_INT_MSK;
Ivo Claryssed4840182010-04-08 16:14:44 +0200561 tmp &= ~NFC_SP_EN;
562 if (nand_chip->ecc.mode == NAND_ECC_HW) {
563 tmp |= NFC_ECC_EN;
564 } else {
565 tmp &= ~NFC_ECC_EN;
566 }
567 writew(tmp, host->regs + NFC_CONFIG1);
568 /* preset operation */
569
570 /* Unlock the internal RAM Buffer */
571 writew(0x2, host->regs + NFC_CONFIG);
572
573 /* Blocks to be unlocked */
574 if (nfc_is_v21()) {
575 writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
576 writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
577 } else if (nfc_is_v1()) {
578 writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
579 writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
580 } else
581 BUG();
582
583 /* Unlock Block Command for given address range */
584 writew(0x4, host->regs + NFC_WRPROT);
585}
586
Sascha Hauer34f6e152008-09-02 17:16:59 +0200587/* Used by the upper layer to write command to NAND Flash for
588 * different operations to be carried out on NAND Flash */
589static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
590 int column, int page_addr)
591{
592 struct nand_chip *nand_chip = mtd->priv;
593 struct mxc_nand_host *host = nand_chip->priv;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200594
595 DEBUG(MTD_DEBUG_LEVEL3,
596 "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
597 command, column, page_addr);
598
599 /* Reset command state information */
600 host->status_request = false;
601
602 /* Command pre-processing step */
Sascha Hauer34f6e152008-09-02 17:16:59 +0200603 switch (command) {
Ivo Claryssed4840182010-04-08 16:14:44 +0200604 case NAND_CMD_RESET:
Ivo Claryssed4840182010-04-08 16:14:44 +0200605 preset(mtd);
Eric Bénard6a8cfcf2010-06-10 16:03:04 +0200606 send_cmd(host, command, false);
Ivo Claryssed4840182010-04-08 16:14:44 +0200607 break;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200608
Sascha Hauer34f6e152008-09-02 17:16:59 +0200609 case NAND_CMD_STATUS:
Sascha Hauerf8f96082009-06-04 17:12:26 +0200610 host->buf_start = 0;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200611 host->status_request = true;
Sascha Hauer89121a62009-06-04 17:18:01 +0200612
613 send_cmd(host, command, true);
614 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200615 break;
616
Sascha Hauer34f6e152008-09-02 17:16:59 +0200617 case NAND_CMD_READ0:
Sascha Hauer34f6e152008-09-02 17:16:59 +0200618 case NAND_CMD_READOOB:
Sascha Hauer89121a62009-06-04 17:18:01 +0200619 if (command == NAND_CMD_READ0)
620 host->buf_start = column;
621 else
622 host->buf_start = column + mtd->writesize;
Sascha Hauerf8f96082009-06-04 17:12:26 +0200623
Sascha Hauer6c499392010-05-28 10:02:17 +0200624 command = NAND_CMD_READ0; /* only READ0 is valid */
Sascha Hauer89121a62009-06-04 17:18:01 +0200625
626 send_cmd(host, command, false);
627 mxc_do_addr_cycle(mtd, column, page_addr);
628
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200629 if (mtd->writesize > 512)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200630 send_cmd(host, NAND_CMD_READSTART, true);
Sascha Hauerc5d23f12009-06-04 17:25:53 +0200631
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200632 send_page(mtd, NFC_OUTPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +0200633
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200634 memcpy(host->data_buf, host->main_area0, mtd->writesize);
Sascha Hauer89121a62009-06-04 17:18:01 +0200635 copy_spare(mtd, true);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200636 break;
637
Sascha Hauer34f6e152008-09-02 17:16:59 +0200638 case NAND_CMD_SEQIN:
Sascha Hauer6c499392010-05-28 10:02:17 +0200639 if (column >= mtd->writesize)
640 /* call ourself to read a page */
641 mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200642
Sascha Hauer6c499392010-05-28 10:02:17 +0200643 host->buf_start = column;
Sascha Hauer89121a62009-06-04 17:18:01 +0200644
645 send_cmd(host, command, false);
646 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200647 break;
648
649 case NAND_CMD_PAGEPROG:
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200650 memcpy(host->main_area0, host->data_buf, mtd->writesize);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200651 copy_spare(mtd, false);
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200652 send_page(mtd, NFC_INPUT);
Sascha Hauer89121a62009-06-04 17:18:01 +0200653 send_cmd(host, command, true);
654 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200655 break;
656
Sascha Hauer34f6e152008-09-02 17:16:59 +0200657 case NAND_CMD_READID:
Sascha Hauer89121a62009-06-04 17:18:01 +0200658 send_cmd(host, command, true);
659 mxc_do_addr_cycle(mtd, column, page_addr);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200660 send_read_id(host);
Sascha Hauer94671142009-10-05 12:14:21 +0200661 host->buf_start = column;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200662 break;
663
Sascha Hauer89121a62009-06-04 17:18:01 +0200664 case NAND_CMD_ERASE1:
Sascha Hauer34f6e152008-09-02 17:16:59 +0200665 case NAND_CMD_ERASE2:
Sascha Hauer89121a62009-06-04 17:18:01 +0200666 send_cmd(host, command, false);
667 mxc_do_addr_cycle(mtd, column, page_addr);
668
Sascha Hauer34f6e152008-09-02 17:16:59 +0200669 break;
670 }
671}
672
Sascha Hauerf1372052009-10-21 14:25:27 +0200673/*
674 * The generic flash bbt decriptors overlap with our ecc
675 * hardware, so define some i.MX specific ones.
676 */
677static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
678static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
679
680static struct nand_bbt_descr bbt_main_descr = {
681 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
682 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
683 .offs = 0,
684 .len = 4,
685 .veroffs = 4,
686 .maxblocks = 4,
687 .pattern = bbt_pattern,
688};
689
690static struct nand_bbt_descr bbt_mirror_descr = {
691 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
692 | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
693 .offs = 0,
694 .len = 4,
695 .veroffs = 4,
696 .maxblocks = 4,
697 .pattern = mirror_pattern,
698};
699
Sascha Hauer34f6e152008-09-02 17:16:59 +0200700static int __init mxcnd_probe(struct platform_device *pdev)
701{
702 struct nand_chip *this;
703 struct mtd_info *mtd;
704 struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
705 struct mxc_nand_host *host;
706 struct resource *res;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200707 int err = 0, nr_parts = 0;
Sascha Hauer94671142009-10-05 12:14:21 +0200708 struct nand_ecclayout *oob_smallpage, *oob_largepage;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200709
710 /* Allocate memory for MTD device structure and private data */
Sascha Hauerf8f96082009-06-04 17:12:26 +0200711 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
712 NAND_MAX_OOBSIZE, GFP_KERNEL);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200713 if (!host)
714 return -ENOMEM;
715
Sascha Hauerf8f96082009-06-04 17:12:26 +0200716 host->data_buf = (uint8_t *)(host + 1);
Sascha Hauerf8f96082009-06-04 17:12:26 +0200717
Sascha Hauer34f6e152008-09-02 17:16:59 +0200718 host->dev = &pdev->dev;
719 /* structures must be linked */
720 this = &host->nand;
721 mtd = &host->mtd;
722 mtd->priv = this;
723 mtd->owner = THIS_MODULE;
David Brownell87f39f02009-03-26 00:42:50 -0700724 mtd->dev.parent = &pdev->dev;
Sascha Hauer1fbff0a2009-10-21 16:06:27 +0200725 mtd->name = DRIVER_NAME;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200726
727 /* 50 us command delay time */
728 this->chip_delay = 5;
729
730 this->priv = host;
731 this->dev_ready = mxc_nand_dev_ready;
732 this->cmdfunc = mxc_nand_command;
733 this->select_chip = mxc_nand_select_chip;
734 this->read_byte = mxc_nand_read_byte;
735 this->read_word = mxc_nand_read_word;
736 this->write_buf = mxc_nand_write_buf;
737 this->read_buf = mxc_nand_read_buf;
738 this->verify_buf = mxc_nand_verify_buf;
739
Sascha Hauere65fb002009-02-16 14:29:10 +0100740 host->clk = clk_get(&pdev->dev, "nfc");
Vladimir Barinov8541c112009-04-23 15:47:22 +0400741 if (IS_ERR(host->clk)) {
742 err = PTR_ERR(host->clk);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200743 goto eclk;
Vladimir Barinov8541c112009-04-23 15:47:22 +0400744 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200745
746 clk_enable(host->clk);
747 host->clk_act = 1;
748
749 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
750 if (!res) {
751 err = -ENODEV;
752 goto eres;
753 }
754
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200755 host->base = ioremap(res->start, resource_size(res));
756 if (!host->base) {
Vladimir Barinov8541c112009-04-23 15:47:22 +0400757 err = -ENOMEM;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200758 goto eres;
759 }
760
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200761 host->main_area0 = host->base;
Sascha Hauer94671142009-10-05 12:14:21 +0200762
763 if (nfc_is_v21()) {
Sascha Hauer938cf992010-08-06 15:53:04 +0200764 host->regs = host->base + 0x1e00;
Sascha Hauer94671142009-10-05 12:14:21 +0200765 host->spare0 = host->base + 0x1000;
766 host->spare_len = 64;
767 oob_smallpage = &nandv2_hw_eccoob_smallpage;
768 oob_largepage = &nandv2_hw_eccoob_largepage;
Ivo Claryssed4840182010-04-08 16:14:44 +0200769 this->ecc.bytes = 9;
Sascha Hauer94671142009-10-05 12:14:21 +0200770 } else if (nfc_is_v1()) {
Sascha Hauer938cf992010-08-06 15:53:04 +0200771 host->regs = host->base + 0xe00;
Sascha Hauer94671142009-10-05 12:14:21 +0200772 host->spare0 = host->base + 0x800;
773 host->spare_len = 16;
774 oob_smallpage = &nandv1_hw_eccoob_smallpage;
775 oob_largepage = &nandv1_hw_eccoob_largepage;
Sascha Hauer94671142009-10-05 12:14:21 +0200776 this->ecc.bytes = 3;
777 } else
778 BUG();
Sascha Hauer34f6e152008-09-02 17:16:59 +0200779
Sascha Hauer13e1add2009-10-21 10:39:05 +0200780 this->ecc.size = 512;
Sascha Hauer94671142009-10-05 12:14:21 +0200781 this->ecc.layout = oob_smallpage;
Sascha Hauer13e1add2009-10-21 10:39:05 +0200782
783 if (pdata->hw_ecc) {
784 this->ecc.calculate = mxc_nand_calculate_ecc;
785 this->ecc.hwctl = mxc_nand_enable_hwecc;
786 this->ecc.correct = mxc_nand_correct_data;
787 this->ecc.mode = NAND_ECC_HW;
Sascha Hauer13e1add2009-10-21 10:39:05 +0200788 } else {
789 this->ecc.mode = NAND_ECC_SOFT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200790 }
791
Sascha Hauer34f6e152008-09-02 17:16:59 +0200792 /* NAND bus width determines access funtions used by upper layer */
Sascha Hauer13e1add2009-10-21 10:39:05 +0200793 if (pdata->width == 2)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200794 this->options |= NAND_BUSWIDTH_16;
Sascha Hauer13e1add2009-10-21 10:39:05 +0200795
Sascha Hauerf1372052009-10-21 14:25:27 +0200796 if (pdata->flash_bbt) {
797 this->bbt_td = &bbt_main_descr;
798 this->bbt_md = &bbt_mirror_descr;
799 /* update flash based bbt */
800 this->options |= NAND_USE_FLASH_BBT;
Sascha Hauer34f6e152008-09-02 17:16:59 +0200801 }
802
Ivo Claryssed4840182010-04-08 16:14:44 +0200803 init_waitqueue_head(&host->irq_waitq);
804
805 host->irq = platform_get_irq(pdev, 0);
806
Ivo Claryssea47bfd22010-04-08 16:16:51 +0200807 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
Ivo Claryssed4840182010-04-08 16:14:44 +0200808 if (err)
809 goto eirq;
810
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400811 /* first scan to find the device and get the page size */
David Woodhouse5e81e882010-02-26 18:32:56 +0000812 if (nand_scan_ident(mtd, 1, NULL)) {
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400813 err = -ENXIO;
814 goto escan;
815 }
Sascha Hauer34f6e152008-09-02 17:16:59 +0200816
Sascha Hauer2d69c7f2009-10-05 11:24:02 +0200817 if (mtd->writesize == 2048)
Sascha Hauer94671142009-10-05 12:14:21 +0200818 this->ecc.layout = oob_largepage;
Vladimir Barinovbd3fd622009-05-25 13:06:17 +0400819
820 /* second phase scan */
821 if (nand_scan_tail(mtd)) {
Sascha Hauer34f6e152008-09-02 17:16:59 +0200822 err = -ENXIO;
823 goto escan;
824 }
825
826 /* Register the partitions */
827#ifdef CONFIG_MTD_PARTITIONS
828 nr_parts =
829 parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
830 if (nr_parts > 0)
831 add_mtd_partitions(mtd, host->parts, nr_parts);
832 else
833#endif
834 {
835 pr_info("Registering %s as whole device\n", mtd->name);
836 add_mtd_device(mtd);
837 }
838
839 platform_set_drvdata(pdev, host);
840
841 return 0;
842
843escan:
Magnus Liljab258fd82009-05-08 21:57:47 +0200844 free_irq(host->irq, host);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200845eirq:
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200846 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200847eres:
848 clk_put(host->clk);
849eclk:
850 kfree(host);
851
852 return err;
853}
854
Uwe Kleine-König51eeb872009-12-07 09:44:05 +0000855static int __devexit mxcnd_remove(struct platform_device *pdev)
Sascha Hauer34f6e152008-09-02 17:16:59 +0200856{
857 struct mxc_nand_host *host = platform_get_drvdata(pdev);
858
859 clk_put(host->clk);
860
861 platform_set_drvdata(pdev, NULL);
862
863 nand_release(&host->mtd);
Magnus Liljab258fd82009-05-08 21:57:47 +0200864 free_irq(host->irq, host);
Sascha Hauerc6de7e12009-10-05 11:14:35 +0200865 iounmap(host->base);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200866 kfree(host);
867
868 return 0;
869}
870
Sascha Hauer34f6e152008-09-02 17:16:59 +0200871static struct platform_driver mxcnd_driver = {
872 .driver = {
873 .name = DRIVER_NAME,
Eric Bénard04dd0d32010-06-17 20:59:04 +0200874 },
Uwe Kleine-Königdaa0f152009-11-24 22:07:08 +0100875 .remove = __devexit_p(mxcnd_remove),
Sascha Hauer34f6e152008-09-02 17:16:59 +0200876};
877
878static int __init mxc_nd_init(void)
879{
Vladimir Barinov8541c112009-04-23 15:47:22 +0400880 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
Sascha Hauer34f6e152008-09-02 17:16:59 +0200881}
882
883static void __exit mxc_nd_cleanup(void)
884{
885 /* Unregister the device structure */
886 platform_driver_unregister(&mxcnd_driver);
887}
888
889module_init(mxc_nd_init);
890module_exit(mxc_nd_cleanup);
891
892MODULE_AUTHOR("Freescale Semiconductor, Inc.");
893MODULE_DESCRIPTION("MXC NAND MTD driver");
894MODULE_LICENSE("GPL");