blob: 023224dd12eb56c7f01b054e9bd545aea3c653a0 [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
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020091static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +020092 size_t *retlen, const uint8_t *buf);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +020093static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020094 int new_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Thomas Gleixnerd470a972006-05-23 23:48:57 +020096/*
97 * For devices which display every fart in the system on a seperate LED. Is
98 * compiled away when LED support is disabled.
99 */
100DEFINE_LED_TRIGGER(nand_led_trigger);
101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102/**
103 * nand_release_device - [GENERIC] release chip
104 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000105 *
106 * Deselect, release chip lock and wake up anyone waiting on the device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100108static void nand_release_device(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200110 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
112 /* De-select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200113 chip->select_chip(mtd, -1);
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100114
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200115 /* Release the controller and the chip */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200116 spin_lock(&chip->controller->lock);
117 chip->controller->active = NULL;
118 chip->state = FL_READY;
119 wake_up(&chip->controller->wq);
120 spin_unlock(&chip->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121}
122
123/**
124 * nand_read_byte - [DEFAULT] read one byte from the chip
125 * @mtd: MTD device structure
126 *
127 * Default read function for 8bit buswith
128 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200129static uint8_t nand_read_byte(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200131 struct nand_chip *chip = mtd->priv;
132 return readb(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133}
134
135/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
137 * @mtd: MTD device structure
138 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000139 * Default read function for 16bit buswith with
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 * endianess conversion
141 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200142static uint8_t nand_read_byte16(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200144 struct nand_chip *chip = mtd->priv;
145 return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146}
147
148/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 * nand_read_word - [DEFAULT] read one word from the chip
150 * @mtd: MTD device structure
151 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000152 * Default read function for 16bit buswith without
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 * endianess conversion
154 */
155static u16 nand_read_word(struct mtd_info *mtd)
156{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200157 struct nand_chip *chip = mtd->priv;
158 return readw(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159}
160
161/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 * nand_select_chip - [DEFAULT] control CE line
163 * @mtd: MTD device structure
164 * @chip: chipnumber to select, -1 for deselect
165 *
166 * Default select function for 1 chip devices.
167 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200168static void nand_select_chip(struct mtd_info *mtd, int chipnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200170 struct nand_chip *chip = mtd->priv;
171
172 switch (chipnr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 case -1:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200174 chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 break;
176 case 0:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 break;
178
179 default:
180 BUG();
181 }
182}
183
184/**
185 * nand_write_buf - [DEFAULT] write buffer to chip
186 * @mtd: MTD device structure
187 * @buf: data buffer
188 * @len: number of bytes to write
189 *
190 * Default write function for 8bit buswith
191 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200192static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193{
194 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200195 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
David Woodhousee0c7d762006-05-13 18:07:53 +0100197 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200198 writeb(buf[i], chip->IO_ADDR_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199}
200
201/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000202 * nand_read_buf - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 * @mtd: MTD device structure
204 * @buf: buffer to store date
205 * @len: number of bytes to read
206 *
207 * Default read function for 8bit buswith
208 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200209static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210{
211 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200212 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
David Woodhousee0c7d762006-05-13 18:07:53 +0100214 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200215 buf[i] = readb(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216}
217
218/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000219 * nand_verify_buf - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 * @mtd: MTD device structure
221 * @buf: buffer containing the data to compare
222 * @len: number of bytes to compare
223 *
224 * Default verify function for 8bit buswith
225 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200226static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227{
228 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200229 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
David Woodhousee0c7d762006-05-13 18:07:53 +0100231 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200232 if (buf[i] != readb(chip->IO_ADDR_R))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 return 0;
235}
236
237/**
238 * nand_write_buf16 - [DEFAULT] write buffer to chip
239 * @mtd: MTD device structure
240 * @buf: data buffer
241 * @len: number of bytes to write
242 *
243 * Default write function for 16bit buswith
244 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200245static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246{
247 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200248 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 u16 *p = (u16 *) buf;
250 len >>= 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000251
David Woodhousee0c7d762006-05-13 18:07:53 +0100252 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200253 writew(p[i], chip->IO_ADDR_W);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255}
256
257/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000258 * nand_read_buf16 - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 * @mtd: MTD device structure
260 * @buf: buffer to store date
261 * @len: number of bytes to read
262 *
263 * Default read function for 16bit buswith
264 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200265static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266{
267 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200268 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 u16 *p = (u16 *) buf;
270 len >>= 1;
271
David Woodhousee0c7d762006-05-13 18:07:53 +0100272 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200273 p[i] = readw(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274}
275
276/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000277 * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 * @mtd: MTD device structure
279 * @buf: buffer containing the data to compare
280 * @len: number of bytes to compare
281 *
282 * Default verify function for 16bit buswith
283 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200284static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285{
286 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200287 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 u16 *p = (u16 *) buf;
289 len >>= 1;
290
David Woodhousee0c7d762006-05-13 18:07:53 +0100291 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200292 if (p[i] != readw(chip->IO_ADDR_R))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 return -EFAULT;
294
295 return 0;
296}
297
298/**
299 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
300 * @mtd: MTD device structure
301 * @ofs: offset from device start
302 * @getchip: 0, if the chip is already selected
303 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000304 * Check, if the block is bad.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 */
306static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
307{
308 int page, chipnr, res = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200309 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 u16 bad;
311
312 if (getchip) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200313 page = (int)(ofs >> chip->page_shift);
314 chipnr = (int)(ofs >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200316 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
318 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200319 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000320 } else
David Woodhousee0c7d762006-05-13 18:07:53 +0100321 page = (int)ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200323 if (chip->options & NAND_BUSWIDTH_16) {
324 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
325 page & chip->pagemask);
326 bad = cpu_to_le16(chip->read_word(mtd));
327 if (chip->badblockpos & 0x1)
Vitaly Wool49196f32005-11-02 16:54:46 +0000328 bad >>= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 if ((bad & 0xFF) != 0xff)
330 res = 1;
331 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200332 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
333 page & chip->pagemask);
334 if (chip->read_byte(mtd) != 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 res = 1;
336 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000337
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200338 if (getchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 nand_release_device(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000340
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 return res;
342}
343
344/**
345 * nand_default_block_markbad - [DEFAULT] mark a block bad
346 * @mtd: MTD device structure
347 * @ofs: offset from device start
348 *
349 * This is the default implementation, which can be overridden by
350 * a hardware specific driver.
351*/
352static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
353{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200354 struct nand_chip *chip = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200355 uint8_t buf[2] = { 0, 0 };
David Woodhousee0c7d762006-05-13 18:07:53 +0100356 size_t retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 int block;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000358
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 /* Get block number */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200360 block = ((int)ofs) >> chip->bbt_erase_shift;
361 if (chip->bbt)
362 chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
364 /* Do we have a flash based bad block table ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200365 if (chip->options & NAND_USE_FLASH_BBT)
David Woodhousee0c7d762006-05-13 18:07:53 +0100366 return nand_update_bbt(mtd, ofs);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000367
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 /* We write two bytes, so we dont have to mess with 16 bit access */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200369 ofs += mtd->oobsize + (chip->badblockpos & ~0x01);
David Woodhousee0c7d762006-05-13 18:07:53 +0100370 return nand_write_oob(mtd, ofs, 2, &retlen, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371}
372
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000373/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 * nand_check_wp - [GENERIC] check if the chip is write protected
375 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000376 * Check, if the device is write protected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000378 * The function expects, that the device is already selected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100380static int nand_check_wp(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200382 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 /* Check the WP bit */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200384 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
385 return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386}
387
388/**
389 * nand_block_checkbad - [GENERIC] Check if a block is marked bad
390 * @mtd: MTD device structure
391 * @ofs: offset from device start
392 * @getchip: 0, if the chip is already selected
393 * @allowbbt: 1, if its allowed to access the bbt area
394 *
395 * Check, if the block is bad. Either by reading the bad block table or
396 * calling of the scan function.
397 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200398static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
399 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200401 struct nand_chip *chip = mtd->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000402
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200403 if (!chip->bbt)
404 return chip->block_bad(mtd, ofs, getchip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 /* Return info from the table */
David Woodhousee0c7d762006-05-13 18:07:53 +0100407 return nand_isbad_bbt(mtd, ofs, allowbbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408}
409
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000410/*
Thomas Gleixner3b887752005-02-22 21:56:49 +0000411 * Wait for the ready pin, after a command
412 * The timeout is catched later.
413 */
414static void nand_wait_ready(struct mtd_info *mtd)
415{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200416 struct nand_chip *chip = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100417 unsigned long timeo = jiffies + 2;
Thomas Gleixner3b887752005-02-22 21:56:49 +0000418
Richard Purdie8fe833c2006-03-31 02:31:14 -0800419 led_trigger_event(nand_led_trigger, LED_FULL);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000420 /* wait until command is processed or timeout occures */
421 do {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200422 if (chip->dev_ready(mtd))
Richard Purdie8fe833c2006-03-31 02:31:14 -0800423 break;
Ingo Molnar8446f1d2005-09-06 15:16:27 -0700424 touch_softlockup_watchdog();
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000425 } while (time_before(jiffies, timeo));
Richard Purdie8fe833c2006-03-31 02:31:14 -0800426 led_trigger_event(nand_led_trigger, LED_OFF);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000427}
428
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429/**
430 * nand_command - [DEFAULT] Send command to NAND device
431 * @mtd: MTD device structure
432 * @command: the command to be sent
433 * @column: the column address for this command, -1 if none
434 * @page_addr: the page address for this command, -1 if none
435 *
436 * Send command to NAND device. This function is used for small page
437 * devices (256/512 Bytes per page)
438 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200439static void nand_command(struct mtd_info *mtd, unsigned int command,
440 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200442 register struct nand_chip *chip = mtd->priv;
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200443 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 /*
446 * Write out the command to the device.
447 */
448 if (command == NAND_CMD_SEQIN) {
449 int readcmd;
450
Joern Engel28318772006-05-22 23:18:05 +0200451 if (column >= mtd->writesize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 /* OOB area */
Joern Engel28318772006-05-22 23:18:05 +0200453 column -= mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 readcmd = NAND_CMD_READOOB;
455 } else if (column < 256) {
456 /* First 256 bytes --> READ0 */
457 readcmd = NAND_CMD_READ0;
458 } else {
459 column -= 256;
460 readcmd = NAND_CMD_READ1;
461 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200462 chip->cmd_ctrl(mtd, readcmd, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200463 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200465 chip->cmd_ctrl(mtd, command, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200467 /*
468 * Address cycle, when necessary
469 */
470 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
471 /* Serially input address */
472 if (column != -1) {
473 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200474 if (chip->options & NAND_BUSWIDTH_16)
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200475 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200476 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200477 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200479 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200480 chip->cmd_ctrl(mtd, page_addr, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200481 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200482 chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200483 /* One more address cycle for devices > 32MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200484 if (chip->chipsize > (32 << 20))
485 chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200486 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200487 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000488
489 /*
490 * program and erase have their own busy handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 * status and sequential in needs no delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100492 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 case NAND_CMD_PAGEPROG:
496 case NAND_CMD_ERASE1:
497 case NAND_CMD_ERASE2:
498 case NAND_CMD_SEQIN:
499 case NAND_CMD_STATUS:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200500 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 return;
502
503 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200504 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200506 udelay(chip->chip_delay);
507 chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200508 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200509 chip->cmd_ctrl(mtd,
510 NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200511 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 return;
513
David Woodhousee0c7d762006-05-13 18:07:53 +0100514 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000516 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 * If we don't have access to the busy pin, we apply the given
518 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100519 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200520 if (!chip->dev_ready) {
521 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 /* Apply this short delay always to ensure that we do wait tWB in
526 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100527 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000528
529 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530}
531
532/**
533 * nand_command_lp - [DEFAULT] Send command to NAND large page device
534 * @mtd: MTD device structure
535 * @command: the command to be sent
536 * @column: the column address for this command, -1 if none
537 * @page_addr: the page address for this command, -1 if none
538 *
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200539 * Send command to NAND device. This is the version for the new large page
540 * devices We dont have the separate regions as we have in the small page
541 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 *
543 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200544static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
545 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200547 register struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
549 /* Emulate NAND_CMD_READOOB */
550 if (command == NAND_CMD_READOOB) {
Joern Engel28318772006-05-22 23:18:05 +0200551 column += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 command = NAND_CMD_READ0;
553 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000554
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200555 /* Command latch cycle */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200556 chip->cmd_ctrl(mtd, command & 0xff,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200557 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
559 if (column != -1 || page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200560 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
562 /* Serially input address */
563 if (column != -1) {
564 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200565 if (chip->options & NAND_BUSWIDTH_16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200567 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200568 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200569 chip->cmd_ctrl(mtd, column >> 8, ctrl);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200572 chip->cmd_ctrl(mtd, page_addr, ctrl);
573 chip->cmd_ctrl(mtd, page_addr >> 8,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200574 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 /* One more address cycle for devices > 128MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200576 if (chip->chipsize > (128 << 20))
577 chip->cmd_ctrl(mtd, page_addr >> 16,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200578 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200581 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000582
583 /*
584 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000585 * status, sequential in, and deplete1 need no delay
586 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000588
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 case NAND_CMD_CACHEDPROG:
590 case NAND_CMD_PAGEPROG:
591 case NAND_CMD_ERASE1:
592 case NAND_CMD_ERASE2:
593 case NAND_CMD_SEQIN:
594 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000595 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return;
597
David Woodhousee0c7d762006-05-13 18:07:53 +0100598 /*
599 * read error status commands require only a short delay
600 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000601 case NAND_CMD_STATUS_ERROR:
602 case NAND_CMD_STATUS_ERROR0:
603 case NAND_CMD_STATUS_ERROR1:
604 case NAND_CMD_STATUS_ERROR2:
605 case NAND_CMD_STATUS_ERROR3:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200606 udelay(chip->chip_delay);
David A. Marlin30f464b2005-01-17 18:35:25 +0000607 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
609 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200610 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200612 udelay(chip->chip_delay);
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200613 chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
614 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
615 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
616 NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200617 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 return;
619
620 case NAND_CMD_READ0:
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200621 chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
622 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
623 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
624 NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000625
David Woodhousee0c7d762006-05-13 18:07:53 +0100626 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000628 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 * If we don't have access to the busy pin, we apply the given
630 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100631 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200632 if (!chip->dev_ready) {
633 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 /* Apply this short delay always to ensure that we do wait tWB in
639 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100640 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000641
642 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643}
644
645/**
646 * nand_get_device - [GENERIC] Get chip for selected access
647 * @this: the nand chip descriptor
648 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000649 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 *
651 * Get the device and lock it for exclusive access
652 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200653static int
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200654nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200656 spinlock_t *lock = &chip->controller->lock;
657 wait_queue_head_t *wq = &chip->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100658 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100659 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100660 spin_lock(lock);
661
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200663 /* Hardware controller shared among independend devices */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200664 if (!chip->controller->active)
665 chip->controller->active = chip;
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200666
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200667 if (chip->controller->active == chip && chip->state == FL_READY) {
668 chip->state = new_state;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100669 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100670 return 0;
671 }
672 if (new_state == FL_PM_SUSPENDED) {
673 spin_unlock(lock);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200674 return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100675 }
676 set_current_state(TASK_UNINTERRUPTIBLE);
677 add_wait_queue(wq, &wait);
678 spin_unlock(lock);
679 schedule();
680 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 goto retry;
682}
683
684/**
685 * nand_wait - [DEFAULT] wait until the command is done
686 * @mtd: MTD device structure
687 * @this: NAND chip structure
688 * @state: state to select the max. timeout value
689 *
690 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000691 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 * general NAND and SmartMedia specs
693 *
694*/
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200695static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
697
David Woodhousee0c7d762006-05-13 18:07:53 +0100698 unsigned long timeo = jiffies;
699 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000700
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100702 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100704 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Richard Purdie8fe833c2006-03-31 02:31:14 -0800706 led_trigger_event(nand_led_trigger, LED_FULL);
707
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 /* Apply this short delay always to ensure that we do wait tWB in
709 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100710 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200712 if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
713 chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000714 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200715 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000717 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 /* Check, if we were interrupted */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200719 if (chip->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 return 0;
721
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200722 if (chip->dev_ready) {
723 if (chip->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000724 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200726 if (chip->read_byte(mtd) & NAND_STATUS_READY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 break;
728 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000729 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800731 led_trigger_event(nand_led_trigger, LED_OFF);
732
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200733 status = (int)chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 return status;
735}
736
737/**
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200738 * nand_read_page_swecc - {REPLACABLE] software ecc based page read function
739 * @mtd: mtd info structure
740 * @chip: nand chip info structure
741 * @buf: buffer to store read data
David A. Marlin068e3c02005-01-24 03:07:46 +0000742 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200743static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
744 uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745{
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200746 int i, eccsize = chip->ecc.size;
747 int eccbytes = chip->ecc.bytes;
748 int eccsteps = chip->ecc.steps;
749 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200750 uint8_t *ecc_calc = chip->buffers.ecccalc;
751 uint8_t *ecc_code = chip->buffers.ecccode;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200752 int *eccpos = chip->autooob->eccpos;
753
754 chip->read_buf(mtd, buf, mtd->writesize);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200755 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200756
757 if (chip->ecc.mode == NAND_ECC_NONE)
758 return 0;
759
760 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
761 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
762
763 for (i = 0; i < chip->ecc.total; i++)
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200764 ecc_code[i] = chip->oob_poi[eccpos[i]];
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200765
766 eccsteps = chip->ecc.steps;
767 p = buf;
768
769 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
770 int stat;
771
772 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
773 if (stat == -1)
774 mtd->ecc_stats.failed++;
775 else
776 mtd->ecc_stats.corrected += stat;
777 }
778 return 0;
Thomas Gleixner22c60f52005-04-04 19:56:32 +0100779}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781/**
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200782 * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function
783 * @mtd: mtd info structure
784 * @chip: nand chip info structure
785 * @buf: buffer to store read data
786 *
787 * Not for syndrome calculating ecc controllers which need a special oob layout
788 */
789static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
790 uint8_t *buf)
791{
792 int i, eccsize = chip->ecc.size;
793 int eccbytes = chip->ecc.bytes;
794 int eccsteps = chip->ecc.steps;
795 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200796 uint8_t *ecc_calc = chip->buffers.ecccalc;
797 uint8_t *ecc_code = chip->buffers.ecccode;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200798 int *eccpos = chip->autooob->eccpos;
799
800 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
801 chip->ecc.hwctl(mtd, NAND_ECC_READ);
802 chip->read_buf(mtd, p, eccsize);
803 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
804 }
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200805 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200806
807 for (i = 0; i < chip->ecc.total; i++)
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200808 ecc_code[i] = chip->oob_poi[eccpos[i]];
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200809
810 eccsteps = chip->ecc.steps;
811 p = buf;
812
813 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
814 int stat;
815
816 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
817 if (stat == -1)
818 mtd->ecc_stats.failed++;
819 else
820 mtd->ecc_stats.corrected += stat;
821 }
822 return 0;
823}
824
825/**
826 * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
827 * @mtd: mtd info structure
828 * @chip: nand chip info structure
829 * @buf: buffer to store read data
830 *
831 * The hw generator calculates the error syndrome automatically. Therefor
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200832 * we need a special oob layout and handling.
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200833 */
834static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
835 uint8_t *buf)
836{
837 int i, eccsize = chip->ecc.size;
838 int eccbytes = chip->ecc.bytes;
839 int eccsteps = chip->ecc.steps;
840 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200841 uint8_t *oob = chip->oob_poi;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200842
843 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
844 int stat;
845
846 chip->ecc.hwctl(mtd, NAND_ECC_READ);
847 chip->read_buf(mtd, p, eccsize);
848
849 if (chip->ecc.prepad) {
850 chip->read_buf(mtd, oob, chip->ecc.prepad);
851 oob += chip->ecc.prepad;
852 }
853
854 chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
855 chip->read_buf(mtd, oob, eccbytes);
856 stat = chip->ecc.correct(mtd, p, oob, NULL);
857
858 if (stat == -1)
859 mtd->ecc_stats.failed++;
860 else
861 mtd->ecc_stats.corrected += stat;
862
863 oob += eccbytes;
864
865 if (chip->ecc.postpad) {
866 chip->read_buf(mtd, oob, chip->ecc.postpad);
867 oob += chip->ecc.postpad;
868 }
869 }
870
871 /* Calculate remaining oob bytes */
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200872 i = oob - chip->oob_poi;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200873 if (i)
874 chip->read_buf(mtd, oob, i);
875
876 return 0;
877}
878
879/**
880 * nand_do_read - [Internal] Read data with ECC
881 *
David A. Marlin068e3c02005-01-24 03:07:46 +0000882 * @mtd: MTD device structure
883 * @from: offset to read from
884 * @len: number of bytes to read
885 * @retlen: pointer to variable to store the number of read bytes
886 * @buf: the databuffer to put data
David A. Marlin068e3c02005-01-24 03:07:46 +0000887 *
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200888 * Internal function. Called with chip held.
David A. Marlin068e3c02005-01-24 03:07:46 +0000889 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200890int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
891 size_t *retlen, uint8_t *buf)
David A. Marlin068e3c02005-01-24 03:07:46 +0000892{
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200893 int chipnr, page, realpage, col, bytes, aligned;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200894 struct nand_chip *chip = mtd->priv;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200895 struct mtd_ecc_stats stats;
896 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
897 int sndcmd = 1;
898 int ret = 0;
899 uint32_t readlen = len;
900 uint8_t *bufpoi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200902 stats = mtd->ecc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200904 chipnr = (int)(from >> chip->chip_shift);
905 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200907 realpage = (int)(from >> chip->page_shift);
908 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200910 col = (int)(from & (mtd->writesize - 1));
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200911 chip->oob_poi = chip->buffers.oobrbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200913 while(1) {
914 bytes = min(mtd->writesize - col, readlen);
915 aligned = (bytes == mtd->writesize);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000916
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200917 /* Is the current page in the buffer ? */
918 if (realpage != chip->pagebuf) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200919 bufpoi = aligned ? buf : chip->buffers.databuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200921 if (likely(sndcmd)) {
922 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
923 sndcmd = 0;
924 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200926 /* Now read the page into the buffer */
927 ret = chip->ecc.read_page(mtd, chip, bufpoi);
928 if (ret < 0)
David Woodhousee0c7d762006-05-13 18:07:53 +0100929 break;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200930
931 /* Transfer not aligned data */
932 if (!aligned) {
933 chip->pagebuf = realpage;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200934 memcpy(buf, chip->buffers.databuf + col, bytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000936
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200937 if (!(chip->options & NAND_NO_READRDY)) {
938 /*
939 * Apply delay or wait for ready/busy pin. Do
940 * this before the AUTOINCR check, so no
941 * problems arise if a chip which does auto
942 * increment is marked as NOAUTOINCR by the
943 * board driver.
944 */
945 if (!chip->dev_ready)
946 udelay(chip->chip_delay);
947 else
948 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000950 } else
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200951 memcpy(buf, chip->buffers.databuf + col, bytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200953 buf += bytes;
954 readlen -= bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000955
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200956 if (!readlen)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000957 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
959 /* For subsequent reads align to page boundary. */
960 col = 0;
961 /* Increment page address */
962 realpage++;
963
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200964 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 /* Check, if we cross a chip boundary */
966 if (!page) {
967 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200968 chip->select_chip(mtd, -1);
969 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 }
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200971
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000972 /* Check, if the chip supports auto page increment
973 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +0100974 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200975 if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000976 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 }
978
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200979 *retlen = len - (size_t) readlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200981 if (ret)
982 return ret;
983
984 return mtd->ecc_stats.failed - stats.failed ? -EBADMSG : 0;
985}
986
987/**
988 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
989 * @mtd: MTD device structure
990 * @from: offset to read from
991 * @len: number of bytes to read
992 * @retlen: pointer to variable to store the number of read bytes
993 * @buf: the databuffer to put data
994 *
995 * Get hold of the chip and call nand_do_read
996 */
997static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
998 size_t *retlen, uint8_t *buf)
999{
1000 int ret;
1001
1002 *retlen = 0;
1003 /* Do not allow reads past end of device */
1004 if ((from + len) > mtd->size)
1005 return -EINVAL;
1006 if (!len)
1007 return 0;
1008
1009 nand_get_device(mtd->priv, mtd, FL_READING);
1010
1011 ret = nand_do_read(mtd, from, len, retlen, buf);
1012
1013 nand_release_device(mtd);
1014
1015 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016}
1017
1018/**
1019 * nand_read_oob - [MTD Interface] NAND read out-of-band
1020 * @mtd: MTD device structure
1021 * @from: offset to read from
1022 * @len: number of bytes to read
1023 * @retlen: pointer to variable to store the number of read bytes
1024 * @buf: the databuffer to put data
1025 *
1026 * NAND read out-of-band data from the spare area
1027 */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001028static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
1029 size_t *retlen, uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030{
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001031 int col, page, realpage, chipnr, sndcmd = 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001032 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001033 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1034 int readlen = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001036 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n",
1037 (unsigned int)from, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
1039 /* Initialize return length value */
1040 *retlen = 0;
1041
1042 /* Do not allow reads past end of device */
1043 if ((from + len) > mtd->size) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001044 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1045 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 return -EINVAL;
1047 }
1048
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001049 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001051 chipnr = (int)(from >> chip->chip_shift);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001052 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001054 /* Shift to get page */
1055 realpage = (int)(from >> chip->page_shift);
1056 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001058 /* Mask to get column */
1059 col = from & (mtd->oobsize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001061 while(1) {
1062 int bytes = min((int)(mtd->oobsize - col), readlen);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001063
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001064 if (likely(sndcmd)) {
1065 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page);
1066 sndcmd = 0;
1067 }
1068
1069 chip->read_buf(mtd, buf, bytes);
1070
1071 readlen -= bytes;
1072 if (!readlen)
1073 break;
1074
1075 if (!(chip->options & NAND_NO_READRDY)) {
1076 /*
1077 * Apply delay or wait for ready/busy pin. Do this
1078 * before the AUTOINCR check, so no problems arise if a
1079 * chip which does auto increment is marked as
1080 * NOAUTOINCR by the board driver.
Thomas Gleixner19870da2005-07-15 14:53:51 +01001081 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001082 if (!chip->dev_ready)
1083 udelay(chip->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001084 else
1085 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001087
1088 buf += bytes;
1089 bytes = mtd->oobsize;
1090 col = 0;
1091
1092 /* Increment page address */
1093 realpage++;
1094
1095 page = realpage & chip->pagemask;
1096 /* Check, if we cross a chip boundary */
1097 if (!page) {
1098 chipnr++;
1099 chip->select_chip(mtd, -1);
1100 chip->select_chip(mtd, chipnr);
1101 }
1102
1103 /* Check, if the chip supports auto page increment
1104 * or if we have hit a block boundary.
1105 */
1106 if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
1107 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 }
1109
1110 /* Deselect and wake up anyone waiting on the device */
1111 nand_release_device(mtd);
1112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 *retlen = len;
1114 return 0;
1115}
1116
1117/**
1118 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1119 * @mtd: MTD device structure
1120 * @buf: temporary buffer
1121 * @from: offset to read from
1122 * @len: number of bytes to read
1123 * @ooblen: number of oob data bytes to read
1124 *
1125 * Read raw data including oob into buffer
1126 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001127int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len,
1128 size_t ooblen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001130 struct nand_chip *chip = mtd->priv;
1131 int page = (int)(from >> chip->page_shift);
1132 int chipnr = (int)(from >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 int sndcmd = 1;
1134 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001135 int pagesize = mtd->writesize + mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001136 int blockcheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
1138 /* Do not allow reads past end of device */
1139 if ((from + len) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001140 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: "
1141 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 return -EINVAL;
1143 }
1144
1145 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001146 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001148 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 /* Add requested oob length */
1151 len += ooblen;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001152 blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001153
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 while (len) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001155 if (likely(sndcmd)) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001156 chip->cmdfunc(mtd, NAND_CMD_READ0, 0,
1157 page & chip->pagemask);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001158 sndcmd = 0;
1159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001161 chip->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
1163 len -= pagesize;
1164 cnt += pagesize;
1165 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001166
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001167 if (!(chip->options & NAND_NO_READRDY)) {
1168 if (!chip->dev_ready)
1169 udelay(chip->chip_delay);
1170 else
1171 nand_wait_ready(mtd);
1172 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001173
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001174 /*
1175 * Check, if the chip supports auto page increment or if we
1176 * cross a block boundary.
1177 */
1178 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 sndcmd = 1;
1180 }
1181
1182 /* Deselect and wake up anyone waiting on the device */
1183 nand_release_device(mtd);
1184 return 0;
1185}
1186
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001187/**
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001188 * nand_write_page_swecc - {REPLACABLE] software ecc based page write function
1189 * @mtd: mtd info structure
1190 * @chip: nand chip info structure
1191 * @buf: data buffer
1192 */
1193static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
1194 const uint8_t *buf)
1195{
1196 int i, eccsize = chip->ecc.size;
1197 int eccbytes = chip->ecc.bytes;
1198 int eccsteps = chip->ecc.steps;
1199 uint8_t *ecc_calc = chip->buffers.ecccalc;
1200 const uint8_t *p = buf;
1201 int *eccpos = chip->autooob->eccpos;
1202
1203 if (chip->ecc.mode != NAND_ECC_NONE) {
1204 /* Software ecc calculation */
1205 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
1206 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1207
1208 for (i = 0; i < chip->ecc.total; i++)
1209 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1210 }
1211
1212 chip->write_buf(mtd, buf, mtd->writesize);
1213 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1214}
1215
1216/**
1217 * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function
1218 * @mtd: mtd info structure
1219 * @chip: nand chip info structure
1220 * @buf: data buffer
1221 */
1222static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
1223 const uint8_t *buf)
1224{
1225 int i, eccsize = chip->ecc.size;
1226 int eccbytes = chip->ecc.bytes;
1227 int eccsteps = chip->ecc.steps;
1228 uint8_t *ecc_calc = chip->buffers.ecccalc;
1229 const uint8_t *p = buf;
1230 int *eccpos = chip->autooob->eccpos;
1231
1232 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
1233 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
David Woodhouse29da9ce2006-05-26 23:05:44 +01001234 chip->write_buf(mtd, p, eccsize);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001235 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1236 }
1237
1238 for (i = 0; i < chip->ecc.total; i++)
1239 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1240
1241 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1242}
1243
1244/**
1245 * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write
1246 * @mtd: mtd info structure
1247 * @chip: nand chip info structure
1248 * @buf: data buffer
1249 *
1250 * The hw generator calculates the error syndrome automatically. Therefor
1251 * we need a special oob layout and handling.
1252 */
1253static void nand_write_page_syndrome(struct mtd_info *mtd,
1254 struct nand_chip *chip, const uint8_t *buf)
1255{
1256 int i, eccsize = chip->ecc.size;
1257 int eccbytes = chip->ecc.bytes;
1258 int eccsteps = chip->ecc.steps;
1259 const uint8_t *p = buf;
1260 uint8_t *oob = chip->oob_poi;
1261
1262 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
1263
1264 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
1265 chip->write_buf(mtd, p, eccsize);
1266
1267 if (chip->ecc.prepad) {
1268 chip->write_buf(mtd, oob, chip->ecc.prepad);
1269 oob += chip->ecc.prepad;
1270 }
1271
1272 chip->ecc.calculate(mtd, p, oob);
1273 chip->write_buf(mtd, oob, eccbytes);
1274 oob += eccbytes;
1275
1276 if (chip->ecc.postpad) {
1277 chip->write_buf(mtd, oob, chip->ecc.postpad);
1278 oob += chip->ecc.postpad;
1279 }
1280 }
1281
1282 /* Calculate remaining oob bytes */
1283 i = oob - chip->oob_poi;
1284 if (i)
1285 chip->write_buf(mtd, oob, i);
1286}
1287
1288/**
1289 * nand_write_page - [INTERNAL] write one page
1290 * @mtd: MTD device structure
1291 * @chip: NAND chip descriptor
1292 * @buf: the data to write
1293 * @page: page number to write
1294 * @cached: cached programming
1295 */
1296static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
1297 const uint8_t *buf, int page, int cached)
1298{
1299 int status;
1300
1301 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
1302
1303 chip->ecc.write_page(mtd, chip, buf);
1304
1305 /*
1306 * Cached progamming disabled for now, Not sure if its worth the
1307 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
1308 */
1309 cached = 0;
1310
1311 if (!cached || !(chip->options & NAND_CACHEPRG)) {
1312
1313 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1314 status = chip->waitfunc(mtd, chip, FL_WRITING);
1315 /*
1316 * See if operation failed and additional status checks are
1317 * available
1318 */
1319 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
1320 status = chip->errstat(mtd, chip, FL_WRITING, status,
1321 page);
1322
1323 if (status & NAND_STATUS_FAIL)
1324 return -EIO;
1325 } else {
1326 chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
1327 status = chip->waitfunc(mtd, chip, FL_WRITING);
1328 }
1329
1330#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1331 /* Send command to read back the data */
1332 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1333
1334 if (chip->verify_buf(mtd, buf, mtd->writesize))
1335 return -EIO;
1336#endif
1337 return 0;
1338}
1339
1340#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
1341
1342/**
1343 * nand_write - [MTD Interface] NAND write with ECC
1344 * @mtd: MTD device structure
1345 * @to: offset to write to
1346 * @len: number of bytes to write
1347 * @retlen: pointer to variable to store the number of written bytes
1348 * @buf: the data to write
1349 *
1350 * NAND write with ECC
1351 */
1352static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1353 size_t *retlen, const uint8_t *buf)
1354{
1355 int chipnr, realpage, page, blockmask;
1356 struct nand_chip *chip = mtd->priv;
1357 uint32_t writelen = len;
1358 int bytes = mtd->writesize;
1359 int ret = -EIO;
1360
1361 *retlen = 0;
1362
1363 /* Do not allow write past end of device */
1364 if ((to + len) > mtd->size) {
1365 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: "
1366 "Attempt to write past end of page\n");
1367 return -EINVAL;
1368 }
1369
1370 /* reject writes, which are not page aligned */
1371 if (NOTALIGNED(to) || NOTALIGNED(len)) {
1372 printk(KERN_NOTICE "nand_write: "
1373 "Attempt to write not page aligned data\n");
1374 return -EINVAL;
1375 }
1376
1377 if (!len)
1378 return 0;
1379
1380 nand_get_device(chip, mtd, FL_WRITING);
1381
1382 /* Check, if it is write protected */
1383 if (nand_check_wp(mtd))
1384 goto out;
1385
1386 chipnr = (int)(to >> chip->chip_shift);
1387 chip->select_chip(mtd, chipnr);
1388
1389 realpage = (int)(to >> chip->page_shift);
1390 page = realpage & chip->pagemask;
1391 blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1392
1393 /* Invalidate the page cache, when we write to the cached page */
1394 if (to <= (chip->pagebuf << chip->page_shift) &&
1395 (chip->pagebuf << chip->page_shift) < (to + len))
1396 chip->pagebuf = -1;
1397
1398 chip->oob_poi = chip->buffers.oobwbuf;
1399
1400 while(1) {
1401 int cached = writelen > bytes && page != blockmask;
1402
1403 ret = nand_write_page(mtd, chip, buf, page, cached);
1404 if (ret)
1405 break;
1406
1407 writelen -= bytes;
1408 if (!writelen)
1409 break;
1410
1411 buf += bytes;
1412 realpage++;
1413
1414 page = realpage & chip->pagemask;
1415 /* Check, if we cross a chip boundary */
1416 if (!page) {
1417 chipnr++;
1418 chip->select_chip(mtd, -1);
1419 chip->select_chip(mtd, chipnr);
1420 }
1421 }
1422 out:
1423 *retlen = len - writelen;
1424 nand_release_device(mtd);
1425 return ret;
1426}
1427
1428/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001429 * nand_write_raw - [GENERIC] Write raw data including oob
1430 * @mtd: MTD device structure
1431 * @buf: source buffer
1432 * @to: offset to write to
1433 * @len: number of bytes to write
1434 * @buf: source buffer
1435 * @oob: oob buffer
1436 *
1437 * Write raw data including oob
1438 */
1439int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001440 const uint8_t *buf, uint8_t *oob)
Thomas Gleixner9223a452006-05-23 17:21:03 +02001441{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001442 struct nand_chip *chip = mtd->priv;
1443 int page = (int)(to >> chip->page_shift);
1444 int chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001445 int ret;
1446
1447 *retlen = 0;
1448
1449 /* Do not allow writes past end of device */
1450 if ((to + len) > mtd->size) {
1451 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1452 "beyond end of device\n");
1453 return -EINVAL;
1454 }
1455
1456 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001457 nand_get_device(chip, mtd, FL_WRITING);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001458
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001459 chip->select_chip(mtd, chipnr);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001460 chip->oob_poi = oob;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001461
1462 while (len != *retlen) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001463 ret = nand_write_page(mtd, chip, buf, page, 0);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001464 if (ret)
1465 return ret;
1466 page++;
1467 *retlen += mtd->writesize;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001468 buf += mtd->writesize;
1469 chip->oob_poi += mtd->oobsize;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001470 }
1471
1472 /* Deselect and wake up anyone waiting on the device */
1473 nand_release_device(mtd);
1474 return 0;
1475}
Thomas Gleixner38217202006-05-23 22:33:52 +02001476EXPORT_SYMBOL_GPL(nand_write_raw);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001477
1478/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 * nand_write_oob - [MTD Interface] NAND write out-of-band
1480 * @mtd: MTD device structure
1481 * @to: offset to write to
1482 * @len: number of bytes to write
1483 * @retlen: pointer to variable to store the number of written bytes
1484 * @buf: the data to write
1485 *
1486 * NAND write out-of-band
1487 */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001488static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1489 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490{
1491 int column, page, status, ret = -EIO, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001492 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001494 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1495 (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496
1497 /* Initialize return length value */
1498 *retlen = 0;
1499
1500 /* Do not allow write past end of page */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001501 column = to & (mtd->oobsize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 if ((column + len) > mtd->oobsize) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001503 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1504 "Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 return -EINVAL;
1506 }
1507
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001508 nand_get_device(chip, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001510 chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001511 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001513 /* Shift to get page */
1514 page = (int)(to >> chip->page_shift);
1515
1516 /*
1517 * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
1518 * of my DiskOnChip 2000 test units) will clear the whole data page too
1519 * if we don't do this. I have no clue why, but I seem to have 'fixed'
1520 * it in the doc2000 driver in August 1999. dwmw2.
1521 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001522 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
1524 /* Check, if it is write protected */
1525 if (nand_check_wp(mtd))
1526 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001527
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001529 if (page == chip->pagebuf)
1530 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001532 if (NAND_MUST_PAD(chip)) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001533 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
1534 page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 /* prepad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001536 chip->write_buf(mtd, ffchars, column);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 /* write data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001538 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 /* postpad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001540 chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 } else {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001542 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column,
1543 page & chip->pagemask);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001544 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 }
1546 /* Send command to program the OOB data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001547 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001549 status = chip->waitfunc(mtd, chip, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
1551 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001552 if (status & NAND_STATUS_FAIL) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001553 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1554 "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 ret = -EIO;
1556 goto out;
1557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 *retlen = len;
1559
1560#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1561 /* Send command to read back the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001562 chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001564 if (chip->verify_buf(mtd, buf, len)) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001565 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1566 "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 ret = -EIO;
1568 goto out;
1569 }
1570#endif
1571 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001572 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 /* Deselect and wake up anyone waiting on the device */
1574 nand_release_device(mtd);
1575
1576 return ret;
1577}
1578
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1581 * @mtd: MTD device structure
1582 * @page: the page address of the block which will be erased
1583 *
1584 * Standard erase command for NAND chips
1585 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001586static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001588 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001590 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1591 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592}
1593
1594/**
1595 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1596 * @mtd: MTD device structure
1597 * @page: the page address of the block which will be erased
1598 *
1599 * AND multi block erase command function
1600 * Erase 4 consecutive blocks
1601 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001602static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001604 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001606 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1607 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1608 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1609 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1610 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611}
1612
1613/**
1614 * nand_erase - [MTD Interface] erase block(s)
1615 * @mtd: MTD device structure
1616 * @instr: erase instruction
1617 *
1618 * Erase one ore more blocks
1619 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001620static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621{
David Woodhousee0c7d762006-05-13 18:07:53 +01001622 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001624
David A. Marlin30f464b2005-01-17 18:35:25 +00001625#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001627 * nand_erase_nand - [Internal] erase block(s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 * @mtd: MTD device structure
1629 * @instr: erase instruction
1630 * @allowbbt: allow erasing the bbt area
1631 *
1632 * Erase one ore more blocks
1633 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001634int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
1635 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636{
1637 int page, len, status, pages_per_block, ret, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001638 struct nand_chip *chip = mtd->priv;
1639 int rewrite_bbt[NAND_MAX_CHIPS]={0};
1640 unsigned int bbt_masked_page = 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001642 DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
1643 (unsigned int)instr->addr, (unsigned int)instr->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645 /* Start address must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001646 if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001647 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 return -EINVAL;
1649 }
1650
1651 /* Length must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001652 if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
1653 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1654 "Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 return -EINVAL;
1656 }
1657
1658 /* Do not allow erase past end of device */
1659 if ((instr->len + instr->addr) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001660 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1661 "Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 return -EINVAL;
1663 }
1664
1665 instr->fail_addr = 0xffffffff;
1666
1667 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001668 nand_get_device(chip, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670 /* Shift to get first page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001671 page = (int)(instr->addr >> chip->page_shift);
1672 chipnr = (int)(instr->addr >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
1674 /* Calculate pages in each block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001675 pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
1677 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001678 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 /* Check, if it is write protected */
1681 if (nand_check_wp(mtd)) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001682 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1683 "Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 instr->state = MTD_ERASE_FAILED;
1685 goto erase_exit;
1686 }
1687
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001688 /*
1689 * If BBT requires refresh, set the BBT page mask to see if the BBT
1690 * should be rewritten. Otherwise the mask is set to 0xffffffff which
1691 * can not be matched. This is also done when the bbt is actually
1692 * erased to avoid recusrsive updates
1693 */
1694 if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
1695 bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
David A. Marlin30f464b2005-01-17 18:35:25 +00001696
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 /* Loop through the pages */
1698 len = instr->len;
1699
1700 instr->state = MTD_ERASING;
1701
1702 while (len) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001703 /*
1704 * heck if we have a bad block, we do not erase bad blocks !
1705 */
1706 if (nand_block_checkbad(mtd, ((loff_t) page) <<
1707 chip->page_shift, 0, allowbbt)) {
1708 printk(KERN_WARNING "nand_erase: attempt to erase a "
1709 "bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 instr->state = MTD_ERASE_FAILED;
1711 goto erase_exit;
1712 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001713
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001714 /*
1715 * Invalidate the page cache, if we erase the block which
1716 * contains the current cached page
1717 */
1718 if (page <= chip->pagebuf && chip->pagebuf <
1719 (page + pages_per_block))
1720 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001722 chip->erase_cmd(mtd, page & chip->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001723
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001724 status = chip->waitfunc(mtd, chip, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001726 /*
1727 * See if operation failed and additional status checks are
1728 * available
1729 */
1730 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
1731 status = chip->errstat(mtd, chip, FL_ERASING,
1732 status, page);
David A. Marlin068e3c02005-01-24 03:07:46 +00001733
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001735 if (status & NAND_STATUS_FAIL) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001736 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1737 "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 instr->state = MTD_ERASE_FAILED;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001739 instr->fail_addr = (page << chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 goto erase_exit;
1741 }
David A. Marlin30f464b2005-01-17 18:35:25 +00001742
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001743 /*
1744 * If BBT requires refresh, set the BBT rewrite flag to the
1745 * page being erased
1746 */
1747 if (bbt_masked_page != 0xffffffff &&
1748 (page & BBT_PAGE_MASK) == bbt_masked_page)
1749 rewrite_bbt[chipnr] = (page << chip->page_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 /* Increment page address and decrement length */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001752 len -= (1 << chip->phys_erase_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 page += pages_per_block;
1754
1755 /* Check, if we cross a chip boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001756 if (len && !(page & chip->pagemask)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001758 chip->select_chip(mtd, -1);
1759 chip->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00001760
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001761 /*
1762 * If BBT requires refresh and BBT-PERCHIP, set the BBT
1763 * page mask to see if this BBT should be rewritten
1764 */
1765 if (bbt_masked_page != 0xffffffff &&
1766 (chip->bbt_td->options & NAND_BBT_PERCHIP))
1767 bbt_masked_page = chip->bbt_td->pages[chipnr] &
1768 BBT_PAGE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 }
1770 }
1771 instr->state = MTD_ERASE_DONE;
1772
David Woodhousee0c7d762006-05-13 18:07:53 +01001773 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
1775 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
1776 /* Do call back function */
1777 if (!ret)
1778 mtd_erase_callback(instr);
1779
1780 /* Deselect and wake up anyone waiting on the device */
1781 nand_release_device(mtd);
1782
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001783 /*
1784 * If BBT requires refresh and erase was successful, rewrite any
1785 * selected bad block tables
1786 */
1787 if (bbt_masked_page == 0xffffffff || ret)
1788 return ret;
1789
1790 for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
1791 if (!rewrite_bbt[chipnr])
1792 continue;
1793 /* update the BBT for chip */
1794 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
1795 "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
1796 chip->bbt_td->pages[chipnr]);
1797 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00001798 }
1799
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 /* Return more or less happy */
1801 return ret;
1802}
1803
1804/**
1805 * nand_sync - [MTD Interface] sync
1806 * @mtd: MTD device structure
1807 *
1808 * Sync is actually a wait for chip ready function
1809 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001810static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001812 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
David Woodhousee0c7d762006-05-13 18:07:53 +01001814 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
1816 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001817 nand_get_device(chip, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01001819 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820}
1821
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001823 * nand_block_isbad - [MTD Interface] Check if block at offset is bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 * @mtd: MTD device structure
1825 * @ofs: offset relative to mtd start
1826 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001827static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
1829 /* Check for invalid offset */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001830 if (offs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001832
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001833 return nand_block_checkbad(mtd, offs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834}
1835
1836/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001837 * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 * @mtd: MTD device structure
1839 * @ofs: offset relative to mtd start
1840 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001841static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001843 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 int ret;
1845
David Woodhousee0c7d762006-05-13 18:07:53 +01001846 if ((ret = nand_block_isbad(mtd, ofs))) {
1847 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 if (ret > 0)
1849 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001850 return ret;
1851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001853 return chip->block_markbad(mtd, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854}
1855
1856/**
Vitaly Wool962034f2005-09-15 14:58:53 +01001857 * nand_suspend - [MTD Interface] Suspend the NAND flash
1858 * @mtd: MTD device structure
1859 */
1860static int nand_suspend(struct mtd_info *mtd)
1861{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001862 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01001863
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001864 return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01001865}
1866
1867/**
1868 * nand_resume - [MTD Interface] Resume the NAND flash
1869 * @mtd: MTD device structure
1870 */
1871static void nand_resume(struct mtd_info *mtd)
1872{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001873 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01001874
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001875 if (chip->state == FL_PM_SUSPENDED)
Vitaly Wool962034f2005-09-15 14:58:53 +01001876 nand_release_device(mtd);
1877 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02001878 printk(KERN_ERR "nand_resume() called for a chip which is not "
1879 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01001880}
1881
Thomas Gleixnera36ed292006-05-23 11:37:03 +02001882/*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001883 * Set default functions
1884 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001885static void nand_set_defaults(struct nand_chip *chip, int busw)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001886{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 /* check for proper chip_delay setup, set 20us if not */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001888 if (!chip->chip_delay)
1889 chip->chip_delay = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890
1891 /* check, if a user supplied command function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001892 if (chip->cmdfunc == NULL)
1893 chip->cmdfunc = nand_command;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894
1895 /* check, if a user supplied wait function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001896 if (chip->waitfunc == NULL)
1897 chip->waitfunc = nand_wait;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001899 if (!chip->select_chip)
1900 chip->select_chip = nand_select_chip;
1901 if (!chip->read_byte)
1902 chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
1903 if (!chip->read_word)
1904 chip->read_word = nand_read_word;
1905 if (!chip->block_bad)
1906 chip->block_bad = nand_block_bad;
1907 if (!chip->block_markbad)
1908 chip->block_markbad = nand_default_block_markbad;
1909 if (!chip->write_buf)
1910 chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
1911 if (!chip->read_buf)
1912 chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
1913 if (!chip->verify_buf)
1914 chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
1915 if (!chip->scan_bbt)
1916 chip->scan_bbt = nand_default_bbt;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001917
1918 if (!chip->controller) {
1919 chip->controller = &chip->hwcontrol;
1920 spin_lock_init(&chip->controller->lock);
1921 init_waitqueue_head(&chip->controller->wq);
1922 }
1923
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001924}
1925
1926/*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001927 * Get the flash and manufacturer id and lookup if the type is supported
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001928 */
1929static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001930 struct nand_chip *chip,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001931 int busw, int *maf_id)
1932{
1933 struct nand_flash_dev *type = NULL;
1934 int i, dev_id, maf_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
1936 /* Select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001937 chip->select_chip(mtd, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
1939 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001940 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
1942 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001943 *maf_id = chip->read_byte(mtd);
1944 dev_id = chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001946 /* Lookup the flash id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001948 if (dev_id == nand_flash_ids[i].id) {
1949 type = &nand_flash_ids[i];
1950 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 }
1953
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001954 if (!type)
1955 return ERR_PTR(-ENODEV);
1956
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02001957 if (!mtd->name)
1958 mtd->name = type->name;
1959
1960 chip->chipsize = type->chipsize << 20;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001961
1962 /* Newer devices have all the information in additional id bytes */
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02001963 if (!type->pagesize) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001964 int extid;
1965 /* The 3rd id byte contains non relevant data ATM */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001966 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001967 /* The 4th id byte is the important one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001968 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001969 /* Calc pagesize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001970 mtd->writesize = 1024 << (extid & 0x3);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001971 extid >>= 2;
1972 /* Calc oobsize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001973 mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001974 extid >>= 2;
1975 /* Calc blocksize. Blocksize is multiples of 64KiB */
1976 mtd->erasesize = (64 * 1024) << (extid & 0x03);
1977 extid >>= 2;
1978 /* Get buswidth information */
1979 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
1980
1981 } else {
1982 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001983 * Old devices have chip data hardcoded in the device id table
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001984 */
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02001985 mtd->erasesize = type->erasesize;
1986 mtd->writesize = type->pagesize;
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001987 mtd->oobsize = mtd->writesize / 32;
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02001988 busw = type->options & NAND_BUSWIDTH_16;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001989 }
1990
1991 /* Try to identify manufacturer */
1992 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
1993 if (nand_manuf_ids[maf_idx].id == *maf_id)
1994 break;
1995 }
1996
1997 /*
1998 * Check, if buswidth is correct. Hardware drivers should set
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001999 * chip correct !
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002000 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002001 if (busw != (chip->options & NAND_BUSWIDTH_16)) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002002 printk(KERN_INFO "NAND device: Manufacturer ID:"
2003 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2004 dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2005 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002006 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002007 busw ? 16 : 8);
2008 return ERR_PTR(-EINVAL);
2009 }
2010
2011 /* Calculate the address shift from the page size */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002012 chip->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002013 /* Convert chipsize to number of pages per chip -1. */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002014 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002015
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002016 chip->bbt_erase_shift = chip->phys_erase_shift =
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002017 ffs(mtd->erasesize) - 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002018 chip->chip_shift = ffs(chip->chipsize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002019
2020 /* Set the bad block position */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002021 chip->badblockpos = mtd->writesize > 512 ?
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002022 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
2023
2024 /* Get chip options, preserve non chip based options */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002025 chip->options &= ~NAND_CHIPOPTIONS_MSK;
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02002026 chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002027
2028 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002029 * Set chip as a default. Board drivers can override it, if necessary
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002030 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002031 chip->options |= NAND_NO_AUTOINCR;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002032
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002033 /* Check if chip is a not a samsung device. Do not clear the
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002034 * options for chips which are not having an extended id.
2035 */
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02002036 if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002037 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002038
2039 /* Check for AND chips with 4 page planes */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002040 if (chip->options & NAND_4PAGE_ARRAY)
2041 chip->erase_cmd = multi_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002042 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002043 chip->erase_cmd = single_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002044
2045 /* Do not replace user supplied command function ! */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002046 if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
2047 chip->cmdfunc = nand_command_lp;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002048
2049 printk(KERN_INFO "NAND device: Manufacturer ID:"
2050 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
2051 nand_manuf_ids[maf_idx].name, type->name);
2052
2053 return type;
2054}
2055
2056/* module_text_address() isn't exported, and it's mostly a pointless
2057 test if this is a module _anyway_ -- they'd have to try _really_ hard
2058 to call us from in-kernel code if the core NAND support is modular. */
2059#ifdef MODULE
2060#define caller_is_module() (1)
2061#else
2062#define caller_is_module() \
2063 module_text_address((unsigned long)__builtin_return_address(0))
2064#endif
2065
2066/**
2067 * nand_scan - [NAND Interface] Scan for the NAND device
2068 * @mtd: MTD device structure
2069 * @maxchips: Number of chips to scan for
2070 *
2071 * This fills out all the uninitialized function pointers
2072 * with the defaults.
2073 * The flash ID is read and the mtd/chip structures are
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002074 * filled with the appropriate values.
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002075 * The mtd->owner field must be set to the module of the caller
2076 *
2077 */
2078int nand_scan(struct mtd_info *mtd, int maxchips)
2079{
2080 int i, busw, nand_maf_id;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002081 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002082 struct nand_flash_dev *type;
2083
2084 /* Many callers got this wrong, so check for it for a while... */
2085 if (!mtd->owner && caller_is_module()) {
2086 printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
2087 BUG();
2088 }
2089
2090 /* Get buswidth to select the correct functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002091 busw = chip->options & NAND_BUSWIDTH_16;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002092 /* Set the default functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002093 nand_set_defaults(chip, busw);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002094
2095 /* Read the flash type */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002096 type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002097
2098 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002099 printk(KERN_WARNING "No NAND device found!!!\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002100 chip->select_chip(mtd, -1);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002101 return PTR_ERR(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 }
2103
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002104 /* Check for a chip array */
David Woodhousee0c7d762006-05-13 18:07:53 +01002105 for (i = 1; i < maxchips; i++) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002106 chip->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002108 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002110 if (nand_maf_id != chip->read_byte(mtd) ||
2111 type->id != chip->read_byte(mtd))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 break;
2113 }
2114 if (i > 1)
2115 printk(KERN_INFO "%d NAND chips detected\n", i);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002116
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 /* Store the number of chips and calc total size for mtd */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002118 chip->numchips = i;
2119 mtd->size = i * chip->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002121 /* Preset the internal oob write buffer */
2122 memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002123
2124 /*
2125 * If no default placement scheme is given, select an appropriate one
2126 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002127 if (!chip->autooob) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002128 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 case 8:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002130 chip->autooob = &nand_oob_8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 break;
2132 case 16:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002133 chip->autooob = &nand_oob_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 break;
2135 case 64:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002136 chip->autooob = &nand_oob_64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 break;
2138 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002139 printk(KERN_WARNING "No oob scheme defined for "
2140 "oobsize %d\n", mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 BUG();
2142 }
2143 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002144
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002145 /*
2146 * The number of bytes available for the filesystem to place fs
2147 * dependend oob data
2148 */
Thomas Gleixner998cf642005-04-01 08:21:48 +01002149 mtd->oobavail = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002150 for (i = 0; chip->autooob->oobfree[i][1]; i++)
2151 mtd->oobavail += chip->autooob->oobfree[i][1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002153 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002154 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2155 * selected and we have 256 byte pagesize fallback to software ECC
David Woodhousee0c7d762006-05-13 18:07:53 +01002156 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002157 switch (chip->ecc.mode) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002158 case NAND_ECC_HW:
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002159 /* Use standard hwecc read page function ? */
2160 if (!chip->ecc.read_page)
2161 chip->ecc.read_page = nand_read_page_hwecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002162 if (!chip->ecc.write_page)
2163 chip->ecc.write_page = nand_write_page_hwecc;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002164
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002165 case NAND_ECC_HW_SYNDROME:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002166 if (!chip->ecc.calculate || !chip->ecc.correct ||
2167 !chip->ecc.hwctl) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002168 printk(KERN_WARNING "No ECC functions supplied, "
2169 "Hardware ECC not possible\n");
2170 BUG();
2171 }
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002172 /* Use standard syndrome read/write page function ? */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002173 if (!chip->ecc.read_page)
2174 chip->ecc.read_page = nand_read_page_syndrome;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002175 if (!chip->ecc.write_page)
2176 chip->ecc.write_page = nand_write_page_syndrome;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002177
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002178 if (mtd->writesize >= chip->ecc.size)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002179 break;
2180 printk(KERN_WARNING "%d byte HW ECC not possible on "
2181 "%d byte page size, fallback to SW ECC\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002182 chip->ecc.size, mtd->writesize);
2183 chip->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002185 case NAND_ECC_SOFT:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002186 chip->ecc.calculate = nand_calculate_ecc;
2187 chip->ecc.correct = nand_correct_data;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002188 chip->ecc.read_page = nand_read_page_swecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002189 chip->ecc.write_page = nand_write_page_swecc;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002190 chip->ecc.size = 256;
2191 chip->ecc.bytes = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002193
2194 case NAND_ECC_NONE:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002195 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2196 "This is not recommended !!\n");
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002197 chip->ecc.read_page = nand_read_page_swecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002198 chip->ecc.write_page = nand_write_page_swecc;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002199 chip->ecc.size = mtd->writesize;
2200 chip->ecc.bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002203 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002204 chip->ecc.mode);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002205 BUG();
2206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002208 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002209 * Set the number of read / write steps for one page depending on ECC
2210 * mode
2211 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002212 chip->ecc.steps = mtd->writesize / chip->ecc.size;
2213 if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002214 printk(KERN_WARNING "Invalid ecc parameters\n");
2215 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 }
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002217 chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002218
Thomas Gleixner04bbd0e2006-05-25 09:45:29 +02002219 /* Initialize state */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002220 chip->state = FL_READY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
2222 /* De-select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002223 chip->select_chip(mtd, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
2225 /* Invalidate the pagebuffer reference */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002226 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
2228 /* Fill in remaining MTD driver data */
2229 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002230 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 mtd->ecctype = MTD_ECC_SW;
2232 mtd->erase = nand_erase;
2233 mtd->point = NULL;
2234 mtd->unpoint = NULL;
2235 mtd->read = nand_read;
2236 mtd->write = nand_write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 mtd->read_oob = nand_read_oob;
2238 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 mtd->sync = nand_sync;
2240 mtd->lock = NULL;
2241 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002242 mtd->suspend = nand_suspend;
2243 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 mtd->block_isbad = nand_block_isbad;
2245 mtd->block_markbad = nand_block_markbad;
2246
2247 /* and make the autooob the default one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002248 memcpy(&mtd->oobinfo, chip->autooob, sizeof(mtd->oobinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002250 /* Check, if we should skip the bad block table scan */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002251 if (chip->options & NAND_SKIP_BBTSCAN)
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002252 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
2254 /* Build bad block table */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002255 return chip->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256}
2257
2258/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002259 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 * @mtd: MTD device structure
2261*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002262void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002264 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
2266#ifdef CONFIG_MTD_PARTITIONS
2267 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002268 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269#endif
2270 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002271 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
Jesper Juhlfa671642005-11-07 01:01:27 -08002273 /* Free bad block table memory */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002274 kfree(chip->bbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275}
2276
David Woodhousee0c7d762006-05-13 18:07:53 +01002277EXPORT_SYMBOL_GPL(nand_scan);
2278EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002279
2280static int __init nand_base_init(void)
2281{
2282 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2283 return 0;
2284}
2285
2286static void __exit nand_base_exit(void)
2287{
2288 led_trigger_unregister_simple(nand_led_trigger);
2289}
2290
2291module_init(nand_base_init);
2292module_exit(nand_base_exit);
2293
David Woodhousee0c7d762006-05-13 18:07:53 +01002294MODULE_LICENSE("GPL");
2295MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2296MODULE_DESCRIPTION("Generic NAND flash driver code");