blob: 649c238837bb73715e5ac3cf0cf603ecc1ec8dde [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
Thomas Gleixnerd470a972006-05-23 23:48:57 +0200167/*
168 * For devices which display every fart in the system on a seperate LED. Is
169 * compiled away when LED support is disabled.
170 */
171DEFINE_LED_TRIGGER(nand_led_trigger);
172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173/**
174 * nand_release_device - [GENERIC] release chip
175 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000176 *
177 * Deselect, release chip lock and wake up anyone waiting on the device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100179static void nand_release_device(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180{
181 struct nand_chip *this = mtd->priv;
182
183 /* De-select the NAND device */
184 this->select_chip(mtd, -1);
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100185
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200186 /* Release the controller and the chip */
187 spin_lock(&this->controller->lock);
188 this->controller->active = NULL;
189 this->state = FL_READY;
190 wake_up(&this->controller->wq);
191 spin_unlock(&this->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192}
193
194/**
195 * nand_read_byte - [DEFAULT] read one byte from the chip
196 * @mtd: MTD device structure
197 *
198 * Default read function for 8bit buswith
199 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200200static uint8_t nand_read_byte(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 struct nand_chip *this = mtd->priv;
203 return readb(this->IO_ADDR_R);
204}
205
206/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
208 * @mtd: MTD device structure
209 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000210 * Default read function for 16bit buswith with
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 * endianess conversion
212 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200213static uint8_t nand_read_byte16(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
215 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200216 return (uint8_t) cpu_to_le16(readw(this->IO_ADDR_R));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217}
218
219/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 * nand_read_word - [DEFAULT] read one word from the chip
221 * @mtd: MTD device structure
222 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000223 * Default read function for 16bit buswith without
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 * endianess conversion
225 */
226static u16 nand_read_word(struct mtd_info *mtd)
227{
228 struct nand_chip *this = mtd->priv;
229 return readw(this->IO_ADDR_R);
230}
231
232/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 * nand_select_chip - [DEFAULT] control CE line
234 * @mtd: MTD device structure
235 * @chip: chipnumber to select, -1 for deselect
236 *
237 * Default select function for 1 chip devices.
238 */
239static void nand_select_chip(struct mtd_info *mtd, int chip)
240{
241 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100242 switch (chip) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 case -1:
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200244 this->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 break;
246 case 0:
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200247 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 break;
249
250 default:
251 BUG();
252 }
253}
254
255/**
256 * nand_write_buf - [DEFAULT] write buffer to chip
257 * @mtd: MTD device structure
258 * @buf: data buffer
259 * @len: number of bytes to write
260 *
261 * Default write function for 8bit buswith
262 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200263static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264{
265 int i;
266 struct nand_chip *this = mtd->priv;
267
David Woodhousee0c7d762006-05-13 18:07:53 +0100268 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 writeb(buf[i], this->IO_ADDR_W);
270}
271
272/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000273 * nand_read_buf - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 * @mtd: MTD device structure
275 * @buf: buffer to store date
276 * @len: number of bytes to read
277 *
278 * Default read function for 8bit buswith
279 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200280static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
282 int i;
283 struct nand_chip *this = mtd->priv;
284
David Woodhousee0c7d762006-05-13 18:07:53 +0100285 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 buf[i] = readb(this->IO_ADDR_R);
287}
288
289/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000290 * nand_verify_buf - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 * @mtd: MTD device structure
292 * @buf: buffer containing the data to compare
293 * @len: number of bytes to compare
294 *
295 * Default verify function for 8bit buswith
296 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200297static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298{
299 int i;
300 struct nand_chip *this = mtd->priv;
301
David Woodhousee0c7d762006-05-13 18:07:53 +0100302 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 if (buf[i] != readb(this->IO_ADDR_R))
304 return -EFAULT;
305
306 return 0;
307}
308
309/**
310 * nand_write_buf16 - [DEFAULT] write buffer to chip
311 * @mtd: MTD device structure
312 * @buf: data buffer
313 * @len: number of bytes to write
314 *
315 * Default write function for 16bit buswith
316 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200317static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
319 int i;
320 struct nand_chip *this = mtd->priv;
321 u16 *p = (u16 *) buf;
322 len >>= 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000323
David Woodhousee0c7d762006-05-13 18:07:53 +0100324 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 writew(p[i], this->IO_ADDR_W);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000326
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327}
328
329/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000330 * nand_read_buf16 - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 * @mtd: MTD device structure
332 * @buf: buffer to store date
333 * @len: number of bytes to read
334 *
335 * Default read function for 16bit buswith
336 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200337static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{
339 int i;
340 struct nand_chip *this = mtd->priv;
341 u16 *p = (u16 *) buf;
342 len >>= 1;
343
David Woodhousee0c7d762006-05-13 18:07:53 +0100344 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 p[i] = readw(this->IO_ADDR_R);
346}
347
348/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000349 * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 * @mtd: MTD device structure
351 * @buf: buffer containing the data to compare
352 * @len: number of bytes to compare
353 *
354 * Default verify function for 16bit buswith
355 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200356static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
358 int i;
359 struct nand_chip *this = mtd->priv;
360 u16 *p = (u16 *) buf;
361 len >>= 1;
362
David Woodhousee0c7d762006-05-13 18:07:53 +0100363 for (i = 0; i < len; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 if (p[i] != readw(this->IO_ADDR_R))
365 return -EFAULT;
366
367 return 0;
368}
369
370/**
371 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
372 * @mtd: MTD device structure
373 * @ofs: offset from device start
374 * @getchip: 0, if the chip is already selected
375 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000376 * Check, if the block is bad.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 */
378static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
379{
380 int page, chipnr, res = 0;
381 struct nand_chip *this = mtd->priv;
382 u16 bad;
383
384 if (getchip) {
385 page = (int)(ofs >> this->page_shift);
386 chipnr = (int)(ofs >> this->chip_shift);
387
388 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +0100389 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391 /* Select the NAND device */
392 this->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000393 } else
David Woodhousee0c7d762006-05-13 18:07:53 +0100394 page = (int)ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
396 if (this->options & NAND_BUSWIDTH_16) {
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200397 this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE,
398 page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 bad = cpu_to_le16(this->read_word(mtd));
400 if (this->badblockpos & 0x1)
Vitaly Wool49196f32005-11-02 16:54:46 +0000401 bad >>= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 if ((bad & 0xFF) != 0xff)
403 res = 1;
404 } else {
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200405 this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos,
406 page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 if (this->read_byte(mtd) != 0xff)
408 res = 1;
409 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000410
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 if (getchip) {
412 /* Deselect and wake up anyone waiting on the device */
413 nand_release_device(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000414 }
415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 return res;
417}
418
419/**
420 * nand_default_block_markbad - [DEFAULT] mark a block bad
421 * @mtd: MTD device structure
422 * @ofs: offset from device start
423 *
424 * This is the default implementation, which can be overridden by
425 * a hardware specific driver.
426*/
427static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
428{
429 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200430 uint8_t buf[2] = { 0, 0 };
David Woodhousee0c7d762006-05-13 18:07:53 +0100431 size_t retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 int block;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000433
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 /* Get block number */
David Woodhousee0c7d762006-05-13 18:07:53 +0100435 block = ((int)ofs) >> this->bbt_erase_shift;
Artem B. Bityuckiy41ce9212005-02-09 14:50:00 +0000436 if (this->bbt)
437 this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
439 /* Do we have a flash based bad block table ? */
440 if (this->options & NAND_USE_FLASH_BBT)
David Woodhousee0c7d762006-05-13 18:07:53 +0100441 return nand_update_bbt(mtd, ofs);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000442
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 /* We write two bytes, so we dont have to mess with 16 bit access */
444 ofs += mtd->oobsize + (this->badblockpos & ~0x01);
David Woodhousee0c7d762006-05-13 18:07:53 +0100445 return nand_write_oob(mtd, ofs, 2, &retlen, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000448/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 * nand_check_wp - [GENERIC] check if the chip is write protected
450 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000451 * Check, if the device is write protected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000453 * The function expects, that the device is already selected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100455static int nand_check_wp(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
457 struct nand_chip *this = mtd->priv;
458 /* Check the WP bit */
David Woodhousee0c7d762006-05-13 18:07:53 +0100459 this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000460 return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461}
462
463/**
464 * nand_block_checkbad - [GENERIC] Check if a block is marked bad
465 * @mtd: MTD device structure
466 * @ofs: offset from device start
467 * @getchip: 0, if the chip is already selected
468 * @allowbbt: 1, if its allowed to access the bbt area
469 *
470 * Check, if the block is bad. Either by reading the bad block table or
471 * calling of the scan function.
472 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200473static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
474 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475{
476 struct nand_chip *this = mtd->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 if (!this->bbt)
479 return this->block_bad(mtd, ofs, getchip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 /* Return info from the table */
David Woodhousee0c7d762006-05-13 18:07:53 +0100482 return nand_isbad_bbt(mtd, ofs, allowbbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483}
484
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000485/*
Thomas Gleixner3b887752005-02-22 21:56:49 +0000486 * Wait for the ready pin, after a command
487 * The timeout is catched later.
488 */
489static void nand_wait_ready(struct mtd_info *mtd)
490{
491 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100492 unsigned long timeo = jiffies + 2;
Thomas Gleixner3b887752005-02-22 21:56:49 +0000493
Richard Purdie8fe833c2006-03-31 02:31:14 -0800494 led_trigger_event(nand_led_trigger, LED_FULL);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000495 /* wait until command is processed or timeout occures */
496 do {
497 if (this->dev_ready(mtd))
Richard Purdie8fe833c2006-03-31 02:31:14 -0800498 break;
Ingo Molnar8446f1d2005-09-06 15:16:27 -0700499 touch_softlockup_watchdog();
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000500 } while (time_before(jiffies, timeo));
Richard Purdie8fe833c2006-03-31 02:31:14 -0800501 led_trigger_event(nand_led_trigger, LED_OFF);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000502}
503
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504/**
505 * nand_command - [DEFAULT] Send command to NAND device
506 * @mtd: MTD device structure
507 * @command: the command to be sent
508 * @column: the column address for this command, -1 if none
509 * @page_addr: the page address for this command, -1 if none
510 *
511 * Send command to NAND device. This function is used for small page
512 * devices (256/512 Bytes per page)
513 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200514static void nand_command(struct mtd_info *mtd, unsigned int command,
515 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516{
517 register struct nand_chip *this = mtd->priv;
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200518 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 /*
521 * Write out the command to the device.
522 */
523 if (command == NAND_CMD_SEQIN) {
524 int readcmd;
525
Joern Engel28318772006-05-22 23:18:05 +0200526 if (column >= mtd->writesize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 /* OOB area */
Joern Engel28318772006-05-22 23:18:05 +0200528 column -= mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 readcmd = NAND_CMD_READOOB;
530 } else if (column < 256) {
531 /* First 256 bytes --> READ0 */
532 readcmd = NAND_CMD_READ0;
533 } else {
534 column -= 256;
535 readcmd = NAND_CMD_READ1;
536 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200537 this->cmd_ctrl(mtd, readcmd, ctrl);
538 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200540 this->cmd_ctrl(mtd, command, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200542 /*
543 * Address cycle, when necessary
544 */
545 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
546 /* Serially input address */
547 if (column != -1) {
548 /* Adjust columns for 16 bit buswidth */
549 if (this->options & NAND_BUSWIDTH_16)
550 column >>= 1;
551 this->cmd_ctrl(mtd, column, ctrl);
552 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200554 if (page_addr != -1) {
555 this->cmd_ctrl(mtd, page_addr, ctrl);
556 ctrl &= ~NAND_CTRL_CHANGE;
557 this->cmd_ctrl(mtd, page_addr >> 8, ctrl);
558 /* One more address cycle for devices > 32MiB */
559 if (this->chipsize > (32 << 20))
560 this->cmd_ctrl(mtd, page_addr >> 16, ctrl);
561 }
562 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000563
564 /*
565 * program and erase have their own busy handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 * status and sequential in needs no delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100567 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000569
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 case NAND_CMD_PAGEPROG:
571 case NAND_CMD_ERASE1:
572 case NAND_CMD_ERASE2:
573 case NAND_CMD_SEQIN:
574 case NAND_CMD_STATUS:
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200575 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 return;
577
578 case NAND_CMD_RESET:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000579 if (this->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 break;
581 udelay(this->chip_delay);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200582 this->cmd_ctrl(mtd, NAND_CMD_STATUS,
583 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
584 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
David Woodhousee0c7d762006-05-13 18:07:53 +0100585 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 return;
587
David Woodhousee0c7d762006-05-13 18:07:53 +0100588 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000590 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 * If we don't have access to the busy pin, we apply the given
592 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100593 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 if (!this->dev_ready) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100595 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000597 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 /* Apply this short delay always to ensure that we do wait tWB in
600 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100601 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000602
603 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604}
605
606/**
607 * nand_command_lp - [DEFAULT] Send command to NAND large page device
608 * @mtd: MTD device structure
609 * @command: the command to be sent
610 * @column: the column address for this command, -1 if none
611 * @page_addr: the page address for this command, -1 if none
612 *
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200613 * Send command to NAND device. This is the version for the new large page
614 * devices We dont have the separate regions as we have in the small page
615 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 *
617 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200618static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
619 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620{
621 register struct nand_chip *this = mtd->priv;
622
623 /* Emulate NAND_CMD_READOOB */
624 if (command == NAND_CMD_READOOB) {
Joern Engel28318772006-05-22 23:18:05 +0200625 column += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 command = NAND_CMD_READ0;
627 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000628
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200629 /* Command latch cycle */
630 this->cmd_ctrl(mtd, command & 0xff,
631 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633 if (column != -1 || page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200634 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
636 /* Serially input address */
637 if (column != -1) {
638 /* Adjust columns for 16 bit buswidth */
639 if (this->options & NAND_BUSWIDTH_16)
640 column >>= 1;
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200641 this->cmd_ctrl(mtd, column, ctrl);
642 ctrl &= ~NAND_CTRL_CHANGE;
643 this->cmd_ctrl(mtd, column >> 8, ctrl);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 if (page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200646 this->cmd_ctrl(mtd, page_addr, ctrl);
647 this->cmd_ctrl(mtd, page_addr >> 8,
648 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 /* One more address cycle for devices > 128MiB */
650 if (this->chipsize > (128 << 20))
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200651 this->cmd_ctrl(mtd, page_addr >> 16,
652 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200655 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000656
657 /*
658 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000659 * status, sequential in, and deplete1 need no delay
660 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000662
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 case NAND_CMD_CACHEDPROG:
664 case NAND_CMD_PAGEPROG:
665 case NAND_CMD_ERASE1:
666 case NAND_CMD_ERASE2:
667 case NAND_CMD_SEQIN:
668 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000669 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 return;
671
David Woodhousee0c7d762006-05-13 18:07:53 +0100672 /*
673 * read error status commands require only a short delay
674 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000675 case NAND_CMD_STATUS_ERROR:
676 case NAND_CMD_STATUS_ERROR0:
677 case NAND_CMD_STATUS_ERROR1:
678 case NAND_CMD_STATUS_ERROR2:
679 case NAND_CMD_STATUS_ERROR3:
680 udelay(this->chip_delay);
681 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
683 case NAND_CMD_RESET:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000684 if (this->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 break;
686 udelay(this->chip_delay);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200687 this->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE | NAND_CLE);
688 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
David Woodhousee0c7d762006-05-13 18:07:53 +0100689 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 return;
691
692 case NAND_CMD_READ0:
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200693 this->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_NCE | NAND_CLE);
694 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000695
David Woodhousee0c7d762006-05-13 18:07:53 +0100696 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000698 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 * If we don't have access to the busy pin, we apply the given
700 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100701 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 if (!this->dev_ready) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100703 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000705 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000707
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 /* Apply this short delay always to ensure that we do wait tWB in
709 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100710 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000711
712 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713}
714
715/**
716 * nand_get_device - [GENERIC] Get chip for selected access
717 * @this: the nand chip descriptor
718 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000719 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 *
721 * Get the device and lock it for exclusive access
722 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200723static int
724nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725{
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200726 spinlock_t *lock = &this->controller->lock;
727 wait_queue_head_t *wq = &this->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100728 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100729 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100730 spin_lock(lock);
731
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200733 /* Hardware controller shared among independend devices */
734 if (!this->controller->active)
735 this->controller->active = this;
736
737 if (this->controller->active == this && this->state == FL_READY) {
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100738 this->state = new_state;
739 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100740 return 0;
741 }
742 if (new_state == FL_PM_SUSPENDED) {
743 spin_unlock(lock);
744 return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100745 }
746 set_current_state(TASK_UNINTERRUPTIBLE);
747 add_wait_queue(wq, &wait);
748 spin_unlock(lock);
749 schedule();
750 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 goto retry;
752}
753
754/**
755 * nand_wait - [DEFAULT] wait until the command is done
756 * @mtd: MTD device structure
757 * @this: NAND chip structure
758 * @state: state to select the max. timeout value
759 *
760 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000761 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 * general NAND and SmartMedia specs
763 *
764*/
765static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
766{
767
David Woodhousee0c7d762006-05-13 18:07:53 +0100768 unsigned long timeo = jiffies;
769 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100772 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100774 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
Richard Purdie8fe833c2006-03-31 02:31:14 -0800776 led_trigger_event(nand_led_trigger, LED_FULL);
777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 /* Apply this short delay always to ensure that we do wait tWB in
779 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100780 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
782 if ((state == FL_ERASING) && (this->options & NAND_IS_AND))
David Woodhousee0c7d762006-05-13 18:07:53 +0100783 this->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000784 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100785 this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000787 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 /* Check, if we were interrupted */
789 if (this->state != state)
790 return 0;
791
792 if (this->dev_ready) {
793 if (this->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000794 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 } else {
796 if (this->read_byte(mtd) & NAND_STATUS_READY)
797 break;
798 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000799 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800801 led_trigger_event(nand_led_trigger, LED_OFF);
802
David Woodhousee0c7d762006-05-13 18:07:53 +0100803 status = (int)this->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 return status;
805}
806
807/**
808 * nand_write_page - [GENERIC] write one page
809 * @mtd: MTD device structure
810 * @this: NAND chip structure
811 * @page: startpage inside the chip, must be called with (page & this->pagemask)
812 * @oob_buf: out of band data buffer
813 * @oobsel: out of band selecttion structre
814 * @cached: 1 = enable cached programming if supported by chip
815 *
816 * Nand_page_program function is used for write and writev !
817 * This function will always program a full page of data
818 * If you call it with a non page aligned buffer, you're lost :)
819 *
820 * Cached programming is not supported yet.
821 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100822static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int page,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200823 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int cached)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824{
David Woodhousee0c7d762006-05-13 18:07:53 +0100825 int i, status;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200826 uint8_t ecc_code[32];
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200827 int eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
David Woodhousee0c7d762006-05-13 18:07:53 +0100828 int *oob_config = oobsel->eccpos;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200829 int datidx = 0, eccidx = 0, eccsteps = this->ecc.steps;
David Woodhousee0c7d762006-05-13 18:07:53 +0100830 int eccbytes = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 /* FIXME: Enable cached programming */
833 cached = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 /* Send command to begin auto page programming */
David Woodhousee0c7d762006-05-13 18:07:53 +0100836 this->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
838 /* Write out complete page of data, take care of eccmode */
839 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100840 /* No ecc, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 case NAND_ECC_NONE:
David Woodhousee0c7d762006-05-13 18:07:53 +0100842 printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
Joern Engel28318772006-05-22 23:18:05 +0200843 this->write_buf(mtd, this->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000845
David Woodhousee0c7d762006-05-13 18:07:53 +0100846 /* Software ecc 3/256, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 case NAND_ECC_SOFT:
848 for (; eccsteps; eccsteps--) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200849 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 for (i = 0; i < 3; i++, eccidx++)
851 oob_buf[oob_config[eccidx]] = ecc_code[i];
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200852 datidx += this->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 }
Joern Engel28318772006-05-22 23:18:05 +0200854 this->write_buf(mtd, this->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 break;
856 default:
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200857 eccbytes = this->ecc.bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 for (; eccsteps; eccsteps--) {
859 /* enable hardware ecc logic for write */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200860 this->ecc.hwctl(mtd, NAND_ECC_WRITE);
861 this->write_buf(mtd, &this->data_poi[datidx], this->ecc.size);
862 this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 for (i = 0; i < eccbytes; i++, eccidx++)
864 oob_buf[oob_config[eccidx]] = ecc_code[i];
865 /* If the hardware ecc provides syndromes then
866 * the ecc code must be written immidiately after
867 * the data bytes (words) */
868 if (this->options & NAND_HWECC_SYNDROME)
869 this->write_buf(mtd, ecc_code, eccbytes);
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +0200870 datidx += this->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 }
872 break;
873 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000874
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 /* Write out OOB data */
876 if (this->options & NAND_HWECC_SYNDROME)
877 this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000878 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 this->write_buf(mtd, oob_buf, mtd->oobsize);
880
881 /* Send command to actually program the data */
David Woodhousee0c7d762006-05-13 18:07:53 +0100882 this->cmdfunc(mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 if (!cached) {
885 /* call wait ready function */
David Woodhousee0c7d762006-05-13 18:07:53 +0100886 status = this->waitfunc(mtd, this, FL_WRITING);
David A. Marlin068e3c02005-01-24 03:07:46 +0000887
888 /* See if operation failed and additional status checks are available */
889 if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
890 status = this->errstat(mtd, this, FL_WRITING, status, page);
891 }
892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +0000894 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100895 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 return -EIO;
897 }
898 } else {
899 /* FIXME: Implement cached programming ! */
David Woodhousee0c7d762006-05-13 18:07:53 +0100900 /* wait until cache is ready */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 // status = this->waitfunc (mtd, this, FL_CACHEDRPG);
902 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000903 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904}
905
906#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
907/**
908 * nand_verify_pages - [GENERIC] verify the chip contents after a write
909 * @mtd: MTD device structure
910 * @this: NAND chip structure
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200911 * @page: startpage inside the chip, must be called with (page & this->pagemask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 * @numpages: number of pages to verify
913 * @oob_buf: out of band data buffer
914 * @oobsel: out of band selecttion structre
915 * @chipnr: number of the current chip
916 * @oobmode: 1 = full buffer verify, 0 = ecc only
917 *
918 * The NAND device assumes that it is always writing to a cleanly erased page.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000919 * Hence, it performs its internal write verification only on bits that
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 * transitioned from 1 to 0. The device does NOT verify the whole page on a
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000921 * byte by byte basis. It is possible that the page was not completely erased
922 * or the page is becoming unusable due to wear. The read with ECC would catch
923 * the error later when the ECC page check fails, but we would rather catch
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 * it early in the page write stage. Better to write no data than invalid data.
925 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100926static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200927 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928{
David Woodhousee0c7d762006-05-13 18:07:53 +0100929 int i, j, datidx = 0, oobofs = 0, res = -EIO;
930 int eccsteps = this->eccsteps;
931 int hweccbytes;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200932 uint8_t oobdata[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
934 hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
935
936 /* Send command to read back the first page */
David Woodhousee0c7d762006-05-13 18:07:53 +0100937 this->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
David Woodhousee0c7d762006-05-13 18:07:53 +0100939 for (;;) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 for (j = 0; j < eccsteps; j++) {
941 /* Loop through and verify the data */
942 if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100943 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 goto out;
945 }
946 datidx += mtd->eccsize;
947 /* Have we a hw generator layout ? */
948 if (!hweccbytes)
949 continue;
950 if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100951 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 goto out;
953 }
954 oobofs += hweccbytes;
955 }
956
957 /* check, if we must compare all data or if we just have to
958 * compare the ecc bytes
959 */
960 if (oobmode) {
961 if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100962 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 goto out;
964 }
965 } else {
966 /* Read always, else autoincrement fails */
967 this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
968
969 if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
970 int ecccnt = oobsel->eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000971
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 for (i = 0; i < ecccnt; i++) {
973 int idx = oobsel->eccpos[i];
David Woodhousee0c7d762006-05-13 18:07:53 +0100974 if (oobdata[idx] != oob_buf[oobofs + idx]) {
975 DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed ECC write verify, page 0x%08x, %6i bytes were succesful\n",
976 __FUNCTION__, page, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 goto out;
978 }
979 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000980 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 }
982 oobofs += mtd->oobsize - hweccbytes * eccsteps;
983 page++;
984 numpages--;
985
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000986 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 * Do this before the AUTOINCR check, so no problems
988 * arise if a chip which does auto increment
989 * is marked as NOAUTOINCR by the board driver.
990 * Do this also before returning, so the chip is
991 * ready for the next command.
David Woodhousee0c7d762006-05-13 18:07:53 +0100992 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000993 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +0100994 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 else
Thomas Gleixner3b887752005-02-22 21:56:49 +0000996 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 /* All done, return happy */
999 if (!numpages)
1000 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001001
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001002 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 if (!NAND_CANAUTOINCR(this))
David Woodhousee0c7d762006-05-13 18:07:53 +01001004 this->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001006 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 * Terminate the read command. We come here in case of an error
1008 * So we must issue a reset command.
1009 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001010 out:
1011 this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return res;
1013}
1014#endif
1015
1016/**
David A. Marlin068e3c02005-01-24 03:07:46 +00001017 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 * @mtd: MTD device structure
1019 * @from: offset to read from
1020 * @len: number of bytes to read
1021 * @retlen: pointer to variable to store the number of read bytes
1022 * @buf: the databuffer to put data
1023 *
David A. Marlin068e3c02005-01-24 03:07:46 +00001024 * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL
1025 * and flags = 0xff
1026 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001027static 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 -07001028{
David Woodhousee0c7d762006-05-13 18:07:53 +01001029 return nand_do_read_ecc(mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001030}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032/**
David A. Marlin068e3c02005-01-24 03:07:46 +00001033 * nand_do_read_ecc - [MTD Interface] Read data with ECC
1034 * @mtd: MTD device structure
1035 * @from: offset to read from
1036 * @len: number of bytes to read
1037 * @retlen: pointer to variable to store the number of read bytes
1038 * @buf: the databuffer to put data
Dan Brownbb75ba42005-04-04 19:02:26 +01001039 * @oob_buf: filesystem supplied oob data buffer (can be NULL)
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001040 * @oobsel: oob selection structure
David A. Marlin068e3c02005-01-24 03:07:46 +00001041 * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed
1042 * and how many corrected error bits are acceptable:
1043 * bits 0..7 - number of tolerable errors
1044 * bit 8 - 0 == do not get/release chip, 1 == get/release chip
1045 *
1046 * NAND read with ECC
1047 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001048int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001049 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel, int flags)
David A. Marlin068e3c02005-01-24 03:07:46 +00001050{
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
1053 int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
1054 struct nand_chip *this = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001055 uint8_t *data_poi, *oob_data = oob_buf;
1056 uint8_t ecc_calc[32];
1057 uint8_t ecc_code[32];
David Woodhousee0c7d762006-05-13 18:07:53 +01001058 int eccmode, eccsteps;
1059 int *oob_config, datidx;
1060 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
1061 int eccbytes;
1062 int compareecc = 1;
1063 int oobreadlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
David Woodhousee0c7d762006-05-13 18:07:53 +01001065 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 -07001066
1067 /* Do not allow reads past end of device */
1068 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001069 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 *retlen = 0;
1071 return -EINVAL;
1072 }
1073
1074 /* Grab the lock and see if the device is available */
David A. Marlin068e3c02005-01-24 03:07:46 +00001075 if (flags & NAND_GET_DEVICE)
David Woodhousee0c7d762006-05-13 18:07:53 +01001076 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 /* Autoplace of oob data ? Use the default placement scheme */
1079 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
1080 oobsel = this->autooob;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001081
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001082 eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 oob_config = oobsel->eccpos;
1084
1085 /* Select the NAND device */
1086 chipnr = (int)(from >> this->chip_shift);
1087 this->select_chip(mtd, chipnr);
1088
1089 /* First we calculate the starting page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001090 realpage = (int)(from >> this->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 page = realpage & this->pagemask;
1092
1093 /* Get raw starting column */
Joern Engel28318772006-05-22 23:18:05 +02001094 col = from & (mtd->writesize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Joern Engel28318772006-05-22 23:18:05 +02001096 end = mtd->writesize;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001097 ecc = this->ecc.size;
1098 eccbytes = this->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001099
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
1101 compareecc = 0;
1102
1103 oobreadlen = mtd->oobsize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001104 if (this->options & NAND_HWECC_SYNDROME)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 oobreadlen -= oobsel->eccbytes;
1106
1107 /* Loop until all data read */
1108 while (read < len) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001109
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 int aligned = (!col && (len - read) >= end);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001111 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 * If the read is not page aligned, we have to read into data buffer
1113 * due to ecc, else we read into return buffer direct
1114 */
1115 if (aligned)
1116 data_poi = &buf[read];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001117 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 data_poi = this->data_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001119
1120 /* Check, if we have this page in the buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 *
1122 * FIXME: Make it work when we must provide oob data too,
1123 * check the usage of data_buf oob field
1124 */
1125 if (realpage == this->pagebuf && !oob_buf) {
1126 /* aligned read ? */
1127 if (aligned)
David Woodhousee0c7d762006-05-13 18:07:53 +01001128 memcpy(data_poi, this->data_buf, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 goto readdata;
1130 }
1131
1132 /* Check, if we must send the read command */
1133 if (sndcmd) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001134 this->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 sndcmd = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001136 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
1138 /* get oob area, if we have no oob buffer from fs-driver */
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001139 if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
1140 oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 oob_data = &this->data_buf[end];
1142
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001143 eccsteps = this->ecc.steps;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001144
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001146 case NAND_ECC_NONE:{
1147 /* No ECC, Read in a page */
1148 static unsigned long lastwhinge = 0;
1149 if ((lastwhinge / HZ) != (jiffies / HZ)) {
1150 printk(KERN_WARNING
1151 "Reading data from NAND FLASH without ECC is not recommended\n");
1152 lastwhinge = jiffies;
1153 }
1154 this->read_buf(mtd, data_poi, end);
1155 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001157
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
1159 this->read_buf(mtd, data_poi, end);
David Woodhousee0c7d762006-05-13 18:07:53 +01001160 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001161 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001162 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
1164 default:
David Woodhousee0c7d762006-05-13 18:07:53 +01001165 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001166 this->ecc.hwctl(mtd, NAND_ECC_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 this->read_buf(mtd, &data_poi[datidx], ecc);
1168
1169 /* HW ecc with syndrome calculation must read the
1170 * syndrome from flash immidiately after the data */
1171 if (!compareecc) {
1172 /* Some hw ecc generators need to know when the
1173 * syndrome is read from flash */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001174 this->ecc.hwctl(mtd, NAND_ECC_READSYN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 this->read_buf(mtd, &oob_data[i], eccbytes);
1176 /* We calc error correction directly, it checks the hw
1177 * generator for an error, reads back the syndrome and
1178 * does the error correction on the fly */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001179 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
David A. Marlin068e3c02005-01-24 03:07:46 +00001180 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001181 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
1182 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 ecc_failed++;
1184 }
1185 } else {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001186 this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001189 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 }
1191
1192 /* read oobdata */
1193 this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
1194
1195 /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
1196 if (!compareecc)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001197 goto readoob;
1198
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 /* Pick the ECC bytes out of the oob data */
1200 for (j = 0; j < oobsel->eccbytes; j++)
1201 ecc_code[j] = oob_data[oob_config[j]];
1202
David Woodhousee0c7d762006-05-13 18:07:53 +01001203 /* correct data, if necessary */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001204 for (i = 0, j = 0, datidx = 0; i < this->ecc.steps; i++, datidx += ecc) {
1205 ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 /* Get next chunk of ecc bytes */
1208 j += eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001209
1210 /* Check, if we have a fs supplied oob-buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 * This is the legacy mode. Used by YAFFS1
1212 * Should go away some day
1213 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001214 if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 int *p = (int *)(&oob_data[mtd->oobsize]);
1216 p[i] = ecc_status;
1217 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001218
1219 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001220 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 ecc_failed++;
1222 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
David Woodhousee0c7d762006-05-13 18:07:53 +01001225 readoob:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 /* check, if we have a fs supplied oob-buffer */
1227 if (oob_buf) {
1228 /* without autoplace. Legacy mode used by YAFFS1 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001229 switch (oobsel->useecc) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 case MTD_NANDECC_AUTOPLACE:
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001231 case MTD_NANDECC_AUTOPL_USR:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 /* Walk through the autoplace chunks */
Dan Brown82e1d192005-04-06 21:13:09 +01001233 for (i = 0; oobsel->oobfree[i][1]; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 int from = oobsel->oobfree[i][0];
1235 int num = oobsel->oobfree[i][1];
1236 memcpy(&oob_buf[oob], &oob_data[from], num);
Dan Brown82e1d192005-04-06 21:13:09 +01001237 oob += num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 break;
1240 case MTD_NANDECC_PLACE:
1241 /* YAFFS1 legacy mode */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02001242 oob_data += this->ecc.steps * sizeof(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 default:
1244 oob_data += mtd->oobsize;
1245 }
1246 }
1247 readdata:
1248 /* Partial page read, transfer data into fs buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001249 if (!aligned) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 for (j = col; j < end && read < len; j++)
1251 buf[read++] = data_poi[j];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001252 this->pagebuf = realpage;
1253 } else
Joern Engel28318772006-05-22 23:18:05 +02001254 read += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001256 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 * Do this before the AUTOINCR check, so no problems
1258 * arise if a chip which does auto increment
1259 * is marked as NOAUTOINCR by the board driver.
David Woodhousee0c7d762006-05-13 18:07:53 +01001260 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001261 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001262 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001264 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 if (read == len)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001267 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
1269 /* For subsequent reads align to page boundary. */
1270 col = 0;
1271 /* Increment page address */
1272 realpage++;
1273
1274 page = realpage & this->pagemask;
1275 /* Check, if we cross a chip boundary */
1276 if (!page) {
1277 chipnr++;
1278 this->select_chip(mtd, -1);
1279 this->select_chip(mtd, chipnr);
1280 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001281 /* Check, if the chip supports auto page increment
1282 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001283 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001285 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 }
1287
1288 /* Deselect and wake up anyone waiting on the device */
David A. Marlin068e3c02005-01-24 03:07:46 +00001289 if (flags & NAND_GET_DEVICE)
1290 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291
1292 /*
1293 * Return success, if no ECC failures, else -EBADMSG
1294 * fs driver will take care of that, because
1295 * retlen == desired len and result == -EBADMSG
1296 */
1297 *retlen = read;
1298 return ecc_failed ? -EBADMSG : 0;
1299}
1300
1301/**
1302 * nand_read_oob - [MTD Interface] NAND read out-of-band
1303 * @mtd: MTD device structure
1304 * @from: offset to read from
1305 * @len: number of bytes to read
1306 * @retlen: pointer to variable to store the number of read bytes
1307 * @buf: the databuffer to put data
1308 *
1309 * NAND read out-of-band data from the spare area
1310 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001311static 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 -07001312{
1313 int i, col, page, chipnr;
1314 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +01001315 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
David Woodhousee0c7d762006-05-13 18:07:53 +01001317 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 -07001318
1319 /* Shift to get page */
1320 page = (int)(from >> this->page_shift);
1321 chipnr = (int)(from >> this->chip_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001322
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 /* Mask to get column */
1324 col = from & (mtd->oobsize - 1);
1325
1326 /* Initialize return length value */
1327 *retlen = 0;
1328
1329 /* Do not allow reads past end of device */
1330 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001331 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 *retlen = 0;
1333 return -EINVAL;
1334 }
1335
1336 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001337 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
1339 /* Select the NAND device */
1340 this->select_chip(mtd, chipnr);
1341
1342 /* Send the read command */
David Woodhousee0c7d762006-05-13 18:07:53 +01001343 this->cmdfunc(mtd, NAND_CMD_READOOB, col, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001344 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 * Read the data, if we read more than one page
1346 * oob data, let the device transfer the data !
1347 */
1348 i = 0;
1349 while (i < len) {
1350 int thislen = mtd->oobsize - col;
1351 thislen = min_t(int, thislen, len);
1352 this->read_buf(mtd, &buf[i], thislen);
1353 i += thislen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
1355 /* Read more ? */
1356 if (i < len) {
1357 page++;
1358 col = 0;
1359
1360 /* Check, if we cross a chip boundary */
1361 if (!(page & this->pagemask)) {
1362 chipnr++;
1363 this->select_chip(mtd, -1);
1364 this->select_chip(mtd, chipnr);
1365 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001366
1367 /* Apply delay or wait for ready/busy pin
Thomas Gleixner19870da2005-07-15 14:53:51 +01001368 * Do this before the AUTOINCR check, so no problems
1369 * arise if a chip which does auto increment
1370 * is marked as NOAUTOINCR by the board driver.
1371 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001372 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001373 udelay(this->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001374 else
1375 nand_wait_ready(mtd);
1376
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001377 /* Check, if the chip supports auto page increment
1378 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001379 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {
1381 /* For subsequent page reads set offset to 0 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001382 this->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 }
1384 }
1385 }
1386
1387 /* Deselect and wake up anyone waiting on the device */
1388 nand_release_device(mtd);
1389
1390 /* Return happy */
1391 *retlen = len;
1392 return 0;
1393}
1394
1395/**
1396 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1397 * @mtd: MTD device structure
1398 * @buf: temporary buffer
1399 * @from: offset to read from
1400 * @len: number of bytes to read
1401 * @ooblen: number of oob data bytes to read
1402 *
1403 * Read raw data including oob into buffer
1404 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001405int 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 -07001406{
1407 struct nand_chip *this = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +01001408 int page = (int)(from >> this->page_shift);
1409 int chip = (int)(from >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 int sndcmd = 1;
1411 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001412 int pagesize = mtd->writesize + mtd->oobsize;
David Woodhousee0c7d762006-05-13 18:07:53 +01001413 int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
1415 /* Do not allow reads past end of device */
1416 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001417 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 return -EINVAL;
1419 }
1420
1421 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001422 nand_get_device(this, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
David Woodhousee0c7d762006-05-13 18:07:53 +01001424 this->select_chip(mtd, chip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001425
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 /* Add requested oob length */
1427 len += ooblen;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001428
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 while (len) {
1430 if (sndcmd)
David Woodhousee0c7d762006-05-13 18:07:53 +01001431 this->cmdfunc(mtd, NAND_CMD_READ0, 0, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001432 sndcmd = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
David Woodhousee0c7d762006-05-13 18:07:53 +01001434 this->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
1436 len -= pagesize;
1437 cnt += pagesize;
1438 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001439
1440 if (!this->dev_ready)
David Woodhousee0c7d762006-05-13 18:07:53 +01001441 udelay(this->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001443 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001444
1445 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
1447 sndcmd = 1;
1448 }
1449
1450 /* Deselect and wake up anyone waiting on the device */
1451 nand_release_device(mtd);
1452 return 0;
1453}
1454
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001455/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001456 * nand_write_raw - [GENERIC] Write raw data including oob
1457 * @mtd: MTD device structure
1458 * @buf: source buffer
1459 * @to: offset to write to
1460 * @len: number of bytes to write
1461 * @buf: source buffer
1462 * @oob: oob buffer
1463 *
1464 * Write raw data including oob
1465 */
1466int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1467 uint8_t *buf, uint8_t *oob)
1468{
1469 struct nand_chip *this = mtd->priv;
1470 int page = (int)(to >> this->page_shift);
1471 int chip = (int)(to >> this->chip_shift);
1472 int ret;
1473
1474 *retlen = 0;
1475
1476 /* Do not allow writes past end of device */
1477 if ((to + len) > mtd->size) {
1478 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1479 "beyond end of device\n");
1480 return -EINVAL;
1481 }
1482
1483 /* Grab the lock and see if the device is available */
1484 nand_get_device(this, mtd, FL_WRITING);
1485
1486 this->select_chip(mtd, chip);
1487 this->data_poi = buf;
1488
1489 while (len != *retlen) {
1490 ret = nand_write_page(mtd, this, page, oob, &mtd->oobinfo, 0);
1491 if (ret)
1492 return ret;
1493 page++;
1494 *retlen += mtd->writesize;
1495 this->data_poi += mtd->writesize;
1496 oob += mtd->oobsize;
1497 }
1498
1499 /* Deselect and wake up anyone waiting on the device */
1500 nand_release_device(mtd);
1501 return 0;
1502}
Thomas Gleixner38217202006-05-23 22:33:52 +02001503EXPORT_SYMBOL_GPL(nand_write_raw);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001504
1505/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001506 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 * @mtd: MTD device structure
1508 * @fsbuf: buffer given by fs driver
1509 * @oobsel: out of band selection structre
1510 * @autoplace: 1 = place given buffer into the oob bytes
1511 * @numpages: number of pages to prepare
1512 *
1513 * Return:
1514 * 1. Filesystem buffer available and autoplacement is off,
1515 * return filesystem buffer
1516 * 2. No filesystem buffer or autoplace is off, return internal
1517 * buffer
1518 * 3. Filesystem buffer is given and autoplace selected
1519 * put data from fs buffer into internal buffer and
1520 * retrun internal buffer
1521 *
1522 * Note: The internal buffer is filled with 0xff. This must
1523 * be done only once, when no autoplacement happens
1524 * Autoplacement sets the buffer dirty flag, which
1525 * forces the 0xff fill before using the buffer again.
1526 *
1527*/
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001528static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct nand_oobinfo *oobsel,
David Woodhousee0c7d762006-05-13 18:07:53 +01001529 int autoplace, int numpages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530{
1531 struct nand_chip *this = mtd->priv;
1532 int i, len, ofs;
1533
1534 /* Zero copy fs supplied buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001535 if (fsbuf && !autoplace)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 return fsbuf;
1537
1538 /* Check, if the buffer must be filled with ff again */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001539 if (this->oobdirty) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001540 memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 this->oobdirty = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001542 }
1543
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 /* If we have no autoplacement or no fs buffer use the internal one */
1545 if (!autoplace || !fsbuf)
1546 return this->oob_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001547
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 /* Walk through the pages and place the data */
1549 this->oobdirty = 1;
1550 ofs = 0;
1551 while (numpages--) {
1552 for (i = 0, len = 0; len < mtd->oobavail; i++) {
1553 int to = ofs + oobsel->oobfree[i][0];
1554 int num = oobsel->oobfree[i][1];
David Woodhousee0c7d762006-05-13 18:07:53 +01001555 memcpy(&this->oob_buf[to], fsbuf, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 len += num;
1557 fsbuf += num;
1558 }
1559 ofs += mtd->oobavail;
1560 }
1561 return this->oob_buf;
1562}
1563
Joern Engel28318772006-05-22 23:18:05 +02001564#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
1566/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001567 * nand_write - [MTD Interface] NAND write with ECC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 * @mtd: MTD device structure
1569 * @to: offset to write to
1570 * @len: number of bytes to write
1571 * @retlen: pointer to variable to store the number of written bytes
1572 * @buf: the data to write
1573 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 * NAND write with ECC
1575 */
Thomas Gleixner9223a452006-05-23 17:21:03 +02001576static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1577 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578{
1579 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
1580 int autoplace = 0, numpages, totalpages;
1581 struct nand_chip *this = mtd->priv;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001582 uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
David Woodhousee0c7d762006-05-13 18:07:53 +01001583 int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
Thomas Gleixner9223a452006-05-23 17:21:03 +02001584 struct nand_oobinfo *oobsel = &mtd->oobinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
Thomas Gleixner9223a452006-05-23 17:21:03 +02001586 DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
1588 /* Initialize retlen, in case of early exit */
1589 *retlen = 0;
1590
1591 /* Do not allow write past end of device */
1592 if ((to + len) > mtd->size) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001593 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 return -EINVAL;
1595 }
1596
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001597 /* reject writes, which are not page aligned */
David Woodhousee0c7d762006-05-13 18:07:53 +01001598 if (NOTALIGNED(to) || NOTALIGNED(len)) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001599 printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 return -EINVAL;
1601 }
1602
1603 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001604 nand_get_device(this, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
1606 /* Calculate chipnr */
1607 chipnr = (int)(to >> this->chip_shift);
1608 /* Select the NAND device */
1609 this->select_chip(mtd, chipnr);
1610
1611 /* Check, if it is write protected */
1612 if (nand_check_wp(mtd))
1613 goto out;
1614
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 /* Autoplace of oob data ? Use the default placement scheme */
1616 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
1617 oobsel = this->autooob;
1618 autoplace = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001619 }
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001620 if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
1621 autoplace = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
1623 /* Setup variables and oob buffer */
1624 totalpages = len >> this->page_shift;
David Woodhousee0c7d762006-05-13 18:07:53 +01001625 page = (int)(to >> this->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001627 if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 this->pagebuf = -1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001629
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 /* Set it relative to chip */
1631 page &= this->pagemask;
1632 startpage = page;
1633 /* Calc number of pages we can write in one go */
David Woodhousee0c7d762006-05-13 18:07:53 +01001634 numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages);
1635 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001636 bufstart = (uint8_t *) buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637
1638 /* Loop until all data is written */
1639 while (written < len) {
1640
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001641 this->data_poi = (uint8_t *) &buf[written];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 /* Write one page. If this is the last page to write
1643 * or the last page in this block, then use the
1644 * real pageprogram command, else select cached programming
1645 * if supported by the chip.
1646 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001647 ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001649 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001651 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 /* Next oob page */
1653 oob += mtd->oobsize;
1654 /* Update written bytes count */
Joern Engel28318772006-05-22 23:18:05 +02001655 written += mtd->writesize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001656 if (written == len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 goto cmp;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001658
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 /* Increment page address */
1660 page++;
1661
1662 /* Have we hit a block boundary ? Then we have to verify and
1663 * if verify is ok, we have to setup the oob buffer for
1664 * the next pages.
David Woodhousee0c7d762006-05-13 18:07:53 +01001665 */
1666 if (!(page & (ppblock - 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 int ofs;
1668 this->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001669 ret = nand_verify_pages(mtd, this, startpage, page - startpage,
1670 oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001672 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001674 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 *retlen = written;
1676
1677 ofs = autoplace ? mtd->oobavail : mtd->oobsize;
1678 if (eccbuf)
1679 eccbuf += (page - startpage) * ofs;
1680 totalpages -= page - startpage;
David Woodhousee0c7d762006-05-13 18:07:53 +01001681 numpages = min(totalpages, ppblock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 page &= this->pagemask;
1683 startpage = page;
David Woodhousee0c7d762006-05-13 18:07:53 +01001684 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Todd Poynor868801e2005-11-05 03:21:15 +00001685 oob = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 /* Check, if we cross a chip boundary */
1687 if (!page) {
1688 chipnr++;
1689 this->select_chip(mtd, -1);
1690 this->select_chip(mtd, chipnr);
1691 }
1692 }
1693 }
1694 /* Verify the remaining pages */
David Woodhousee0c7d762006-05-13 18:07:53 +01001695 cmp:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 this->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001697 ret = nand_verify_pages(mtd, this, startpage, totalpages, oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 if (!ret)
1699 *retlen = written;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001700 else
Thomas Gleixner9223a452006-05-23 17:21:03 +02001701 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
David Woodhousee0c7d762006-05-13 18:07:53 +01001703 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 /* Deselect and wake up anyone waiting on the device */
1705 nand_release_device(mtd);
1706
1707 return ret;
1708}
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710/**
1711 * nand_write_oob - [MTD Interface] NAND write out-of-band
1712 * @mtd: MTD device structure
1713 * @to: offset to write to
1714 * @len: number of bytes to write
1715 * @retlen: pointer to variable to store the number of written bytes
1716 * @buf: the data to write
1717 *
1718 * NAND write out-of-band
1719 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001720static 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 -07001721{
1722 int column, page, status, ret = -EIO, chipnr;
1723 struct nand_chip *this = mtd->priv;
1724
David Woodhousee0c7d762006-05-13 18:07:53 +01001725 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 -07001726
1727 /* Shift to get page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001728 page = (int)(to >> this->page_shift);
1729 chipnr = (int)(to >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
1731 /* Mask to get column */
1732 column = to & (mtd->oobsize - 1);
1733
1734 /* Initialize return length value */
1735 *retlen = 0;
1736
1737 /* Do not allow write past end of page */
1738 if ((column + len) > mtd->oobsize) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001739 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 return -EINVAL;
1741 }
1742
1743 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001744 nand_get_device(this, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
1746 /* Select the NAND device */
1747 this->select_chip(mtd, chipnr);
1748
1749 /* Reset the chip. Some chips (like the Toshiba TC5832DC found
1750 in one of my DiskOnChip 2000 test units) will clear the whole
1751 data page too if we don't do this. I have no clue why, but
1752 I seem to have 'fixed' it in the doc2000 driver in
1753 August 1999. dwmw2. */
1754 this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
1755
1756 /* Check, if it is write protected */
1757 if (nand_check_wp(mtd))
1758 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001759
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 /* Invalidate the page cache, if we write to the cached page */
1761 if (page == this->pagebuf)
1762 this->pagebuf = -1;
1763
1764 if (NAND_MUST_PAD(this)) {
1765 /* Write out desired data */
Joern Engel28318772006-05-22 23:18:05 +02001766 this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 /* prepad 0xff for partial programming */
1768 this->write_buf(mtd, ffchars, column);
1769 /* write data */
1770 this->write_buf(mtd, buf, len);
1771 /* postpad 0xff for partial programming */
David Woodhousee0c7d762006-05-13 18:07:53 +01001772 this->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 } else {
1774 /* Write out desired data */
Joern Engel28318772006-05-22 23:18:05 +02001775 this->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 /* write data */
1777 this->write_buf(mtd, buf, len);
1778 }
1779 /* Send command to program the OOB data */
David Woodhousee0c7d762006-05-13 18:07:53 +01001780 this->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
David Woodhousee0c7d762006-05-13 18:07:53 +01001782 status = this->waitfunc(mtd, this, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001785 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001786 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 ret = -EIO;
1788 goto out;
1789 }
1790 /* Return happy */
1791 *retlen = len;
1792
1793#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1794 /* Send command to read back the data */
David Woodhousee0c7d762006-05-13 18:07:53 +01001795 this->cmdfunc(mtd, NAND_CMD_READOOB, column, page & this->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796
1797 if (this->verify_buf(mtd, buf, len)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001798 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 ret = -EIO;
1800 goto out;
1801 }
1802#endif
1803 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001804 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 /* Deselect and wake up anyone waiting on the device */
1806 nand_release_device(mtd);
1807
1808 return ret;
1809}
1810
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1813 * @mtd: MTD device structure
1814 * @page: the page address of the block which will be erased
1815 *
1816 * Standard erase command for NAND chips
1817 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001818static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819{
1820 struct nand_chip *this = mtd->priv;
1821 /* Send commands to erase a block */
David Woodhousee0c7d762006-05-13 18:07:53 +01001822 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1823 this->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824}
1825
1826/**
1827 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1828 * @mtd: MTD device structure
1829 * @page: the page address of the block which will be erased
1830 *
1831 * AND multi block erase command function
1832 * Erase 4 consecutive blocks
1833 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001834static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835{
1836 struct nand_chip *this = mtd->priv;
1837 /* Send commands to erase a block */
David Woodhousee0c7d762006-05-13 18:07:53 +01001838 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1839 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1840 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1841 this->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1842 this->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843}
1844
1845/**
1846 * nand_erase - [MTD Interface] erase block(s)
1847 * @mtd: MTD device structure
1848 * @instr: erase instruction
1849 *
1850 * Erase one ore more blocks
1851 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001852static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853{
David Woodhousee0c7d762006-05-13 18:07:53 +01001854 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001856
David A. Marlin30f464b2005-01-17 18:35:25 +00001857#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858/**
1859 * nand_erase_intern - [NAND Interface] erase block(s)
1860 * @mtd: MTD device structure
1861 * @instr: erase instruction
1862 * @allowbbt: allow erasing the bbt area
1863 *
1864 * Erase one ore more blocks
1865 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001866int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867{
1868 int page, len, status, pages_per_block, ret, chipnr;
1869 struct nand_chip *this = mtd->priv;
David A. Marlin30f464b2005-01-17 18:35:25 +00001870 int rewrite_bbt[NAND_MAX_CHIPS]={0}; /* flags to indicate the page, if bbt needs to be rewritten. */
1871 unsigned int bbt_masked_page; /* bbt mask to compare to page being erased. */
1872 /* It is used to see if the current page is in the same */
1873 /* 256 block group and the same bank as the bbt. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
David Woodhousee0c7d762006-05-13 18:07:53 +01001875 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 -07001876
1877 /* Start address must align on block boundary */
1878 if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001879 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 return -EINVAL;
1881 }
1882
1883 /* Length must align on block boundary */
1884 if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001885 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 return -EINVAL;
1887 }
1888
1889 /* Do not allow erase past end of device */
1890 if ((instr->len + instr->addr) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001891 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 return -EINVAL;
1893 }
1894
1895 instr->fail_addr = 0xffffffff;
1896
1897 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01001898 nand_get_device(this, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900 /* Shift to get first page */
David Woodhousee0c7d762006-05-13 18:07:53 +01001901 page = (int)(instr->addr >> this->page_shift);
1902 chipnr = (int)(instr->addr >> this->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903
1904 /* Calculate pages in each block */
1905 pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
1906
1907 /* Select the NAND device */
1908 this->select_chip(mtd, chipnr);
1909
1910 /* Check the WP bit */
1911 /* Check, if it is write protected */
1912 if (nand_check_wp(mtd)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001913 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 instr->state = MTD_ERASE_FAILED;
1915 goto erase_exit;
1916 }
1917
David A. Marlin30f464b2005-01-17 18:35:25 +00001918 /* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */
1919 if (this->options & BBT_AUTO_REFRESH) {
1920 bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
1921 } else {
1922 bbt_masked_page = 0xffffffff; /* should not match anything */
1923 }
1924
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 /* Loop through the pages */
1926 len = instr->len;
1927
1928 instr->state = MTD_ERASING;
1929
1930 while (len) {
1931 /* Check if we have a bad block, we do not erase bad blocks ! */
1932 if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001933 printk(KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 instr->state = MTD_ERASE_FAILED;
1935 goto erase_exit;
1936 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001937
1938 /* Invalidate the page cache, if we erase the block which contains
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 the current cached page */
1940 if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
1941 this->pagebuf = -1;
1942
David Woodhousee0c7d762006-05-13 18:07:53 +01001943 this->erase_cmd(mtd, page & this->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001944
David Woodhousee0c7d762006-05-13 18:07:53 +01001945 status = this->waitfunc(mtd, this, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
David A. Marlin068e3c02005-01-24 03:07:46 +00001947 /* See if operation failed and additional status checks are available */
1948 if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
1949 status = this->errstat(mtd, this, FL_ERASING, status, page);
1950 }
1951
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001953 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001954 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 instr->state = MTD_ERASE_FAILED;
1956 instr->fail_addr = (page << this->page_shift);
1957 goto erase_exit;
1958 }
David A. Marlin30f464b2005-01-17 18:35:25 +00001959
1960 /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */
1961 if (this->options & BBT_AUTO_REFRESH) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001962 if (((page & BBT_PAGE_MASK) == bbt_masked_page) &&
David A. Marlin30f464b2005-01-17 18:35:25 +00001963 (page != this->bbt_td->pages[chipnr])) {
1964 rewrite_bbt[chipnr] = (page << this->page_shift);
1965 }
1966 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001967
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 /* Increment page address and decrement length */
1969 len -= (1 << this->phys_erase_shift);
1970 page += pages_per_block;
1971
1972 /* Check, if we cross a chip boundary */
1973 if (len && !(page & this->pagemask)) {
1974 chipnr++;
1975 this->select_chip(mtd, -1);
1976 this->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00001977
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001978 /* if BBT requires refresh and BBT-PERCHIP,
David A. Marlin30f464b2005-01-17 18:35:25 +00001979 * set the BBT page mask to see if this BBT should be rewritten */
1980 if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) {
1981 bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
1982 }
1983
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 }
1985 }
1986 instr->state = MTD_ERASE_DONE;
1987
David Woodhousee0c7d762006-05-13 18:07:53 +01001988 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
1990 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
1991 /* Do call back function */
1992 if (!ret)
1993 mtd_erase_callback(instr);
1994
1995 /* Deselect and wake up anyone waiting on the device */
1996 nand_release_device(mtd);
1997
David A. Marlin30f464b2005-01-17 18:35:25 +00001998 /* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */
1999 if ((this->options & BBT_AUTO_REFRESH) && (!ret)) {
2000 for (chipnr = 0; chipnr < this->numchips; chipnr++) {
2001 if (rewrite_bbt[chipnr]) {
2002 /* update the BBT for chip */
David Woodhousee0c7d762006-05-13 18:07:53 +01002003 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n",
2004 chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]);
2005 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00002006 }
2007 }
2008 }
2009
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 /* Return more or less happy */
2011 return ret;
2012}
2013
2014/**
2015 * nand_sync - [MTD Interface] sync
2016 * @mtd: MTD device structure
2017 *
2018 * Sync is actually a wait for chip ready function
2019 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002020static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021{
2022 struct nand_chip *this = mtd->priv;
2023
David Woodhousee0c7d762006-05-13 18:07:53 +01002024 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
2026 /* Grab the lock and see if the device is available */
David Woodhousee0c7d762006-05-13 18:07:53 +01002027 nand_get_device(this, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01002029 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030}
2031
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032/**
2033 * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
2034 * @mtd: MTD device structure
2035 * @ofs: offset relative to mtd start
2036 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002037static int nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038{
2039 /* Check for invalid offset */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002040 if (ofs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002042
David Woodhousee0c7d762006-05-13 18:07:53 +01002043 return nand_block_checkbad(mtd, ofs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044}
2045
2046/**
2047 * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
2048 * @mtd: MTD device structure
2049 * @ofs: offset relative to mtd start
2050 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002051static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052{
2053 struct nand_chip *this = mtd->priv;
2054 int ret;
2055
David Woodhousee0c7d762006-05-13 18:07:53 +01002056 if ((ret = nand_block_isbad(mtd, ofs))) {
2057 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 if (ret > 0)
2059 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01002060 return ret;
2061 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
2063 return this->block_markbad(mtd, ofs);
2064}
2065
2066/**
Vitaly Wool962034f2005-09-15 14:58:53 +01002067 * nand_suspend - [MTD Interface] Suspend the NAND flash
2068 * @mtd: MTD device structure
2069 */
2070static int nand_suspend(struct mtd_info *mtd)
2071{
2072 struct nand_chip *this = mtd->priv;
2073
David Woodhousee0c7d762006-05-13 18:07:53 +01002074 return nand_get_device(this, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01002075}
2076
2077/**
2078 * nand_resume - [MTD Interface] Resume the NAND flash
2079 * @mtd: MTD device structure
2080 */
2081static void nand_resume(struct mtd_info *mtd)
2082{
2083 struct nand_chip *this = mtd->priv;
2084
2085 if (this->state == FL_PM_SUSPENDED)
2086 nand_release_device(mtd);
2087 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02002088 printk(KERN_ERR "nand_resume() called for a chip which is not "
2089 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01002090}
2091
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002092/*
2093 * Free allocated data structures
2094 */
2095static void nand_free_kmem(struct nand_chip *this)
2096{
2097 /* Buffer allocated by nand_scan ? */
2098 if (this->options & NAND_OOBBUF_ALLOC)
2099 kfree(this->oob_buf);
2100 /* Buffer allocated by nand_scan ? */
2101 if (this->options & NAND_DATABUF_ALLOC)
2102 kfree(this->data_buf);
2103 /* Controller allocated by nand_scan ? */
2104 if (this->options & NAND_CONTROLLER_ALLOC)
2105 kfree(this->controller);
2106}
2107
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002108/*
2109 * Allocate buffers and data structures
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 */
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002111static int nand_allocate_kmem(struct mtd_info *mtd, struct nand_chip *this)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112{
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002113 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002115 if (!this->oob_buf) {
2116 len = mtd->oobsize <<
2117 (this->phys_erase_shift - this->page_shift);
2118 this->oob_buf = kmalloc(len, GFP_KERNEL);
2119 if (!this->oob_buf)
2120 goto outerr;
2121 this->options |= NAND_OOBBUF_ALLOC;
David Woodhouse552d9202006-05-14 01:20:46 +01002122 }
2123
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002124 if (!this->data_buf) {
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002125 len = mtd->writesize + mtd->oobsize;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002126 this->data_buf = kmalloc(len, GFP_KERNEL);
2127 if (!this->data_buf)
2128 goto outerr;
2129 this->options |= NAND_DATABUF_ALLOC;
2130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002132 if (!this->controller) {
2133 this->controller = kzalloc(sizeof(struct nand_hw_control),
2134 GFP_KERNEL);
2135 if (!this->controller)
2136 goto outerr;
2137 this->options |= NAND_CONTROLLER_ALLOC;
2138 }
2139 return 0;
2140
2141 outerr:
2142 printk(KERN_ERR "nand_scan(): Cannot allocate buffers\n");
2143 nand_free_kmem(this);
2144 return -ENOMEM;
2145}
2146
2147/*
2148 * Set default functions
2149 */
2150static void nand_set_defaults(struct nand_chip *this, int busw)
2151{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 /* check for proper chip_delay setup, set 20us if not */
2153 if (!this->chip_delay)
2154 this->chip_delay = 20;
2155
2156 /* check, if a user supplied command function given */
2157 if (this->cmdfunc == NULL)
2158 this->cmdfunc = nand_command;
2159
2160 /* check, if a user supplied wait function given */
2161 if (this->waitfunc == NULL)
2162 this->waitfunc = nand_wait;
2163
2164 if (!this->select_chip)
2165 this->select_chip = nand_select_chip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 if (!this->read_byte)
2167 this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 if (!this->read_word)
2169 this->read_word = nand_read_word;
2170 if (!this->block_bad)
2171 this->block_bad = nand_block_bad;
2172 if (!this->block_markbad)
2173 this->block_markbad = nand_default_block_markbad;
2174 if (!this->write_buf)
2175 this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
2176 if (!this->read_buf)
2177 this->read_buf = busw ? nand_read_buf16 : nand_read_buf;
2178 if (!this->verify_buf)
2179 this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
2180 if (!this->scan_bbt)
2181 this->scan_bbt = nand_default_bbt;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002182}
2183
2184/*
2185 * Get the flash and manufacturer id and lookup if the typ is supported
2186 */
2187static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2188 struct nand_chip *this,
2189 int busw, int *maf_id)
2190{
2191 struct nand_flash_dev *type = NULL;
2192 int i, dev_id, maf_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193
2194 /* Select the device */
2195 this->select_chip(mtd, 0);
2196
2197 /* Send the command for reading device ID */
David Woodhousee0c7d762006-05-13 18:07:53 +01002198 this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199
2200 /* Read manufacturer and device IDs */
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002201 *maf_id = this->read_byte(mtd);
2202 dev_id = this->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002204 /* Lookup the flash id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002206 if (dev_id == nand_flash_ids[i].id) {
2207 type = &nand_flash_ids[i];
2208 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 }
2211
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002212 if (!type)
2213 return ERR_PTR(-ENODEV);
2214
2215 this->chipsize = nand_flash_ids[i].chipsize << 20;
2216
2217 /* Newer devices have all the information in additional id bytes */
2218 if (!nand_flash_ids[i].pagesize) {
2219 int extid;
2220 /* The 3rd id byte contains non relevant data ATM */
2221 extid = this->read_byte(mtd);
2222 /* The 4th id byte is the important one */
2223 extid = this->read_byte(mtd);
2224 /* Calc pagesize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002225 mtd->writesize = 1024 << (extid & 0x3);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002226 extid >>= 2;
2227 /* Calc oobsize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002228 mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002229 extid >>= 2;
2230 /* Calc blocksize. Blocksize is multiples of 64KiB */
2231 mtd->erasesize = (64 * 1024) << (extid & 0x03);
2232 extid >>= 2;
2233 /* Get buswidth information */
2234 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
2235
2236 } else {
2237 /*
2238 * Old devices have this data hardcoded in the device id table
2239 */
2240 mtd->erasesize = nand_flash_ids[i].erasesize;
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002241 mtd->writesize = nand_flash_ids[i].pagesize;
2242 mtd->oobsize = mtd->writesize / 32;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002243 busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
2244 }
2245
2246 /* Try to identify manufacturer */
2247 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
2248 if (nand_manuf_ids[maf_idx].id == *maf_id)
2249 break;
2250 }
2251
2252 /*
2253 * Check, if buswidth is correct. Hardware drivers should set
2254 * this correct !
2255 */
2256 if (busw != (this->options & NAND_BUSWIDTH_16)) {
2257 printk(KERN_INFO "NAND device: Manufacturer ID:"
2258 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2259 dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2260 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
2261 (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
2262 busw ? 16 : 8);
2263 return ERR_PTR(-EINVAL);
2264 }
2265
2266 /* Calculate the address shift from the page size */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002267 this->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002268 /* Convert chipsize to number of pages per chip -1. */
2269 this->pagemask = (this->chipsize >> this->page_shift) - 1;
2270
2271 this->bbt_erase_shift = this->phys_erase_shift =
2272 ffs(mtd->erasesize) - 1;
2273 this->chip_shift = ffs(this->chipsize) - 1;
2274
2275 /* Set the bad block position */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002276 this->badblockpos = mtd->writesize > 512 ?
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002277 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
2278
2279 /* Get chip options, preserve non chip based options */
2280 this->options &= ~NAND_CHIPOPTIONS_MSK;
2281 this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
2282
2283 /*
2284 * Set this as a default. Board drivers can override it, if necessary
2285 */
2286 this->options |= NAND_NO_AUTOINCR;
2287
2288 /* Check if this is a not a samsung device. Do not clear the
2289 * options for chips which are not having an extended id.
2290 */
2291 if (*maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
2292 this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
2293
2294 /* Check for AND chips with 4 page planes */
2295 if (this->options & NAND_4PAGE_ARRAY)
2296 this->erase_cmd = multi_erase_cmd;
2297 else
2298 this->erase_cmd = single_erase_cmd;
2299
2300 /* Do not replace user supplied command function ! */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002301 if (mtd->writesize > 512 && this->cmdfunc == nand_command)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002302 this->cmdfunc = nand_command_lp;
2303
2304 printk(KERN_INFO "NAND device: Manufacturer ID:"
2305 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
2306 nand_manuf_ids[maf_idx].name, type->name);
2307
2308 return type;
2309}
2310
2311/* module_text_address() isn't exported, and it's mostly a pointless
2312 test if this is a module _anyway_ -- they'd have to try _really_ hard
2313 to call us from in-kernel code if the core NAND support is modular. */
2314#ifdef MODULE
2315#define caller_is_module() (1)
2316#else
2317#define caller_is_module() \
2318 module_text_address((unsigned long)__builtin_return_address(0))
2319#endif
2320
2321/**
2322 * nand_scan - [NAND Interface] Scan for the NAND device
2323 * @mtd: MTD device structure
2324 * @maxchips: Number of chips to scan for
2325 *
2326 * This fills out all the uninitialized function pointers
2327 * with the defaults.
2328 * The flash ID is read and the mtd/chip structures are
2329 * filled with the appropriate values. Buffers are allocated if
2330 * they are not provided by the board driver
2331 * The mtd->owner field must be set to the module of the caller
2332 *
2333 */
2334int nand_scan(struct mtd_info *mtd, int maxchips)
2335{
2336 int i, busw, nand_maf_id;
2337 struct nand_chip *this = mtd->priv;
2338 struct nand_flash_dev *type;
2339
2340 /* Many callers got this wrong, so check for it for a while... */
2341 if (!mtd->owner && caller_is_module()) {
2342 printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
2343 BUG();
2344 }
2345
2346 /* Get buswidth to select the correct functions */
2347 busw = this->options & NAND_BUSWIDTH_16;
2348 /* Set the default functions */
2349 nand_set_defaults(this, busw);
2350
2351 /* Read the flash type */
2352 type = nand_get_flash_type(mtd, this, busw, &nand_maf_id);
2353
2354 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002355 printk(KERN_WARNING "No NAND device found!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 this->select_chip(mtd, -1);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002357 return PTR_ERR(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 }
2359
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002360 /* Check for a chip array */
David Woodhousee0c7d762006-05-13 18:07:53 +01002361 for (i = 1; i < maxchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 this->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 /* Send the command for reading device ID */
David Woodhousee0c7d762006-05-13 18:07:53 +01002364 this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 /* Read manufacturer and device IDs */
2366 if (nand_maf_id != this->read_byte(mtd) ||
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002367 type->id != this->read_byte(mtd))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 break;
2369 }
2370 if (i > 1)
2371 printk(KERN_INFO "%d NAND chips detected\n", i);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002372
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 /* Store the number of chips and calc total size for mtd */
2374 this->numchips = i;
2375 mtd->size = i * this->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002377 /* Allocate buffers and data structures */
2378 if (nand_allocate_kmem(mtd, this))
2379 return -ENOMEM;
2380
2381 /* Preset the internal oob buffer */
2382 memset(this->oob_buf, 0xff,
2383 mtd->oobsize << (this->phys_erase_shift - this->page_shift));
2384
2385 /*
2386 * If no default placement scheme is given, select an appropriate one
2387 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 if (!this->autooob) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002389 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 case 8:
2391 this->autooob = &nand_oob_8;
2392 break;
2393 case 16:
2394 this->autooob = &nand_oob_16;
2395 break;
2396 case 64:
2397 this->autooob = &nand_oob_64;
2398 break;
2399 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002400 printk(KERN_WARNING "No oob scheme defined for "
2401 "oobsize %d\n", mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 BUG();
2403 }
2404 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002405
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002406 /*
2407 * The number of bytes available for the filesystem to place fs
2408 * dependend oob data
2409 */
Thomas Gleixner998cf642005-04-01 08:21:48 +01002410 mtd->oobavail = 0;
2411 for (i = 0; this->autooob->oobfree[i][1]; i++)
2412 mtd->oobavail += this->autooob->oobfree[i][1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002414 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002415 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2416 * selected and we have 256 byte pagesize fallback to software ECC
David Woodhousee0c7d762006-05-13 18:07:53 +01002417 */
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002418 switch (this->ecc.mode) {
2419 case NAND_ECC_HW:
2420 case NAND_ECC_HW_SYNDROME:
2421 if (!this->ecc.calculate || !this->ecc.correct ||
2422 !this->ecc.hwctl) {
2423 printk(KERN_WARNING "No ECC functions supplied, "
2424 "Hardware ECC not possible\n");
2425 BUG();
2426 }
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002427 if (mtd->writesize >= this->ecc.size)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002428 break;
2429 printk(KERN_WARNING "%d byte HW ECC not possible on "
2430 "%d byte page size, fallback to SW ECC\n",
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002431 this->ecc.size, mtd->writesize);
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002432 this->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002434 case NAND_ECC_SOFT:
2435 this->ecc.calculate = nand_calculate_ecc;
2436 this->ecc.correct = nand_correct_data;
2437 this->ecc.size = 256;
2438 this->ecc.bytes = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002440
2441 case NAND_ECC_NONE:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002442 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2443 "This is not recommended !!\n");
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002444 this->ecc.size = mtd->writesize;
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002445 this->ecc.bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002448 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002449 this->ecc.mode);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002450 BUG();
2451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002453 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002454 * Set the number of read / write steps for one page depending on ECC
2455 * mode
2456 */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002457 this->ecc.steps = mtd->writesize / this->ecc.size;
2458 if(this->ecc.steps * this->ecc.size != mtd->writesize) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002459 printk(KERN_WARNING "Invalid ecc parameters\n");
2460 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002462
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 /* Initialize state, waitqueue and spinlock */
2464 this->state = FL_READY;
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002465 init_waitqueue_head(&this->controller->wq);
2466 spin_lock_init(&this->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467
2468 /* De-select the device */
2469 this->select_chip(mtd, -1);
2470
2471 /* Invalidate the pagebuffer reference */
2472 this->pagebuf = -1;
2473
2474 /* Fill in remaining MTD driver data */
2475 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002476 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 mtd->ecctype = MTD_ECC_SW;
2478 mtd->erase = nand_erase;
2479 mtd->point = NULL;
2480 mtd->unpoint = NULL;
2481 mtd->read = nand_read;
2482 mtd->write = nand_write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 mtd->read_oob = nand_read_oob;
2484 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 mtd->sync = nand_sync;
2486 mtd->lock = NULL;
2487 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002488 mtd->suspend = nand_suspend;
2489 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 mtd->block_isbad = nand_block_isbad;
2491 mtd->block_markbad = nand_block_markbad;
2492
2493 /* and make the autooob the default one */
2494 memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
2495
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002496 /* Check, if we should skip the bad block table scan */
2497 if (this->options & NAND_SKIP_BBTSCAN)
2498 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
2500 /* Build bad block table */
David Woodhousee0c7d762006-05-13 18:07:53 +01002501 return this->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502}
2503
2504/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002505 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 * @mtd: MTD device structure
2507*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002508void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509{
2510 struct nand_chip *this = mtd->priv;
2511
2512#ifdef CONFIG_MTD_PARTITIONS
2513 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002514 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515#endif
2516 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002517 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518
Jesper Juhlfa671642005-11-07 01:01:27 -08002519 /* Free bad block table memory */
David Woodhousee0c7d762006-05-13 18:07:53 +01002520 kfree(this->bbt);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002521 /* Free buffers */
2522 nand_free_kmem(this);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523}
2524
David Woodhousee0c7d762006-05-13 18:07:53 +01002525EXPORT_SYMBOL_GPL(nand_scan);
2526EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002527
2528static int __init nand_base_init(void)
2529{
2530 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2531 return 0;
2532}
2533
2534static void __exit nand_base_exit(void)
2535{
2536 led_trigger_unregister_simple(nand_led_trigger);
2537}
2538
2539module_init(nand_base_init);
2540module_exit(nand_base_exit);
2541
David Woodhousee0c7d762006-05-13 18:07:53 +01002542MODULE_LICENSE("GPL");
2543MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2544MODULE_DESCRIPTION("Generic NAND flash driver code");