blob: e922b829c4beecbb5fbbe4158446b87115fdc406 [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 */
Thomas Gleixner5bd34c02006-05-27 22:16:10 +020055static struct nand_ecclayout nand_oob_8 = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 .eccbytes = 3,
57 .eccpos = {0, 1, 2},
Thomas Gleixner5bd34c02006-05-27 22:16:10 +020058 .oobfree = {
59 {.offset = 3,
60 .length = 2},
61 {.offset = 6,
62 .length = 2}}
Linus Torvalds1da177e2005-04-16 15:20:36 -070063};
64
Thomas Gleixner5bd34c02006-05-27 22:16:10 +020065static struct nand_ecclayout nand_oob_16 = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 .eccbytes = 6,
67 .eccpos = {0, 1, 2, 3, 6, 7},
Thomas Gleixner5bd34c02006-05-27 22:16:10 +020068 .oobfree = {
69 {.offset = 8,
70 . length = 8}}
Linus Torvalds1da177e2005-04-16 15:20:36 -070071};
72
Thomas Gleixner5bd34c02006-05-27 22:16:10 +020073static struct nand_ecclayout nand_oob_64 = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 .eccbytes = 24,
75 .eccpos = {
David Woodhousee0c7d762006-05-13 18:07:53 +010076 40, 41, 42, 43, 44, 45, 46, 47,
77 48, 49, 50, 51, 52, 53, 54, 55,
78 56, 57, 58, 59, 60, 61, 62, 63},
Thomas Gleixner5bd34c02006-05-27 22:16:10 +020079 .oobfree = {
80 {.offset = 2,
81 .length = 38}}
Linus Torvalds1da177e2005-04-16 15:20:36 -070082};
83
84/* This is used for padding purposes in nand_write_oob */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +020085static uint8_t ffchars[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 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 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
90 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
91 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94};
95
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020096static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +020097 size_t *retlen, const uint8_t *buf);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +020098static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +020099 int new_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Thomas Gleixnerd470a972006-05-23 23:48:57 +0200101/*
102 * For devices which display every fart in the system on a seperate LED. Is
103 * compiled away when LED support is disabled.
104 */
105DEFINE_LED_TRIGGER(nand_led_trigger);
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107/**
108 * nand_release_device - [GENERIC] release chip
109 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000110 *
111 * Deselect, release chip lock and wake up anyone waiting on the device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100113static void nand_release_device(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200115 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117 /* De-select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200118 chip->select_chip(mtd, -1);
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100119
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200120 /* Release the controller and the chip */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200121 spin_lock(&chip->controller->lock);
122 chip->controller->active = NULL;
123 chip->state = FL_READY;
124 wake_up(&chip->controller->wq);
125 spin_unlock(&chip->controller->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126}
127
128/**
129 * nand_read_byte - [DEFAULT] read one byte from the chip
130 * @mtd: MTD device structure
131 *
132 * Default read function for 8bit buswith
133 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200134static uint8_t nand_read_byte(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200136 struct nand_chip *chip = mtd->priv;
137 return readb(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138}
139
140/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
142 * @mtd: MTD device structure
143 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000144 * Default read function for 16bit buswith with
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 * endianess conversion
146 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200147static uint8_t nand_read_byte16(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200149 struct nand_chip *chip = mtd->priv;
150 return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151}
152
153/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 * nand_read_word - [DEFAULT] read one word from the chip
155 * @mtd: MTD device structure
156 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000157 * Default read function for 16bit buswith without
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 * endianess conversion
159 */
160static u16 nand_read_word(struct mtd_info *mtd)
161{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200162 struct nand_chip *chip = mtd->priv;
163 return readw(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164}
165
166/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 * nand_select_chip - [DEFAULT] control CE line
168 * @mtd: MTD device structure
169 * @chip: chipnumber to select, -1 for deselect
170 *
171 * Default select function for 1 chip devices.
172 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200173static void nand_select_chip(struct mtd_info *mtd, int chipnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200175 struct nand_chip *chip = mtd->priv;
176
177 switch (chipnr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 case -1:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200179 chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 break;
181 case 0:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 break;
183
184 default:
185 BUG();
186 }
187}
188
189/**
190 * nand_write_buf - [DEFAULT] write buffer to chip
191 * @mtd: MTD device structure
192 * @buf: data buffer
193 * @len: number of bytes to write
194 *
195 * Default write function for 8bit buswith
196 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200197static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198{
199 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200200 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
David Woodhousee0c7d762006-05-13 18:07:53 +0100202 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200203 writeb(buf[i], chip->IO_ADDR_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204}
205
206/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000207 * nand_read_buf - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 * @mtd: MTD device structure
209 * @buf: buffer to store date
210 * @len: number of bytes to read
211 *
212 * Default read function for 8bit buswith
213 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200214static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215{
216 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200217 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
David Woodhousee0c7d762006-05-13 18:07:53 +0100219 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200220 buf[i] = readb(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221}
222
223/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000224 * nand_verify_buf - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 * @mtd: MTD device structure
226 * @buf: buffer containing the data to compare
227 * @len: number of bytes to compare
228 *
229 * Default verify function for 8bit buswith
230 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200231static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232{
233 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200234 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
David Woodhousee0c7d762006-05-13 18:07:53 +0100236 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200237 if (buf[i] != readb(chip->IO_ADDR_R))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 return 0;
240}
241
242/**
243 * nand_write_buf16 - [DEFAULT] write buffer to chip
244 * @mtd: MTD device structure
245 * @buf: data buffer
246 * @len: number of bytes to write
247 *
248 * Default write function for 16bit buswith
249 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200250static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251{
252 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200253 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 u16 *p = (u16 *) buf;
255 len >>= 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000256
David Woodhousee0c7d762006-05-13 18:07:53 +0100257 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200258 writew(p[i], chip->IO_ADDR_W);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000259
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260}
261
262/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000263 * nand_read_buf16 - [DEFAULT] read chip data into buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 * @mtd: MTD device structure
265 * @buf: buffer to store date
266 * @len: number of bytes to read
267 *
268 * Default read function for 16bit buswith
269 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200270static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
272 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200273 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 u16 *p = (u16 *) buf;
275 len >>= 1;
276
David Woodhousee0c7d762006-05-13 18:07:53 +0100277 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200278 p[i] = readw(chip->IO_ADDR_R);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279}
280
281/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000282 * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 * @mtd: MTD device structure
284 * @buf: buffer containing the data to compare
285 * @len: number of bytes to compare
286 *
287 * Default verify function for 16bit buswith
288 */
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200289static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290{
291 int i;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200292 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 u16 *p = (u16 *) buf;
294 len >>= 1;
295
David Woodhousee0c7d762006-05-13 18:07:53 +0100296 for (i = 0; i < len; i++)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200297 if (p[i] != readw(chip->IO_ADDR_R))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 return -EFAULT;
299
300 return 0;
301}
302
303/**
304 * nand_block_bad - [DEFAULT] Read bad block marker from the chip
305 * @mtd: MTD device structure
306 * @ofs: offset from device start
307 * @getchip: 0, if the chip is already selected
308 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000309 * Check, if the block is bad.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 */
311static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
312{
313 int page, chipnr, res = 0;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200314 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 u16 bad;
316
317 if (getchip) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200318 page = (int)(ofs >> chip->page_shift);
319 chipnr = (int)(ofs >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200321 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200324 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000325 } else
David Woodhousee0c7d762006-05-13 18:07:53 +0100326 page = (int)ofs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200328 if (chip->options & NAND_BUSWIDTH_16) {
329 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
330 page & chip->pagemask);
331 bad = cpu_to_le16(chip->read_word(mtd));
332 if (chip->badblockpos & 0x1)
Vitaly Wool49196f32005-11-02 16:54:46 +0000333 bad >>= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 if ((bad & 0xFF) != 0xff)
335 res = 1;
336 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200337 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
338 page & chip->pagemask);
339 if (chip->read_byte(mtd) != 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 res = 1;
341 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000342
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200343 if (getchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 nand_release_device(mtd);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000345
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 return res;
347}
348
349/**
350 * nand_default_block_markbad - [DEFAULT] mark a block bad
351 * @mtd: MTD device structure
352 * @ofs: offset from device start
353 *
354 * This is the default implementation, which can be overridden by
355 * a hardware specific driver.
356*/
357static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
358{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200359 struct nand_chip *chip = mtd->priv;
Thomas Gleixner58dd8f2b2006-05-23 11:52:35 +0200360 uint8_t buf[2] = { 0, 0 };
David Woodhousee0c7d762006-05-13 18:07:53 +0100361 size_t retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 int block;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 /* Get block number */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200365 block = ((int)ofs) >> chip->bbt_erase_shift;
366 if (chip->bbt)
367 chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
369 /* Do we have a flash based bad block table ? */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200370 if (chip->options & NAND_USE_FLASH_BBT)
David Woodhousee0c7d762006-05-13 18:07:53 +0100371 return nand_update_bbt(mtd, ofs);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 /* We write two bytes, so we dont have to mess with 16 bit access */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200374 ofs += mtd->oobsize + (chip->badblockpos & ~0x01);
David Woodhousee0c7d762006-05-13 18:07:53 +0100375 return nand_write_oob(mtd, ofs, 2, &retlen, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376}
377
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000378/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 * nand_check_wp - [GENERIC] check if the chip is write protected
380 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000381 * Check, if the device is write protected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 *
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000383 * The function expects, that the device is already selected
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 */
David Woodhousee0c7d762006-05-13 18:07:53 +0100385static int nand_check_wp(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200387 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 /* Check the WP bit */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200389 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
390 return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391}
392
393/**
394 * nand_block_checkbad - [GENERIC] Check if a block is marked bad
395 * @mtd: MTD device structure
396 * @ofs: offset from device start
397 * @getchip: 0, if the chip is already selected
398 * @allowbbt: 1, if its allowed to access the bbt area
399 *
400 * Check, if the block is bad. Either by reading the bad block table or
401 * calling of the scan function.
402 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200403static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
404 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200406 struct nand_chip *chip = mtd->priv;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000407
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200408 if (!chip->bbt)
409 return chip->block_bad(mtd, ofs, getchip);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000410
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 /* Return info from the table */
David Woodhousee0c7d762006-05-13 18:07:53 +0100412 return nand_isbad_bbt(mtd, ofs, allowbbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413}
414
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000415/*
Thomas Gleixner3b887752005-02-22 21:56:49 +0000416 * Wait for the ready pin, after a command
417 * The timeout is catched later.
418 */
419static void nand_wait_ready(struct mtd_info *mtd)
420{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200421 struct nand_chip *chip = mtd->priv;
David Woodhousee0c7d762006-05-13 18:07:53 +0100422 unsigned long timeo = jiffies + 2;
Thomas Gleixner3b887752005-02-22 21:56:49 +0000423
Richard Purdie8fe833c2006-03-31 02:31:14 -0800424 led_trigger_event(nand_led_trigger, LED_FULL);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000425 /* wait until command is processed or timeout occures */
426 do {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200427 if (chip->dev_ready(mtd))
Richard Purdie8fe833c2006-03-31 02:31:14 -0800428 break;
Ingo Molnar8446f1d2005-09-06 15:16:27 -0700429 touch_softlockup_watchdog();
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000430 } while (time_before(jiffies, timeo));
Richard Purdie8fe833c2006-03-31 02:31:14 -0800431 led_trigger_event(nand_led_trigger, LED_OFF);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000432}
433
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434/**
435 * nand_command - [DEFAULT] Send command to NAND device
436 * @mtd: MTD device structure
437 * @command: the command to be sent
438 * @column: the column address for this command, -1 if none
439 * @page_addr: the page address for this command, -1 if none
440 *
441 * Send command to NAND device. This function is used for small page
442 * devices (256/512 Bytes per page)
443 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200444static void nand_command(struct mtd_info *mtd, unsigned int command,
445 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200447 register struct nand_chip *chip = mtd->priv;
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200448 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 /*
451 * Write out the command to the device.
452 */
453 if (command == NAND_CMD_SEQIN) {
454 int readcmd;
455
Joern Engel28318772006-05-22 23:18:05 +0200456 if (column >= mtd->writesize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 /* OOB area */
Joern Engel28318772006-05-22 23:18:05 +0200458 column -= mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 readcmd = NAND_CMD_READOOB;
460 } else if (column < 256) {
461 /* First 256 bytes --> READ0 */
462 readcmd = NAND_CMD_READ0;
463 } else {
464 column -= 256;
465 readcmd = NAND_CMD_READ1;
466 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200467 chip->cmd_ctrl(mtd, readcmd, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200468 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200470 chip->cmd_ctrl(mtd, command, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200472 /*
473 * Address cycle, when necessary
474 */
475 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
476 /* Serially input address */
477 if (column != -1) {
478 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200479 if (chip->options & NAND_BUSWIDTH_16)
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200480 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200481 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200482 ctrl &= ~NAND_CTRL_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 }
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200484 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200485 chip->cmd_ctrl(mtd, page_addr, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200486 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200487 chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200488 /* One more address cycle for devices > 32MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200489 if (chip->chipsize > (32 << 20))
490 chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200491 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200492 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000493
494 /*
495 * program and erase have their own busy handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 * status and sequential in needs no delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100497 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 case NAND_CMD_PAGEPROG:
501 case NAND_CMD_ERASE1:
502 case NAND_CMD_ERASE2:
503 case NAND_CMD_SEQIN:
504 case NAND_CMD_STATUS:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200505 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 return;
507
508 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200509 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200511 udelay(chip->chip_delay);
512 chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200513 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200514 chip->cmd_ctrl(mtd,
515 NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200516 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 return;
518
David Woodhousee0c7d762006-05-13 18:07:53 +0100519 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000521 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 * If we don't have access to the busy pin, we apply the given
523 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100524 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200525 if (!chip->dev_ready) {
526 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 /* Apply this short delay always to ensure that we do wait tWB in
531 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100532 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000533
534 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535}
536
537/**
538 * nand_command_lp - [DEFAULT] Send command to NAND large page device
539 * @mtd: MTD device structure
540 * @command: the command to be sent
541 * @column: the column address for this command, -1 if none
542 * @page_addr: the page address for this command, -1 if none
543 *
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200544 * Send command to NAND device. This is the version for the new large page
545 * devices We dont have the separate regions as we have in the small page
546 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 *
548 */
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200549static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
550 int column, int page_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200552 register struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
554 /* Emulate NAND_CMD_READOOB */
555 if (command == NAND_CMD_READOOB) {
Joern Engel28318772006-05-22 23:18:05 +0200556 column += mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 command = NAND_CMD_READ0;
558 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000559
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200560 /* Command latch cycle */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200561 chip->cmd_ctrl(mtd, command & 0xff,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200562 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
564 if (column != -1 || page_addr != -1) {
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200565 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
567 /* Serially input address */
568 if (column != -1) {
569 /* Adjust columns for 16 bit buswidth */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200570 if (chip->options & NAND_BUSWIDTH_16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 column >>= 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200572 chip->cmd_ctrl(mtd, column, ctrl);
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200573 ctrl &= ~NAND_CTRL_CHANGE;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200574 chip->cmd_ctrl(mtd, column >> 8, ctrl);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000575 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 if (page_addr != -1) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200577 chip->cmd_ctrl(mtd, page_addr, ctrl);
578 chip->cmd_ctrl(mtd, page_addr >> 8,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200579 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 /* One more address cycle for devices > 128MiB */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200581 if (chip->chipsize > (128 << 20))
582 chip->cmd_ctrl(mtd, page_addr >> 16,
Thomas Gleixner7abd3ef2006-05-23 23:25:53 +0200583 NAND_NCE | NAND_ALE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 }
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200586 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000587
588 /*
589 * program and erase have their own busy handlers
David A. Marlin30f464b2005-01-17 18:35:25 +0000590 * status, sequential in, and deplete1 need no delay
591 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 switch (command) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000593
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 case NAND_CMD_CACHEDPROG:
595 case NAND_CMD_PAGEPROG:
596 case NAND_CMD_ERASE1:
597 case NAND_CMD_ERASE2:
598 case NAND_CMD_SEQIN:
599 case NAND_CMD_STATUS:
David A. Marlin30f464b2005-01-17 18:35:25 +0000600 case NAND_CMD_DEPLETE1:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 return;
602
David Woodhousee0c7d762006-05-13 18:07:53 +0100603 /*
604 * read error status commands require only a short delay
605 */
David A. Marlin30f464b2005-01-17 18:35:25 +0000606 case NAND_CMD_STATUS_ERROR:
607 case NAND_CMD_STATUS_ERROR0:
608 case NAND_CMD_STATUS_ERROR1:
609 case NAND_CMD_STATUS_ERROR2:
610 case NAND_CMD_STATUS_ERROR3:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200611 udelay(chip->chip_delay);
David A. Marlin30f464b2005-01-17 18:35:25 +0000612 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
614 case NAND_CMD_RESET:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200615 if (chip->dev_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 break;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200617 udelay(chip->chip_delay);
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200618 chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
619 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
620 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
621 NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200622 while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 return;
624
625 case NAND_CMD_READ0:
Thomas Gleixner12efdde2006-05-24 22:57:09 +0200626 chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
627 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
628 chip->cmd_ctrl(mtd, NAND_CMD_NONE,
629 NAND_NCE | NAND_CTRL_CHANGE);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000630
David Woodhousee0c7d762006-05-13 18:07:53 +0100631 /* This applies to read commands */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 default:
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000633 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 * If we don't have access to the busy pin, we apply the given
635 * command delay
David Woodhousee0c7d762006-05-13 18:07:53 +0100636 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200637 if (!chip->dev_ready) {
638 udelay(chip->chip_delay);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 return;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000640 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 }
Thomas Gleixner3b887752005-02-22 21:56:49 +0000642
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 /* Apply this short delay always to ensure that we do wait tWB in
644 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100645 ndelay(100);
Thomas Gleixner3b887752005-02-22 21:56:49 +0000646
647 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}
649
650/**
651 * nand_get_device - [GENERIC] Get chip for selected access
652 * @this: the nand chip descriptor
653 * @mtd: MTD device structure
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000654 * @new_state: the state which is requested
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 *
656 * Get the device and lock it for exclusive access
657 */
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +0200658static int
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200659nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200661 spinlock_t *lock = &chip->controller->lock;
662 wait_queue_head_t *wq = &chip->controller->wq;
David Woodhousee0c7d762006-05-13 18:07:53 +0100663 DECLARE_WAITQUEUE(wait, current);
David Woodhousee0c7d762006-05-13 18:07:53 +0100664 retry:
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100665 spin_lock(lock);
666
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 /* Hardware controller shared among independend devices */
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200668 /* Hardware controller shared among independend devices */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200669 if (!chip->controller->active)
670 chip->controller->active = chip;
Thomas Gleixnera36ed292006-05-23 11:37:03 +0200671
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200672 if (chip->controller->active == chip && chip->state == FL_READY) {
673 chip->state = new_state;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100674 spin_unlock(lock);
Vitaly Wool962034f2005-09-15 14:58:53 +0100675 return 0;
676 }
677 if (new_state == FL_PM_SUSPENDED) {
678 spin_unlock(lock);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200679 return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
Thomas Gleixner0dfc6242005-05-31 20:39:20 +0100680 }
681 set_current_state(TASK_UNINTERRUPTIBLE);
682 add_wait_queue(wq, &wait);
683 spin_unlock(lock);
684 schedule();
685 remove_wait_queue(wq, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 goto retry;
687}
688
689/**
690 * nand_wait - [DEFAULT] wait until the command is done
691 * @mtd: MTD device structure
692 * @this: NAND chip structure
693 * @state: state to select the max. timeout value
694 *
695 * Wait for command done. This applies to erase and program only
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000696 * Erase can take up to 400ms and program up to 20ms according to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 * general NAND and SmartMedia specs
698 *
699*/
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200700static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
702
David Woodhousee0c7d762006-05-13 18:07:53 +0100703 unsigned long timeo = jiffies;
704 int status;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000705
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 if (state == FL_ERASING)
David Woodhousee0c7d762006-05-13 18:07:53 +0100707 timeo += (HZ * 400) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 else
David Woodhousee0c7d762006-05-13 18:07:53 +0100709 timeo += (HZ * 20) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Richard Purdie8fe833c2006-03-31 02:31:14 -0800711 led_trigger_event(nand_led_trigger, LED_FULL);
712
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 /* Apply this short delay always to ensure that we do wait tWB in
714 * any case on any machine. */
David Woodhousee0c7d762006-05-13 18:07:53 +0100715 ndelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200717 if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
718 chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000719 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200720 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000722 while (time_before(jiffies, timeo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 /* Check, if we were interrupted */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200724 if (chip->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 return 0;
726
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200727 if (chip->dev_ready) {
728 if (chip->dev_ready(mtd))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000729 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 } else {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200731 if (chip->read_byte(mtd) & NAND_STATUS_READY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 break;
733 }
Thomas Gleixner20a6c212005-03-01 09:32:48 +0000734 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 }
Richard Purdie8fe833c2006-03-31 02:31:14 -0800736 led_trigger_event(nand_led_trigger, LED_OFF);
737
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200738 status = (int)chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 return status;
740}
741
742/**
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200743 * nand_read_page_swecc - {REPLACABLE] software ecc based page read function
744 * @mtd: mtd info structure
745 * @chip: nand chip info structure
746 * @buf: buffer to store read data
David A. Marlin068e3c02005-01-24 03:07:46 +0000747 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200748static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
749 uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200751 int i, eccsize = chip->ecc.size;
752 int eccbytes = chip->ecc.bytes;
753 int eccsteps = chip->ecc.steps;
754 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200755 uint8_t *ecc_calc = chip->buffers.ecccalc;
756 uint8_t *ecc_code = chip->buffers.ecccode;
Thomas Gleixner5bd34c02006-05-27 22:16:10 +0200757 int *eccpos = chip->ecc.layout->eccpos;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200758
759 chip->read_buf(mtd, buf, mtd->writesize);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200760 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200761
762 if (chip->ecc.mode == NAND_ECC_NONE)
763 return 0;
764
765 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
766 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
767
768 for (i = 0; i < chip->ecc.total; i++)
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200769 ecc_code[i] = chip->oob_poi[eccpos[i]];
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200770
771 eccsteps = chip->ecc.steps;
772 p = buf;
773
774 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
775 int stat;
776
777 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
778 if (stat == -1)
779 mtd->ecc_stats.failed++;
780 else
781 mtd->ecc_stats.corrected += stat;
782 }
783 return 0;
Thomas Gleixner22c60f52005-04-04 19:56:32 +0100784}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786/**
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200787 * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function
788 * @mtd: mtd info structure
789 * @chip: nand chip info structure
790 * @buf: buffer to store read data
791 *
792 * Not for syndrome calculating ecc controllers which need a special oob layout
793 */
794static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
795 uint8_t *buf)
796{
797 int i, eccsize = chip->ecc.size;
798 int eccbytes = chip->ecc.bytes;
799 int eccsteps = chip->ecc.steps;
800 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200801 uint8_t *ecc_calc = chip->buffers.ecccalc;
802 uint8_t *ecc_code = chip->buffers.ecccode;
Thomas Gleixner5bd34c02006-05-27 22:16:10 +0200803 int *eccpos = chip->ecc.layout->eccpos;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200804
805 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
806 chip->ecc.hwctl(mtd, NAND_ECC_READ);
807 chip->read_buf(mtd, p, eccsize);
808 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
809 }
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200810 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200811
812 for (i = 0; i < chip->ecc.total; i++)
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200813 ecc_code[i] = chip->oob_poi[eccpos[i]];
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200814
815 eccsteps = chip->ecc.steps;
816 p = buf;
817
818 for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
819 int stat;
820
821 stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
822 if (stat == -1)
823 mtd->ecc_stats.failed++;
824 else
825 mtd->ecc_stats.corrected += stat;
826 }
827 return 0;
828}
829
830/**
831 * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
832 * @mtd: mtd info structure
833 * @chip: nand chip info structure
834 * @buf: buffer to store read data
835 *
836 * The hw generator calculates the error syndrome automatically. Therefor
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200837 * we need a special oob layout and handling.
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200838 */
839static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
840 uint8_t *buf)
841{
842 int i, eccsize = chip->ecc.size;
843 int eccbytes = chip->ecc.bytes;
844 int eccsteps = chip->ecc.steps;
845 uint8_t *p = buf;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200846 uint8_t *oob = chip->oob_poi;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200847
848 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
849 int stat;
850
851 chip->ecc.hwctl(mtd, NAND_ECC_READ);
852 chip->read_buf(mtd, p, eccsize);
853
854 if (chip->ecc.prepad) {
855 chip->read_buf(mtd, oob, chip->ecc.prepad);
856 oob += chip->ecc.prepad;
857 }
858
859 chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
860 chip->read_buf(mtd, oob, eccbytes);
861 stat = chip->ecc.correct(mtd, p, oob, NULL);
862
863 if (stat == -1)
864 mtd->ecc_stats.failed++;
865 else
866 mtd->ecc_stats.corrected += stat;
867
868 oob += eccbytes;
869
870 if (chip->ecc.postpad) {
871 chip->read_buf(mtd, oob, chip->ecc.postpad);
872 oob += chip->ecc.postpad;
873 }
874 }
875
876 /* Calculate remaining oob bytes */
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200877 i = oob - chip->oob_poi;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200878 if (i)
879 chip->read_buf(mtd, oob, i);
880
881 return 0;
882}
883
884/**
885 * nand_do_read - [Internal] Read data with ECC
886 *
David A. Marlin068e3c02005-01-24 03:07:46 +0000887 * @mtd: MTD device structure
888 * @from: offset to read from
889 * @len: number of bytes to read
890 * @retlen: pointer to variable to store the number of read bytes
891 * @buf: the databuffer to put data
David A. Marlin068e3c02005-01-24 03:07:46 +0000892 *
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200893 * Internal function. Called with chip held.
David A. Marlin068e3c02005-01-24 03:07:46 +0000894 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200895int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
896 size_t *retlen, uint8_t *buf)
David A. Marlin068e3c02005-01-24 03:07:46 +0000897{
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200898 int chipnr, page, realpage, col, bytes, aligned;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200899 struct nand_chip *chip = mtd->priv;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200900 struct mtd_ecc_stats stats;
901 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
902 int sndcmd = 1;
903 int ret = 0;
904 uint32_t readlen = len;
905 uint8_t *bufpoi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200907 stats = mtd->ecc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200909 chipnr = (int)(from >> chip->chip_shift);
910 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200912 realpage = (int)(from >> chip->page_shift);
913 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200915 col = (int)(from & (mtd->writesize - 1));
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200916 chip->oob_poi = chip->buffers.oobrbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200918 while(1) {
919 bytes = min(mtd->writesize - col, readlen);
920 aligned = (bytes == mtd->writesize);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000921
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200922 /* Is the current page in the buffer ? */
923 if (realpage != chip->pagebuf) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200924 bufpoi = aligned ? buf : chip->buffers.databuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200926 if (likely(sndcmd)) {
927 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
928 sndcmd = 0;
929 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200931 /* Now read the page into the buffer */
932 ret = chip->ecc.read_page(mtd, chip, bufpoi);
933 if (ret < 0)
David Woodhousee0c7d762006-05-13 18:07:53 +0100934 break;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200935
936 /* Transfer not aligned data */
937 if (!aligned) {
938 chip->pagebuf = realpage;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200939 memcpy(buf, chip->buffers.databuf + col, bytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000941
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200942 if (!(chip->options & NAND_NO_READRDY)) {
943 /*
944 * Apply delay or wait for ready/busy pin. Do
945 * this before the AUTOINCR check, so no
946 * problems arise if a chip which does auto
947 * increment is marked as NOAUTOINCR by the
948 * board driver.
949 */
950 if (!chip->dev_ready)
951 udelay(chip->chip_delay);
952 else
953 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000955 } else
Thomas Gleixnerf75e5092006-05-26 18:52:08 +0200956 memcpy(buf, chip->buffers.databuf + col, bytes);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200958 buf += bytes;
959 readlen -= bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000960
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200961 if (!readlen)
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000962 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
964 /* For subsequent reads align to page boundary. */
965 col = 0;
966 /* Increment page address */
967 realpage++;
968
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200969 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 /* Check, if we cross a chip boundary */
971 if (!page) {
972 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +0200973 chip->select_chip(mtd, -1);
974 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 }
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200976
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000977 /* Check, if the chip supports auto page increment
978 * or if we have hit a block boundary.
David Woodhousee0c7d762006-05-13 18:07:53 +0100979 */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200980 if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
Thomas Gleixner61b03bd2005-11-07 11:15:49 +0000981 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 }
983
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200984 *retlen = len - (size_t) readlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +0200986 if (ret)
987 return ret;
988
989 return mtd->ecc_stats.failed - stats.failed ? -EBADMSG : 0;
990}
991
992/**
993 * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
994 * @mtd: MTD device structure
995 * @from: offset to read from
996 * @len: number of bytes to read
997 * @retlen: pointer to variable to store the number of read bytes
998 * @buf: the databuffer to put data
999 *
1000 * Get hold of the chip and call nand_do_read
1001 */
1002static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
1003 size_t *retlen, uint8_t *buf)
1004{
1005 int ret;
1006
1007 *retlen = 0;
1008 /* Do not allow reads past end of device */
1009 if ((from + len) > mtd->size)
1010 return -EINVAL;
1011 if (!len)
1012 return 0;
1013
1014 nand_get_device(mtd->priv, mtd, FL_READING);
1015
1016 ret = nand_do_read(mtd, from, len, retlen, buf);
1017
1018 nand_release_device(mtd);
1019
1020 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021}
1022
1023/**
1024 * nand_read_oob - [MTD Interface] NAND read out-of-band
1025 * @mtd: MTD device structure
1026 * @from: offset to read from
1027 * @len: number of bytes to read
1028 * @retlen: pointer to variable to store the number of read bytes
1029 * @buf: the databuffer to put data
1030 *
1031 * NAND read out-of-band data from the spare area
1032 */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001033static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
1034 size_t *retlen, uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035{
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001036 int col, page, realpage, chipnr, sndcmd = 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001037 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001038 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1039 int readlen = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001041 DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n",
1042 (unsigned int)from, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
1044 /* Initialize return length value */
1045 *retlen = 0;
1046
1047 /* Do not allow reads past end of device */
1048 if ((from + len) > mtd->size) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001049 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
1050 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 return -EINVAL;
1052 }
1053
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001054 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001056 chipnr = (int)(from >> chip->chip_shift);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001057 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001059 /* Shift to get page */
1060 realpage = (int)(from >> chip->page_shift);
1061 page = realpage & chip->pagemask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001063 /* Mask to get column */
1064 col = from & (mtd->oobsize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001066 while(1) {
1067 int bytes = min((int)(mtd->oobsize - col), readlen);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001068
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001069 if (likely(sndcmd)) {
1070 chip->cmdfunc(mtd, NAND_CMD_READOOB, col, page);
1071 sndcmd = 0;
1072 }
1073
1074 chip->read_buf(mtd, buf, bytes);
1075
1076 readlen -= bytes;
1077 if (!readlen)
1078 break;
1079
1080 if (!(chip->options & NAND_NO_READRDY)) {
1081 /*
1082 * Apply delay or wait for ready/busy pin. Do this
1083 * before the AUTOINCR check, so no problems arise if a
1084 * chip which does auto increment is marked as
1085 * NOAUTOINCR by the board driver.
Thomas Gleixner19870da2005-07-15 14:53:51 +01001086 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001087 if (!chip->dev_ready)
1088 udelay(chip->chip_delay);
Thomas Gleixner19870da2005-07-15 14:53:51 +01001089 else
1090 nand_wait_ready(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 }
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001092
1093 buf += bytes;
1094 bytes = mtd->oobsize;
1095 col = 0;
1096
1097 /* Increment page address */
1098 realpage++;
1099
1100 page = realpage & chip->pagemask;
1101 /* Check, if we cross a chip boundary */
1102 if (!page) {
1103 chipnr++;
1104 chip->select_chip(mtd, -1);
1105 chip->select_chip(mtd, chipnr);
1106 }
1107
1108 /* Check, if the chip supports auto page increment
1109 * or if we have hit a block boundary.
1110 */
1111 if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
1112 sndcmd = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 }
1114
1115 /* Deselect and wake up anyone waiting on the device */
1116 nand_release_device(mtd);
1117
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 *retlen = len;
1119 return 0;
1120}
1121
1122/**
1123 * nand_read_raw - [GENERIC] Read raw data including oob into buffer
1124 * @mtd: MTD device structure
1125 * @buf: temporary buffer
1126 * @from: offset to read from
1127 * @len: number of bytes to read
1128 * @ooblen: number of oob data bytes to read
1129 *
1130 * Read raw data including oob into buffer
1131 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001132int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len,
1133 size_t ooblen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001135 struct nand_chip *chip = mtd->priv;
1136 int page = (int)(from >> chip->page_shift);
1137 int chipnr = (int)(from >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 int sndcmd = 1;
1139 int cnt = 0;
Joern Engel28318772006-05-22 23:18:05 +02001140 int pagesize = mtd->writesize + mtd->oobsize;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001141 int blockcheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143 /* Do not allow reads past end of device */
1144 if ((from + len) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001145 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: "
1146 "Attempt read beyond end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 return -EINVAL;
1148 }
1149
1150 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001151 nand_get_device(chip, mtd, FL_READING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001153 chip->select_chip(mtd, chipnr);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 /* Add requested oob length */
1156 len += ooblen;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001157 blockcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001158
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 while (len) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001160 if (likely(sndcmd)) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001161 chip->cmdfunc(mtd, NAND_CMD_READ0, 0,
1162 page & chip->pagemask);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001163 sndcmd = 0;
1164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001166 chip->read_buf(mtd, &buf[cnt], pagesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
1168 len -= pagesize;
1169 cnt += pagesize;
1170 page++;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001171
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001172 if (!(chip->options & NAND_NO_READRDY)) {
1173 if (!chip->dev_ready)
1174 udelay(chip->chip_delay);
1175 else
1176 nand_wait_ready(mtd);
1177 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001178
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001179 /*
1180 * Check, if the chip supports auto page increment or if we
1181 * cross a block boundary.
1182 */
1183 if (!NAND_CANAUTOINCR(chip) || !(page & blockcheck))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 sndcmd = 1;
1185 }
1186
1187 /* Deselect and wake up anyone waiting on the device */
1188 nand_release_device(mtd);
1189 return 0;
1190}
1191
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001192/**
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001193 * nand_write_page_swecc - {REPLACABLE] software ecc based page write function
1194 * @mtd: mtd info structure
1195 * @chip: nand chip info structure
1196 * @buf: data buffer
1197 */
1198static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
1199 const uint8_t *buf)
1200{
1201 int i, eccsize = chip->ecc.size;
1202 int eccbytes = chip->ecc.bytes;
1203 int eccsteps = chip->ecc.steps;
1204 uint8_t *ecc_calc = chip->buffers.ecccalc;
1205 const uint8_t *p = buf;
Thomas Gleixner5bd34c02006-05-27 22:16:10 +02001206 int *eccpos = chip->ecc.layout->eccpos;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001207
1208 if (chip->ecc.mode != NAND_ECC_NONE) {
1209 /* Software ecc calculation */
1210 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
1211 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1212
1213 for (i = 0; i < chip->ecc.total; i++)
1214 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1215 }
1216
1217 chip->write_buf(mtd, buf, mtd->writesize);
1218 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1219}
1220
1221/**
1222 * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function
1223 * @mtd: mtd info structure
1224 * @chip: nand chip info structure
1225 * @buf: data buffer
1226 */
1227static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
1228 const uint8_t *buf)
1229{
1230 int i, eccsize = chip->ecc.size;
1231 int eccbytes = chip->ecc.bytes;
1232 int eccsteps = chip->ecc.steps;
1233 uint8_t *ecc_calc = chip->buffers.ecccalc;
1234 const uint8_t *p = buf;
Thomas Gleixner5bd34c02006-05-27 22:16:10 +02001235 int *eccpos = chip->ecc.layout->eccpos;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001236
1237 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
1238 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
David Woodhouse29da9ce2006-05-26 23:05:44 +01001239 chip->write_buf(mtd, p, eccsize);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001240 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1241 }
1242
1243 for (i = 0; i < chip->ecc.total; i++)
1244 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1245
1246 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1247}
1248
1249/**
1250 * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write
1251 * @mtd: mtd info structure
1252 * @chip: nand chip info structure
1253 * @buf: data buffer
1254 *
1255 * The hw generator calculates the error syndrome automatically. Therefor
1256 * we need a special oob layout and handling.
1257 */
1258static void nand_write_page_syndrome(struct mtd_info *mtd,
1259 struct nand_chip *chip, const uint8_t *buf)
1260{
1261 int i, eccsize = chip->ecc.size;
1262 int eccbytes = chip->ecc.bytes;
1263 int eccsteps = chip->ecc.steps;
1264 const uint8_t *p = buf;
1265 uint8_t *oob = chip->oob_poi;
1266
1267 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
1268
1269 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
1270 chip->write_buf(mtd, p, eccsize);
1271
1272 if (chip->ecc.prepad) {
1273 chip->write_buf(mtd, oob, chip->ecc.prepad);
1274 oob += chip->ecc.prepad;
1275 }
1276
1277 chip->ecc.calculate(mtd, p, oob);
1278 chip->write_buf(mtd, oob, eccbytes);
1279 oob += eccbytes;
1280
1281 if (chip->ecc.postpad) {
1282 chip->write_buf(mtd, oob, chip->ecc.postpad);
1283 oob += chip->ecc.postpad;
1284 }
1285 }
1286
1287 /* Calculate remaining oob bytes */
1288 i = oob - chip->oob_poi;
1289 if (i)
1290 chip->write_buf(mtd, oob, i);
1291}
1292
1293/**
1294 * nand_write_page - [INTERNAL] write one page
1295 * @mtd: MTD device structure
1296 * @chip: NAND chip descriptor
1297 * @buf: the data to write
1298 * @page: page number to write
1299 * @cached: cached programming
1300 */
1301static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
1302 const uint8_t *buf, int page, int cached)
1303{
1304 int status;
1305
1306 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
1307
1308 chip->ecc.write_page(mtd, chip, buf);
1309
1310 /*
1311 * Cached progamming disabled for now, Not sure if its worth the
1312 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
1313 */
1314 cached = 0;
1315
1316 if (!cached || !(chip->options & NAND_CACHEPRG)) {
1317
1318 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1319 status = chip->waitfunc(mtd, chip, FL_WRITING);
1320 /*
1321 * See if operation failed and additional status checks are
1322 * available
1323 */
1324 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
1325 status = chip->errstat(mtd, chip, FL_WRITING, status,
1326 page);
1327
1328 if (status & NAND_STATUS_FAIL)
1329 return -EIO;
1330 } else {
1331 chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
1332 status = chip->waitfunc(mtd, chip, FL_WRITING);
1333 }
1334
1335#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1336 /* Send command to read back the data */
1337 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1338
1339 if (chip->verify_buf(mtd, buf, mtd->writesize))
1340 return -EIO;
1341#endif
1342 return 0;
1343}
1344
1345#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
1346
1347/**
1348 * nand_write - [MTD Interface] NAND write with ECC
1349 * @mtd: MTD device structure
1350 * @to: offset to write to
1351 * @len: number of bytes to write
1352 * @retlen: pointer to variable to store the number of written bytes
1353 * @buf: the data to write
1354 *
1355 * NAND write with ECC
1356 */
1357static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1358 size_t *retlen, const uint8_t *buf)
1359{
1360 int chipnr, realpage, page, blockmask;
1361 struct nand_chip *chip = mtd->priv;
1362 uint32_t writelen = len;
1363 int bytes = mtd->writesize;
1364 int ret = -EIO;
1365
1366 *retlen = 0;
1367
1368 /* Do not allow write past end of device */
1369 if ((to + len) > mtd->size) {
1370 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: "
1371 "Attempt to write past end of page\n");
1372 return -EINVAL;
1373 }
1374
1375 /* reject writes, which are not page aligned */
1376 if (NOTALIGNED(to) || NOTALIGNED(len)) {
1377 printk(KERN_NOTICE "nand_write: "
1378 "Attempt to write not page aligned data\n");
1379 return -EINVAL;
1380 }
1381
1382 if (!len)
1383 return 0;
1384
1385 nand_get_device(chip, mtd, FL_WRITING);
1386
1387 /* Check, if it is write protected */
1388 if (nand_check_wp(mtd))
1389 goto out;
1390
1391 chipnr = (int)(to >> chip->chip_shift);
1392 chip->select_chip(mtd, chipnr);
1393
1394 realpage = (int)(to >> chip->page_shift);
1395 page = realpage & chip->pagemask;
1396 blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1397
1398 /* Invalidate the page cache, when we write to the cached page */
1399 if (to <= (chip->pagebuf << chip->page_shift) &&
1400 (chip->pagebuf << chip->page_shift) < (to + len))
1401 chip->pagebuf = -1;
1402
1403 chip->oob_poi = chip->buffers.oobwbuf;
1404
1405 while(1) {
1406 int cached = writelen > bytes && page != blockmask;
1407
1408 ret = nand_write_page(mtd, chip, buf, page, cached);
1409 if (ret)
1410 break;
1411
1412 writelen -= bytes;
1413 if (!writelen)
1414 break;
1415
1416 buf += bytes;
1417 realpage++;
1418
1419 page = realpage & chip->pagemask;
1420 /* Check, if we cross a chip boundary */
1421 if (!page) {
1422 chipnr++;
1423 chip->select_chip(mtd, -1);
1424 chip->select_chip(mtd, chipnr);
1425 }
1426 }
1427 out:
1428 *retlen = len - writelen;
1429 nand_release_device(mtd);
1430 return ret;
1431}
1432
1433/**
Thomas Gleixner9223a452006-05-23 17:21:03 +02001434 * nand_write_raw - [GENERIC] Write raw data including oob
1435 * @mtd: MTD device structure
1436 * @buf: source buffer
1437 * @to: offset to write to
1438 * @len: number of bytes to write
1439 * @buf: source buffer
1440 * @oob: oob buffer
1441 *
1442 * Write raw data including oob
1443 */
1444int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001445 const uint8_t *buf, uint8_t *oob)
Thomas Gleixner9223a452006-05-23 17:21:03 +02001446{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001447 struct nand_chip *chip = mtd->priv;
1448 int page = (int)(to >> chip->page_shift);
1449 int chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001450 int ret;
1451
1452 *retlen = 0;
1453
1454 /* Do not allow writes past end of device */
1455 if ((to + len) > mtd->size) {
1456 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1457 "beyond end of device\n");
1458 return -EINVAL;
1459 }
1460
1461 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001462 nand_get_device(chip, mtd, FL_WRITING);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001463
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001464 chip->select_chip(mtd, chipnr);
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001465 chip->oob_poi = oob;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001466
1467 while (len != *retlen) {
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001468 ret = nand_write_page(mtd, chip, buf, page, 0);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001469 if (ret)
1470 return ret;
1471 page++;
1472 *retlen += mtd->writesize;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001473 buf += mtd->writesize;
1474 chip->oob_poi += mtd->oobsize;
Thomas Gleixner9223a452006-05-23 17:21:03 +02001475 }
1476
1477 /* Deselect and wake up anyone waiting on the device */
1478 nand_release_device(mtd);
1479 return 0;
1480}
Thomas Gleixner38217202006-05-23 22:33:52 +02001481EXPORT_SYMBOL_GPL(nand_write_raw);
Thomas Gleixner9223a452006-05-23 17:21:03 +02001482
1483/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 * nand_write_oob - [MTD Interface] NAND write out-of-band
1485 * @mtd: MTD device structure
1486 * @to: offset to write to
1487 * @len: number of bytes to write
1488 * @retlen: pointer to variable to store the number of written bytes
1489 * @buf: the data to write
1490 *
1491 * NAND write out-of-band
1492 */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001493static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1494 size_t *retlen, const uint8_t *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495{
1496 int column, page, status, ret = -EIO, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001497 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001499 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
1500 (unsigned int)to, (int)len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
1502 /* Initialize return length value */
1503 *retlen = 0;
1504
1505 /* Do not allow write past end of page */
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001506 column = to & (mtd->oobsize - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 if ((column + len) > mtd->oobsize) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001508 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1509 "Attempt to write past end of page\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 return -EINVAL;
1511 }
1512
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001513 nand_get_device(chip, mtd, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001515 chipnr = (int)(to >> chip->chip_shift);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001516 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001518 /* Shift to get page */
1519 page = (int)(to >> chip->page_shift);
1520
1521 /*
1522 * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
1523 * of my DiskOnChip 2000 test units) will clear the whole data page too
1524 * if we don't do this. I have no clue why, but I seem to have 'fixed'
1525 * it in the doc2000 driver in August 1999. dwmw2.
1526 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001527 chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
1529 /* Check, if it is write protected */
1530 if (nand_check_wp(mtd))
1531 goto out;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001532
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 /* Invalidate the page cache, if we write to the cached page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001534 if (page == chip->pagebuf)
1535 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001537 if (NAND_MUST_PAD(chip)) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001538 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
1539 page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 /* prepad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001541 chip->write_buf(mtd, ffchars, column);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 /* write data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001543 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 /* postpad 0xff for partial programming */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001545 chip->write_buf(mtd, ffchars, mtd->oobsize - (len + column));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 } else {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001547 chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + column,
1548 page & chip->pagemask);
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001549 chip->write_buf(mtd, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 }
1551 /* Send command to program the OOB data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001552 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001554 status = chip->waitfunc(mtd, chip, FL_WRITING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556 /* See if device thinks it succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001557 if (status & NAND_STATUS_FAIL) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001558 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1559 "Failed write, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 ret = -EIO;
1561 goto out;
1562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 *retlen = len;
1564
1565#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
1566 /* Send command to read back the data */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001567 chip->cmdfunc(mtd, NAND_CMD_READOOB, column, page & chip->pagemask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001569 if (chip->verify_buf(mtd, buf, len)) {
Thomas Gleixner7314e9e2006-05-25 09:51:54 +02001570 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
1571 "Failed write verify, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 ret = -EIO;
1573 goto out;
1574 }
1575#endif
1576 ret = 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001577 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 /* Deselect and wake up anyone waiting on the device */
1579 nand_release_device(mtd);
1580
1581 return ret;
1582}
1583
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 * single_erease_cmd - [GENERIC] NAND standard block erase command function
1586 * @mtd: MTD device structure
1587 * @page: the page address of the block which will be erased
1588 *
1589 * Standard erase command for NAND chips
1590 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001591static void single_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001593 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001595 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1596 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597}
1598
1599/**
1600 * multi_erease_cmd - [GENERIC] AND specific block erase command function
1601 * @mtd: MTD device structure
1602 * @page: the page address of the block which will be erased
1603 *
1604 * AND multi block erase command function
1605 * Erase 4 consecutive blocks
1606 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001607static void multi_erase_cmd(struct mtd_info *mtd, int page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001609 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 /* Send commands to erase a block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001611 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1612 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1613 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
1614 chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1615 chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616}
1617
1618/**
1619 * nand_erase - [MTD Interface] erase block(s)
1620 * @mtd: MTD device structure
1621 * @instr: erase instruction
1622 *
1623 * Erase one ore more blocks
1624 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001625static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626{
David Woodhousee0c7d762006-05-13 18:07:53 +01001627 return nand_erase_nand(mtd, instr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628}
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001629
David A. Marlin30f464b2005-01-17 18:35:25 +00001630#define BBT_PAGE_MASK 0xffffff3f
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001632 * nand_erase_nand - [Internal] erase block(s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 * @mtd: MTD device structure
1634 * @instr: erase instruction
1635 * @allowbbt: allow erasing the bbt area
1636 *
1637 * Erase one ore more blocks
1638 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001639int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
1640 int allowbbt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641{
1642 int page, len, status, pages_per_block, ret, chipnr;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001643 struct nand_chip *chip = mtd->priv;
1644 int rewrite_bbt[NAND_MAX_CHIPS]={0};
1645 unsigned int bbt_masked_page = 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001647 DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
1648 (unsigned int)instr->addr, (unsigned int)instr->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
1650 /* Start address must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001651 if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01001652 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 return -EINVAL;
1654 }
1655
1656 /* Length must align on block boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001657 if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
1658 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1659 "Length not block aligned\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 return -EINVAL;
1661 }
1662
1663 /* Do not allow erase past end of device */
1664 if ((instr->len + instr->addr) > mtd->size) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001665 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1666 "Erase past end of device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 return -EINVAL;
1668 }
1669
1670 instr->fail_addr = 0xffffffff;
1671
1672 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001673 nand_get_device(chip, mtd, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
1675 /* Shift to get first page */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001676 page = (int)(instr->addr >> chip->page_shift);
1677 chipnr = (int)(instr->addr >> chip->chip_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
1679 /* Calculate pages in each block */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001680 pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
1682 /* Select the NAND device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001683 chip->select_chip(mtd, chipnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 /* Check, if it is write protected */
1686 if (nand_check_wp(mtd)) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001687 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1688 "Device is write protected!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 instr->state = MTD_ERASE_FAILED;
1690 goto erase_exit;
1691 }
1692
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001693 /*
1694 * If BBT requires refresh, set the BBT page mask to see if the BBT
1695 * should be rewritten. Otherwise the mask is set to 0xffffffff which
1696 * can not be matched. This is also done when the bbt is actually
1697 * erased to avoid recusrsive updates
1698 */
1699 if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
1700 bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
David A. Marlin30f464b2005-01-17 18:35:25 +00001701
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 /* Loop through the pages */
1703 len = instr->len;
1704
1705 instr->state = MTD_ERASING;
1706
1707 while (len) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001708 /*
1709 * heck if we have a bad block, we do not erase bad blocks !
1710 */
1711 if (nand_block_checkbad(mtd, ((loff_t) page) <<
1712 chip->page_shift, 0, allowbbt)) {
1713 printk(KERN_WARNING "nand_erase: attempt to erase a "
1714 "bad block at page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 instr->state = MTD_ERASE_FAILED;
1716 goto erase_exit;
1717 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001718
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001719 /*
1720 * Invalidate the page cache, if we erase the block which
1721 * contains the current cached page
1722 */
1723 if (page <= chip->pagebuf && chip->pagebuf <
1724 (page + pages_per_block))
1725 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001727 chip->erase_cmd(mtd, page & chip->pagemask);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001728
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001729 status = chip->waitfunc(mtd, chip, FL_ERASING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001731 /*
1732 * See if operation failed and additional status checks are
1733 * available
1734 */
1735 if ((status & NAND_STATUS_FAIL) && (chip->errstat))
1736 status = chip->errstat(mtd, chip, FL_ERASING,
1737 status, page);
David A. Marlin068e3c02005-01-24 03:07:46 +00001738
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 /* See if block erase succeeded */
David A. Marlina4ab4c52005-01-23 18:30:53 +00001740 if (status & NAND_STATUS_FAIL) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001741 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
1742 "Failed erase, page 0x%08x\n", page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 instr->state = MTD_ERASE_FAILED;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001744 instr->fail_addr = (page << chip->page_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 goto erase_exit;
1746 }
David A. Marlin30f464b2005-01-17 18:35:25 +00001747
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001748 /*
1749 * If BBT requires refresh, set the BBT rewrite flag to the
1750 * page being erased
1751 */
1752 if (bbt_masked_page != 0xffffffff &&
1753 (page & BBT_PAGE_MASK) == bbt_masked_page)
1754 rewrite_bbt[chipnr] = (page << chip->page_shift);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 /* Increment page address and decrement length */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001757 len -= (1 << chip->phys_erase_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 page += pages_per_block;
1759
1760 /* Check, if we cross a chip boundary */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001761 if (len && !(page & chip->pagemask)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 chipnr++;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001763 chip->select_chip(mtd, -1);
1764 chip->select_chip(mtd, chipnr);
David A. Marlin30f464b2005-01-17 18:35:25 +00001765
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001766 /*
1767 * If BBT requires refresh and BBT-PERCHIP, set the BBT
1768 * page mask to see if this BBT should be rewritten
1769 */
1770 if (bbt_masked_page != 0xffffffff &&
1771 (chip->bbt_td->options & NAND_BBT_PERCHIP))
1772 bbt_masked_page = chip->bbt_td->pages[chipnr] &
1773 BBT_PAGE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 }
1775 }
1776 instr->state = MTD_ERASE_DONE;
1777
David Woodhousee0c7d762006-05-13 18:07:53 +01001778 erase_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779
1780 ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
1781 /* Do call back function */
1782 if (!ret)
1783 mtd_erase_callback(instr);
1784
1785 /* Deselect and wake up anyone waiting on the device */
1786 nand_release_device(mtd);
1787
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001788 /*
1789 * If BBT requires refresh and erase was successful, rewrite any
1790 * selected bad block tables
1791 */
1792 if (bbt_masked_page == 0xffffffff || ret)
1793 return ret;
1794
1795 for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
1796 if (!rewrite_bbt[chipnr])
1797 continue;
1798 /* update the BBT for chip */
1799 DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
1800 "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
1801 chip->bbt_td->pages[chipnr]);
1802 nand_update_bbt(mtd, rewrite_bbt[chipnr]);
David A. Marlin30f464b2005-01-17 18:35:25 +00001803 }
1804
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 /* Return more or less happy */
1806 return ret;
1807}
1808
1809/**
1810 * nand_sync - [MTD Interface] sync
1811 * @mtd: MTD device structure
1812 *
1813 * Sync is actually a wait for chip ready function
1814 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001815static void nand_sync(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001817 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
David Woodhousee0c7d762006-05-13 18:07:53 +01001819 DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
1821 /* Grab the lock and see if the device is available */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001822 nand_get_device(chip, mtd, FL_SYNCING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 /* Release it and go back */
David Woodhousee0c7d762006-05-13 18:07:53 +01001824 nand_release_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825}
1826
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001828 * nand_block_isbad - [MTD Interface] Check if block at offset is bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 * @mtd: MTD device structure
1830 * @ofs: offset relative to mtd start
1831 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001832static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833{
1834 /* Check for invalid offset */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001835 if (offs > mtd->size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 return -EINVAL;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00001837
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001838 return nand_block_checkbad(mtd, offs, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839}
1840
1841/**
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001842 * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 * @mtd: MTD device structure
1844 * @ofs: offset relative to mtd start
1845 */
David Woodhousee0c7d762006-05-13 18:07:53 +01001846static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001848 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 int ret;
1850
David Woodhousee0c7d762006-05-13 18:07:53 +01001851 if ((ret = nand_block_isbad(mtd, ofs))) {
1852 /* If it was bad already, return success and do nothing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 if (ret > 0)
1854 return 0;
David Woodhousee0c7d762006-05-13 18:07:53 +01001855 return ret;
1856 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001858 return chip->block_markbad(mtd, ofs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859}
1860
1861/**
Vitaly Wool962034f2005-09-15 14:58:53 +01001862 * nand_suspend - [MTD Interface] Suspend the NAND flash
1863 * @mtd: MTD device structure
1864 */
1865static int nand_suspend(struct mtd_info *mtd)
1866{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001867 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01001868
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001869 return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
Vitaly Wool962034f2005-09-15 14:58:53 +01001870}
1871
1872/**
1873 * nand_resume - [MTD Interface] Resume the NAND flash
1874 * @mtd: MTD device structure
1875 */
1876static void nand_resume(struct mtd_info *mtd)
1877{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001878 struct nand_chip *chip = mtd->priv;
Vitaly Wool962034f2005-09-15 14:58:53 +01001879
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001880 if (chip->state == FL_PM_SUSPENDED)
Vitaly Wool962034f2005-09-15 14:58:53 +01001881 nand_release_device(mtd);
1882 else
Thomas Gleixner2c0a2be2006-05-23 11:50:56 +02001883 printk(KERN_ERR "nand_resume() called for a chip which is not "
1884 "in suspended state\n");
Vitaly Wool962034f2005-09-15 14:58:53 +01001885}
1886
Thomas Gleixnera36ed292006-05-23 11:37:03 +02001887/*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001888 * Set default functions
1889 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001890static void nand_set_defaults(struct nand_chip *chip, int busw)
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001891{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 /* check for proper chip_delay setup, set 20us if not */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001893 if (!chip->chip_delay)
1894 chip->chip_delay = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895
1896 /* check, if a user supplied command function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001897 if (chip->cmdfunc == NULL)
1898 chip->cmdfunc = nand_command;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900 /* check, if a user supplied wait function given */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001901 if (chip->waitfunc == NULL)
1902 chip->waitfunc = nand_wait;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001904 if (!chip->select_chip)
1905 chip->select_chip = nand_select_chip;
1906 if (!chip->read_byte)
1907 chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
1908 if (!chip->read_word)
1909 chip->read_word = nand_read_word;
1910 if (!chip->block_bad)
1911 chip->block_bad = nand_block_bad;
1912 if (!chip->block_markbad)
1913 chip->block_markbad = nand_default_block_markbad;
1914 if (!chip->write_buf)
1915 chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
1916 if (!chip->read_buf)
1917 chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
1918 if (!chip->verify_buf)
1919 chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
1920 if (!chip->scan_bbt)
1921 chip->scan_bbt = nand_default_bbt;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02001922
1923 if (!chip->controller) {
1924 chip->controller = &chip->hwcontrol;
1925 spin_lock_init(&chip->controller->lock);
1926 init_waitqueue_head(&chip->controller->wq);
1927 }
1928
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001929}
1930
1931/*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001932 * Get the flash and manufacturer id and lookup if the type is supported
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001933 */
1934static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001935 struct nand_chip *chip,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001936 int busw, int *maf_id)
1937{
1938 struct nand_flash_dev *type = NULL;
1939 int i, dev_id, maf_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941 /* Select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001942 chip->select_chip(mtd, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943
1944 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001945 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
1947 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001948 *maf_id = chip->read_byte(mtd);
1949 dev_id = chip->read_byte(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001951 /* Lookup the flash id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001953 if (dev_id == nand_flash_ids[i].id) {
1954 type = &nand_flash_ids[i];
1955 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 }
1958
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001959 if (!type)
1960 return ERR_PTR(-ENODEV);
1961
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02001962 if (!mtd->name)
1963 mtd->name = type->name;
1964
1965 chip->chipsize = type->chipsize << 20;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001966
1967 /* Newer devices have all the information in additional id bytes */
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02001968 if (!type->pagesize) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001969 int extid;
1970 /* The 3rd id byte contains non relevant data ATM */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001971 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001972 /* The 4th id byte is the important one */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001973 extid = chip->read_byte(mtd);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001974 /* Calc pagesize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001975 mtd->writesize = 1024 << (extid & 0x3);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001976 extid >>= 2;
1977 /* Calc oobsize */
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001978 mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001979 extid >>= 2;
1980 /* Calc blocksize. Blocksize is multiples of 64KiB */
1981 mtd->erasesize = (64 * 1024) << (extid & 0x03);
1982 extid >>= 2;
1983 /* Get buswidth information */
1984 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
1985
1986 } else {
1987 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02001988 * Old devices have chip data hardcoded in the device id table
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001989 */
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02001990 mtd->erasesize = type->erasesize;
1991 mtd->writesize = type->pagesize;
Thomas Gleixner4cbb9b82006-05-23 12:37:31 +02001992 mtd->oobsize = mtd->writesize / 32;
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02001993 busw = type->options & NAND_BUSWIDTH_16;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02001994 }
1995
1996 /* Try to identify manufacturer */
1997 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
1998 if (nand_manuf_ids[maf_idx].id == *maf_id)
1999 break;
2000 }
2001
2002 /*
2003 * Check, if buswidth is correct. Hardware drivers should set
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002004 * chip correct !
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002005 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002006 if (busw != (chip->options & NAND_BUSWIDTH_16)) {
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002007 printk(KERN_INFO "NAND device: Manufacturer ID:"
2008 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2009 dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2010 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002011 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002012 busw ? 16 : 8);
2013 return ERR_PTR(-EINVAL);
2014 }
2015
2016 /* Calculate the address shift from the page size */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002017 chip->page_shift = ffs(mtd->writesize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002018 /* Convert chipsize to number of pages per chip -1. */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002019 chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002020
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002021 chip->bbt_erase_shift = chip->phys_erase_shift =
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002022 ffs(mtd->erasesize) - 1;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002023 chip->chip_shift = ffs(chip->chipsize) - 1;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002024
2025 /* Set the bad block position */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002026 chip->badblockpos = mtd->writesize > 512 ?
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002027 NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
2028
2029 /* Get chip options, preserve non chip based options */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002030 chip->options &= ~NAND_CHIPOPTIONS_MSK;
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02002031 chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002032
2033 /*
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002034 * Set chip as a default. Board drivers can override it, if necessary
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002035 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002036 chip->options |= NAND_NO_AUTOINCR;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002037
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002038 /* Check if chip is a not a samsung device. Do not clear the
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002039 * options for chips which are not having an extended id.
2040 */
Thomas Gleixnerba0251f2006-05-27 01:02:13 +02002041 if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002042 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002043
2044 /* Check for AND chips with 4 page planes */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002045 if (chip->options & NAND_4PAGE_ARRAY)
2046 chip->erase_cmd = multi_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002047 else
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002048 chip->erase_cmd = single_erase_cmd;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002049
2050 /* Do not replace user supplied command function ! */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002051 if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
2052 chip->cmdfunc = nand_command_lp;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002053
2054 printk(KERN_INFO "NAND device: Manufacturer ID:"
2055 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
2056 nand_manuf_ids[maf_idx].name, type->name);
2057
2058 return type;
2059}
2060
2061/* module_text_address() isn't exported, and it's mostly a pointless
2062 test if this is a module _anyway_ -- they'd have to try _really_ hard
2063 to call us from in-kernel code if the core NAND support is modular. */
2064#ifdef MODULE
2065#define caller_is_module() (1)
2066#else
2067#define caller_is_module() \
2068 module_text_address((unsigned long)__builtin_return_address(0))
2069#endif
2070
2071/**
2072 * nand_scan - [NAND Interface] Scan for the NAND device
2073 * @mtd: MTD device structure
2074 * @maxchips: Number of chips to scan for
2075 *
2076 * This fills out all the uninitialized function pointers
2077 * with the defaults.
2078 * The flash ID is read and the mtd/chip structures are
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002079 * filled with the appropriate values.
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002080 * The mtd->owner field must be set to the module of the caller
2081 *
2082 */
2083int nand_scan(struct mtd_info *mtd, int maxchips)
2084{
2085 int i, busw, nand_maf_id;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002086 struct nand_chip *chip = mtd->priv;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002087 struct nand_flash_dev *type;
2088
2089 /* Many callers got this wrong, so check for it for a while... */
2090 if (!mtd->owner && caller_is_module()) {
2091 printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
2092 BUG();
2093 }
2094
2095 /* Get buswidth to select the correct functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002096 busw = chip->options & NAND_BUSWIDTH_16;
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002097 /* Set the default functions */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002098 nand_set_defaults(chip, busw);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002099
2100 /* Read the flash type */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002101 type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002102
2103 if (IS_ERR(type)) {
David Woodhousee0c7d762006-05-13 18:07:53 +01002104 printk(KERN_WARNING "No NAND device found!!!\n");
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002105 chip->select_chip(mtd, -1);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002106 return PTR_ERR(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 }
2108
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002109 /* Check for a chip array */
David Woodhousee0c7d762006-05-13 18:07:53 +01002110 for (i = 1; i < maxchips; i++) {
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002111 chip->select_chip(mtd, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 /* Send the command for reading device ID */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002113 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 /* Read manufacturer and device IDs */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002115 if (nand_maf_id != chip->read_byte(mtd) ||
2116 type->id != chip->read_byte(mtd))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 break;
2118 }
2119 if (i > 1)
2120 printk(KERN_INFO "%d NAND chips detected\n", i);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002121
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 /* Store the number of chips and calc total size for mtd */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002123 chip->numchips = i;
2124 mtd->size = i * chip->chipsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002126 /* Preset the internal oob write buffer */
2127 memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize);
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002128
2129 /*
2130 * If no default placement scheme is given, select an appropriate one
2131 */
Thomas Gleixner5bd34c02006-05-27 22:16:10 +02002132 if (!chip->ecc.layout) {
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002133 switch (mtd->oobsize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 case 8:
Thomas Gleixner5bd34c02006-05-27 22:16:10 +02002135 chip->ecc.layout = &nand_oob_8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 break;
2137 case 16:
Thomas Gleixner5bd34c02006-05-27 22:16:10 +02002138 chip->ecc.layout = &nand_oob_16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 break;
2140 case 64:
Thomas Gleixner5bd34c02006-05-27 22:16:10 +02002141 chip->ecc.layout = &nand_oob_64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 break;
2143 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002144 printk(KERN_WARNING "No oob scheme defined for "
2145 "oobsize %d\n", mtd->oobsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 BUG();
2147 }
2148 }
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002149
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002150 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002151 * check ECC mode, default to software if 3byte/512byte hardware ECC is
2152 * selected and we have 256 byte pagesize fallback to software ECC
David Woodhousee0c7d762006-05-13 18:07:53 +01002153 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002154 switch (chip->ecc.mode) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002155 case NAND_ECC_HW:
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002156 /* Use standard hwecc read page function ? */
2157 if (!chip->ecc.read_page)
2158 chip->ecc.read_page = nand_read_page_hwecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002159 if (!chip->ecc.write_page)
2160 chip->ecc.write_page = nand_write_page_hwecc;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002161
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002162 case NAND_ECC_HW_SYNDROME:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002163 if (!chip->ecc.calculate || !chip->ecc.correct ||
2164 !chip->ecc.hwctl) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002165 printk(KERN_WARNING "No ECC functions supplied, "
2166 "Hardware ECC not possible\n");
2167 BUG();
2168 }
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002169 /* Use standard syndrome read/write page function ? */
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002170 if (!chip->ecc.read_page)
2171 chip->ecc.read_page = nand_read_page_syndrome;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002172 if (!chip->ecc.write_page)
2173 chip->ecc.write_page = nand_write_page_syndrome;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002174
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002175 if (mtd->writesize >= chip->ecc.size)
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002176 break;
2177 printk(KERN_WARNING "%d byte HW ECC not possible on "
2178 "%d byte page size, fallback to SW ECC\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002179 chip->ecc.size, mtd->writesize);
2180 chip->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002182 case NAND_ECC_SOFT:
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002183 chip->ecc.calculate = nand_calculate_ecc;
2184 chip->ecc.correct = nand_correct_data;
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002185 chip->ecc.read_page = nand_read_page_swecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002186 chip->ecc.write_page = nand_write_page_swecc;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002187 chip->ecc.size = 256;
2188 chip->ecc.bytes = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 break;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002190
2191 case NAND_ECC_NONE:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002192 printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
2193 "This is not recommended !!\n");
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002194 chip->ecc.read_page = nand_read_page_swecc;
Thomas Gleixnerf75e5092006-05-26 18:52:08 +02002195 chip->ecc.write_page = nand_write_page_swecc;
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002196 chip->ecc.size = mtd->writesize;
2197 chip->ecc.bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 default:
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002200 printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002201 chip->ecc.mode);
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002202 BUG();
2203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002205 /*
Thomas Gleixner5bd34c02006-05-27 22:16:10 +02002206 * The number of bytes available for a client to place data into
2207 * the out of band area
2208 */
2209 chip->ecc.layout->oobavail = 0;
2210 for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
2211 chip->ecc.layout->oobavail +=
2212 chip->ecc.layout->oobfree[i].length;
2213
2214 /*
Thomas Gleixner7aa65bf2006-05-23 11:54:38 +02002215 * Set the number of read / write steps for one page depending on ECC
2216 * mode
2217 */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002218 chip->ecc.steps = mtd->writesize / chip->ecc.size;
2219 if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
Thomas Gleixner6dfc6d22006-05-23 12:00:46 +02002220 printk(KERN_WARNING "Invalid ecc parameters\n");
2221 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 }
Thomas Gleixnerf5bbdac2006-05-25 10:07:16 +02002223 chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002224
Thomas Gleixner04bbd0e2006-05-25 09:45:29 +02002225 /* Initialize state */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002226 chip->state = FL_READY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
2228 /* De-select the device */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002229 chip->select_chip(mtd, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
2231 /* Invalidate the pagebuffer reference */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002232 chip->pagebuf = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233
2234 /* Fill in remaining MTD driver data */
2235 mtd->type = MTD_NANDFLASH;
Joern Engel5fa43392006-05-22 23:18:29 +02002236 mtd->flags = MTD_CAP_NANDFLASH;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 mtd->ecctype = MTD_ECC_SW;
2238 mtd->erase = nand_erase;
2239 mtd->point = NULL;
2240 mtd->unpoint = NULL;
2241 mtd->read = nand_read;
2242 mtd->write = nand_write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 mtd->read_oob = nand_read_oob;
2244 mtd->write_oob = nand_write_oob;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 mtd->sync = nand_sync;
2246 mtd->lock = NULL;
2247 mtd->unlock = NULL;
Vitaly Wool962034f2005-09-15 14:58:53 +01002248 mtd->suspend = nand_suspend;
2249 mtd->resume = nand_resume;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 mtd->block_isbad = nand_block_isbad;
2251 mtd->block_markbad = nand_block_markbad;
2252
Thomas Gleixner5bd34c02006-05-27 22:16:10 +02002253 /* propagate ecc.layout to mtd_info */
2254 mtd->ecclayout = chip->ecc.layout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002256 /* Check, if we should skip the bad block table scan */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002257 if (chip->options & NAND_SKIP_BBTSCAN)
Thomas Gleixner0040bf32005-02-09 12:20:00 +00002258 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
2260 /* Build bad block table */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002261 return chip->scan_bbt(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262}
2263
2264/**
Thomas Gleixner61b03bd2005-11-07 11:15:49 +00002265 * nand_release - [NAND Interface] Free resources held by the NAND device
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 * @mtd: MTD device structure
2267*/
David Woodhousee0c7d762006-05-13 18:07:53 +01002268void nand_release(struct mtd_info *mtd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269{
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002270 struct nand_chip *chip = mtd->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271
2272#ifdef CONFIG_MTD_PARTITIONS
2273 /* Deregister partitions */
David Woodhousee0c7d762006-05-13 18:07:53 +01002274 del_mtd_partitions(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275#endif
2276 /* Deregister the device */
David Woodhousee0c7d762006-05-13 18:07:53 +01002277 del_mtd_device(mtd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Jesper Juhlfa671642005-11-07 01:01:27 -08002279 /* Free bad block table memory */
Thomas Gleixnerace4dfe2006-05-24 12:07:37 +02002280 kfree(chip->bbt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281}
2282
David Woodhousee0c7d762006-05-13 18:07:53 +01002283EXPORT_SYMBOL_GPL(nand_scan);
2284EXPORT_SYMBOL_GPL(nand_release);
Richard Purdie8fe833c2006-03-31 02:31:14 -08002285
2286static int __init nand_base_init(void)
2287{
2288 led_trigger_register_simple("nand-disk", &nand_led_trigger);
2289 return 0;
2290}
2291
2292static void __exit nand_base_exit(void)
2293{
2294 led_trigger_unregister_simple(nand_led_trigger);
2295}
2296
2297module_init(nand_base_init);
2298module_exit(nand_base_exit);
2299
David Woodhousee0c7d762006-05-13 18:07:53 +01002300MODULE_LICENSE("GPL");
2301MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
2302MODULE_DESCRIPTION("Generic NAND flash driver code");