blob: 6036d322bf68cf22440be8b4a8496bc98ed90621 [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 Gleixnerace4dfe2006-05-24 12:07:37 +0200541 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
542 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 return;
544
David Woodhousee0c7d762006-05-13 18:07:53 +0100545 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000547 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 * If we don't have access to the busy pin, we apply the given
549 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100550 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200551 if (!chip->dev_ready) {
552 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 /* Apply this short delay always to ensure that we do wait tWB in
557 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100558 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000559
560 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561}
562
563/**
564 * nand_command_lp - [DEFAULT] Send command to NAND large page device
565 * @mtd: MTD device structure
566 * @command: the command to be sent
567 * @column: the column address for this command, -1 if none
568 * @page_addr: the page address for this command, -1 if none
569 *
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200570 * Send command to NAND device. This is the version for the new large page
571 * devices We dont have the separate regions as we have in the small page
572 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 *
574 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200575static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
576 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200578 register struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
580 /* Emulate NAND_CMD_READOOB */
581 if (command == NAND_CMD_READOOB) {
Joern Engel28318772006-05-22 23:18:05 +0200582 column += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 command = NAND_CMD_READ0;
584 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000585
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200586 /* Command latch cycle */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200587 chip->cmd_ctrl(mtd, command & 0xff,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200588 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590 if (column != -1 || page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200591 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
593 /* Serially input address */
594 if (column != -1) {
595 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200596 if (chip->options & NAND_BUSWIDTH_16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200598 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200599 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200600 chip->cmd_ctrl(mtd, column >> 8, ctrl);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000601 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200603 chip->cmd_ctrl(mtd, page_addr, ctrl);
604 chip->cmd_ctrl(mtd, page_addr >> 8,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200605 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 /* One more address cycle for devices > 128MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200607 if (chip->chipsize > (128 << 20))
608 chip->cmd_ctrl(mtd, page_addr >> 16,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200609 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200612 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000613
614 /*
615 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000616 * status, sequential in, and deplete1 need no delay
617 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 case NAND_CMD_CACHEDPROG:
621 case NAND_CMD_PAGEPROG:
622 case NAND_CMD_ERASE1:
623 case NAND_CMD_ERASE2:
624 case NAND_CMD_SEQIN:
625 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000626 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 return;
628
David Woodhousee0c7d762006-05-13 18:07:53 +0100629 /*
630 * read error status commands require only a short delay
631 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000632 case NAND_CMD_STATUS_ERROR:
633 case NAND_CMD_STATUS_ERROR0:
634 case NAND_CMD_STATUS_ERROR1:
635 case NAND_CMD_STATUS_ERROR2:
636 case NAND_CMD_STATUS_ERROR3:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200637 udelay(chip->chip_delay);
David A. Marlin30f464b2005-01-17 18:35:25 +0000638 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
640 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200641 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200643 udelay(chip->chip_delay);
644 chip->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE | NAND_CLE);
645 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
646 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 return;
648
649 case NAND_CMD_READ0:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200650 chip->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_NCE | NAND_CLE);
651 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000652
David Woodhousee0c7d762006-05-13 18:07:53 +0100653 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000655 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 * If we don't have access to the busy pin, we apply the given
657 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100658 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200659 if (!chip->dev_ready) {
660 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000662 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000664
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 /* Apply this short delay always to ensure that we do wait tWB in
666 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100667 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000668
669 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670}
671
672/**
673 * nand_get_device - [GENERIC] Get chip for selected access
674 * @this: the nand chip descriptor
675 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000676 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 *
678 * Get the device and lock it for exclusive access
679 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200680static int
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200681nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200683 spinlock_t *lock = &chip->controller->lock;
684 wait_queue_head_t *wq = &chip->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100685 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100686 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100687 spin_lock(lock);
688
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200690 /* Hardware controller shared among independend devices */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200691 if (!chip->controller->active)
692 chip->controller->active = chip;
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200693
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200694 if (chip->controller->active == chip && chip->state == FL_READY) {
695 chip->state = new_state;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100696 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100697 return 0;
698 }
699 if (new_state == FL_PM_SUSPENDED) {
700 spin_unlock(lock);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200701 return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100702 }
703 set_current_state(TASK_UNINTERRUPTIBLE);
704 add_wait_queue(wq, &wait);
705 spin_unlock(lock);
706 schedule();
707 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 goto retry;
709}
710
711/**
712 * nand_wait - [DEFAULT] wait until the command is done
713 * @mtd: MTD device structure
714 * @this: NAND chip structure
715 * @state: state to select the max. timeout value
716 *
717 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000718 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 * general NAND and SmartMedia specs
720 *
721*/
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200722static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723{
724
David Woodhousee0c7d762006-05-13 18:07:53 +0100725 unsigned long timeo = jiffies;
726 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000727
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100729 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100731 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
Richard Purdie8fe833c2006-03-31 02:31:14 -0800733 led_trigger_event(nand_led_trigger, LED_FULL);
734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 /* Apply this short delay always to ensure that we do wait tWB in
736 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100737 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200739 if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
740 chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000741 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200742 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000744 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 /* Check, if we were interrupted */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200746 if (chip->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 return 0;
748
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200749 if (chip->dev_ready) {
750 if (chip->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000751 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200753 if (chip->read_byte(mtd) & NAND_STATUS_READY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 break;
755 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000756 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800758 led_trigger_event(nand_led_trigger, LED_OFF);
759
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200760 status = (int)chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 return status;
762}
763
764/**
765 * nand_write_page - [GENERIC] write one page
766 * @mtd: MTD device structure
767 * @this: NAND chip structure
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200768 * @page: startpage inside the chip, must be called with (page & chip->pagemask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 * @oob_buf: out of band data buffer
770 * @oobsel: out of band selecttion structre
771 * @cached: 1 = enable cached programming if supported by chip
772 *
773 * Nand_page_program function is used for write and writev !
774 * This function will always program a full page of data
775 * If you call it with a non page aligned buffer, you're lost :)
776 *
777 * Cached programming is not supported yet.
778 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200779static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, int page,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200780 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int cached)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781{
David Woodhousee0c7d762006-05-13 18:07:53 +0100782 int i, status;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200783 uint8_t ecc_code[32];
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200784 int eccmode = oobsel->useecc ? chip->ecc.mode : NAND_ECC_NONE;
David Woodhousee0c7d762006-05-13 18:07:53 +0100785 int *oob_config = oobsel->eccpos;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200786 int datidx = 0, eccidx = 0, eccsteps = chip->ecc.steps;
David Woodhousee0c7d762006-05-13 18:07:53 +0100787 int eccbytes = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000788
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 /* FIXME: Enable cached programming */
790 cached = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000791
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 /* Send command to begin auto page programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200793 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795 /* Write out complete page of data, take care of eccmode */
796 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100797 /* No ecc, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 case NAND_ECC_NONE:
David Woodhousee0c7d762006-05-13 18:07:53 +0100799 printk(KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200800 chip->write_buf(mtd, chip->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000802
David Woodhousee0c7d762006-05-13 18:07:53 +0100803 /* Software ecc 3/256, write all */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 case NAND_ECC_SOFT:
805 for (; eccsteps; eccsteps--) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200806 chip->ecc.calculate(mtd, &chip->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 for (i = 0; i < 3; i++, eccidx++)
808 oob_buf[oob_config[eccidx]] = ecc_code[i];
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200809 datidx += chip->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200811 chip->write_buf(mtd, chip->data_poi, mtd->writesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 break;
813 default:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200814 eccbytes = chip->ecc.bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 for (; eccsteps; eccsteps--) {
816 /* enable hardware ecc logic for write */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200817 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
818 chip->write_buf(mtd, &chip->data_poi[datidx], chip->ecc.size);
819 chip->ecc.calculate(mtd, &chip->data_poi[datidx], ecc_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 for (i = 0; i < eccbytes; i++, eccidx++)
821 oob_buf[oob_config[eccidx]] = ecc_code[i];
822 /* If the hardware ecc provides syndromes then
823 * the ecc code must be written immidiately after
824 * the data bytes (words) */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200825 if (chip->options & NAND_HWECC_SYNDROME)
826 chip->write_buf(mtd, ecc_code, eccbytes);
827 datidx += chip->ecc.size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 }
829 break;
830 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 /* Write out OOB data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200833 if (chip->options & NAND_HWECC_SYNDROME)
834 chip->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000835 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200836 chip->write_buf(mtd, oob_buf, mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
838 /* Send command to actually program the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200839 chip->cmdfunc(mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
841 if (!cached) {
842 /* call wait ready function */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200843 status = chip->waitfunc(mtd, chip, FL_WRITING);
David A. Marlin068e3c02005-01-24 03:07:46 +0000844
845 /* See if operation failed and additional status checks are available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200846 if ((status & NAND_STATUS_FAIL) && (chip->errstat)) {
847 status = chip->errstat(mtd, chip, FL_WRITING, status, page);
David A. Marlin068e3c02005-01-24 03:07:46 +0000848 }
849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +0000851 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100852 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 return -EIO;
854 }
855 } else {
856 /* FIXME: Implement cached programming ! */
David Woodhousee0c7d762006-05-13 18:07:53 +0100857 /* wait until cache is ready */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200858 // status = chip->waitfunc (mtd, this, FL_CACHEDRPG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000860 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861}
862
863#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
864/**
865 * nand_verify_pages - [GENERIC] verify the chip contents after a write
866 * @mtd: MTD device structure
867 * @this: NAND chip structure
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200868 * @page: startpage inside the chip, must be called with (page & chip->pagemask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 * @numpages: number of pages to verify
870 * @oob_buf: out of band data buffer
871 * @oobsel: out of band selecttion structre
872 * @chipnr: number of the current chip
873 * @oobmode: 1 = full buffer verify, 0 = ecc only
874 *
875 * The NAND device assumes that it is always writing to a cleanly erased page.
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000876 * Hence, it performs its internal write verification only on bits that
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 * transitioned from 1 to 0. The device does NOT verify the whole page on a
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000878 * byte by byte basis. It is possible that the page was not completely erased
879 * or the page is becoming unusable due to wear. The read with ECC would catch
880 * the error later when the ECC page check fails, but we would rather catch
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 * it early in the page write stage. Better to write no data than invalid data.
882 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200883static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *chip, int page, int numpages,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200884 uint8_t *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885{
David Woodhousee0c7d762006-05-13 18:07:53 +0100886 int i, j, datidx = 0, oobofs = 0, res = -EIO;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200887 int eccsteps = chip->eccsteps;
David Woodhousee0c7d762006-05-13 18:07:53 +0100888 int hweccbytes;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200889 uint8_t oobdata[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200891 hweccbytes = (chip->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
893 /* Send command to read back the first page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200894 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
David Woodhousee0c7d762006-05-13 18:07:53 +0100896 for (;;) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 for (j = 0; j < eccsteps; j++) {
898 /* Loop through and verify the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200899 if (chip->verify_buf(mtd, &chip->data_poi[datidx], mtd->eccsize)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100900 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 goto out;
902 }
903 datidx += mtd->eccsize;
904 /* Have we a hw generator layout ? */
905 if (!hweccbytes)
906 continue;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200907 if (chip->verify_buf(mtd, &chip->oob_buf[oobofs], hweccbytes)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100908 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 goto out;
910 }
911 oobofs += hweccbytes;
912 }
913
914 /* check, if we must compare all data or if we just have to
915 * compare the ecc bytes
916 */
917 if (oobmode) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200918 if (chip->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
David Woodhousee0c7d762006-05-13 18:07:53 +0100919 DEBUG(MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 goto out;
921 }
922 } else {
923 /* Read always, else autoincrement fails */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200924 chip->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
926 if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
927 int ecccnt = oobsel->eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000928
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 for (i = 0; i < ecccnt; i++) {
930 int idx = oobsel->eccpos[i];
David Woodhousee0c7d762006-05-13 18:07:53 +0100931 if (oobdata[idx] != oob_buf[oobofs + idx]) {
932 DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed ECC write verify, page 0x%08x, %6i bytes were succesful\n",
933 __FUNCTION__, page, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 goto out;
935 }
936 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000937 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
939 oobofs += mtd->oobsize - hweccbytes * eccsteps;
940 page++;
941 numpages--;
942
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000943 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 * Do this before the AUTOINCR check, so no problems
945 * arise if a chip which does auto increment
946 * is marked as NOAUTOINCR by the board driver.
947 * Do this also before returning, so the chip is
948 * ready for the next command.
David Woodhousee0c7d762006-05-13 18:07:53 +0100949 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200950 if (!chip->dev_ready)
951 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 else
Thomas Gleixner3b887752005-02-22 21:56:49 +0000953 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
955 /* All done, return happy */
956 if (!numpages)
957 return 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000958
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000959 /* Check, if the chip supports auto page increment */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 if (!NAND_CANAUTOINCR(this))
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200961 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000963 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 * Terminate the read command. We come here in case of an error
965 * So we must issue a reset command.
966 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100967 out:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200968 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 return res;
970}
971#endif
972
973/**
David A. Marlin068e3c02005-01-24 03:07:46 +0000974 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 * @mtd: MTD device structure
976 * @from: offset to read from
977 * @len: number of bytes to read
978 * @retlen: pointer to variable to store the number of read bytes
979 * @buf: the databuffer to put data
980 *
David A. Marlin068e3c02005-01-24 03:07:46 +0000981 * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL
982 * and flags = 0xff
983 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200984static 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 -0700985{
David Woodhousee0c7d762006-05-13 18:07:53 +0100986 return nand_do_read_ecc(mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);
Thomas Gleixner22c60f52005-04-04 19:56:32 +0100987}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989/**
David A. Marlin068e3c02005-01-24 03:07:46 +0000990 * nand_do_read_ecc - [MTD Interface] Read data with ECC
991 * @mtd: MTD device structure
992 * @from: offset to read from
993 * @len: number of bytes to read
994 * @retlen: pointer to variable to store the number of read bytes
995 * @buf: the databuffer to put data
Dan Brownbb75ba42005-04-04 19:02:26 +0100996 * @oob_buf: filesystem supplied oob data buffer (can be NULL)
Thomas Gleixner22c60f52005-04-04 19:56:32 +0100997 * @oobsel: oob selection structure
David A. Marlin068e3c02005-01-24 03:07:46 +0000998 * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed
999 * and how many corrected error bits are acceptable:
1000 * bits 0..7 - number of tolerable errors
1001 * bit 8 - 0 == do not get/release chip, 1 == get/release chip
1002 *
1003 * NAND read with ECC
1004 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001005int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001006 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel, int flags)
David A. Marlin068e3c02005-01-24 03:07:46 +00001007{
Thomas Gleixner22c60f52005-04-04 19:56:32 +01001008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
1010 int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001011 struct nand_chip *chip = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001012 uint8_t *data_poi, *oob_data = oob_buf;
1013 uint8_t ecc_calc[32];
1014 uint8_t ecc_code[32];
David Woodhousee0c7d762006-05-13 18:07:53 +01001015 int eccmode, eccsteps;
1016 int *oob_config, datidx;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001017 int blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
David Woodhousee0c7d762006-05-13 18:07:53 +01001018 int eccbytes;
1019 int compareecc = 1;
1020 int oobreadlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
David Woodhousee0c7d762006-05-13 18:07:53 +01001022 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 -07001023
1024 /* Do not allow reads past end of device */
1025 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001026 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 *retlen = 0;
1028 return -EINVAL;
1029 }
1030
1031 /* Grab the lock and see if the device is available */
David A. Marlin068e3c02005-01-24 03:07:46 +00001032 if (flags & NAND_GET_DEVICE)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001033 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 /* Autoplace of oob data ? Use the default placement scheme */
1036 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001037 oobsel = chip->autooob;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001038
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001039 eccmode = oobsel->useecc ? chip->ecc.mode : NAND_ECC_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 oob_config = oobsel->eccpos;
1041
1042 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001043 chipnr = (int)(from >> chip->chip_shift);
1044 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
1046 /* First we calculate the starting page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001047 realpage = (int)(from >> chip->page_shift);
1048 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
1050 /* Get raw starting column */
Joern Engel28318772006-05-22 23:18:05 +02001051 col = from & (mtd->writesize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
Joern Engel28318772006-05-22 23:18:05 +02001053 end = mtd->writesize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001054 ecc = chip->ecc.size;
1055 eccbytes = chip->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001056
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001057 if ((eccmode == NAND_ECC_NONE) || (chip->options & NAND_HWECC_SYNDROME))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 compareecc = 0;
1059
1060 oobreadlen = mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001061 if (chip->options & NAND_HWECC_SYNDROME)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 oobreadlen -= oobsel->eccbytes;
1063
1064 /* Loop until all data read */
1065 while (read < len) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 int aligned = (!col && (len - read) >= end);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001068 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 * If the read is not page aligned, we have to read into data buffer
1070 * due to ecc, else we read into return buffer direct
1071 */
1072 if (aligned)
1073 data_poi = &buf[read];
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001074 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001075 data_poi = chip->data_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001076
1077 /* Check, if we have this page in the buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 *
1079 * FIXME: Make it work when we must provide oob data too,
1080 * check the usage of data_buf oob field
1081 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001082 if (realpage == chip->pagebuf && !oob_buf) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 /* aligned read ? */
1084 if (aligned)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001085 memcpy(data_poi, chip->data_buf, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 goto readdata;
1087 }
1088
1089 /* Check, if we must send the read command */
1090 if (sndcmd) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001091 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 sndcmd = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095 /* get oob area, if we have no oob buffer from fs-driver */
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001096 if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
1097 oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001098 oob_data = &chip->data_buf[end];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001100 eccsteps = chip->ecc.steps;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 switch (eccmode) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001103 case NAND_ECC_NONE:{
1104 /* No ECC, Read in a page */
1105 static unsigned long lastwhinge = 0;
1106 if ((lastwhinge / HZ) != (jiffies / HZ)) {
1107 printk(KERN_WARNING
1108 "Reading data from NAND FLASH without ECC is not recommended\n");
1109 lastwhinge = jiffies;
1110 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001111 chip->read_buf(mtd, data_poi, end);
David Woodhousee0c7d762006-05-13 18:07:53 +01001112 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001116 chip->read_buf(mtd, data_poi, end);
David Woodhousee0c7d762006-05-13 18:07:53 +01001117 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001118 chip->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001119 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
1121 default:
David Woodhousee0c7d762006-05-13 18:07:53 +01001122 for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001123 chip->ecc.hwctl(mtd, NAND_ECC_READ);
1124 chip->read_buf(mtd, &data_poi[datidx], ecc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 /* HW ecc with syndrome calculation must read the
1127 * syndrome from flash immidiately after the data */
1128 if (!compareecc) {
1129 /* Some hw ecc generators need to know when the
1130 * syndrome is read from flash */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001131 chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
1132 chip->read_buf(mtd, &oob_data[i], eccbytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 /* We calc error correction directly, it checks the hw
1134 * generator for an error, reads back the syndrome and
1135 * does the error correction on the fly */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001136 ecc_status = chip->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
David A. Marlin068e3c02005-01-24 03:07:46 +00001137 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001138 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: "
1139 "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 ecc_failed++;
1141 }
1142 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001143 chip->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001146 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 }
1148
1149 /* read oobdata */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001150 chip->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
1152 /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
1153 if (!compareecc)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001154 goto readoob;
1155
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 /* Pick the ECC bytes out of the oob data */
1157 for (j = 0; j < oobsel->eccbytes; j++)
1158 ecc_code[j] = oob_data[oob_config[j]];
1159
David Woodhousee0c7d762006-05-13 18:07:53 +01001160 /* correct data, if necessary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001161 for (i = 0, j = 0, datidx = 0; i < chip->ecc.steps; i++, datidx += ecc) {
1162 ecc_status = chip->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001163
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 /* Get next chunk of ecc bytes */
1165 j += eccbytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001166
1167 /* Check, if we have a fs supplied oob-buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 * This is the legacy mode. Used by YAFFS1
1169 * Should go away some day
1170 */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001171 if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 int *p = (int *)(&oob_data[mtd->oobsize]);
1173 p[i] = ecc_status;
1174 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001175
1176 if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001177 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 ecc_failed++;
1179 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
David Woodhousee0c7d762006-05-13 18:07:53 +01001182 readoob:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 /* check, if we have a fs supplied oob-buffer */
1184 if (oob_buf) {
1185 /* without autoplace. Legacy mode used by YAFFS1 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001186 switch (oobsel->useecc) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 case MTD_NANDECC_AUTOPLACE:
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001188 case MTD_NANDECC_AUTOPL_USR:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 /* Walk through the autoplace chunks */
Dan Brown82e1d192005-04-06 21:13:09 +01001190 for (i = 0; oobsel->oobfree[i][1]; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 int from = oobsel->oobfree[i][0];
1192 int num = oobsel->oobfree[i][1];
1193 memcpy(&oob_buf[oob], &oob_data[from], num);
Dan Brown82e1d192005-04-06 21:13:09 +01001194 oob += num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 break;
1197 case MTD_NANDECC_PLACE:
1198 /* YAFFS1 legacy mode */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001199 oob_data += chip->ecc.steps * sizeof(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 default:
1201 oob_data += mtd->oobsize;
1202 }
1203 }
1204 readdata:
1205 /* Partial page read, transfer data into fs buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001206 if (!aligned) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 for (j = col; j < end && read < len; j++)
1208 buf[read++] = data_poi[j];
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001209 chip->pagebuf = realpage;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001210 } else
Joern Engel28318772006-05-22 23:18:05 +02001211 read += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001213 /* Apply delay or wait for ready/busy pin
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 * Do this before the AUTOINCR check, so no problems
1215 * arise if a chip which does auto increment
1216 * is marked as NOAUTOINCR by the board driver.
David Woodhousee0c7d762006-05-13 18:07:53 +01001217 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001218 if (!chip->dev_ready)
1219 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001221 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 if (read == len)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001224 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
1226 /* For subsequent reads align to page boundary. */
1227 col = 0;
1228 /* Increment page address */
1229 realpage++;
1230
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001231 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 /* Check, if we cross a chip boundary */
1233 if (!page) {
1234 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001235 chip->select_chip(mtd, -1);
1236 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001238 /* Check, if the chip supports auto page increment
1239 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001240 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001241 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001242 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 }
1244
1245 /* Deselect and wake up anyone waiting on the device */
David A. Marlin068e3c02005-01-24 03:07:46 +00001246 if (flags & NAND_GET_DEVICE)
1247 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
1249 /*
1250 * Return success, if no ECC failures, else -EBADMSG
1251 * fs driver will take care of that, because
1252 * retlen == desired len and result == -EBADMSG
1253 */
1254 *retlen = read;
1255 return ecc_failed ? -EBADMSG : 0;
1256}
1257
1258/**
1259 * nand_read_oob - [MTD Interface] NAND read out-of-band
1260 * @mtd: MTD device structure
1261 * @from: offset to read from
1262 * @len: number of bytes to read
1263 * @retlen: pointer to variable to store the number of read bytes
1264 * @buf: the databuffer to put data
1265 *
1266 * NAND read out-of-band data from the spare area
1267 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001268static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269{
1270 int i, col, page, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001271 struct nand_chip *chip = mtd->priv;
1272 int blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
David Woodhousee0c7d762006-05-13 18:07:53 +01001274 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int)from, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
1276 /* Shift to get page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001277 page = (int)(from >> chip->page_shift);
1278 chipnr = (int)(from >> chip->chip_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 /* Mask to get column */
1281 col = from & (mtd->oobsize - 1);
1282
1283 /* Initialize return length value */
1284 *retlen = 0;
1285
1286 /* Do not allow reads past end of device */
1287 if ((from + len) > mtd->size) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001288 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 *retlen = 0;
1290 return -EINVAL;
1291 }
1292
1293 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001294 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
1296 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001297 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
1299 /* Send the read command */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001300 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page & chip->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001301 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 * Read the data, if we read more than one page
1303 * oob data, let the device transfer the data !
1304 */
1305 i = 0;
1306 while (i < len) {
1307 int thislen = mtd->oobsize - col;
1308 thislen = min_t(int, thislen, len);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001309 chip->read_buf(mtd, &buf[i], thislen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 i += thislen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
1312 /* Read more ? */
1313 if (i < len) {
1314 page++;
1315 col = 0;
1316
1317 /* Check, if we cross a chip boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001318 if (!(page & chip->pagemask)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001320 chip->select_chip(mtd, -1);
1321 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001323
1324 /* Apply delay or wait for ready/busy pin
Thomas Gleixner19870da2005-07-15 14:53:51 +01001325 * Do this before the AUTOINCR check, so no problems
1326 * arise if a chip which does auto increment
1327 * is marked as NOAUTOINCR by the board driver.
1328 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001329 if (!chip->dev_ready)
1330 udelay(chip->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001331 else
1332 nand_wait_ready(mtd);
1333
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001334 /* Check, if the chip supports auto page increment
1335 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +01001336 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001337 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 /* For subsequent page reads set offset to 0 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001339 chip->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 }
1341 }
1342 }
1343
1344 /* Deselect and wake up anyone waiting on the device */
1345 nand_release_device(mtd);
1346
1347 /* Return happy */
1348 *retlen = len;
1349 return 0;
1350}
1351
1352/**
1353 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1354 * @mtd: MTD device structure
1355 * @buf: temporary buffer
1356 * @from: offset to read from
1357 * @len: number of bytes to read
1358 * @ooblen: number of oob data bytes to read
1359 *
1360 * Read raw data including oob into buffer
1361 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001362int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len,
1363 size_t ooblen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001365 struct nand_chip *chip = mtd->priv;
1366 int page = (int)(from >> chip->page_shift);
1367 int chipnr = (int)(from >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 int sndcmd = 1;
1369 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001370 int pagesize = mtd->writesize + mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001371 int blockcheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
1373 /* Do not allow reads past end of device */
1374 if ((from + len) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001375 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: "
1376 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 return -EINVAL;
1378 }
1379
1380 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001381 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001383 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001384
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 /* Add requested oob length */
1386 len += ooblen;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001387 blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001388
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 while (len) {
1390 if (sndcmd)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001391 chip->cmdfunc(mtd, NAND_CMD_READ0, 0,
1392 page & chip->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001393 sndcmd = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001395 chip->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
1397 len -= pagesize;
1398 cnt += pagesize;
1399 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001400
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001401 if (!chip->dev_ready)
1402 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 else
Thomas Gleixner3b887752005-02-22 21:56:49 +00001404 nand_wait_ready(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001405
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001406 /*
1407 * Check, if the chip supports auto page increment or if we
1408 * cross a block boundary.
1409 */
1410 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 sndcmd = 1;
1412 }
1413
1414 /* Deselect and wake up anyone waiting on the device */
1415 nand_release_device(mtd);
1416 return 0;
1417}
1418
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001419/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001420 * nand_write_raw - [GENERIC] Write raw data including oob
1421 * @mtd: MTD device structure
1422 * @buf: source buffer
1423 * @to: offset to write to
1424 * @len: number of bytes to write
1425 * @buf: source buffer
1426 * @oob: oob buffer
1427 *
1428 * Write raw data including oob
1429 */
1430int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1431 uint8_t *buf, uint8_t *oob)
1432{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001433 struct nand_chip *chip = mtd->priv;
1434 int page = (int)(to >> chip->page_shift);
1435 int chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001436 int ret;
1437
1438 *retlen = 0;
1439
1440 /* Do not allow writes past end of device */
1441 if ((to + len) > mtd->size) {
1442 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1443 "beyond end of device\n");
1444 return -EINVAL;
1445 }
1446
1447 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001448 nand_get_device(chip, mtd, FL_WRITING);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001449
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001450 chip->select_chip(mtd, chipnr);
1451 chip->data_poi = buf;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001452
1453 while (len != *retlen) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001454 ret = nand_write_page(mtd, chip, page, oob, &mtd->oobinfo, 0);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001455 if (ret)
1456 return ret;
1457 page++;
1458 *retlen += mtd->writesize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001459 chip->data_poi += mtd->writesize;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001460 oob += mtd->oobsize;
1461 }
1462
1463 /* Deselect and wake up anyone waiting on the device */
1464 nand_release_device(mtd);
1465 return 0;
1466}
Thomas Gleixner38217202006-05-23 22:33:52 +02001467EXPORT_SYMBOL_GPL(nand_write_raw);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001468
1469/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001470 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 * @mtd: MTD device structure
1472 * @fsbuf: buffer given by fs driver
1473 * @oobsel: out of band selection structre
1474 * @autoplace: 1 = place given buffer into the oob bytes
1475 * @numpages: number of pages to prepare
1476 *
1477 * Return:
1478 * 1. Filesystem buffer available and autoplacement is off,
1479 * return filesystem buffer
1480 * 2. No filesystem buffer or autoplace is off, return internal
1481 * buffer
1482 * 3. Filesystem buffer is given and autoplace selected
1483 * put data from fs buffer into internal buffer and
1484 * retrun internal buffer
1485 *
1486 * Note: The internal buffer is filled with 0xff. This must
1487 * be done only once, when no autoplacement happens
1488 * Autoplacement sets the buffer dirty flag, which
1489 * forces the 0xff fill before using the buffer again.
1490 *
1491*/
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001492static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct nand_oobinfo *oobsel,
David Woodhousee0c7d762006-05-13 18:07:53 +01001493 int autoplace, int numpages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001495 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 int i, len, ofs;
1497
1498 /* Zero copy fs supplied buffer */
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001499 if (fsbuf && !autoplace)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 return fsbuf;
1501
1502 /* Check, if the buffer must be filled with ff again */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001503 if (chip->oobdirty) {
1504 memset(chip->oob_buf, 0xff, mtd->oobsize << (chip->phys_erase_shift - chip->page_shift));
1505 chip->oobdirty = 0;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001506 }
1507
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 /* If we have no autoplacement or no fs buffer use the internal one */
1509 if (!autoplace || !fsbuf)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001510 return chip->oob_buf;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001511
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 /* Walk through the pages and place the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001513 chip->oobdirty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 ofs = 0;
1515 while (numpages--) {
1516 for (i = 0, len = 0; len < mtd->oobavail; i++) {
1517 int to = ofs + oobsel->oobfree[i][0];
1518 int num = oobsel->oobfree[i][1];
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001519 memcpy(&chip->oob_buf[to], fsbuf, num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 len += num;
1521 fsbuf += num;
1522 }
1523 ofs += mtd->oobavail;
1524 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001525 return chip->oob_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526}
1527
Joern Engel28318772006-05-22 23:18:05 +02001528#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
1530/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001531 * nand_write - [MTD Interface] NAND write with ECC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 * @mtd: MTD device structure
1533 * @to: offset to write to
1534 * @len: number of bytes to write
1535 * @retlen: pointer to variable to store the number of written bytes
1536 * @buf: the data to write
1537 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 * NAND write with ECC
1539 */
Thomas Gleixner9223a452006-05-23 17:21:03 +02001540static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1541 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542{
1543 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
1544 int autoplace = 0, numpages, totalpages;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001545 struct nand_chip *chip = mtd->priv;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001546 uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001547 int ppblock = (1 << (chip->phys_erase_shift - chip->page_shift));
Thomas Gleixner9223a452006-05-23 17:21:03 +02001548 struct nand_oobinfo *oobsel = &mtd->oobinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
Thomas Gleixner9223a452006-05-23 17:21:03 +02001550 DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 /* Initialize retlen, in case of early exit */
1553 *retlen = 0;
1554
1555 /* Do not allow write past end of device */
1556 if ((to + len) > mtd->size) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001557 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 return -EINVAL;
1559 }
1560
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001561 /* reject writes, which are not page aligned */
David Woodhousee0c7d762006-05-13 18:07:53 +01001562 if (NOTALIGNED(to) || NOTALIGNED(len)) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001563 printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 return -EINVAL;
1565 }
1566
1567 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001568 nand_get_device(chip, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
1570 /* Calculate chipnr */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001571 chipnr = (int)(to >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001573 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574
1575 /* Check, if it is write protected */
1576 if (nand_check_wp(mtd))
1577 goto out;
1578
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 /* Autoplace of oob data ? Use the default placement scheme */
1580 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001581 oobsel = chip->autooob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 autoplace = 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001583 }
Thomas Gleixner90e260c2005-05-19 17:10:26 +01001584 if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
1585 autoplace = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
1587 /* Setup variables and oob buffer */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001588 totalpages = len >> chip->page_shift;
1589 page = (int)(to >> chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001591 if (page <= chip->pagebuf && chip->pagebuf < (page + totalpages))
1592 chip->pagebuf = -1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001593
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 /* Set it relative to chip */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001595 page &= chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 startpage = page;
1597 /* Calc number of pages we can write in one go */
David Woodhousee0c7d762006-05-13 18:07:53 +01001598 numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages);
1599 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001600 bufstart = (uint8_t *) buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
1602 /* Loop until all data is written */
1603 while (written < len) {
1604
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001605 chip->data_poi = (uint8_t *) &buf[written];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 /* Write one page. If this is the last page to write
1607 * or the last page in this block, then use the
1608 * real pageprogram command, else select cached programming
1609 * if supported by the chip.
1610 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001611 ret = nand_write_page(mtd, chip, page, &oobbuf[oob], oobsel, (--numpages > 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001613 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 /* Next oob page */
1617 oob += mtd->oobsize;
1618 /* Update written bytes count */
Joern Engel28318772006-05-22 23:18:05 +02001619 written += mtd->writesize;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001620 if (written == len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 goto cmp;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001622
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 /* Increment page address */
1624 page++;
1625
1626 /* Have we hit a block boundary ? Then we have to verify and
1627 * if verify is ok, we have to setup the oob buffer for
1628 * the next pages.
David Woodhousee0c7d762006-05-13 18:07:53 +01001629 */
1630 if (!(page & (ppblock - 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 int ofs;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001632 chip->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001633 ret = nand_verify_pages(mtd, this, startpage, page - startpage,
1634 oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 if (ret) {
Thomas Gleixner9223a452006-05-23 17:21:03 +02001636 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001638 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 *retlen = written;
1640
1641 ofs = autoplace ? mtd->oobavail : mtd->oobsize;
1642 if (eccbuf)
1643 eccbuf += (page - startpage) * ofs;
1644 totalpages -= page - startpage;
David Woodhousee0c7d762006-05-13 18:07:53 +01001645 numpages = min(totalpages, ppblock);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001646 page &= chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 startpage = page;
David Woodhousee0c7d762006-05-13 18:07:53 +01001648 oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages);
Todd Poynor868801e2005-11-05 03:21:15 +00001649 oob = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 /* Check, if we cross a chip boundary */
1651 if (!page) {
1652 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001653 chip->select_chip(mtd, -1);
1654 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 }
1656 }
1657 }
1658 /* Verify the remaining pages */
David Woodhousee0c7d762006-05-13 18:07:53 +01001659 cmp:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001660 chip->data_poi = bufstart;
David Woodhousee0c7d762006-05-13 18:07:53 +01001661 ret = nand_verify_pages(mtd, this, startpage, totalpages, oobbuf, oobsel, chipnr, (eccbuf != NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 if (!ret)
1663 *retlen = written;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001664 else
Thomas Gleixner9223a452006-05-23 17:21:03 +02001665 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
David Woodhousee0c7d762006-05-13 18:07:53 +01001667 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 /* Deselect and wake up anyone waiting on the device */
1669 nand_release_device(mtd);
1670
1671 return ret;
1672}
1673
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674/**
1675 * nand_write_oob - [MTD Interface] NAND write out-of-band
1676 * @mtd: MTD device structure
1677 * @to: offset to write to
1678 * @len: number of bytes to write
1679 * @retlen: pointer to variable to store the number of written bytes
1680 * @buf: the data to write
1681 *
1682 * NAND write out-of-band
1683 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +02001684static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685{
1686 int column, page, status, ret = -EIO, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001687 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688
David Woodhousee0c7d762006-05-13 18:07:53 +01001689 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690
1691 /* Shift to get page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001692 page = (int)(to >> chip->page_shift);
1693 chipnr = (int)(to >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
1695 /* Mask to get column */
1696 column = to & (mtd->oobsize - 1);
1697
1698 /* Initialize return length value */
1699 *retlen = 0;
1700
1701 /* Do not allow write past end of page */
1702 if ((column + len) > mtd->oobsize) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001703 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 return -EINVAL;
1705 }
1706
1707 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001708 nand_get_device(chip, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
1710 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001711 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712
1713 /* Reset the chip. Some chips (like the Toshiba TC5832DC found
1714 in one of my DiskOnChip 2000 test units) will clear the whole
1715 data page too if we don't do this. I have no clue why, but
1716 I seem to have 'fixed' it in the doc2000 driver in
1717 August 1999. dwmw2. */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001718 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719
1720 /* Check, if it is write protected */
1721 if (nand_check_wp(mtd))
1722 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001723
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001725 if (page == chip->pagebuf)
1726 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001728 if (NAND_MUST_PAD(chip)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 /* Write out desired data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001730 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 /* prepad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001732 chip->write_buf(mtd, ffchars, column);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 /* write data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001734 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 /* postpad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001736 chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 } else {
1738 /* Write out desired data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001739 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column, page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 /* write data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001741 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 }
1743 /* Send command to program the OOB data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001744 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001746 status = chip->waitfunc(mtd, chip, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747
1748 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001749 if (status & NAND_STATUS_FAIL) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001750 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 ret = -EIO;
1752 goto out;
1753 }
1754 /* Return happy */
1755 *retlen = len;
1756
1757#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1758 /* Send command to read back the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001759 chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001761 if (chip->verify_buf(mtd, buf, len)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001762 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 ret = -EIO;
1764 goto out;
1765 }
1766#endif
1767 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001768 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 /* Deselect and wake up anyone waiting on the device */
1770 nand_release_device(mtd);
1771
1772 return ret;
1773}
1774
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1777 * @mtd: MTD device structure
1778 * @page: the page address of the block which will be erased
1779 *
1780 * Standard erase command for NAND chips
1781 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001782static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001784 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001786 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1787 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788}
1789
1790/**
1791 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1792 * @mtd: MTD device structure
1793 * @page: the page address of the block which will be erased
1794 *
1795 * AND multi block erase command function
1796 * Erase 4 consecutive blocks
1797 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001798static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001800 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001802 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1803 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1804 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1805 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1806 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807}
1808
1809/**
1810 * nand_erase - [MTD Interface] erase block(s)
1811 * @mtd: MTD device structure
1812 * @instr: erase instruction
1813 *
1814 * Erase one ore more blocks
1815 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001816static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817{
David Woodhousee0c7d762006-05-13 18:07:53 +01001818 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001820
David A. Marlin30f464b2005-01-17 18:35:25 +00001821#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001823 * nand_erase_nand - [Internal] erase block(s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 * @mtd: MTD device structure
1825 * @instr: erase instruction
1826 * @allowbbt: allow erasing the bbt area
1827 *
1828 * Erase one ore more blocks
1829 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001830int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
1831 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832{
1833 int page, len, status, pages_per_block, ret, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001834 struct nand_chip *chip = mtd->priv;
1835 int rewrite_bbt[NAND_MAX_CHIPS]={0};
1836 unsigned int bbt_masked_page = 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001838 DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
1839 (unsigned int)instr->addr, (unsigned int)instr->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840
1841 /* Start address must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001842 if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001843 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 return -EINVAL;
1845 }
1846
1847 /* Length must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001848 if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
1849 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1850 "Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 return -EINVAL;
1852 }
1853
1854 /* Do not allow erase past end of device */
1855 if ((instr->len + instr->addr) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001856 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1857 "Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 return -EINVAL;
1859 }
1860
1861 instr->fail_addr = 0xffffffff;
1862
1863 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001864 nand_get_device(chip, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
1866 /* Shift to get first page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001867 page = (int)(instr->addr >> chip->page_shift);
1868 chipnr = (int)(instr->addr >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
1870 /* Calculate pages in each block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001871 pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
1873 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001874 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 /* Check, if it is write protected */
1877 if (nand_check_wp(mtd)) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001878 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1879 "Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 instr->state = MTD_ERASE_FAILED;
1881 goto erase_exit;
1882 }
1883
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001884 /*
1885 * If BBT requires refresh, set the BBT page mask to see if the BBT
1886 * should be rewritten. Otherwise the mask is set to 0xffffffff which
1887 * can not be matched. This is also done when the bbt is actually
1888 * erased to avoid recusrsive updates
1889 */
1890 if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
1891 bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
David A. Marlin30f464b2005-01-17 18:35:25 +00001892
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 /* Loop through the pages */
1894 len = instr->len;
1895
1896 instr->state = MTD_ERASING;
1897
1898 while (len) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001899 /*
1900 * heck if we have a bad block, we do not erase bad blocks !
1901 */
1902 if (nand_block_checkbad(mtd, ((loff_t) page) <<
1903 chip->page_shift, 0, allowbbt)) {
1904 printk(KERN_WARNING "nand_erase: attempt to erase a "
1905 "bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 instr->state = MTD_ERASE_FAILED;
1907 goto erase_exit;
1908 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001909
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001910 /*
1911 * Invalidate the page cache, if we erase the block which
1912 * contains the current cached page
1913 */
1914 if (page <= chip->pagebuf && chip->pagebuf <
1915 (page + pages_per_block))
1916 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001918 chip->erase_cmd(mtd, page & chip->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001919
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001920 status = chip->waitfunc(mtd, chip, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001922 /*
1923 * See if operation failed and additional status checks are
1924 * available
1925 */
1926 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
1927 status = chip->errstat(mtd, chip, FL_ERASING,
1928 status, page);
David A. Marlin068e3c02005-01-24 03:07:46 +00001929
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001931 if (status & NAND_STATUS_FAIL) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001932 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1933 "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 instr->state = MTD_ERASE_FAILED;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001935 instr->fail_addr = (page << chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 goto erase_exit;
1937 }
David A. Marlin30f464b2005-01-17 18:35:25 +00001938
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001939 /*
1940 * If BBT requires refresh, set the BBT rewrite flag to the
1941 * page being erased
1942 */
1943 if (bbt_masked_page != 0xffffffff &&
1944 (page & BBT_PAGE_MASK) == bbt_masked_page)
1945 rewrite_bbt[chipnr] = (page << chip->page_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001946
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 /* Increment page address and decrement length */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001948 len -= (1 << chip->phys_erase_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 page += pages_per_block;
1950
1951 /* Check, if we cross a chip boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001952 if (len && !(page & chip->pagemask)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001954 chip->select_chip(mtd, -1);
1955 chip->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00001956
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001957 /*
1958 * If BBT requires refresh and BBT-PERCHIP, set the BBT
1959 * page mask to see if this BBT should be rewritten
1960 */
1961 if (bbt_masked_page != 0xffffffff &&
1962 (chip->bbt_td->options & NAND_BBT_PERCHIP))
1963 bbt_masked_page = chip->bbt_td->pages[chipnr] &
1964 BBT_PAGE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 }
1966 }
1967 instr->state = MTD_ERASE_DONE;
1968
David Woodhousee0c7d762006-05-13 18:07:53 +01001969 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970
1971 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
1972 /* Do call back function */
1973 if (!ret)
1974 mtd_erase_callback(instr);
1975
1976 /* Deselect and wake up anyone waiting on the device */
1977 nand_release_device(mtd);
1978
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001979 /*
1980 * If BBT requires refresh and erase was successful, rewrite any
1981 * selected bad block tables
1982 */
1983 if (bbt_masked_page == 0xffffffff || ret)
1984 return ret;
1985
1986 for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
1987 if (!rewrite_bbt[chipnr])
1988 continue;
1989 /* update the BBT for chip */
1990 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
1991 "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
1992 chip->bbt_td->pages[chipnr]);
1993 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00001994 }
1995
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 /* Return more or less happy */
1997 return ret;
1998}
1999
2000/**
2001 * nand_sync - [MTD Interface] sync
2002 * @mtd: MTD device structure
2003 *
2004 * Sync is actually a wait for chip ready function
2005 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002006static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002008 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
David Woodhousee0c7d762006-05-13 18:07:53 +01002010 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
2012 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002013 nand_get_device(chip, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01002015 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016}
2017
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002019 * nand_block_isbad - [MTD Interface] Check if block at offset is bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 * @mtd: MTD device structure
2021 * @ofs: offset relative to mtd start
2022 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002023static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024{
2025 /* Check for invalid offset */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002026 if (offs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002028
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002029 return nand_block_checkbad(mtd, offs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030}
2031
2032/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002033 * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 * @mtd: MTD device structure
2035 * @ofs: offset relative to mtd start
2036 */
David Woodhousee0c7d762006-05-13 18:07:53 +01002037static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002039 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 int ret;
2041
David Woodhousee0c7d762006-05-13 18:07:53 +01002042 if ((ret = nand_block_isbad(mtd, ofs))) {
2043 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 if (ret > 0)
2045 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01002046 return ret;
2047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002049 return chip->block_markbad(mtd, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050}
2051
2052/**
Vitaly Wool962034f2005-09-15 14:58:53 +01002053 * nand_suspend - [MTD Interface] Suspend the NAND flash
2054 * @mtd: MTD device structure
2055 */
2056static int nand_suspend(struct mtd_info *mtd)
2057{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002058 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01002059
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002060 return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01002061}
2062
2063/**
2064 * nand_resume - [MTD Interface] Resume the NAND flash
2065 * @mtd: MTD device structure
2066 */
2067static void nand_resume(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 if (chip->state == FL_PM_SUSPENDED)
Vitaly Wool962034f2005-09-15 14:58:53 +01002072 nand_release_device(mtd);
2073 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02002074 printk(KERN_ERR "nand_resume() called for a chip which is not "
2075 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01002076}
2077
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002078/*
2079 * Free allocated data structures
2080 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002081static void nand_free_kmem(struct nand_chip *chip)
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002082{
2083 /* Buffer allocated by nand_scan ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002084 if (chip->options & NAND_OOBBUF_ALLOC)
2085 kfree(chip->oob_buf);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002086 /* Buffer allocated by nand_scan ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002087 if (chip->options & NAND_DATABUF_ALLOC)
2088 kfree(chip->data_buf);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002089 /* Controller allocated by nand_scan ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002090 if (chip->options & NAND_CONTROLLER_ALLOC)
2091 kfree(chip->controller);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002092}
2093
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002094/*
2095 * Allocate buffers and data structures
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002097static int nand_allocate_kmem(struct mtd_info *mtd, struct nand_chip *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098{
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002099 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002101 if (!chip->oob_buf) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002102 len = mtd->oobsize <<
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002103 (chip->phys_erase_shift - chip->page_shift);
2104 chip->oob_buf = kmalloc(len, GFP_KERNEL);
2105 if (!chip->oob_buf)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002106 goto outerr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002107 chip->options |= NAND_OOBBUF_ALLOC;
David Woodhouse552d9202006-05-14 01:20:46 +01002108 }
2109
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002110 if (!chip->data_buf) {
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002111 len = mtd->writesize + mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002112 chip->data_buf = kmalloc(len, GFP_KERNEL);
2113 if (!chip->data_buf)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002114 goto outerr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002115 chip->options |= NAND_DATABUF_ALLOC;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002118 if (!chip->controller) {
2119 chip->controller = kzalloc(sizeof(struct nand_hw_control),
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002120 GFP_KERNEL);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002121 if (!chip->controller)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002122 goto outerr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002123 chip->options |= NAND_CONTROLLER_ALLOC;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002124 }
2125 return 0;
2126
2127 outerr:
2128 printk(KERN_ERR "nand_scan(): Cannot allocate buffers\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002129 nand_free_kmem(chip);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002130 return -ENOMEM;
2131}
2132
2133/*
2134 * Set default functions
2135 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002136static void nand_set_defaults(struct nand_chip *chip, int busw)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002137{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 /* check for proper chip_delay setup, set 20us if not */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002139 if (!chip->chip_delay)
2140 chip->chip_delay = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141
2142 /* check, if a user supplied command function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002143 if (chip->cmdfunc == NULL)
2144 chip->cmdfunc = nand_command;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
2146 /* check, if a user supplied wait function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002147 if (chip->waitfunc == NULL)
2148 chip->waitfunc = nand_wait;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002150 if (!chip->select_chip)
2151 chip->select_chip = nand_select_chip;
2152 if (!chip->read_byte)
2153 chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
2154 if (!chip->read_word)
2155 chip->read_word = nand_read_word;
2156 if (!chip->block_bad)
2157 chip->block_bad = nand_block_bad;
2158 if (!chip->block_markbad)
2159 chip->block_markbad = nand_default_block_markbad;
2160 if (!chip->write_buf)
2161 chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
2162 if (!chip->read_buf)
2163 chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
2164 if (!chip->verify_buf)
2165 chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
2166 if (!chip->scan_bbt)
2167 chip->scan_bbt = nand_default_bbt;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002168}
2169
2170/*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002171 * Get the flash and manufacturer id and lookup if the type is supported
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002172 */
2173static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002174 struct nand_chip *chip,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002175 int busw, int *maf_id)
2176{
2177 struct nand_flash_dev *type = NULL;
2178 int i, dev_id, maf_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
2180 /* Select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002181 chip->select_chip(mtd, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
2183 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002184 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185
2186 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002187 *maf_id = chip->read_byte(mtd);
2188 dev_id = chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002190 /* Lookup the flash id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002192 if (dev_id == nand_flash_ids[i].id) {
2193 type = &nand_flash_ids[i];
2194 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 }
2197
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002198 if (!type)
2199 return ERR_PTR(-ENODEV);
2200
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002201 chip->chipsize = nand_flash_ids[i].chipsize << 20;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002202
2203 /* Newer devices have all the information in additional id bytes */
2204 if (!nand_flash_ids[i].pagesize) {
2205 int extid;
2206 /* The 3rd id byte contains non relevant data ATM */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002207 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002208 /* The 4th id byte is the important one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002209 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002210 /* Calc pagesize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002211 mtd->writesize = 1024 << (extid & 0x3);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002212 extid >>= 2;
2213 /* Calc oobsize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002214 mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002215 extid >>= 2;
2216 /* Calc blocksize. Blocksize is multiples of 64KiB */
2217 mtd->erasesize = (64 * 1024) << (extid & 0x03);
2218 extid >>= 2;
2219 /* Get buswidth information */
2220 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
2221
2222 } else {
2223 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002224 * Old devices have chip data hardcoded in the device id table
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002225 */
2226 mtd->erasesize = nand_flash_ids[i].erasesize;
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02002227 mtd->writesize = nand_flash_ids[i].pagesize;
2228 mtd->oobsize = mtd->writesize / 32;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002229 busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
2230 }
2231
2232 /* Try to identify manufacturer */
2233 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
2234 if (nand_manuf_ids[maf_idx].id == *maf_id)
2235 break;
2236 }
2237
2238 /*
2239 * Check, if buswidth is correct. Hardware drivers should set
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002240 * chip correct !
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002241 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002242 if (busw != (chip->options & NAND_BUSWIDTH_16)) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002243 printk(KERN_INFO "NAND device: Manufacturer ID:"
2244 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2245 dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2246 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002247 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002248 busw ? 16 : 8);
2249 return ERR_PTR(-EINVAL);
2250 }
2251
2252 /* Calculate the address shift from the page size */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002253 chip->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002254 /* Convert chipsize to number of pages per chip -1. */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002255 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002256
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002257 chip->bbt_erase_shift = chip->phys_erase_shift =
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002258 ffs(mtd->erasesize) - 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002259 chip->chip_shift = ffs(chip->chipsize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002260
2261 /* Set the bad block position */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002262 chip->badblockpos = mtd->writesize > 512 ?
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002263 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
2264
2265 /* Get chip options, preserve non chip based options */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002266 chip->options &= ~NAND_CHIPOPTIONS_MSK;
2267 chip->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002268
2269 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002270 * Set chip as a default. Board drivers can override it, if necessary
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002271 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002272 chip->options |= NAND_NO_AUTOINCR;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002273
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002274 /* Check if chip is a not a samsung device. Do not clear the
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002275 * options for chips which are not having an extended id.
2276 */
2277 if (*maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002278 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002279
2280 /* Check for AND chips with 4 page planes */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002281 if (chip->options & NAND_4PAGE_ARRAY)
2282 chip->erase_cmd = multi_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002283 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002284 chip->erase_cmd = single_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002285
2286 /* Do not replace user supplied command function ! */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002287 if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
2288 chip->cmdfunc = nand_command_lp;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002289
2290 printk(KERN_INFO "NAND device: Manufacturer ID:"
2291 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
2292 nand_manuf_ids[maf_idx].name, type->name);
2293
2294 return type;
2295}
2296
2297/* module_text_address() isn't exported, and it's mostly a pointless
2298 test if this is a module _anyway_ -- they'd have to try _really_ hard
2299 to call us from in-kernel code if the core NAND support is modular. */
2300#ifdef MODULE
2301#define caller_is_module() (1)
2302#else
2303#define caller_is_module() \
2304 module_text_address((unsigned long)__builtin_return_address(0))
2305#endif
2306
2307/**
2308 * nand_scan - [NAND Interface] Scan for the NAND device
2309 * @mtd: MTD device structure
2310 * @maxchips: Number of chips to scan for
2311 *
2312 * This fills out all the uninitialized function pointers
2313 * with the defaults.
2314 * The flash ID is read and the mtd/chip structures are
2315 * filled with the appropriate values. Buffers are allocated if
2316 * they are not provided by the board driver
2317 * The mtd->owner field must be set to the module of the caller
2318 *
2319 */
2320int nand_scan(struct mtd_info *mtd, int maxchips)
2321{
2322 int i, busw, nand_maf_id;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002323 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002324 struct nand_flash_dev *type;
2325
2326 /* Many callers got this wrong, so check for it for a while... */
2327 if (!mtd->owner && caller_is_module()) {
2328 printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
2329 BUG();
2330 }
2331
2332 /* Get buswidth to select the correct functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002333 busw = chip->options & NAND_BUSWIDTH_16;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002334 /* Set the default functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002335 nand_set_defaults(chip, busw);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002336
2337 /* Read the flash type */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002338 type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002339
2340 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002341 printk(KERN_WARNING "No NAND device found!!!\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002342 chip->select_chip(mtd, -1);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002343 return PTR_ERR(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 }
2345
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002346 /* Check for a chip array */
David Woodhousee0c7d762006-05-13 18:07:53 +01002347 for (i = 1; i < maxchips; i++) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002348 chip->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002350 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002352 if (nand_maf_id != chip->read_byte(mtd) ||
2353 type->id != chip->read_byte(mtd))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 break;
2355 }
2356 if (i > 1)
2357 printk(KERN_INFO "%d NAND chips detected\n", i);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002358
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 /* Store the number of chips and calc total size for mtd */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002360 chip->numchips = i;
2361 mtd->size = i * chip->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002363 /* Allocate buffers and data structures */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002364 if (nand_allocate_kmem(mtd, chip))
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002365 return -ENOMEM;
2366
2367 /* Preset the internal oob buffer */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002368 memset(chip->oob_buf, 0xff,
2369 mtd->oobsize << (chip->phys_erase_shift - chip->page_shift));
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002370
2371 /*
2372 * If no default placement scheme is given, select an appropriate one
2373 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002374 if (!chip->autooob) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002375 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 case 8:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002377 chip->autooob = &nand_oob_8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 break;
2379 case 16:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002380 chip->autooob = &nand_oob_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 break;
2382 case 64:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002383 chip->autooob = &nand_oob_64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 break;
2385 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002386 printk(KERN_WARNING "No oob scheme defined for "
2387 "oobsize %d\n", mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 BUG();
2389 }
2390 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002391
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002392 /*
2393 * The number of bytes available for the filesystem to place fs
2394 * dependend oob data
2395 */
Thomas Gleixner998cf642005-04-01 08:21:48 +01002396 mtd->oobavail = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002397 for (i = 0; chip->autooob->oobfree[i][1]; i++)
2398 mtd->oobavail += chip->autooob->oobfree[i][1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002400 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002401 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2402 * selected and we have 256 byte pagesize fallback to software ECC
David Woodhousee0c7d762006-05-13 18:07:53 +01002403 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002404 switch (chip->ecc.mode) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002405 case NAND_ECC_HW:
2406 case NAND_ECC_HW_SYNDROME:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002407 if (!chip->ecc.calculate || !chip->ecc.correct ||
2408 !chip->ecc.hwctl) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002409 printk(KERN_WARNING "No ECC functions supplied, "
2410 "Hardware ECC not possible\n");
2411 BUG();
2412 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002413 if (mtd->writesize >= chip->ecc.size)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002414 break;
2415 printk(KERN_WARNING "%d byte HW ECC not possible on "
2416 "%d byte page size, fallback to SW ECC\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002417 chip->ecc.size, mtd->writesize);
2418 chip->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002420 case NAND_ECC_SOFT:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002421 chip->ecc.calculate = nand_calculate_ecc;
2422 chip->ecc.correct = nand_correct_data;
2423 chip->ecc.size = 256;
2424 chip->ecc.bytes = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002426
2427 case NAND_ECC_NONE:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002428 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2429 "This is not recommended !!\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002430 chip->ecc.size = mtd->writesize;
2431 chip->ecc.bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002434 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002435 chip->ecc.mode);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002436 BUG();
2437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002439 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002440 * Set the number of read / write steps for one page depending on ECC
2441 * mode
2442 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002443 chip->ecc.steps = mtd->writesize / chip->ecc.size;
2444 if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002445 printk(KERN_WARNING "Invalid ecc parameters\n");
2446 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002448
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 /* Initialize state, waitqueue and spinlock */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002450 chip->state = FL_READY;
2451 init_waitqueue_head(&chip->controller->wq);
2452 spin_lock_init(&chip->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453
2454 /* De-select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002455 chip->select_chip(mtd, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
2457 /* Invalidate the pagebuffer reference */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002458 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
2460 /* Fill in remaining MTD driver data */
2461 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002462 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 mtd->ecctype = MTD_ECC_SW;
2464 mtd->erase = nand_erase;
2465 mtd->point = NULL;
2466 mtd->unpoint = NULL;
2467 mtd->read = nand_read;
2468 mtd->write = nand_write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 mtd->read_oob = nand_read_oob;
2470 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 mtd->sync = nand_sync;
2472 mtd->lock = NULL;
2473 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002474 mtd->suspend = nand_suspend;
2475 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 mtd->block_isbad = nand_block_isbad;
2477 mtd->block_markbad = nand_block_markbad;
2478
2479 /* and make the autooob the default one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002480 memcpy(&mtd->oobinfo, chip->autooob, sizeof(mtd->oobinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002482 /* Check, if we should skip the bad block table scan */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002483 if (chip->options & NAND_SKIP_BBTSCAN)
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002484 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
2486 /* Build bad block table */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002487 return chip->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488}
2489
2490/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002491 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 * @mtd: MTD device structure
2493*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002494void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002496 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
2498#ifdef CONFIG_MTD_PARTITIONS
2499 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002500 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501#endif
2502 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002503 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504
Jesper Juhlfa671642005-11-07 01:01:27 -08002505 /* Free bad block table memory */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002506 kfree(chip->bbt);
Thomas Gleixnera36ed292006-05-23 11:37:03 +02002507 /* Free buffers */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002508 nand_free_kmem(chip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509}
2510
David Woodhousee0c7d762006-05-13 18:07:53 +01002511EXPORT_SYMBOL_GPL(nand_scan);
2512EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002513
2514static int __init nand_base_init(void)
2515{
2516 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2517 return 0;
2518}
2519
2520static void __exit nand_base_exit(void)
2521{
2522 led_trigger_unregister_simple(nand_led_trigger);
2523}
2524
2525module_init(nand_base_init);
2526module_exit(nand_base_exit);
2527
David Woodhousee0c7d762006-05-13 18:07:53 +01002528MODULE_LICENSE("GPL");
2529MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2530MODULE_DESCRIPTION("Generic NAND flash driver code");