blob: da2f4d16e5062e709bd889f271d394d77fac29e9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * drivers/mtd/nand.c
3 *
4 * Overview:
5 * This is the generic MTD driver for NAND flash devices. It should be
6 * capable of working with almost all NAND chips currently available.
7 * Basic support for AG-AND chips is provided.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00008 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * Additional technical information is available on
10 * http://www.linux-mtd.infradead.org/tech/nand.html
Thomas Gleixner61b03bd2005-11-07 11:15:49 +000011 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020013 * 2002 Thomas Gleixner (tglx@linutronix.de)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +000015 * 02-08-2004 tglx: support for strange chips, which cannot auto increment
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 * pages on read / read_oob
17 *
18 * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes
19 * pointed this out, as he marked an auto increment capable chip
20 * as NOAUTOINCR in the board driver.
21 * Make reads over block boundaries work too
22 *
23 * 04-14-2004 tglx: first working version for 2k page size chips
Thomas Gleixner61b03bd2005-11-07 11:15:49 +000024 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 * 05-19-2004 tglx: Basic support for Renesas AG-AND chips
26 *
27 * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020028 * among multiple independend devices. Suggestions and initial
29 * patch from Ben Dooks <ben-mtd@fluff.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 *
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020031 * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb"
32 * issue. Basically, any block not rewritten may lose data when
33 * surrounding blocks are rewritten many times. JFFS2 ensures
34 * this doesn't happen for blocks it uses, but the Bad Block
35 * Table(s) may not be rewritten. To ensure they do not lose
36 * data, force them to be rewritten when some of the surrounding
37 * blocks are erased. Rather than tracking a specific nearby
38 * block (which could itself go bad), use a page address 'mask' to
39 * select several blocks in the same area, and rewrite the BBT
40 * when any of them are erased.
David A. Marlin30f464b2005-01-17 18:35:25 +000041 *
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020042 * 01-03-2005 dmarlin: added support for the device recovery command sequence
43 * for Renesas AG-AND chips. If there was a sudden loss of power
44 * during an erase operation, a "device recovery" operation must
45 * be performed when power is restored to ensure correct
46 * operation.
David A. Marlin30f464b2005-01-17 18:35:25 +000047 *
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020048 * 01-20-2005 dmarlin: added support for optional hardware specific callback
49 * routine to perform extra error status checks on erase and write
50 * failures. This required adding a wrapper function for
51 * nand_read_ecc.
David A. Marlin068e3c02005-01-24 03:07:46 +000052 *
Vitaly Wool962034f2005-09-15 14:58:53 +010053 * 08-20-2005 vwool: suspend/resume added
54 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 * Credits:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +000056 * David Woodhouse for adding multichip support
57 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 * Aleph One Ltd. and Toby Churchill Ltd. for supporting the
59 * rework for 2K page size chips
60 *
61 * TODO:
62 * Enable cached programming for 2k page size chips
63 * Check, if mtd->ecctype should be set to MTD_ECC_HW
64 * if we have HW ecc support.
65 * The AG-AND chips have nice features for speed improvement,
66 * which are not supported yet. Read / program 4 pages in one go.
67 *
Vitaly Wool962034f2005-09-15 14:58:53 +010068 * $Id: nand_base.c,v 1.150 2005/09/15 13:58:48 vwool Exp $
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 *
70 * This program is free software; you can redistribute it and/or modify
71 * it under the terms of the GNU General Public License version 2 as
72 * published by the Free Software Foundation.
73 *
74 */
75
David Woodhouse552d9202006-05-14 01:20:46 +010076#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#include <linux/delay.h>
78#include <linux/errno.h>
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +020079#include <linux/err.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#include <linux/sched.h>
81#include <linux/slab.h>
82#include <linux/types.h>
83#include <linux/mtd/mtd.h>
84#include <linux/mtd/nand.h>
85#include <linux/mtd/nand_ecc.h>
86#include <linux/mtd/compatmac.h>
87#include <linux/interrupt.h>
88#include <linux/bitops.h>
Richard Purdie8fe833c2006-03-31 02:31:14 -080089#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070090#include <asm/io.h>
91
92#ifdef CONFIG_MTD_PARTITIONS
93#include <linux/mtd/partitions.h>
94#endif
95
96/* Define default oob placement schemes for large and small page devices */
97static struct nand_oobinfo nand_oob_8 = {
98 .useecc = MTD_NANDECC_AUTOPLACE,
99 .eccbytes = 3,
100 .eccpos = {0, 1, 2},
David Woodhousee0c7d762006-05-13 18:07:53 +0100101 .oobfree = {{3, 2}, {6, 2}}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102};
103
104static struct nand_oobinfo nand_oob_16 = {
105 .useecc = MTD_NANDECC_AUTOPLACE,
106 .eccbytes = 6,
107 .eccpos = {0, 1, 2, 3, 6, 7},
David Woodhousee0c7d762006-05-13 18:07:53 +0100108 .oobfree = {{8, 8}}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109};
110
111static struct nand_oobinfo nand_oob_64 = {
112 .useecc = MTD_NANDECC_AUTOPLACE,
113 .eccbytes = 24,
114 .eccpos = {
David Woodhousee0c7d762006-05-13 18:07:53 +0100115 40, 41, 42, 43, 44, 45, 46, 47,
116 48, 49, 50, 51, 52, 53, 54, 55,
117 56, 57, 58, 59, 60, 61, 62, 63},
118 .oobfree = {{2, 38}}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119};
120
121/* This is used for padding purposes in nand_write_oob */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200122static uint8_t ffchars[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
124 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
125 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
126 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131};
132
133/*
134 * NAND low-level MTD interface functions
135 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200136static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
137static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len);
138static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200140static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200141 size_t *retlen, uint8_t *buf);
David Woodhousee0c7d762006-05-13 18:07:53 +0100142static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200143 size_t *retlen, uint8_t *buf, uint8_t *eccbuf,
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200144 struct nand_oobinfo *oobsel);
145static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200146 size_t *retlen, uint8_t *buf);
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200147static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200148 size_t *retlen, const uint8_t *buf);
David Woodhousee0c7d762006-05-13 18:07:53 +0100149static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200150 size_t *retlen, const uint8_t *buf, uint8_t *eccbuf,
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200151 struct nand_oobinfo *oobsel);
152static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200153 size_t *retlen, const uint8_t *buf);
David Woodhousee0c7d762006-05-13 18:07:53 +0100154static int nand_erase(struct mtd_info *mtd, struct erase_info *instr);
155static void nand_sync(struct mtd_info *mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
157/* Some internal functions */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200158static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200159 int page, uint8_t * oob_buf,
David Woodhousee0c7d762006-05-13 18:07:53 +0100160 struct nand_oobinfo *oobsel, int mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200162static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200163 int page, int numpages, uint8_t *oob_buf,
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200164 struct nand_oobinfo *oobsel, int chipnr,
165 int oobmode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166#else
167#define nand_verify_pages(...) (0)
168#endif
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000169
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200170static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd,
171 int new_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173/**
174 * nand_release_device - [GENERIC] release chip
175 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000176 *
177 * Deselect, release chip lock and wake up anyone waiting on the device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100179static void nand_release_device(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180{
181 struct nand_chip *this = mtd->priv;
182
183 /* De-select the NAND device */
184 this->select_chip(mtd, -1);
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100185
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200186 /* Release the controller and the chip */
187 spin_lock(&this->controller->lock);
188 this->controller->active = NULL;
189 this->state = FL_READY;
190 wake_up(&this->controller->wq);
191 spin_unlock(&this->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192}
193
194/**
195 * nand_read_byte - [DEFAULT] read one byte from the chip
196 * @mtd: MTD device structure
197 *
198 * Default read function for 8bit buswith
199 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200200static uint8_t nand_read_byte(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 struct nand_chip *this = mtd->priv;
203 return readb(this->IO_ADDR_R);
204}
205
206/**
207 * nand_write_byte - [DEFAULT] write one byte to the chip
208 * @mtd: MTD device structure
209 * @byte: pointer to data byte to write
210 *
211 * Default write function for 8it buswith
212 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200213static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
215 struct nand_chip *this = mtd->priv;
216 writeb(byte, this->IO_ADDR_W);
217}
218
219/**
220 * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
221 * @mtd: MTD device structure
222 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000223 * Default read function for 16bit buswith with
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 * endianess conversion
225 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200226static uint8_t nand_read_byte16(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227{
228 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200229 return (uint8_t) cpu_to_le16(readw(this->IO_ADDR_R));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230}
231
232/**
233 * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip
234 * @mtd: MTD device structure
235 * @byte: pointer to data byte to write
236 *
237 * Default write function for 16bit buswith with
238 * endianess conversion
239 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200240static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241{
242 struct nand_chip *this = mtd->priv;
243 writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
244}
245
246/**
247 * nand_read_word - [DEFAULT] read one word from the chip
248 * @mtd: MTD device structure
249 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000250 * Default read function for 16bit buswith without
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 * endianess conversion
252 */
253static u16 nand_read_word(struct mtd_info *mtd)
254{
255 struct nand_chip *this = mtd->priv;
256 return readw(this->IO_ADDR_R);
257}
258
259/**
260 * nand_write_word - [DEFAULT] write one word to the chip
261 * @mtd: MTD device structure
262 * @word: data word to write
263 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000264 * Default write function for 16bit buswith without
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 * endianess conversion
266 */
267static void nand_write_word(struct mtd_info *mtd, u16 word)
268{
269 struct nand_chip *this = mtd->priv;
270 writew(word, this->IO_ADDR_W);
271}
272
273/**
274 * nand_select_chip - [DEFAULT] control CE line
275 * @mtd: MTD device structure
276 * @chip: chipnumber to select, -1 for deselect
277 *
278 * Default select function for 1 chip devices.
279 */
280static void nand_select_chip(struct mtd_info *mtd, int chip)
281{
282 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100283 switch (chip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 case -1:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000285 this->hwcontrol(mtd, NAND_CTL_CLRNCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 break;
287 case 0:
288 this->hwcontrol(mtd, NAND_CTL_SETNCE);
289 break;
290
291 default:
292 BUG();
293 }
294}
295
296/**
297 * nand_write_buf - [DEFAULT] write buffer to chip
298 * @mtd: MTD device structure
299 * @buf: data buffer
300 * @len: number of bytes to write
301 *
302 * Default write function for 8bit buswith
303 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200304static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305{
306 int i;
307 struct nand_chip *this = mtd->priv;
308
David Woodhousee0c7d762006-05-13 18:07:53 +0100309 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 writeb(buf[i], this->IO_ADDR_W);
311}
312
313/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000314 * nand_read_buf - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 * @mtd: MTD device structure
316 * @buf: buffer to store date
317 * @len: number of bytes to read
318 *
319 * Default read function for 8bit buswith
320 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200321static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322{
323 int i;
324 struct nand_chip *this = mtd->priv;
325
David Woodhousee0c7d762006-05-13 18:07:53 +0100326 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 buf[i] = readb(this->IO_ADDR_R);
328}
329
330/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000331 * nand_verify_buf - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 * @mtd: MTD device structure
333 * @buf: buffer containing the data to compare
334 * @len: number of bytes to compare
335 *
336 * Default verify function for 8bit buswith
337 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200338static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339{
340 int i;
341 struct nand_chip *this = mtd->priv;
342
David Woodhousee0c7d762006-05-13 18:07:53 +0100343 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 if (buf[i] != readb(this->IO_ADDR_R))
345 return -EFAULT;
346
347 return 0;
348}
349
350/**
351 * nand_write_buf16 - [DEFAULT] write buffer to chip
352 * @mtd: MTD device structure
353 * @buf: data buffer
354 * @len: number of bytes to write
355 *
356 * Default write function for 16bit buswith
357 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200358static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359{
360 int i;
361 struct nand_chip *this = mtd->priv;
362 u16 *p = (u16 *) buf;
363 len >>= 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000364
David Woodhousee0c7d762006-05-13 18:07:53 +0100365 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 writew(p[i], this->IO_ADDR_W);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000367
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368}
369
370/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000371 * nand_read_buf16 - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 * @mtd: MTD device structure
373 * @buf: buffer to store date
374 * @len: number of bytes to read
375 *
376 * Default read function for 16bit buswith
377 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200378static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379{
380 int i;
381 struct nand_chip *this = mtd->priv;
382 u16 *p = (u16 *) buf;
383 len >>= 1;
384
David Woodhousee0c7d762006-05-13 18:07:53 +0100385 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 p[i] = readw(this->IO_ADDR_R);
387}
388
389/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000390 * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 * @mtd: MTD device structure
392 * @buf: buffer containing the data to compare
393 * @len: number of bytes to compare
394 *
395 * Default verify function for 16bit buswith
396 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200397static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398{
399 int i;
400 struct nand_chip *this = mtd->priv;
401 u16 *p = (u16 *) buf;
402 len >>= 1;
403
David Woodhousee0c7d762006-05-13 18:07:53 +0100404 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 if (p[i] != readw(this->IO_ADDR_R))
406 return -EFAULT;
407
408 return 0;
409}
410
411/**
412 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
413 * @mtd: MTD device structure
414 * @ofs: offset from device start
415 * @getchip: 0, if the chip is already selected
416 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000417 * Check, if the block is bad.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 */
419static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
420{
421 int page, chipnr, res = 0;
422 struct nand_chip *this = mtd->priv;
423 u16 bad;
424
425 if (getchip) {
426 page = (int)(ofs >> this->page_shift);
427 chipnr = (int)(ofs >> this->chip_shift);
428
429 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +0100430 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
432 /* Select the NAND device */
433 this->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000434 } else
David Woodhousee0c7d762006-05-13 18:07:53 +0100435 page = (int)ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
437 if (this->options & NAND_BUSWIDTH_16) {
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200438 this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE,
439 page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 bad = cpu_to_le16(this->read_word(mtd));
441 if (this->badblockpos & 0x1)
Vitaly Wool49196f32005-11-02 16:54:46 +0000442 bad >>= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 if ((bad & 0xFF) != 0xff)
444 res = 1;
445 } else {
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200446 this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos,
447 page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 if (this->read_byte(mtd) != 0xff)
449 res = 1;
450 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000451
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 if (getchip) {
453 /* Deselect and wake up anyone waiting on the device */
454 nand_release_device(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000455 }
456
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 return res;
458}
459
460/**
461 * nand_default_block_markbad - [DEFAULT] mark a block bad
462 * @mtd: MTD device structure
463 * @ofs: offset from device start
464 *
465 * This is the default implementation, which can be overridden by
466 * a hardware specific driver.
467*/
468static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
469{
470 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200471 uint8_t buf[2] = { 0, 0 };
David Woodhousee0c7d762006-05-13 18:07:53 +0100472 size_t retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 int block;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000474
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 /* Get block number */
David Woodhousee0c7d762006-05-13 18:07:53 +0100476 block = ((int)ofs) >> this->bbt_erase_shift;
Artem B. Bityuckiy41ce9212005-02-09 14:50:00 +0000477 if (this->bbt)
478 this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
480 /* Do we have a flash based bad block table ? */
481 if (this->options & NAND_USE_FLASH_BBT)
David Woodhousee0c7d762006-05-13 18:07:53 +0100482 return nand_update_bbt(mtd, ofs);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 /* We write two bytes, so we dont have to mess with 16 bit access */
485 ofs += mtd->oobsize + (this->badblockpos & ~0x01);
David Woodhousee0c7d762006-05-13 18:07:53 +0100486 return nand_write_oob(mtd, ofs, 2, &retlen, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487}
488
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000489/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 * nand_check_wp - [GENERIC] check if the chip is write protected
491 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000492 * Check, if the device is write protected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000494 * The function expects, that the device is already selected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100496static int nand_check_wp(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
498 struct nand_chip *this = mtd->priv;
499 /* Check the WP bit */
David Woodhousee0c7d762006-05-13 18:07:53 +0100500 this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000501 return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502}
503
504/**
505 * nand_block_checkbad - [GENERIC] Check if a block is marked bad
506 * @mtd: MTD device structure
507 * @ofs: offset from device start
508 * @getchip: 0, if the chip is already selected
509 * @allowbbt: 1, if its allowed to access the bbt area
510 *
511 * Check, if the block is bad. Either by reading the bad block table or
512 * calling of the scan function.
513 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200514static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
515 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516{
517 struct nand_chip *this = mtd->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000518
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 if (!this->bbt)
520 return this->block_bad(mtd, ofs, getchip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000521
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 /* Return info from the table */
David Woodhousee0c7d762006-05-13 18:07:53 +0100523 return nand_isbad_bbt(mtd, ofs, allowbbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524}
525
Richard Purdie8fe833c2006-03-31 02:31:14 -0800526DEFINE_LED_TRIGGER(nand_led_trigger);
527
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000528/*
Thomas Gleixner3b887752005-02-22 21:56:49 +0000529 * Wait for the ready pin, after a command
530 * The timeout is catched later.
531 */
532static void nand_wait_ready(struct mtd_info *mtd)
533{
534 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100535 unsigned long timeo = jiffies + 2;
Thomas Gleixner3b887752005-02-22 21:56:49 +0000536
Richard Purdie8fe833c2006-03-31 02:31:14 -0800537 led_trigger_event(nand_led_trigger, LED_FULL);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000538 /* wait until command is processed or timeout occures */
539 do {
540 if (this->dev_ready(mtd))
Richard Purdie8fe833c2006-03-31 02:31:14 -0800541 break;
Ingo Molnar8446f1d2005-09-06 15:16:27 -0700542 touch_softlockup_watchdog();
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000543 } while (time_before(jiffies, timeo));
Richard Purdie8fe833c2006-03-31 02:31:14 -0800544 led_trigger_event(nand_led_trigger, LED_OFF);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000545}
546
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547/**
548 * nand_command - [DEFAULT] Send command to NAND device
549 * @mtd: MTD device structure
550 * @command: the command to be sent
551 * @column: the column address for this command, -1 if none
552 * @page_addr: the page address for this command, -1 if none
553 *
554 * Send command to NAND device. This function is used for small page
555 * devices (256/512 Bytes per page)
556 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200557static void nand_command(struct mtd_info *mtd, unsigned command, int column,
558 int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
560 register struct nand_chip *this = mtd->priv;
561
562 /* Begin command latch cycle */
563 this->hwcontrol(mtd, NAND_CTL_SETCLE);
564 /*
565 * Write out the command to the device.
566 */
567 if (command == NAND_CMD_SEQIN) {
568 int readcmd;
569
Joern Engel28318772006-05-22 23:18:05 +0200570 if (column >= mtd->writesize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 /* OOB area */
Joern Engel28318772006-05-22 23:18:05 +0200572 column -= mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 readcmd = NAND_CMD_READOOB;
574 } else if (column < 256) {
575 /* First 256 bytes --> READ0 */
576 readcmd = NAND_CMD_READ0;
577 } else {
578 column -= 256;
579 readcmd = NAND_CMD_READ1;
580 }
581 this->write_byte(mtd, readcmd);
582 }
583 this->write_byte(mtd, command);
584
585 /* Set ALE and clear CLE to start address cycle */
586 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
587
588 if (column != -1 || page_addr != -1) {
589 this->hwcontrol(mtd, NAND_CTL_SETALE);
590
591 /* Serially input address */
592 if (column != -1) {
593 /* Adjust columns for 16 bit buswidth */
594 if (this->options & NAND_BUSWIDTH_16)
595 column >>= 1;
596 this->write_byte(mtd, column);
597 }
598 if (page_addr != -1) {
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200599 this->write_byte(mtd, (uint8_t)(page_addr & 0xff));
600 this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 /* One more address cycle for devices > 32MiB */
602 if (this->chipsize > (32 << 20))
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200603 this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0x0f));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 }
605 /* Latch in address */
606 this->hwcontrol(mtd, NAND_CTL_CLRALE);
607 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000608
609 /*
610 * program and erase have their own busy handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 * status and sequential in needs no delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100612 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000614
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 case NAND_CMD_PAGEPROG:
616 case NAND_CMD_ERASE1:
617 case NAND_CMD_ERASE2:
618 case NAND_CMD_SEQIN:
619 case NAND_CMD_STATUS:
620 return;
621
622 case NAND_CMD_RESET:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000623 if (this->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 break;
625 udelay(this->chip_delay);
626 this->hwcontrol(mtd, NAND_CTL_SETCLE);
627 this->write_byte(mtd, NAND_CMD_STATUS);
628 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
David Woodhousee0c7d762006-05-13 18:07:53 +0100629 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 return;
631
David Woodhousee0c7d762006-05-13 18:07:53 +0100632 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000634 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 * If we don't have access to the busy pin, we apply the given
636 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100637 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 if (!this->dev_ready) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100639 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 /* Apply this short delay always to ensure that we do wait tWB in
644 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100645 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000646
647 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}
649
650/**
651 * nand_command_lp - [DEFAULT] Send command to NAND large page device
652 * @mtd: MTD device structure
653 * @command: the command to be sent
654 * @column: the column address for this command, -1 if none
655 * @page_addr: the page address for this command, -1 if none
656 *
657 * Send command to NAND device. This is the version for the new large page devices
David Woodhousee0c7d762006-05-13 18:07:53 +0100658 * We dont have the separate regions as we have in the small page devices.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 * We must emulate NAND_CMD_READOOB to keep the code compatible.
660 *
661 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100662static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663{
664 register struct nand_chip *this = mtd->priv;
665
666 /* Emulate NAND_CMD_READOOB */
667 if (command == NAND_CMD_READOOB) {
Joern Engel28318772006-05-22 23:18:05 +0200668 column += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 command = NAND_CMD_READ0;
670 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 /* Begin command latch cycle */
673 this->hwcontrol(mtd, NAND_CTL_SETCLE);
674 /* Write out the command to the device. */
David A. Marlin30f464b2005-01-17 18:35:25 +0000675 this->write_byte(mtd, (command & 0xff));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 /* End command latch cycle */
677 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
678
679 if (column != -1 || page_addr != -1) {
680 this->hwcontrol(mtd, NAND_CTL_SETALE);
681
682 /* Serially input address */
683 if (column != -1) {
684 /* Adjust columns for 16 bit buswidth */
685 if (this->options & NAND_BUSWIDTH_16)
686 column >>= 1;
687 this->write_byte(mtd, column & 0xff);
688 this->write_byte(mtd, column >> 8);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 if (page_addr != -1) {
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200691 this->write_byte(mtd, (uint8_t)(page_addr & 0xff));
692 this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 /* One more address cycle for devices > 128MiB */
694 if (this->chipsize > (128 << 20))
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200695 this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0xff));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 }
697 /* Latch in address */
698 this->hwcontrol(mtd, NAND_CTL_CLRALE);
699 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000700
701 /*
702 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000703 * status, sequential in, and deplete1 need no delay
704 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000706
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 case NAND_CMD_CACHEDPROG:
708 case NAND_CMD_PAGEPROG:
709 case NAND_CMD_ERASE1:
710 case NAND_CMD_ERASE2:
711 case NAND_CMD_SEQIN:
712 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000713 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 return;
715
David Woodhousee0c7d762006-05-13 18:07:53 +0100716 /*
717 * read error status commands require only a short delay
718 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000719 case NAND_CMD_STATUS_ERROR:
720 case NAND_CMD_STATUS_ERROR0:
721 case NAND_CMD_STATUS_ERROR1:
722 case NAND_CMD_STATUS_ERROR2:
723 case NAND_CMD_STATUS_ERROR3:
724 udelay(this->chip_delay);
725 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
727 case NAND_CMD_RESET:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000728 if (this->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 break;
730 udelay(this->chip_delay);
731 this->hwcontrol(mtd, NAND_CTL_SETCLE);
732 this->write_byte(mtd, NAND_CMD_STATUS);
733 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
David Woodhousee0c7d762006-05-13 18:07:53 +0100734 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 return;
736
737 case NAND_CMD_READ0:
738 /* Begin command latch cycle */
739 this->hwcontrol(mtd, NAND_CTL_SETCLE);
740 /* Write out the start read command */
741 this->write_byte(mtd, NAND_CMD_READSTART);
742 /* End command latch cycle */
743 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
744 /* Fall through into ready check */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000745
David Woodhousee0c7d762006-05-13 18:07:53 +0100746 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000748 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 * If we don't have access to the busy pin, we apply the given
750 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100751 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 if (!this->dev_ready) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100753 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000755 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000757
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 /* Apply this short delay always to ensure that we do wait tWB in
759 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100760 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000761
762 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763}
764
765/**
766 * nand_get_device - [GENERIC] Get chip for selected access
767 * @this: the nand chip descriptor
768 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000769 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 *
771 * Get the device and lock it for exclusive access
772 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200773static int
774nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775{
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200776 spinlock_t *lock = &this->controller->lock;
777 wait_queue_head_t *wq = &this->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100778 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100779 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100780 spin_lock(lock);
781
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200783 /* Hardware controller shared among independend devices */
784 if (!this->controller->active)
785 this->controller->active = this;
786
787 if (this->controller->active == this && this->state == FL_READY) {
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100788 this->state = new_state;
789 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100790 return 0;
791 }
792 if (new_state == FL_PM_SUSPENDED) {
793 spin_unlock(lock);
794 return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100795 }
796 set_current_state(TASK_UNINTERRUPTIBLE);
797 add_wait_queue(wq, &wait);
798 spin_unlock(lock);
799 schedule();
800 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 goto retry;
802}
803
804/**
805 * nand_wait - [DEFAULT] wait until the command is done
806 * @mtd: MTD device structure
807 * @this: NAND chip structure
808 * @state: state to select the max. timeout value
809 *
810 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000811 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 * general NAND and SmartMedia specs
813 *
814*/
815static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
816{
817
David Woodhousee0c7d762006-05-13 18:07:53 +0100818 unsigned long timeo = jiffies;
819 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000820
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100822 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100824 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Richard Purdie8fe833c2006-03-31 02:31:14 -0800826 led_trigger_event(nand_led_trigger, LED_FULL);
827
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 /* Apply this short delay always to ensure that we do wait tWB in
829 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100830 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
832 if ((state == FL_ERASING) && (this->options & NAND_IS_AND))
David Woodhousee0c7d762006-05-13 18:07:53 +0100833 this->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000834 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100835 this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000837 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 /* Check, if we were interrupted */
839 if (this->state != state)
840 return 0;
841
842 if (this->dev_ready) {
843 if (this->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000844 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 } else {
846 if (this->read_byte(mtd) & NAND_STATUS_READY)
847 break;
848 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000849 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800851 led_trigger_event(nand_led_trigger, LED_OFF);
852
David Woodhousee0c7d762006-05-13 18:07:53 +0100853 status = (int)this->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 return status;
855}
856
857/**
858 * nand_write_page - [GENERIC] write one page
859 * @mtd: MTD device structure
860 * @this: NAND chip structure
861 * @page: startpage inside the chip, must be called with (page & this->pagemask)
862 * @oob_buf: out of band data buffer
863 * @oobsel: out of band selecttion structre
864 * @cached: 1 = enable cached programming if supported by chip
865 *
866 * Nand_page_program function is used for write and writev !
867 * This function will always program a full page of data
868 * If you call it with a non page aligned buffer, you're lost :)
869 *
870 * Cached programming is not supported yet.
871 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100872static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int page,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200873 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int cached)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874{
David Woodhousee0c7d762006-05-13 18:07:53 +0100875 int i, status;
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200876 uint8_t ecc_code[32];
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200877 int eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
David Woodhousee0c7d762006-05-13 18:07:53 +0100878 int *oob_config = oobsel->eccpos;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200879 int datidx = 0, eccidx = 0, eccsteps = this->ecc.steps;
David Woodhousee0c7d762006-05-13 18:07:53 +0100880 int eccbytes = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 /* FIXME: Enable cached programming */
883 cached = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000884
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 /* Send command to begin auto page programming */
David Woodhousee0c7d762006-05-13 18:07:53 +0100886 this->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
888 /* Write out complete page of data, take care of eccmode */
889 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100890 /* No ecc, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 case NAND_ECC_NONE:
David Woodhousee0c7d762006-05-13 18:07:53 +0100892 printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
Joern Engel28318772006-05-22 23:18:05 +0200893 this->write_buf(mtd, this->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000895
David Woodhousee0c7d762006-05-13 18:07:53 +0100896 /* Software ecc 3/256, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 case NAND_ECC_SOFT:
898 for (; eccsteps; eccsteps--) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200899 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 for (i = 0; i < 3; i++, eccidx++)
901 oob_buf[oob_config[eccidx]] = ecc_code[i];
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200902 datidx += this->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 }
Joern Engel28318772006-05-22 23:18:05 +0200904 this->write_buf(mtd, this->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 break;
906 default:
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200907 eccbytes = this->ecc.bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 for (; eccsteps; eccsteps--) {
909 /* enable hardware ecc logic for write */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200910 this->ecc.hwctl(mtd, NAND_ECC_WRITE);
911 this->write_buf(mtd, &this->data_poi[datidx], this->ecc.size);
912 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 for (i = 0; i < eccbytes; i++, eccidx++)
914 oob_buf[oob_config[eccidx]] = ecc_code[i];
915 /* If the hardware ecc provides syndromes then
916 * the ecc code must be written immidiately after
917 * the data bytes (words) */
918 if (this->options & NAND_HWECC_SYNDROME)
919 this->write_buf(mtd, ecc_code, eccbytes);
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200920 datidx += this->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 }
922 break;
923 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 /* Write out OOB data */
926 if (this->options & NAND_HWECC_SYNDROME)
927 this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000928 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 this->write_buf(mtd, oob_buf, mtd->oobsize);
930
931 /* Send command to actually program the data */
David Woodhousee0c7d762006-05-13 18:07:53 +0100932 this->cmdfunc(mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
934 if (!cached) {
935 /* call wait ready function */
David Woodhousee0c7d762006-05-13 18:07:53 +0100936 status = this->waitfunc(mtd, this, FL_WRITING);
David A. Marlin068e3c02005-01-24 03:07:46 +0000937
938 /* See if operation failed and additional status checks are available */
939 if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
940 status = this->errstat(mtd, this, FL_WRITING, status, page);
941 }
942
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +0000944 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100945 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 return -EIO;
947 }
948 } else {
949 /* FIXME: Implement cached programming ! */
David Woodhousee0c7d762006-05-13 18:07:53 +0100950 /* wait until cache is ready */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 // status = this->waitfunc (mtd, this, FL_CACHEDRPG);
952 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000953 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954}
955
956#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
957/**
958 * nand_verify_pages - [GENERIC] verify the chip contents after a write
959 * @mtd: MTD device structure
960 * @this: NAND chip structure
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200961 * @page: startpage inside the chip, must be called with (page & this->pagemask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 * @numpages: number of pages to verify
963 * @oob_buf: out of band data buffer
964 * @oobsel: out of band selecttion structre
965 * @chipnr: number of the current chip
966 * @oobmode: 1 = full buffer verify, 0 = ecc only
967 *
968 * The NAND device assumes that it is always writing to a cleanly erased page.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000969 * Hence, it performs its internal write verification only on bits that
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 * transitioned from 1 to 0. The device does NOT verify the whole page on a
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000971 * byte by byte basis. It is possible that the page was not completely erased
972 * or the page is becoming unusable due to wear. The read with ECC would catch
973 * the error later when the ECC page check fails, but we would rather catch
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 * it early in the page write stage. Better to write no data than invalid data.
975 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100976static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200977 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978{
David Woodhousee0c7d762006-05-13 18:07:53 +0100979 int i, j, datidx = 0, oobofs = 0, res = -EIO;
980 int eccsteps = this->eccsteps;
981 int hweccbytes;
Thomas Gleixner58dd8f22006-05-23 11:52:35 +0200982 uint8_t oobdata[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984 hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
985
986 /* Send command to read back the first page */
David Woodhousee0c7d762006-05-13 18:07:53 +0100987 this->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
David Woodhousee0c7d762006-05-13 18:07:53 +0100989 for (;;) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 for (j = 0; j < eccsteps; j++) {
991 /* Loop through and verify the data */
992 if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100993 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 goto out;
995 }
996 datidx += mtd->eccsize;
997 /* Have we a hw generator layout ? */
998 if (!hweccbytes)
999 continue;
1000 if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001001 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 goto out;
1003 }
1004 oobofs += hweccbytes;
1005 }
1006
1007 /* check, if we must compare all data or if we just have to
1008 * compare the ecc bytes
1009 */
1010 if (oobmode) {
1011 if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001012 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 goto out;
1014 }
1015 } else {
1016 /* Read always, else autoincrement fails */
1017 this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
1018
1019 if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
1020 int ecccnt = oobsel->eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 for (i = 0; i < ecccnt; i++) {
1023 int idx = oobsel->eccpos[i];
David Woodhousee0c7d762006-05-13 18:07:53 +01001024 if (oobdata[idx] != oob_buf[oobofs + idx]) {
1025 DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed ECC write verify, page 0x%08x, %6i bytes were succesful\n",
1026 __FUNCTION__, page, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 goto out;
1028 }
1029 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001030 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 }
1032 oobofs += mtd->oobsize - hweccbytes * eccsteps;
1033 page++;
1034 numpages--;
1035
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001036 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 * Do this before the AUTOINCR check, so no problems
1038 * arise if a chip which does auto increment
1039 * is marked as NOAUTOINCR by the board driver.
1040 * Do this also before returning, so the chip is
1041 * ready for the next command.
David Woodhousee0c7d762006-05-13 18:07:53 +01001042 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001043 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001044 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001046 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
1048 /* All done, return happy */
1049 if (!numpages)
1050 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001051
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001052 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 if (!NAND_CANAUTOINCR(this))
David Woodhousee0c7d762006-05-13 18:07:53 +01001054 this->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001056 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 * Terminate the read command. We come here in case of an error
1058 * So we must issue a reset command.
1059 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001060 out:
1061 this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 return res;
1063}
1064#endif
1065
1066/**
David A. Marlin068e3c02005-01-24 03:07:46 +00001067 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 * @mtd: MTD device structure
1069 * @from: offset to read from
1070 * @len: number of bytes to read
1071 * @retlen: pointer to variable to store the number of read bytes
1072 * @buf: the databuffer to put data
1073 *
David A. Marlin068e3c02005-01-24 03:07:46 +00001074 * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL
1075 * and flags = 0xff
1076 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001077static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
David Woodhousee0c7d762006-05-13 18:07:53 +01001079 return nand_do_read_ecc(mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001080}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082/**
David A. Marlin068e3c02005-01-24 03:07:46 +00001083 * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 * @mtd: MTD device structure
1085 * @from: offset to read from
1086 * @len: number of bytes to read
1087 * @retlen: pointer to variable to store the number of read bytes
1088 * @buf: the databuffer to put data
1089 * @oob_buf: filesystem supplied oob data buffer
1090 * @oobsel: oob selection structure
1091 *
David A. Marlin068e3c02005-01-24 03:07:46 +00001092 * This function simply calls nand_do_read_ecc with flags = 0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001094static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001095 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096{
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001097 /* use userspace supplied oobinfo, if zero */
1098 if (oobsel == NULL)
1099 oobsel = &mtd->oobinfo;
David A. Marlin068e3c02005-01-24 03:07:46 +00001100 return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);
1101}
1102
David A. Marlin068e3c02005-01-24 03:07:46 +00001103/**
1104 * nand_do_read_ecc - [MTD Interface] Read data with ECC
1105 * @mtd: MTD device structure
1106 * @from: offset to read from
1107 * @len: number of bytes to read
1108 * @retlen: pointer to variable to store the number of read bytes
1109 * @buf: the databuffer to put data
Dan Brownbb75ba42005-04-04 19:02:26 +01001110 * @oob_buf: filesystem supplied oob data buffer (can be NULL)
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001111 * @oobsel: oob selection structure
David A. Marlin068e3c02005-01-24 03:07:46 +00001112 * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed
1113 * and how many corrected error bits are acceptable:
1114 * bits 0..7 - number of tolerable errors
1115 * bit 8 - 0 == do not get/release chip, 1 == get/release chip
1116 *
1117 * NAND read with ECC
1118 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001119int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001120 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel, int flags)
David A. Marlin068e3c02005-01-24 03:07:46 +00001121{
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001122
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
1124 int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
1125 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001126 uint8_t *data_poi, *oob_data = oob_buf;
1127 uint8_t ecc_calc[32];
1128 uint8_t ecc_code[32];
David Woodhousee0c7d762006-05-13 18:07:53 +01001129 int eccmode, eccsteps;
1130 int *oob_config, datidx;
1131 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
1132 int eccbytes;
1133 int compareecc = 1;
1134 int oobreadlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
David Woodhousee0c7d762006-05-13 18:07:53 +01001136 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int)from, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
1138 /* Do not allow reads past end of device */
1139 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001140 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 *retlen = 0;
1142 return -EINVAL;
1143 }
1144
1145 /* Grab the lock and see if the device is available */
David A. Marlin068e3c02005-01-24 03:07:46 +00001146 if (flags & NAND_GET_DEVICE)
David Woodhousee0c7d762006-05-13 18:07:53 +01001147 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 /* Autoplace of oob data ? Use the default placement scheme */
1150 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
1151 oobsel = this->autooob;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001152
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001153 eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 oob_config = oobsel->eccpos;
1155
1156 /* Select the NAND device */
1157 chipnr = (int)(from >> this->chip_shift);
1158 this->select_chip(mtd, chipnr);
1159
1160 /* First we calculate the starting page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001161 realpage = (int)(from >> this->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 page = realpage & this->pagemask;
1163
1164 /* Get raw starting column */
Joern Engel28318772006-05-22 23:18:05 +02001165 col = from & (mtd->writesize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166
Joern Engel28318772006-05-22 23:18:05 +02001167 end = mtd->writesize;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001168 ecc = this->ecc.size;
1169 eccbytes = this->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001170
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
1172 compareecc = 0;
1173
1174 oobreadlen = mtd->oobsize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001175 if (this->options & NAND_HWECC_SYNDROME)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 oobreadlen -= oobsel->eccbytes;
1177
1178 /* Loop until all data read */
1179 while (read < len) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001180
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 int aligned = (!col && (len - read) >= end);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001182 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 * If the read is not page aligned, we have to read into data buffer
1184 * due to ecc, else we read into return buffer direct
1185 */
1186 if (aligned)
1187 data_poi = &buf[read];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001188 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 data_poi = this->data_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001190
1191 /* Check, if we have this page in the buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 *
1193 * FIXME: Make it work when we must provide oob data too,
1194 * check the usage of data_buf oob field
1195 */
1196 if (realpage == this->pagebuf && !oob_buf) {
1197 /* aligned read ? */
1198 if (aligned)
David Woodhousee0c7d762006-05-13 18:07:53 +01001199 memcpy(data_poi, this->data_buf, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 goto readdata;
1201 }
1202
1203 /* Check, if we must send the read command */
1204 if (sndcmd) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001205 this->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 sndcmd = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
1209 /* get oob area, if we have no oob buffer from fs-driver */
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001210 if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
1211 oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 oob_data = &this->data_buf[end];
1213
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001214 eccsteps = this->ecc.steps;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001215
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001217 case NAND_ECC_NONE:{
1218 /* No ECC, Read in a page */
1219 static unsigned long lastwhinge = 0;
1220 if ((lastwhinge / HZ) != (jiffies / HZ)) {
1221 printk(KERN_WARNING
1222 "Reading data from NAND FLASH without ECC is not recommended\n");
1223 lastwhinge = jiffies;
1224 }
1225 this->read_buf(mtd, data_poi, end);
1226 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001228
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
1230 this->read_buf(mtd, data_poi, end);
David Woodhousee0c7d762006-05-13 18:07:53 +01001231 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001232 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001233 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
1235 default:
David Woodhousee0c7d762006-05-13 18:07:53 +01001236 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001237 this->ecc.hwctl(mtd, NAND_ECC_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 this->read_buf(mtd, &data_poi[datidx], ecc);
1239
1240 /* HW ecc with syndrome calculation must read the
1241 * syndrome from flash immidiately after the data */
1242 if (!compareecc) {
1243 /* Some hw ecc generators need to know when the
1244 * syndrome is read from flash */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001245 this->ecc.hwctl(mtd, NAND_ECC_READSYN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 this->read_buf(mtd, &oob_data[i], eccbytes);
1247 /* We calc error correction directly, it checks the hw
1248 * generator for an error, reads back the syndrome and
1249 * does the error correction on the fly */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001250 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
David A. Marlin068e3c02005-01-24 03:07:46 +00001251 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001252 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
1253 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 ecc_failed++;
1255 }
1256 } else {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001257 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001260 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 }
1262
1263 /* read oobdata */
1264 this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
1265
1266 /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
1267 if (!compareecc)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001268 goto readoob;
1269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 /* Pick the ECC bytes out of the oob data */
1271 for (j = 0; j < oobsel->eccbytes; j++)
1272 ecc_code[j] = oob_data[oob_config[j]];
1273
David Woodhousee0c7d762006-05-13 18:07:53 +01001274 /* correct data, if necessary */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001275 for (i = 0, j = 0, datidx = 0; i < this->ecc.steps; i++, datidx += ecc) {
1276 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 /* Get next chunk of ecc bytes */
1279 j += eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001280
1281 /* Check, if we have a fs supplied oob-buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 * This is the legacy mode. Used by YAFFS1
1283 * Should go away some day
1284 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001285 if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 int *p = (int *)(&oob_data[mtd->oobsize]);
1287 p[i] = ecc_status;
1288 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001289
1290 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001291 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 ecc_failed++;
1293 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
David Woodhousee0c7d762006-05-13 18:07:53 +01001296 readoob:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 /* check, if we have a fs supplied oob-buffer */
1298 if (oob_buf) {
1299 /* without autoplace. Legacy mode used by YAFFS1 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001300 switch (oobsel->useecc) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 case MTD_NANDECC_AUTOPLACE:
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001302 case MTD_NANDECC_AUTOPL_USR:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 /* Walk through the autoplace chunks */
Dan Brown82e1d192005-04-06 21:13:09 +01001304 for (i = 0; oobsel->oobfree[i][1]; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 int from = oobsel->oobfree[i][0];
1306 int num = oobsel->oobfree[i][1];
1307 memcpy(&oob_buf[oob], &oob_data[from], num);
Dan Brown82e1d192005-04-06 21:13:09 +01001308 oob += num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 break;
1311 case MTD_NANDECC_PLACE:
1312 /* YAFFS1 legacy mode */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001313 oob_data += this->ecc.steps * sizeof(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 default:
1315 oob_data += mtd->oobsize;
1316 }
1317 }
1318 readdata:
1319 /* Partial page read, transfer data into fs buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001320 if (!aligned) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 for (j = col; j < end && read < len; j++)
1322 buf[read++] = data_poi[j];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001323 this->pagebuf = realpage;
1324 } else
Joern Engel28318772006-05-22 23:18:05 +02001325 read += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001327 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 * Do this before the AUTOINCR check, so no problems
1329 * arise if a chip which does auto increment
1330 * is marked as NOAUTOINCR by the board driver.
David Woodhousee0c7d762006-05-13 18:07:53 +01001331 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001332 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001333 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001335 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001336
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 if (read == len)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001338 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
1340 /* For subsequent reads align to page boundary. */
1341 col = 0;
1342 /* Increment page address */
1343 realpage++;
1344
1345 page = realpage & this->pagemask;
1346 /* Check, if we cross a chip boundary */
1347 if (!page) {
1348 chipnr++;
1349 this->select_chip(mtd, -1);
1350 this->select_chip(mtd, chipnr);
1351 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001352 /* Check, if the chip supports auto page increment
1353 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001354 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001356 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 }
1358
1359 /* Deselect and wake up anyone waiting on the device */
David A. Marlin068e3c02005-01-24 03:07:46 +00001360 if (flags & NAND_GET_DEVICE)
1361 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363 /*
1364 * Return success, if no ECC failures, else -EBADMSG
1365 * fs driver will take care of that, because
1366 * retlen == desired len and result == -EBADMSG
1367 */
1368 *retlen = read;
1369 return ecc_failed ? -EBADMSG : 0;
1370}
1371
1372/**
1373 * nand_read_oob - [MTD Interface] NAND read out-of-band
1374 * @mtd: MTD device structure
1375 * @from: offset to read from
1376 * @len: number of bytes to read
1377 * @retlen: pointer to variable to store the number of read bytes
1378 * @buf: the databuffer to put data
1379 *
1380 * NAND read out-of-band data from the spare area
1381 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001382static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383{
1384 int i, col, page, chipnr;
1385 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +01001386 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
David Woodhousee0c7d762006-05-13 18:07:53 +01001388 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int)from, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390 /* Shift to get page */
1391 page = (int)(from >> this->page_shift);
1392 chipnr = (int)(from >> this->chip_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 /* Mask to get column */
1395 col = from & (mtd->oobsize - 1);
1396
1397 /* Initialize return length value */
1398 *retlen = 0;
1399
1400 /* Do not allow reads past end of device */
1401 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001402 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 *retlen = 0;
1404 return -EINVAL;
1405 }
1406
1407 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001408 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409
1410 /* Select the NAND device */
1411 this->select_chip(mtd, chipnr);
1412
1413 /* Send the read command */
David Woodhousee0c7d762006-05-13 18:07:53 +01001414 this->cmdfunc(mtd, NAND_CMD_READOOB, col, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001415 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 * Read the data, if we read more than one page
1417 * oob data, let the device transfer the data !
1418 */
1419 i = 0;
1420 while (i < len) {
1421 int thislen = mtd->oobsize - col;
1422 thislen = min_t(int, thislen, len);
1423 this->read_buf(mtd, &buf[i], thislen);
1424 i += thislen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
1426 /* Read more ? */
1427 if (i < len) {
1428 page++;
1429 col = 0;
1430
1431 /* Check, if we cross a chip boundary */
1432 if (!(page & this->pagemask)) {
1433 chipnr++;
1434 this->select_chip(mtd, -1);
1435 this->select_chip(mtd, chipnr);
1436 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001437
1438 /* Apply delay or wait for ready/busy pin
Thomas Gleixner19870da2005-07-15 14:53:51 +01001439 * Do this before the AUTOINCR check, so no problems
1440 * arise if a chip which does auto increment
1441 * is marked as NOAUTOINCR by the board driver.
1442 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001443 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001444 udelay(this->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001445 else
1446 nand_wait_ready(mtd);
1447
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001448 /* Check, if the chip supports auto page increment
1449 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001450 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {
1452 /* For subsequent page reads set offset to 0 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001453 this->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
1455 }
1456 }
1457
1458 /* Deselect and wake up anyone waiting on the device */
1459 nand_release_device(mtd);
1460
1461 /* Return happy */
1462 *retlen = len;
1463 return 0;
1464}
1465
1466/**
1467 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1468 * @mtd: MTD device structure
1469 * @buf: temporary buffer
1470 * @from: offset to read from
1471 * @len: number of bytes to read
1472 * @ooblen: number of oob data bytes to read
1473 *
1474 * Read raw data including oob into buffer
1475 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001476int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477{
1478 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +01001479 int page = (int)(from >> this->page_shift);
1480 int chip = (int)(from >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 int sndcmd = 1;
1482 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001483 int pagesize = mtd->writesize + mtd->oobsize;
David Woodhousee0c7d762006-05-13 18:07:53 +01001484 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
1486 /* Do not allow reads past end of device */
1487 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001488 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 return -EINVAL;
1490 }
1491
1492 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001493 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
David Woodhousee0c7d762006-05-13 18:07:53 +01001495 this->select_chip(mtd, chip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001496
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 /* Add requested oob length */
1498 len += ooblen;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001499
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 while (len) {
1501 if (sndcmd)
David Woodhousee0c7d762006-05-13 18:07:53 +01001502 this->cmdfunc(mtd, NAND_CMD_READ0, 0, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001503 sndcmd = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
David Woodhousee0c7d762006-05-13 18:07:53 +01001505 this->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
1507 len -= pagesize;
1508 cnt += pagesize;
1509 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001510
1511 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001512 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001514 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001515
1516 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
1518 sndcmd = 1;
1519 }
1520
1521 /* Deselect and wake up anyone waiting on the device */
1522 nand_release_device(mtd);
1523 return 0;
1524}
1525
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001526/**
1527 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 * @mtd: MTD device structure
1529 * @fsbuf: buffer given by fs driver
1530 * @oobsel: out of band selection structre
1531 * @autoplace: 1 = place given buffer into the oob bytes
1532 * @numpages: number of pages to prepare
1533 *
1534 * Return:
1535 * 1. Filesystem buffer available and autoplacement is off,
1536 * return filesystem buffer
1537 * 2. No filesystem buffer or autoplace is off, return internal
1538 * buffer
1539 * 3. Filesystem buffer is given and autoplace selected
1540 * put data from fs buffer into internal buffer and
1541 * retrun internal buffer
1542 *
1543 * Note: The internal buffer is filled with 0xff. This must
1544 * be done only once, when no autoplacement happens
1545 * Autoplacement sets the buffer dirty flag, which
1546 * forces the 0xff fill before using the buffer again.
1547 *
1548*/
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001549static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct nand_oobinfo *oobsel,
David Woodhousee0c7d762006-05-13 18:07:53 +01001550 int autoplace, int numpages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
1552 struct nand_chip *this = mtd->priv;
1553 int i, len, ofs;
1554
1555 /* Zero copy fs supplied buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001556 if (fsbuf && !autoplace)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 return fsbuf;
1558
1559 /* Check, if the buffer must be filled with ff again */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001560 if (this->oobdirty) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001561 memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 this->oobdirty = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001563 }
1564
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 /* If we have no autoplacement or no fs buffer use the internal one */
1566 if (!autoplace || !fsbuf)
1567 return this->oob_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001568
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 /* Walk through the pages and place the data */
1570 this->oobdirty = 1;
1571 ofs = 0;
1572 while (numpages--) {
1573 for (i = 0, len = 0; len < mtd->oobavail; i++) {
1574 int to = ofs + oobsel->oobfree[i][0];
1575 int num = oobsel->oobfree[i][1];
David Woodhousee0c7d762006-05-13 18:07:53 +01001576 memcpy(&this->oob_buf[to], fsbuf, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 len += num;
1578 fsbuf += num;
1579 }
1580 ofs += mtd->oobavail;
1581 }
1582 return this->oob_buf;
1583}
1584
Joern Engel28318772006-05-22 23:18:05 +02001585#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
1587/**
1588 * nand_write - [MTD Interface] compability function for nand_write_ecc
1589 * @mtd: MTD device structure
1590 * @to: offset to write to
1591 * @len: number of bytes to write
1592 * @retlen: pointer to variable to store the number of written bytes
1593 * @buf: the data to write
1594 *
1595 * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
1596 *
1597*/
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001598static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599{
David Woodhousee0c7d762006-05-13 18:07:53 +01001600 return (nand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001602
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603/**
1604 * nand_write_ecc - [MTD Interface] NAND write with ECC
1605 * @mtd: MTD device structure
1606 * @to: offset to write to
1607 * @len: number of bytes to write
1608 * @retlen: pointer to variable to store the number of written bytes
1609 * @buf: the data to write
1610 * @eccbuf: filesystem supplied oob data buffer
1611 * @oobsel: oob selection structure
1612 *
1613 * NAND write with ECC
1614 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001615static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001616 size_t *retlen, const uint8_t *buf, uint8_t *eccbuf,
David Woodhousee0c7d762006-05-13 18:07:53 +01001617 struct nand_oobinfo *oobsel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618{
1619 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
1620 int autoplace = 0, numpages, totalpages;
1621 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001622 uint8_t *oobbuf, *bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001623 int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
David Woodhousee0c7d762006-05-13 18:07:53 +01001625 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
1627 /* Initialize retlen, in case of early exit */
1628 *retlen = 0;
1629
1630 /* Do not allow write past end of device */
1631 if ((to + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001632 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 return -EINVAL;
1634 }
1635
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001636 /* reject writes, which are not page aligned */
David Woodhousee0c7d762006-05-13 18:07:53 +01001637 if (NOTALIGNED(to) || NOTALIGNED(len)) {
1638 printk(KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 return -EINVAL;
1640 }
1641
1642 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001643 nand_get_device(this, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645 /* Calculate chipnr */
1646 chipnr = (int)(to >> this->chip_shift);
1647 /* Select the NAND device */
1648 this->select_chip(mtd, chipnr);
1649
1650 /* Check, if it is write protected */
1651 if (nand_check_wp(mtd))
1652 goto out;
1653
1654 /* if oobsel is NULL, use chip defaults */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001655 if (oobsel == NULL)
1656 oobsel = &mtd->oobinfo;
1657
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 /* Autoplace of oob data ? Use the default placement scheme */
1659 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
1660 oobsel = this->autooob;
1661 autoplace = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001662 }
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001663 if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
1664 autoplace = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
1666 /* Setup variables and oob buffer */
1667 totalpages = len >> this->page_shift;
David Woodhousee0c7d762006-05-13 18:07:53 +01001668 page = (int)(to >> this->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001670 if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 this->pagebuf = -1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001672
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 /* Set it relative to chip */
1674 page &= this->pagemask;
1675 startpage = page;
1676 /* Calc number of pages we can write in one go */
David Woodhousee0c7d762006-05-13 18:07:53 +01001677 numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages);
1678 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001679 bufstart = (uint8_t *) buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
1681 /* Loop until all data is written */
1682 while (written < len) {
1683
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001684 this->data_poi = (uint8_t *) &buf[written];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 /* Write one page. If this is the last page to write
1686 * or the last page in this block, then use the
1687 * real pageprogram command, else select cached programming
1688 * if supported by the chip.
1689 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001690 ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 if (ret) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001692 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 /* Next oob page */
1696 oob += mtd->oobsize;
1697 /* Update written bytes count */
Joern Engel28318772006-05-22 23:18:05 +02001698 written += mtd->writesize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001699 if (written == len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 goto cmp;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001701
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 /* Increment page address */
1703 page++;
1704
1705 /* Have we hit a block boundary ? Then we have to verify and
1706 * if verify is ok, we have to setup the oob buffer for
1707 * the next pages.
David Woodhousee0c7d762006-05-13 18:07:53 +01001708 */
1709 if (!(page & (ppblock - 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 int ofs;
1711 this->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001712 ret = nand_verify_pages(mtd, this, startpage, page - startpage,
1713 oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 if (ret) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001715 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001717 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 *retlen = written;
1719
1720 ofs = autoplace ? mtd->oobavail : mtd->oobsize;
1721 if (eccbuf)
1722 eccbuf += (page - startpage) * ofs;
1723 totalpages -= page - startpage;
David Woodhousee0c7d762006-05-13 18:07:53 +01001724 numpages = min(totalpages, ppblock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 page &= this->pagemask;
1726 startpage = page;
David Woodhousee0c7d762006-05-13 18:07:53 +01001727 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Todd Poynor868801e2005-11-05 03:21:15 +00001728 oob = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 /* Check, if we cross a chip boundary */
1730 if (!page) {
1731 chipnr++;
1732 this->select_chip(mtd, -1);
1733 this->select_chip(mtd, chipnr);
1734 }
1735 }
1736 }
1737 /* Verify the remaining pages */
David Woodhousee0c7d762006-05-13 18:07:53 +01001738 cmp:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 this->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001740 ret = nand_verify_pages(mtd, this, startpage, totalpages, oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 if (!ret)
1742 *retlen = written;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001743 else
David Woodhousee0c7d762006-05-13 18:07:53 +01001744 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
David Woodhousee0c7d762006-05-13 18:07:53 +01001746 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 /* Deselect and wake up anyone waiting on the device */
1748 nand_release_device(mtd);
1749
1750 return ret;
1751}
1752
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753/**
1754 * nand_write_oob - [MTD Interface] NAND write out-of-band
1755 * @mtd: MTD device structure
1756 * @to: offset to write to
1757 * @len: number of bytes to write
1758 * @retlen: pointer to variable to store the number of written bytes
1759 * @buf: the data to write
1760 *
1761 * NAND write out-of-band
1762 */
Thomas Gleixner58dd8f22006-05-23 11:52:35 +02001763static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764{
1765 int column, page, status, ret = -EIO, chipnr;
1766 struct nand_chip *this = mtd->priv;
1767
David Woodhousee0c7d762006-05-13 18:07:53 +01001768 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
1770 /* Shift to get page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001771 page = (int)(to >> this->page_shift);
1772 chipnr = (int)(to >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774 /* Mask to get column */
1775 column = to & (mtd->oobsize - 1);
1776
1777 /* Initialize return length value */
1778 *retlen = 0;
1779
1780 /* Do not allow write past end of page */
1781 if ((column + len) > mtd->oobsize) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001782 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 return -EINVAL;
1784 }
1785
1786 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001787 nand_get_device(this, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788
1789 /* Select the NAND device */
1790 this->select_chip(mtd, chipnr);
1791
1792 /* Reset the chip. Some chips (like the Toshiba TC5832DC found
1793 in one of my DiskOnChip 2000 test units) will clear the whole
1794 data page too if we don't do this. I have no clue why, but
1795 I seem to have 'fixed' it in the doc2000 driver in
1796 August 1999. dwmw2. */
1797 this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
1798
1799 /* Check, if it is write protected */
1800 if (nand_check_wp(mtd))
1801 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001802
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 /* Invalidate the page cache, if we write to the cached page */
1804 if (page == this->pagebuf)
1805 this->pagebuf = -1;
1806
1807 if (NAND_MUST_PAD(this)) {
1808 /* Write out desired data */
Joern Engel28318772006-05-22 23:18:05 +02001809 this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 /* prepad 0xff for partial programming */
1811 this->write_buf(mtd, ffchars, column);
1812 /* write data */
1813 this->write_buf(mtd, buf, len);
1814 /* postpad 0xff for partial programming */
David Woodhousee0c7d762006-05-13 18:07:53 +01001815 this->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 } else {
1817 /* Write out desired data */
Joern Engel28318772006-05-22 23:18:05 +02001818 this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 /* write data */
1820 this->write_buf(mtd, buf, len);
1821 }
1822 /* Send command to program the OOB data */
David Woodhousee0c7d762006-05-13 18:07:53 +01001823 this->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824
David Woodhousee0c7d762006-05-13 18:07:53 +01001825 status = this->waitfunc(mtd, this, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
1827 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001828 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001829 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 ret = -EIO;
1831 goto out;
1832 }
1833 /* Return happy */
1834 *retlen = len;
1835
1836#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1837 /* Send command to read back the data */
David Woodhousee0c7d762006-05-13 18:07:53 +01001838 this->cmdfunc(mtd, NAND_CMD_READOOB, column, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
1840 if (this->verify_buf(mtd, buf, len)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001841 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 ret = -EIO;
1843 goto out;
1844 }
1845#endif
1846 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001847 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 /* Deselect and wake up anyone waiting on the device */
1849 nand_release_device(mtd);
1850
1851 return ret;
1852}
1853
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1856 * @mtd: MTD device structure
1857 * @page: the page address of the block which will be erased
1858 *
1859 * Standard erase command for NAND chips
1860 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001861static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862{
1863 struct nand_chip *this = mtd->priv;
1864 /* Send commands to erase a block */
David Woodhousee0c7d762006-05-13 18:07:53 +01001865 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1866 this->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867}
1868
1869/**
1870 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1871 * @mtd: MTD device structure
1872 * @page: the page address of the block which will be erased
1873 *
1874 * AND multi block erase command function
1875 * Erase 4 consecutive blocks
1876 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001877static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878{
1879 struct nand_chip *this = mtd->priv;
1880 /* Send commands to erase a block */
David Woodhousee0c7d762006-05-13 18:07:53 +01001881 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1882 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1883 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1884 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1885 this->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886}
1887
1888/**
1889 * nand_erase - [MTD Interface] erase block(s)
1890 * @mtd: MTD device structure
1891 * @instr: erase instruction
1892 *
1893 * Erase one ore more blocks
1894 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001895static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896{
David Woodhousee0c7d762006-05-13 18:07:53 +01001897 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001899
David A. Marlin30f464b2005-01-17 18:35:25 +00001900#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901/**
1902 * nand_erase_intern - [NAND Interface] erase block(s)
1903 * @mtd: MTD device structure
1904 * @instr: erase instruction
1905 * @allowbbt: allow erasing the bbt area
1906 *
1907 * Erase one ore more blocks
1908 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001909int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910{
1911 int page, len, status, pages_per_block, ret, chipnr;
1912 struct nand_chip *this = mtd->priv;
David A. Marlin30f464b2005-01-17 18:35:25 +00001913 int rewrite_bbt[NAND_MAX_CHIPS]={0}; /* flags to indicate the page, if bbt needs to be rewritten. */
1914 unsigned int bbt_masked_page; /* bbt mask to compare to page being erased. */
1915 /* It is used to see if the current page is in the same */
1916 /* 256 block group and the same bank as the bbt. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
David Woodhousee0c7d762006-05-13 18:07:53 +01001918 DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n", (unsigned int)instr->addr, (unsigned int)instr->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
1920 /* Start address must align on block boundary */
1921 if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001922 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 return -EINVAL;
1924 }
1925
1926 /* Length must align on block boundary */
1927 if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001928 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 return -EINVAL;
1930 }
1931
1932 /* Do not allow erase past end of device */
1933 if ((instr->len + instr->addr) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001934 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 return -EINVAL;
1936 }
1937
1938 instr->fail_addr = 0xffffffff;
1939
1940 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001941 nand_get_device(this, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
1943 /* Shift to get first page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001944 page = (int)(instr->addr >> this->page_shift);
1945 chipnr = (int)(instr->addr >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
1947 /* Calculate pages in each block */
1948 pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
1949
1950 /* Select the NAND device */
1951 this->select_chip(mtd, chipnr);
1952
1953 /* Check the WP bit */
1954 /* Check, if it is write protected */
1955 if (nand_check_wp(mtd)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001956 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 instr->state = MTD_ERASE_FAILED;
1958 goto erase_exit;
1959 }
1960
David A. Marlin30f464b2005-01-17 18:35:25 +00001961 /* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */
1962 if (this->options & BBT_AUTO_REFRESH) {
1963 bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
1964 } else {
1965 bbt_masked_page = 0xffffffff; /* should not match anything */
1966 }
1967
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 /* Loop through the pages */
1969 len = instr->len;
1970
1971 instr->state = MTD_ERASING;
1972
1973 while (len) {
1974 /* Check if we have a bad block, we do not erase bad blocks ! */
1975 if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001976 printk(KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 instr->state = MTD_ERASE_FAILED;
1978 goto erase_exit;
1979 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001980
1981 /* Invalidate the page cache, if we erase the block which contains
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 the current cached page */
1983 if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
1984 this->pagebuf = -1;
1985
David Woodhousee0c7d762006-05-13 18:07:53 +01001986 this->erase_cmd(mtd, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001987
David Woodhousee0c7d762006-05-13 18:07:53 +01001988 status = this->waitfunc(mtd, this, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
David A. Marlin068e3c02005-01-24 03:07:46 +00001990 /* See if operation failed and additional status checks are available */
1991 if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
1992 status = this->errstat(mtd, this, FL_ERASING, status, page);
1993 }
1994
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001996 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001997 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 instr->state = MTD_ERASE_FAILED;
1999 instr->fail_addr = (page << this->page_shift);
2000 goto erase_exit;
2001 }
David A. Marlin30f464b2005-01-17 18:35:25 +00002002
2003 /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */
2004 if (this->options & BBT_AUTO_REFRESH) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002005 if (((page & BBT_PAGE_MASK) == bbt_masked_page) &&
David A. Marlin30f464b2005-01-17 18:35:25 +00002006 (page != this->bbt_td->pages[chipnr])) {
2007 rewrite_bbt[chipnr] = (page << this->page_shift);
2008 }
2009 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002010
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 /* Increment page address and decrement length */
2012 len -= (1 << this->phys_erase_shift);
2013 page += pages_per_block;
2014
2015 /* Check, if we cross a chip boundary */
2016 if (len && !(page & this->pagemask)) {
2017 chipnr++;
2018 this->select_chip(mtd, -1);
2019 this->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00002020
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002021 /* if BBT requires refresh and BBT-PERCHIP,
David A. Marlin30f464b2005-01-17 18:35:25 +00002022 * set the BBT page mask to see if this BBT should be rewritten */
2023 if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) {
2024 bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
2025 }
2026
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 }
2028 }
2029 instr->state = MTD_ERASE_DONE;
2030
David Woodhousee0c7d762006-05-13 18:07:53 +01002031 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032
2033 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
2034 /* Do call back function */
2035 if (!ret)
2036 mtd_erase_callback(instr);
2037
2038 /* Deselect and wake up anyone waiting on the device */
2039 nand_release_device(mtd);
2040
David A. Marlin30f464b2005-01-17 18:35:25 +00002041 /* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */
2042 if ((this->options & BBT_AUTO_REFRESH) && (!ret)) {
2043 for (chipnr = 0; chipnr < this->numchips; chipnr++) {
2044 if (rewrite_bbt[chipnr]) {
2045 /* update the BBT for chip */
David Woodhousee0c7d762006-05-13 18:07:53 +01002046 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n",
2047 chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]);
2048 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00002049 }
2050 }
2051 }
2052
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 /* Return more or less happy */
2054 return ret;
2055}
2056
2057/**
2058 * nand_sync - [MTD Interface] sync
2059 * @mtd: MTD device structure
2060 *
2061 * Sync is actually a wait for chip ready function
2062 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002063static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064{
2065 struct nand_chip *this = mtd->priv;
2066
David Woodhousee0c7d762006-05-13 18:07:53 +01002067 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
2069 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01002070 nand_get_device(this, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01002072 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073}
2074
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075/**
2076 * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
2077 * @mtd: MTD device structure
2078 * @ofs: offset relative to mtd start
2079 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002080static int nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081{
2082 /* Check for invalid offset */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002083 if (ofs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002085
David Woodhousee0c7d762006-05-13 18:07:53 +01002086 return nand_block_checkbad(mtd, ofs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087}
2088
2089/**
2090 * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
2091 * @mtd: MTD device structure
2092 * @ofs: offset relative to mtd start
2093 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002094static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095{
2096 struct nand_chip *this = mtd->priv;
2097 int ret;
2098
David Woodhousee0c7d762006-05-13 18:07:53 +01002099 if ((ret = nand_block_isbad(mtd, ofs))) {
2100 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 if (ret > 0)
2102 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01002103 return ret;
2104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
2106 return this->block_markbad(mtd, ofs);
2107}
2108
2109/**
Vitaly Wool962034f2005-09-15 14:58:53 +01002110 * nand_suspend - [MTD Interface] Suspend the NAND flash
2111 * @mtd: MTD device structure
2112 */
2113static int nand_suspend(struct mtd_info *mtd)
2114{
2115 struct nand_chip *this = mtd->priv;
2116
David Woodhousee0c7d762006-05-13 18:07:53 +01002117 return nand_get_device(this, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01002118}
2119
2120/**
2121 * nand_resume - [MTD Interface] Resume the NAND flash
2122 * @mtd: MTD device structure
2123 */
2124static void nand_resume(struct mtd_info *mtd)
2125{
2126 struct nand_chip *this = mtd->priv;
2127
2128 if (this->state == FL_PM_SUSPENDED)
2129 nand_release_device(mtd);
2130 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02002131 printk(KERN_ERR "nand_resume() called for a chip which is not "
2132 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01002133}
2134
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002135/*
2136 * Free allocated data structures
2137 */
2138static void nand_free_kmem(struct nand_chip *this)
2139{
2140 /* Buffer allocated by nand_scan ? */
2141 if (this->options & NAND_OOBBUF_ALLOC)
2142 kfree(this->oob_buf);
2143 /* Buffer allocated by nand_scan ? */
2144 if (this->options & NAND_DATABUF_ALLOC)
2145 kfree(this->data_buf);
2146 /* Controller allocated by nand_scan ? */
2147 if (this->options & NAND_CONTROLLER_ALLOC)
2148 kfree(this->controller);
2149}
2150
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002151/*
2152 * Allocate buffers and data structures
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 */
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002154static int nand_allocate_kmem(struct mtd_info *mtd, struct nand_chip *this)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155{
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002156 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002158 if (!this->oob_buf) {
2159 len = mtd->oobsize <<
2160 (this->phys_erase_shift - this->page_shift);
2161 this->oob_buf = kmalloc(len, GFP_KERNEL);
2162 if (!this->oob_buf)
2163 goto outerr;
2164 this->options |= NAND_OOBBUF_ALLOC;
David Woodhouse552d9202006-05-14 01:20:46 +01002165 }
2166
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002167 if (!this->data_buf) {
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002168 len = mtd->writesize + mtd->oobsize;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002169 this->data_buf = kmalloc(len, GFP_KERNEL);
2170 if (!this->data_buf)
2171 goto outerr;
2172 this->options |= NAND_DATABUF_ALLOC;
2173 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002175 if (!this->controller) {
2176 this->controller = kzalloc(sizeof(struct nand_hw_control),
2177 GFP_KERNEL);
2178 if (!this->controller)
2179 goto outerr;
2180 this->options |= NAND_CONTROLLER_ALLOC;
2181 }
2182 return 0;
2183
2184 outerr:
2185 printk(KERN_ERR "nand_scan(): Cannot allocate buffers\n");
2186 nand_free_kmem(this);
2187 return -ENOMEM;
2188}
2189
2190/*
2191 * Set default functions
2192 */
2193static void nand_set_defaults(struct nand_chip *this, int busw)
2194{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 /* check for proper chip_delay setup, set 20us if not */
2196 if (!this->chip_delay)
2197 this->chip_delay = 20;
2198
2199 /* check, if a user supplied command function given */
2200 if (this->cmdfunc == NULL)
2201 this->cmdfunc = nand_command;
2202
2203 /* check, if a user supplied wait function given */
2204 if (this->waitfunc == NULL)
2205 this->waitfunc = nand_wait;
2206
2207 if (!this->select_chip)
2208 this->select_chip = nand_select_chip;
2209 if (!this->write_byte)
2210 this->write_byte = busw ? nand_write_byte16 : nand_write_byte;
2211 if (!this->read_byte)
2212 this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
2213 if (!this->write_word)
2214 this->write_word = nand_write_word;
2215 if (!this->read_word)
2216 this->read_word = nand_read_word;
2217 if (!this->block_bad)
2218 this->block_bad = nand_block_bad;
2219 if (!this->block_markbad)
2220 this->block_markbad = nand_default_block_markbad;
2221 if (!this->write_buf)
2222 this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
2223 if (!this->read_buf)
2224 this->read_buf = busw ? nand_read_buf16 : nand_read_buf;
2225 if (!this->verify_buf)
2226 this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
2227 if (!this->scan_bbt)
2228 this->scan_bbt = nand_default_bbt;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002229}
2230
2231/*
2232 * Get the flash and manufacturer id and lookup if the typ is supported
2233 */
2234static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2235 struct nand_chip *this,
2236 int busw, int *maf_id)
2237{
2238 struct nand_flash_dev *type = NULL;
2239 int i, dev_id, maf_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241 /* Select the device */
2242 this->select_chip(mtd, 0);
2243
2244 /* Send the command for reading device ID */
David Woodhousee0c7d762006-05-13 18:07:53 +01002245 this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246
2247 /* Read manufacturer and device IDs */
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002248 *maf_id = this->read_byte(mtd);
2249 dev_id = this->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002251 /* Lookup the flash id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002253 if (dev_id == nand_flash_ids[i].id) {
2254 type = &nand_flash_ids[i];
2255 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 }
2258
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002259 if (!type)
2260 return ERR_PTR(-ENODEV);
2261
2262 this->chipsize = nand_flash_ids[i].chipsize << 20;
2263
2264 /* Newer devices have all the information in additional id bytes */
2265 if (!nand_flash_ids[i].pagesize) {
2266 int extid;
2267 /* The 3rd id byte contains non relevant data ATM */
2268 extid = this->read_byte(mtd);
2269 /* The 4th id byte is the important one */
2270 extid = this->read_byte(mtd);
2271 /* Calc pagesize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002272 mtd->writesize = 1024 << (extid & 0x3);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002273 extid >>= 2;
2274 /* Calc oobsize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002275 mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002276 extid >>= 2;
2277 /* Calc blocksize. Blocksize is multiples of 64KiB */
2278 mtd->erasesize = (64 * 1024) << (extid & 0x03);
2279 extid >>= 2;
2280 /* Get buswidth information */
2281 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
2282
2283 } else {
2284 /*
2285 * Old devices have this data hardcoded in the device id table
2286 */
2287 mtd->erasesize = nand_flash_ids[i].erasesize;
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002288 mtd->writesize = nand_flash_ids[i].pagesize;
2289 mtd->oobsize = mtd->writesize / 32;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002290 busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
2291 }
2292
2293 /* Try to identify manufacturer */
2294 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
2295 if (nand_manuf_ids[maf_idx].id == *maf_id)
2296 break;
2297 }
2298
2299 /*
2300 * Check, if buswidth is correct. Hardware drivers should set
2301 * this correct !
2302 */
2303 if (busw != (this->options & NAND_BUSWIDTH_16)) {
2304 printk(KERN_INFO "NAND device: Manufacturer ID:"
2305 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2306 dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2307 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
2308 (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
2309 busw ? 16 : 8);
2310 return ERR_PTR(-EINVAL);
2311 }
2312
2313 /* Calculate the address shift from the page size */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002314 this->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002315 /* Convert chipsize to number of pages per chip -1. */
2316 this->pagemask = (this->chipsize >> this->page_shift) - 1;
2317
2318 this->bbt_erase_shift = this->phys_erase_shift =
2319 ffs(mtd->erasesize) - 1;
2320 this->chip_shift = ffs(this->chipsize) - 1;
2321
2322 /* Set the bad block position */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002323 this->badblockpos = mtd->writesize > 512 ?
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002324 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
2325
2326 /* Get chip options, preserve non chip based options */
2327 this->options &= ~NAND_CHIPOPTIONS_MSK;
2328 this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
2329
2330 /*
2331 * Set this as a default. Board drivers can override it, if necessary
2332 */
2333 this->options |= NAND_NO_AUTOINCR;
2334
2335 /* Check if this is a not a samsung device. Do not clear the
2336 * options for chips which are not having an extended id.
2337 */
2338 if (*maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
2339 this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
2340
2341 /* Check for AND chips with 4 page planes */
2342 if (this->options & NAND_4PAGE_ARRAY)
2343 this->erase_cmd = multi_erase_cmd;
2344 else
2345 this->erase_cmd = single_erase_cmd;
2346
2347 /* Do not replace user supplied command function ! */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002348 if (mtd->writesize > 512 && this->cmdfunc == nand_command)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002349 this->cmdfunc = nand_command_lp;
2350
2351 printk(KERN_INFO "NAND device: Manufacturer ID:"
2352 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
2353 nand_manuf_ids[maf_idx].name, type->name);
2354
2355 return type;
2356}
2357
2358/* module_text_address() isn't exported, and it's mostly a pointless
2359 test if this is a module _anyway_ -- they'd have to try _really_ hard
2360 to call us from in-kernel code if the core NAND support is modular. */
2361#ifdef MODULE
2362#define caller_is_module() (1)
2363#else
2364#define caller_is_module() \
2365 module_text_address((unsigned long)__builtin_return_address(0))
2366#endif
2367
2368/**
2369 * nand_scan - [NAND Interface] Scan for the NAND device
2370 * @mtd: MTD device structure
2371 * @maxchips: Number of chips to scan for
2372 *
2373 * This fills out all the uninitialized function pointers
2374 * with the defaults.
2375 * The flash ID is read and the mtd/chip structures are
2376 * filled with the appropriate values. Buffers are allocated if
2377 * they are not provided by the board driver
2378 * The mtd->owner field must be set to the module of the caller
2379 *
2380 */
2381int nand_scan(struct mtd_info *mtd, int maxchips)
2382{
2383 int i, busw, nand_maf_id;
2384 struct nand_chip *this = mtd->priv;
2385 struct nand_flash_dev *type;
2386
2387 /* Many callers got this wrong, so check for it for a while... */
2388 if (!mtd->owner && caller_is_module()) {
2389 printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
2390 BUG();
2391 }
2392
2393 /* Get buswidth to select the correct functions */
2394 busw = this->options & NAND_BUSWIDTH_16;
2395 /* Set the default functions */
2396 nand_set_defaults(this, busw);
2397
2398 /* Read the flash type */
2399 type = nand_get_flash_type(mtd, this, busw, &nand_maf_id);
2400
2401 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002402 printk(KERN_WARNING "No NAND device found!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 this->select_chip(mtd, -1);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002404 return PTR_ERR(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 }
2406
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002407 /* Check for a chip array */
David Woodhousee0c7d762006-05-13 18:07:53 +01002408 for (i = 1; i < maxchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 this->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 /* Send the command for reading device ID */
David Woodhousee0c7d762006-05-13 18:07:53 +01002411 this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 /* Read manufacturer and device IDs */
2413 if (nand_maf_id != this->read_byte(mtd) ||
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002414 type->id != this->read_byte(mtd))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 break;
2416 }
2417 if (i > 1)
2418 printk(KERN_INFO "%d NAND chips detected\n", i);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002419
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 /* Store the number of chips and calc total size for mtd */
2421 this->numchips = i;
2422 mtd->size = i * this->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002424 /* Allocate buffers and data structures */
2425 if (nand_allocate_kmem(mtd, this))
2426 return -ENOMEM;
2427
2428 /* Preset the internal oob buffer */
2429 memset(this->oob_buf, 0xff,
2430 mtd->oobsize << (this->phys_erase_shift - this->page_shift));
2431
2432 /*
2433 * If no default placement scheme is given, select an appropriate one
2434 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 if (!this->autooob) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002436 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 case 8:
2438 this->autooob = &nand_oob_8;
2439 break;
2440 case 16:
2441 this->autooob = &nand_oob_16;
2442 break;
2443 case 64:
2444 this->autooob = &nand_oob_64;
2445 break;
2446 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002447 printk(KERN_WARNING "No oob scheme defined for "
2448 "oobsize %d\n", mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 BUG();
2450 }
2451 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002452
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002453 /*
2454 * The number of bytes available for the filesystem to place fs
2455 * dependend oob data
2456 */
Thomas Gleixner998cf642005-04-01 08:21:48 +01002457 mtd->oobavail = 0;
2458 for (i = 0; this->autooob->oobfree[i][1]; i++)
2459 mtd->oobavail += this->autooob->oobfree[i][1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002461 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002462 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2463 * selected and we have 256 byte pagesize fallback to software ECC
David Woodhousee0c7d762006-05-13 18:07:53 +01002464 */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002465 switch (this->ecc.mode) {
2466 case NAND_ECC_HW:
2467 case NAND_ECC_HW_SYNDROME:
2468 if (!this->ecc.calculate || !this->ecc.correct ||
2469 !this->ecc.hwctl) {
2470 printk(KERN_WARNING "No ECC functions supplied, "
2471 "Hardware ECC not possible\n");
2472 BUG();
2473 }
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002474 if (mtd->writesize >= this->ecc.size)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002475 break;
2476 printk(KERN_WARNING "%d byte HW ECC not possible on "
2477 "%d byte page size, fallback to SW ECC\n",
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002478 this->ecc.size, mtd->writesize);
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002479 this->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002481 case NAND_ECC_SOFT:
2482 this->ecc.calculate = nand_calculate_ecc;
2483 this->ecc.correct = nand_correct_data;
2484 this->ecc.size = 256;
2485 this->ecc.bytes = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002487
2488 case NAND_ECC_NONE:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002489 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2490 "This is not recommended !!\n");
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002491 this->ecc.size = mtd->writesize;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002492 this->ecc.bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002495 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002496 this->ecc.mode);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002497 BUG();
2498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002500 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002501 * Set the number of read / write steps for one page depending on ECC
2502 * mode
2503 */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002504 this->ecc.steps = mtd->writesize / this->ecc.size;
2505 if(this->ecc.steps * this->ecc.size != mtd->writesize) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002506 printk(KERN_WARNING "Invalid ecc parameters\n");
2507 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002509
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 /* Initialize state, waitqueue and spinlock */
2511 this->state = FL_READY;
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002512 init_waitqueue_head(&this->controller->wq);
2513 spin_lock_init(&this->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514
2515 /* De-select the device */
2516 this->select_chip(mtd, -1);
2517
2518 /* Invalidate the pagebuffer reference */
2519 this->pagebuf = -1;
2520
2521 /* Fill in remaining MTD driver data */
2522 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002523 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 mtd->ecctype = MTD_ECC_SW;
2525 mtd->erase = nand_erase;
2526 mtd->point = NULL;
2527 mtd->unpoint = NULL;
2528 mtd->read = nand_read;
2529 mtd->write = nand_write;
2530 mtd->read_ecc = nand_read_ecc;
2531 mtd->write_ecc = nand_write_ecc;
2532 mtd->read_oob = nand_read_oob;
2533 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 mtd->sync = nand_sync;
2535 mtd->lock = NULL;
2536 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002537 mtd->suspend = nand_suspend;
2538 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 mtd->block_isbad = nand_block_isbad;
2540 mtd->block_markbad = nand_block_markbad;
2541
2542 /* and make the autooob the default one */
2543 memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
2544
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002545 /* Check, if we should skip the bad block table scan */
2546 if (this->options & NAND_SKIP_BBTSCAN)
2547 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
2549 /* Build bad block table */
David Woodhousee0c7d762006-05-13 18:07:53 +01002550 return this->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551}
2552
2553/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002554 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 * @mtd: MTD device structure
2556*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002557void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558{
2559 struct nand_chip *this = mtd->priv;
2560
2561#ifdef CONFIG_MTD_PARTITIONS
2562 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002563 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564#endif
2565 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002566 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
Jesper Juhlfa671642005-11-07 01:01:27 -08002568 /* Free bad block table memory */
David Woodhousee0c7d762006-05-13 18:07:53 +01002569 kfree(this->bbt);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002570 /* Free buffers */
2571 nand_free_kmem(this);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572}
2573
David Woodhousee0c7d762006-05-13 18:07:53 +01002574EXPORT_SYMBOL_GPL(nand_scan);
2575EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002576
2577static int __init nand_base_init(void)
2578{
2579 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2580 return 0;
2581}
2582
2583static void __exit nand_base_exit(void)
2584{
2585 led_trigger_unregister_simple(nand_led_trigger);
2586}
2587
2588module_init(nand_base_init);
2589module_exit(nand_base_exit);
2590
David Woodhousee0c7d762006-05-13 18:07:53 +01002591MODULE_LICENSE("GPL");
2592MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2593MODULE_DESCRIPTION("Generic NAND flash driver code");