omap_gpmc.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. /*
  2. * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
  3. * Rohit Choraria <rohitkc@ti.com>
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <common.h>
  24. #include <asm/io.h>
  25. #include <asm/errno.h>
  26. #include <asm/arch/mem.h>
  27. #include <asm/arch/omap_gpmc.h>
  28. #include <linux/mtd/nand_ecc.h>
  29. #include <linux/compiler.h>
  30. #include <nand.h>
  31. #ifdef CONFIG_AM33XX
  32. #include <asm/arch/elm.h>
  33. #endif
  34. static uint8_t cs;
  35. static __maybe_unused struct nand_ecclayout hw_nand_oob =
  36. GPMC_NAND_HW_ECC_LAYOUT;
  37. /*
  38. * omap_nand_hwcontrol - Set the address pointers corretly for the
  39. * following address/data/command operation
  40. */
  41. static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
  42. uint32_t ctrl)
  43. {
  44. register struct nand_chip *this = mtd->priv;
  45. /*
  46. * Point the IO_ADDR to DATA and ADDRESS registers instead
  47. * of chip address
  48. */
  49. switch (ctrl) {
  50. case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
  51. this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
  52. break;
  53. case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
  54. this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
  55. break;
  56. case NAND_CTRL_CHANGE | NAND_NCE:
  57. this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
  58. break;
  59. }
  60. if (cmd != NAND_CMD_NONE)
  61. writeb(cmd, this->IO_ADDR_W);
  62. }
  63. #ifdef CONFIG_SPL_BUILD
  64. /* Check wait pin as dev ready indicator */
  65. int omap_spl_dev_ready(struct mtd_info *mtd)
  66. {
  67. return gpmc_cfg->status & (1 << 8);
  68. }
  69. #endif
  70. /*
  71. * omap_hwecc_init - Initialize the Hardware ECC for NAND flash in
  72. * GPMC controller
  73. * @mtd: MTD device structure
  74. *
  75. */
  76. static void __maybe_unused omap_hwecc_init(struct nand_chip *chip)
  77. {
  78. /*
  79. * Init ECC Control Register
  80. * Clear all ECC | Enable Reg1
  81. */
  82. writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
  83. writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL, &gpmc_cfg->ecc_size_config);
  84. }
  85. /*
  86. * gen_true_ecc - This function will generate true ECC value, which
  87. * can be used when correcting data read from NAND flash memory core
  88. *
  89. * @ecc_buf: buffer to store ecc code
  90. *
  91. * @return: re-formatted ECC value
  92. */
  93. static uint32_t gen_true_ecc(uint8_t *ecc_buf)
  94. {
  95. return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
  96. ((ecc_buf[2] & 0x0F) << 8);
  97. }
  98. /*
  99. * omap_correct_data - Compares the ecc read from nand spare area with ECC
  100. * registers values and corrects one bit error if it has occured
  101. * Further details can be had from OMAP TRM and the following selected links:
  102. * http://en.wikipedia.org/wiki/Hamming_code
  103. * http://www.cs.utexas.edu/users/plaxton/c/337/05f/slides/ErrorCorrection-4.pdf
  104. *
  105. * @mtd: MTD device structure
  106. * @dat: page data
  107. * @read_ecc: ecc read from nand flash
  108. * @calc_ecc: ecc read from ECC registers
  109. *
  110. * @return 0 if data is OK or corrected, else returns -1
  111. */
  112. static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
  113. uint8_t *read_ecc, uint8_t *calc_ecc)
  114. {
  115. uint32_t orig_ecc, new_ecc, res, hm;
  116. uint16_t parity_bits, byte;
  117. uint8_t bit;
  118. /* Regenerate the orginal ECC */
  119. orig_ecc = gen_true_ecc(read_ecc);
  120. new_ecc = gen_true_ecc(calc_ecc);
  121. /* Get the XOR of real ecc */
  122. res = orig_ecc ^ new_ecc;
  123. if (res) {
  124. /* Get the hamming width */
  125. hm = hweight32(res);
  126. /* Single bit errors can be corrected! */
  127. if (hm == 12) {
  128. /* Correctable data! */
  129. parity_bits = res >> 16;
  130. bit = (parity_bits & 0x7);
  131. byte = (parity_bits >> 3) & 0x1FF;
  132. /* Flip the bit to correct */
  133. dat[byte] ^= (0x1 << bit);
  134. } else if (hm == 1) {
  135. printf("Error: Ecc is wrong\n");
  136. /* ECC itself is corrupted */
  137. return 2;
  138. } else {
  139. /*
  140. * hm distance != parity pairs OR one, could mean 2 bit
  141. * error OR potentially be on a blank page..
  142. * orig_ecc: contains spare area data from nand flash.
  143. * new_ecc: generated ecc while reading data area.
  144. * Note: if the ecc = 0, all data bits from which it was
  145. * generated are 0xFF.
  146. * The 3 byte(24 bits) ecc is generated per 512byte
  147. * chunk of a page. If orig_ecc(from spare area)
  148. * is 0xFF && new_ecc(computed now from data area)=0x0,
  149. * this means that data area is 0xFF and spare area is
  150. * 0xFF. A sure sign of a erased page!
  151. */
  152. if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
  153. return 0;
  154. printf("Error: Bad compare! failed\n");
  155. /* detected 2 bit error */
  156. return -1;
  157. }
  158. }
  159. return 0;
  160. }
  161. /*
  162. * omap_calculate_ecc - Generate non-inverted ECC bytes.
  163. *
  164. * Using noninverted ECC can be considered ugly since writing a blank
  165. * page ie. padding will clear the ECC bytes. This is no problem as
  166. * long nobody is trying to write data on the seemingly unused page.
  167. * Reading an erased page will produce an ECC mismatch between
  168. * generated and read ECC bytes that has to be dealt with separately.
  169. * E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
  170. * is used, the result of read will be 0x0 while the ECC offsets of the
  171. * spare area will be 0xFF which will result in an ECC mismatch.
  172. * @mtd: MTD structure
  173. * @dat: unused
  174. * @ecc_code: ecc_code buffer
  175. */
  176. static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
  177. const uint8_t *dat, uint8_t *ecc_code)
  178. {
  179. u_int32_t val;
  180. /* Start Reading from HW ECC1_Result = 0x200 */
  181. val = readl(&gpmc_cfg->ecc1_result);
  182. ecc_code[0] = val & 0xFF;
  183. ecc_code[1] = (val >> 16) & 0xFF;
  184. ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
  185. /*
  186. * Stop reading anymore ECC vals and clear old results
  187. * enable will be called if more reads are required
  188. */
  189. writel(0x000, &gpmc_cfg->ecc_config);
  190. return 0;
  191. }
  192. /*
  193. * omap_enable_ecc - This function enables the hardware ecc functionality
  194. * @mtd: MTD device structure
  195. * @mode: Read/Write mode
  196. */
  197. static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
  198. {
  199. struct nand_chip *chip = mtd->priv;
  200. uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
  201. switch (mode) {
  202. case NAND_ECC_READ:
  203. case NAND_ECC_WRITE:
  204. /* Clear the ecc result registers, select ecc reg as 1 */
  205. writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
  206. /*
  207. * Size 0 = 0xFF, Size1 is 0xFF - both are 512 bytes
  208. * tell all regs to generate size0 sized regs
  209. * we just have a single ECC engine for all CS
  210. */
  211. writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL,
  212. &gpmc_cfg->ecc_size_config);
  213. val = (dev_width << 7) | (cs << 1) | (0x1);
  214. writel(val, &gpmc_cfg->ecc_config);
  215. break;
  216. default:
  217. printf("Error: Unrecognized Mode[%d]!\n", mode);
  218. break;
  219. }
  220. }
  221. /*
  222. * BCH8 support (needs ELM and thus AM33xx-only)
  223. */
  224. #ifdef CONFIG_AM33XX
  225. struct nand_bch_priv {
  226. uint8_t mode;
  227. uint8_t type;
  228. uint8_t nibbles;
  229. };
  230. /* bch types */
  231. #define ECC_BCH4 0
  232. #define ECC_BCH8 1
  233. #define ECC_BCH16 2
  234. /* BCH nibbles for diff bch levels */
  235. #define NAND_ECC_HW_BCH ((uint8_t)(NAND_ECC_HW_OOB_FIRST) + 1)
  236. #define ECC_BCH4_NIBBLES 13
  237. #define ECC_BCH8_NIBBLES 26
  238. #define ECC_BCH16_NIBBLES 52
  239. static struct nand_ecclayout hw_bch8_nand_oob = GPMC_NAND_HW_BCH8_ECC_LAYOUT;
  240. static struct nand_bch_priv bch_priv = {
  241. .mode = NAND_ECC_HW_BCH,
  242. .type = ECC_BCH8,
  243. .nibbles = ECC_BCH8_NIBBLES
  244. };
  245. /*
  246. * omap_read_bch8_result - Read BCH result for BCH8 level
  247. *
  248. * @mtd: MTD device structure
  249. * @big_endian: When set read register 3 first
  250. * @ecc_code: Read syndrome from BCH result registers
  251. */
  252. static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
  253. uint8_t *ecc_code)
  254. {
  255. uint32_t *ptr;
  256. int8_t i = 0, j;
  257. if (big_endian) {
  258. ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
  259. ecc_code[i++] = readl(ptr) & 0xFF;
  260. ptr--;
  261. for (j = 0; j < 3; j++) {
  262. ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
  263. ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
  264. ecc_code[i++] = (readl(ptr) >> 8) & 0xFF;
  265. ecc_code[i++] = readl(ptr) & 0xFF;
  266. ptr--;
  267. }
  268. } else {
  269. ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[0];
  270. for (j = 0; j < 3; j++) {
  271. ecc_code[i++] = readl(ptr) & 0xFF;
  272. ecc_code[i++] = (readl(ptr) >> 8) & 0xFF;
  273. ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
  274. ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
  275. ptr++;
  276. }
  277. ecc_code[i++] = readl(ptr) & 0xFF;
  278. ecc_code[i++] = 0; /* 14th byte is always zero */
  279. }
  280. }
  281. /*
  282. * omap_ecc_disable - Disable H/W ECC calculation
  283. *
  284. * @mtd: MTD device structure
  285. *
  286. */
  287. static void omap_ecc_disable(struct mtd_info *mtd)
  288. {
  289. writel((readl(&gpmc_cfg->ecc_config) & ~0x1),
  290. &gpmc_cfg->ecc_config);
  291. }
  292. /*
  293. * omap_rotate_ecc_bch - Rotate the syndrome bytes
  294. *
  295. * @mtd: MTD device structure
  296. * @calc_ecc: ECC read from ECC registers
  297. * @syndrome: Rotated syndrome will be retuned in this array
  298. *
  299. */
  300. static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
  301. uint8_t *syndrome)
  302. {
  303. struct nand_chip *chip = mtd->priv;
  304. struct nand_bch_priv *bch = chip->priv;
  305. uint8_t n_bytes = 0;
  306. int8_t i, j;
  307. switch (bch->type) {
  308. case ECC_BCH4:
  309. n_bytes = 8;
  310. break;
  311. case ECC_BCH16:
  312. n_bytes = 28;
  313. break;
  314. case ECC_BCH8:
  315. default:
  316. n_bytes = 13;
  317. break;
  318. }
  319. for (i = 0, j = (n_bytes-1); i < n_bytes; i++, j--)
  320. syndrome[i] = calc_ecc[j];
  321. }
  322. /*
  323. * omap_calculate_ecc_bch - Read BCH ECC result
  324. *
  325. * @mtd: MTD structure
  326. * @dat: unused
  327. * @ecc_code: ecc_code buffer
  328. */
  329. static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
  330. uint8_t *ecc_code)
  331. {
  332. struct nand_chip *chip = mtd->priv;
  333. struct nand_bch_priv *bch = chip->priv;
  334. uint8_t big_endian = 1;
  335. int8_t ret = 0;
  336. if (bch->type == ECC_BCH8)
  337. omap_read_bch8_result(mtd, big_endian, ecc_code);
  338. else /* BCH4 and BCH16 currently not supported */
  339. ret = -1;
  340. /*
  341. * Stop reading anymore ECC vals and clear old results
  342. * enable will be called if more reads are required
  343. */
  344. omap_ecc_disable(mtd);
  345. return ret;
  346. }
  347. /*
  348. * omap_fix_errors_bch - Correct bch error in the data
  349. *
  350. * @mtd: MTD device structure
  351. * @data: Data read from flash
  352. * @error_count:Number of errors in data
  353. * @error_loc: Locations of errors in the data
  354. *
  355. */
  356. static void omap_fix_errors_bch(struct mtd_info *mtd, uint8_t *data,
  357. uint32_t error_count, uint32_t *error_loc)
  358. {
  359. struct nand_chip *chip = mtd->priv;
  360. struct nand_bch_priv *bch = chip->priv;
  361. uint8_t count = 0;
  362. uint32_t error_byte_pos;
  363. uint32_t error_bit_mask;
  364. uint32_t last_bit = (bch->nibbles * 4) - 1;
  365. /* Flip all bits as specified by the error location array. */
  366. /* FOR( each found error location flip the bit ) */
  367. for (count = 0; count < error_count; count++) {
  368. if (error_loc[count] > last_bit) {
  369. /* Remove the ECC spare bits from correction. */
  370. error_loc[count] -= (last_bit + 1);
  371. /* Offset bit in data region */
  372. error_byte_pos = ((512 * 8) -
  373. (error_loc[count]) - 1) / 8;
  374. /* Error Bit mask */
  375. error_bit_mask = 0x1 << (error_loc[count] % 8);
  376. /* Toggle the error bit to make the correction. */
  377. data[error_byte_pos] ^= error_bit_mask;
  378. }
  379. }
  380. }
  381. /*
  382. * omap_correct_data_bch - Compares the ecc read from nand spare area
  383. * with ECC registers values and corrects one bit error if it has occured
  384. *
  385. * @mtd: MTD device structure
  386. * @dat: page data
  387. * @read_ecc: ecc read from nand flash (ignored)
  388. * @calc_ecc: ecc read from ECC registers
  389. *
  390. * @return 0 if data is OK or corrected, else returns -1
  391. */
  392. static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
  393. uint8_t *read_ecc, uint8_t *calc_ecc)
  394. {
  395. struct nand_chip *chip = mtd->priv;
  396. struct nand_bch_priv *bch = chip->priv;
  397. uint8_t syndrome[28];
  398. uint32_t error_count = 0;
  399. uint32_t error_loc[8];
  400. uint32_t i, ecc_flag;
  401. ecc_flag = 0;
  402. for (i = 0; i < chip->ecc.bytes; i++)
  403. if (read_ecc[i] != 0xff)
  404. ecc_flag = 1;
  405. if (!ecc_flag)
  406. return 0;
  407. elm_reset();
  408. elm_config((enum bch_level)(bch->type));
  409. /*
  410. * while reading ECC result we read it in big endian.
  411. * Hence while loading to ELM we have rotate to get the right endian.
  412. */
  413. omap_rotate_ecc_bch(mtd, calc_ecc, syndrome);
  414. /* use elm module to check for errors */
  415. if (elm_check_error(syndrome, bch->nibbles, &error_count,
  416. error_loc) != 0) {
  417. printf("ECC: uncorrectable.\n");
  418. return -1;
  419. }
  420. /* correct bch error */
  421. if (error_count > 0)
  422. omap_fix_errors_bch(mtd, dat, error_count, error_loc);
  423. return 0;
  424. }
  425. /*
  426. * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
  427. * GPMC controller
  428. * @mtd: MTD device structure
  429. * @mode: Read/Write mode
  430. */
  431. static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
  432. {
  433. uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
  434. uint32_t unused_length = 0;
  435. struct nand_bch_priv *bch = chip->priv;
  436. switch (bch->nibbles) {
  437. case ECC_BCH4_NIBBLES:
  438. unused_length = 3;
  439. break;
  440. case ECC_BCH8_NIBBLES:
  441. unused_length = 2;
  442. break;
  443. case ECC_BCH16_NIBBLES:
  444. unused_length = 0;
  445. break;
  446. }
  447. /* Clear the ecc result registers, select ecc reg as 1 */
  448. writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
  449. switch (mode) {
  450. case NAND_ECC_WRITE:
  451. /* eccsize1 config */
  452. val = ((unused_length + bch->nibbles) << 22);
  453. break;
  454. case NAND_ECC_READ:
  455. default:
  456. /* by default eccsize0 selected for ecc1resultsize */
  457. /* eccsize0 config */
  458. val = (bch->nibbles << 12);
  459. /* eccsize1 config */
  460. val |= (unused_length << 22);
  461. break;
  462. }
  463. /* ecc size configuration */
  464. writel(val, &gpmc_cfg->ecc_size_config);
  465. /* by default 512bytes sector page is selected */
  466. /* set bch mode */
  467. val = (1 << 16);
  468. /* bch4 / bch8 / bch16 */
  469. val |= (bch->type << 12);
  470. /* set wrap mode to 1 */
  471. val |= (1 << 8);
  472. val |= (dev_width << 7);
  473. val |= (cs << 1);
  474. writel(val, &gpmc_cfg->ecc_config);
  475. }
  476. /*
  477. * omap_enable_ecc_bch- This function enables the bch h/w ecc functionality
  478. * @mtd: MTD device structure
  479. * @mode: Read/Write mode
  480. *
  481. */
  482. static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
  483. {
  484. struct nand_chip *chip = mtd->priv;
  485. omap_hwecc_init_bch(chip, mode);
  486. /* enable ecc */
  487. writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config);
  488. }
  489. /**
  490. * omap_read_page_bch - hardware ecc based page read function
  491. * @mtd: mtd info structure
  492. * @chip: nand chip info structure
  493. * @buf: buffer to store read data
  494. * @page: page number to read
  495. *
  496. */
  497. static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
  498. uint8_t *buf, int page)
  499. {
  500. int i, eccsize = chip->ecc.size;
  501. int eccbytes = chip->ecc.bytes;
  502. int eccsteps = chip->ecc.steps;
  503. uint8_t *p = buf;
  504. uint8_t *ecc_calc = chip->buffers->ecccalc;
  505. uint8_t *ecc_code = chip->buffers->ecccode;
  506. uint32_t *eccpos = chip->ecc.layout->eccpos;
  507. uint8_t *oob = chip->oob_poi;
  508. uint32_t data_pos;
  509. uint32_t oob_pos;
  510. data_pos = 0;
  511. /* oob area start */
  512. oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
  513. oob += chip->ecc.layout->eccpos[0];
  514. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
  515. oob += eccbytes) {
  516. chip->ecc.hwctl(mtd, NAND_ECC_READ);
  517. /* read data */
  518. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
  519. chip->read_buf(mtd, p, eccsize);
  520. /* read respective ecc from oob area */
  521. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
  522. chip->read_buf(mtd, oob, eccbytes);
  523. /* read syndrome */
  524. chip->ecc.calculate(mtd, p, &ecc_calc[i]);
  525. data_pos += eccsize;
  526. oob_pos += eccbytes;
  527. }
  528. for (i = 0; i < chip->ecc.total; i++)
  529. ecc_code[i] = chip->oob_poi[eccpos[i]];
  530. eccsteps = chip->ecc.steps;
  531. p = buf;
  532. for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  533. int stat;
  534. stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
  535. if (stat < 0)
  536. mtd->ecc_stats.failed++;
  537. else
  538. mtd->ecc_stats.corrected += stat;
  539. }
  540. return 0;
  541. }
  542. #endif /* CONFIG_AM33XX */
  543. #ifndef CONFIG_SPL_BUILD
  544. /*
  545. * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
  546. * The default is to come up on s/w ecc
  547. *
  548. * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
  549. *
  550. */
  551. void omap_nand_switch_ecc(int32_t hardware)
  552. {
  553. struct nand_chip *nand;
  554. struct mtd_info *mtd;
  555. if (nand_curr_device < 0 ||
  556. nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
  557. !nand_info[nand_curr_device].name) {
  558. printf("Error: Can't switch ecc, no devices available\n");
  559. return;
  560. }
  561. mtd = &nand_info[nand_curr_device];
  562. nand = mtd->priv;
  563. nand->options |= NAND_OWN_BUFFERS;
  564. /* Reset ecc interface */
  565. nand->ecc.read_page = NULL;
  566. nand->ecc.write_page = NULL;
  567. nand->ecc.read_oob = NULL;
  568. nand->ecc.write_oob = NULL;
  569. nand->ecc.hwctl = NULL;
  570. nand->ecc.correct = NULL;
  571. nand->ecc.calculate = NULL;
  572. /* Setup the ecc configurations again */
  573. if (hardware == 1) {
  574. nand->ecc.mode = NAND_ECC_HW;
  575. nand->ecc.layout = &hw_nand_oob;
  576. nand->ecc.size = 512;
  577. nand->ecc.bytes = 3;
  578. nand->ecc.hwctl = omap_enable_hwecc;
  579. nand->ecc.correct = omap_correct_data;
  580. nand->ecc.calculate = omap_calculate_ecc;
  581. omap_hwecc_init(nand);
  582. printf("HW ECC selected\n");
  583. #ifdef CONFIG_AM33XX
  584. } else if (hardware == 2) {
  585. nand->ecc.mode = NAND_ECC_HW;
  586. nand->ecc.layout = &hw_bch8_nand_oob;
  587. nand->ecc.size = 512;
  588. nand->ecc.bytes = 14;
  589. nand->ecc.read_page = omap_read_page_bch;
  590. nand->ecc.hwctl = omap_enable_ecc_bch;
  591. nand->ecc.correct = omap_correct_data_bch;
  592. nand->ecc.calculate = omap_calculate_ecc_bch;
  593. omap_hwecc_init_bch(nand, NAND_ECC_READ);
  594. printf("HW BCH8 selected\n");
  595. #endif
  596. } else {
  597. nand->ecc.mode = NAND_ECC_SOFT;
  598. /* Use mtd default settings */
  599. nand->ecc.layout = NULL;
  600. nand->ecc.size = 0;
  601. printf("SW ECC selected\n");
  602. }
  603. /* Update NAND handling after ECC mode switch */
  604. nand_scan_tail(mtd);
  605. nand->options &= ~NAND_OWN_BUFFERS;
  606. }
  607. #endif /* CONFIG_SPL_BUILD */
  608. /*
  609. * Board-specific NAND initialization. The following members of the
  610. * argument are board-specific:
  611. * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
  612. * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
  613. * - cmd_ctrl: hardwarespecific function for accesing control-lines
  614. * - waitfunc: hardwarespecific function for accesing device ready/busy line
  615. * - ecc.hwctl: function to enable (reset) hardware ecc generator
  616. * - ecc.mode: mode of ecc, see defines
  617. * - chip_delay: chip dependent delay for transfering data from array to
  618. * read regs (tR)
  619. * - options: various chip options. They can partly be set to inform
  620. * nand_scan about special functionality. See the defines for further
  621. * explanation
  622. */
  623. int board_nand_init(struct nand_chip *nand)
  624. {
  625. int32_t gpmc_config = 0;
  626. cs = 0;
  627. /*
  628. * xloader/Uboot's gpmc configuration would have configured GPMC for
  629. * nand type of memory. The following logic scans and latches on to the
  630. * first CS with NAND type memory.
  631. * TBD: need to make this logic generic to handle multiple CS NAND
  632. * devices.
  633. */
  634. while (cs < GPMC_MAX_CS) {
  635. /* Check if NAND type is set */
  636. if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
  637. /* Found it!! */
  638. break;
  639. }
  640. cs++;
  641. }
  642. if (cs >= GPMC_MAX_CS) {
  643. printf("NAND: Unable to find NAND settings in "
  644. "GPMC Configuration - quitting\n");
  645. return -ENODEV;
  646. }
  647. gpmc_config = readl(&gpmc_cfg->config);
  648. /* Disable Write protect */
  649. gpmc_config |= 0x10;
  650. writel(gpmc_config, &gpmc_cfg->config);
  651. nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
  652. nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
  653. nand->cmd_ctrl = omap_nand_hwcontrol;
  654. nand->options = NAND_NO_PADDING | NAND_CACHEPRG | NAND_NO_AUTOINCR;
  655. /* If we are 16 bit dev, our gpmc config tells us that */
  656. if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
  657. nand->options |= NAND_BUSWIDTH_16;
  658. nand->chip_delay = 100;
  659. #ifdef CONFIG_AM33XX
  660. /* required in case of BCH */
  661. elm_init();
  662. /* BCH info that will be correct for SPL or overridden otherwise. */
  663. nand->priv = &bch_priv;
  664. #endif
  665. /* Default ECC mode */
  666. #ifdef CONFIG_AM33XX
  667. nand->ecc.mode = NAND_ECC_HW;
  668. nand->ecc.layout = &hw_bch8_nand_oob;
  669. nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
  670. nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
  671. nand->ecc.hwctl = omap_enable_ecc_bch;
  672. nand->ecc.correct = omap_correct_data_bch;
  673. nand->ecc.calculate = omap_calculate_ecc_bch;
  674. nand->ecc.read_page = omap_read_page_bch;
  675. omap_hwecc_init_bch(nand, NAND_ECC_READ);
  676. #else
  677. #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
  678. nand->ecc.mode = NAND_ECC_SOFT;
  679. #else
  680. nand->ecc.mode = NAND_ECC_HW;
  681. nand->ecc.layout = &hw_nand_oob;
  682. nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
  683. nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
  684. nand->ecc.hwctl = omap_enable_hwecc;
  685. nand->ecc.correct = omap_correct_data;
  686. nand->ecc.calculate = omap_calculate_ecc;
  687. omap_hwecc_init(nand);
  688. #endif
  689. #endif
  690. #ifdef CONFIG_SPL_BUILD
  691. if (nand->options & NAND_BUSWIDTH_16)
  692. nand->read_buf = nand_read_buf16;
  693. else
  694. nand->read_buf = nand_read_buf;
  695. nand->dev_ready = omap_spl_dev_ready;
  696. #endif
  697. return 0;
  698. }