blob: 49bca242610bffc1df8e1862be46e1d83aeeaa37 [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 Gleixnerace4dfe2006-05-24 12:07:37 +020013 * 2002-2006 Thomas Gleixner (tglx@linutronix.de)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 *
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +020015 * Credits:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +000016 * David Woodhouse for adding multichip support
17 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 * Aleph One Ltd. and Toby Churchill Ltd. for supporting the
19 * rework for 2K page size chips
20 *
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +020021 * TODO:
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 * Enable cached programming for 2k page size chips
23 * Check, if mtd->ecctype should be set to MTD_ECC_HW
24 * if we have HW ecc support.
25 * The AG-AND chips have nice features for speed improvement,
26 * which are not supported yet. Read / program 4 pages in one go.
27 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070028 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License version 2 as
30 * published by the Free Software Foundation.
31 *
32 */
33
David Woodhouse552d9202006-05-14 01:20:46 +010034#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/delay.h>
36#include <linux/errno.h>
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +020037#include <linux/err.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/sched.h>
39#include <linux/slab.h>
40#include <linux/types.h>
41#include <linux/mtd/mtd.h>
42#include <linux/mtd/nand.h>
43#include <linux/mtd/nand_ecc.h>
44#include <linux/mtd/compatmac.h>
45#include <linux/interrupt.h>
46#include <linux/bitops.h>
Richard Purdie8fe833c2006-03-31 02:31:14 -080047#include <linux/leds.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <asm/io.h>
49
50#ifdef CONFIG_MTD_PARTITIONS
51#include <linux/mtd/partitions.h>
52#endif
53
54/* Define default oob placement schemes for large and small page devices */
55static struct nand_oobinfo nand_oob_8 = {
56 .useecc = MTD_NANDECC_AUTOPLACE,
57 .eccbytes = 3,
58 .eccpos = {0, 1, 2},
David Woodhousee0c7d762006-05-13 18:07:53 +010059 .oobfree = {{3, 2}, {6, 2}}
Linus Torvalds1da177e2005-04-16 15:20:36 -070060};
61
62static struct nand_oobinfo nand_oob_16 = {
63 .useecc = MTD_NANDECC_AUTOPLACE,
64 .eccbytes = 6,
65 .eccpos = {0, 1, 2, 3, 6, 7},
David Woodhousee0c7d762006-05-13 18:07:53 +010066 .oobfree = {{8, 8}}
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
69static struct nand_oobinfo nand_oob_64 = {
70 .useecc = MTD_NANDECC_AUTOPLACE,
71 .eccbytes = 24,
72 .eccpos = {
David Woodhousee0c7d762006-05-13 18:07:53 +010073 40, 41, 42, 43, 44, 45, 46, 47,
74 48, 49, 50, 51, 52, 53, 54, 55,
75 56, 57, 58, 59, 60, 61, 62, 63},
76 .oobfree = {{2, 38}}
Linus Torvalds1da177e2005-04-16 15:20:36 -070077};
78
79/* This is used for padding purposes in nand_write_oob */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +020080static uint8_t ffchars[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
82 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
83 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
84 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
85 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
86 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
87 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
88 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
89};
90
91/*
92 * NAND low-level MTD interface functions
93 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +020094static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
95static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len);
96static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020098static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +020099 size_t *retlen, uint8_t *buf);
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200100static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200101 size_t *retlen, uint8_t *buf);
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200102static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200103 size_t *retlen, const uint8_t *buf);
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200104static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200105 size_t *retlen, const uint8_t *buf);
David Woodhousee0c7d762006-05-13 18:07:53 +0100106static int nand_erase(struct mtd_info *mtd, struct erase_info *instr);
107static void nand_sync(struct mtd_info *mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109/* Some internal functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200110static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200111 int page, uint8_t * oob_buf,
David Woodhousee0c7d762006-05-13 18:07:53 +0100112 struct nand_oobinfo *oobsel, int mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200114static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *chip,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200115 int page, int numpages, uint8_t *oob_buf,
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200116 struct nand_oobinfo *oobsel, int chipnr,
117 int oobmode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118#else
119#define nand_verify_pages(...) (0)
120#endif
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000121
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200122static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200123 int new_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
Thomas Gleixnerd470a972006-05-23 23:48:57 +0200125/*
126 * For devices which display every fart in the system on a seperate LED. Is
127 * compiled away when LED support is disabled.
128 */
129DEFINE_LED_TRIGGER(nand_led_trigger);
130
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131/**
132 * nand_release_device - [GENERIC] release chip
133 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000134 *
135 * Deselect, release chip lock and wake up anyone waiting on the device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100137static void nand_release_device(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200139 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141 /* De-select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200142 chip->select_chip(mtd, -1);
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100143
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200144 /* Release the controller and the chip */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200145 spin_lock(&chip->controller->lock);
146 chip->controller->active = NULL;
147 chip->state = FL_READY;
148 wake_up(&chip->controller->wq);
149 spin_unlock(&chip->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150}
151
152/**
153 * nand_read_byte - [DEFAULT] read one byte from the chip
154 * @mtd: MTD device structure
155 *
156 * Default read function for 8bit buswith
157 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200158static uint8_t nand_read_byte(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200160 struct nand_chip *chip = mtd->priv;
161 return readb(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162}
163
164/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
166 * @mtd: MTD device structure
167 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000168 * Default read function for 16bit buswith with
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 * endianess conversion
170 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200171static uint8_t nand_read_byte16(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200173 struct nand_chip *chip = mtd->priv;
174 return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175}
176
177/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 * nand_read_word - [DEFAULT] read one word from the chip
179 * @mtd: MTD device structure
180 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000181 * Default read function for 16bit buswith without
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 * endianess conversion
183 */
184static u16 nand_read_word(struct mtd_info *mtd)
185{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200186 struct nand_chip *chip = mtd->priv;
187 return readw(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188}
189
190/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 * nand_select_chip - [DEFAULT] control CE line
192 * @mtd: MTD device structure
193 * @chip: chipnumber to select, -1 for deselect
194 *
195 * Default select function for 1 chip devices.
196 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200197static void nand_select_chip(struct mtd_info *mtd, int chipnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200199 struct nand_chip *chip = mtd->priv;
200
201 switch (chipnr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 case -1:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200203 chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 break;
205 case 0:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200206 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
207 NAND_NCE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 break;
209
210 default:
211 BUG();
212 }
213}
214
215/**
216 * nand_write_buf - [DEFAULT] write buffer to chip
217 * @mtd: MTD device structure
218 * @buf: data buffer
219 * @len: number of bytes to write
220 *
221 * Default write function for 8bit buswith
222 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200223static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224{
225 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200226 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
David Woodhousee0c7d762006-05-13 18:07:53 +0100228 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200229 writeb(buf[i], chip->IO_ADDR_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230}
231
232/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000233 * nand_read_buf - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 * @mtd: MTD device structure
235 * @buf: buffer to store date
236 * @len: number of bytes to read
237 *
238 * Default read function for 8bit buswith
239 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200240static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241{
242 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200243 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
David Woodhousee0c7d762006-05-13 18:07:53 +0100245 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200246 buf[i] = readb(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247}
248
249/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000250 * nand_verify_buf - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 * @mtd: MTD device structure
252 * @buf: buffer containing the data to compare
253 * @len: number of bytes to compare
254 *
255 * Default verify function for 8bit buswith
256 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200257static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258{
259 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200260 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
David Woodhousee0c7d762006-05-13 18:07:53 +0100262 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200263 if (buf[i] != readb(chip->IO_ADDR_R))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 return -EFAULT;
265
266 return 0;
267}
268
269/**
270 * nand_write_buf16 - [DEFAULT] write buffer to chip
271 * @mtd: MTD device structure
272 * @buf: data buffer
273 * @len: number of bytes to write
274 *
275 * Default write function for 16bit buswith
276 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200277static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{
279 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200280 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 u16 *p = (u16 *) buf;
282 len >>= 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000283
David Woodhousee0c7d762006-05-13 18:07:53 +0100284 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200285 writew(p[i], chip->IO_ADDR_W);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287}
288
289/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000290 * nand_read_buf16 - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 * @mtd: MTD device structure
292 * @buf: buffer to store date
293 * @len: number of bytes to read
294 *
295 * Default read function for 16bit buswith
296 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200297static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298{
299 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200300 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 u16 *p = (u16 *) buf;
302 len >>= 1;
303
David Woodhousee0c7d762006-05-13 18:07:53 +0100304 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200305 p[i] = readw(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306}
307
308/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000309 * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 * @mtd: MTD device structure
311 * @buf: buffer containing the data to compare
312 * @len: number of bytes to compare
313 *
314 * Default verify function for 16bit buswith
315 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200316static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317{
318 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200319 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 u16 *p = (u16 *) buf;
321 len >>= 1;
322
David Woodhousee0c7d762006-05-13 18:07:53 +0100323 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200324 if (p[i] != readw(chip->IO_ADDR_R))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 return -EFAULT;
326
327 return 0;
328}
329
330/**
331 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
332 * @mtd: MTD device structure
333 * @ofs: offset from device start
334 * @getchip: 0, if the chip is already selected
335 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000336 * Check, if the block is bad.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 */
338static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
339{
340 int page, chipnr, res = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200341 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 u16 bad;
343
344 if (getchip) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200345 page = (int)(ofs >> chip->page_shift);
346 chipnr = (int)(ofs >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200348 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200351 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000352 } else
David Woodhousee0c7d762006-05-13 18:07:53 +0100353 page = (int)ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200355 if (chip->options & NAND_BUSWIDTH_16) {
356 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
357 page & chip->pagemask);
358 bad = cpu_to_le16(chip->read_word(mtd));
359 if (chip->badblockpos & 0x1)
Vitaly Wool49196f32005-11-02 16:54:46 +0000360 bad >>= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 if ((bad & 0xFF) != 0xff)
362 res = 1;
363 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200364 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
365 page & chip->pagemask);
366 if (chip->read_byte(mtd) != 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 res = 1;
368 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000369
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200370 if (getchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 nand_release_device(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 return res;
374}
375
376/**
377 * nand_default_block_markbad - [DEFAULT] mark a block bad
378 * @mtd: MTD device structure
379 * @ofs: offset from device start
380 *
381 * This is the default implementation, which can be overridden by
382 * a hardware specific driver.
383*/
384static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
385{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200386 struct nand_chip *chip = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200387 uint8_t buf[2] = { 0, 0 };
David Woodhousee0c7d762006-05-13 18:07:53 +0100388 size_t retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 int block;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000390
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 /* Get block number */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200392 block = ((int)ofs) >> chip->bbt_erase_shift;
393 if (chip->bbt)
394 chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
396 /* Do we have a flash based bad block table ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200397 if (chip->options & NAND_USE_FLASH_BBT)
David Woodhousee0c7d762006-05-13 18:07:53 +0100398 return nand_update_bbt(mtd, ofs);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 /* We write two bytes, so we dont have to mess with 16 bit access */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200401 ofs += mtd->oobsize + (chip->badblockpos & ~0x01);
David Woodhousee0c7d762006-05-13 18:07:53 +0100402 return nand_write_oob(mtd, ofs, 2, &retlen, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403}
404
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000405/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 * nand_check_wp - [GENERIC] check if the chip is write protected
407 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000408 * Check, if the device is write protected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000410 * The function expects, that the device is already selected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100412static int nand_check_wp(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200414 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 /* Check the WP bit */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200416 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
417 return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418}
419
420/**
421 * nand_block_checkbad - [GENERIC] Check if a block is marked bad
422 * @mtd: MTD device structure
423 * @ofs: offset from device start
424 * @getchip: 0, if the chip is already selected
425 * @allowbbt: 1, if its allowed to access the bbt area
426 *
427 * Check, if the block is bad. Either by reading the bad block table or
428 * calling of the scan function.
429 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200430static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
431 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200433 struct nand_chip *chip = mtd->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000434
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200435 if (!chip->bbt)
436 return chip->block_bad(mtd, ofs, getchip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 /* Return info from the table */
David Woodhousee0c7d762006-05-13 18:07:53 +0100439 return nand_isbad_bbt(mtd, ofs, allowbbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440}
441
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000442/*
Thomas Gleixner3b887752005-02-22 21:56:49 +0000443 * Wait for the ready pin, after a command
444 * The timeout is catched later.
445 */
446static void nand_wait_ready(struct mtd_info *mtd)
447{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200448 struct nand_chip *chip = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100449 unsigned long timeo = jiffies + 2;
Thomas Gleixner3b887752005-02-22 21:56:49 +0000450
Richard Purdie8fe833c2006-03-31 02:31:14 -0800451 led_trigger_event(nand_led_trigger, LED_FULL);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000452 /* wait until command is processed or timeout occures */
453 do {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200454 if (chip->dev_ready(mtd))
Richard Purdie8fe833c2006-03-31 02:31:14 -0800455 break;
Ingo Molnar8446f1d2005-09-06 15:16:27 -0700456 touch_softlockup_watchdog();
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000457 } while (time_before(jiffies, timeo));
Richard Purdie8fe833c2006-03-31 02:31:14 -0800458 led_trigger_event(nand_led_trigger, LED_OFF);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000459}
460
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461/**
462 * nand_command - [DEFAULT] Send command to NAND device
463 * @mtd: MTD device structure
464 * @command: the command to be sent
465 * @column: the column address for this command, -1 if none
466 * @page_addr: the page address for this command, -1 if none
467 *
468 * Send command to NAND device. This function is used for small page
469 * devices (256/512 Bytes per page)
470 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200471static void nand_command(struct mtd_info *mtd, unsigned int command,
472 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200474 register struct nand_chip *chip = mtd->priv;
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200475 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 /*
478 * Write out the command to the device.
479 */
480 if (command == NAND_CMD_SEQIN) {
481 int readcmd;
482
Joern Engel28318772006-05-22 23:18:05 +0200483 if (column >= mtd->writesize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 /* OOB area */
Joern Engel28318772006-05-22 23:18:05 +0200485 column -= mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 readcmd = NAND_CMD_READOOB;
487 } else if (column < 256) {
488 /* First 256 bytes --> READ0 */
489 readcmd = NAND_CMD_READ0;
490 } else {
491 column -= 256;
492 readcmd = NAND_CMD_READ1;
493 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200494 chip->cmd_ctrl(mtd, readcmd, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200495 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200497 chip->cmd_ctrl(mtd, command, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200499 /*
500 * Address cycle, when necessary
501 */
502 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
503 /* Serially input address */
504 if (column != -1) {
505 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200506 if (chip->options & NAND_BUSWIDTH_16)
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200507 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200508 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200509 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200511 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200512 chip->cmd_ctrl(mtd, page_addr, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200513 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200514 chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200515 /* One more address cycle for devices > 32MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200516 if (chip->chipsize > (32 << 20))
517 chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200518 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200519 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000520
521 /*
522 * program and erase have their own busy handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 * status and sequential in needs no delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100524 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 case NAND_CMD_PAGEPROG:
528 case NAND_CMD_ERASE1:
529 case NAND_CMD_ERASE2:
530 case NAND_CMD_SEQIN:
531 case NAND_CMD_STATUS:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200532 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 return;
534
535 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200536 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200538 udelay(chip->chip_delay);
539 chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200540 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200541 chip->cmd_ctrl(mtd,
542 NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200543 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 return;
545
David Woodhousee0c7d762006-05-13 18:07:53 +0100546 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000548 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 * If we don't have access to the busy pin, we apply the given
550 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100551 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200552 if (!chip->dev_ready) {
553 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000555 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 /* Apply this short delay always to ensure that we do wait tWB in
558 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100559 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000560
561 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562}
563
564/**
565 * nand_command_lp - [DEFAULT] Send command to NAND large page device
566 * @mtd: MTD device structure
567 * @command: the command to be sent
568 * @column: the column address for this command, -1 if none
569 * @page_addr: the page address for this command, -1 if none
570 *
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200571 * Send command to NAND device. This is the version for the new large page
572 * devices We dont have the separate regions as we have in the small page
573 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 *
575 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200576static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
577 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200579 register struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
581 /* Emulate NAND_CMD_READOOB */
582 if (command == NAND_CMD_READOOB) {
Joern Engel28318772006-05-22 23:18:05 +0200583 column += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 command = NAND_CMD_READ0;
585 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000586
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200587 /* Command latch cycle */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200588 chip->cmd_ctrl(mtd, command & 0xff,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200589 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591 if (column != -1 || page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200592 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
594 /* Serially input address */
595 if (column != -1) {
596 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200597 if (chip->options & NAND_BUSWIDTH_16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200599 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200600 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200601 chip->cmd_ctrl(mtd, column >> 8, ctrl);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200604 chip->cmd_ctrl(mtd, page_addr, ctrl);
605 chip->cmd_ctrl(mtd, page_addr >> 8,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200606 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 /* One more address cycle for devices > 128MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200608 if (chip->chipsize > (128 << 20))
609 chip->cmd_ctrl(mtd, page_addr >> 16,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200610 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200613 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000614
615 /*
616 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000617 * status, sequential in, and deplete1 need no delay
618 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000620
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 case NAND_CMD_CACHEDPROG:
622 case NAND_CMD_PAGEPROG:
623 case NAND_CMD_ERASE1:
624 case NAND_CMD_ERASE2:
625 case NAND_CMD_SEQIN:
626 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000627 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 return;
629
David Woodhousee0c7d762006-05-13 18:07:53 +0100630 /*
631 * read error status commands require only a short delay
632 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000633 case NAND_CMD_STATUS_ERROR:
634 case NAND_CMD_STATUS_ERROR0:
635 case NAND_CMD_STATUS_ERROR1:
636 case NAND_CMD_STATUS_ERROR2:
637 case NAND_CMD_STATUS_ERROR3:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200638 udelay(chip->chip_delay);
David A. Marlin30f464b2005-01-17 18:35:25 +0000639 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200642 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200644 udelay(chip->chip_delay);
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200645 chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
646 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
647 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
648 NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200649 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 return;
651
652 case NAND_CMD_READ0:
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200653 chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
654 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
655 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
656 NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000657
David Woodhousee0c7d762006-05-13 18:07:53 +0100658 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000660 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 * If we don't have access to the busy pin, we apply the given
662 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100663 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200664 if (!chip->dev_ready) {
665 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000667 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000669
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 /* Apply this short delay always to ensure that we do wait tWB in
671 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100672 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000673
674 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675}
676
677/**
678 * nand_get_device - [GENERIC] Get chip for selected access
679 * @this: the nand chip descriptor
680 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000681 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 *
683 * Get the device and lock it for exclusive access
684 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200685static int
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200686nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200688 spinlock_t *lock = &chip->controller->lock;
689 wait_queue_head_t *wq = &chip->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100690 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100691 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100692 spin_lock(lock);
693
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200695 /* Hardware controller shared among independend devices */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200696 if (!chip->controller->active)
697 chip->controller->active = chip;
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200698
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200699 if (chip->controller->active == chip && chip->state == FL_READY) {
700 chip->state = new_state;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100701 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100702 return 0;
703 }
704 if (new_state == FL_PM_SUSPENDED) {
705 spin_unlock(lock);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200706 return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100707 }
708 set_current_state(TASK_UNINTERRUPTIBLE);
709 add_wait_queue(wq, &wait);
710 spin_unlock(lock);
711 schedule();
712 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 goto retry;
714}
715
716/**
717 * nand_wait - [DEFAULT] wait until the command is done
718 * @mtd: MTD device structure
719 * @this: NAND chip structure
720 * @state: state to select the max. timeout value
721 *
722 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000723 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 * general NAND and SmartMedia specs
725 *
726*/
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200727static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728{
729
David Woodhousee0c7d762006-05-13 18:07:53 +0100730 unsigned long timeo = jiffies;
731 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100734 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100736 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Richard Purdie8fe833c2006-03-31 02:31:14 -0800738 led_trigger_event(nand_led_trigger, LED_FULL);
739
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 /* Apply this short delay always to ensure that we do wait tWB in
741 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100742 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200744 if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
745 chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000746 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200747 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000749 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 /* Check, if we were interrupted */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200751 if (chip->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return 0;
753
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200754 if (chip->dev_ready) {
755 if (chip->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000756 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200758 if (chip->read_byte(mtd) & NAND_STATUS_READY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 break;
760 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000761 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800763 led_trigger_event(nand_led_trigger, LED_OFF);
764
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200765 status = (int)chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 return status;
767}
768
769/**
770 * nand_write_page - [GENERIC] write one page
771 * @mtd: MTD device structure
772 * @this: NAND chip structure
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200773 * @page: startpage inside the chip, must be called with (page & chip->pagemask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 * @oob_buf: out of band data buffer
775 * @oobsel: out of band selecttion structre
776 * @cached: 1 = enable cached programming if supported by chip
777 *
778 * Nand_page_program function is used for write and writev !
779 * This function will always program a full page of data
780 * If you call it with a non page aligned buffer, you're lost :)
781 *
782 * Cached programming is not supported yet.
783 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200784static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, int page,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200785 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int cached)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
David Woodhousee0c7d762006-05-13 18:07:53 +0100787 int i, status;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200788 uint8_t ecc_code[32];
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200789 int eccmode = oobsel->useecc ? chip->ecc.mode : NAND_ECC_NONE;
David Woodhousee0c7d762006-05-13 18:07:53 +0100790 int *oob_config = oobsel->eccpos;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200791 int datidx = 0, eccidx = 0, eccsteps = chip->ecc.steps;
David Woodhousee0c7d762006-05-13 18:07:53 +0100792 int eccbytes = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 /* FIXME: Enable cached programming */
795 cached = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 /* Send command to begin auto page programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200798 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
800 /* Write out complete page of data, take care of eccmode */
801 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100802 /* No ecc, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 case NAND_ECC_NONE:
David Woodhousee0c7d762006-05-13 18:07:53 +0100804 printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200805 chip->write_buf(mtd, chip->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000807
David Woodhousee0c7d762006-05-13 18:07:53 +0100808 /* Software ecc 3/256, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 case NAND_ECC_SOFT:
810 for (; eccsteps; eccsteps--) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200811 chip->ecc.calculate(mtd, &chip->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 for (i = 0; i < 3; i++, eccidx++)
813 oob_buf[oob_config[eccidx]] = ecc_code[i];
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200814 datidx += chip->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200816 chip->write_buf(mtd, chip->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 break;
818 default:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200819 eccbytes = chip->ecc.bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 for (; eccsteps; eccsteps--) {
821 /* enable hardware ecc logic for write */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200822 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
823 chip->write_buf(mtd, &chip->data_poi[datidx], chip->ecc.size);
824 chip->ecc.calculate(mtd, &chip->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 for (i = 0; i < eccbytes; i++, eccidx++)
826 oob_buf[oob_config[eccidx]] = ecc_code[i];
827 /* If the hardware ecc provides syndromes then
828 * the ecc code must be written immidiately after
829 * the data bytes (words) */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200830 if (chip->options & NAND_HWECC_SYNDROME)
831 chip->write_buf(mtd, ecc_code, eccbytes);
832 datidx += chip->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 }
834 break;
835 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 /* Write out OOB data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200838 if (chip->options & NAND_HWECC_SYNDROME)
839 chip->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000840 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200841 chip->write_buf(mtd, oob_buf, mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
843 /* Send command to actually program the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200844 chip->cmdfunc(mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845
846 if (!cached) {
847 /* call wait ready function */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200848 status = chip->waitfunc(mtd, chip, FL_WRITING);
David A. Marlin068e3c02005-01-24 03:07:46 +0000849
850 /* See if operation failed and additional status checks are available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200851 if ((status & NAND_STATUS_FAIL) && (chip->errstat)) {
852 status = chip->errstat(mtd, chip, FL_WRITING, status, page);
David A. Marlin068e3c02005-01-24 03:07:46 +0000853 }
854
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +0000856 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100857 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 return -EIO;
859 }
860 } else {
861 /* FIXME: Implement cached programming ! */
David Woodhousee0c7d762006-05-13 18:07:53 +0100862 /* wait until cache is ready */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200863 // status = chip->waitfunc (mtd, this, FL_CACHEDRPG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000865 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866}
867
868#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
869/**
870 * nand_verify_pages - [GENERIC] verify the chip contents after a write
871 * @mtd: MTD device structure
872 * @this: NAND chip structure
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200873 * @page: startpage inside the chip, must be called with (page & chip->pagemask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 * @numpages: number of pages to verify
875 * @oob_buf: out of band data buffer
876 * @oobsel: out of band selecttion structre
877 * @chipnr: number of the current chip
878 * @oobmode: 1 = full buffer verify, 0 = ecc only
879 *
880 * The NAND device assumes that it is always writing to a cleanly erased page.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000881 * Hence, it performs its internal write verification only on bits that
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 * transitioned from 1 to 0. The device does NOT verify the whole page on a
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000883 * byte by byte basis. It is possible that the page was not completely erased
884 * or the page is becoming unusable due to wear. The read with ECC would catch
885 * the error later when the ECC page check fails, but we would rather catch
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 * it early in the page write stage. Better to write no data than invalid data.
887 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200888static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *chip, int page, int numpages,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200889 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890{
David Woodhousee0c7d762006-05-13 18:07:53 +0100891 int i, j, datidx = 0, oobofs = 0, res = -EIO;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200892 int eccsteps = chip->eccsteps;
David Woodhousee0c7d762006-05-13 18:07:53 +0100893 int hweccbytes;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200894 uint8_t oobdata[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200896 hweccbytes = (chip->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
898 /* Send command to read back the first page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200899 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
David Woodhousee0c7d762006-05-13 18:07:53 +0100901 for (;;) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 for (j = 0; j < eccsteps; j++) {
903 /* Loop through and verify the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200904 if (chip->verify_buf(mtd, &chip->data_poi[datidx], mtd->eccsize)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100905 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 goto out;
907 }
908 datidx += mtd->eccsize;
909 /* Have we a hw generator layout ? */
910 if (!hweccbytes)
911 continue;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200912 if (chip->verify_buf(mtd, &chip->oob_buf[oobofs], hweccbytes)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100913 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 goto out;
915 }
916 oobofs += hweccbytes;
917 }
918
919 /* check, if we must compare all data or if we just have to
920 * compare the ecc bytes
921 */
922 if (oobmode) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200923 if (chip->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100924 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 goto out;
926 }
927 } else {
928 /* Read always, else autoincrement fails */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200929 chip->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930
931 if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
932 int ecccnt = oobsel->eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000933
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 for (i = 0; i < ecccnt; i++) {
935 int idx = oobsel->eccpos[i];
David Woodhousee0c7d762006-05-13 18:07:53 +0100936 if (oobdata[idx] != oob_buf[oobofs + idx]) {
937 DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed ECC write verify, page 0x%08x, %6i bytes were succesful\n",
938 __FUNCTION__, page, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 goto out;
940 }
941 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000942 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 }
944 oobofs += mtd->oobsize - hweccbytes * eccsteps;
945 page++;
946 numpages--;
947
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000948 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 * Do this before the AUTOINCR check, so no problems
950 * arise if a chip which does auto increment
951 * is marked as NOAUTOINCR by the board driver.
952 * Do this also before returning, so the chip is
953 * ready for the next command.
David Woodhousee0c7d762006-05-13 18:07:53 +0100954 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200955 if (!chip->dev_ready)
956 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 else
Thomas Gleixner3b887752005-02-22 21:56:49 +0000958 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
960 /* All done, return happy */
961 if (!numpages)
962 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000963
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000964 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 if (!NAND_CANAUTOINCR(this))
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200966 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000968 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 * Terminate the read command. We come here in case of an error
970 * So we must issue a reset command.
971 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100972 out:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200973 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 return res;
975}
976#endif
977
978/**
David A. Marlin068e3c02005-01-24 03:07:46 +0000979 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 * @mtd: MTD device structure
981 * @from: offset to read from
982 * @len: number of bytes to read
983 * @retlen: pointer to variable to store the number of read bytes
984 * @buf: the databuffer to put data
985 *
David A. Marlin068e3c02005-01-24 03:07:46 +0000986 * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL
987 * and flags = 0xff
988 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200989static 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 -0700990{
David Woodhousee0c7d762006-05-13 18:07:53 +0100991 return nand_do_read_ecc(mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);
Thomas Gleixner22c60f52005-04-04 19:56:32 +0100992}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994/**
David A. Marlin068e3c02005-01-24 03:07:46 +0000995 * nand_do_read_ecc - [MTD Interface] Read data with ECC
996 * @mtd: MTD device structure
997 * @from: offset to read from
998 * @len: number of bytes to read
999 * @retlen: pointer to variable to store the number of read bytes
1000 * @buf: the databuffer to put data
Dan Brownbb75ba42005-04-04 19:02:26 +01001001 * @oob_buf: filesystem supplied oob data buffer (can be NULL)
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001002 * @oobsel: oob selection structure
David A. Marlin068e3c02005-01-24 03:07:46 +00001003 * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed
1004 * and how many corrected error bits are acceptable:
1005 * bits 0..7 - number of tolerable errors
1006 * bit 8 - 0 == do not get/release chip, 1 == get/release chip
1007 *
1008 * NAND read with ECC
1009 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001010int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001011 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel, int flags)
David A. Marlin068e3c02005-01-24 03:07:46 +00001012{
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001013
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
1015 int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001016 struct nand_chip *chip = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001017 uint8_t *data_poi, *oob_data = oob_buf;
1018 uint8_t ecc_calc[32];
1019 uint8_t ecc_code[32];
David Woodhousee0c7d762006-05-13 18:07:53 +01001020 int eccmode, eccsteps;
1021 int *oob_config, datidx;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001022 int blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
David Woodhousee0c7d762006-05-13 18:07:53 +01001023 int eccbytes;
1024 int compareecc = 1;
1025 int oobreadlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
David Woodhousee0c7d762006-05-13 18:07:53 +01001027 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 -07001028
1029 /* Do not allow reads past end of device */
1030 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001031 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 *retlen = 0;
1033 return -EINVAL;
1034 }
1035
1036 /* Grab the lock and see if the device is available */
David A. Marlin068e3c02005-01-24 03:07:46 +00001037 if (flags & NAND_GET_DEVICE)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001038 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 /* Autoplace of oob data ? Use the default placement scheme */
1041 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001042 oobsel = chip->autooob;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001043
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001044 eccmode = oobsel->useecc ? chip->ecc.mode : NAND_ECC_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 oob_config = oobsel->eccpos;
1046
1047 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001048 chipnr = (int)(from >> chip->chip_shift);
1049 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051 /* First we calculate the starting page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001052 realpage = (int)(from >> chip->page_shift);
1053 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
1055 /* Get raw starting column */
Joern Engel28318772006-05-22 23:18:05 +02001056 col = from & (mtd->writesize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Joern Engel28318772006-05-22 23:18:05 +02001058 end = mtd->writesize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001059 ecc = chip->ecc.size;
1060 eccbytes = chip->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001061
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001062 if ((eccmode == NAND_ECC_NONE) || (chip->options & NAND_HWECC_SYNDROME))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 compareecc = 0;
1064
1065 oobreadlen = mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001066 if (chip->options & NAND_HWECC_SYNDROME)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 oobreadlen -= oobsel->eccbytes;
1068
1069 /* Loop until all data read */
1070 while (read < len) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 int aligned = (!col && (len - read) >= end);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001073 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 * If the read is not page aligned, we have to read into data buffer
1075 * due to ecc, else we read into return buffer direct
1076 */
1077 if (aligned)
1078 data_poi = &buf[read];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001079 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001080 data_poi = chip->data_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001081
1082 /* Check, if we have this page in the buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 *
1084 * FIXME: Make it work when we must provide oob data too,
1085 * check the usage of data_buf oob field
1086 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001087 if (realpage == chip->pagebuf && !oob_buf) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 /* aligned read ? */
1089 if (aligned)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001090 memcpy(data_poi, chip->data_buf, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 goto readdata;
1092 }
1093
1094 /* Check, if we must send the read command */
1095 if (sndcmd) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001096 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 sndcmd = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001098 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 /* get oob area, if we have no oob buffer from fs-driver */
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001101 if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
1102 oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001103 oob_data = &chip->data_buf[end];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001105 eccsteps = chip->ecc.steps;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001108 case NAND_ECC_NONE:{
1109 /* No ECC, Read in a page */
1110 static unsigned long lastwhinge = 0;
1111 if ((lastwhinge / HZ) != (jiffies / HZ)) {
1112 printk(KERN_WARNING
1113 "Reading data from NAND FLASH without ECC is not recommended\n");
1114 lastwhinge = jiffies;
1115 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001116 chip->read_buf(mtd, data_poi, end);
David Woodhousee0c7d762006-05-13 18:07:53 +01001117 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001119
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001121 chip->read_buf(mtd, data_poi, end);
David Woodhousee0c7d762006-05-13 18:07:53 +01001122 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001123 chip->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001124 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 default:
David Woodhousee0c7d762006-05-13 18:07:53 +01001127 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001128 chip->ecc.hwctl(mtd, NAND_ECC_READ);
1129 chip->read_buf(mtd, &data_poi[datidx], ecc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
1131 /* HW ecc with syndrome calculation must read the
1132 * syndrome from flash immidiately after the data */
1133 if (!compareecc) {
1134 /* Some hw ecc generators need to know when the
1135 * syndrome is read from flash */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001136 chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
1137 chip->read_buf(mtd, &oob_data[i], eccbytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 /* We calc error correction directly, it checks the hw
1139 * generator for an error, reads back the syndrome and
1140 * does the error correction on the fly */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001141 ecc_status = chip->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
David A. Marlin068e3c02005-01-24 03:07:46 +00001142 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001143 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
1144 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 ecc_failed++;
1146 }
1147 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001148 chip->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001151 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 }
1153
1154 /* read oobdata */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001155 chip->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
1157 /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
1158 if (!compareecc)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001159 goto readoob;
1160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 /* Pick the ECC bytes out of the oob data */
1162 for (j = 0; j < oobsel->eccbytes; j++)
1163 ecc_code[j] = oob_data[oob_config[j]];
1164
David Woodhousee0c7d762006-05-13 18:07:53 +01001165 /* correct data, if necessary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001166 for (i = 0, j = 0, datidx = 0; i < chip->ecc.steps; i++, datidx += ecc) {
1167 ecc_status = chip->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 /* Get next chunk of ecc bytes */
1170 j += eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001171
1172 /* Check, if we have a fs supplied oob-buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 * This is the legacy mode. Used by YAFFS1
1174 * Should go away some day
1175 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001176 if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 int *p = (int *)(&oob_data[mtd->oobsize]);
1178 p[i] = ecc_status;
1179 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001180
1181 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001182 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 ecc_failed++;
1184 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
David Woodhousee0c7d762006-05-13 18:07:53 +01001187 readoob:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 /* check, if we have a fs supplied oob-buffer */
1189 if (oob_buf) {
1190 /* without autoplace. Legacy mode used by YAFFS1 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001191 switch (oobsel->useecc) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 case MTD_NANDECC_AUTOPLACE:
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001193 case MTD_NANDECC_AUTOPL_USR:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 /* Walk through the autoplace chunks */
Dan Brown82e1d192005-04-06 21:13:09 +01001195 for (i = 0; oobsel->oobfree[i][1]; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 int from = oobsel->oobfree[i][0];
1197 int num = oobsel->oobfree[i][1];
1198 memcpy(&oob_buf[oob], &oob_data[from], num);
Dan Brown82e1d192005-04-06 21:13:09 +01001199 oob += num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 break;
1202 case MTD_NANDECC_PLACE:
1203 /* YAFFS1 legacy mode */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001204 oob_data += chip->ecc.steps * sizeof(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 default:
1206 oob_data += mtd->oobsize;
1207 }
1208 }
1209 readdata:
1210 /* Partial page read, transfer data into fs buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001211 if (!aligned) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 for (j = col; j < end && read < len; j++)
1213 buf[read++] = data_poi[j];
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001214 chip->pagebuf = realpage;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001215 } else
Joern Engel28318772006-05-22 23:18:05 +02001216 read += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001218 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 * Do this before the AUTOINCR check, so no problems
1220 * arise if a chip which does auto increment
1221 * is marked as NOAUTOINCR by the board driver.
David Woodhousee0c7d762006-05-13 18:07:53 +01001222 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001223 if (!chip->dev_ready)
1224 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001226 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001227
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 if (read == len)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001229 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 /* For subsequent reads align to page boundary. */
1232 col = 0;
1233 /* Increment page address */
1234 realpage++;
1235
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001236 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 /* Check, if we cross a chip boundary */
1238 if (!page) {
1239 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001240 chip->select_chip(mtd, -1);
1241 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001243 /* Check, if the chip supports auto page increment
1244 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001245 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001246 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001247 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 }
1249
1250 /* Deselect and wake up anyone waiting on the device */
David A. Marlin068e3c02005-01-24 03:07:46 +00001251 if (flags & NAND_GET_DEVICE)
1252 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
1254 /*
1255 * Return success, if no ECC failures, else -EBADMSG
1256 * fs driver will take care of that, because
1257 * retlen == desired len and result == -EBADMSG
1258 */
1259 *retlen = read;
1260 return ecc_failed ? -EBADMSG : 0;
1261}
1262
1263/**
1264 * nand_read_oob - [MTD Interface] NAND read out-of-band
1265 * @mtd: MTD device structure
1266 * @from: offset to read from
1267 * @len: number of bytes to read
1268 * @retlen: pointer to variable to store the number of read bytes
1269 * @buf: the databuffer to put data
1270 *
1271 * NAND read out-of-band data from the spare area
1272 */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001273static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
1274 size_t *retlen, uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275{
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001276 int col, page, realpage, chipnr, sndcmd = 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001277 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001278 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1279 int readlen = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001281 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n",
1282 (unsigned int)from, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
1284 /* Initialize return length value */
1285 *retlen = 0;
1286
1287 /* Do not allow reads past end of device */
1288 if ((from + len) > mtd->size) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001289 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1290 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 return -EINVAL;
1292 }
1293
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001294 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001296 chipnr = (int)(from >> chip->chip_shift);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001297 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001299 /* Shift to get page */
1300 realpage = (int)(from >> chip->page_shift);
1301 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001303 /* Mask to get column */
1304 col = from & (mtd->oobsize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001306 while(1) {
1307 int bytes = min((int)(mtd->oobsize - col), readlen);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001308
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001309 if (likely(sndcmd)) {
1310 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page);
1311 sndcmd = 0;
1312 }
1313
1314 chip->read_buf(mtd, buf, bytes);
1315
1316 readlen -= bytes;
1317 if (!readlen)
1318 break;
1319
1320 if (!(chip->options & NAND_NO_READRDY)) {
1321 /*
1322 * Apply delay or wait for ready/busy pin. Do this
1323 * before the AUTOINCR check, so no problems arise if a
1324 * chip which does auto increment is marked as
1325 * NOAUTOINCR by the board driver.
Thomas Gleixner19870da2005-07-15 14:53:51 +01001326 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001327 if (!chip->dev_ready)
1328 udelay(chip->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001329 else
1330 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 }
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001332
1333 buf += bytes;
1334 bytes = mtd->oobsize;
1335 col = 0;
1336
1337 /* Increment page address */
1338 realpage++;
1339
1340 page = realpage & chip->pagemask;
1341 /* Check, if we cross a chip boundary */
1342 if (!page) {
1343 chipnr++;
1344 chip->select_chip(mtd, -1);
1345 chip->select_chip(mtd, chipnr);
1346 }
1347
1348 /* Check, if the chip supports auto page increment
1349 * or if we have hit a block boundary.
1350 */
1351 if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
1352 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 }
1354
1355 /* Deselect and wake up anyone waiting on the device */
1356 nand_release_device(mtd);
1357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 *retlen = len;
1359 return 0;
1360}
1361
1362/**
1363 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1364 * @mtd: MTD device structure
1365 * @buf: temporary buffer
1366 * @from: offset to read from
1367 * @len: number of bytes to read
1368 * @ooblen: number of oob data bytes to read
1369 *
1370 * Read raw data including oob into buffer
1371 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001372int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len,
1373 size_t ooblen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001375 struct nand_chip *chip = mtd->priv;
1376 int page = (int)(from >> chip->page_shift);
1377 int chipnr = (int)(from >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 int sndcmd = 1;
1379 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001380 int pagesize = mtd->writesize + mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001381 int blockcheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
1383 /* Do not allow reads past end of device */
1384 if ((from + len) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001385 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: "
1386 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 return -EINVAL;
1388 }
1389
1390 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001391 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001393 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001394
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 /* Add requested oob length */
1396 len += ooblen;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001397 blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001398
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 while (len) {
1400 if (sndcmd)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001401 chip->cmdfunc(mtd, NAND_CMD_READ0, 0,
1402 page & chip->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001403 sndcmd = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001405 chip->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
1407 len -= pagesize;
1408 cnt += pagesize;
1409 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001410
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001411 if (!chip->dev_ready)
1412 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001414 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001415
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001416 /*
1417 * Check, if the chip supports auto page increment or if we
1418 * cross a block boundary.
1419 */
1420 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 sndcmd = 1;
1422 }
1423
1424 /* Deselect and wake up anyone waiting on the device */
1425 nand_release_device(mtd);
1426 return 0;
1427}
1428
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001429/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001430 * nand_write_raw - [GENERIC] Write raw data including oob
1431 * @mtd: MTD device structure
1432 * @buf: source buffer
1433 * @to: offset to write to
1434 * @len: number of bytes to write
1435 * @buf: source buffer
1436 * @oob: oob buffer
1437 *
1438 * Write raw data including oob
1439 */
1440int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1441 uint8_t *buf, uint8_t *oob)
1442{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001443 struct nand_chip *chip = mtd->priv;
1444 int page = (int)(to >> chip->page_shift);
1445 int chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001446 int ret;
1447
1448 *retlen = 0;
1449
1450 /* Do not allow writes past end of device */
1451 if ((to + len) > mtd->size) {
1452 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1453 "beyond end of device\n");
1454 return -EINVAL;
1455 }
1456
1457 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001458 nand_get_device(chip, mtd, FL_WRITING);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001459
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001460 chip->select_chip(mtd, chipnr);
1461 chip->data_poi = buf;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001462
1463 while (len != *retlen) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001464 ret = nand_write_page(mtd, chip, page, oob, &mtd->oobinfo, 0);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001465 if (ret)
1466 return ret;
1467 page++;
1468 *retlen += mtd->writesize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001469 chip->data_poi += mtd->writesize;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001470 oob += mtd->oobsize;
1471 }
1472
1473 /* Deselect and wake up anyone waiting on the device */
1474 nand_release_device(mtd);
1475 return 0;
1476}
Thomas Gleixner38217202006-05-23 22:33:52 +02001477EXPORT_SYMBOL_GPL(nand_write_raw);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001478
1479/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001480 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 * @mtd: MTD device structure
1482 * @fsbuf: buffer given by fs driver
1483 * @oobsel: out of band selection structre
1484 * @autoplace: 1 = place given buffer into the oob bytes
1485 * @numpages: number of pages to prepare
1486 *
1487 * Return:
1488 * 1. Filesystem buffer available and autoplacement is off,
1489 * return filesystem buffer
1490 * 2. No filesystem buffer or autoplace is off, return internal
1491 * buffer
1492 * 3. Filesystem buffer is given and autoplace selected
1493 * put data from fs buffer into internal buffer and
1494 * retrun internal buffer
1495 *
1496 * Note: The internal buffer is filled with 0xff. This must
1497 * be done only once, when no autoplacement happens
1498 * Autoplacement sets the buffer dirty flag, which
1499 * forces the 0xff fill before using the buffer again.
1500 *
1501*/
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001502static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct nand_oobinfo *oobsel,
David Woodhousee0c7d762006-05-13 18:07:53 +01001503 int autoplace, int numpages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001505 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 int i, len, ofs;
1507
1508 /* Zero copy fs supplied buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001509 if (fsbuf && !autoplace)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 return fsbuf;
1511
1512 /* Check, if the buffer must be filled with ff again */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001513 if (chip->oobdirty) {
1514 memset(chip->oob_buf, 0xff, mtd->oobsize << (chip->phys_erase_shift - chip->page_shift));
1515 chip->oobdirty = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001516 }
1517
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 /* If we have no autoplacement or no fs buffer use the internal one */
1519 if (!autoplace || !fsbuf)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001520 return chip->oob_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001521
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 /* Walk through the pages and place the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001523 chip->oobdirty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 ofs = 0;
1525 while (numpages--) {
1526 for (i = 0, len = 0; len < mtd->oobavail; i++) {
1527 int to = ofs + oobsel->oobfree[i][0];
1528 int num = oobsel->oobfree[i][1];
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001529 memcpy(&chip->oob_buf[to], fsbuf, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 len += num;
1531 fsbuf += num;
1532 }
1533 ofs += mtd->oobavail;
1534 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001535 return chip->oob_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536}
1537
Joern Engel28318772006-05-22 23:18:05 +02001538#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539
1540/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001541 * nand_write - [MTD Interface] NAND write with ECC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 * @mtd: MTD device structure
1543 * @to: offset to write to
1544 * @len: number of bytes to write
1545 * @retlen: pointer to variable to store the number of written bytes
1546 * @buf: the data to write
1547 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 * NAND write with ECC
1549 */
Thomas Gleixner9223a452006-05-23 17:21:03 +02001550static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1551 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552{
1553 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
1554 int autoplace = 0, numpages, totalpages;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001555 struct nand_chip *chip = mtd->priv;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001556 uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001557 int ppblock = (1 << (chip->phys_erase_shift - chip->page_shift));
Thomas Gleixner9223a452006-05-23 17:21:03 +02001558 struct nand_oobinfo *oobsel = &mtd->oobinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
Thomas Gleixner9223a452006-05-23 17:21:03 +02001560 DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
1562 /* Initialize retlen, in case of early exit */
1563 *retlen = 0;
1564
1565 /* Do not allow write past end of device */
1566 if ((to + len) > mtd->size) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001567 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 return -EINVAL;
1569 }
1570
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001571 /* reject writes, which are not page aligned */
David Woodhousee0c7d762006-05-13 18:07:53 +01001572 if (NOTALIGNED(to) || NOTALIGNED(len)) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001573 printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 return -EINVAL;
1575 }
1576
1577 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001578 nand_get_device(chip, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579
1580 /* Calculate chipnr */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001581 chipnr = (int)(to >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001583 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
1585 /* Check, if it is write protected */
1586 if (nand_check_wp(mtd))
1587 goto out;
1588
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 /* Autoplace of oob data ? Use the default placement scheme */
1590 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001591 oobsel = chip->autooob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 autoplace = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001593 }
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001594 if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
1595 autoplace = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
1597 /* Setup variables and oob buffer */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001598 totalpages = len >> chip->page_shift;
1599 page = (int)(to >> chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001601 if (page <= chip->pagebuf && chip->pagebuf < (page + totalpages))
1602 chip->pagebuf = -1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001603
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 /* Set it relative to chip */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001605 page &= chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 startpage = page;
1607 /* Calc number of pages we can write in one go */
David Woodhousee0c7d762006-05-13 18:07:53 +01001608 numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages);
1609 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001610 bufstart = (uint8_t *) buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
1612 /* Loop until all data is written */
1613 while (written < len) {
1614
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001615 chip->data_poi = (uint8_t *) &buf[written];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 /* Write one page. If this is the last page to write
1617 * or the last page in this block, then use the
1618 * real pageprogram command, else select cached programming
1619 * if supported by the chip.
1620 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001621 ret = nand_write_page(mtd, chip, page, &oobbuf[oob], oobsel, (--numpages > 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001623 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 /* Next oob page */
1627 oob += mtd->oobsize;
1628 /* Update written bytes count */
Joern Engel28318772006-05-22 23:18:05 +02001629 written += mtd->writesize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001630 if (written == len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 goto cmp;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001632
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 /* Increment page address */
1634 page++;
1635
1636 /* Have we hit a block boundary ? Then we have to verify and
1637 * if verify is ok, we have to setup the oob buffer for
1638 * the next pages.
David Woodhousee0c7d762006-05-13 18:07:53 +01001639 */
1640 if (!(page & (ppblock - 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 int ofs;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001642 chip->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001643 ret = nand_verify_pages(mtd, this, startpage, page - startpage,
1644 oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001646 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001648 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 *retlen = written;
1650
1651 ofs = autoplace ? mtd->oobavail : mtd->oobsize;
1652 if (eccbuf)
1653 eccbuf += (page - startpage) * ofs;
1654 totalpages -= page - startpage;
David Woodhousee0c7d762006-05-13 18:07:53 +01001655 numpages = min(totalpages, ppblock);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001656 page &= chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 startpage = page;
David Woodhousee0c7d762006-05-13 18:07:53 +01001658 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Todd Poynor868801e2005-11-05 03:21:15 +00001659 oob = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 /* Check, if we cross a chip boundary */
1661 if (!page) {
1662 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001663 chip->select_chip(mtd, -1);
1664 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 }
1666 }
1667 }
1668 /* Verify the remaining pages */
David Woodhousee0c7d762006-05-13 18:07:53 +01001669 cmp:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001670 chip->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001671 ret = nand_verify_pages(mtd, this, startpage, totalpages, oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 if (!ret)
1673 *retlen = written;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001674 else
Thomas Gleixner9223a452006-05-23 17:21:03 +02001675 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
David Woodhousee0c7d762006-05-13 18:07:53 +01001677 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 /* Deselect and wake up anyone waiting on the device */
1679 nand_release_device(mtd);
1680
1681 return ret;
1682}
1683
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001684
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685/**
1686 * nand_write_oob - [MTD Interface] NAND write out-of-band
1687 * @mtd: MTD device structure
1688 * @to: offset to write to
1689 * @len: number of bytes to write
1690 * @retlen: pointer to variable to store the number of written bytes
1691 * @buf: the data to write
1692 *
1693 * NAND write out-of-band
1694 */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001695static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1696 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697{
1698 int column, page, status, ret = -EIO, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001699 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001701 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1702 (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
1704 /* Initialize return length value */
1705 *retlen = 0;
1706
1707 /* Do not allow write past end of page */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001708 column = to & (mtd->oobsize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 if ((column + len) > mtd->oobsize) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001710 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1711 "Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 return -EINVAL;
1713 }
1714
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001715 nand_get_device(chip, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001717 chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001718 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001720 /* Shift to get page */
1721 page = (int)(to >> chip->page_shift);
1722
1723 /*
1724 * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
1725 * of my DiskOnChip 2000 test units) will clear the whole data page too
1726 * if we don't do this. I have no clue why, but I seem to have 'fixed'
1727 * it in the doc2000 driver in August 1999. dwmw2.
1728 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001729 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
1731 /* Check, if it is write protected */
1732 if (nand_check_wp(mtd))
1733 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001734
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001736 if (page == chip->pagebuf)
1737 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001739 if (NAND_MUST_PAD(chip)) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001740 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
1741 page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 /* prepad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001743 chip->write_buf(mtd, ffchars, column);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 /* write data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001745 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 /* postpad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001747 chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 } else {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001749 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column,
1750 page & chip->pagemask);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001751 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 }
1753 /* Send command to program the OOB data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001754 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001756 status = chip->waitfunc(mtd, chip, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
1758 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001759 if (status & NAND_STATUS_FAIL) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001760 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1761 "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 ret = -EIO;
1763 goto out;
1764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 *retlen = len;
1766
1767#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1768 /* Send command to read back the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001769 chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001771 if (chip->verify_buf(mtd, buf, len)) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001772 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1773 "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 ret = -EIO;
1775 goto out;
1776 }
1777#endif
1778 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001779 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 /* Deselect and wake up anyone waiting on the device */
1781 nand_release_device(mtd);
1782
1783 return ret;
1784}
1785
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1788 * @mtd: MTD device structure
1789 * @page: the page address of the block which will be erased
1790 *
1791 * Standard erase command for NAND chips
1792 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001793static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001795 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001797 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1798 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799}
1800
1801/**
1802 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1803 * @mtd: MTD device structure
1804 * @page: the page address of the block which will be erased
1805 *
1806 * AND multi block erase command function
1807 * Erase 4 consecutive blocks
1808 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001809static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001811 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001813 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1814 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1815 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1816 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1817 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818}
1819
1820/**
1821 * nand_erase - [MTD Interface] erase block(s)
1822 * @mtd: MTD device structure
1823 * @instr: erase instruction
1824 *
1825 * Erase one ore more blocks
1826 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001827static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
David Woodhousee0c7d762006-05-13 18:07:53 +01001829 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001831
David A. Marlin30f464b2005-01-17 18:35:25 +00001832#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001834 * nand_erase_nand - [Internal] erase block(s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 * @mtd: MTD device structure
1836 * @instr: erase instruction
1837 * @allowbbt: allow erasing the bbt area
1838 *
1839 * Erase one ore more blocks
1840 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001841int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
1842 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843{
1844 int page, len, status, pages_per_block, ret, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001845 struct nand_chip *chip = mtd->priv;
1846 int rewrite_bbt[NAND_MAX_CHIPS]={0};
1847 unsigned int bbt_masked_page = 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001849 DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
1850 (unsigned int)instr->addr, (unsigned int)instr->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
1852 /* Start address must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001853 if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001854 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 return -EINVAL;
1856 }
1857
1858 /* Length must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001859 if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
1860 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1861 "Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 return -EINVAL;
1863 }
1864
1865 /* Do not allow erase past end of device */
1866 if ((instr->len + instr->addr) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001867 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1868 "Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 return -EINVAL;
1870 }
1871
1872 instr->fail_addr = 0xffffffff;
1873
1874 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001875 nand_get_device(chip, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
1877 /* Shift to get first page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001878 page = (int)(instr->addr >> chip->page_shift);
1879 chipnr = (int)(instr->addr >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
1881 /* Calculate pages in each block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001882 pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
1884 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001885 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 /* Check, if it is write protected */
1888 if (nand_check_wp(mtd)) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001889 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1890 "Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 instr->state = MTD_ERASE_FAILED;
1892 goto erase_exit;
1893 }
1894
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001895 /*
1896 * If BBT requires refresh, set the BBT page mask to see if the BBT
1897 * should be rewritten. Otherwise the mask is set to 0xffffffff which
1898 * can not be matched. This is also done when the bbt is actually
1899 * erased to avoid recusrsive updates
1900 */
1901 if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
1902 bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
David A. Marlin30f464b2005-01-17 18:35:25 +00001903
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 /* Loop through the pages */
1905 len = instr->len;
1906
1907 instr->state = MTD_ERASING;
1908
1909 while (len) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001910 /*
1911 * heck if we have a bad block, we do not erase bad blocks !
1912 */
1913 if (nand_block_checkbad(mtd, ((loff_t) page) <<
1914 chip->page_shift, 0, allowbbt)) {
1915 printk(KERN_WARNING "nand_erase: attempt to erase a "
1916 "bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 instr->state = MTD_ERASE_FAILED;
1918 goto erase_exit;
1919 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001920
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001921 /*
1922 * Invalidate the page cache, if we erase the block which
1923 * contains the current cached page
1924 */
1925 if (page <= chip->pagebuf && chip->pagebuf <
1926 (page + pages_per_block))
1927 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001929 chip->erase_cmd(mtd, page & chip->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001930
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001931 status = chip->waitfunc(mtd, chip, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001933 /*
1934 * See if operation failed and additional status checks are
1935 * available
1936 */
1937 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
1938 status = chip->errstat(mtd, chip, FL_ERASING,
1939 status, page);
David A. Marlin068e3c02005-01-24 03:07:46 +00001940
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001942 if (status & NAND_STATUS_FAIL) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001943 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1944 "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 instr->state = MTD_ERASE_FAILED;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001946 instr->fail_addr = (page << chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 goto erase_exit;
1948 }
David A. Marlin30f464b2005-01-17 18:35:25 +00001949
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001950 /*
1951 * If BBT requires refresh, set the BBT rewrite flag to the
1952 * page being erased
1953 */
1954 if (bbt_masked_page != 0xffffffff &&
1955 (page & BBT_PAGE_MASK) == bbt_masked_page)
1956 rewrite_bbt[chipnr] = (page << chip->page_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001957
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 /* Increment page address and decrement length */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001959 len -= (1 << chip->phys_erase_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 page += pages_per_block;
1961
1962 /* Check, if we cross a chip boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001963 if (len && !(page & chip->pagemask)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001965 chip->select_chip(mtd, -1);
1966 chip->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00001967
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001968 /*
1969 * If BBT requires refresh and BBT-PERCHIP, set the BBT
1970 * page mask to see if this BBT should be rewritten
1971 */
1972 if (bbt_masked_page != 0xffffffff &&
1973 (chip->bbt_td->options & NAND_BBT_PERCHIP))
1974 bbt_masked_page = chip->bbt_td->pages[chipnr] &
1975 BBT_PAGE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 }
1977 }
1978 instr->state = MTD_ERASE_DONE;
1979
David Woodhousee0c7d762006-05-13 18:07:53 +01001980 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981
1982 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
1983 /* Do call back function */
1984 if (!ret)
1985 mtd_erase_callback(instr);
1986
1987 /* Deselect and wake up anyone waiting on the device */
1988 nand_release_device(mtd);
1989
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001990 /*
1991 * If BBT requires refresh and erase was successful, rewrite any
1992 * selected bad block tables
1993 */
1994 if (bbt_masked_page == 0xffffffff || ret)
1995 return ret;
1996
1997 for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
1998 if (!rewrite_bbt[chipnr])
1999 continue;
2000 /* update the BBT for chip */
2001 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
2002 "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
2003 chip->bbt_td->pages[chipnr]);
2004 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00002005 }
2006
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 /* Return more or less happy */
2008 return ret;
2009}
2010
2011/**
2012 * nand_sync - [MTD Interface] sync
2013 * @mtd: MTD device structure
2014 *
2015 * Sync is actually a wait for chip ready function
2016 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002017static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002019 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
David Woodhousee0c7d762006-05-13 18:07:53 +01002021 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
2023 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002024 nand_get_device(chip, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01002026 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027}
2028
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002030 * nand_block_isbad - [MTD Interface] Check if block at offset is bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 * @mtd: MTD device structure
2032 * @ofs: offset relative to mtd start
2033 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002034static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035{
2036 /* Check for invalid offset */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002037 if (offs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002039
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002040 return nand_block_checkbad(mtd, offs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041}
2042
2043/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002044 * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 * @mtd: MTD device structure
2046 * @ofs: offset relative to mtd start
2047 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002048static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002050 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 int ret;
2052
David Woodhousee0c7d762006-05-13 18:07:53 +01002053 if ((ret = nand_block_isbad(mtd, ofs))) {
2054 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 if (ret > 0)
2056 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01002057 return ret;
2058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002060 return chip->block_markbad(mtd, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061}
2062
2063/**
Vitaly Wool962034f2005-09-15 14:58:53 +01002064 * nand_suspend - [MTD Interface] Suspend the NAND flash
2065 * @mtd: MTD device structure
2066 */
2067static int nand_suspend(struct mtd_info *mtd)
2068{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002069 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01002070
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002071 return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01002072}
2073
2074/**
2075 * nand_resume - [MTD Interface] Resume the NAND flash
2076 * @mtd: MTD device structure
2077 */
2078static void nand_resume(struct mtd_info *mtd)
2079{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002080 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01002081
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002082 if (chip->state == FL_PM_SUSPENDED)
Vitaly Wool962034f2005-09-15 14:58:53 +01002083 nand_release_device(mtd);
2084 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02002085 printk(KERN_ERR "nand_resume() called for a chip which is not "
2086 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01002087}
2088
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002089/*
2090 * Free allocated data structures
2091 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002092static void nand_free_kmem(struct nand_chip *chip)
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002093{
2094 /* Buffer allocated by nand_scan ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002095 if (chip->options & NAND_OOBBUF_ALLOC)
2096 kfree(chip->oob_buf);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002097 /* Buffer allocated by nand_scan ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002098 if (chip->options & NAND_DATABUF_ALLOC)
2099 kfree(chip->data_buf);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002100 /* Controller allocated by nand_scan ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002101 if (chip->options & NAND_CONTROLLER_ALLOC)
2102 kfree(chip->controller);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002103}
2104
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002105/*
2106 * Allocate buffers and data structures
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002108static int nand_allocate_kmem(struct mtd_info *mtd, struct nand_chip *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109{
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002110 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002112 if (!chip->oob_buf) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002113 len = mtd->oobsize <<
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002114 (chip->phys_erase_shift - chip->page_shift);
2115 chip->oob_buf = kmalloc(len, GFP_KERNEL);
2116 if (!chip->oob_buf)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002117 goto outerr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002118 chip->options |= NAND_OOBBUF_ALLOC;
David Woodhouse552d9202006-05-14 01:20:46 +01002119 }
2120
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002121 if (!chip->data_buf) {
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002122 len = mtd->writesize + mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002123 chip->data_buf = kmalloc(len, GFP_KERNEL);
2124 if (!chip->data_buf)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002125 goto outerr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002126 chip->options |= NAND_DATABUF_ALLOC;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002129 if (!chip->controller) {
2130 chip->controller = kzalloc(sizeof(struct nand_hw_control),
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002131 GFP_KERNEL);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002132 if (!chip->controller)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002133 goto outerr;
Thomas Gleixner04bbd0e2006-05-25 09:45:29 +02002134
2135 spin_lock_init(&chip->controller->lock);
2136 init_waitqueue_head(&chip->controller->wq);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002137 chip->options |= NAND_CONTROLLER_ALLOC;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002138 }
2139 return 0;
2140
2141 outerr:
2142 printk(KERN_ERR "nand_scan(): Cannot allocate buffers\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002143 nand_free_kmem(chip);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002144 return -ENOMEM;
2145}
2146
2147/*
2148 * Set default functions
2149 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002150static void nand_set_defaults(struct nand_chip *chip, int busw)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002151{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 /* check for proper chip_delay setup, set 20us if not */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002153 if (!chip->chip_delay)
2154 chip->chip_delay = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
2156 /* check, if a user supplied command function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002157 if (chip->cmdfunc == NULL)
2158 chip->cmdfunc = nand_command;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160 /* check, if a user supplied wait function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002161 if (chip->waitfunc == NULL)
2162 chip->waitfunc = nand_wait;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002164 if (!chip->select_chip)
2165 chip->select_chip = nand_select_chip;
2166 if (!chip->read_byte)
2167 chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
2168 if (!chip->read_word)
2169 chip->read_word = nand_read_word;
2170 if (!chip->block_bad)
2171 chip->block_bad = nand_block_bad;
2172 if (!chip->block_markbad)
2173 chip->block_markbad = nand_default_block_markbad;
2174 if (!chip->write_buf)
2175 chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
2176 if (!chip->read_buf)
2177 chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
2178 if (!chip->verify_buf)
2179 chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
2180 if (!chip->scan_bbt)
2181 chip->scan_bbt = nand_default_bbt;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002182}
2183
2184/*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002185 * Get the flash and manufacturer id and lookup if the type is supported
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002186 */
2187static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002188 struct nand_chip *chip,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002189 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 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002195 chip->select_chip(mtd, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196
2197 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002198 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199
2200 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002201 *maf_id = chip->read_byte(mtd);
2202 dev_id = chip->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
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002215 chip->chipsize = nand_flash_ids[i].chipsize << 20;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002216
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 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002221 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002222 /* The 4th id byte is the important one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002223 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002224 /* 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 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002238 * Old devices have chip data hardcoded in the device id table
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002239 */
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
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002254 * chip correct !
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002255 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002256 if (busw != (chip->options & NAND_BUSWIDTH_16)) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002257 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",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002261 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002262 busw ? 16 : 8);
2263 return ERR_PTR(-EINVAL);
2264 }
2265
2266 /* Calculate the address shift from the page size */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002267 chip->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002268 /* Convert chipsize to number of pages per chip -1. */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002269 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002270
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002271 chip->bbt_erase_shift = chip->phys_erase_shift =
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002272 ffs(mtd->erasesize) - 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002273 chip->chip_shift = ffs(chip->chipsize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002274
2275 /* Set the bad block position */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002276 chip->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 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002280 chip->options &= ~NAND_CHIPOPTIONS_MSK;
2281 chip->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002282
2283 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002284 * Set chip as a default. Board drivers can override it, if necessary
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002285 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002286 chip->options |= NAND_NO_AUTOINCR;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002287
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002288 /* Check if chip is a not a samsung device. Do not clear the
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002289 * options for chips which are not having an extended id.
2290 */
2291 if (*maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002292 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002293
2294 /* Check for AND chips with 4 page planes */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002295 if (chip->options & NAND_4PAGE_ARRAY)
2296 chip->erase_cmd = multi_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002297 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002298 chip->erase_cmd = single_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002299
2300 /* Do not replace user supplied command function ! */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002301 if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
2302 chip->cmdfunc = nand_command_lp;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002303
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;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002337 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002338 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 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002347 busw = chip->options & NAND_BUSWIDTH_16;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002348 /* Set the default functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002349 nand_set_defaults(chip, busw);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002350
2351 /* Read the flash type */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002352 type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002353
2354 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002355 printk(KERN_WARNING "No NAND device found!!!\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002356 chip->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++) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002362 chip->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002364 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002366 if (nand_maf_id != chip->read_byte(mtd) ||
2367 type->id != chip->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 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002374 chip->numchips = i;
2375 mtd->size = i * chip->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002377 /* Allocate buffers and data structures */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002378 if (nand_allocate_kmem(mtd, chip))
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002379 return -ENOMEM;
2380
2381 /* Preset the internal oob buffer */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002382 memset(chip->oob_buf, 0xff,
2383 mtd->oobsize << (chip->phys_erase_shift - chip->page_shift));
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002384
2385 /*
2386 * If no default placement scheme is given, select an appropriate one
2387 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002388 if (!chip->autooob) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002389 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 case 8:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002391 chip->autooob = &nand_oob_8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 break;
2393 case 16:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002394 chip->autooob = &nand_oob_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 break;
2396 case 64:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002397 chip->autooob = &nand_oob_64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 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;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002411 for (i = 0; chip->autooob->oobfree[i][1]; i++)
2412 mtd->oobavail += chip->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 Gleixnerace4dfe2006-05-24 12:07:37 +02002418 switch (chip->ecc.mode) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002419 case NAND_ECC_HW:
2420 case NAND_ECC_HW_SYNDROME:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002421 if (!chip->ecc.calculate || !chip->ecc.correct ||
2422 !chip->ecc.hwctl) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002423 printk(KERN_WARNING "No ECC functions supplied, "
2424 "Hardware ECC not possible\n");
2425 BUG();
2426 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002427 if (mtd->writesize >= chip->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 Gleixnerace4dfe2006-05-24 12:07:37 +02002431 chip->ecc.size, mtd->writesize);
2432 chip->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:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002435 chip->ecc.calculate = nand_calculate_ecc;
2436 chip->ecc.correct = nand_correct_data;
2437 chip->ecc.size = 256;
2438 chip->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 Gleixnerace4dfe2006-05-24 12:07:37 +02002444 chip->ecc.size = mtd->writesize;
2445 chip->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 Gleixnerace4dfe2006-05-24 12:07:37 +02002449 chip->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 Gleixnerace4dfe2006-05-24 12:07:37 +02002457 chip->ecc.steps = mtd->writesize / chip->ecc.size;
2458 if(chip->ecc.steps * chip->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
Thomas Gleixner04bbd0e2006-05-25 09:45:29 +02002463 /* Initialize state */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002464 chip->state = FL_READY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
2466 /* De-select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002467 chip->select_chip(mtd, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468
2469 /* Invalidate the pagebuffer reference */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002470 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471
2472 /* Fill in remaining MTD driver data */
2473 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002474 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 mtd->ecctype = MTD_ECC_SW;
2476 mtd->erase = nand_erase;
2477 mtd->point = NULL;
2478 mtd->unpoint = NULL;
2479 mtd->read = nand_read;
2480 mtd->write = nand_write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 mtd->read_oob = nand_read_oob;
2482 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 mtd->sync = nand_sync;
2484 mtd->lock = NULL;
2485 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002486 mtd->suspend = nand_suspend;
2487 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 mtd->block_isbad = nand_block_isbad;
2489 mtd->block_markbad = nand_block_markbad;
2490
2491 /* and make the autooob the default one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002492 memcpy(&mtd->oobinfo, chip->autooob, sizeof(mtd->oobinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002494 /* Check, if we should skip the bad block table scan */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002495 if (chip->options & NAND_SKIP_BBTSCAN)
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002496 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
2498 /* Build bad block table */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002499 return chip->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500}
2501
2502/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002503 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 * @mtd: MTD device structure
2505*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002506void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002508 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
2510#ifdef CONFIG_MTD_PARTITIONS
2511 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002512 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513#endif
2514 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002515 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516
Jesper Juhlfa671642005-11-07 01:01:27 -08002517 /* Free bad block table memory */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002518 kfree(chip->bbt);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002519 /* Free buffers */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002520 nand_free_kmem(chip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521}
2522
David Woodhousee0c7d762006-05-13 18:07:53 +01002523EXPORT_SYMBOL_GPL(nand_scan);
2524EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002525
2526static int __init nand_base_init(void)
2527{
2528 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2529 return 0;
2530}
2531
2532static void __exit nand_base_exit(void)
2533{
2534 led_trigger_unregister_simple(nand_led_trigger);
2535}
2536
2537module_init(nand_base_init);
2538module_exit(nand_base_exit);
2539
David Woodhousee0c7d762006-05-13 18:07:53 +01002540MODULE_LICENSE("GPL");
2541MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2542MODULE_DESCRIPTION("Generic NAND flash driver code");