blob: aa2e14538bf48ea3e2b5348cd306ba6af6184d2f [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 Gleixner58dd8f2b2006-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 Gleixner58dd8f2b2006-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 Gleixner58dd8f2b2006-05-23 11:52:35 +0200141 size_t *retlen, uint8_t *buf);
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200142static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200143 size_t *retlen, uint8_t *buf);
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200144static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200145 size_t *retlen, const uint8_t *buf);
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200146static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200147 size_t *retlen, const uint8_t *buf);
David Woodhousee0c7d762006-05-13 18:07:53 +0100148static int nand_erase(struct mtd_info *mtd, struct erase_info *instr);
149static void nand_sync(struct mtd_info *mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
151/* Some internal functions */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200152static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200153 int page, uint8_t * oob_buf,
David Woodhousee0c7d762006-05-13 18:07:53 +0100154 struct nand_oobinfo *oobsel, int mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200156static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200157 int page, int numpages, uint8_t *oob_buf,
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200158 struct nand_oobinfo *oobsel, int chipnr,
159 int oobmode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160#else
161#define nand_verify_pages(...) (0)
162#endif
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000163
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200164static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd,
165 int new_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167/**
168 * nand_release_device - [GENERIC] release chip
169 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000170 *
171 * Deselect, release chip lock and wake up anyone waiting on the device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100173static void nand_release_device(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174{
175 struct nand_chip *this = mtd->priv;
176
177 /* De-select the NAND device */
178 this->select_chip(mtd, -1);
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100179
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200180 /* Release the controller and the chip */
181 spin_lock(&this->controller->lock);
182 this->controller->active = NULL;
183 this->state = FL_READY;
184 wake_up(&this->controller->wq);
185 spin_unlock(&this->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186}
187
188/**
189 * nand_read_byte - [DEFAULT] read one byte from the chip
190 * @mtd: MTD device structure
191 *
192 * Default read function for 8bit buswith
193 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200194static uint8_t nand_read_byte(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195{
196 struct nand_chip *this = mtd->priv;
197 return readb(this->IO_ADDR_R);
198}
199
200/**
201 * nand_write_byte - [DEFAULT] write one byte to the chip
202 * @mtd: MTD device structure
203 * @byte: pointer to data byte to write
204 *
205 * Default write function for 8it buswith
206 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200207static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208{
209 struct nand_chip *this = mtd->priv;
210 writeb(byte, this->IO_ADDR_W);
211}
212
213/**
214 * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
215 * @mtd: MTD device structure
216 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000217 * Default read function for 16bit buswith with
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 * endianess conversion
219 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200220static uint8_t nand_read_byte16(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221{
222 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200223 return (uint8_t) cpu_to_le16(readw(this->IO_ADDR_R));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224}
225
226/**
227 * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip
228 * @mtd: MTD device structure
229 * @byte: pointer to data byte to write
230 *
231 * Default write function for 16bit buswith with
232 * endianess conversion
233 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200234static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235{
236 struct nand_chip *this = mtd->priv;
237 writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
238}
239
240/**
241 * nand_read_word - [DEFAULT] read one word from the chip
242 * @mtd: MTD device structure
243 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000244 * Default read function for 16bit buswith without
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 * endianess conversion
246 */
247static u16 nand_read_word(struct mtd_info *mtd)
248{
249 struct nand_chip *this = mtd->priv;
250 return readw(this->IO_ADDR_R);
251}
252
253/**
254 * nand_write_word - [DEFAULT] write one word to the chip
255 * @mtd: MTD device structure
256 * @word: data word to write
257 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000258 * Default write function for 16bit buswith without
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 * endianess conversion
260 */
261static void nand_write_word(struct mtd_info *mtd, u16 word)
262{
263 struct nand_chip *this = mtd->priv;
264 writew(word, this->IO_ADDR_W);
265}
266
267/**
268 * nand_select_chip - [DEFAULT] control CE line
269 * @mtd: MTD device structure
270 * @chip: chipnumber to select, -1 for deselect
271 *
272 * Default select function for 1 chip devices.
273 */
274static void nand_select_chip(struct mtd_info *mtd, int chip)
275{
276 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100277 switch (chip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 case -1:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000279 this->hwcontrol(mtd, NAND_CTL_CLRNCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 break;
281 case 0:
282 this->hwcontrol(mtd, NAND_CTL_SETNCE);
283 break;
284
285 default:
286 BUG();
287 }
288}
289
290/**
291 * nand_write_buf - [DEFAULT] write buffer to chip
292 * @mtd: MTD device structure
293 * @buf: data buffer
294 * @len: number of bytes to write
295 *
296 * Default write function for 8bit buswith
297 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200298static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299{
300 int i;
301 struct nand_chip *this = mtd->priv;
302
David Woodhousee0c7d762006-05-13 18:07:53 +0100303 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 writeb(buf[i], this->IO_ADDR_W);
305}
306
307/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000308 * nand_read_buf - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 * @mtd: MTD device structure
310 * @buf: buffer to store date
311 * @len: number of bytes to read
312 *
313 * Default read function for 8bit buswith
314 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200315static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316{
317 int i;
318 struct nand_chip *this = mtd->priv;
319
David Woodhousee0c7d762006-05-13 18:07:53 +0100320 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 buf[i] = readb(this->IO_ADDR_R);
322}
323
324/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000325 * nand_verify_buf - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 * @mtd: MTD device structure
327 * @buf: buffer containing the data to compare
328 * @len: number of bytes to compare
329 *
330 * Default verify function for 8bit buswith
331 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200332static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333{
334 int i;
335 struct nand_chip *this = mtd->priv;
336
David Woodhousee0c7d762006-05-13 18:07:53 +0100337 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 if (buf[i] != readb(this->IO_ADDR_R))
339 return -EFAULT;
340
341 return 0;
342}
343
344/**
345 * nand_write_buf16 - [DEFAULT] write buffer to chip
346 * @mtd: MTD device structure
347 * @buf: data buffer
348 * @len: number of bytes to write
349 *
350 * Default write function for 16bit buswith
351 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200352static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353{
354 int i;
355 struct nand_chip *this = mtd->priv;
356 u16 *p = (u16 *) buf;
357 len >>= 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000358
David Woodhousee0c7d762006-05-13 18:07:53 +0100359 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 writew(p[i], this->IO_ADDR_W);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000361
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362}
363
364/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000365 * nand_read_buf16 - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 * @mtd: MTD device structure
367 * @buf: buffer to store date
368 * @len: number of bytes to read
369 *
370 * Default read function for 16bit buswith
371 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200372static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 int i;
375 struct nand_chip *this = mtd->priv;
376 u16 *p = (u16 *) buf;
377 len >>= 1;
378
David Woodhousee0c7d762006-05-13 18:07:53 +0100379 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 p[i] = readw(this->IO_ADDR_R);
381}
382
383/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000384 * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 * @mtd: MTD device structure
386 * @buf: buffer containing the data to compare
387 * @len: number of bytes to compare
388 *
389 * Default verify function for 16bit buswith
390 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200391static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
393 int i;
394 struct nand_chip *this = mtd->priv;
395 u16 *p = (u16 *) buf;
396 len >>= 1;
397
David Woodhousee0c7d762006-05-13 18:07:53 +0100398 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 if (p[i] != readw(this->IO_ADDR_R))
400 return -EFAULT;
401
402 return 0;
403}
404
405/**
406 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
407 * @mtd: MTD device structure
408 * @ofs: offset from device start
409 * @getchip: 0, if the chip is already selected
410 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000411 * Check, if the block is bad.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 */
413static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
414{
415 int page, chipnr, res = 0;
416 struct nand_chip *this = mtd->priv;
417 u16 bad;
418
419 if (getchip) {
420 page = (int)(ofs >> this->page_shift);
421 chipnr = (int)(ofs >> this->chip_shift);
422
423 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +0100424 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
426 /* Select the NAND device */
427 this->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000428 } else
David Woodhousee0c7d762006-05-13 18:07:53 +0100429 page = (int)ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
431 if (this->options & NAND_BUSWIDTH_16) {
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200432 this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE,
433 page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 bad = cpu_to_le16(this->read_word(mtd));
435 if (this->badblockpos & 0x1)
Vitaly Wool49196f32005-11-02 16:54:46 +0000436 bad >>= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 if ((bad & 0xFF) != 0xff)
438 res = 1;
439 } else {
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200440 this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos,
441 page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 if (this->read_byte(mtd) != 0xff)
443 res = 1;
444 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000445
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 if (getchip) {
447 /* Deselect and wake up anyone waiting on the device */
448 nand_release_device(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000449 }
450
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 return res;
452}
453
454/**
455 * nand_default_block_markbad - [DEFAULT] mark a block bad
456 * @mtd: MTD device structure
457 * @ofs: offset from device start
458 *
459 * This is the default implementation, which can be overridden by
460 * a hardware specific driver.
461*/
462static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
463{
464 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200465 uint8_t buf[2] = { 0, 0 };
David Woodhousee0c7d762006-05-13 18:07:53 +0100466 size_t retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 int block;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000468
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 /* Get block number */
David Woodhousee0c7d762006-05-13 18:07:53 +0100470 block = ((int)ofs) >> this->bbt_erase_shift;
Artem B. Bityuckiy41ce9212005-02-09 14:50:00 +0000471 if (this->bbt)
472 this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
474 /* Do we have a flash based bad block table ? */
475 if (this->options & NAND_USE_FLASH_BBT)
David Woodhousee0c7d762006-05-13 18:07:53 +0100476 return nand_update_bbt(mtd, ofs);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 /* We write two bytes, so we dont have to mess with 16 bit access */
479 ofs += mtd->oobsize + (this->badblockpos & ~0x01);
David Woodhousee0c7d762006-05-13 18:07:53 +0100480 return nand_write_oob(mtd, ofs, 2, &retlen, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481}
482
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000483/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 * nand_check_wp - [GENERIC] check if the chip is write protected
485 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000486 * Check, if the device is write protected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000488 * The function expects, that the device is already selected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100490static int nand_check_wp(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
492 struct nand_chip *this = mtd->priv;
493 /* Check the WP bit */
David Woodhousee0c7d762006-05-13 18:07:53 +0100494 this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000495 return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496}
497
498/**
499 * nand_block_checkbad - [GENERIC] Check if a block is marked bad
500 * @mtd: MTD device structure
501 * @ofs: offset from device start
502 * @getchip: 0, if the chip is already selected
503 * @allowbbt: 1, if its allowed to access the bbt area
504 *
505 * Check, if the block is bad. Either by reading the bad block table or
506 * calling of the scan function.
507 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200508static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
509 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510{
511 struct nand_chip *this = mtd->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000512
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 if (!this->bbt)
514 return this->block_bad(mtd, ofs, getchip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000515
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 /* Return info from the table */
David Woodhousee0c7d762006-05-13 18:07:53 +0100517 return nand_isbad_bbt(mtd, ofs, allowbbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518}
519
Richard Purdie8fe833c2006-03-31 02:31:14 -0800520DEFINE_LED_TRIGGER(nand_led_trigger);
521
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000522/*
Thomas Gleixner3b887752005-02-22 21:56:49 +0000523 * Wait for the ready pin, after a command
524 * The timeout is catched later.
525 */
526static void nand_wait_ready(struct mtd_info *mtd)
527{
528 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100529 unsigned long timeo = jiffies + 2;
Thomas Gleixner3b887752005-02-22 21:56:49 +0000530
Richard Purdie8fe833c2006-03-31 02:31:14 -0800531 led_trigger_event(nand_led_trigger, LED_FULL);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000532 /* wait until command is processed or timeout occures */
533 do {
534 if (this->dev_ready(mtd))
Richard Purdie8fe833c2006-03-31 02:31:14 -0800535 break;
Ingo Molnar8446f1d2005-09-06 15:16:27 -0700536 touch_softlockup_watchdog();
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000537 } while (time_before(jiffies, timeo));
Richard Purdie8fe833c2006-03-31 02:31:14 -0800538 led_trigger_event(nand_led_trigger, LED_OFF);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000539}
540
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541/**
542 * nand_command - [DEFAULT] Send command to NAND device
543 * @mtd: MTD device structure
544 * @command: the command to be sent
545 * @column: the column address for this command, -1 if none
546 * @page_addr: the page address for this command, -1 if none
547 *
548 * Send command to NAND device. This function is used for small page
549 * devices (256/512 Bytes per page)
550 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200551static void nand_command(struct mtd_info *mtd, unsigned command, int column,
552 int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
554 register struct nand_chip *this = mtd->priv;
555
556 /* Begin command latch cycle */
557 this->hwcontrol(mtd, NAND_CTL_SETCLE);
558 /*
559 * Write out the command to the device.
560 */
561 if (command == NAND_CMD_SEQIN) {
562 int readcmd;
563
Joern Engel28318772006-05-22 23:18:05 +0200564 if (column >= mtd->writesize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 /* OOB area */
Joern Engel28318772006-05-22 23:18:05 +0200566 column -= mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 readcmd = NAND_CMD_READOOB;
568 } else if (column < 256) {
569 /* First 256 bytes --> READ0 */
570 readcmd = NAND_CMD_READ0;
571 } else {
572 column -= 256;
573 readcmd = NAND_CMD_READ1;
574 }
575 this->write_byte(mtd, readcmd);
576 }
577 this->write_byte(mtd, command);
578
579 /* Set ALE and clear CLE to start address cycle */
580 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
581
582 if (column != -1 || page_addr != -1) {
583 this->hwcontrol(mtd, NAND_CTL_SETALE);
584
585 /* Serially input address */
586 if (column != -1) {
587 /* Adjust columns for 16 bit buswidth */
588 if (this->options & NAND_BUSWIDTH_16)
589 column >>= 1;
590 this->write_byte(mtd, column);
591 }
592 if (page_addr != -1) {
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200593 this->write_byte(mtd, (uint8_t)(page_addr & 0xff));
594 this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 /* One more address cycle for devices > 32MiB */
596 if (this->chipsize > (32 << 20))
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200597 this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0x0f));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 }
599 /* Latch in address */
600 this->hwcontrol(mtd, NAND_CTL_CLRALE);
601 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000602
603 /*
604 * program and erase have their own busy handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 * status and sequential in needs no delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100606 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000608
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 case NAND_CMD_PAGEPROG:
610 case NAND_CMD_ERASE1:
611 case NAND_CMD_ERASE2:
612 case NAND_CMD_SEQIN:
613 case NAND_CMD_STATUS:
614 return;
615
616 case NAND_CMD_RESET:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000617 if (this->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 break;
619 udelay(this->chip_delay);
620 this->hwcontrol(mtd, NAND_CTL_SETCLE);
621 this->write_byte(mtd, NAND_CMD_STATUS);
622 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
David Woodhousee0c7d762006-05-13 18:07:53 +0100623 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 return;
625
David Woodhousee0c7d762006-05-13 18:07:53 +0100626 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000628 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 * If we don't have access to the busy pin, we apply the given
630 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100631 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 if (!this->dev_ready) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100633 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 /* Apply this short delay always to ensure that we do wait tWB in
638 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100639 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000640
641 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642}
643
644/**
645 * nand_command_lp - [DEFAULT] Send command to NAND large page device
646 * @mtd: MTD device structure
647 * @command: the command to be sent
648 * @column: the column address for this command, -1 if none
649 * @page_addr: the page address for this command, -1 if none
650 *
651 * Send command to NAND device. This is the version for the new large page devices
David Woodhousee0c7d762006-05-13 18:07:53 +0100652 * We dont have the separate regions as we have in the small page devices.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 * We must emulate NAND_CMD_READOOB to keep the code compatible.
654 *
655 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100656static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
658 register struct nand_chip *this = mtd->priv;
659
660 /* Emulate NAND_CMD_READOOB */
661 if (command == NAND_CMD_READOOB) {
Joern Engel28318772006-05-22 23:18:05 +0200662 column += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 command = NAND_CMD_READ0;
664 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000665
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 /* Begin command latch cycle */
667 this->hwcontrol(mtd, NAND_CTL_SETCLE);
668 /* Write out the command to the device. */
David A. Marlin30f464b2005-01-17 18:35:25 +0000669 this->write_byte(mtd, (command & 0xff));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 /* End command latch cycle */
671 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
672
673 if (column != -1 || page_addr != -1) {
674 this->hwcontrol(mtd, NAND_CTL_SETALE);
675
676 /* Serially input address */
677 if (column != -1) {
678 /* Adjust columns for 16 bit buswidth */
679 if (this->options & NAND_BUSWIDTH_16)
680 column >>= 1;
681 this->write_byte(mtd, column & 0xff);
682 this->write_byte(mtd, column >> 8);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 if (page_addr != -1) {
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200685 this->write_byte(mtd, (uint8_t)(page_addr & 0xff));
686 this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 /* One more address cycle for devices > 128MiB */
688 if (this->chipsize > (128 << 20))
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200689 this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0xff));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 }
691 /* Latch in address */
692 this->hwcontrol(mtd, NAND_CTL_CLRALE);
693 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000694
695 /*
696 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000697 * status, sequential in, and deplete1 need no delay
698 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000700
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 case NAND_CMD_CACHEDPROG:
702 case NAND_CMD_PAGEPROG:
703 case NAND_CMD_ERASE1:
704 case NAND_CMD_ERASE2:
705 case NAND_CMD_SEQIN:
706 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000707 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 return;
709
David Woodhousee0c7d762006-05-13 18:07:53 +0100710 /*
711 * read error status commands require only a short delay
712 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000713 case NAND_CMD_STATUS_ERROR:
714 case NAND_CMD_STATUS_ERROR0:
715 case NAND_CMD_STATUS_ERROR1:
716 case NAND_CMD_STATUS_ERROR2:
717 case NAND_CMD_STATUS_ERROR3:
718 udelay(this->chip_delay);
719 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 case NAND_CMD_RESET:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000722 if (this->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 break;
724 udelay(this->chip_delay);
725 this->hwcontrol(mtd, NAND_CTL_SETCLE);
726 this->write_byte(mtd, NAND_CMD_STATUS);
727 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
David Woodhousee0c7d762006-05-13 18:07:53 +0100728 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 return;
730
731 case NAND_CMD_READ0:
732 /* Begin command latch cycle */
733 this->hwcontrol(mtd, NAND_CTL_SETCLE);
734 /* Write out the start read command */
735 this->write_byte(mtd, NAND_CMD_READSTART);
736 /* End command latch cycle */
737 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
738 /* Fall through into ready check */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000739
David Woodhousee0c7d762006-05-13 18:07:53 +0100740 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000742 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 * If we don't have access to the busy pin, we apply the given
744 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100745 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 if (!this->dev_ready) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100747 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000749 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 /* Apply this short delay always to ensure that we do wait tWB in
753 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100754 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000755
756 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757}
758
759/**
760 * nand_get_device - [GENERIC] Get chip for selected access
761 * @this: the nand chip descriptor
762 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000763 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 *
765 * Get the device and lock it for exclusive access
766 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200767static int
768nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769{
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200770 spinlock_t *lock = &this->controller->lock;
771 wait_queue_head_t *wq = &this->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100772 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100773 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100774 spin_lock(lock);
775
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200777 /* Hardware controller shared among independend devices */
778 if (!this->controller->active)
779 this->controller->active = this;
780
781 if (this->controller->active == this && this->state == FL_READY) {
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100782 this->state = new_state;
783 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100784 return 0;
785 }
786 if (new_state == FL_PM_SUSPENDED) {
787 spin_unlock(lock);
788 return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100789 }
790 set_current_state(TASK_UNINTERRUPTIBLE);
791 add_wait_queue(wq, &wait);
792 spin_unlock(lock);
793 schedule();
794 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 goto retry;
796}
797
798/**
799 * nand_wait - [DEFAULT] wait until the command is done
800 * @mtd: MTD device structure
801 * @this: NAND chip structure
802 * @state: state to select the max. timeout value
803 *
804 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000805 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 * general NAND and SmartMedia specs
807 *
808*/
809static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
810{
811
David Woodhousee0c7d762006-05-13 18:07:53 +0100812 unsigned long timeo = jiffies;
813 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000814
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100816 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100818 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Richard Purdie8fe833c2006-03-31 02:31:14 -0800820 led_trigger_event(nand_led_trigger, LED_FULL);
821
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 /* Apply this short delay always to ensure that we do wait tWB in
823 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100824 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
826 if ((state == FL_ERASING) && (this->options & NAND_IS_AND))
David Woodhousee0c7d762006-05-13 18:07:53 +0100827 this->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000828 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100829 this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000831 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 /* Check, if we were interrupted */
833 if (this->state != state)
834 return 0;
835
836 if (this->dev_ready) {
837 if (this->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000838 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 } else {
840 if (this->read_byte(mtd) & NAND_STATUS_READY)
841 break;
842 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000843 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800845 led_trigger_event(nand_led_trigger, LED_OFF);
846
David Woodhousee0c7d762006-05-13 18:07:53 +0100847 status = (int)this->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 return status;
849}
850
851/**
852 * nand_write_page - [GENERIC] write one page
853 * @mtd: MTD device structure
854 * @this: NAND chip structure
855 * @page: startpage inside the chip, must be called with (page & this->pagemask)
856 * @oob_buf: out of band data buffer
857 * @oobsel: out of band selecttion structre
858 * @cached: 1 = enable cached programming if supported by chip
859 *
860 * Nand_page_program function is used for write and writev !
861 * This function will always program a full page of data
862 * If you call it with a non page aligned buffer, you're lost :)
863 *
864 * Cached programming is not supported yet.
865 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100866static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int page,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200867 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int cached)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868{
David Woodhousee0c7d762006-05-13 18:07:53 +0100869 int i, status;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200870 uint8_t ecc_code[32];
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200871 int eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
David Woodhousee0c7d762006-05-13 18:07:53 +0100872 int *oob_config = oobsel->eccpos;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200873 int datidx = 0, eccidx = 0, eccsteps = this->ecc.steps;
David Woodhousee0c7d762006-05-13 18:07:53 +0100874 int eccbytes = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000875
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 /* FIXME: Enable cached programming */
877 cached = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 /* Send command to begin auto page programming */
David Woodhousee0c7d762006-05-13 18:07:53 +0100880 this->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
882 /* Write out complete page of data, take care of eccmode */
883 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100884 /* No ecc, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 case NAND_ECC_NONE:
David Woodhousee0c7d762006-05-13 18:07:53 +0100886 printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
Joern Engel28318772006-05-22 23:18:05 +0200887 this->write_buf(mtd, this->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000889
David Woodhousee0c7d762006-05-13 18:07:53 +0100890 /* Software ecc 3/256, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 case NAND_ECC_SOFT:
892 for (; eccsteps; eccsteps--) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200893 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 for (i = 0; i < 3; i++, eccidx++)
895 oob_buf[oob_config[eccidx]] = ecc_code[i];
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200896 datidx += this->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 }
Joern Engel28318772006-05-22 23:18:05 +0200898 this->write_buf(mtd, this->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 break;
900 default:
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200901 eccbytes = this->ecc.bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 for (; eccsteps; eccsteps--) {
903 /* enable hardware ecc logic for write */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200904 this->ecc.hwctl(mtd, NAND_ECC_WRITE);
905 this->write_buf(mtd, &this->data_poi[datidx], this->ecc.size);
906 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 for (i = 0; i < eccbytes; i++, eccidx++)
908 oob_buf[oob_config[eccidx]] = ecc_code[i];
909 /* If the hardware ecc provides syndromes then
910 * the ecc code must be written immidiately after
911 * the data bytes (words) */
912 if (this->options & NAND_HWECC_SYNDROME)
913 this->write_buf(mtd, ecc_code, eccbytes);
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200914 datidx += this->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 }
916 break;
917 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 /* Write out OOB data */
920 if (this->options & NAND_HWECC_SYNDROME)
921 this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000922 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 this->write_buf(mtd, oob_buf, mtd->oobsize);
924
925 /* Send command to actually program the data */
David Woodhousee0c7d762006-05-13 18:07:53 +0100926 this->cmdfunc(mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928 if (!cached) {
929 /* call wait ready function */
David Woodhousee0c7d762006-05-13 18:07:53 +0100930 status = this->waitfunc(mtd, this, FL_WRITING);
David A. Marlin068e3c02005-01-24 03:07:46 +0000931
932 /* See if operation failed and additional status checks are available */
933 if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
934 status = this->errstat(mtd, this, FL_WRITING, status, page);
935 }
936
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +0000938 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100939 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 return -EIO;
941 }
942 } else {
943 /* FIXME: Implement cached programming ! */
David Woodhousee0c7d762006-05-13 18:07:53 +0100944 /* wait until cache is ready */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 // status = this->waitfunc (mtd, this, FL_CACHEDRPG);
946 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000947 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948}
949
950#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
951/**
952 * nand_verify_pages - [GENERIC] verify the chip contents after a write
953 * @mtd: MTD device structure
954 * @this: NAND chip structure
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200955 * @page: startpage inside the chip, must be called with (page & this->pagemask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 * @numpages: number of pages to verify
957 * @oob_buf: out of band data buffer
958 * @oobsel: out of band selecttion structre
959 * @chipnr: number of the current chip
960 * @oobmode: 1 = full buffer verify, 0 = ecc only
961 *
962 * The NAND device assumes that it is always writing to a cleanly erased page.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000963 * Hence, it performs its internal write verification only on bits that
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 * transitioned from 1 to 0. The device does NOT verify the whole page on a
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000965 * byte by byte basis. It is possible that the page was not completely erased
966 * or the page is becoming unusable due to wear. The read with ECC would catch
967 * the error later when the ECC page check fails, but we would rather catch
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 * it early in the page write stage. Better to write no data than invalid data.
969 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100970static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200971 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972{
David Woodhousee0c7d762006-05-13 18:07:53 +0100973 int i, j, datidx = 0, oobofs = 0, res = -EIO;
974 int eccsteps = this->eccsteps;
975 int hweccbytes;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200976 uint8_t oobdata[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
978 hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
979
980 /* Send command to read back the first page */
David Woodhousee0c7d762006-05-13 18:07:53 +0100981 this->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
David Woodhousee0c7d762006-05-13 18:07:53 +0100983 for (;;) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 for (j = 0; j < eccsteps; j++) {
985 /* Loop through and verify the data */
986 if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100987 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 goto out;
989 }
990 datidx += mtd->eccsize;
991 /* Have we a hw generator layout ? */
992 if (!hweccbytes)
993 continue;
994 if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100995 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 goto out;
997 }
998 oobofs += hweccbytes;
999 }
1000
1001 /* check, if we must compare all data or if we just have to
1002 * compare the ecc bytes
1003 */
1004 if (oobmode) {
1005 if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001006 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 goto out;
1008 }
1009 } else {
1010 /* Read always, else autoincrement fails */
1011 this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
1012
1013 if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
1014 int ecccnt = oobsel->eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 for (i = 0; i < ecccnt; i++) {
1017 int idx = oobsel->eccpos[i];
David Woodhousee0c7d762006-05-13 18:07:53 +01001018 if (oobdata[idx] != oob_buf[oobofs + idx]) {
1019 DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed ECC write verify, page 0x%08x, %6i bytes were succesful\n",
1020 __FUNCTION__, page, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 goto out;
1022 }
1023 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001024 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 }
1026 oobofs += mtd->oobsize - hweccbytes * eccsteps;
1027 page++;
1028 numpages--;
1029
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001030 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 * Do this before the AUTOINCR check, so no problems
1032 * arise if a chip which does auto increment
1033 * is marked as NOAUTOINCR by the board driver.
1034 * Do this also before returning, so the chip is
1035 * ready for the next command.
David Woodhousee0c7d762006-05-13 18:07:53 +01001036 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001037 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001038 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001040 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
1042 /* All done, return happy */
1043 if (!numpages)
1044 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001045
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001046 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 if (!NAND_CANAUTOINCR(this))
David Woodhousee0c7d762006-05-13 18:07:53 +01001048 this->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001050 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 * Terminate the read command. We come here in case of an error
1052 * So we must issue a reset command.
1053 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001054 out:
1055 this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 return res;
1057}
1058#endif
1059
1060/**
David A. Marlin068e3c02005-01-24 03:07:46 +00001061 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 * @mtd: MTD device structure
1063 * @from: offset to read from
1064 * @len: number of bytes to read
1065 * @retlen: pointer to variable to store the number of read bytes
1066 * @buf: the databuffer to put data
1067 *
David A. Marlin068e3c02005-01-24 03:07:46 +00001068 * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL
1069 * and flags = 0xff
1070 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001071static 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 -07001072{
David Woodhousee0c7d762006-05-13 18:07:53 +01001073 return nand_do_read_ecc(mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001074}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076/**
David A. Marlin068e3c02005-01-24 03:07:46 +00001077 * nand_do_read_ecc - [MTD Interface] Read data with ECC
1078 * @mtd: MTD device structure
1079 * @from: offset to read from
1080 * @len: number of bytes to read
1081 * @retlen: pointer to variable to store the number of read bytes
1082 * @buf: the databuffer to put data
Dan Brownbb75ba42005-04-04 19:02:26 +01001083 * @oob_buf: filesystem supplied oob data buffer (can be NULL)
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001084 * @oobsel: oob selection structure
David A. Marlin068e3c02005-01-24 03:07:46 +00001085 * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed
1086 * and how many corrected error bits are acceptable:
1087 * bits 0..7 - number of tolerable errors
1088 * bit 8 - 0 == do not get/release chip, 1 == get/release chip
1089 *
1090 * NAND read with ECC
1091 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001092int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001093 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel, int flags)
David A. Marlin068e3c02005-01-24 03:07:46 +00001094{
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
1097 int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
1098 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001099 uint8_t *data_poi, *oob_data = oob_buf;
1100 uint8_t ecc_calc[32];
1101 uint8_t ecc_code[32];
David Woodhousee0c7d762006-05-13 18:07:53 +01001102 int eccmode, eccsteps;
1103 int *oob_config, datidx;
1104 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
1105 int eccbytes;
1106 int compareecc = 1;
1107 int oobreadlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
David Woodhousee0c7d762006-05-13 18:07:53 +01001109 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 -07001110
1111 /* Do not allow reads past end of device */
1112 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001113 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 *retlen = 0;
1115 return -EINVAL;
1116 }
1117
1118 /* Grab the lock and see if the device is available */
David A. Marlin068e3c02005-01-24 03:07:46 +00001119 if (flags & NAND_GET_DEVICE)
David Woodhousee0c7d762006-05-13 18:07:53 +01001120 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 /* Autoplace of oob data ? Use the default placement scheme */
1123 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
1124 oobsel = this->autooob;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001125
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001126 eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 oob_config = oobsel->eccpos;
1128
1129 /* Select the NAND device */
1130 chipnr = (int)(from >> this->chip_shift);
1131 this->select_chip(mtd, chipnr);
1132
1133 /* First we calculate the starting page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001134 realpage = (int)(from >> this->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 page = realpage & this->pagemask;
1136
1137 /* Get raw starting column */
Joern Engel28318772006-05-22 23:18:05 +02001138 col = from & (mtd->writesize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Joern Engel28318772006-05-22 23:18:05 +02001140 end = mtd->writesize;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001141 ecc = this->ecc.size;
1142 eccbytes = this->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001143
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
1145 compareecc = 0;
1146
1147 oobreadlen = mtd->oobsize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001148 if (this->options & NAND_HWECC_SYNDROME)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 oobreadlen -= oobsel->eccbytes;
1150
1151 /* Loop until all data read */
1152 while (read < len) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001153
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 int aligned = (!col && (len - read) >= end);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001155 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 * If the read is not page aligned, we have to read into data buffer
1157 * due to ecc, else we read into return buffer direct
1158 */
1159 if (aligned)
1160 data_poi = &buf[read];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001161 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 data_poi = this->data_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001163
1164 /* Check, if we have this page in the buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 *
1166 * FIXME: Make it work when we must provide oob data too,
1167 * check the usage of data_buf oob field
1168 */
1169 if (realpage == this->pagebuf && !oob_buf) {
1170 /* aligned read ? */
1171 if (aligned)
David Woodhousee0c7d762006-05-13 18:07:53 +01001172 memcpy(data_poi, this->data_buf, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 goto readdata;
1174 }
1175
1176 /* Check, if we must send the read command */
1177 if (sndcmd) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001178 this->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 sndcmd = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182 /* get oob area, if we have no oob buffer from fs-driver */
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001183 if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
1184 oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 oob_data = &this->data_buf[end];
1186
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001187 eccsteps = this->ecc.steps;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001188
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001190 case NAND_ECC_NONE:{
1191 /* No ECC, Read in a page */
1192 static unsigned long lastwhinge = 0;
1193 if ((lastwhinge / HZ) != (jiffies / HZ)) {
1194 printk(KERN_WARNING
1195 "Reading data from NAND FLASH without ECC is not recommended\n");
1196 lastwhinge = jiffies;
1197 }
1198 this->read_buf(mtd, data_poi, end);
1199 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
1203 this->read_buf(mtd, data_poi, end);
David Woodhousee0c7d762006-05-13 18:07:53 +01001204 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001205 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001206 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
1208 default:
David Woodhousee0c7d762006-05-13 18:07:53 +01001209 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001210 this->ecc.hwctl(mtd, NAND_ECC_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 this->read_buf(mtd, &data_poi[datidx], ecc);
1212
1213 /* HW ecc with syndrome calculation must read the
1214 * syndrome from flash immidiately after the data */
1215 if (!compareecc) {
1216 /* Some hw ecc generators need to know when the
1217 * syndrome is read from flash */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001218 this->ecc.hwctl(mtd, NAND_ECC_READSYN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 this->read_buf(mtd, &oob_data[i], eccbytes);
1220 /* We calc error correction directly, it checks the hw
1221 * generator for an error, reads back the syndrome and
1222 * does the error correction on the fly */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001223 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
David A. Marlin068e3c02005-01-24 03:07:46 +00001224 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001225 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
1226 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 ecc_failed++;
1228 }
1229 } else {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001230 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001233 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
1235
1236 /* read oobdata */
1237 this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
1238
1239 /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
1240 if (!compareecc)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001241 goto readoob;
1242
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 /* Pick the ECC bytes out of the oob data */
1244 for (j = 0; j < oobsel->eccbytes; j++)
1245 ecc_code[j] = oob_data[oob_config[j]];
1246
David Woodhousee0c7d762006-05-13 18:07:53 +01001247 /* correct data, if necessary */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001248 for (i = 0, j = 0, datidx = 0; i < this->ecc.steps; i++, datidx += ecc) {
1249 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 /* Get next chunk of ecc bytes */
1252 j += eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001253
1254 /* Check, if we have a fs supplied oob-buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 * This is the legacy mode. Used by YAFFS1
1256 * Should go away some day
1257 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001258 if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 int *p = (int *)(&oob_data[mtd->oobsize]);
1260 p[i] = ecc_status;
1261 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001262
1263 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001264 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 ecc_failed++;
1266 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
David Woodhousee0c7d762006-05-13 18:07:53 +01001269 readoob:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 /* check, if we have a fs supplied oob-buffer */
1271 if (oob_buf) {
1272 /* without autoplace. Legacy mode used by YAFFS1 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001273 switch (oobsel->useecc) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 case MTD_NANDECC_AUTOPLACE:
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001275 case MTD_NANDECC_AUTOPL_USR:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 /* Walk through the autoplace chunks */
Dan Brown82e1d192005-04-06 21:13:09 +01001277 for (i = 0; oobsel->oobfree[i][1]; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 int from = oobsel->oobfree[i][0];
1279 int num = oobsel->oobfree[i][1];
1280 memcpy(&oob_buf[oob], &oob_data[from], num);
Dan Brown82e1d192005-04-06 21:13:09 +01001281 oob += num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 break;
1284 case MTD_NANDECC_PLACE:
1285 /* YAFFS1 legacy mode */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001286 oob_data += this->ecc.steps * sizeof(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 default:
1288 oob_data += mtd->oobsize;
1289 }
1290 }
1291 readdata:
1292 /* Partial page read, transfer data into fs buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001293 if (!aligned) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 for (j = col; j < end && read < len; j++)
1295 buf[read++] = data_poi[j];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001296 this->pagebuf = realpage;
1297 } else
Joern Engel28318772006-05-22 23:18:05 +02001298 read += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001300 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 * Do this before the AUTOINCR check, so no problems
1302 * arise if a chip which does auto increment
1303 * is marked as NOAUTOINCR by the board driver.
David Woodhousee0c7d762006-05-13 18:07:53 +01001304 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001305 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001306 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001308 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001309
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 if (read == len)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001311 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
1313 /* For subsequent reads align to page boundary. */
1314 col = 0;
1315 /* Increment page address */
1316 realpage++;
1317
1318 page = realpage & this->pagemask;
1319 /* Check, if we cross a chip boundary */
1320 if (!page) {
1321 chipnr++;
1322 this->select_chip(mtd, -1);
1323 this->select_chip(mtd, chipnr);
1324 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001325 /* Check, if the chip supports auto page increment
1326 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001327 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001329 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 }
1331
1332 /* Deselect and wake up anyone waiting on the device */
David A. Marlin068e3c02005-01-24 03:07:46 +00001333 if (flags & NAND_GET_DEVICE)
1334 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
1336 /*
1337 * Return success, if no ECC failures, else -EBADMSG
1338 * fs driver will take care of that, because
1339 * retlen == desired len and result == -EBADMSG
1340 */
1341 *retlen = read;
1342 return ecc_failed ? -EBADMSG : 0;
1343}
1344
1345/**
1346 * nand_read_oob - [MTD Interface] NAND read out-of-band
1347 * @mtd: MTD device structure
1348 * @from: offset to read from
1349 * @len: number of bytes to read
1350 * @retlen: pointer to variable to store the number of read bytes
1351 * @buf: the databuffer to put data
1352 *
1353 * NAND read out-of-band data from the spare area
1354 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001355static 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 -07001356{
1357 int i, col, page, chipnr;
1358 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +01001359 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
David Woodhousee0c7d762006-05-13 18:07:53 +01001361 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 -07001362
1363 /* Shift to get page */
1364 page = (int)(from >> this->page_shift);
1365 chipnr = (int)(from >> this->chip_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001366
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 /* Mask to get column */
1368 col = from & (mtd->oobsize - 1);
1369
1370 /* Initialize return length value */
1371 *retlen = 0;
1372
1373 /* Do not allow reads past end of device */
1374 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001375 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 *retlen = 0;
1377 return -EINVAL;
1378 }
1379
1380 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001381 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
1383 /* Select the NAND device */
1384 this->select_chip(mtd, chipnr);
1385
1386 /* Send the read command */
David Woodhousee0c7d762006-05-13 18:07:53 +01001387 this->cmdfunc(mtd, NAND_CMD_READOOB, col, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001388 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 * Read the data, if we read more than one page
1390 * oob data, let the device transfer the data !
1391 */
1392 i = 0;
1393 while (i < len) {
1394 int thislen = mtd->oobsize - col;
1395 thislen = min_t(int, thislen, len);
1396 this->read_buf(mtd, &buf[i], thislen);
1397 i += thislen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
1399 /* Read more ? */
1400 if (i < len) {
1401 page++;
1402 col = 0;
1403
1404 /* Check, if we cross a chip boundary */
1405 if (!(page & this->pagemask)) {
1406 chipnr++;
1407 this->select_chip(mtd, -1);
1408 this->select_chip(mtd, chipnr);
1409 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001410
1411 /* Apply delay or wait for ready/busy pin
Thomas Gleixner19870da2005-07-15 14:53:51 +01001412 * Do this before the AUTOINCR check, so no problems
1413 * arise if a chip which does auto increment
1414 * is marked as NOAUTOINCR by the board driver.
1415 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001416 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001417 udelay(this->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001418 else
1419 nand_wait_ready(mtd);
1420
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001421 /* Check, if the chip supports auto page increment
1422 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001423 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {
1425 /* For subsequent page reads set offset to 0 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001426 this->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 }
1428 }
1429 }
1430
1431 /* Deselect and wake up anyone waiting on the device */
1432 nand_release_device(mtd);
1433
1434 /* Return happy */
1435 *retlen = len;
1436 return 0;
1437}
1438
1439/**
1440 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1441 * @mtd: MTD device structure
1442 * @buf: temporary buffer
1443 * @from: offset to read from
1444 * @len: number of bytes to read
1445 * @ooblen: number of oob data bytes to read
1446 *
1447 * Read raw data including oob into buffer
1448 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001449int 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 -07001450{
1451 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +01001452 int page = (int)(from >> this->page_shift);
1453 int chip = (int)(from >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 int sndcmd = 1;
1455 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001456 int pagesize = mtd->writesize + mtd->oobsize;
David Woodhousee0c7d762006-05-13 18:07:53 +01001457 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 /* Do not allow reads past end of device */
1460 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001461 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 return -EINVAL;
1463 }
1464
1465 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001466 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
David Woodhousee0c7d762006-05-13 18:07:53 +01001468 this->select_chip(mtd, chip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001469
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 /* Add requested oob length */
1471 len += ooblen;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001472
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 while (len) {
1474 if (sndcmd)
David Woodhousee0c7d762006-05-13 18:07:53 +01001475 this->cmdfunc(mtd, NAND_CMD_READ0, 0, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001476 sndcmd = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
David Woodhousee0c7d762006-05-13 18:07:53 +01001478 this->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
1480 len -= pagesize;
1481 cnt += pagesize;
1482 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001483
1484 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001485 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001487 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001488
1489 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
1491 sndcmd = 1;
1492 }
1493
1494 /* Deselect and wake up anyone waiting on the device */
1495 nand_release_device(mtd);
1496 return 0;
1497}
1498
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001499/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001500 * nand_write_raw - [GENERIC] Write raw data including oob
1501 * @mtd: MTD device structure
1502 * @buf: source buffer
1503 * @to: offset to write to
1504 * @len: number of bytes to write
1505 * @buf: source buffer
1506 * @oob: oob buffer
1507 *
1508 * Write raw data including oob
1509 */
1510int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1511 uint8_t *buf, uint8_t *oob)
1512{
1513 struct nand_chip *this = mtd->priv;
1514 int page = (int)(to >> this->page_shift);
1515 int chip = (int)(to >> this->chip_shift);
1516 int ret;
1517
1518 *retlen = 0;
1519
1520 /* Do not allow writes past end of device */
1521 if ((to + len) > mtd->size) {
1522 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1523 "beyond end of device\n");
1524 return -EINVAL;
1525 }
1526
1527 /* Grab the lock and see if the device is available */
1528 nand_get_device(this, mtd, FL_WRITING);
1529
1530 this->select_chip(mtd, chip);
1531 this->data_poi = buf;
1532
1533 while (len != *retlen) {
1534 ret = nand_write_page(mtd, this, page, oob, &mtd->oobinfo, 0);
1535 if (ret)
1536 return ret;
1537 page++;
1538 *retlen += mtd->writesize;
1539 this->data_poi += mtd->writesize;
1540 oob += mtd->oobsize;
1541 }
1542
1543 /* Deselect and wake up anyone waiting on the device */
1544 nand_release_device(mtd);
1545 return 0;
1546}
Thomas Gleixner38217202006-05-23 22:33:52 +02001547EXPORT_SYMBOL_GPL(nand_write_raw);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001548
1549/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001550 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 * @mtd: MTD device structure
1552 * @fsbuf: buffer given by fs driver
1553 * @oobsel: out of band selection structre
1554 * @autoplace: 1 = place given buffer into the oob bytes
1555 * @numpages: number of pages to prepare
1556 *
1557 * Return:
1558 * 1. Filesystem buffer available and autoplacement is off,
1559 * return filesystem buffer
1560 * 2. No filesystem buffer or autoplace is off, return internal
1561 * buffer
1562 * 3. Filesystem buffer is given and autoplace selected
1563 * put data from fs buffer into internal buffer and
1564 * retrun internal buffer
1565 *
1566 * Note: The internal buffer is filled with 0xff. This must
1567 * be done only once, when no autoplacement happens
1568 * Autoplacement sets the buffer dirty flag, which
1569 * forces the 0xff fill before using the buffer again.
1570 *
1571*/
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001572static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct nand_oobinfo *oobsel,
David Woodhousee0c7d762006-05-13 18:07:53 +01001573 int autoplace, int numpages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574{
1575 struct nand_chip *this = mtd->priv;
1576 int i, len, ofs;
1577
1578 /* Zero copy fs supplied buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001579 if (fsbuf && !autoplace)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 return fsbuf;
1581
1582 /* Check, if the buffer must be filled with ff again */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001583 if (this->oobdirty) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001584 memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 this->oobdirty = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001586 }
1587
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 /* If we have no autoplacement or no fs buffer use the internal one */
1589 if (!autoplace || !fsbuf)
1590 return this->oob_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001591
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 /* Walk through the pages and place the data */
1593 this->oobdirty = 1;
1594 ofs = 0;
1595 while (numpages--) {
1596 for (i = 0, len = 0; len < mtd->oobavail; i++) {
1597 int to = ofs + oobsel->oobfree[i][0];
1598 int num = oobsel->oobfree[i][1];
David Woodhousee0c7d762006-05-13 18:07:53 +01001599 memcpy(&this->oob_buf[to], fsbuf, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 len += num;
1601 fsbuf += num;
1602 }
1603 ofs += mtd->oobavail;
1604 }
1605 return this->oob_buf;
1606}
1607
Joern Engel28318772006-05-22 23:18:05 +02001608#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609
1610/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001611 * nand_write - [MTD Interface] NAND write with ECC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 * @mtd: MTD device structure
1613 * @to: offset to write to
1614 * @len: number of bytes to write
1615 * @retlen: pointer to variable to store the number of written bytes
1616 * @buf: the data to write
1617 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 * NAND write with ECC
1619 */
Thomas Gleixner9223a452006-05-23 17:21:03 +02001620static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1621 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622{
1623 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
1624 int autoplace = 0, numpages, totalpages;
1625 struct nand_chip *this = mtd->priv;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001626 uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
David Woodhousee0c7d762006-05-13 18:07:53 +01001627 int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
Thomas Gleixner9223a452006-05-23 17:21:03 +02001628 struct nand_oobinfo *oobsel = &mtd->oobinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
Thomas Gleixner9223a452006-05-23 17:21:03 +02001630 DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
1632 /* Initialize retlen, in case of early exit */
1633 *retlen = 0;
1634
1635 /* Do not allow write past end of device */
1636 if ((to + len) > mtd->size) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001637 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 return -EINVAL;
1639 }
1640
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001641 /* reject writes, which are not page aligned */
David Woodhousee0c7d762006-05-13 18:07:53 +01001642 if (NOTALIGNED(to) || NOTALIGNED(len)) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001643 printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 return -EINVAL;
1645 }
1646
1647 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001648 nand_get_device(this, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
1650 /* Calculate chipnr */
1651 chipnr = (int)(to >> this->chip_shift);
1652 /* Select the NAND device */
1653 this->select_chip(mtd, chipnr);
1654
1655 /* Check, if it is write protected */
1656 if (nand_check_wp(mtd))
1657 goto out;
1658
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 /* Autoplace of oob data ? Use the default placement scheme */
1660 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
1661 oobsel = this->autooob;
1662 autoplace = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001663 }
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001664 if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
1665 autoplace = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
1667 /* Setup variables and oob buffer */
1668 totalpages = len >> this->page_shift;
David Woodhousee0c7d762006-05-13 18:07:53 +01001669 page = (int)(to >> this->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001671 if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 this->pagebuf = -1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001673
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 /* Set it relative to chip */
1675 page &= this->pagemask;
1676 startpage = page;
1677 /* Calc number of pages we can write in one go */
David Woodhousee0c7d762006-05-13 18:07:53 +01001678 numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages);
1679 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001680 bufstart = (uint8_t *) buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
1682 /* Loop until all data is written */
1683 while (written < len) {
1684
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001685 this->data_poi = (uint8_t *) &buf[written];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 /* Write one page. If this is the last page to write
1687 * or the last page in this block, then use the
1688 * real pageprogram command, else select cached programming
1689 * if supported by the chip.
1690 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001691 ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001693 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 /* Next oob page */
1697 oob += mtd->oobsize;
1698 /* Update written bytes count */
Joern Engel28318772006-05-22 23:18:05 +02001699 written += mtd->writesize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001700 if (written == len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 goto cmp;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001702
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 /* Increment page address */
1704 page++;
1705
1706 /* Have we hit a block boundary ? Then we have to verify and
1707 * if verify is ok, we have to setup the oob buffer for
1708 * the next pages.
David Woodhousee0c7d762006-05-13 18:07:53 +01001709 */
1710 if (!(page & (ppblock - 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 int ofs;
1712 this->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001713 ret = nand_verify_pages(mtd, this, startpage, page - startpage,
1714 oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001716 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001718 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 *retlen = written;
1720
1721 ofs = autoplace ? mtd->oobavail : mtd->oobsize;
1722 if (eccbuf)
1723 eccbuf += (page - startpage) * ofs;
1724 totalpages -= page - startpage;
David Woodhousee0c7d762006-05-13 18:07:53 +01001725 numpages = min(totalpages, ppblock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 page &= this->pagemask;
1727 startpage = page;
David Woodhousee0c7d762006-05-13 18:07:53 +01001728 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Todd Poynor868801e2005-11-05 03:21:15 +00001729 oob = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 /* Check, if we cross a chip boundary */
1731 if (!page) {
1732 chipnr++;
1733 this->select_chip(mtd, -1);
1734 this->select_chip(mtd, chipnr);
1735 }
1736 }
1737 }
1738 /* Verify the remaining pages */
David Woodhousee0c7d762006-05-13 18:07:53 +01001739 cmp:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 this->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001741 ret = nand_verify_pages(mtd, this, startpage, totalpages, oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 if (!ret)
1743 *retlen = written;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001744 else
Thomas Gleixner9223a452006-05-23 17:21:03 +02001745 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
David Woodhousee0c7d762006-05-13 18:07:53 +01001747 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 /* Deselect and wake up anyone waiting on the device */
1749 nand_release_device(mtd);
1750
1751 return ret;
1752}
1753
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754/**
1755 * nand_write_oob - [MTD Interface] NAND write out-of-band
1756 * @mtd: MTD device structure
1757 * @to: offset to write to
1758 * @len: number of bytes to write
1759 * @retlen: pointer to variable to store the number of written bytes
1760 * @buf: the data to write
1761 *
1762 * NAND write out-of-band
1763 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001764static 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 -07001765{
1766 int column, page, status, ret = -EIO, chipnr;
1767 struct nand_chip *this = mtd->priv;
1768
David Woodhousee0c7d762006-05-13 18:07:53 +01001769 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 -07001770
1771 /* Shift to get page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001772 page = (int)(to >> this->page_shift);
1773 chipnr = (int)(to >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
1775 /* Mask to get column */
1776 column = to & (mtd->oobsize - 1);
1777
1778 /* Initialize return length value */
1779 *retlen = 0;
1780
1781 /* Do not allow write past end of page */
1782 if ((column + len) > mtd->oobsize) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001783 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 return -EINVAL;
1785 }
1786
1787 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001788 nand_get_device(this, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789
1790 /* Select the NAND device */
1791 this->select_chip(mtd, chipnr);
1792
1793 /* Reset the chip. Some chips (like the Toshiba TC5832DC found
1794 in one of my DiskOnChip 2000 test units) will clear the whole
1795 data page too if we don't do this. I have no clue why, but
1796 I seem to have 'fixed' it in the doc2000 driver in
1797 August 1999. dwmw2. */
1798 this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
1799
1800 /* Check, if it is write protected */
1801 if (nand_check_wp(mtd))
1802 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001803
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 /* Invalidate the page cache, if we write to the cached page */
1805 if (page == this->pagebuf)
1806 this->pagebuf = -1;
1807
1808 if (NAND_MUST_PAD(this)) {
1809 /* Write out desired data */
Joern Engel28318772006-05-22 23:18:05 +02001810 this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 /* prepad 0xff for partial programming */
1812 this->write_buf(mtd, ffchars, column);
1813 /* write data */
1814 this->write_buf(mtd, buf, len);
1815 /* postpad 0xff for partial programming */
David Woodhousee0c7d762006-05-13 18:07:53 +01001816 this->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 } else {
1818 /* Write out desired data */
Joern Engel28318772006-05-22 23:18:05 +02001819 this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 /* write data */
1821 this->write_buf(mtd, buf, len);
1822 }
1823 /* Send command to program the OOB data */
David Woodhousee0c7d762006-05-13 18:07:53 +01001824 this->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
David Woodhousee0c7d762006-05-13 18:07:53 +01001826 status = this->waitfunc(mtd, this, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
1828 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001829 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001830 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 ret = -EIO;
1832 goto out;
1833 }
1834 /* Return happy */
1835 *retlen = len;
1836
1837#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1838 /* Send command to read back the data */
David Woodhousee0c7d762006-05-13 18:07:53 +01001839 this->cmdfunc(mtd, NAND_CMD_READOOB, column, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840
1841 if (this->verify_buf(mtd, buf, len)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001842 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 ret = -EIO;
1844 goto out;
1845 }
1846#endif
1847 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001848 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 /* Deselect and wake up anyone waiting on the device */
1850 nand_release_device(mtd);
1851
1852 return ret;
1853}
1854
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1857 * @mtd: MTD device structure
1858 * @page: the page address of the block which will be erased
1859 *
1860 * Standard erase command for NAND chips
1861 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001862static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863{
1864 struct nand_chip *this = mtd->priv;
1865 /* Send commands to erase a block */
David Woodhousee0c7d762006-05-13 18:07:53 +01001866 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1867 this->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868}
1869
1870/**
1871 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1872 * @mtd: MTD device structure
1873 * @page: the page address of the block which will be erased
1874 *
1875 * AND multi block erase command function
1876 * Erase 4 consecutive blocks
1877 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001878static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879{
1880 struct nand_chip *this = mtd->priv;
1881 /* Send commands to erase a block */
David Woodhousee0c7d762006-05-13 18:07:53 +01001882 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_ERASE1, -1, page);
1886 this->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887}
1888
1889/**
1890 * nand_erase - [MTD Interface] erase block(s)
1891 * @mtd: MTD device structure
1892 * @instr: erase instruction
1893 *
1894 * Erase one ore more blocks
1895 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001896static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897{
David Woodhousee0c7d762006-05-13 18:07:53 +01001898 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001900
David A. Marlin30f464b2005-01-17 18:35:25 +00001901#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902/**
1903 * nand_erase_intern - [NAND Interface] erase block(s)
1904 * @mtd: MTD device structure
1905 * @instr: erase instruction
1906 * @allowbbt: allow erasing the bbt area
1907 *
1908 * Erase one ore more blocks
1909 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001910int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911{
1912 int page, len, status, pages_per_block, ret, chipnr;
1913 struct nand_chip *this = mtd->priv;
David A. Marlin30f464b2005-01-17 18:35:25 +00001914 int rewrite_bbt[NAND_MAX_CHIPS]={0}; /* flags to indicate the page, if bbt needs to be rewritten. */
1915 unsigned int bbt_masked_page; /* bbt mask to compare to page being erased. */
1916 /* It is used to see if the current page is in the same */
1917 /* 256 block group and the same bank as the bbt. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918
David Woodhousee0c7d762006-05-13 18:07:53 +01001919 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 -07001920
1921 /* Start address must align on block boundary */
1922 if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001923 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 return -EINVAL;
1925 }
1926
1927 /* Length must align on block boundary */
1928 if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001929 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 return -EINVAL;
1931 }
1932
1933 /* Do not allow erase past end of device */
1934 if ((instr->len + instr->addr) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001935 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 return -EINVAL;
1937 }
1938
1939 instr->fail_addr = 0xffffffff;
1940
1941 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001942 nand_get_device(this, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943
1944 /* Shift to get first page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001945 page = (int)(instr->addr >> this->page_shift);
1946 chipnr = (int)(instr->addr >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947
1948 /* Calculate pages in each block */
1949 pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
1950
1951 /* Select the NAND device */
1952 this->select_chip(mtd, chipnr);
1953
1954 /* Check the WP bit */
1955 /* Check, if it is write protected */
1956 if (nand_check_wp(mtd)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001957 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 instr->state = MTD_ERASE_FAILED;
1959 goto erase_exit;
1960 }
1961
David A. Marlin30f464b2005-01-17 18:35:25 +00001962 /* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */
1963 if (this->options & BBT_AUTO_REFRESH) {
1964 bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
1965 } else {
1966 bbt_masked_page = 0xffffffff; /* should not match anything */
1967 }
1968
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 /* Loop through the pages */
1970 len = instr->len;
1971
1972 instr->state = MTD_ERASING;
1973
1974 while (len) {
1975 /* Check if we have a bad block, we do not erase bad blocks ! */
1976 if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001977 printk(KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 instr->state = MTD_ERASE_FAILED;
1979 goto erase_exit;
1980 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001981
1982 /* Invalidate the page cache, if we erase the block which contains
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 the current cached page */
1984 if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
1985 this->pagebuf = -1;
1986
David Woodhousee0c7d762006-05-13 18:07:53 +01001987 this->erase_cmd(mtd, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001988
David Woodhousee0c7d762006-05-13 18:07:53 +01001989 status = this->waitfunc(mtd, this, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
David A. Marlin068e3c02005-01-24 03:07:46 +00001991 /* See if operation failed and additional status checks are available */
1992 if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
1993 status = this->errstat(mtd, this, FL_ERASING, status, page);
1994 }
1995
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001997 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001998 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 instr->state = MTD_ERASE_FAILED;
2000 instr->fail_addr = (page << this->page_shift);
2001 goto erase_exit;
2002 }
David A. Marlin30f464b2005-01-17 18:35:25 +00002003
2004 /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */
2005 if (this->options & BBT_AUTO_REFRESH) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002006 if (((page & BBT_PAGE_MASK) == bbt_masked_page) &&
David A. Marlin30f464b2005-01-17 18:35:25 +00002007 (page != this->bbt_td->pages[chipnr])) {
2008 rewrite_bbt[chipnr] = (page << this->page_shift);
2009 }
2010 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002011
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 /* Increment page address and decrement length */
2013 len -= (1 << this->phys_erase_shift);
2014 page += pages_per_block;
2015
2016 /* Check, if we cross a chip boundary */
2017 if (len && !(page & this->pagemask)) {
2018 chipnr++;
2019 this->select_chip(mtd, -1);
2020 this->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00002021
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002022 /* if BBT requires refresh and BBT-PERCHIP,
David A. Marlin30f464b2005-01-17 18:35:25 +00002023 * set the BBT page mask to see if this BBT should be rewritten */
2024 if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) {
2025 bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
2026 }
2027
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 }
2029 }
2030 instr->state = MTD_ERASE_DONE;
2031
David Woodhousee0c7d762006-05-13 18:07:53 +01002032 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
2034 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
2035 /* Do call back function */
2036 if (!ret)
2037 mtd_erase_callback(instr);
2038
2039 /* Deselect and wake up anyone waiting on the device */
2040 nand_release_device(mtd);
2041
David A. Marlin30f464b2005-01-17 18:35:25 +00002042 /* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */
2043 if ((this->options & BBT_AUTO_REFRESH) && (!ret)) {
2044 for (chipnr = 0; chipnr < this->numchips; chipnr++) {
2045 if (rewrite_bbt[chipnr]) {
2046 /* update the BBT for chip */
David Woodhousee0c7d762006-05-13 18:07:53 +01002047 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n",
2048 chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]);
2049 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00002050 }
2051 }
2052 }
2053
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 /* Return more or less happy */
2055 return ret;
2056}
2057
2058/**
2059 * nand_sync - [MTD Interface] sync
2060 * @mtd: MTD device structure
2061 *
2062 * Sync is actually a wait for chip ready function
2063 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002064static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065{
2066 struct nand_chip *this = mtd->priv;
2067
David Woodhousee0c7d762006-05-13 18:07:53 +01002068 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
2070 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01002071 nand_get_device(this, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01002073 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074}
2075
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076/**
2077 * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
2078 * @mtd: MTD device structure
2079 * @ofs: offset relative to mtd start
2080 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002081static int nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082{
2083 /* Check for invalid offset */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002084 if (ofs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002086
David Woodhousee0c7d762006-05-13 18:07:53 +01002087 return nand_block_checkbad(mtd, ofs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088}
2089
2090/**
2091 * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
2092 * @mtd: MTD device structure
2093 * @ofs: offset relative to mtd start
2094 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002095static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096{
2097 struct nand_chip *this = mtd->priv;
2098 int ret;
2099
David Woodhousee0c7d762006-05-13 18:07:53 +01002100 if ((ret = nand_block_isbad(mtd, ofs))) {
2101 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 if (ret > 0)
2103 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01002104 return ret;
2105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
2107 return this->block_markbad(mtd, ofs);
2108}
2109
2110/**
Vitaly Wool962034f2005-09-15 14:58:53 +01002111 * nand_suspend - [MTD Interface] Suspend the NAND flash
2112 * @mtd: MTD device structure
2113 */
2114static int nand_suspend(struct mtd_info *mtd)
2115{
2116 struct nand_chip *this = mtd->priv;
2117
David Woodhousee0c7d762006-05-13 18:07:53 +01002118 return nand_get_device(this, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01002119}
2120
2121/**
2122 * nand_resume - [MTD Interface] Resume the NAND flash
2123 * @mtd: MTD device structure
2124 */
2125static void nand_resume(struct mtd_info *mtd)
2126{
2127 struct nand_chip *this = mtd->priv;
2128
2129 if (this->state == FL_PM_SUSPENDED)
2130 nand_release_device(mtd);
2131 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02002132 printk(KERN_ERR "nand_resume() called for a chip which is not "
2133 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01002134}
2135
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002136/*
2137 * Free allocated data structures
2138 */
2139static void nand_free_kmem(struct nand_chip *this)
2140{
2141 /* Buffer allocated by nand_scan ? */
2142 if (this->options & NAND_OOBBUF_ALLOC)
2143 kfree(this->oob_buf);
2144 /* Buffer allocated by nand_scan ? */
2145 if (this->options & NAND_DATABUF_ALLOC)
2146 kfree(this->data_buf);
2147 /* Controller allocated by nand_scan ? */
2148 if (this->options & NAND_CONTROLLER_ALLOC)
2149 kfree(this->controller);
2150}
2151
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002152/*
2153 * Allocate buffers and data structures
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 */
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002155static int nand_allocate_kmem(struct mtd_info *mtd, struct nand_chip *this)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002157 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002159 if (!this->oob_buf) {
2160 len = mtd->oobsize <<
2161 (this->phys_erase_shift - this->page_shift);
2162 this->oob_buf = kmalloc(len, GFP_KERNEL);
2163 if (!this->oob_buf)
2164 goto outerr;
2165 this->options |= NAND_OOBBUF_ALLOC;
David Woodhouse552d9202006-05-14 01:20:46 +01002166 }
2167
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002168 if (!this->data_buf) {
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002169 len = mtd->writesize + mtd->oobsize;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002170 this->data_buf = kmalloc(len, GFP_KERNEL);
2171 if (!this->data_buf)
2172 goto outerr;
2173 this->options |= NAND_DATABUF_ALLOC;
2174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002176 if (!this->controller) {
2177 this->controller = kzalloc(sizeof(struct nand_hw_control),
2178 GFP_KERNEL);
2179 if (!this->controller)
2180 goto outerr;
2181 this->options |= NAND_CONTROLLER_ALLOC;
2182 }
2183 return 0;
2184
2185 outerr:
2186 printk(KERN_ERR "nand_scan(): Cannot allocate buffers\n");
2187 nand_free_kmem(this);
2188 return -ENOMEM;
2189}
2190
2191/*
2192 * Set default functions
2193 */
2194static void nand_set_defaults(struct nand_chip *this, int busw)
2195{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 /* check for proper chip_delay setup, set 20us if not */
2197 if (!this->chip_delay)
2198 this->chip_delay = 20;
2199
2200 /* check, if a user supplied command function given */
2201 if (this->cmdfunc == NULL)
2202 this->cmdfunc = nand_command;
2203
2204 /* check, if a user supplied wait function given */
2205 if (this->waitfunc == NULL)
2206 this->waitfunc = nand_wait;
2207
2208 if (!this->select_chip)
2209 this->select_chip = nand_select_chip;
2210 if (!this->write_byte)
2211 this->write_byte = busw ? nand_write_byte16 : nand_write_byte;
2212 if (!this->read_byte)
2213 this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
2214 if (!this->write_word)
2215 this->write_word = nand_write_word;
2216 if (!this->read_word)
2217 this->read_word = nand_read_word;
2218 if (!this->block_bad)
2219 this->block_bad = nand_block_bad;
2220 if (!this->block_markbad)
2221 this->block_markbad = nand_default_block_markbad;
2222 if (!this->write_buf)
2223 this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
2224 if (!this->read_buf)
2225 this->read_buf = busw ? nand_read_buf16 : nand_read_buf;
2226 if (!this->verify_buf)
2227 this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
2228 if (!this->scan_bbt)
2229 this->scan_bbt = nand_default_bbt;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002230}
2231
2232/*
2233 * Get the flash and manufacturer id and lookup if the typ is supported
2234 */
2235static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2236 struct nand_chip *this,
2237 int busw, int *maf_id)
2238{
2239 struct nand_flash_dev *type = NULL;
2240 int i, dev_id, maf_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
2242 /* Select the device */
2243 this->select_chip(mtd, 0);
2244
2245 /* Send the command for reading device ID */
David Woodhousee0c7d762006-05-13 18:07:53 +01002246 this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247
2248 /* Read manufacturer and device IDs */
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002249 *maf_id = this->read_byte(mtd);
2250 dev_id = this->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002252 /* Lookup the flash id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002254 if (dev_id == nand_flash_ids[i].id) {
2255 type = &nand_flash_ids[i];
2256 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 }
2259
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002260 if (!type)
2261 return ERR_PTR(-ENODEV);
2262
2263 this->chipsize = nand_flash_ids[i].chipsize << 20;
2264
2265 /* Newer devices have all the information in additional id bytes */
2266 if (!nand_flash_ids[i].pagesize) {
2267 int extid;
2268 /* The 3rd id byte contains non relevant data ATM */
2269 extid = this->read_byte(mtd);
2270 /* The 4th id byte is the important one */
2271 extid = this->read_byte(mtd);
2272 /* Calc pagesize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002273 mtd->writesize = 1024 << (extid & 0x3);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002274 extid >>= 2;
2275 /* Calc oobsize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002276 mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002277 extid >>= 2;
2278 /* Calc blocksize. Blocksize is multiples of 64KiB */
2279 mtd->erasesize = (64 * 1024) << (extid & 0x03);
2280 extid >>= 2;
2281 /* Get buswidth information */
2282 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
2283
2284 } else {
2285 /*
2286 * Old devices have this data hardcoded in the device id table
2287 */
2288 mtd->erasesize = nand_flash_ids[i].erasesize;
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002289 mtd->writesize = nand_flash_ids[i].pagesize;
2290 mtd->oobsize = mtd->writesize / 32;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002291 busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
2292 }
2293
2294 /* Try to identify manufacturer */
2295 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
2296 if (nand_manuf_ids[maf_idx].id == *maf_id)
2297 break;
2298 }
2299
2300 /*
2301 * Check, if buswidth is correct. Hardware drivers should set
2302 * this correct !
2303 */
2304 if (busw != (this->options & NAND_BUSWIDTH_16)) {
2305 printk(KERN_INFO "NAND device: Manufacturer ID:"
2306 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2307 dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2308 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
2309 (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
2310 busw ? 16 : 8);
2311 return ERR_PTR(-EINVAL);
2312 }
2313
2314 /* Calculate the address shift from the page size */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002315 this->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002316 /* Convert chipsize to number of pages per chip -1. */
2317 this->pagemask = (this->chipsize >> this->page_shift) - 1;
2318
2319 this->bbt_erase_shift = this->phys_erase_shift =
2320 ffs(mtd->erasesize) - 1;
2321 this->chip_shift = ffs(this->chipsize) - 1;
2322
2323 /* Set the bad block position */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002324 this->badblockpos = mtd->writesize > 512 ?
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002325 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
2326
2327 /* Get chip options, preserve non chip based options */
2328 this->options &= ~NAND_CHIPOPTIONS_MSK;
2329 this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
2330
2331 /*
2332 * Set this as a default. Board drivers can override it, if necessary
2333 */
2334 this->options |= NAND_NO_AUTOINCR;
2335
2336 /* Check if this is a not a samsung device. Do not clear the
2337 * options for chips which are not having an extended id.
2338 */
2339 if (*maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
2340 this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
2341
2342 /* Check for AND chips with 4 page planes */
2343 if (this->options & NAND_4PAGE_ARRAY)
2344 this->erase_cmd = multi_erase_cmd;
2345 else
2346 this->erase_cmd = single_erase_cmd;
2347
2348 /* Do not replace user supplied command function ! */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002349 if (mtd->writesize > 512 && this->cmdfunc == nand_command)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002350 this->cmdfunc = nand_command_lp;
2351
2352 printk(KERN_INFO "NAND device: Manufacturer ID:"
2353 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
2354 nand_manuf_ids[maf_idx].name, type->name);
2355
2356 return type;
2357}
2358
2359/* module_text_address() isn't exported, and it's mostly a pointless
2360 test if this is a module _anyway_ -- they'd have to try _really_ hard
2361 to call us from in-kernel code if the core NAND support is modular. */
2362#ifdef MODULE
2363#define caller_is_module() (1)
2364#else
2365#define caller_is_module() \
2366 module_text_address((unsigned long)__builtin_return_address(0))
2367#endif
2368
2369/**
2370 * nand_scan - [NAND Interface] Scan for the NAND device
2371 * @mtd: MTD device structure
2372 * @maxchips: Number of chips to scan for
2373 *
2374 * This fills out all the uninitialized function pointers
2375 * with the defaults.
2376 * The flash ID is read and the mtd/chip structures are
2377 * filled with the appropriate values. Buffers are allocated if
2378 * they are not provided by the board driver
2379 * The mtd->owner field must be set to the module of the caller
2380 *
2381 */
2382int nand_scan(struct mtd_info *mtd, int maxchips)
2383{
2384 int i, busw, nand_maf_id;
2385 struct nand_chip *this = mtd->priv;
2386 struct nand_flash_dev *type;
2387
2388 /* Many callers got this wrong, so check for it for a while... */
2389 if (!mtd->owner && caller_is_module()) {
2390 printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
2391 BUG();
2392 }
2393
2394 /* Get buswidth to select the correct functions */
2395 busw = this->options & NAND_BUSWIDTH_16;
2396 /* Set the default functions */
2397 nand_set_defaults(this, busw);
2398
2399 /* Read the flash type */
2400 type = nand_get_flash_type(mtd, this, busw, &nand_maf_id);
2401
2402 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002403 printk(KERN_WARNING "No NAND device found!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 this->select_chip(mtd, -1);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002405 return PTR_ERR(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 }
2407
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002408 /* Check for a chip array */
David Woodhousee0c7d762006-05-13 18:07:53 +01002409 for (i = 1; i < maxchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 this->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 /* Send the command for reading device ID */
David Woodhousee0c7d762006-05-13 18:07:53 +01002412 this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 /* Read manufacturer and device IDs */
2414 if (nand_maf_id != this->read_byte(mtd) ||
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002415 type->id != this->read_byte(mtd))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 break;
2417 }
2418 if (i > 1)
2419 printk(KERN_INFO "%d NAND chips detected\n", i);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002420
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 /* Store the number of chips and calc total size for mtd */
2422 this->numchips = i;
2423 mtd->size = i * this->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002425 /* Allocate buffers and data structures */
2426 if (nand_allocate_kmem(mtd, this))
2427 return -ENOMEM;
2428
2429 /* Preset the internal oob buffer */
2430 memset(this->oob_buf, 0xff,
2431 mtd->oobsize << (this->phys_erase_shift - this->page_shift));
2432
2433 /*
2434 * If no default placement scheme is given, select an appropriate one
2435 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 if (!this->autooob) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002437 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 case 8:
2439 this->autooob = &nand_oob_8;
2440 break;
2441 case 16:
2442 this->autooob = &nand_oob_16;
2443 break;
2444 case 64:
2445 this->autooob = &nand_oob_64;
2446 break;
2447 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002448 printk(KERN_WARNING "No oob scheme defined for "
2449 "oobsize %d\n", mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 BUG();
2451 }
2452 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002453
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002454 /*
2455 * The number of bytes available for the filesystem to place fs
2456 * dependend oob data
2457 */
Thomas Gleixner998cf642005-04-01 08:21:48 +01002458 mtd->oobavail = 0;
2459 for (i = 0; this->autooob->oobfree[i][1]; i++)
2460 mtd->oobavail += this->autooob->oobfree[i][1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002462 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002463 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2464 * selected and we have 256 byte pagesize fallback to software ECC
David Woodhousee0c7d762006-05-13 18:07:53 +01002465 */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002466 switch (this->ecc.mode) {
2467 case NAND_ECC_HW:
2468 case NAND_ECC_HW_SYNDROME:
2469 if (!this->ecc.calculate || !this->ecc.correct ||
2470 !this->ecc.hwctl) {
2471 printk(KERN_WARNING "No ECC functions supplied, "
2472 "Hardware ECC not possible\n");
2473 BUG();
2474 }
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002475 if (mtd->writesize >= this->ecc.size)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002476 break;
2477 printk(KERN_WARNING "%d byte HW ECC not possible on "
2478 "%d byte page size, fallback to SW ECC\n",
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002479 this->ecc.size, mtd->writesize);
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002480 this->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002482 case NAND_ECC_SOFT:
2483 this->ecc.calculate = nand_calculate_ecc;
2484 this->ecc.correct = nand_correct_data;
2485 this->ecc.size = 256;
2486 this->ecc.bytes = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002488
2489 case NAND_ECC_NONE:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002490 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2491 "This is not recommended !!\n");
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002492 this->ecc.size = mtd->writesize;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002493 this->ecc.bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002496 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002497 this->ecc.mode);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002498 BUG();
2499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002501 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002502 * Set the number of read / write steps for one page depending on ECC
2503 * mode
2504 */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002505 this->ecc.steps = mtd->writesize / this->ecc.size;
2506 if(this->ecc.steps * this->ecc.size != mtd->writesize) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002507 printk(KERN_WARNING "Invalid ecc parameters\n");
2508 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002510
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 /* Initialize state, waitqueue and spinlock */
2512 this->state = FL_READY;
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002513 init_waitqueue_head(&this->controller->wq);
2514 spin_lock_init(&this->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515
2516 /* De-select the device */
2517 this->select_chip(mtd, -1);
2518
2519 /* Invalidate the pagebuffer reference */
2520 this->pagebuf = -1;
2521
2522 /* Fill in remaining MTD driver data */
2523 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002524 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 mtd->ecctype = MTD_ECC_SW;
2526 mtd->erase = nand_erase;
2527 mtd->point = NULL;
2528 mtd->unpoint = NULL;
2529 mtd->read = nand_read;
2530 mtd->write = nand_write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 mtd->read_oob = nand_read_oob;
2532 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 mtd->sync = nand_sync;
2534 mtd->lock = NULL;
2535 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002536 mtd->suspend = nand_suspend;
2537 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 mtd->block_isbad = nand_block_isbad;
2539 mtd->block_markbad = nand_block_markbad;
2540
2541 /* and make the autooob the default one */
2542 memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
2543
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002544 /* Check, if we should skip the bad block table scan */
2545 if (this->options & NAND_SKIP_BBTSCAN)
2546 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
2548 /* Build bad block table */
David Woodhousee0c7d762006-05-13 18:07:53 +01002549 return this->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550}
2551
2552/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002553 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 * @mtd: MTD device structure
2555*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002556void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557{
2558 struct nand_chip *this = mtd->priv;
2559
2560#ifdef CONFIG_MTD_PARTITIONS
2561 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002562 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563#endif
2564 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002565 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
Jesper Juhlfa671642005-11-07 01:01:27 -08002567 /* Free bad block table memory */
David Woodhousee0c7d762006-05-13 18:07:53 +01002568 kfree(this->bbt);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002569 /* Free buffers */
2570 nand_free_kmem(this);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571}
2572
David Woodhousee0c7d762006-05-13 18:07:53 +01002573EXPORT_SYMBOL_GPL(nand_scan);
2574EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002575
2576static int __init nand_base_init(void)
2577{
2578 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2579 return 0;
2580}
2581
2582static void __exit nand_base_exit(void)
2583{
2584 led_trigger_unregister_simple(nand_led_trigger);
2585}
2586
2587module_init(nand_base_init);
2588module_exit(nand_base_exit);
2589
David Woodhousee0c7d762006-05-13 18:07:53 +01002590MODULE_LICENSE("GPL");
2591MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2592MODULE_DESCRIPTION("Generic NAND flash driver code");