blob: bb18476acd7b4556c922b0cd2b0a7ab601a588a2 [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:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200177 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
178 NAND_NCE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 break;
180
181 default:
182 BUG();
183 }
184}
185
186/**
187 * nand_write_buf - [DEFAULT] write buffer to chip
188 * @mtd: MTD device structure
189 * @buf: data buffer
190 * @len: number of bytes to write
191 *
192 * Default write function for 8bit buswith
193 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200194static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195{
196 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200197 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
David Woodhousee0c7d762006-05-13 18:07:53 +0100199 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200200 writeb(buf[i], chip->IO_ADDR_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201}
202
203/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000204 * nand_read_buf - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 * @mtd: MTD device structure
206 * @buf: buffer to store date
207 * @len: number of bytes to read
208 *
209 * Default read function for 8bit buswith
210 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200211static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212{
213 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200214 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
David Woodhousee0c7d762006-05-13 18:07:53 +0100216 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200217 buf[i] = readb(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218}
219
220/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000221 * nand_verify_buf - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 * @mtd: MTD device structure
223 * @buf: buffer containing the data to compare
224 * @len: number of bytes to compare
225 *
226 * Default verify function for 8bit buswith
227 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200228static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229{
230 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200231 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
David Woodhousee0c7d762006-05-13 18:07:53 +0100233 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200234 if (buf[i] != readb(chip->IO_ADDR_R))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 return 0;
237}
238
239/**
240 * nand_write_buf16 - [DEFAULT] write buffer to chip
241 * @mtd: MTD device structure
242 * @buf: data buffer
243 * @len: number of bytes to write
244 *
245 * Default write function for 16bit buswith
246 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200247static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248{
249 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200250 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 u16 *p = (u16 *) buf;
252 len >>= 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000253
David Woodhousee0c7d762006-05-13 18:07:53 +0100254 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200255 writew(p[i], chip->IO_ADDR_W);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257}
258
259/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000260 * nand_read_buf16 - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 * @mtd: MTD device structure
262 * @buf: buffer to store date
263 * @len: number of bytes to read
264 *
265 * Default read function for 16bit buswith
266 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200267static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268{
269 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200270 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 u16 *p = (u16 *) buf;
272 len >>= 1;
273
David Woodhousee0c7d762006-05-13 18:07:53 +0100274 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200275 p[i] = readw(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276}
277
278/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000279 * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 * @mtd: MTD device structure
281 * @buf: buffer containing the data to compare
282 * @len: number of bytes to compare
283 *
284 * Default verify function for 16bit buswith
285 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200286static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287{
288 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200289 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 u16 *p = (u16 *) buf;
291 len >>= 1;
292
David Woodhousee0c7d762006-05-13 18:07:53 +0100293 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200294 if (p[i] != readw(chip->IO_ADDR_R))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return -EFAULT;
296
297 return 0;
298}
299
300/**
301 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
302 * @mtd: MTD device structure
303 * @ofs: offset from device start
304 * @getchip: 0, if the chip is already selected
305 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000306 * Check, if the block is bad.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 */
308static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
309{
310 int page, chipnr, res = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200311 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 u16 bad;
313
314 if (getchip) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200315 page = (int)(ofs >> chip->page_shift);
316 chipnr = (int)(ofs >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200318 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200321 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000322 } else
David Woodhousee0c7d762006-05-13 18:07:53 +0100323 page = (int)ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200325 if (chip->options & NAND_BUSWIDTH_16) {
326 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
327 page & chip->pagemask);
328 bad = cpu_to_le16(chip->read_word(mtd));
329 if (chip->badblockpos & 0x1)
Vitaly Wool49196f32005-11-02 16:54:46 +0000330 bad >>= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 if ((bad & 0xFF) != 0xff)
332 res = 1;
333 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200334 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
335 page & chip->pagemask);
336 if (chip->read_byte(mtd) != 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 res = 1;
338 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000339
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200340 if (getchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 nand_release_device(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 return res;
344}
345
346/**
347 * nand_default_block_markbad - [DEFAULT] mark a block bad
348 * @mtd: MTD device structure
349 * @ofs: offset from device start
350 *
351 * This is the default implementation, which can be overridden by
352 * a hardware specific driver.
353*/
354static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
355{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200356 struct nand_chip *chip = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200357 uint8_t buf[2] = { 0, 0 };
David Woodhousee0c7d762006-05-13 18:07:53 +0100358 size_t retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 int block;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000360
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 /* Get block number */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200362 block = ((int)ofs) >> chip->bbt_erase_shift;
363 if (chip->bbt)
364 chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366 /* Do we have a flash based bad block table ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200367 if (chip->options & NAND_USE_FLASH_BBT)
David Woodhousee0c7d762006-05-13 18:07:53 +0100368 return nand_update_bbt(mtd, ofs);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 /* We write two bytes, so we dont have to mess with 16 bit access */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200371 ofs += mtd->oobsize + (chip->badblockpos & ~0x01);
David Woodhousee0c7d762006-05-13 18:07:53 +0100372 return nand_write_oob(mtd, ofs, 2, &retlen, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373}
374
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000375/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 * nand_check_wp - [GENERIC] check if the chip is write protected
377 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000378 * Check, if the device is write protected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000380 * The function expects, that the device is already selected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100382static int nand_check_wp(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200384 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 /* Check the WP bit */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200386 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
387 return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388}
389
390/**
391 * nand_block_checkbad - [GENERIC] Check if a block is marked bad
392 * @mtd: MTD device structure
393 * @ofs: offset from device start
394 * @getchip: 0, if the chip is already selected
395 * @allowbbt: 1, if its allowed to access the bbt area
396 *
397 * Check, if the block is bad. Either by reading the bad block table or
398 * calling of the scan function.
399 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200400static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
401 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200403 struct nand_chip *chip = mtd->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000404
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200405 if (!chip->bbt)
406 return chip->block_bad(mtd, ofs, getchip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 /* Return info from the table */
David Woodhousee0c7d762006-05-13 18:07:53 +0100409 return nand_isbad_bbt(mtd, ofs, allowbbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410}
411
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000412/*
Thomas Gleixner3b887752005-02-22 21:56:49 +0000413 * Wait for the ready pin, after a command
414 * The timeout is catched later.
415 */
416static void nand_wait_ready(struct mtd_info *mtd)
417{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200418 struct nand_chip *chip = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100419 unsigned long timeo = jiffies + 2;
Thomas Gleixner3b887752005-02-22 21:56:49 +0000420
Richard Purdie8fe833c2006-03-31 02:31:14 -0800421 led_trigger_event(nand_led_trigger, LED_FULL);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000422 /* wait until command is processed or timeout occures */
423 do {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200424 if (chip->dev_ready(mtd))
Richard Purdie8fe833c2006-03-31 02:31:14 -0800425 break;
Ingo Molnar8446f1d2005-09-06 15:16:27 -0700426 touch_softlockup_watchdog();
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000427 } while (time_before(jiffies, timeo));
Richard Purdie8fe833c2006-03-31 02:31:14 -0800428 led_trigger_event(nand_led_trigger, LED_OFF);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000429}
430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431/**
432 * nand_command - [DEFAULT] Send command to NAND device
433 * @mtd: MTD device structure
434 * @command: the command to be sent
435 * @column: the column address for this command, -1 if none
436 * @page_addr: the page address for this command, -1 if none
437 *
438 * Send command to NAND device. This function is used for small page
439 * devices (256/512 Bytes per page)
440 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200441static void nand_command(struct mtd_info *mtd, unsigned int command,
442 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200444 register struct nand_chip *chip = mtd->priv;
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200445 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 /*
448 * Write out the command to the device.
449 */
450 if (command == NAND_CMD_SEQIN) {
451 int readcmd;
452
Joern Engel28318772006-05-22 23:18:05 +0200453 if (column >= mtd->writesize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 /* OOB area */
Joern Engel28318772006-05-22 23:18:05 +0200455 column -= mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 readcmd = NAND_CMD_READOOB;
457 } else if (column < 256) {
458 /* First 256 bytes --> READ0 */
459 readcmd = NAND_CMD_READ0;
460 } else {
461 column -= 256;
462 readcmd = NAND_CMD_READ1;
463 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200464 chip->cmd_ctrl(mtd, readcmd, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200465 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200467 chip->cmd_ctrl(mtd, command, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200469 /*
470 * Address cycle, when necessary
471 */
472 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
473 /* Serially input address */
474 if (column != -1) {
475 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200476 if (chip->options & NAND_BUSWIDTH_16)
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200477 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200478 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200479 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200481 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200482 chip->cmd_ctrl(mtd, page_addr, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200483 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200484 chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200485 /* One more address cycle for devices > 32MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200486 if (chip->chipsize > (32 << 20))
487 chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200488 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200489 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000490
491 /*
492 * program and erase have their own busy handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 * status and sequential in needs no delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100494 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 case NAND_CMD_PAGEPROG:
498 case NAND_CMD_ERASE1:
499 case NAND_CMD_ERASE2:
500 case NAND_CMD_SEQIN:
501 case NAND_CMD_STATUS:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200502 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 return;
504
505 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200506 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200508 udelay(chip->chip_delay);
509 chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200510 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200511 chip->cmd_ctrl(mtd,
512 NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200513 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 return;
515
David Woodhousee0c7d762006-05-13 18:07:53 +0100516 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000518 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 * If we don't have access to the busy pin, we apply the given
520 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100521 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200522 if (!chip->dev_ready) {
523 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 /* Apply this short delay always to ensure that we do wait tWB in
528 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100529 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000530
531 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532}
533
534/**
535 * nand_command_lp - [DEFAULT] Send command to NAND large page device
536 * @mtd: MTD device structure
537 * @command: the command to be sent
538 * @column: the column address for this command, -1 if none
539 * @page_addr: the page address for this command, -1 if none
540 *
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200541 * Send command to NAND device. This is the version for the new large page
542 * devices We dont have the separate regions as we have in the small page
543 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 *
545 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200546static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
547 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200549 register struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
551 /* Emulate NAND_CMD_READOOB */
552 if (command == NAND_CMD_READOOB) {
Joern Engel28318772006-05-22 23:18:05 +0200553 column += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 command = NAND_CMD_READ0;
555 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000556
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200557 /* Command latch cycle */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200558 chip->cmd_ctrl(mtd, command & 0xff,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200559 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
561 if (column != -1 || page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200562 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
564 /* Serially input address */
565 if (column != -1) {
566 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200567 if (chip->options & NAND_BUSWIDTH_16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200569 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200570 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200571 chip->cmd_ctrl(mtd, column >> 8, ctrl);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200574 chip->cmd_ctrl(mtd, page_addr, ctrl);
575 chip->cmd_ctrl(mtd, page_addr >> 8,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200576 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 /* One more address cycle for devices > 128MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200578 if (chip->chipsize > (128 << 20))
579 chip->cmd_ctrl(mtd, page_addr >> 16,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200580 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200583 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000584
585 /*
586 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000587 * status, sequential in, and deplete1 need no delay
588 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000590
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 case NAND_CMD_CACHEDPROG:
592 case NAND_CMD_PAGEPROG:
593 case NAND_CMD_ERASE1:
594 case NAND_CMD_ERASE2:
595 case NAND_CMD_SEQIN:
596 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000597 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 return;
599
David Woodhousee0c7d762006-05-13 18:07:53 +0100600 /*
601 * read error status commands require only a short delay
602 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000603 case NAND_CMD_STATUS_ERROR:
604 case NAND_CMD_STATUS_ERROR0:
605 case NAND_CMD_STATUS_ERROR1:
606 case NAND_CMD_STATUS_ERROR2:
607 case NAND_CMD_STATUS_ERROR3:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200608 udelay(chip->chip_delay);
David A. Marlin30f464b2005-01-17 18:35:25 +0000609 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
611 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200612 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200614 udelay(chip->chip_delay);
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200615 chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
616 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
617 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
618 NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200619 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 return;
621
622 case NAND_CMD_READ0:
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200623 chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
624 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
625 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
626 NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000627
David Woodhousee0c7d762006-05-13 18:07:53 +0100628 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000630 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 * If we don't have access to the busy pin, we apply the given
632 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100633 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200634 if (!chip->dev_ready) {
635 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000637 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 /* Apply this short delay always to ensure that we do wait tWB in
641 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100642 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000643
644 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645}
646
647/**
648 * nand_get_device - [GENERIC] Get chip for selected access
649 * @this: the nand chip descriptor
650 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000651 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 *
653 * Get the device and lock it for exclusive access
654 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200655static int
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200656nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200658 spinlock_t *lock = &chip->controller->lock;
659 wait_queue_head_t *wq = &chip->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100660 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100661 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100662 spin_lock(lock);
663
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200665 /* Hardware controller shared among independend devices */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200666 if (!chip->controller->active)
667 chip->controller->active = chip;
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200668
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200669 if (chip->controller->active == chip && chip->state == FL_READY) {
670 chip->state = new_state;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100671 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100672 return 0;
673 }
674 if (new_state == FL_PM_SUSPENDED) {
675 spin_unlock(lock);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200676 return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100677 }
678 set_current_state(TASK_UNINTERRUPTIBLE);
679 add_wait_queue(wq, &wait);
680 spin_unlock(lock);
681 schedule();
682 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 goto retry;
684}
685
686/**
687 * nand_wait - [DEFAULT] wait until the command is done
688 * @mtd: MTD device structure
689 * @this: NAND chip structure
690 * @state: state to select the max. timeout value
691 *
692 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000693 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 * general NAND and SmartMedia specs
695 *
696*/
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200697static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
699
David Woodhousee0c7d762006-05-13 18:07:53 +0100700 unsigned long timeo = jiffies;
701 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000702
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100704 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100706 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Richard Purdie8fe833c2006-03-31 02:31:14 -0800708 led_trigger_event(nand_led_trigger, LED_FULL);
709
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 /* Apply this short delay always to ensure that we do wait tWB in
711 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100712 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200714 if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
715 chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000716 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200717 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000719 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 /* Check, if we were interrupted */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200721 if (chip->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 return 0;
723
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200724 if (chip->dev_ready) {
725 if (chip->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000726 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200728 if (chip->read_byte(mtd) & NAND_STATUS_READY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 break;
730 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000731 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800733 led_trigger_event(nand_led_trigger, LED_OFF);
734
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200735 status = (int)chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 return status;
737}
738
739/**
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200740 * nand_read_page_swecc - {REPLACABLE] software ecc based page read function
741 * @mtd: mtd info structure
742 * @chip: nand chip info structure
743 * @buf: buffer to store read data
David A. Marlin068e3c02005-01-24 03:07:46 +0000744 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200745static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
746 uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747{
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200748 int i, eccsize = chip->ecc.size;
749 int eccbytes = chip->ecc.bytes;
750 int eccsteps = chip->ecc.steps;
751 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200752 uint8_t *ecc_calc = chip->buffers.ecccalc;
753 uint8_t *ecc_code = chip->buffers.ecccode;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200754 int *eccpos = chip->autooob->eccpos;
755
756 chip->read_buf(mtd, buf, mtd->writesize);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200757 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200758
759 if (chip->ecc.mode == NAND_ECC_NONE)
760 return 0;
761
762 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
763 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
764
765 for (i = 0; i < chip->ecc.total; i++)
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200766 ecc_code[i] = chip->oob_poi[eccpos[i]];
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200767
768 eccsteps = chip->ecc.steps;
769 p = buf;
770
771 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
772 int stat;
773
774 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
775 if (stat == -1)
776 mtd->ecc_stats.failed++;
777 else
778 mtd->ecc_stats.corrected += stat;
779 }
780 return 0;
Thomas Gleixner22c60f52005-04-04 19:56:32 +0100781}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783/**
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200784 * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function
785 * @mtd: mtd info structure
786 * @chip: nand chip info structure
787 * @buf: buffer to store read data
788 *
789 * Not for syndrome calculating ecc controllers which need a special oob layout
790 */
791static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
792 uint8_t *buf)
793{
794 int i, eccsize = chip->ecc.size;
795 int eccbytes = chip->ecc.bytes;
796 int eccsteps = chip->ecc.steps;
797 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200798 uint8_t *ecc_calc = chip->buffers.ecccalc;
799 uint8_t *ecc_code = chip->buffers.ecccode;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200800 int *eccpos = chip->autooob->eccpos;
801
802 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
803 chip->ecc.hwctl(mtd, NAND_ECC_READ);
804 chip->read_buf(mtd, p, eccsize);
805 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
806 }
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200807 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200808
809 for (i = 0; i < chip->ecc.total; i++)
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200810 ecc_code[i] = chip->oob_poi[eccpos[i]];
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200811
812 eccsteps = chip->ecc.steps;
813 p = buf;
814
815 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
816 int stat;
817
818 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
819 if (stat == -1)
820 mtd->ecc_stats.failed++;
821 else
822 mtd->ecc_stats.corrected += stat;
823 }
824 return 0;
825}
826
827/**
828 * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
829 * @mtd: mtd info structure
830 * @chip: nand chip info structure
831 * @buf: buffer to store read data
832 *
833 * The hw generator calculates the error syndrome automatically. Therefor
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200834 * we need a special oob layout and handling.
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200835 */
836static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
837 uint8_t *buf)
838{
839 int i, eccsize = chip->ecc.size;
840 int eccbytes = chip->ecc.bytes;
841 int eccsteps = chip->ecc.steps;
842 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200843 uint8_t *oob = chip->oob_poi;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200844
845 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
846 int stat;
847
848 chip->ecc.hwctl(mtd, NAND_ECC_READ);
849 chip->read_buf(mtd, p, eccsize);
850
851 if (chip->ecc.prepad) {
852 chip->read_buf(mtd, oob, chip->ecc.prepad);
853 oob += chip->ecc.prepad;
854 }
855
856 chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
857 chip->read_buf(mtd, oob, eccbytes);
858 stat = chip->ecc.correct(mtd, p, oob, NULL);
859
860 if (stat == -1)
861 mtd->ecc_stats.failed++;
862 else
863 mtd->ecc_stats.corrected += stat;
864
865 oob += eccbytes;
866
867 if (chip->ecc.postpad) {
868 chip->read_buf(mtd, oob, chip->ecc.postpad);
869 oob += chip->ecc.postpad;
870 }
871 }
872
873 /* Calculate remaining oob bytes */
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200874 i = oob - chip->oob_poi;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200875 if (i)
876 chip->read_buf(mtd, oob, i);
877
878 return 0;
879}
880
881/**
882 * nand_do_read - [Internal] Read data with ECC
883 *
David A. Marlin068e3c02005-01-24 03:07:46 +0000884 * @mtd: MTD device structure
885 * @from: offset to read from
886 * @len: number of bytes to read
887 * @retlen: pointer to variable to store the number of read bytes
888 * @buf: the databuffer to put data
David A. Marlin068e3c02005-01-24 03:07:46 +0000889 *
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200890 * Internal function. Called with chip held.
David A. Marlin068e3c02005-01-24 03:07:46 +0000891 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200892int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
893 size_t *retlen, uint8_t *buf)
David A. Marlin068e3c02005-01-24 03:07:46 +0000894{
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200895 int chipnr, page, realpage, col, bytes, aligned;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200896 struct nand_chip *chip = mtd->priv;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200897 struct mtd_ecc_stats stats;
898 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
899 int sndcmd = 1;
900 int ret = 0;
901 uint32_t readlen = len;
902 uint8_t *bufpoi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200904 stats = mtd->ecc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200906 chipnr = (int)(from >> chip->chip_shift);
907 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200909 realpage = (int)(from >> chip->page_shift);
910 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200912 col = (int)(from & (mtd->writesize - 1));
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200913 chip->oob_poi = chip->buffers.oobrbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200915 while(1) {
916 bytes = min(mtd->writesize - col, readlen);
917 aligned = (bytes == mtd->writesize);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000918
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200919 /* Is the current page in the buffer ? */
920 if (realpage != chip->pagebuf) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200921 bufpoi = aligned ? buf : chip->buffers.databuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200923 if (likely(sndcmd)) {
924 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
925 sndcmd = 0;
926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200928 /* Now read the page into the buffer */
929 ret = chip->ecc.read_page(mtd, chip, bufpoi);
930 if (ret < 0)
David Woodhousee0c7d762006-05-13 18:07:53 +0100931 break;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200932
933 /* Transfer not aligned data */
934 if (!aligned) {
935 chip->pagebuf = realpage;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200936 memcpy(buf, chip->buffers.databuf + col, bytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000938
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200939 if (!(chip->options & NAND_NO_READRDY)) {
940 /*
941 * Apply delay or wait for ready/busy pin. Do
942 * this before the AUTOINCR check, so no
943 * problems arise if a chip which does auto
944 * increment is marked as NOAUTOINCR by the
945 * board driver.
946 */
947 if (!chip->dev_ready)
948 udelay(chip->chip_delay);
949 else
950 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000952 } else
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200953 memcpy(buf, chip->buffers.databuf + col, bytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200955 buf += bytes;
956 readlen -= bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000957
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200958 if (!readlen)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000959 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
961 /* For subsequent reads align to page boundary. */
962 col = 0;
963 /* Increment page address */
964 realpage++;
965
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200966 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 /* Check, if we cross a chip boundary */
968 if (!page) {
969 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200970 chip->select_chip(mtd, -1);
971 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 }
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200973
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000974 /* Check, if the chip supports auto page increment
975 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +0100976 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200977 if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000978 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 }
980
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200981 *retlen = len - (size_t) readlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200983 if (ret)
984 return ret;
985
986 return mtd->ecc_stats.failed - stats.failed ? -EBADMSG : 0;
987}
988
989/**
990 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
991 * @mtd: MTD device structure
992 * @from: offset to read from
993 * @len: number of bytes to read
994 * @retlen: pointer to variable to store the number of read bytes
995 * @buf: the databuffer to put data
996 *
997 * Get hold of the chip and call nand_do_read
998 */
999static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
1000 size_t *retlen, uint8_t *buf)
1001{
1002 int ret;
1003
1004 *retlen = 0;
1005 /* Do not allow reads past end of device */
1006 if ((from + len) > mtd->size)
1007 return -EINVAL;
1008 if (!len)
1009 return 0;
1010
1011 nand_get_device(mtd->priv, mtd, FL_READING);
1012
1013 ret = nand_do_read(mtd, from, len, retlen, buf);
1014
1015 nand_release_device(mtd);
1016
1017 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018}
1019
1020/**
1021 * nand_read_oob - [MTD Interface] NAND read out-of-band
1022 * @mtd: MTD device structure
1023 * @from: offset to read from
1024 * @len: number of bytes to read
1025 * @retlen: pointer to variable to store the number of read bytes
1026 * @buf: the databuffer to put data
1027 *
1028 * NAND read out-of-band data from the spare area
1029 */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001030static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
1031 size_t *retlen, uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032{
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001033 int col, page, realpage, chipnr, sndcmd = 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001034 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001035 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1036 int readlen = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001038 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n",
1039 (unsigned int)from, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
1041 /* Initialize return length value */
1042 *retlen = 0;
1043
1044 /* Do not allow reads past end of device */
1045 if ((from + len) > mtd->size) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001046 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1047 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 return -EINVAL;
1049 }
1050
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001051 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001053 chipnr = (int)(from >> chip->chip_shift);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001054 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001056 /* Shift to get page */
1057 realpage = (int)(from >> chip->page_shift);
1058 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001060 /* Mask to get column */
1061 col = from & (mtd->oobsize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001063 while(1) {
1064 int bytes = min((int)(mtd->oobsize - col), readlen);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001065
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001066 if (likely(sndcmd)) {
1067 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page);
1068 sndcmd = 0;
1069 }
1070
1071 chip->read_buf(mtd, buf, bytes);
1072
1073 readlen -= bytes;
1074 if (!readlen)
1075 break;
1076
1077 if (!(chip->options & NAND_NO_READRDY)) {
1078 /*
1079 * Apply delay or wait for ready/busy pin. Do this
1080 * before the AUTOINCR check, so no problems arise if a
1081 * chip which does auto increment is marked as
1082 * NOAUTOINCR by the board driver.
Thomas Gleixner19870da2005-07-15 14:53:51 +01001083 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001084 if (!chip->dev_ready)
1085 udelay(chip->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001086 else
1087 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 }
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001089
1090 buf += bytes;
1091 bytes = mtd->oobsize;
1092 col = 0;
1093
1094 /* Increment page address */
1095 realpage++;
1096
1097 page = realpage & chip->pagemask;
1098 /* Check, if we cross a chip boundary */
1099 if (!page) {
1100 chipnr++;
1101 chip->select_chip(mtd, -1);
1102 chip->select_chip(mtd, chipnr);
1103 }
1104
1105 /* Check, if the chip supports auto page increment
1106 * or if we have hit a block boundary.
1107 */
1108 if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
1109 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 }
1111
1112 /* Deselect and wake up anyone waiting on the device */
1113 nand_release_device(mtd);
1114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 *retlen = len;
1116 return 0;
1117}
1118
1119/**
1120 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1121 * @mtd: MTD device structure
1122 * @buf: temporary buffer
1123 * @from: offset to read from
1124 * @len: number of bytes to read
1125 * @ooblen: number of oob data bytes to read
1126 *
1127 * Read raw data including oob into buffer
1128 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001129int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len,
1130 size_t ooblen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001132 struct nand_chip *chip = mtd->priv;
1133 int page = (int)(from >> chip->page_shift);
1134 int chipnr = (int)(from >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 int sndcmd = 1;
1136 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001137 int pagesize = mtd->writesize + mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001138 int blockcheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
1140 /* Do not allow reads past end of device */
1141 if ((from + len) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001142 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: "
1143 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 return -EINVAL;
1145 }
1146
1147 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001148 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001150 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001151
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 /* Add requested oob length */
1153 len += ooblen;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001154 blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001155
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 while (len) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001157 if (likely(sndcmd)) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001158 chip->cmdfunc(mtd, NAND_CMD_READ0, 0,
1159 page & chip->pagemask);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001160 sndcmd = 0;
1161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001163 chip->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 len -= pagesize;
1166 cnt += pagesize;
1167 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001168
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001169 if (!(chip->options & NAND_NO_READRDY)) {
1170 if (!chip->dev_ready)
1171 udelay(chip->chip_delay);
1172 else
1173 nand_wait_ready(mtd);
1174 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001175
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001176 /*
1177 * Check, if the chip supports auto page increment or if we
1178 * cross a block boundary.
1179 */
1180 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 sndcmd = 1;
1182 }
1183
1184 /* Deselect and wake up anyone waiting on the device */
1185 nand_release_device(mtd);
1186 return 0;
1187}
1188
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001189/**
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001190 * nand_write_page_swecc - {REPLACABLE] software ecc based page write function
1191 * @mtd: mtd info structure
1192 * @chip: nand chip info structure
1193 * @buf: data buffer
1194 */
1195static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
1196 const uint8_t *buf)
1197{
1198 int i, eccsize = chip->ecc.size;
1199 int eccbytes = chip->ecc.bytes;
1200 int eccsteps = chip->ecc.steps;
1201 uint8_t *ecc_calc = chip->buffers.ecccalc;
1202 const uint8_t *p = buf;
1203 int *eccpos = chip->autooob->eccpos;
1204
1205 if (chip->ecc.mode != NAND_ECC_NONE) {
1206 /* Software ecc calculation */
1207 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
1208 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1209
1210 for (i = 0; i < chip->ecc.total; i++)
1211 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1212 }
1213
1214 chip->write_buf(mtd, buf, mtd->writesize);
1215 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1216}
1217
1218/**
1219 * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function
1220 * @mtd: mtd info structure
1221 * @chip: nand chip info structure
1222 * @buf: data buffer
1223 */
1224static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
1225 const uint8_t *buf)
1226{
1227 int i, eccsize = chip->ecc.size;
1228 int eccbytes = chip->ecc.bytes;
1229 int eccsteps = chip->ecc.steps;
1230 uint8_t *ecc_calc = chip->buffers.ecccalc;
1231 const uint8_t *p = buf;
1232 int *eccpos = chip->autooob->eccpos;
1233
1234 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
1235 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
David Woodhouse29da9ce2006-05-26 23:05:44 +01001236 chip->write_buf(mtd, p, eccsize);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001237 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1238 }
1239
1240 for (i = 0; i < chip->ecc.total; i++)
1241 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1242
1243 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1244}
1245
1246/**
1247 * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write
1248 * @mtd: mtd info structure
1249 * @chip: nand chip info structure
1250 * @buf: data buffer
1251 *
1252 * The hw generator calculates the error syndrome automatically. Therefor
1253 * we need a special oob layout and handling.
1254 */
1255static void nand_write_page_syndrome(struct mtd_info *mtd,
1256 struct nand_chip *chip, const uint8_t *buf)
1257{
1258 int i, eccsize = chip->ecc.size;
1259 int eccbytes = chip->ecc.bytes;
1260 int eccsteps = chip->ecc.steps;
1261 const uint8_t *p = buf;
1262 uint8_t *oob = chip->oob_poi;
1263
1264 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
1265
1266 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
1267 chip->write_buf(mtd, p, eccsize);
1268
1269 if (chip->ecc.prepad) {
1270 chip->write_buf(mtd, oob, chip->ecc.prepad);
1271 oob += chip->ecc.prepad;
1272 }
1273
1274 chip->ecc.calculate(mtd, p, oob);
1275 chip->write_buf(mtd, oob, eccbytes);
1276 oob += eccbytes;
1277
1278 if (chip->ecc.postpad) {
1279 chip->write_buf(mtd, oob, chip->ecc.postpad);
1280 oob += chip->ecc.postpad;
1281 }
1282 }
1283
1284 /* Calculate remaining oob bytes */
1285 i = oob - chip->oob_poi;
1286 if (i)
1287 chip->write_buf(mtd, oob, i);
1288}
1289
1290/**
1291 * nand_write_page - [INTERNAL] write one page
1292 * @mtd: MTD device structure
1293 * @chip: NAND chip descriptor
1294 * @buf: the data to write
1295 * @page: page number to write
1296 * @cached: cached programming
1297 */
1298static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
1299 const uint8_t *buf, int page, int cached)
1300{
1301 int status;
1302
1303 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
1304
1305 chip->ecc.write_page(mtd, chip, buf);
1306
1307 /*
1308 * Cached progamming disabled for now, Not sure if its worth the
1309 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
1310 */
1311 cached = 0;
1312
1313 if (!cached || !(chip->options & NAND_CACHEPRG)) {
1314
1315 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1316 status = chip->waitfunc(mtd, chip, FL_WRITING);
1317 /*
1318 * See if operation failed and additional status checks are
1319 * available
1320 */
1321 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
1322 status = chip->errstat(mtd, chip, FL_WRITING, status,
1323 page);
1324
1325 if (status & NAND_STATUS_FAIL)
1326 return -EIO;
1327 } else {
1328 chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
1329 status = chip->waitfunc(mtd, chip, FL_WRITING);
1330 }
1331
1332#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1333 /* Send command to read back the data */
1334 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1335
1336 if (chip->verify_buf(mtd, buf, mtd->writesize))
1337 return -EIO;
1338#endif
1339 return 0;
1340}
1341
1342#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
1343
1344/**
1345 * nand_write - [MTD Interface] NAND write with ECC
1346 * @mtd: MTD device structure
1347 * @to: offset to write to
1348 * @len: number of bytes to write
1349 * @retlen: pointer to variable to store the number of written bytes
1350 * @buf: the data to write
1351 *
1352 * NAND write with ECC
1353 */
1354static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1355 size_t *retlen, const uint8_t *buf)
1356{
1357 int chipnr, realpage, page, blockmask;
1358 struct nand_chip *chip = mtd->priv;
1359 uint32_t writelen = len;
1360 int bytes = mtd->writesize;
1361 int ret = -EIO;
1362
1363 *retlen = 0;
1364
1365 /* Do not allow write past end of device */
1366 if ((to + len) > mtd->size) {
1367 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: "
1368 "Attempt to write past end of page\n");
1369 return -EINVAL;
1370 }
1371
1372 /* reject writes, which are not page aligned */
1373 if (NOTALIGNED(to) || NOTALIGNED(len)) {
1374 printk(KERN_NOTICE "nand_write: "
1375 "Attempt to write not page aligned data\n");
1376 return -EINVAL;
1377 }
1378
1379 if (!len)
1380 return 0;
1381
1382 nand_get_device(chip, mtd, FL_WRITING);
1383
1384 /* Check, if it is write protected */
1385 if (nand_check_wp(mtd))
1386 goto out;
1387
1388 chipnr = (int)(to >> chip->chip_shift);
1389 chip->select_chip(mtd, chipnr);
1390
1391 realpage = (int)(to >> chip->page_shift);
1392 page = realpage & chip->pagemask;
1393 blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1394
1395 /* Invalidate the page cache, when we write to the cached page */
1396 if (to <= (chip->pagebuf << chip->page_shift) &&
1397 (chip->pagebuf << chip->page_shift) < (to + len))
1398 chip->pagebuf = -1;
1399
1400 chip->oob_poi = chip->buffers.oobwbuf;
1401
1402 while(1) {
1403 int cached = writelen > bytes && page != blockmask;
1404
1405 ret = nand_write_page(mtd, chip, buf, page, cached);
1406 if (ret)
1407 break;
1408
1409 writelen -= bytes;
1410 if (!writelen)
1411 break;
1412
1413 buf += bytes;
1414 realpage++;
1415
1416 page = realpage & chip->pagemask;
1417 /* Check, if we cross a chip boundary */
1418 if (!page) {
1419 chipnr++;
1420 chip->select_chip(mtd, -1);
1421 chip->select_chip(mtd, chipnr);
1422 }
1423 }
1424 out:
1425 *retlen = len - writelen;
1426 nand_release_device(mtd);
1427 return ret;
1428}
1429
1430/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001431 * nand_write_raw - [GENERIC] Write raw data including oob
1432 * @mtd: MTD device structure
1433 * @buf: source buffer
1434 * @to: offset to write to
1435 * @len: number of bytes to write
1436 * @buf: source buffer
1437 * @oob: oob buffer
1438 *
1439 * Write raw data including oob
1440 */
1441int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001442 const uint8_t *buf, uint8_t *oob)
Thomas Gleixner9223a452006-05-23 17:21:03 +02001443{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001444 struct nand_chip *chip = mtd->priv;
1445 int page = (int)(to >> chip->page_shift);
1446 int chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001447 int ret;
1448
1449 *retlen = 0;
1450
1451 /* Do not allow writes past end of device */
1452 if ((to + len) > mtd->size) {
1453 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1454 "beyond end of device\n");
1455 return -EINVAL;
1456 }
1457
1458 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001459 nand_get_device(chip, mtd, FL_WRITING);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001460
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001461 chip->select_chip(mtd, chipnr);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001462 chip->oob_poi = oob;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001463
1464 while (len != *retlen) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001465 ret = nand_write_page(mtd, chip, buf, page, 0);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001466 if (ret)
1467 return ret;
1468 page++;
1469 *retlen += mtd->writesize;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001470 buf += mtd->writesize;
1471 chip->oob_poi += mtd->oobsize;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001472 }
1473
1474 /* Deselect and wake up anyone waiting on the device */
1475 nand_release_device(mtd);
1476 return 0;
1477}
Thomas Gleixner38217202006-05-23 22:33:52 +02001478EXPORT_SYMBOL_GPL(nand_write_raw);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001479
1480/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 * nand_write_oob - [MTD Interface] NAND write out-of-band
1482 * @mtd: MTD device structure
1483 * @to: offset to write to
1484 * @len: number of bytes to write
1485 * @retlen: pointer to variable to store the number of written bytes
1486 * @buf: the data to write
1487 *
1488 * NAND write out-of-band
1489 */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001490static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1491 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492{
1493 int column, page, status, ret = -EIO, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001494 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001496 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1497 (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
1499 /* Initialize return length value */
1500 *retlen = 0;
1501
1502 /* Do not allow write past end of page */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001503 column = to & (mtd->oobsize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 if ((column + len) > mtd->oobsize) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001505 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1506 "Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 return -EINVAL;
1508 }
1509
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001510 nand_get_device(chip, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001512 chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001513 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001515 /* Shift to get page */
1516 page = (int)(to >> chip->page_shift);
1517
1518 /*
1519 * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
1520 * of my DiskOnChip 2000 test units) will clear the whole data page too
1521 * if we don't do this. I have no clue why, but I seem to have 'fixed'
1522 * it in the doc2000 driver in August 1999. dwmw2.
1523 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001524 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
1526 /* Check, if it is write protected */
1527 if (nand_check_wp(mtd))
1528 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001529
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001531 if (page == chip->pagebuf)
1532 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001534 if (NAND_MUST_PAD(chip)) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001535 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
1536 page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 /* prepad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001538 chip->write_buf(mtd, ffchars, column);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 /* write data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001540 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 /* postpad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001542 chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 } else {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001544 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column,
1545 page & chip->pagemask);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001546 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 }
1548 /* Send command to program the OOB data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001549 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001551 status = chip->waitfunc(mtd, chip, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552
1553 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001554 if (status & NAND_STATUS_FAIL) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001555 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1556 "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 ret = -EIO;
1558 goto out;
1559 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 *retlen = len;
1561
1562#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1563 /* Send command to read back the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001564 chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001566 if (chip->verify_buf(mtd, buf, len)) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001567 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1568 "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 ret = -EIO;
1570 goto out;
1571 }
1572#endif
1573 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001574 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 /* Deselect and wake up anyone waiting on the device */
1576 nand_release_device(mtd);
1577
1578 return ret;
1579}
1580
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1583 * @mtd: MTD device structure
1584 * @page: the page address of the block which will be erased
1585 *
1586 * Standard erase command for NAND chips
1587 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001588static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001590 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001592 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1593 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594}
1595
1596/**
1597 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1598 * @mtd: MTD device structure
1599 * @page: the page address of the block which will be erased
1600 *
1601 * AND multi block erase command function
1602 * Erase 4 consecutive blocks
1603 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001604static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001606 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001608 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1609 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1610 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1611 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1612 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613}
1614
1615/**
1616 * nand_erase - [MTD Interface] erase block(s)
1617 * @mtd: MTD device structure
1618 * @instr: erase instruction
1619 *
1620 * Erase one ore more blocks
1621 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001622static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
David Woodhousee0c7d762006-05-13 18:07:53 +01001624 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001626
David A. Marlin30f464b2005-01-17 18:35:25 +00001627#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001629 * nand_erase_nand - [Internal] erase block(s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 * @mtd: MTD device structure
1631 * @instr: erase instruction
1632 * @allowbbt: allow erasing the bbt area
1633 *
1634 * Erase one ore more blocks
1635 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001636int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
1637 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
1639 int page, len, status, pages_per_block, ret, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001640 struct nand_chip *chip = mtd->priv;
1641 int rewrite_bbt[NAND_MAX_CHIPS]={0};
1642 unsigned int bbt_masked_page = 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001644 DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
1645 (unsigned int)instr->addr, (unsigned int)instr->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
1647 /* Start address must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001648 if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001649 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 return -EINVAL;
1651 }
1652
1653 /* Length must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001654 if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
1655 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1656 "Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 return -EINVAL;
1658 }
1659
1660 /* Do not allow erase past end of device */
1661 if ((instr->len + instr->addr) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001662 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1663 "Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 return -EINVAL;
1665 }
1666
1667 instr->fail_addr = 0xffffffff;
1668
1669 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001670 nand_get_device(chip, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
1672 /* Shift to get first page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001673 page = (int)(instr->addr >> chip->page_shift);
1674 chipnr = (int)(instr->addr >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
1676 /* Calculate pages in each block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001677 pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
1679 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001680 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 /* Check, if it is write protected */
1683 if (nand_check_wp(mtd)) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001684 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1685 "Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 instr->state = MTD_ERASE_FAILED;
1687 goto erase_exit;
1688 }
1689
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001690 /*
1691 * If BBT requires refresh, set the BBT page mask to see if the BBT
1692 * should be rewritten. Otherwise the mask is set to 0xffffffff which
1693 * can not be matched. This is also done when the bbt is actually
1694 * erased to avoid recusrsive updates
1695 */
1696 if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
1697 bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
David A. Marlin30f464b2005-01-17 18:35:25 +00001698
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 /* Loop through the pages */
1700 len = instr->len;
1701
1702 instr->state = MTD_ERASING;
1703
1704 while (len) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001705 /*
1706 * heck if we have a bad block, we do not erase bad blocks !
1707 */
1708 if (nand_block_checkbad(mtd, ((loff_t) page) <<
1709 chip->page_shift, 0, allowbbt)) {
1710 printk(KERN_WARNING "nand_erase: attempt to erase a "
1711 "bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 instr->state = MTD_ERASE_FAILED;
1713 goto erase_exit;
1714 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001715
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001716 /*
1717 * Invalidate the page cache, if we erase the block which
1718 * contains the current cached page
1719 */
1720 if (page <= chip->pagebuf && chip->pagebuf <
1721 (page + pages_per_block))
1722 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001724 chip->erase_cmd(mtd, page & chip->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001725
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001726 status = chip->waitfunc(mtd, chip, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001728 /*
1729 * See if operation failed and additional status checks are
1730 * available
1731 */
1732 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
1733 status = chip->errstat(mtd, chip, FL_ERASING,
1734 status, page);
David A. Marlin068e3c02005-01-24 03:07:46 +00001735
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001737 if (status & NAND_STATUS_FAIL) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001738 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1739 "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 instr->state = MTD_ERASE_FAILED;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001741 instr->fail_addr = (page << chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 goto erase_exit;
1743 }
David A. Marlin30f464b2005-01-17 18:35:25 +00001744
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001745 /*
1746 * If BBT requires refresh, set the BBT rewrite flag to the
1747 * page being erased
1748 */
1749 if (bbt_masked_page != 0xffffffff &&
1750 (page & BBT_PAGE_MASK) == bbt_masked_page)
1751 rewrite_bbt[chipnr] = (page << chip->page_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001752
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 /* Increment page address and decrement length */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001754 len -= (1 << chip->phys_erase_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 page += pages_per_block;
1756
1757 /* Check, if we cross a chip boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001758 if (len && !(page & chip->pagemask)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001760 chip->select_chip(mtd, -1);
1761 chip->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00001762
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001763 /*
1764 * If BBT requires refresh and BBT-PERCHIP, set the BBT
1765 * page mask to see if this BBT should be rewritten
1766 */
1767 if (bbt_masked_page != 0xffffffff &&
1768 (chip->bbt_td->options & NAND_BBT_PERCHIP))
1769 bbt_masked_page = chip->bbt_td->pages[chipnr] &
1770 BBT_PAGE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 }
1772 }
1773 instr->state = MTD_ERASE_DONE;
1774
David Woodhousee0c7d762006-05-13 18:07:53 +01001775 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776
1777 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
1778 /* Do call back function */
1779 if (!ret)
1780 mtd_erase_callback(instr);
1781
1782 /* Deselect and wake up anyone waiting on the device */
1783 nand_release_device(mtd);
1784
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001785 /*
1786 * If BBT requires refresh and erase was successful, rewrite any
1787 * selected bad block tables
1788 */
1789 if (bbt_masked_page == 0xffffffff || ret)
1790 return ret;
1791
1792 for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
1793 if (!rewrite_bbt[chipnr])
1794 continue;
1795 /* update the BBT for chip */
1796 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
1797 "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
1798 chip->bbt_td->pages[chipnr]);
1799 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00001800 }
1801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 /* Return more or less happy */
1803 return ret;
1804}
1805
1806/**
1807 * nand_sync - [MTD Interface] sync
1808 * @mtd: MTD device structure
1809 *
1810 * Sync is actually a wait for chip ready function
1811 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001812static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001814 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
David Woodhousee0c7d762006-05-13 18:07:53 +01001816 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
1818 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001819 nand_get_device(chip, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01001821 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822}
1823
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001825 * nand_block_isbad - [MTD Interface] Check if block at offset is bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 * @mtd: MTD device structure
1827 * @ofs: offset relative to mtd start
1828 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001829static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
1831 /* Check for invalid offset */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001832 if (offs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001834
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001835 return nand_block_checkbad(mtd, offs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836}
1837
1838/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001839 * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 * @mtd: MTD device structure
1841 * @ofs: offset relative to mtd start
1842 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001843static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001845 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 int ret;
1847
David Woodhousee0c7d762006-05-13 18:07:53 +01001848 if ((ret = nand_block_isbad(mtd, ofs))) {
1849 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 if (ret > 0)
1851 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001852 return ret;
1853 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001855 return chip->block_markbad(mtd, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856}
1857
1858/**
Vitaly Wool962034f2005-09-15 14:58:53 +01001859 * nand_suspend - [MTD Interface] Suspend the NAND flash
1860 * @mtd: MTD device structure
1861 */
1862static int nand_suspend(struct mtd_info *mtd)
1863{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001864 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01001865
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001866 return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01001867}
1868
1869/**
1870 * nand_resume - [MTD Interface] Resume the NAND flash
1871 * @mtd: MTD device structure
1872 */
1873static void nand_resume(struct mtd_info *mtd)
1874{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001875 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01001876
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001877 if (chip->state == FL_PM_SUSPENDED)
Vitaly Wool962034f2005-09-15 14:58:53 +01001878 nand_release_device(mtd);
1879 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02001880 printk(KERN_ERR "nand_resume() called for a chip which is not "
1881 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01001882}
1883
Thomas Gleixnera36ed292006-05-23 11:37:03 +02001884/*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001885 * Set default functions
1886 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001887static void nand_set_defaults(struct nand_chip *chip, int busw)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001888{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 /* check for proper chip_delay setup, set 20us if not */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001890 if (!chip->chip_delay)
1891 chip->chip_delay = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892
1893 /* check, if a user supplied command function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001894 if (chip->cmdfunc == NULL)
1895 chip->cmdfunc = nand_command;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
1897 /* check, if a user supplied wait function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001898 if (chip->waitfunc == NULL)
1899 chip->waitfunc = nand_wait;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001901 if (!chip->select_chip)
1902 chip->select_chip = nand_select_chip;
1903 if (!chip->read_byte)
1904 chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
1905 if (!chip->read_word)
1906 chip->read_word = nand_read_word;
1907 if (!chip->block_bad)
1908 chip->block_bad = nand_block_bad;
1909 if (!chip->block_markbad)
1910 chip->block_markbad = nand_default_block_markbad;
1911 if (!chip->write_buf)
1912 chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
1913 if (!chip->read_buf)
1914 chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
1915 if (!chip->verify_buf)
1916 chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
1917 if (!chip->scan_bbt)
1918 chip->scan_bbt = nand_default_bbt;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001919
1920 if (!chip->controller) {
1921 chip->controller = &chip->hwcontrol;
1922 spin_lock_init(&chip->controller->lock);
1923 init_waitqueue_head(&chip->controller->wq);
1924 }
1925
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001926}
1927
1928/*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001929 * Get the flash and manufacturer id and lookup if the type is supported
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001930 */
1931static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001932 struct nand_chip *chip,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001933 int busw, int *maf_id)
1934{
1935 struct nand_flash_dev *type = NULL;
1936 int i, dev_id, maf_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937
1938 /* Select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001939 chip->select_chip(mtd, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001942 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943
1944 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001945 *maf_id = chip->read_byte(mtd);
1946 dev_id = chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001948 /* Lookup the flash id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001950 if (dev_id == nand_flash_ids[i].id) {
1951 type = &nand_flash_ids[i];
1952 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 }
1955
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001956 if (!type)
1957 return ERR_PTR(-ENODEV);
1958
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001959 chip->chipsize = nand_flash_ids[i].chipsize << 20;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001960
1961 /* Newer devices have all the information in additional id bytes */
1962 if (!nand_flash_ids[i].pagesize) {
1963 int extid;
1964 /* The 3rd id byte contains non relevant data ATM */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001965 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001966 /* The 4th id byte is the important one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001967 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001968 /* Calc pagesize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001969 mtd->writesize = 1024 << (extid & 0x3);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001970 extid >>= 2;
1971 /* Calc oobsize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001972 mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001973 extid >>= 2;
1974 /* Calc blocksize. Blocksize is multiples of 64KiB */
1975 mtd->erasesize = (64 * 1024) << (extid & 0x03);
1976 extid >>= 2;
1977 /* Get buswidth information */
1978 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
1979
1980 } else {
1981 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001982 * Old devices have chip data hardcoded in the device id table
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001983 */
1984 mtd->erasesize = nand_flash_ids[i].erasesize;
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001985 mtd->writesize = nand_flash_ids[i].pagesize;
1986 mtd->oobsize = mtd->writesize / 32;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001987 busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
1988 }
1989
1990 /* Try to identify manufacturer */
1991 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
1992 if (nand_manuf_ids[maf_idx].id == *maf_id)
1993 break;
1994 }
1995
1996 /*
1997 * Check, if buswidth is correct. Hardware drivers should set
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001998 * chip correct !
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001999 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002000 if (busw != (chip->options & NAND_BUSWIDTH_16)) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002001 printk(KERN_INFO "NAND device: Manufacturer ID:"
2002 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2003 dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2004 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002005 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002006 busw ? 16 : 8);
2007 return ERR_PTR(-EINVAL);
2008 }
2009
2010 /* Calculate the address shift from the page size */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002011 chip->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002012 /* Convert chipsize to number of pages per chip -1. */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002013 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002014
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002015 chip->bbt_erase_shift = chip->phys_erase_shift =
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002016 ffs(mtd->erasesize) - 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002017 chip->chip_shift = ffs(chip->chipsize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002018
2019 /* Set the bad block position */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002020 chip->badblockpos = mtd->writesize > 512 ?
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002021 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
2022
2023 /* Get chip options, preserve non chip based options */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002024 chip->options &= ~NAND_CHIPOPTIONS_MSK;
2025 chip->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002026
2027 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002028 * Set chip as a default. Board drivers can override it, if necessary
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002029 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002030 chip->options |= NAND_NO_AUTOINCR;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002031
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002032 /* Check if chip is a not a samsung device. Do not clear the
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002033 * options for chips which are not having an extended id.
2034 */
2035 if (*maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002036 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002037
2038 /* Check for AND chips with 4 page planes */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002039 if (chip->options & NAND_4PAGE_ARRAY)
2040 chip->erase_cmd = multi_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002041 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002042 chip->erase_cmd = single_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002043
2044 /* Do not replace user supplied command function ! */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002045 if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
2046 chip->cmdfunc = nand_command_lp;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002047
2048 printk(KERN_INFO "NAND device: Manufacturer ID:"
2049 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
2050 nand_manuf_ids[maf_idx].name, type->name);
2051
2052 return type;
2053}
2054
2055/* module_text_address() isn't exported, and it's mostly a pointless
2056 test if this is a module _anyway_ -- they'd have to try _really_ hard
2057 to call us from in-kernel code if the core NAND support is modular. */
2058#ifdef MODULE
2059#define caller_is_module() (1)
2060#else
2061#define caller_is_module() \
2062 module_text_address((unsigned long)__builtin_return_address(0))
2063#endif
2064
2065/**
2066 * nand_scan - [NAND Interface] Scan for the NAND device
2067 * @mtd: MTD device structure
2068 * @maxchips: Number of chips to scan for
2069 *
2070 * This fills out all the uninitialized function pointers
2071 * with the defaults.
2072 * The flash ID is read and the mtd/chip structures are
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002073 * filled with the appropriate values.
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002074 * The mtd->owner field must be set to the module of the caller
2075 *
2076 */
2077int nand_scan(struct mtd_info *mtd, int maxchips)
2078{
2079 int i, busw, nand_maf_id;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002080 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002081 struct nand_flash_dev *type;
2082
2083 /* Many callers got this wrong, so check for it for a while... */
2084 if (!mtd->owner && caller_is_module()) {
2085 printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
2086 BUG();
2087 }
2088
2089 /* Get buswidth to select the correct functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002090 busw = chip->options & NAND_BUSWIDTH_16;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002091 /* Set the default functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002092 nand_set_defaults(chip, busw);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002093
2094 /* Read the flash type */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002095 type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002096
2097 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002098 printk(KERN_WARNING "No NAND device found!!!\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002099 chip->select_chip(mtd, -1);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002100 return PTR_ERR(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 }
2102
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002103 /* Check for a chip array */
David Woodhousee0c7d762006-05-13 18:07:53 +01002104 for (i = 1; i < maxchips; i++) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002105 chip->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002107 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002109 if (nand_maf_id != chip->read_byte(mtd) ||
2110 type->id != chip->read_byte(mtd))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 break;
2112 }
2113 if (i > 1)
2114 printk(KERN_INFO "%d NAND chips detected\n", i);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002115
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 /* Store the number of chips and calc total size for mtd */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002117 chip->numchips = i;
2118 mtd->size = i * chip->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002120 /* Preset the internal oob write buffer */
2121 memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002122
2123 /*
2124 * If no default placement scheme is given, select an appropriate one
2125 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002126 if (!chip->autooob) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002127 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 case 8:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002129 chip->autooob = &nand_oob_8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 break;
2131 case 16:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002132 chip->autooob = &nand_oob_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 break;
2134 case 64:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002135 chip->autooob = &nand_oob_64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 break;
2137 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002138 printk(KERN_WARNING "No oob scheme defined for "
2139 "oobsize %d\n", mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 BUG();
2141 }
2142 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002143
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002144 /*
2145 * The number of bytes available for the filesystem to place fs
2146 * dependend oob data
2147 */
Thomas Gleixner998cf642005-04-01 08:21:48 +01002148 mtd->oobavail = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002149 for (i = 0; chip->autooob->oobfree[i][1]; i++)
2150 mtd->oobavail += chip->autooob->oobfree[i][1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002152 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002153 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2154 * selected and we have 256 byte pagesize fallback to software ECC
David Woodhousee0c7d762006-05-13 18:07:53 +01002155 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002156 switch (chip->ecc.mode) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002157 case NAND_ECC_HW:
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002158 /* Use standard hwecc read page function ? */
2159 if (!chip->ecc.read_page)
2160 chip->ecc.read_page = nand_read_page_hwecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002161 if (!chip->ecc.write_page)
2162 chip->ecc.write_page = nand_write_page_hwecc;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002163
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002164 case NAND_ECC_HW_SYNDROME:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002165 if (!chip->ecc.calculate || !chip->ecc.correct ||
2166 !chip->ecc.hwctl) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002167 printk(KERN_WARNING "No ECC functions supplied, "
2168 "Hardware ECC not possible\n");
2169 BUG();
2170 }
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002171 /* Use standard syndrome read/write page function ? */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002172 if (!chip->ecc.read_page)
2173 chip->ecc.read_page = nand_read_page_syndrome;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002174 if (!chip->ecc.write_page)
2175 chip->ecc.write_page = nand_write_page_syndrome;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002176
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002177 if (mtd->writesize >= chip->ecc.size)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002178 break;
2179 printk(KERN_WARNING "%d byte HW ECC not possible on "
2180 "%d byte page size, fallback to SW ECC\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002181 chip->ecc.size, mtd->writesize);
2182 chip->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002184 case NAND_ECC_SOFT:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002185 chip->ecc.calculate = nand_calculate_ecc;
2186 chip->ecc.correct = nand_correct_data;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002187 chip->ecc.read_page = nand_read_page_swecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002188 chip->ecc.write_page = nand_write_page_swecc;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002189 chip->ecc.size = 256;
2190 chip->ecc.bytes = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002192
2193 case NAND_ECC_NONE:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002194 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2195 "This is not recommended !!\n");
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002196 chip->ecc.read_page = nand_read_page_swecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002197 chip->ecc.write_page = nand_write_page_swecc;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002198 chip->ecc.size = mtd->writesize;
2199 chip->ecc.bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002202 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002203 chip->ecc.mode);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002204 BUG();
2205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002207 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002208 * Set the number of read / write steps for one page depending on ECC
2209 * mode
2210 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002211 chip->ecc.steps = mtd->writesize / chip->ecc.size;
2212 if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002213 printk(KERN_WARNING "Invalid ecc parameters\n");
2214 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 }
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002216 chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002217
Thomas Gleixner04bbd0e2006-05-25 09:45:29 +02002218 /* Initialize state */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002219 chip->state = FL_READY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
2221 /* De-select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002222 chip->select_chip(mtd, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
2224 /* Invalidate the pagebuffer reference */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002225 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
2227 /* Fill in remaining MTD driver data */
2228 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002229 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 mtd->ecctype = MTD_ECC_SW;
2231 mtd->erase = nand_erase;
2232 mtd->point = NULL;
2233 mtd->unpoint = NULL;
2234 mtd->read = nand_read;
2235 mtd->write = nand_write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 mtd->read_oob = nand_read_oob;
2237 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 mtd->sync = nand_sync;
2239 mtd->lock = NULL;
2240 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002241 mtd->suspend = nand_suspend;
2242 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 mtd->block_isbad = nand_block_isbad;
2244 mtd->block_markbad = nand_block_markbad;
2245
2246 /* and make the autooob the default one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002247 memcpy(&mtd->oobinfo, chip->autooob, sizeof(mtd->oobinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002249 /* Check, if we should skip the bad block table scan */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002250 if (chip->options & NAND_SKIP_BBTSCAN)
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002251 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252
2253 /* Build bad block table */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002254 return chip->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255}
2256
2257/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002258 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 * @mtd: MTD device structure
2260*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002261void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002263 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264
2265#ifdef CONFIG_MTD_PARTITIONS
2266 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002267 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268#endif
2269 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002270 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271
Jesper Juhlfa671642005-11-07 01:01:27 -08002272 /* Free bad block table memory */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002273 kfree(chip->bbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274}
2275
David Woodhousee0c7d762006-05-13 18:07:53 +01002276EXPORT_SYMBOL_GPL(nand_scan);
2277EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002278
2279static int __init nand_base_init(void)
2280{
2281 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2282 return 0;
2283}
2284
2285static void __exit nand_base_exit(void)
2286{
2287 led_trigger_unregister_simple(nand_led_trigger);
2288}
2289
2290module_init(nand_base_init);
2291module_exit(nand_base_exit);
2292
David Woodhousee0c7d762006-05-13 18:07:53 +01002293MODULE_LICENSE("GPL");
2294MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2295MODULE_DESCRIPTION("Generic NAND flash driver code");