blob: f6997fb77b910569881b8b677607834b9a308ba3 [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 Gleixner7abd3ef2006-05-23 23:25:53 +0200279 this->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 break;
281 case 0:
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200282 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 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 Gleixner7abd3ef2006-05-23 23:25:53 +0200551static void nand_command(struct mtd_info *mtd, unsigned int command,
552 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
554 register struct nand_chip *this = mtd->priv;
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200555 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 /*
558 * Write out the command to the device.
559 */
560 if (command == NAND_CMD_SEQIN) {
561 int readcmd;
562
Joern Engel28318772006-05-22 23:18:05 +0200563 if (column >= mtd->writesize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 /* OOB area */
Joern Engel28318772006-05-22 23:18:05 +0200565 column -= mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 readcmd = NAND_CMD_READOOB;
567 } else if (column < 256) {
568 /* First 256 bytes --> READ0 */
569 readcmd = NAND_CMD_READ0;
570 } else {
571 column -= 256;
572 readcmd = NAND_CMD_READ1;
573 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200574 this->cmd_ctrl(mtd, readcmd, ctrl);
575 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200577 this->cmd_ctrl(mtd, command, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200579 /*
580 * Address cycle, when necessary
581 */
582 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
583 /* Serially input address */
584 if (column != -1) {
585 /* Adjust columns for 16 bit buswidth */
586 if (this->options & NAND_BUSWIDTH_16)
587 column >>= 1;
588 this->cmd_ctrl(mtd, column, ctrl);
589 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200591 if (page_addr != -1) {
592 this->cmd_ctrl(mtd, page_addr, ctrl);
593 ctrl &= ~NAND_CTRL_CHANGE;
594 this->cmd_ctrl(mtd, page_addr >> 8, ctrl);
595 /* One more address cycle for devices > 32MiB */
596 if (this->chipsize > (32 << 20))
597 this->cmd_ctrl(mtd, page_addr >> 16, ctrl);
598 }
599 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000600
601 /*
602 * program and erase have their own busy handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 * status and sequential in needs no delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100604 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000606
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 case NAND_CMD_PAGEPROG:
608 case NAND_CMD_ERASE1:
609 case NAND_CMD_ERASE2:
610 case NAND_CMD_SEQIN:
611 case NAND_CMD_STATUS:
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200612 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 return;
614
615 case NAND_CMD_RESET:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000616 if (this->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 break;
618 udelay(this->chip_delay);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200619 this->cmd_ctrl(mtd, NAND_CMD_STATUS,
620 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
621 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
David Woodhousee0c7d762006-05-13 18:07:53 +0100622 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 return;
624
David Woodhousee0c7d762006-05-13 18:07:53 +0100625 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000627 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 * If we don't have access to the busy pin, we apply the given
629 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100630 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 if (!this->dev_ready) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100632 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 /* Apply this short delay always to ensure that we do wait tWB in
637 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100638 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000639
640 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641}
642
643/**
644 * nand_command_lp - [DEFAULT] Send command to NAND large page device
645 * @mtd: MTD device structure
646 * @command: the command to be sent
647 * @column: the column address for this command, -1 if none
648 * @page_addr: the page address for this command, -1 if none
649 *
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200650 * Send command to NAND device. This is the version for the new large page
651 * devices We dont have the separate regions as we have in the small page
652 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 *
654 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200655static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
656 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
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200666 /* Command latch cycle */
667 this->cmd_ctrl(mtd, command & 0xff,
668 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
670 if (column != -1 || page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200671 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
673 /* Serially input address */
674 if (column != -1) {
675 /* Adjust columns for 16 bit buswidth */
676 if (this->options & NAND_BUSWIDTH_16)
677 column >>= 1;
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200678 this->cmd_ctrl(mtd, column, ctrl);
679 ctrl &= ~NAND_CTRL_CHANGE;
680 this->cmd_ctrl(mtd, column >> 8, ctrl);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 if (page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200683 this->cmd_ctrl(mtd, page_addr, ctrl);
684 this->cmd_ctrl(mtd, page_addr >> 8,
685 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 /* One more address cycle for devices > 128MiB */
687 if (this->chipsize > (128 << 20))
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200688 this->cmd_ctrl(mtd, page_addr >> 16,
689 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200692 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000693
694 /*
695 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000696 * status, sequential in, and deplete1 need no delay
697 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000699
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 case NAND_CMD_CACHEDPROG:
701 case NAND_CMD_PAGEPROG:
702 case NAND_CMD_ERASE1:
703 case NAND_CMD_ERASE2:
704 case NAND_CMD_SEQIN:
705 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000706 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 return;
708
David Woodhousee0c7d762006-05-13 18:07:53 +0100709 /*
710 * read error status commands require only a short delay
711 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000712 case NAND_CMD_STATUS_ERROR:
713 case NAND_CMD_STATUS_ERROR0:
714 case NAND_CMD_STATUS_ERROR1:
715 case NAND_CMD_STATUS_ERROR2:
716 case NAND_CMD_STATUS_ERROR3:
717 udelay(this->chip_delay);
718 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
720 case NAND_CMD_RESET:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000721 if (this->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 break;
723 udelay(this->chip_delay);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200724 this->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE | NAND_CLE);
725 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
David Woodhousee0c7d762006-05-13 18:07:53 +0100726 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 return;
728
729 case NAND_CMD_READ0:
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200730 this->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_NCE | NAND_CLE);
731 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000732
David Woodhousee0c7d762006-05-13 18:07:53 +0100733 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000735 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 * If we don't have access to the busy pin, we apply the given
737 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100738 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 if (!this->dev_ready) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100740 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000742 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 /* Apply this short delay always to ensure that we do wait tWB in
746 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100747 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000748
749 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750}
751
752/**
753 * nand_get_device - [GENERIC] Get chip for selected access
754 * @this: the nand chip descriptor
755 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000756 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 *
758 * Get the device and lock it for exclusive access
759 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200760static int
761nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762{
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200763 spinlock_t *lock = &this->controller->lock;
764 wait_queue_head_t *wq = &this->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100765 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100766 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100767 spin_lock(lock);
768
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200770 /* Hardware controller shared among independend devices */
771 if (!this->controller->active)
772 this->controller->active = this;
773
774 if (this->controller->active == this && this->state == FL_READY) {
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100775 this->state = new_state;
776 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100777 return 0;
778 }
779 if (new_state == FL_PM_SUSPENDED) {
780 spin_unlock(lock);
781 return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100782 }
783 set_current_state(TASK_UNINTERRUPTIBLE);
784 add_wait_queue(wq, &wait);
785 spin_unlock(lock);
786 schedule();
787 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 goto retry;
789}
790
791/**
792 * nand_wait - [DEFAULT] wait until the command is done
793 * @mtd: MTD device structure
794 * @this: NAND chip structure
795 * @state: state to select the max. timeout value
796 *
797 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000798 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 * general NAND and SmartMedia specs
800 *
801*/
802static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
803{
804
David Woodhousee0c7d762006-05-13 18:07:53 +0100805 unsigned long timeo = jiffies;
806 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000807
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100809 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100811 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
Richard Purdie8fe833c2006-03-31 02:31:14 -0800813 led_trigger_event(nand_led_trigger, LED_FULL);
814
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 /* Apply this short delay always to ensure that we do wait tWB in
816 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100817 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
819 if ((state == FL_ERASING) && (this->options & NAND_IS_AND))
David Woodhousee0c7d762006-05-13 18:07:53 +0100820 this->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000821 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100822 this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000824 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 /* Check, if we were interrupted */
826 if (this->state != state)
827 return 0;
828
829 if (this->dev_ready) {
830 if (this->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000831 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 } else {
833 if (this->read_byte(mtd) & NAND_STATUS_READY)
834 break;
835 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000836 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800838 led_trigger_event(nand_led_trigger, LED_OFF);
839
David Woodhousee0c7d762006-05-13 18:07:53 +0100840 status = (int)this->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 return status;
842}
843
844/**
845 * nand_write_page - [GENERIC] write one page
846 * @mtd: MTD device structure
847 * @this: NAND chip structure
848 * @page: startpage inside the chip, must be called with (page & this->pagemask)
849 * @oob_buf: out of band data buffer
850 * @oobsel: out of band selecttion structre
851 * @cached: 1 = enable cached programming if supported by chip
852 *
853 * Nand_page_program function is used for write and writev !
854 * This function will always program a full page of data
855 * If you call it with a non page aligned buffer, you're lost :)
856 *
857 * Cached programming is not supported yet.
858 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100859static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int page,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200860 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int cached)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861{
David Woodhousee0c7d762006-05-13 18:07:53 +0100862 int i, status;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200863 uint8_t ecc_code[32];
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200864 int eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
David Woodhousee0c7d762006-05-13 18:07:53 +0100865 int *oob_config = oobsel->eccpos;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200866 int datidx = 0, eccidx = 0, eccsteps = this->ecc.steps;
David Woodhousee0c7d762006-05-13 18:07:53 +0100867 int eccbytes = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 /* FIXME: Enable cached programming */
870 cached = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 /* Send command to begin auto page programming */
David Woodhousee0c7d762006-05-13 18:07:53 +0100873 this->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
875 /* Write out complete page of data, take care of eccmode */
876 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100877 /* No ecc, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 case NAND_ECC_NONE:
David Woodhousee0c7d762006-05-13 18:07:53 +0100879 printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
Joern Engel28318772006-05-22 23:18:05 +0200880 this->write_buf(mtd, this->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000882
David Woodhousee0c7d762006-05-13 18:07:53 +0100883 /* Software ecc 3/256, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 case NAND_ECC_SOFT:
885 for (; eccsteps; eccsteps--) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200886 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 for (i = 0; i < 3; i++, eccidx++)
888 oob_buf[oob_config[eccidx]] = ecc_code[i];
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200889 datidx += this->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 }
Joern Engel28318772006-05-22 23:18:05 +0200891 this->write_buf(mtd, this->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 break;
893 default:
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200894 eccbytes = this->ecc.bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 for (; eccsteps; eccsteps--) {
896 /* enable hardware ecc logic for write */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200897 this->ecc.hwctl(mtd, NAND_ECC_WRITE);
898 this->write_buf(mtd, &this->data_poi[datidx], this->ecc.size);
899 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 for (i = 0; i < eccbytes; i++, eccidx++)
901 oob_buf[oob_config[eccidx]] = ecc_code[i];
902 /* If the hardware ecc provides syndromes then
903 * the ecc code must be written immidiately after
904 * the data bytes (words) */
905 if (this->options & NAND_HWECC_SYNDROME)
906 this->write_buf(mtd, ecc_code, eccbytes);
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200907 datidx += this->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 }
909 break;
910 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000911
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 /* Write out OOB data */
913 if (this->options & NAND_HWECC_SYNDROME)
914 this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000915 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 this->write_buf(mtd, oob_buf, mtd->oobsize);
917
918 /* Send command to actually program the data */
David Woodhousee0c7d762006-05-13 18:07:53 +0100919 this->cmdfunc(mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
921 if (!cached) {
922 /* call wait ready function */
David Woodhousee0c7d762006-05-13 18:07:53 +0100923 status = this->waitfunc(mtd, this, FL_WRITING);
David A. Marlin068e3c02005-01-24 03:07:46 +0000924
925 /* See if operation failed and additional status checks are available */
926 if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
927 status = this->errstat(mtd, this, FL_WRITING, status, page);
928 }
929
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +0000931 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100932 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 return -EIO;
934 }
935 } else {
936 /* FIXME: Implement cached programming ! */
David Woodhousee0c7d762006-05-13 18:07:53 +0100937 /* wait until cache is ready */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 // status = this->waitfunc (mtd, this, FL_CACHEDRPG);
939 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000940 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941}
942
943#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
944/**
945 * nand_verify_pages - [GENERIC] verify the chip contents after a write
946 * @mtd: MTD device structure
947 * @this: NAND chip structure
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200948 * @page: startpage inside the chip, must be called with (page & this->pagemask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 * @numpages: number of pages to verify
950 * @oob_buf: out of band data buffer
951 * @oobsel: out of band selecttion structre
952 * @chipnr: number of the current chip
953 * @oobmode: 1 = full buffer verify, 0 = ecc only
954 *
955 * The NAND device assumes that it is always writing to a cleanly erased page.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000956 * Hence, it performs its internal write verification only on bits that
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 * transitioned from 1 to 0. The device does NOT verify the whole page on a
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000958 * byte by byte basis. It is possible that the page was not completely erased
959 * or the page is becoming unusable due to wear. The read with ECC would catch
960 * the error later when the ECC page check fails, but we would rather catch
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 * it early in the page write stage. Better to write no data than invalid data.
962 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100963static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200964 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965{
David Woodhousee0c7d762006-05-13 18:07:53 +0100966 int i, j, datidx = 0, oobofs = 0, res = -EIO;
967 int eccsteps = this->eccsteps;
968 int hweccbytes;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200969 uint8_t oobdata[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
971 hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
972
973 /* Send command to read back the first page */
David Woodhousee0c7d762006-05-13 18:07:53 +0100974 this->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
David Woodhousee0c7d762006-05-13 18:07:53 +0100976 for (;;) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 for (j = 0; j < eccsteps; j++) {
978 /* Loop through and verify the data */
979 if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100980 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 goto out;
982 }
983 datidx += mtd->eccsize;
984 /* Have we a hw generator layout ? */
985 if (!hweccbytes)
986 continue;
987 if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100988 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 goto out;
990 }
991 oobofs += hweccbytes;
992 }
993
994 /* check, if we must compare all data or if we just have to
995 * compare the ecc bytes
996 */
997 if (oobmode) {
998 if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100999 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 goto out;
1001 }
1002 } else {
1003 /* Read always, else autoincrement fails */
1004 this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
1005
1006 if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
1007 int ecccnt = oobsel->eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 for (i = 0; i < ecccnt; i++) {
1010 int idx = oobsel->eccpos[i];
David Woodhousee0c7d762006-05-13 18:07:53 +01001011 if (oobdata[idx] != oob_buf[oobofs + idx]) {
1012 DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed ECC write verify, page 0x%08x, %6i bytes were succesful\n",
1013 __FUNCTION__, page, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 goto out;
1015 }
1016 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 }
1019 oobofs += mtd->oobsize - hweccbytes * eccsteps;
1020 page++;
1021 numpages--;
1022
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001023 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 * Do this before the AUTOINCR check, so no problems
1025 * arise if a chip which does auto increment
1026 * is marked as NOAUTOINCR by the board driver.
1027 * Do this also before returning, so the chip is
1028 * ready for the next command.
David Woodhousee0c7d762006-05-13 18:07:53 +01001029 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001030 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001031 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001033 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
1035 /* All done, return happy */
1036 if (!numpages)
1037 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001038
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001039 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 if (!NAND_CANAUTOINCR(this))
David Woodhousee0c7d762006-05-13 18:07:53 +01001041 this->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001043 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 * Terminate the read command. We come here in case of an error
1045 * So we must issue a reset command.
1046 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001047 out:
1048 this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 return res;
1050}
1051#endif
1052
1053/**
David A. Marlin068e3c02005-01-24 03:07:46 +00001054 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 * @mtd: MTD device structure
1056 * @from: offset to read from
1057 * @len: number of bytes to read
1058 * @retlen: pointer to variable to store the number of read bytes
1059 * @buf: the databuffer to put data
1060 *
David A. Marlin068e3c02005-01-24 03:07:46 +00001061 * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL
1062 * and flags = 0xff
1063 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001064static 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 -07001065{
David Woodhousee0c7d762006-05-13 18:07:53 +01001066 return nand_do_read_ecc(mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001067}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069/**
David A. Marlin068e3c02005-01-24 03:07:46 +00001070 * nand_do_read_ecc - [MTD Interface] Read data with ECC
1071 * @mtd: MTD device structure
1072 * @from: offset to read from
1073 * @len: number of bytes to read
1074 * @retlen: pointer to variable to store the number of read bytes
1075 * @buf: the databuffer to put data
Dan Brownbb75ba42005-04-04 19:02:26 +01001076 * @oob_buf: filesystem supplied oob data buffer (can be NULL)
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001077 * @oobsel: oob selection structure
David A. Marlin068e3c02005-01-24 03:07:46 +00001078 * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed
1079 * and how many corrected error bits are acceptable:
1080 * bits 0..7 - number of tolerable errors
1081 * bit 8 - 0 == do not get/release chip, 1 == get/release chip
1082 *
1083 * NAND read with ECC
1084 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001085int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001086 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel, int flags)
David A. Marlin068e3c02005-01-24 03:07:46 +00001087{
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001088
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
1090 int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
1091 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001092 uint8_t *data_poi, *oob_data = oob_buf;
1093 uint8_t ecc_calc[32];
1094 uint8_t ecc_code[32];
David Woodhousee0c7d762006-05-13 18:07:53 +01001095 int eccmode, eccsteps;
1096 int *oob_config, datidx;
1097 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
1098 int eccbytes;
1099 int compareecc = 1;
1100 int oobreadlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
David Woodhousee0c7d762006-05-13 18:07:53 +01001102 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 -07001103
1104 /* Do not allow reads past end of device */
1105 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001106 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 *retlen = 0;
1108 return -EINVAL;
1109 }
1110
1111 /* Grab the lock and see if the device is available */
David A. Marlin068e3c02005-01-24 03:07:46 +00001112 if (flags & NAND_GET_DEVICE)
David Woodhousee0c7d762006-05-13 18:07:53 +01001113 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 /* Autoplace of oob data ? Use the default placement scheme */
1116 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
1117 oobsel = this->autooob;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001118
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001119 eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 oob_config = oobsel->eccpos;
1121
1122 /* Select the NAND device */
1123 chipnr = (int)(from >> this->chip_shift);
1124 this->select_chip(mtd, chipnr);
1125
1126 /* First we calculate the starting page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001127 realpage = (int)(from >> this->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 page = realpage & this->pagemask;
1129
1130 /* Get raw starting column */
Joern Engel28318772006-05-22 23:18:05 +02001131 col = from & (mtd->writesize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Joern Engel28318772006-05-22 23:18:05 +02001133 end = mtd->writesize;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001134 ecc = this->ecc.size;
1135 eccbytes = this->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
1138 compareecc = 0;
1139
1140 oobreadlen = mtd->oobsize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001141 if (this->options & NAND_HWECC_SYNDROME)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 oobreadlen -= oobsel->eccbytes;
1143
1144 /* Loop until all data read */
1145 while (read < len) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 int aligned = (!col && (len - read) >= end);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001148 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 * If the read is not page aligned, we have to read into data buffer
1150 * due to ecc, else we read into return buffer direct
1151 */
1152 if (aligned)
1153 data_poi = &buf[read];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001154 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 data_poi = this->data_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001156
1157 /* Check, if we have this page in the buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 *
1159 * FIXME: Make it work when we must provide oob data too,
1160 * check the usage of data_buf oob field
1161 */
1162 if (realpage == this->pagebuf && !oob_buf) {
1163 /* aligned read ? */
1164 if (aligned)
David Woodhousee0c7d762006-05-13 18:07:53 +01001165 memcpy(data_poi, this->data_buf, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 goto readdata;
1167 }
1168
1169 /* Check, if we must send the read command */
1170 if (sndcmd) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001171 this->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 sndcmd = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001173 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
1175 /* get oob area, if we have no oob buffer from fs-driver */
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001176 if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
1177 oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 oob_data = &this->data_buf[end];
1179
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001180 eccsteps = this->ecc.steps;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001181
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001183 case NAND_ECC_NONE:{
1184 /* No ECC, Read in a page */
1185 static unsigned long lastwhinge = 0;
1186 if ((lastwhinge / HZ) != (jiffies / HZ)) {
1187 printk(KERN_WARNING
1188 "Reading data from NAND FLASH without ECC is not recommended\n");
1189 lastwhinge = jiffies;
1190 }
1191 this->read_buf(mtd, data_poi, end);
1192 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001194
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
1196 this->read_buf(mtd, data_poi, end);
David Woodhousee0c7d762006-05-13 18:07:53 +01001197 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001198 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001199 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
1201 default:
David Woodhousee0c7d762006-05-13 18:07:53 +01001202 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001203 this->ecc.hwctl(mtd, NAND_ECC_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 this->read_buf(mtd, &data_poi[datidx], ecc);
1205
1206 /* HW ecc with syndrome calculation must read the
1207 * syndrome from flash immidiately after the data */
1208 if (!compareecc) {
1209 /* Some hw ecc generators need to know when the
1210 * syndrome is read from flash */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001211 this->ecc.hwctl(mtd, NAND_ECC_READSYN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 this->read_buf(mtd, &oob_data[i], eccbytes);
1213 /* We calc error correction directly, it checks the hw
1214 * generator for an error, reads back the syndrome and
1215 * does the error correction on the fly */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001216 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
David A. Marlin068e3c02005-01-24 03:07:46 +00001217 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001218 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
1219 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 ecc_failed++;
1221 }
1222 } else {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001223 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001226 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 }
1228
1229 /* read oobdata */
1230 this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
1231
1232 /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
1233 if (!compareecc)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001234 goto readoob;
1235
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 /* Pick the ECC bytes out of the oob data */
1237 for (j = 0; j < oobsel->eccbytes; j++)
1238 ecc_code[j] = oob_data[oob_config[j]];
1239
David Woodhousee0c7d762006-05-13 18:07:53 +01001240 /* correct data, if necessary */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001241 for (i = 0, j = 0, datidx = 0; i < this->ecc.steps; i++, datidx += ecc) {
1242 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001243
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 /* Get next chunk of ecc bytes */
1245 j += eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001246
1247 /* Check, if we have a fs supplied oob-buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 * This is the legacy mode. Used by YAFFS1
1249 * Should go away some day
1250 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001251 if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 int *p = (int *)(&oob_data[mtd->oobsize]);
1253 p[i] = ecc_status;
1254 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001255
1256 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001257 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 ecc_failed++;
1259 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
David Woodhousee0c7d762006-05-13 18:07:53 +01001262 readoob:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 /* check, if we have a fs supplied oob-buffer */
1264 if (oob_buf) {
1265 /* without autoplace. Legacy mode used by YAFFS1 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001266 switch (oobsel->useecc) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 case MTD_NANDECC_AUTOPLACE:
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001268 case MTD_NANDECC_AUTOPL_USR:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 /* Walk through the autoplace chunks */
Dan Brown82e1d192005-04-06 21:13:09 +01001270 for (i = 0; oobsel->oobfree[i][1]; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 int from = oobsel->oobfree[i][0];
1272 int num = oobsel->oobfree[i][1];
1273 memcpy(&oob_buf[oob], &oob_data[from], num);
Dan Brown82e1d192005-04-06 21:13:09 +01001274 oob += num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 break;
1277 case MTD_NANDECC_PLACE:
1278 /* YAFFS1 legacy mode */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001279 oob_data += this->ecc.steps * sizeof(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 default:
1281 oob_data += mtd->oobsize;
1282 }
1283 }
1284 readdata:
1285 /* Partial page read, transfer data into fs buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001286 if (!aligned) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 for (j = col; j < end && read < len; j++)
1288 buf[read++] = data_poi[j];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001289 this->pagebuf = realpage;
1290 } else
Joern Engel28318772006-05-22 23:18:05 +02001291 read += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001293 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 * Do this before the AUTOINCR check, so no problems
1295 * arise if a chip which does auto increment
1296 * is marked as NOAUTOINCR by the board driver.
David Woodhousee0c7d762006-05-13 18:07:53 +01001297 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001298 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001299 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001301 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001302
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 if (read == len)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001304 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
1306 /* For subsequent reads align to page boundary. */
1307 col = 0;
1308 /* Increment page address */
1309 realpage++;
1310
1311 page = realpage & this->pagemask;
1312 /* Check, if we cross a chip boundary */
1313 if (!page) {
1314 chipnr++;
1315 this->select_chip(mtd, -1);
1316 this->select_chip(mtd, chipnr);
1317 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001318 /* Check, if the chip supports auto page increment
1319 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001320 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001322 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 }
1324
1325 /* Deselect and wake up anyone waiting on the device */
David A. Marlin068e3c02005-01-24 03:07:46 +00001326 if (flags & NAND_GET_DEVICE)
1327 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
1329 /*
1330 * Return success, if no ECC failures, else -EBADMSG
1331 * fs driver will take care of that, because
1332 * retlen == desired len and result == -EBADMSG
1333 */
1334 *retlen = read;
1335 return ecc_failed ? -EBADMSG : 0;
1336}
1337
1338/**
1339 * nand_read_oob - [MTD Interface] NAND read out-of-band
1340 * @mtd: MTD device structure
1341 * @from: offset to read from
1342 * @len: number of bytes to read
1343 * @retlen: pointer to variable to store the number of read bytes
1344 * @buf: the databuffer to put data
1345 *
1346 * NAND read out-of-band data from the spare area
1347 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001348static 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 -07001349{
1350 int i, col, page, chipnr;
1351 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +01001352 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
David Woodhousee0c7d762006-05-13 18:07:53 +01001354 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 -07001355
1356 /* Shift to get page */
1357 page = (int)(from >> this->page_shift);
1358 chipnr = (int)(from >> this->chip_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001359
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 /* Mask to get column */
1361 col = from & (mtd->oobsize - 1);
1362
1363 /* Initialize return length value */
1364 *retlen = 0;
1365
1366 /* Do not allow reads past end of device */
1367 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001368 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 *retlen = 0;
1370 return -EINVAL;
1371 }
1372
1373 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001374 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376 /* Select the NAND device */
1377 this->select_chip(mtd, chipnr);
1378
1379 /* Send the read command */
David Woodhousee0c7d762006-05-13 18:07:53 +01001380 this->cmdfunc(mtd, NAND_CMD_READOOB, col, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001381 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 * Read the data, if we read more than one page
1383 * oob data, let the device transfer the data !
1384 */
1385 i = 0;
1386 while (i < len) {
1387 int thislen = mtd->oobsize - col;
1388 thislen = min_t(int, thislen, len);
1389 this->read_buf(mtd, &buf[i], thislen);
1390 i += thislen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
1392 /* Read more ? */
1393 if (i < len) {
1394 page++;
1395 col = 0;
1396
1397 /* Check, if we cross a chip boundary */
1398 if (!(page & this->pagemask)) {
1399 chipnr++;
1400 this->select_chip(mtd, -1);
1401 this->select_chip(mtd, chipnr);
1402 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001403
1404 /* Apply delay or wait for ready/busy pin
Thomas Gleixner19870da2005-07-15 14:53:51 +01001405 * Do this before the AUTOINCR check, so no problems
1406 * arise if a chip which does auto increment
1407 * is marked as NOAUTOINCR by the board driver.
1408 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001409 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001410 udelay(this->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001411 else
1412 nand_wait_ready(mtd);
1413
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001414 /* Check, if the chip supports auto page increment
1415 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001416 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {
1418 /* For subsequent page reads set offset to 0 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001419 this->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 }
1421 }
1422 }
1423
1424 /* Deselect and wake up anyone waiting on the device */
1425 nand_release_device(mtd);
1426
1427 /* Return happy */
1428 *retlen = len;
1429 return 0;
1430}
1431
1432/**
1433 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1434 * @mtd: MTD device structure
1435 * @buf: temporary buffer
1436 * @from: offset to read from
1437 * @len: number of bytes to read
1438 * @ooblen: number of oob data bytes to read
1439 *
1440 * Read raw data including oob into buffer
1441 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001442int 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 -07001443{
1444 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +01001445 int page = (int)(from >> this->page_shift);
1446 int chip = (int)(from >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 int sndcmd = 1;
1448 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001449 int pagesize = mtd->writesize + mtd->oobsize;
David Woodhousee0c7d762006-05-13 18:07:53 +01001450 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
1452 /* Do not allow reads past end of device */
1453 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001454 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 return -EINVAL;
1456 }
1457
1458 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001459 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
David Woodhousee0c7d762006-05-13 18:07:53 +01001461 this->select_chip(mtd, chip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001462
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 /* Add requested oob length */
1464 len += ooblen;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 while (len) {
1467 if (sndcmd)
David Woodhousee0c7d762006-05-13 18:07:53 +01001468 this->cmdfunc(mtd, NAND_CMD_READ0, 0, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001469 sndcmd = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
David Woodhousee0c7d762006-05-13 18:07:53 +01001471 this->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
1473 len -= pagesize;
1474 cnt += pagesize;
1475 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001476
1477 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001478 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001480 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001481
1482 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
1484 sndcmd = 1;
1485 }
1486
1487 /* Deselect and wake up anyone waiting on the device */
1488 nand_release_device(mtd);
1489 return 0;
1490}
1491
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001492/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001493 * nand_write_raw - [GENERIC] Write raw data including oob
1494 * @mtd: MTD device structure
1495 * @buf: source buffer
1496 * @to: offset to write to
1497 * @len: number of bytes to write
1498 * @buf: source buffer
1499 * @oob: oob buffer
1500 *
1501 * Write raw data including oob
1502 */
1503int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1504 uint8_t *buf, uint8_t *oob)
1505{
1506 struct nand_chip *this = mtd->priv;
1507 int page = (int)(to >> this->page_shift);
1508 int chip = (int)(to >> this->chip_shift);
1509 int ret;
1510
1511 *retlen = 0;
1512
1513 /* Do not allow writes past end of device */
1514 if ((to + len) > mtd->size) {
1515 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1516 "beyond end of device\n");
1517 return -EINVAL;
1518 }
1519
1520 /* Grab the lock and see if the device is available */
1521 nand_get_device(this, mtd, FL_WRITING);
1522
1523 this->select_chip(mtd, chip);
1524 this->data_poi = buf;
1525
1526 while (len != *retlen) {
1527 ret = nand_write_page(mtd, this, page, oob, &mtd->oobinfo, 0);
1528 if (ret)
1529 return ret;
1530 page++;
1531 *retlen += mtd->writesize;
1532 this->data_poi += mtd->writesize;
1533 oob += mtd->oobsize;
1534 }
1535
1536 /* Deselect and wake up anyone waiting on the device */
1537 nand_release_device(mtd);
1538 return 0;
1539}
Thomas Gleixner38217202006-05-23 22:33:52 +02001540EXPORT_SYMBOL_GPL(nand_write_raw);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001541
1542/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001543 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 * @mtd: MTD device structure
1545 * @fsbuf: buffer given by fs driver
1546 * @oobsel: out of band selection structre
1547 * @autoplace: 1 = place given buffer into the oob bytes
1548 * @numpages: number of pages to prepare
1549 *
1550 * Return:
1551 * 1. Filesystem buffer available and autoplacement is off,
1552 * return filesystem buffer
1553 * 2. No filesystem buffer or autoplace is off, return internal
1554 * buffer
1555 * 3. Filesystem buffer is given and autoplace selected
1556 * put data from fs buffer into internal buffer and
1557 * retrun internal buffer
1558 *
1559 * Note: The internal buffer is filled with 0xff. This must
1560 * be done only once, when no autoplacement happens
1561 * Autoplacement sets the buffer dirty flag, which
1562 * forces the 0xff fill before using the buffer again.
1563 *
1564*/
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001565static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct nand_oobinfo *oobsel,
David Woodhousee0c7d762006-05-13 18:07:53 +01001566 int autoplace, int numpages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567{
1568 struct nand_chip *this = mtd->priv;
1569 int i, len, ofs;
1570
1571 /* Zero copy fs supplied buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001572 if (fsbuf && !autoplace)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 return fsbuf;
1574
1575 /* Check, if the buffer must be filled with ff again */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001576 if (this->oobdirty) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001577 memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 this->oobdirty = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001579 }
1580
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 /* If we have no autoplacement or no fs buffer use the internal one */
1582 if (!autoplace || !fsbuf)
1583 return this->oob_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001584
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 /* Walk through the pages and place the data */
1586 this->oobdirty = 1;
1587 ofs = 0;
1588 while (numpages--) {
1589 for (i = 0, len = 0; len < mtd->oobavail; i++) {
1590 int to = ofs + oobsel->oobfree[i][0];
1591 int num = oobsel->oobfree[i][1];
David Woodhousee0c7d762006-05-13 18:07:53 +01001592 memcpy(&this->oob_buf[to], fsbuf, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 len += num;
1594 fsbuf += num;
1595 }
1596 ofs += mtd->oobavail;
1597 }
1598 return this->oob_buf;
1599}
1600
Joern Engel28318772006-05-22 23:18:05 +02001601#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
1603/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001604 * nand_write - [MTD Interface] NAND write with ECC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 * @mtd: MTD device structure
1606 * @to: offset to write to
1607 * @len: number of bytes to write
1608 * @retlen: pointer to variable to store the number of written bytes
1609 * @buf: the data to write
1610 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 * NAND write with ECC
1612 */
Thomas Gleixner9223a452006-05-23 17:21:03 +02001613static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1614 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615{
1616 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
1617 int autoplace = 0, numpages, totalpages;
1618 struct nand_chip *this = mtd->priv;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001619 uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
David Woodhousee0c7d762006-05-13 18:07:53 +01001620 int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
Thomas Gleixner9223a452006-05-23 17:21:03 +02001621 struct nand_oobinfo *oobsel = &mtd->oobinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
Thomas Gleixner9223a452006-05-23 17:21:03 +02001623 DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
1625 /* Initialize retlen, in case of early exit */
1626 *retlen = 0;
1627
1628 /* Do not allow write past end of device */
1629 if ((to + len) > mtd->size) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001630 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 return -EINVAL;
1632 }
1633
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001634 /* reject writes, which are not page aligned */
David Woodhousee0c7d762006-05-13 18:07:53 +01001635 if (NOTALIGNED(to) || NOTALIGNED(len)) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001636 printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 return -EINVAL;
1638 }
1639
1640 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001641 nand_get_device(this, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
1643 /* Calculate chipnr */
1644 chipnr = (int)(to >> this->chip_shift);
1645 /* Select the NAND device */
1646 this->select_chip(mtd, chipnr);
1647
1648 /* Check, if it is write protected */
1649 if (nand_check_wp(mtd))
1650 goto out;
1651
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 /* Autoplace of oob data ? Use the default placement scheme */
1653 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
1654 oobsel = this->autooob;
1655 autoplace = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001656 }
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001657 if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
1658 autoplace = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659
1660 /* Setup variables and oob buffer */
1661 totalpages = len >> this->page_shift;
David Woodhousee0c7d762006-05-13 18:07:53 +01001662 page = (int)(to >> this->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001664 if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 this->pagebuf = -1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001666
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 /* Set it relative to chip */
1668 page &= this->pagemask;
1669 startpage = page;
1670 /* Calc number of pages we can write in one go */
David Woodhousee0c7d762006-05-13 18:07:53 +01001671 numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages);
1672 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001673 bufstart = (uint8_t *) buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
1675 /* Loop until all data is written */
1676 while (written < len) {
1677
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001678 this->data_poi = (uint8_t *) &buf[written];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 /* Write one page. If this is the last page to write
1680 * or the last page in this block, then use the
1681 * real pageprogram command, else select cached programming
1682 * if supported by the chip.
1683 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001684 ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001686 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001688 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 /* Next oob page */
1690 oob += mtd->oobsize;
1691 /* Update written bytes count */
Joern Engel28318772006-05-22 23:18:05 +02001692 written += mtd->writesize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001693 if (written == len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 goto cmp;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001695
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 /* Increment page address */
1697 page++;
1698
1699 /* Have we hit a block boundary ? Then we have to verify and
1700 * if verify is ok, we have to setup the oob buffer for
1701 * the next pages.
David Woodhousee0c7d762006-05-13 18:07:53 +01001702 */
1703 if (!(page & (ppblock - 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 int ofs;
1705 this->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001706 ret = nand_verify_pages(mtd, this, startpage, page - startpage,
1707 oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001709 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001711 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 *retlen = written;
1713
1714 ofs = autoplace ? mtd->oobavail : mtd->oobsize;
1715 if (eccbuf)
1716 eccbuf += (page - startpage) * ofs;
1717 totalpages -= page - startpage;
David Woodhousee0c7d762006-05-13 18:07:53 +01001718 numpages = min(totalpages, ppblock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 page &= this->pagemask;
1720 startpage = page;
David Woodhousee0c7d762006-05-13 18:07:53 +01001721 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Todd Poynor868801e2005-11-05 03:21:15 +00001722 oob = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 /* Check, if we cross a chip boundary */
1724 if (!page) {
1725 chipnr++;
1726 this->select_chip(mtd, -1);
1727 this->select_chip(mtd, chipnr);
1728 }
1729 }
1730 }
1731 /* Verify the remaining pages */
David Woodhousee0c7d762006-05-13 18:07:53 +01001732 cmp:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 this->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001734 ret = nand_verify_pages(mtd, this, startpage, totalpages, oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 if (!ret)
1736 *retlen = written;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001737 else
Thomas Gleixner9223a452006-05-23 17:21:03 +02001738 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
David Woodhousee0c7d762006-05-13 18:07:53 +01001740 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 /* Deselect and wake up anyone waiting on the device */
1742 nand_release_device(mtd);
1743
1744 return ret;
1745}
1746
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747/**
1748 * nand_write_oob - [MTD Interface] NAND write out-of-band
1749 * @mtd: MTD device structure
1750 * @to: offset to write to
1751 * @len: number of bytes to write
1752 * @retlen: pointer to variable to store the number of written bytes
1753 * @buf: the data to write
1754 *
1755 * NAND write out-of-band
1756 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001757static 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 -07001758{
1759 int column, page, status, ret = -EIO, chipnr;
1760 struct nand_chip *this = mtd->priv;
1761
David Woodhousee0c7d762006-05-13 18:07:53 +01001762 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 -07001763
1764 /* Shift to get page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001765 page = (int)(to >> this->page_shift);
1766 chipnr = (int)(to >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
1768 /* Mask to get column */
1769 column = to & (mtd->oobsize - 1);
1770
1771 /* Initialize return length value */
1772 *retlen = 0;
1773
1774 /* Do not allow write past end of page */
1775 if ((column + len) > mtd->oobsize) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001776 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 return -EINVAL;
1778 }
1779
1780 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001781 nand_get_device(this, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
1783 /* Select the NAND device */
1784 this->select_chip(mtd, chipnr);
1785
1786 /* Reset the chip. Some chips (like the Toshiba TC5832DC found
1787 in one of my DiskOnChip 2000 test units) will clear the whole
1788 data page too if we don't do this. I have no clue why, but
1789 I seem to have 'fixed' it in the doc2000 driver in
1790 August 1999. dwmw2. */
1791 this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
1792
1793 /* Check, if it is write protected */
1794 if (nand_check_wp(mtd))
1795 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001796
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 /* Invalidate the page cache, if we write to the cached page */
1798 if (page == this->pagebuf)
1799 this->pagebuf = -1;
1800
1801 if (NAND_MUST_PAD(this)) {
1802 /* Write out desired data */
Joern Engel28318772006-05-22 23:18:05 +02001803 this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 /* prepad 0xff for partial programming */
1805 this->write_buf(mtd, ffchars, column);
1806 /* write data */
1807 this->write_buf(mtd, buf, len);
1808 /* postpad 0xff for partial programming */
David Woodhousee0c7d762006-05-13 18:07:53 +01001809 this->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 } else {
1811 /* Write out desired data */
Joern Engel28318772006-05-22 23:18:05 +02001812 this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 /* write data */
1814 this->write_buf(mtd, buf, len);
1815 }
1816 /* Send command to program the OOB data */
David Woodhousee0c7d762006-05-13 18:07:53 +01001817 this->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
David Woodhousee0c7d762006-05-13 18:07:53 +01001819 status = this->waitfunc(mtd, this, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
1821 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001822 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001823 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 ret = -EIO;
1825 goto out;
1826 }
1827 /* Return happy */
1828 *retlen = len;
1829
1830#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1831 /* Send command to read back the data */
David Woodhousee0c7d762006-05-13 18:07:53 +01001832 this->cmdfunc(mtd, NAND_CMD_READOOB, column, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
1834 if (this->verify_buf(mtd, buf, len)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001835 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 ret = -EIO;
1837 goto out;
1838 }
1839#endif
1840 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001841 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 /* Deselect and wake up anyone waiting on the device */
1843 nand_release_device(mtd);
1844
1845 return ret;
1846}
1847
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1850 * @mtd: MTD device structure
1851 * @page: the page address of the block which will be erased
1852 *
1853 * Standard erase command for NAND chips
1854 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001855static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856{
1857 struct nand_chip *this = mtd->priv;
1858 /* Send commands to erase a block */
David Woodhousee0c7d762006-05-13 18:07:53 +01001859 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1860 this->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861}
1862
1863/**
1864 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1865 * @mtd: MTD device structure
1866 * @page: the page address of the block which will be erased
1867 *
1868 * AND multi block erase command function
1869 * Erase 4 consecutive blocks
1870 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001871static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872{
1873 struct nand_chip *this = mtd->priv;
1874 /* Send commands to erase a block */
David Woodhousee0c7d762006-05-13 18:07:53 +01001875 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1876 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1877 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1878 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1879 this->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880}
1881
1882/**
1883 * nand_erase - [MTD Interface] erase block(s)
1884 * @mtd: MTD device structure
1885 * @instr: erase instruction
1886 *
1887 * Erase one ore more blocks
1888 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001889static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890{
David Woodhousee0c7d762006-05-13 18:07:53 +01001891 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001893
David A. Marlin30f464b2005-01-17 18:35:25 +00001894#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895/**
1896 * nand_erase_intern - [NAND Interface] erase block(s)
1897 * @mtd: MTD device structure
1898 * @instr: erase instruction
1899 * @allowbbt: allow erasing the bbt area
1900 *
1901 * Erase one ore more blocks
1902 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001903int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904{
1905 int page, len, status, pages_per_block, ret, chipnr;
1906 struct nand_chip *this = mtd->priv;
David A. Marlin30f464b2005-01-17 18:35:25 +00001907 int rewrite_bbt[NAND_MAX_CHIPS]={0}; /* flags to indicate the page, if bbt needs to be rewritten. */
1908 unsigned int bbt_masked_page; /* bbt mask to compare to page being erased. */
1909 /* It is used to see if the current page is in the same */
1910 /* 256 block group and the same bank as the bbt. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911
David Woodhousee0c7d762006-05-13 18:07:53 +01001912 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 -07001913
1914 /* Start address must align on block boundary */
1915 if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001916 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 return -EINVAL;
1918 }
1919
1920 /* Length must align on block boundary */
1921 if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001922 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 return -EINVAL;
1924 }
1925
1926 /* Do not allow erase past end of device */
1927 if ((instr->len + instr->addr) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001928 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 return -EINVAL;
1930 }
1931
1932 instr->fail_addr = 0xffffffff;
1933
1934 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001935 nand_get_device(this, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
1937 /* Shift to get first page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001938 page = (int)(instr->addr >> this->page_shift);
1939 chipnr = (int)(instr->addr >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941 /* Calculate pages in each block */
1942 pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
1943
1944 /* Select the NAND device */
1945 this->select_chip(mtd, chipnr);
1946
1947 /* Check the WP bit */
1948 /* Check, if it is write protected */
1949 if (nand_check_wp(mtd)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001950 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 instr->state = MTD_ERASE_FAILED;
1952 goto erase_exit;
1953 }
1954
David A. Marlin30f464b2005-01-17 18:35:25 +00001955 /* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */
1956 if (this->options & BBT_AUTO_REFRESH) {
1957 bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
1958 } else {
1959 bbt_masked_page = 0xffffffff; /* should not match anything */
1960 }
1961
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 /* Loop through the pages */
1963 len = instr->len;
1964
1965 instr->state = MTD_ERASING;
1966
1967 while (len) {
1968 /* Check if we have a bad block, we do not erase bad blocks ! */
1969 if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001970 printk(KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 instr->state = MTD_ERASE_FAILED;
1972 goto erase_exit;
1973 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001974
1975 /* Invalidate the page cache, if we erase the block which contains
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 the current cached page */
1977 if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
1978 this->pagebuf = -1;
1979
David Woodhousee0c7d762006-05-13 18:07:53 +01001980 this->erase_cmd(mtd, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001981
David Woodhousee0c7d762006-05-13 18:07:53 +01001982 status = this->waitfunc(mtd, this, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
David A. Marlin068e3c02005-01-24 03:07:46 +00001984 /* See if operation failed and additional status checks are available */
1985 if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
1986 status = this->errstat(mtd, this, FL_ERASING, status, page);
1987 }
1988
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001990 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001991 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 instr->state = MTD_ERASE_FAILED;
1993 instr->fail_addr = (page << this->page_shift);
1994 goto erase_exit;
1995 }
David A. Marlin30f464b2005-01-17 18:35:25 +00001996
1997 /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */
1998 if (this->options & BBT_AUTO_REFRESH) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001999 if (((page & BBT_PAGE_MASK) == bbt_masked_page) &&
David A. Marlin30f464b2005-01-17 18:35:25 +00002000 (page != this->bbt_td->pages[chipnr])) {
2001 rewrite_bbt[chipnr] = (page << this->page_shift);
2002 }
2003 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002004
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 /* Increment page address and decrement length */
2006 len -= (1 << this->phys_erase_shift);
2007 page += pages_per_block;
2008
2009 /* Check, if we cross a chip boundary */
2010 if (len && !(page & this->pagemask)) {
2011 chipnr++;
2012 this->select_chip(mtd, -1);
2013 this->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00002014
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002015 /* if BBT requires refresh and BBT-PERCHIP,
David A. Marlin30f464b2005-01-17 18:35:25 +00002016 * set the BBT page mask to see if this BBT should be rewritten */
2017 if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) {
2018 bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
2019 }
2020
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 }
2022 }
2023 instr->state = MTD_ERASE_DONE;
2024
David Woodhousee0c7d762006-05-13 18:07:53 +01002025 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
2027 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
2028 /* Do call back function */
2029 if (!ret)
2030 mtd_erase_callback(instr);
2031
2032 /* Deselect and wake up anyone waiting on the device */
2033 nand_release_device(mtd);
2034
David A. Marlin30f464b2005-01-17 18:35:25 +00002035 /* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */
2036 if ((this->options & BBT_AUTO_REFRESH) && (!ret)) {
2037 for (chipnr = 0; chipnr < this->numchips; chipnr++) {
2038 if (rewrite_bbt[chipnr]) {
2039 /* update the BBT for chip */
David Woodhousee0c7d762006-05-13 18:07:53 +01002040 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n",
2041 chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]);
2042 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00002043 }
2044 }
2045 }
2046
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 /* Return more or less happy */
2048 return ret;
2049}
2050
2051/**
2052 * nand_sync - [MTD Interface] sync
2053 * @mtd: MTD device structure
2054 *
2055 * Sync is actually a wait for chip ready function
2056 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002057static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058{
2059 struct nand_chip *this = mtd->priv;
2060
David Woodhousee0c7d762006-05-13 18:07:53 +01002061 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
2063 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01002064 nand_get_device(this, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01002066 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067}
2068
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069/**
2070 * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
2071 * @mtd: MTD device structure
2072 * @ofs: offset relative to mtd start
2073 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002074static int nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075{
2076 /* Check for invalid offset */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002077 if (ofs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002079
David Woodhousee0c7d762006-05-13 18:07:53 +01002080 return nand_block_checkbad(mtd, ofs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081}
2082
2083/**
2084 * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
2085 * @mtd: MTD device structure
2086 * @ofs: offset relative to mtd start
2087 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002088static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089{
2090 struct nand_chip *this = mtd->priv;
2091 int ret;
2092
David Woodhousee0c7d762006-05-13 18:07:53 +01002093 if ((ret = nand_block_isbad(mtd, ofs))) {
2094 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 if (ret > 0)
2096 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01002097 return ret;
2098 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099
2100 return this->block_markbad(mtd, ofs);
2101}
2102
2103/**
Vitaly Wool962034f2005-09-15 14:58:53 +01002104 * nand_suspend - [MTD Interface] Suspend the NAND flash
2105 * @mtd: MTD device structure
2106 */
2107static int nand_suspend(struct mtd_info *mtd)
2108{
2109 struct nand_chip *this = mtd->priv;
2110
David Woodhousee0c7d762006-05-13 18:07:53 +01002111 return nand_get_device(this, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01002112}
2113
2114/**
2115 * nand_resume - [MTD Interface] Resume the NAND flash
2116 * @mtd: MTD device structure
2117 */
2118static void nand_resume(struct mtd_info *mtd)
2119{
2120 struct nand_chip *this = mtd->priv;
2121
2122 if (this->state == FL_PM_SUSPENDED)
2123 nand_release_device(mtd);
2124 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02002125 printk(KERN_ERR "nand_resume() called for a chip which is not "
2126 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01002127}
2128
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002129/*
2130 * Free allocated data structures
2131 */
2132static void nand_free_kmem(struct nand_chip *this)
2133{
2134 /* Buffer allocated by nand_scan ? */
2135 if (this->options & NAND_OOBBUF_ALLOC)
2136 kfree(this->oob_buf);
2137 /* Buffer allocated by nand_scan ? */
2138 if (this->options & NAND_DATABUF_ALLOC)
2139 kfree(this->data_buf);
2140 /* Controller allocated by nand_scan ? */
2141 if (this->options & NAND_CONTROLLER_ALLOC)
2142 kfree(this->controller);
2143}
2144
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002145/*
2146 * Allocate buffers and data structures
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 */
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002148static int nand_allocate_kmem(struct mtd_info *mtd, struct nand_chip *this)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149{
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002150 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002152 if (!this->oob_buf) {
2153 len = mtd->oobsize <<
2154 (this->phys_erase_shift - this->page_shift);
2155 this->oob_buf = kmalloc(len, GFP_KERNEL);
2156 if (!this->oob_buf)
2157 goto outerr;
2158 this->options |= NAND_OOBBUF_ALLOC;
David Woodhouse552d9202006-05-14 01:20:46 +01002159 }
2160
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002161 if (!this->data_buf) {
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002162 len = mtd->writesize + mtd->oobsize;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002163 this->data_buf = kmalloc(len, GFP_KERNEL);
2164 if (!this->data_buf)
2165 goto outerr;
2166 this->options |= NAND_DATABUF_ALLOC;
2167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002169 if (!this->controller) {
2170 this->controller = kzalloc(sizeof(struct nand_hw_control),
2171 GFP_KERNEL);
2172 if (!this->controller)
2173 goto outerr;
2174 this->options |= NAND_CONTROLLER_ALLOC;
2175 }
2176 return 0;
2177
2178 outerr:
2179 printk(KERN_ERR "nand_scan(): Cannot allocate buffers\n");
2180 nand_free_kmem(this);
2181 return -ENOMEM;
2182}
2183
2184/*
2185 * Set default functions
2186 */
2187static void nand_set_defaults(struct nand_chip *this, int busw)
2188{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 /* check for proper chip_delay setup, set 20us if not */
2190 if (!this->chip_delay)
2191 this->chip_delay = 20;
2192
2193 /* check, if a user supplied command function given */
2194 if (this->cmdfunc == NULL)
2195 this->cmdfunc = nand_command;
2196
2197 /* check, if a user supplied wait function given */
2198 if (this->waitfunc == NULL)
2199 this->waitfunc = nand_wait;
2200
2201 if (!this->select_chip)
2202 this->select_chip = nand_select_chip;
2203 if (!this->write_byte)
2204 this->write_byte = busw ? nand_write_byte16 : nand_write_byte;
2205 if (!this->read_byte)
2206 this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
2207 if (!this->write_word)
2208 this->write_word = nand_write_word;
2209 if (!this->read_word)
2210 this->read_word = nand_read_word;
2211 if (!this->block_bad)
2212 this->block_bad = nand_block_bad;
2213 if (!this->block_markbad)
2214 this->block_markbad = nand_default_block_markbad;
2215 if (!this->write_buf)
2216 this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
2217 if (!this->read_buf)
2218 this->read_buf = busw ? nand_read_buf16 : nand_read_buf;
2219 if (!this->verify_buf)
2220 this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
2221 if (!this->scan_bbt)
2222 this->scan_bbt = nand_default_bbt;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002223}
2224
2225/*
2226 * Get the flash and manufacturer id and lookup if the typ is supported
2227 */
2228static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2229 struct nand_chip *this,
2230 int busw, int *maf_id)
2231{
2232 struct nand_flash_dev *type = NULL;
2233 int i, dev_id, maf_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
2235 /* Select the device */
2236 this->select_chip(mtd, 0);
2237
2238 /* Send the command for reading device ID */
David Woodhousee0c7d762006-05-13 18:07:53 +01002239 this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241 /* Read manufacturer and device IDs */
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002242 *maf_id = this->read_byte(mtd);
2243 dev_id = this->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002245 /* Lookup the flash id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002247 if (dev_id == nand_flash_ids[i].id) {
2248 type = &nand_flash_ids[i];
2249 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 }
2252
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002253 if (!type)
2254 return ERR_PTR(-ENODEV);
2255
2256 this->chipsize = nand_flash_ids[i].chipsize << 20;
2257
2258 /* Newer devices have all the information in additional id bytes */
2259 if (!nand_flash_ids[i].pagesize) {
2260 int extid;
2261 /* The 3rd id byte contains non relevant data ATM */
2262 extid = this->read_byte(mtd);
2263 /* The 4th id byte is the important one */
2264 extid = this->read_byte(mtd);
2265 /* Calc pagesize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002266 mtd->writesize = 1024 << (extid & 0x3);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002267 extid >>= 2;
2268 /* Calc oobsize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002269 mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002270 extid >>= 2;
2271 /* Calc blocksize. Blocksize is multiples of 64KiB */
2272 mtd->erasesize = (64 * 1024) << (extid & 0x03);
2273 extid >>= 2;
2274 /* Get buswidth information */
2275 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
2276
2277 } else {
2278 /*
2279 * Old devices have this data hardcoded in the device id table
2280 */
2281 mtd->erasesize = nand_flash_ids[i].erasesize;
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002282 mtd->writesize = nand_flash_ids[i].pagesize;
2283 mtd->oobsize = mtd->writesize / 32;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002284 busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
2285 }
2286
2287 /* Try to identify manufacturer */
2288 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
2289 if (nand_manuf_ids[maf_idx].id == *maf_id)
2290 break;
2291 }
2292
2293 /*
2294 * Check, if buswidth is correct. Hardware drivers should set
2295 * this correct !
2296 */
2297 if (busw != (this->options & NAND_BUSWIDTH_16)) {
2298 printk(KERN_INFO "NAND device: Manufacturer ID:"
2299 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2300 dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2301 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
2302 (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
2303 busw ? 16 : 8);
2304 return ERR_PTR(-EINVAL);
2305 }
2306
2307 /* Calculate the address shift from the page size */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002308 this->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002309 /* Convert chipsize to number of pages per chip -1. */
2310 this->pagemask = (this->chipsize >> this->page_shift) - 1;
2311
2312 this->bbt_erase_shift = this->phys_erase_shift =
2313 ffs(mtd->erasesize) - 1;
2314 this->chip_shift = ffs(this->chipsize) - 1;
2315
2316 /* Set the bad block position */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002317 this->badblockpos = mtd->writesize > 512 ?
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002318 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
2319
2320 /* Get chip options, preserve non chip based options */
2321 this->options &= ~NAND_CHIPOPTIONS_MSK;
2322 this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
2323
2324 /*
2325 * Set this as a default. Board drivers can override it, if necessary
2326 */
2327 this->options |= NAND_NO_AUTOINCR;
2328
2329 /* Check if this is a not a samsung device. Do not clear the
2330 * options for chips which are not having an extended id.
2331 */
2332 if (*maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
2333 this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
2334
2335 /* Check for AND chips with 4 page planes */
2336 if (this->options & NAND_4PAGE_ARRAY)
2337 this->erase_cmd = multi_erase_cmd;
2338 else
2339 this->erase_cmd = single_erase_cmd;
2340
2341 /* Do not replace user supplied command function ! */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002342 if (mtd->writesize > 512 && this->cmdfunc == nand_command)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002343 this->cmdfunc = nand_command_lp;
2344
2345 printk(KERN_INFO "NAND device: Manufacturer ID:"
2346 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
2347 nand_manuf_ids[maf_idx].name, type->name);
2348
2349 return type;
2350}
2351
2352/* module_text_address() isn't exported, and it's mostly a pointless
2353 test if this is a module _anyway_ -- they'd have to try _really_ hard
2354 to call us from in-kernel code if the core NAND support is modular. */
2355#ifdef MODULE
2356#define caller_is_module() (1)
2357#else
2358#define caller_is_module() \
2359 module_text_address((unsigned long)__builtin_return_address(0))
2360#endif
2361
2362/**
2363 * nand_scan - [NAND Interface] Scan for the NAND device
2364 * @mtd: MTD device structure
2365 * @maxchips: Number of chips to scan for
2366 *
2367 * This fills out all the uninitialized function pointers
2368 * with the defaults.
2369 * The flash ID is read and the mtd/chip structures are
2370 * filled with the appropriate values. Buffers are allocated if
2371 * they are not provided by the board driver
2372 * The mtd->owner field must be set to the module of the caller
2373 *
2374 */
2375int nand_scan(struct mtd_info *mtd, int maxchips)
2376{
2377 int i, busw, nand_maf_id;
2378 struct nand_chip *this = mtd->priv;
2379 struct nand_flash_dev *type;
2380
2381 /* Many callers got this wrong, so check for it for a while... */
2382 if (!mtd->owner && caller_is_module()) {
2383 printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
2384 BUG();
2385 }
2386
2387 /* Get buswidth to select the correct functions */
2388 busw = this->options & NAND_BUSWIDTH_16;
2389 /* Set the default functions */
2390 nand_set_defaults(this, busw);
2391
2392 /* Read the flash type */
2393 type = nand_get_flash_type(mtd, this, busw, &nand_maf_id);
2394
2395 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002396 printk(KERN_WARNING "No NAND device found!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 this->select_chip(mtd, -1);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002398 return PTR_ERR(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 }
2400
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002401 /* Check for a chip array */
David Woodhousee0c7d762006-05-13 18:07:53 +01002402 for (i = 1; i < maxchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 this->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 /* Send the command for reading device ID */
David Woodhousee0c7d762006-05-13 18:07:53 +01002405 this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 /* Read manufacturer and device IDs */
2407 if (nand_maf_id != this->read_byte(mtd) ||
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002408 type->id != this->read_byte(mtd))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 break;
2410 }
2411 if (i > 1)
2412 printk(KERN_INFO "%d NAND chips detected\n", i);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002413
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 /* Store the number of chips and calc total size for mtd */
2415 this->numchips = i;
2416 mtd->size = i * this->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002418 /* Allocate buffers and data structures */
2419 if (nand_allocate_kmem(mtd, this))
2420 return -ENOMEM;
2421
2422 /* Preset the internal oob buffer */
2423 memset(this->oob_buf, 0xff,
2424 mtd->oobsize << (this->phys_erase_shift - this->page_shift));
2425
2426 /*
2427 * If no default placement scheme is given, select an appropriate one
2428 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 if (!this->autooob) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002430 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 case 8:
2432 this->autooob = &nand_oob_8;
2433 break;
2434 case 16:
2435 this->autooob = &nand_oob_16;
2436 break;
2437 case 64:
2438 this->autooob = &nand_oob_64;
2439 break;
2440 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002441 printk(KERN_WARNING "No oob scheme defined for "
2442 "oobsize %d\n", mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 BUG();
2444 }
2445 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002446
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002447 /*
2448 * The number of bytes available for the filesystem to place fs
2449 * dependend oob data
2450 */
Thomas Gleixner998cf642005-04-01 08:21:48 +01002451 mtd->oobavail = 0;
2452 for (i = 0; this->autooob->oobfree[i][1]; i++)
2453 mtd->oobavail += this->autooob->oobfree[i][1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002455 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002456 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2457 * selected and we have 256 byte pagesize fallback to software ECC
David Woodhousee0c7d762006-05-13 18:07:53 +01002458 */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002459 switch (this->ecc.mode) {
2460 case NAND_ECC_HW:
2461 case NAND_ECC_HW_SYNDROME:
2462 if (!this->ecc.calculate || !this->ecc.correct ||
2463 !this->ecc.hwctl) {
2464 printk(KERN_WARNING "No ECC functions supplied, "
2465 "Hardware ECC not possible\n");
2466 BUG();
2467 }
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002468 if (mtd->writesize >= this->ecc.size)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002469 break;
2470 printk(KERN_WARNING "%d byte HW ECC not possible on "
2471 "%d byte page size, fallback to SW ECC\n",
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002472 this->ecc.size, mtd->writesize);
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002473 this->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002475 case NAND_ECC_SOFT:
2476 this->ecc.calculate = nand_calculate_ecc;
2477 this->ecc.correct = nand_correct_data;
2478 this->ecc.size = 256;
2479 this->ecc.bytes = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002481
2482 case NAND_ECC_NONE:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002483 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2484 "This is not recommended !!\n");
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002485 this->ecc.size = mtd->writesize;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002486 this->ecc.bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002489 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002490 this->ecc.mode);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002491 BUG();
2492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002494 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002495 * Set the number of read / write steps for one page depending on ECC
2496 * mode
2497 */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002498 this->ecc.steps = mtd->writesize / this->ecc.size;
2499 if(this->ecc.steps * this->ecc.size != mtd->writesize) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002500 printk(KERN_WARNING "Invalid ecc parameters\n");
2501 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002503
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 /* Initialize state, waitqueue and spinlock */
2505 this->state = FL_READY;
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002506 init_waitqueue_head(&this->controller->wq);
2507 spin_lock_init(&this->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
2509 /* De-select the device */
2510 this->select_chip(mtd, -1);
2511
2512 /* Invalidate the pagebuffer reference */
2513 this->pagebuf = -1;
2514
2515 /* Fill in remaining MTD driver data */
2516 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002517 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 mtd->ecctype = MTD_ECC_SW;
2519 mtd->erase = nand_erase;
2520 mtd->point = NULL;
2521 mtd->unpoint = NULL;
2522 mtd->read = nand_read;
2523 mtd->write = nand_write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 mtd->read_oob = nand_read_oob;
2525 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 mtd->sync = nand_sync;
2527 mtd->lock = NULL;
2528 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002529 mtd->suspend = nand_suspend;
2530 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 mtd->block_isbad = nand_block_isbad;
2532 mtd->block_markbad = nand_block_markbad;
2533
2534 /* and make the autooob the default one */
2535 memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
2536
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002537 /* Check, if we should skip the bad block table scan */
2538 if (this->options & NAND_SKIP_BBTSCAN)
2539 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
2541 /* Build bad block table */
David Woodhousee0c7d762006-05-13 18:07:53 +01002542 return this->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543}
2544
2545/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002546 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 * @mtd: MTD device structure
2548*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002549void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550{
2551 struct nand_chip *this = mtd->priv;
2552
2553#ifdef CONFIG_MTD_PARTITIONS
2554 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002555 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556#endif
2557 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002558 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
Jesper Juhlfa671642005-11-07 01:01:27 -08002560 /* Free bad block table memory */
David Woodhousee0c7d762006-05-13 18:07:53 +01002561 kfree(this->bbt);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002562 /* Free buffers */
2563 nand_free_kmem(this);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564}
2565
David Woodhousee0c7d762006-05-13 18:07:53 +01002566EXPORT_SYMBOL_GPL(nand_scan);
2567EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002568
2569static int __init nand_base_init(void)
2570{
2571 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2572 return 0;
2573}
2574
2575static void __exit nand_base_exit(void)
2576{
2577 led_trigger_unregister_simple(nand_led_trigger);
2578}
2579
2580module_init(nand_base_init);
2581module_exit(nand_base_exit);
2582
David Woodhousee0c7d762006-05-13 18:07:53 +01002583MODULE_LICENSE("GPL");
2584MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2585MODULE_DESCRIPTION("Generic NAND flash driver code");