nand_util.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. /*
  2. * drivers/mtd/nand/nand_util.c
  3. *
  4. * Copyright (C) 2006 by Weiss-Electronic GmbH.
  5. * All rights reserved.
  6. *
  7. * @author: Guido Classen <clagix@gmail.com>
  8. * @descr: NAND Flash support
  9. * @references: borrowed heavily from Linux mtd-utils code:
  10. * flash_eraseall.c by Arcom Control System Ltd
  11. * nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
  12. * and Thomas Gleixner (tglx@linutronix.de)
  13. *
  14. * See file CREDITS for list of people who contributed to this
  15. * project.
  16. *
  17. * This program is free software; you can redistribute it and/or
  18. * modify it under the terms of the GNU General Public License version
  19. * 2 as published by the Free Software Foundation.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software
  28. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  29. * MA 02111-1307 USA
  30. *
  31. */
  32. #include <common.h>
  33. #if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
  34. #include <command.h>
  35. #include <watchdog.h>
  36. #include <malloc.h>
  37. #include <div64.h>
  38. #include <asm/errno.h>
  39. #include <linux/mtd/mtd.h>
  40. #include <nand.h>
  41. #include <jffs2/jffs2.h>
  42. typedef struct erase_info erase_info_t;
  43. typedef struct mtd_info mtd_info_t;
  44. /* support only for native endian JFFS2 */
  45. #define cpu_to_je16(x) (x)
  46. #define cpu_to_je32(x) (x)
  47. /*****************************************************************************/
  48. static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip)
  49. {
  50. return 0;
  51. }
  52. /**
  53. * nand_erase_opts: - erase NAND flash with support for various options
  54. * (jffs2 formating)
  55. *
  56. * @param meminfo NAND device to erase
  57. * @param opts options, @see struct nand_erase_options
  58. * @return 0 in case of success
  59. *
  60. * This code is ported from flash_eraseall.c from Linux mtd utils by
  61. * Arcom Control System Ltd.
  62. */
  63. int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
  64. {
  65. struct jffs2_unknown_node cleanmarker;
  66. erase_info_t erase;
  67. ulong erase_length;
  68. int bbtest = 1;
  69. int result;
  70. int percent_complete = -1;
  71. int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL;
  72. const char *mtd_device = meminfo->name;
  73. struct mtd_oob_ops oob_opts;
  74. struct nand_chip *chip = meminfo->priv;
  75. uint8_t buf[64];
  76. memset(buf, 0, sizeof(buf));
  77. memset(&erase, 0, sizeof(erase));
  78. memset(&oob_opts, 0, sizeof(oob_opts));
  79. erase.mtd = meminfo;
  80. erase.len = meminfo->erasesize;
  81. erase.addr = opts->offset;
  82. erase_length = opts->length;
  83. cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
  84. cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
  85. cleanmarker.totlen = cpu_to_je32(8);
  86. cleanmarker.hdr_crc = cpu_to_je32(
  87. crc32_no_comp(0, (unsigned char *) &cleanmarker,
  88. sizeof(struct jffs2_unknown_node) - 4));
  89. /* scrub option allows to erase badblock. To prevent internal
  90. * check from erase() method, set block check method to dummy
  91. * and disable bad block table while erasing.
  92. */
  93. if (opts->scrub) {
  94. struct nand_chip *priv_nand = meminfo->priv;
  95. nand_block_bad_old = priv_nand->block_bad;
  96. priv_nand->block_bad = nand_block_bad_scrub;
  97. /* we don't need the bad block table anymore...
  98. * after scrub, there are no bad blocks left!
  99. */
  100. if (priv_nand->bbt) {
  101. kfree(priv_nand->bbt);
  102. }
  103. priv_nand->bbt = NULL;
  104. }
  105. if (erase_length < meminfo->erasesize) {
  106. printf("Warning: Erase size 0x%08lx smaller than one " \
  107. "erase block 0x%08x\n",erase_length, meminfo->erasesize);
  108. printf(" Erasing 0x%08x instead\n", meminfo->erasesize);
  109. erase_length = meminfo->erasesize;
  110. }
  111. for (;
  112. erase.addr < opts->offset + erase_length;
  113. erase.addr += meminfo->erasesize) {
  114. WATCHDOG_RESET ();
  115. if (!opts->scrub && bbtest) {
  116. int ret = meminfo->block_isbad(meminfo, erase.addr);
  117. if (ret > 0) {
  118. if (!opts->quiet)
  119. printf("\rSkipping bad block at "
  120. "0x%08x "
  121. " \n",
  122. erase.addr);
  123. continue;
  124. } else if (ret < 0) {
  125. printf("\n%s: MTD get bad block failed: %d\n",
  126. mtd_device,
  127. ret);
  128. return -1;
  129. }
  130. }
  131. result = meminfo->erase(meminfo, &erase);
  132. if (result != 0) {
  133. printf("\n%s: MTD Erase failure: %d\n",
  134. mtd_device, result);
  135. continue;
  136. }
  137. /* format for JFFS2 ? */
  138. if (opts->jffs2) {
  139. chip->ops.len = chip->ops.ooblen = 64;
  140. chip->ops.datbuf = NULL;
  141. chip->ops.oobbuf = buf;
  142. chip->ops.ooboffs = chip->badblockpos & ~0x01;
  143. result = meminfo->write_oob(meminfo,
  144. erase.addr + meminfo->oobsize,
  145. &chip->ops);
  146. if (result != 0) {
  147. printf("\n%s: MTD writeoob failure: %d\n",
  148. mtd_device, result);
  149. continue;
  150. }
  151. else
  152. printf("%s: MTD writeoob at 0x%08x\n",mtd_device, erase.addr + meminfo->oobsize );
  153. }
  154. if (!opts->quiet) {
  155. unsigned long long n =(unsigned long long)
  156. (erase.addr + meminfo->erasesize - opts->offset)
  157. * 100;
  158. int percent;
  159. do_div(n, erase_length);
  160. percent = (int)n;
  161. /* output progress message only at whole percent
  162. * steps to reduce the number of messages printed
  163. * on (slow) serial consoles
  164. */
  165. if (percent != percent_complete) {
  166. percent_complete = percent;
  167. printf("\rErasing at 0x%x -- %3d%% complete.",
  168. erase.addr, percent);
  169. if (opts->jffs2 && result == 0)
  170. printf(" Cleanmarker written at 0x%x.",
  171. erase.addr);
  172. }
  173. }
  174. }
  175. if (!opts->quiet)
  176. printf("\n");
  177. if (nand_block_bad_old) {
  178. struct nand_chip *priv_nand = meminfo->priv;
  179. priv_nand->block_bad = nand_block_bad_old;
  180. priv_nand->scan_bbt(meminfo);
  181. }
  182. return 0;
  183. }
  184. /* XXX U-BOOT XXX */
  185. #if 0
  186. #define MAX_PAGE_SIZE 2048
  187. #define MAX_OOB_SIZE 64
  188. /*
  189. * buffer array used for writing data
  190. */
  191. static unsigned char data_buf[MAX_PAGE_SIZE];
  192. static unsigned char oob_buf[MAX_OOB_SIZE];
  193. /* OOB layouts to pass into the kernel as default */
  194. static struct nand_ecclayout none_ecclayout = {
  195. .useecc = MTD_NANDECC_OFF,
  196. };
  197. static struct nand_ecclayout jffs2_ecclayout = {
  198. .useecc = MTD_NANDECC_PLACE,
  199. .eccbytes = 6,
  200. .eccpos = { 0, 1, 2, 3, 6, 7 }
  201. };
  202. static struct nand_ecclayout yaffs_ecclayout = {
  203. .useecc = MTD_NANDECC_PLACE,
  204. .eccbytes = 6,
  205. .eccpos = { 8, 9, 10, 13, 14, 15}
  206. };
  207. static struct nand_ecclayout autoplace_ecclayout = {
  208. .useecc = MTD_NANDECC_AUTOPLACE
  209. };
  210. #endif
  211. /**
  212. * nand_fill_oob - [Internal] Transfer client buffer to oob
  213. * @chip: nand chip structure
  214. * @oob: oob data buffer
  215. * @ops: oob ops structure
  216. *
  217. * Copied from nand_base.c
  218. */
  219. static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
  220. struct mtd_oob_ops *ops)
  221. {
  222. size_t len = ops->ooblen;
  223. switch(ops->mode) {
  224. case MTD_OOB_PLACE:
  225. case MTD_OOB_RAW:
  226. memcpy(chip->oob_poi + ops->ooboffs, oob, len);
  227. return oob + len;
  228. case MTD_OOB_AUTO: {
  229. struct nand_oobfree *free = chip->ecc.layout->oobfree;
  230. uint32_t boffs = 0, woffs = ops->ooboffs;
  231. size_t bytes = 0;
  232. for(; free->length && len; free++, len -= bytes) {
  233. /* Write request not from offset 0 ? */
  234. if (unlikely(woffs)) {
  235. if (woffs >= free->length) {
  236. woffs -= free->length;
  237. continue;
  238. }
  239. boffs = free->offset + woffs;
  240. bytes = min_t(size_t, len,
  241. (free->length - woffs));
  242. woffs = 0;
  243. } else {
  244. bytes = min_t(size_t, len, free->length);
  245. boffs = free->offset;
  246. }
  247. memcpy(chip->oob_poi + boffs, oob, bytes);
  248. oob += bytes;
  249. }
  250. return oob;
  251. }
  252. default:
  253. BUG();
  254. }
  255. return NULL;
  256. }
  257. #define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0
  258. /* copied from nand_base.c: nand_do_write_ops()
  259. * Only very small changes
  260. */
  261. int nand_write_opts(nand_info_t *mtd, loff_t to, mtd_oob_ops_t *ops)
  262. {
  263. int chipnr, realpage, page, blockmask, column;
  264. struct nand_chip *chip = mtd->priv;
  265. uint32_t writelen = ops->len;
  266. uint8_t *oob = ops->oobbuf;
  267. uint8_t *buf = ops->datbuf;
  268. int ret, subpage;
  269. ops->retlen = 0;
  270. if (!writelen)
  271. return 0;
  272. printk("nand_write_opts: to: 0x%08x, ops->len: 0x%08x\n", to, ops->len);
  273. /* reject writes, which are not page aligned */
  274. if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
  275. printk(KERN_NOTICE "nand_write: "
  276. "Attempt to write not page aligned data\n");
  277. return -EINVAL;
  278. }
  279. column = to & (mtd->writesize - 1);
  280. subpage = column || (writelen & (mtd->writesize - 1));
  281. if (subpage && oob) {
  282. printk(KERN_NOTICE "nand_write: "
  283. "Attempt to write oob to subpage\n");
  284. return -EINVAL;
  285. }
  286. chipnr = (int)(to >> chip->chip_shift);
  287. chip->select_chip(mtd, chipnr);
  288. /* XXX U-BOOT XXX */
  289. #if 0
  290. /* Check, if it is write protected */
  291. if (nand_check_wp(mtd))
  292. return -EIO;
  293. #endif
  294. realpage = (int)(to >> chip->page_shift);
  295. page = realpage & chip->pagemask;
  296. blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
  297. /* Invalidate the page cache, when we write to the cached page */
  298. if (to <= (chip->pagebuf << chip->page_shift) &&
  299. (chip->pagebuf << chip->page_shift) < (to + ops->len))
  300. chip->pagebuf = -1;
  301. /* If we're not given explicit OOB data, let it be 0xFF */
  302. if (likely(!oob)) {
  303. printf("!oob, writing %d bytes with 0xff to chip->oob_poi (0x%08x)\n", mtd->oobsize, chip->oob_poi);
  304. memset(chip->oob_poi, 0xff, mtd->oobsize);
  305. }
  306. while(1) {
  307. int bytes = mtd->writesize;
  308. int cached = writelen > bytes && page != blockmask;
  309. uint8_t *wbuf = buf;
  310. /* Partial page write ? */
  311. if (unlikely(column || writelen < (mtd->writesize - 1))) {
  312. cached = 0;
  313. bytes = min_t(int, bytes - column, (int) writelen);
  314. chip->pagebuf = -1;
  315. memset(chip->buffers->databuf, 0xff, mtd->writesize);
  316. memcpy(&chip->buffers->databuf[column], buf, bytes);
  317. wbuf = chip->buffers->databuf;
  318. }
  319. if (unlikely(oob))
  320. oob = nand_fill_oob(chip, oob, ops);
  321. ret = chip->write_page(mtd, chip, wbuf, page, cached,
  322. (ops->mode == MTD_OOB_RAW));
  323. if (ret)
  324. break;
  325. writelen -= bytes;
  326. if (!writelen)
  327. break;
  328. column = 0;
  329. buf += bytes;
  330. realpage++;
  331. page = realpage & chip->pagemask;
  332. /* Check, if we cross a chip boundary */
  333. if (!page) {
  334. chipnr++;
  335. chip->select_chip(mtd, -1);
  336. chip->select_chip(mtd, chipnr);
  337. }
  338. }
  339. ops->retlen = ops->len - writelen;
  340. if (unlikely(oob))
  341. ops->oobretlen = ops->ooblen;
  342. return ret;
  343. }
  344. /* XXX U-BOOT XXX */
  345. #if 0
  346. /**
  347. * nand_write_opts: - write image to NAND flash with support for various options
  348. *
  349. * @param meminfo NAND device to erase
  350. * @param opts write options (@see nand_write_options)
  351. * @return 0 in case of success
  352. *
  353. * This code is ported from nandwrite.c from Linux mtd utils by
  354. * Steven J. Hill and Thomas Gleixner.
  355. */
  356. int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
  357. {
  358. int imglen = 0;
  359. int pagelen;
  360. int baderaseblock;
  361. int blockstart = -1;
  362. loff_t offs;
  363. int readlen;
  364. int ecclayoutchanged = 0;
  365. int percent_complete = -1;
  366. struct nand_ecclayout old_ecclayout;
  367. ulong mtdoffset = opts->offset;
  368. ulong erasesize_blockalign;
  369. u_char *buffer = opts->buffer;
  370. size_t written;
  371. int result;
  372. if (opts->pad && opts->writeoob) {
  373. printf("Can't pad when oob data is present.\n");
  374. return -1;
  375. }
  376. /* set erasesize to specified number of blocks - to match
  377. * jffs2 (virtual) block size */
  378. if (opts->blockalign == 0) {
  379. erasesize_blockalign = meminfo->erasesize;
  380. } else {
  381. erasesize_blockalign = meminfo->erasesize * opts->blockalign;
  382. }
  383. /* make sure device page sizes are valid */
  384. if (!(meminfo->oobsize == 16 && meminfo->writesize == 512)
  385. && !(meminfo->oobsize == 8 && meminfo->writesize == 256)
  386. && !(meminfo->oobsize == 64 && meminfo->writesize == 2048)) {
  387. printf("Unknown flash (not normal NAND)\n");
  388. return -1;
  389. }
  390. /* read the current oob info */
  391. memcpy(&old_ecclayout, &meminfo->ecclayout, sizeof(old_ecclayout));
  392. /* write without ecc? */
  393. if (opts->noecc) {
  394. memcpy(&meminfo->ecclayout, &none_ecclayout,
  395. sizeof(meminfo->ecclayout));
  396. ecclayoutchanged = 1;
  397. }
  398. /* autoplace ECC? */
  399. if (opts->autoplace && (old_ecclayout.useecc != MTD_NANDECC_AUTOPLACE)) {
  400. memcpy(&meminfo->ecclayout, &autoplace_ecclayout,
  401. sizeof(meminfo->ecclayout));
  402. ecclayoutchanged = 1;
  403. }
  404. /* force OOB layout for jffs2 or yaffs? */
  405. if (opts->forcejffs2 || opts->forceyaffs) {
  406. struct nand_ecclayout *oobsel =
  407. opts->forcejffs2 ? &jffs2_ecclayout : &yaffs_ecclayout;
  408. if (meminfo->oobsize == 8) {
  409. if (opts->forceyaffs) {
  410. printf("YAFSS cannot operate on "
  411. "256 Byte page size\n");
  412. goto restoreoob;
  413. }
  414. /* Adjust number of ecc bytes */
  415. jffs2_ecclayout.eccbytes = 3;
  416. }
  417. memcpy(&meminfo->ecclayout, oobsel, sizeof(meminfo->ecclayout));
  418. }
  419. /* get image length */
  420. imglen = opts->length;
  421. pagelen = meminfo->writesize
  422. + ((opts->writeoob != 0) ? meminfo->oobsize : 0);
  423. /* check, if file is pagealigned */
  424. if ((!opts->pad) && ((imglen % pagelen) != 0)) {
  425. printf("Input block length is not page aligned\n");
  426. goto restoreoob;
  427. }
  428. /* check, if length fits into device */
  429. if (((imglen / pagelen) * meminfo->writesize)
  430. > (meminfo->size - opts->offset)) {
  431. printf("Image %d bytes, NAND page %d bytes, "
  432. "OOB area %u bytes, device size %u bytes\n",
  433. imglen, pagelen, meminfo->writesize, meminfo->size);
  434. printf("Input block does not fit into device\n");
  435. goto restoreoob;
  436. }
  437. if (!opts->quiet)
  438. printf("\n");
  439. /* get data from input and write to the device */
  440. while (imglen && (mtdoffset < meminfo->size)) {
  441. WATCHDOG_RESET ();
  442. /*
  443. * new eraseblock, check for bad block(s). Stay in the
  444. * loop to be sure if the offset changes because of
  445. * a bad block, that the next block that will be
  446. * written to is also checked. Thus avoiding errors if
  447. * the block(s) after the skipped block(s) is also bad
  448. * (number of blocks depending on the blockalign
  449. */
  450. while (blockstart != (mtdoffset & (~erasesize_blockalign+1))) {
  451. blockstart = mtdoffset & (~erasesize_blockalign+1);
  452. offs = blockstart;
  453. baderaseblock = 0;
  454. /* check all the blocks in an erase block for
  455. * bad blocks */
  456. do {
  457. int ret = meminfo->block_isbad(meminfo, offs);
  458. if (ret < 0) {
  459. printf("Bad block check failed\n");
  460. goto restoreoob;
  461. }
  462. if (ret == 1) {
  463. baderaseblock = 1;
  464. if (!opts->quiet)
  465. printf("\rBad block at 0x%lx "
  466. "in erase block from "
  467. "0x%x will be skipped\n",
  468. (long) offs,
  469. blockstart);
  470. }
  471. if (baderaseblock) {
  472. mtdoffset = blockstart
  473. + erasesize_blockalign;
  474. }
  475. offs += erasesize_blockalign
  476. / opts->blockalign;
  477. } while (offs < blockstart + erasesize_blockalign);
  478. }
  479. readlen = meminfo->writesize;
  480. if (opts->pad && (imglen < readlen)) {
  481. readlen = imglen;
  482. memset(data_buf + readlen, 0xff,
  483. meminfo->writesize - readlen);
  484. }
  485. /* read page data from input memory buffer */
  486. memcpy(data_buf, buffer, readlen);
  487. buffer += readlen;
  488. if (opts->writeoob) {
  489. /* read OOB data from input memory block, exit
  490. * on failure */
  491. memcpy(oob_buf, buffer, meminfo->oobsize);
  492. buffer += meminfo->oobsize;
  493. /* write OOB data first, as ecc will be placed
  494. * in there*/
  495. result = meminfo->write_oob(meminfo,
  496. mtdoffset,
  497. meminfo->oobsize,
  498. &written,
  499. (unsigned char *)
  500. &oob_buf);
  501. if (result != 0) {
  502. printf("\nMTD writeoob failure: %d\n",
  503. result);
  504. goto restoreoob;
  505. }
  506. imglen -= meminfo->oobsize;
  507. }
  508. /* write out the page data */
  509. result = meminfo->write(meminfo,
  510. mtdoffset,
  511. meminfo->writesize,
  512. &written,
  513. (unsigned char *) &data_buf);
  514. if (result != 0) {
  515. printf("writing NAND page at offset 0x%lx failed\n",
  516. mtdoffset);
  517. goto restoreoob;
  518. }
  519. imglen -= readlen;
  520. if (!opts->quiet) {
  521. unsigned long long n = (unsigned long long)
  522. (opts->length-imglen) * 100;
  523. int percent;
  524. do_div(n, opts->length);
  525. percent = (int)n;
  526. /* output progress message only at whole percent
  527. * steps to reduce the number of messages printed
  528. * on (slow) serial consoles
  529. */
  530. if (percent != percent_complete) {
  531. printf("\rWriting data at 0x%lx "
  532. "-- %3d%% complete.",
  533. mtdoffset, percent);
  534. percent_complete = percent;
  535. }
  536. }
  537. mtdoffset += meminfo->writesize;
  538. }
  539. if (!opts->quiet)
  540. printf("\n");
  541. restoreoob:
  542. if (ecclayoutchanged) {
  543. memcpy(&meminfo->ecclayout, &old_ecclayout,
  544. sizeof(meminfo->ecclayout));
  545. }
  546. if (imglen > 0) {
  547. printf("Data did not fit into device, due to bad blocks\n");
  548. return -1;
  549. }
  550. /* return happy */
  551. return 0;
  552. }
  553. /**
  554. * nand_read_opts: - read image from NAND flash with support for various options
  555. *
  556. * @param meminfo NAND device to erase
  557. * @param opts read options (@see struct nand_read_options)
  558. * @return 0 in case of success
  559. *
  560. */
  561. int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)
  562. {
  563. int imglen = opts->length;
  564. int pagelen;
  565. int baderaseblock;
  566. int blockstart = -1;
  567. int percent_complete = -1;
  568. loff_t offs;
  569. size_t readlen;
  570. ulong mtdoffset = opts->offset;
  571. u_char *buffer = opts->buffer;
  572. int result;
  573. /* make sure device page sizes are valid */
  574. if (!(meminfo->oobsize == 16 && meminfo->writesize == 512)
  575. && !(meminfo->oobsize == 8 && meminfo->writesize == 256)
  576. && !(meminfo->oobsize == 64 && meminfo->writesize == 2048)) {
  577. printf("Unknown flash (not normal NAND)\n");
  578. return -1;
  579. }
  580. pagelen = meminfo->writesize
  581. + ((opts->readoob != 0) ? meminfo->oobsize : 0);
  582. /* check, if length is not larger than device */
  583. if (((imglen / pagelen) * meminfo->writesize)
  584. > (meminfo->size - opts->offset)) {
  585. printf("Image %d bytes, NAND page %d bytes, "
  586. "OOB area %u bytes, device size %u bytes\n",
  587. imglen, pagelen, meminfo->writesize, meminfo->size);
  588. printf("Input block is larger than device\n");
  589. return -1;
  590. }
  591. if (!opts->quiet)
  592. printf("\n");
  593. /* get data from input and write to the device */
  594. while (imglen && (mtdoffset < meminfo->size)) {
  595. WATCHDOG_RESET ();
  596. /*
  597. * new eraseblock, check for bad block(s). Stay in the
  598. * loop to be sure if the offset changes because of
  599. * a bad block, that the next block that will be
  600. * written to is also checked. Thus avoiding errors if
  601. * the block(s) after the skipped block(s) is also bad
  602. * (number of blocks depending on the blockalign
  603. */
  604. while (blockstart != (mtdoffset & (~meminfo->erasesize+1))) {
  605. blockstart = mtdoffset & (~meminfo->erasesize+1);
  606. offs = blockstart;
  607. baderaseblock = 0;
  608. /* check all the blocks in an erase block for
  609. * bad blocks */
  610. do {
  611. int ret = meminfo->block_isbad(meminfo, offs);
  612. if (ret < 0) {
  613. printf("Bad block check failed\n");
  614. return -1;
  615. }
  616. if (ret == 1) {
  617. baderaseblock = 1;
  618. if (!opts->quiet)
  619. printf("\rBad block at 0x%lx "
  620. "in erase block from "
  621. "0x%x will be skipped\n",
  622. (long) offs,
  623. blockstart);
  624. }
  625. if (baderaseblock) {
  626. mtdoffset = blockstart
  627. + meminfo->erasesize;
  628. }
  629. offs += meminfo->erasesize;
  630. } while (offs < blockstart + meminfo->erasesize);
  631. }
  632. /* read page data to memory buffer */
  633. result = meminfo->read(meminfo,
  634. mtdoffset,
  635. meminfo->writesize,
  636. &readlen,
  637. (unsigned char *) &data_buf);
  638. if (result != 0) {
  639. printf("reading NAND page at offset 0x%lx failed\n",
  640. mtdoffset);
  641. return -1;
  642. }
  643. if (imglen < readlen) {
  644. readlen = imglen;
  645. }
  646. memcpy(buffer, data_buf, readlen);
  647. buffer += readlen;
  648. imglen -= readlen;
  649. if (opts->readoob) {
  650. result = meminfo->read_oob(meminfo,
  651. mtdoffset,
  652. meminfo->oobsize,
  653. &readlen,
  654. (unsigned char *)
  655. &oob_buf);
  656. if (result != 0) {
  657. printf("\nMTD readoob failure: %d\n",
  658. result);
  659. return -1;
  660. }
  661. if (imglen < readlen) {
  662. readlen = imglen;
  663. }
  664. memcpy(buffer, oob_buf, readlen);
  665. buffer += readlen;
  666. imglen -= readlen;
  667. }
  668. if (!opts->quiet) {
  669. unsigned long long n = (unsigned long long)
  670. (opts->length-imglen) * 100;
  671. int percent;
  672. do_div(n, opts->length);
  673. percent = (int)n;
  674. /* output progress message only at whole percent
  675. * steps to reduce the number of messages printed
  676. * on (slow) serial consoles
  677. */
  678. if (percent != percent_complete) {
  679. if (!opts->quiet)
  680. printf("\rReading data from 0x%lx "
  681. "-- %3d%% complete.",
  682. mtdoffset, percent);
  683. percent_complete = percent;
  684. }
  685. }
  686. mtdoffset += meminfo->writesize;
  687. }
  688. if (!opts->quiet)
  689. printf("\n");
  690. if (imglen > 0) {
  691. printf("Could not read entire image due to bad blocks\n");
  692. return -1;
  693. }
  694. /* return happy */
  695. return 0;
  696. }
  697. #endif
  698. /* XXX U-BOOT XXX */
  699. #if 0
  700. /******************************************************************************
  701. * Support for locking / unlocking operations of some NAND devices
  702. *****************************************************************************/
  703. #define NAND_CMD_LOCK 0x2a
  704. #define NAND_CMD_LOCK_TIGHT 0x2c
  705. #define NAND_CMD_UNLOCK1 0x23
  706. #define NAND_CMD_UNLOCK2 0x24
  707. #define NAND_CMD_LOCK_STATUS 0x7a
  708. /**
  709. * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT
  710. * state
  711. *
  712. * @param meminfo nand mtd instance
  713. * @param tight bring device in lock tight mode
  714. *
  715. * @return 0 on success, -1 in case of error
  716. *
  717. * The lock / lock-tight command only applies to the whole chip. To get some
  718. * parts of the chip lock and others unlocked use the following sequence:
  719. *
  720. * - Lock all pages of the chip using nand_lock(mtd, 0) (or the lockpre pin)
  721. * - Call nand_unlock() once for each consecutive area to be unlocked
  722. * - If desired: Bring the chip to the lock-tight state using nand_lock(mtd, 1)
  723. *
  724. * If the device is in lock-tight state software can't change the
  725. * current active lock/unlock state of all pages. nand_lock() / nand_unlock()
  726. * calls will fail. It is only posible to leave lock-tight state by
  727. * an hardware signal (low pulse on _WP pin) or by power down.
  728. */
  729. int nand_lock(nand_info_t *meminfo, int tight)
  730. {
  731. int ret = 0;
  732. int status;
  733. struct nand_chip *this = meminfo->priv;
  734. /* select the NAND device */
  735. this->select_chip(meminfo, 0);
  736. this->cmdfunc(meminfo,
  737. (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK),
  738. -1, -1);
  739. /* call wait ready function */
  740. status = this->waitfunc(meminfo, this, FL_WRITING);
  741. /* see if device thinks it succeeded */
  742. if (status & 0x01) {
  743. ret = -1;
  744. }
  745. /* de-select the NAND device */
  746. this->select_chip(meminfo, -1);
  747. return ret;
  748. }
  749. /**
  750. * nand_get_lock_status: - query current lock state from one page of NAND
  751. * flash
  752. *
  753. * @param meminfo nand mtd instance
  754. * @param offset page address to query (muss be page aligned!)
  755. *
  756. * @return -1 in case of error
  757. * >0 lock status:
  758. * bitfield with the following combinations:
  759. * NAND_LOCK_STATUS_TIGHT: page in tight state
  760. * NAND_LOCK_STATUS_LOCK: page locked
  761. * NAND_LOCK_STATUS_UNLOCK: page unlocked
  762. *
  763. */
  764. int nand_get_lock_status(nand_info_t *meminfo, ulong offset)
  765. {
  766. int ret = 0;
  767. int chipnr;
  768. int page;
  769. struct nand_chip *this = meminfo->priv;
  770. /* select the NAND device */
  771. chipnr = (int)(offset >> this->chip_shift);
  772. this->select_chip(meminfo, chipnr);
  773. if ((offset & (meminfo->writesize - 1)) != 0) {
  774. printf ("nand_get_lock_status: "
  775. "Start address must be beginning of "
  776. "nand page!\n");
  777. ret = -1;
  778. goto out;
  779. }
  780. /* check the Lock Status */
  781. page = (int)(offset >> this->page_shift);
  782. this->cmdfunc(meminfo, NAND_CMD_LOCK_STATUS, -1, page & this->pagemask);
  783. ret = this->read_byte(meminfo) & (NAND_LOCK_STATUS_TIGHT
  784. | NAND_LOCK_STATUS_LOCK
  785. | NAND_LOCK_STATUS_UNLOCK);
  786. out:
  787. /* de-select the NAND device */
  788. this->select_chip(meminfo, -1);
  789. return ret;
  790. }
  791. /**
  792. * nand_unlock: - Unlock area of NAND pages
  793. * only one consecutive area can be unlocked at one time!
  794. *
  795. * @param meminfo nand mtd instance
  796. * @param start start byte address
  797. * @param length number of bytes to unlock (must be a multiple of
  798. * page size nand->writesize)
  799. *
  800. * @return 0 on success, -1 in case of error
  801. */
  802. int nand_unlock(nand_info_t *meminfo, ulong start, ulong length)
  803. {
  804. int ret = 0;
  805. int chipnr;
  806. int status;
  807. int page;
  808. struct nand_chip *this = meminfo->priv;
  809. printf ("nand_unlock: start: %08x, length: %d!\n",
  810. (int)start, (int)length);
  811. /* select the NAND device */
  812. chipnr = (int)(start >> this->chip_shift);
  813. this->select_chip(meminfo, chipnr);
  814. /* check the WP bit */
  815. this->cmdfunc(meminfo, NAND_CMD_STATUS, -1, -1);
  816. if ((this->read_byte(meminfo) & 0x80) == 0) {
  817. printf ("nand_unlock: Device is write protected!\n");
  818. ret = -1;
  819. goto out;
  820. }
  821. if ((start & (meminfo->writesize - 1)) != 0) {
  822. printf ("nand_unlock: Start address must be beginning of "
  823. "nand page!\n");
  824. ret = -1;
  825. goto out;
  826. }
  827. if (length == 0 || (length & (meminfo->writesize - 1)) != 0) {
  828. printf ("nand_unlock: Length must be a multiple of nand page "
  829. "size!\n");
  830. ret = -1;
  831. goto out;
  832. }
  833. /* submit address of first page to unlock */
  834. page = (int)(start >> this->page_shift);
  835. this->cmdfunc(meminfo, NAND_CMD_UNLOCK1, -1, page & this->pagemask);
  836. /* submit ADDRESS of LAST page to unlock */
  837. page += (int)(length >> this->page_shift) - 1;
  838. this->cmdfunc(meminfo, NAND_CMD_UNLOCK2, -1, page & this->pagemask);
  839. /* call wait ready function */
  840. status = this->waitfunc(meminfo, this, FL_WRITING);
  841. /* see if device thinks it succeeded */
  842. if (status & 0x01) {
  843. /* there was an error */
  844. ret = -1;
  845. goto out;
  846. }
  847. out:
  848. /* de-select the NAND device */
  849. this->select_chip(meminfo, -1);
  850. return ret;
  851. }
  852. #endif
  853. #endif