omap_gpmc.c 21 KB

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