]>
Commit | Line | Data |
---|---|---|
932394ac WD |
1 | /* |
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. | |
ac7eb8a3 | 7 | * |
932394ac | 8 | * Additional technical information is available on |
c45912d8 | 9 | * http://www.linux-mtd.infradead.org/doc/nand.html |
ac7eb8a3 | 10 | * |
932394ac | 11 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) |
cfa460ad | 12 | * 2002-2006 Thomas Gleixner (tglx@linutronix.de) |
932394ac | 13 | * |
cfa460ad | 14 | * Credits: |
ac7eb8a3 WD |
15 | * David Woodhouse for adding multichip support |
16 | * | |
932394ac WD |
17 | * Aleph One Ltd. and Toby Churchill Ltd. for supporting the |
18 | * rework for 2K page size chips | |
19 | * | |
cfa460ad | 20 | * TODO: |
932394ac WD |
21 | * Enable cached programming for 2k page size chips |
22 | * Check, if mtd->ecctype should be set to MTD_ECC_HW | |
dfe64e2c | 23 | * if we have HW ECC support. |
c45912d8 | 24 | * BBT table is not serialized, has to be fixed |
932394ac | 25 | * |
932394ac WD |
26 | * This program is free software; you can redistribute it and/or modify |
27 | * it under the terms of the GNU General Public License version 2 as | |
28 | * published by the Free Software Foundation. | |
29 | * | |
30 | */ | |
31 | ||
ff94bc40 HS |
32 | #ifndef __UBOOT__ |
33 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
cfa460ad | 34 | |
ff94bc40 HS |
35 | #include <linux/module.h> |
36 | #include <linux/delay.h> | |
37 | #include <linux/errno.h> | |
38 | #include <linux/err.h> | |
39 | #include <linux/sched.h> | |
40 | #include <linux/slab.h> | |
41 | #include <linux/types.h> | |
42 | #include <linux/mtd/mtd.h> | |
43 | #include <linux/mtd/nand.h> | |
44 | #include <linux/mtd/nand_ecc.h> | |
45 | #include <linux/mtd/nand_bch.h> | |
46 | #include <linux/interrupt.h> | |
47 | #include <linux/bitops.h> | |
48 | #include <linux/leds.h> | |
49 | #include <linux/io.h> | |
50 | #include <linux/mtd/partitions.h> | |
51 | #else | |
52 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
53 | #include <common.h> | |
932394ac WD |
54 | #include <malloc.h> |
55 | #include <watchdog.h> | |
cfa460ad | 56 | #include <linux/err.h> |
7b15e2bb | 57 | #include <linux/compat.h> |
932394ac WD |
58 | #include <linux/mtd/mtd.h> |
59 | #include <linux/mtd/nand.h> | |
60 | #include <linux/mtd/nand_ecc.h> | |
4c6de856 | 61 | #include <linux/mtd/nand_bch.h> |
10bb62d8 SR |
62 | #ifdef CONFIG_MTD_PARTITIONS |
63 | #include <linux/mtd/partitions.h> | |
64 | #endif | |
932394ac WD |
65 | #include <asm/io.h> |
66 | #include <asm/errno.h> | |
67 | ||
8da60128 PT |
68 | /* |
69 | * CONFIG_SYS_NAND_RESET_CNT is used as a timeout mechanism when resetting | |
70 | * a flash. NAND flash is initialized prior to interrupts so standard timers | |
71 | * can't be used. CONFIG_SYS_NAND_RESET_CNT should be set to a value | |
72 | * which is greater than (max NAND reset time / NAND status read time). | |
73 | * A conservative default of 200000 (500 us / 25 ns) is used as a default. | |
74 | */ | |
75 | #ifndef CONFIG_SYS_NAND_RESET_CNT | |
76 | #define CONFIG_SYS_NAND_RESET_CNT 200000 | |
77 | #endif | |
78 | ||
ff94bc40 HS |
79 | static bool is_module_text_address(unsigned long addr) {return 0;} |
80 | #endif | |
81 | ||
932394ac | 82 | /* Define default oob placement schemes for large and small page devices */ |
cfa460ad | 83 | static struct nand_ecclayout nand_oob_8 = { |
932394ac WD |
84 | .eccbytes = 3, |
85 | .eccpos = {0, 1, 2}, | |
cfa460ad WJ |
86 | .oobfree = { |
87 | {.offset = 3, | |
88 | .length = 2}, | |
89 | {.offset = 6, | |
90e3f395 | 90 | .length = 2} } |
932394ac WD |
91 | }; |
92 | ||
cfa460ad | 93 | static struct nand_ecclayout nand_oob_16 = { |
932394ac WD |
94 | .eccbytes = 6, |
95 | .eccpos = {0, 1, 2, 3, 6, 7}, | |
cfa460ad WJ |
96 | .oobfree = { |
97 | {.offset = 8, | |
90e3f395 | 98 | . length = 8} } |
932394ac WD |
99 | }; |
100 | ||
cfa460ad | 101 | static struct nand_ecclayout nand_oob_64 = { |
932394ac WD |
102 | .eccbytes = 24, |
103 | .eccpos = { | |
cfa460ad WJ |
104 | 40, 41, 42, 43, 44, 45, 46, 47, |
105 | 48, 49, 50, 51, 52, 53, 54, 55, | |
106 | 56, 57, 58, 59, 60, 61, 62, 63}, | |
107 | .oobfree = { | |
108 | {.offset = 2, | |
90e3f395 | 109 | .length = 38} } |
932394ac WD |
110 | }; |
111 | ||
cfa460ad | 112 | static struct nand_ecclayout nand_oob_128 = { |
248ae5cf SP |
113 | .eccbytes = 48, |
114 | .eccpos = { | |
90e3f395 CH |
115 | 80, 81, 82, 83, 84, 85, 86, 87, |
116 | 88, 89, 90, 91, 92, 93, 94, 95, | |
117 | 96, 97, 98, 99, 100, 101, 102, 103, | |
cfa460ad WJ |
118 | 104, 105, 106, 107, 108, 109, 110, 111, |
119 | 112, 113, 114, 115, 116, 117, 118, 119, | |
120 | 120, 121, 122, 123, 124, 125, 126, 127}, | |
121 | .oobfree = { | |
122 | {.offset = 2, | |
90e3f395 | 123 | .length = 78} } |
932394ac WD |
124 | }; |
125 | ||
ff94bc40 | 126 | static int nand_get_device(struct mtd_info *mtd, int new_state); |
cfa460ad WJ |
127 | |
128 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |
129 | struct mtd_oob_ops *ops); | |
130 | ||
ff94bc40 HS |
131 | /* |
132 | * For devices which display every fart in the system on a separate LED. Is | |
133 | * compiled away when LED support is disabled. | |
134 | */ | |
135 | DEFINE_LED_TRIGGER(nand_led_trigger); | |
248ae5cf | 136 | |
2a8e0fc8 CH |
137 | static int check_offs_len(struct mtd_info *mtd, |
138 | loff_t ofs, uint64_t len) | |
139 | { | |
140 | struct nand_chip *chip = mtd->priv; | |
141 | int ret = 0; | |
142 | ||
143 | /* Start address must align on block boundary */ | |
ff94bc40 HS |
144 | if (ofs & ((1ULL << chip->phys_erase_shift) - 1)) { |
145 | pr_debug("%s: unaligned address\n", __func__); | |
2a8e0fc8 CH |
146 | ret = -EINVAL; |
147 | } | |
148 | ||
149 | /* Length must align on block boundary */ | |
ff94bc40 HS |
150 | if (len & ((1ULL << chip->phys_erase_shift) - 1)) { |
151 | pr_debug("%s: length not block aligned\n", __func__); | |
2a8e0fc8 CH |
152 | ret = -EINVAL; |
153 | } | |
154 | ||
2a8e0fc8 CH |
155 | return ret; |
156 | } | |
157 | ||
932394ac WD |
158 | /** |
159 | * nand_release_device - [GENERIC] release chip | |
dfe64e2c | 160 | * @mtd: MTD device structure |
ac7eb8a3 | 161 | * |
ff94bc40 | 162 | * Release chip lock and wake up anyone waiting on the device. |
932394ac | 163 | */ |
90e3f395 | 164 | static void nand_release_device(struct mtd_info *mtd) |
8e9655f8 | 165 | { |
2a8e0fc8 CH |
166 | struct nand_chip *chip = mtd->priv; |
167 | ||
ff94bc40 HS |
168 | #ifndef __UBOOT__ |
169 | /* Release the controller and the chip */ | |
170 | spin_lock(&chip->controller->lock); | |
171 | chip->controller->active = NULL; | |
172 | chip->state = FL_READY; | |
173 | wake_up(&chip->controller->wq); | |
174 | spin_unlock(&chip->controller->lock); | |
175 | #else | |
2a8e0fc8 CH |
176 | /* De-select the NAND device */ |
177 | chip->select_chip(mtd, -1); | |
ff94bc40 | 178 | #endif |
8e9655f8 | 179 | } |
932394ac WD |
180 | |
181 | /** | |
182 | * nand_read_byte - [DEFAULT] read one byte from the chip | |
dfe64e2c | 183 | * @mtd: MTD device structure |
932394ac | 184 | * |
ff94bc40 | 185 | * Default read function for 8bit buswidth |
932394ac | 186 | */ |
ff94bc40 HS |
187 | #ifndef __UBOOT__ |
188 | static uint8_t nand_read_byte(struct mtd_info *mtd) | |
189 | #else | |
82645f81 | 190 | uint8_t nand_read_byte(struct mtd_info *mtd) |
ff94bc40 | 191 | #endif |
932394ac | 192 | { |
cfa460ad WJ |
193 | struct nand_chip *chip = mtd->priv; |
194 | return readb(chip->IO_ADDR_R); | |
932394ac WD |
195 | } |
196 | ||
197 | /** | |
ff94bc40 | 198 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip |
dfe64e2c SL |
199 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip |
200 | * @mtd: MTD device structure | |
201 | * | |
202 | * Default read function for 16bit buswidth with endianness conversion. | |
932394ac | 203 | * |
932394ac | 204 | */ |
cfa460ad | 205 | static uint8_t nand_read_byte16(struct mtd_info *mtd) |
932394ac | 206 | { |
cfa460ad WJ |
207 | struct nand_chip *chip = mtd->priv; |
208 | return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R)); | |
932394ac WD |
209 | } |
210 | ||
211 | /** | |
212 | * nand_read_word - [DEFAULT] read one word from the chip | |
dfe64e2c | 213 | * @mtd: MTD device structure |
932394ac | 214 | * |
dfe64e2c | 215 | * Default read function for 16bit buswidth without endianness conversion. |
932394ac WD |
216 | */ |
217 | static u16 nand_read_word(struct mtd_info *mtd) | |
218 | { | |
cfa460ad WJ |
219 | struct nand_chip *chip = mtd->priv; |
220 | return readw(chip->IO_ADDR_R); | |
932394ac WD |
221 | } |
222 | ||
223 | /** | |
224 | * nand_select_chip - [DEFAULT] control CE line | |
dfe64e2c SL |
225 | * @mtd: MTD device structure |
226 | * @chipnr: chipnumber to select, -1 for deselect | |
932394ac WD |
227 | * |
228 | * Default select function for 1 chip devices. | |
229 | */ | |
cfa460ad | 230 | static void nand_select_chip(struct mtd_info *mtd, int chipnr) |
932394ac | 231 | { |
cfa460ad WJ |
232 | struct nand_chip *chip = mtd->priv; |
233 | ||
234 | switch (chipnr) { | |
932394ac | 235 | case -1: |
cfa460ad | 236 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); |
932394ac WD |
237 | break; |
238 | case 0: | |
932394ac WD |
239 | break; |
240 | ||
241 | default: | |
242 | BUG(); | |
243 | } | |
244 | } | |
245 | ||
ff94bc40 HS |
246 | /** |
247 | * nand_write_byte - [DEFAULT] write single byte to chip | |
248 | * @mtd: MTD device structure | |
249 | * @byte: value to write | |
250 | * | |
251 | * Default function to write a byte to I/O[7:0] | |
252 | */ | |
253 | static void nand_write_byte(struct mtd_info *mtd, uint8_t byte) | |
254 | { | |
255 | struct nand_chip *chip = mtd->priv; | |
256 | ||
257 | chip->write_buf(mtd, &byte, 1); | |
258 | } | |
259 | ||
260 | /** | |
261 | * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16 | |
262 | * @mtd: MTD device structure | |
263 | * @byte: value to write | |
264 | * | |
265 | * Default function to write a byte to I/O[7:0] on a 16-bit wide chip. | |
266 | */ | |
267 | static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) | |
268 | { | |
269 | struct nand_chip *chip = mtd->priv; | |
270 | uint16_t word = byte; | |
271 | ||
272 | /* | |
273 | * It's not entirely clear what should happen to I/O[15:8] when writing | |
274 | * a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads: | |
275 | * | |
276 | * When the host supports a 16-bit bus width, only data is | |
277 | * transferred at the 16-bit width. All address and command line | |
278 | * transfers shall use only the lower 8-bits of the data bus. During | |
279 | * command transfers, the host may place any value on the upper | |
280 | * 8-bits of the data bus. During address transfers, the host shall | |
281 | * set the upper 8-bits of the data bus to 00h. | |
282 | * | |
283 | * One user of the write_byte callback is nand_onfi_set_features. The | |
284 | * four parameters are specified to be written to I/O[7:0], but this is | |
285 | * neither an address nor a command transfer. Let's assume a 0 on the | |
286 | * upper I/O lines is OK. | |
287 | */ | |
288 | chip->write_buf(mtd, (uint8_t *)&word, 2); | |
289 | } | |
290 | ||
291 | #if defined(__UBOOT__) && !defined(CONFIG_BLACKFIN) | |
292 | static void iowrite8_rep(void *addr, const uint8_t *buf, int len) | |
293 | { | |
294 | int i; | |
295 | ||
296 | for (i = 0; i < len; i++) | |
297 | writeb(buf[i], addr); | |
298 | } | |
299 | static void ioread8_rep(void *addr, uint8_t *buf, int len) | |
300 | { | |
301 | int i; | |
302 | ||
303 | for (i = 0; i < len; i++) | |
304 | buf[i] = readb(addr); | |
305 | } | |
306 | ||
307 | static void ioread16_rep(void *addr, void *buf, int len) | |
308 | { | |
309 | int i; | |
310 | u16 *p = (u16 *) buf; | |
be16aba5 | 311 | |
ff94bc40 HS |
312 | for (i = 0; i < len; i++) |
313 | p[i] = readw(addr); | |
314 | } | |
315 | ||
316 | static void iowrite16_rep(void *addr, void *buf, int len) | |
317 | { | |
318 | int i; | |
319 | u16 *p = (u16 *) buf; | |
ff94bc40 HS |
320 | |
321 | for (i = 0; i < len; i++) | |
322 | writew(p[i], addr); | |
323 | } | |
324 | #endif | |
325 | ||
932394ac WD |
326 | /** |
327 | * nand_write_buf - [DEFAULT] write buffer to chip | |
dfe64e2c SL |
328 | * @mtd: MTD device structure |
329 | * @buf: data buffer | |
330 | * @len: number of bytes to write | |
932394ac | 331 | * |
dfe64e2c | 332 | * Default write function for 8bit buswidth. |
932394ac | 333 | */ |
ff94bc40 HS |
334 | #ifndef __UBOOT__ |
335 | static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |
336 | #else | |
82645f81 | 337 | void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
ff94bc40 | 338 | #endif |
932394ac | 339 | { |
cfa460ad | 340 | struct nand_chip *chip = mtd->priv; |
932394ac | 341 | |
ff94bc40 | 342 | iowrite8_rep(chip->IO_ADDR_W, buf, len); |
932394ac WD |
343 | } |
344 | ||
345 | /** | |
ac7eb8a3 | 346 | * nand_read_buf - [DEFAULT] read chip data into buffer |
dfe64e2c SL |
347 | * @mtd: MTD device structure |
348 | * @buf: buffer to store date | |
349 | * @len: number of bytes to read | |
932394ac | 350 | * |
dfe64e2c | 351 | * Default read function for 8bit buswidth. |
932394ac | 352 | */ |
ff94bc40 HS |
353 | #ifndef __UBOOT__ |
354 | static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |
355 | #else | |
12c2f1ee | 356 | void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
ff94bc40 | 357 | #endif |
932394ac | 358 | { |
cfa460ad | 359 | struct nand_chip *chip = mtd->priv; |
932394ac | 360 | |
ff94bc40 | 361 | ioread8_rep(chip->IO_ADDR_R, buf, len); |
932394ac WD |
362 | } |
363 | ||
932394ac | 364 | /** |
ff94bc40 | 365 | * nand_write_buf16 - [DEFAULT] write buffer to chip |
dfe64e2c | 366 | * @mtd: MTD device structure |
ff94bc40 HS |
367 | * @buf: data buffer |
368 | * @len: number of bytes to write | |
932394ac | 369 | * |
ff94bc40 | 370 | * Default write function for 16bit buswidth. |
932394ac | 371 | */ |
ff94bc40 HS |
372 | #ifndef __UBOOT__ |
373 | static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) | |
374 | #else | |
375 | void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) | |
376 | #endif | |
932394ac | 377 | { |
cfa460ad | 378 | struct nand_chip *chip = mtd->priv; |
932394ac | 379 | u16 *p = (u16 *) buf; |
932394ac | 380 | |
ff94bc40 | 381 | iowrite16_rep(chip->IO_ADDR_W, p, len >> 1); |
932394ac WD |
382 | } |
383 | ||
384 | /** | |
ff94bc40 | 385 | * nand_read_buf16 - [DEFAULT] read chip data into buffer |
dfe64e2c | 386 | * @mtd: MTD device structure |
ff94bc40 HS |
387 | * @buf: buffer to store date |
388 | * @len: number of bytes to read | |
932394ac | 389 | * |
ff94bc40 | 390 | * Default read function for 16bit buswidth. |
932394ac | 391 | */ |
ff94bc40 HS |
392 | #ifndef __UBOOT__ |
393 | static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) | |
394 | #else | |
395 | void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) | |
396 | #endif | |
932394ac | 397 | { |
cfa460ad | 398 | struct nand_chip *chip = mtd->priv; |
932394ac | 399 | u16 *p = (u16 *) buf; |
932394ac | 400 | |
ff94bc40 | 401 | ioread16_rep(chip->IO_ADDR_R, p, len >> 1); |
932394ac WD |
402 | } |
403 | ||
404 | /** | |
405 | * nand_block_bad - [DEFAULT] Read bad block marker from the chip | |
dfe64e2c SL |
406 | * @mtd: MTD device structure |
407 | * @ofs: offset from device start | |
408 | * @getchip: 0, if the chip is already selected | |
932394ac | 409 | * |
ac7eb8a3 | 410 | * Check, if the block is bad. |
932394ac WD |
411 | */ |
412 | static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |
413 | { | |
dfe64e2c | 414 | int page, chipnr, res = 0, i = 0; |
cfa460ad | 415 | struct nand_chip *chip = mtd->priv; |
932394ac WD |
416 | u16 bad; |
417 | ||
dfe64e2c | 418 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) |
2a8e0fc8 CH |
419 | ofs += mtd->erasesize - mtd->writesize; |
420 | ||
cfa460ad | 421 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; |
a7988659 | 422 | |
932394ac | 423 | if (getchip) { |
cfa460ad | 424 | chipnr = (int)(ofs >> chip->chip_shift); |
932394ac | 425 | |
ff94bc40 | 426 | nand_get_device(mtd, FL_READING); |
932394ac WD |
427 | |
428 | /* Select the NAND device */ | |
cfa460ad | 429 | chip->select_chip(mtd, chipnr); |
a7988659 | 430 | } |
932394ac | 431 | |
dfe64e2c SL |
432 | do { |
433 | if (chip->options & NAND_BUSWIDTH_16) { | |
434 | chip->cmdfunc(mtd, NAND_CMD_READOOB, | |
435 | chip->badblockpos & 0xFE, page); | |
436 | bad = cpu_to_le16(chip->read_word(mtd)); | |
437 | if (chip->badblockpos & 0x1) | |
438 | bad >>= 8; | |
439 | else | |
440 | bad &= 0xFF; | |
441 | } else { | |
442 | chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, | |
443 | page); | |
444 | bad = chip->read_byte(mtd); | |
445 | } | |
ac7eb8a3 | 446 | |
dfe64e2c SL |
447 | if (likely(chip->badblockbits == 8)) |
448 | res = bad != 0xFF; | |
449 | else | |
450 | res = hweight8(bad) < chip->badblockbits; | |
451 | ofs += mtd->writesize; | |
452 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; | |
453 | i++; | |
454 | } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); | |
2a8e0fc8 | 455 | |
ff94bc40 HS |
456 | if (getchip) { |
457 | chip->select_chip(mtd, -1); | |
932394ac | 458 | nand_release_device(mtd); |
ff94bc40 | 459 | } |
ac7eb8a3 | 460 | |
932394ac WD |
461 | return res; |
462 | } | |
463 | ||
464 | /** | |
ff94bc40 | 465 | * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker |
dfe64e2c SL |
466 | * @mtd: MTD device structure |
467 | * @ofs: offset from device start | |
932394ac | 468 | * |
dfe64e2c | 469 | * This is the default implementation, which can be overridden by a hardware |
ff94bc40 HS |
470 | * specific driver. It provides the details for writing a bad block marker to a |
471 | * block. | |
472 | */ | |
473 | static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |
474 | { | |
475 | struct nand_chip *chip = mtd->priv; | |
476 | struct mtd_oob_ops ops; | |
477 | uint8_t buf[2] = { 0, 0 }; | |
478 | int ret = 0, res, i = 0; | |
479 | ||
480 | ops.datbuf = NULL; | |
481 | ops.oobbuf = buf; | |
482 | ops.ooboffs = chip->badblockpos; | |
483 | if (chip->options & NAND_BUSWIDTH_16) { | |
484 | ops.ooboffs &= ~0x01; | |
485 | ops.len = ops.ooblen = 2; | |
486 | } else { | |
487 | ops.len = ops.ooblen = 1; | |
488 | } | |
489 | ops.mode = MTD_OPS_PLACE_OOB; | |
490 | ||
491 | /* Write to first/last page(s) if necessary */ | |
492 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) | |
493 | ofs += mtd->erasesize - mtd->writesize; | |
494 | do { | |
495 | res = nand_do_write_oob(mtd, ofs, &ops); | |
496 | if (!ret) | |
497 | ret = res; | |
498 | ||
499 | i++; | |
500 | ofs += mtd->writesize; | |
501 | } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); | |
502 | ||
503 | return ret; | |
504 | } | |
505 | ||
506 | /** | |
507 | * nand_block_markbad_lowlevel - mark a block bad | |
508 | * @mtd: MTD device structure | |
509 | * @ofs: offset from device start | |
510 | * | |
511 | * This function performs the generic NAND bad block marking steps (i.e., bad | |
512 | * block table(s) and/or marker(s)). We only allow the hardware driver to | |
513 | * specify how to write bad block markers to OOB (chip->block_markbad). | |
514 | * | |
515 | * We try operations in the following order: | |
dfe64e2c | 516 | * (1) erase the affected block, to allow OOB marker to be written cleanly |
ff94bc40 HS |
517 | * (2) write bad block marker to OOB area of affected block (unless flag |
518 | * NAND_BBT_NO_OOB_BBM is present) | |
519 | * (3) update the BBT | |
520 | * Note that we retain the first error encountered in (2) or (3), finish the | |
dfe64e2c | 521 | * procedures, and dump the error in the end. |
932394ac | 522 | */ |
ff94bc40 | 523 | static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) |
932394ac | 524 | { |
cfa460ad | 525 | struct nand_chip *chip = mtd->priv; |
ff94bc40 | 526 | int res, ret = 0; |
2a8e0fc8 | 527 | |
ff94bc40 | 528 | if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) { |
dfe64e2c SL |
529 | struct erase_info einfo; |
530 | ||
531 | /* Attempt erase before marking OOB */ | |
532 | memset(&einfo, 0, sizeof(einfo)); | |
533 | einfo.mtd = mtd; | |
534 | einfo.addr = ofs; | |
ff94bc40 | 535 | einfo.len = 1ULL << chip->phys_erase_shift; |
dfe64e2c | 536 | nand_erase_nand(mtd, &einfo, 0); |
2a8e0fc8 | 537 | |
ff94bc40 HS |
538 | /* Write bad block marker to OOB */ |
539 | nand_get_device(mtd, FL_WRITING); | |
540 | ret = chip->block_markbad(mtd, ofs); | |
c45912d8 | 541 | nand_release_device(mtd); |
cfa460ad | 542 | } |
dfe64e2c | 543 | |
ff94bc40 HS |
544 | /* Mark block bad in BBT */ |
545 | if (chip->bbt) { | |
546 | res = nand_markbad_bbt(mtd, ofs); | |
dfe64e2c SL |
547 | if (!ret) |
548 | ret = res; | |
549 | } | |
550 | ||
cfa460ad WJ |
551 | if (!ret) |
552 | mtd->ecc_stats.badblocks++; | |
c45912d8 | 553 | |
cfa460ad | 554 | return ret; |
932394ac WD |
555 | } |
556 | ||
ac7eb8a3 | 557 | /** |
932394ac | 558 | * nand_check_wp - [GENERIC] check if the chip is write protected |
dfe64e2c | 559 | * @mtd: MTD device structure |
932394ac | 560 | * |
dfe64e2c SL |
561 | * Check, if the device is write protected. The function expects, that the |
562 | * device is already selected. | |
932394ac | 563 | */ |
cfa460ad | 564 | static int nand_check_wp(struct mtd_info *mtd) |
932394ac | 565 | { |
cfa460ad | 566 | struct nand_chip *chip = mtd->priv; |
2a8e0fc8 | 567 | |
dfe64e2c | 568 | /* Broken xD cards report WP despite being writable */ |
2a8e0fc8 CH |
569 | if (chip->options & NAND_BROKEN_XD) |
570 | return 0; | |
571 | ||
932394ac | 572 | /* Check the WP bit */ |
cfa460ad WJ |
573 | chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); |
574 | return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; | |
932394ac | 575 | } |