omap_gpmc.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. /*
  2. * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
  3. * Rohit Choraria <rohitkc@ti.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <asm/io.h>
  9. #include <asm/errno.h>
  10. #include <asm/arch/mem.h>
  11. #include <asm/arch/cpu.h>
  12. #include <asm/omap_gpmc.h>
  13. #include <linux/mtd/nand_ecc.h>
  14. #include <linux/bch.h>
  15. #include <linux/compiler.h>
  16. #include <nand.h>
  17. #include <asm/omap_elm.h>
  18. #define BADBLOCK_MARKER_LENGTH 2
  19. #define SECTOR_BYTES 512
  20. #define ECCCLEAR (0x1 << 8)
  21. #define ECCRESULTREG1 (0x1 << 0)
  22. /* 4 bit padding to make byte aligned, 56 = 52 + 4 */
  23. #define BCH4_BIT_PAD 4
  24. #ifdef CONFIG_BCH
  25. static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
  26. 0x97, 0x79, 0xe5, 0x24, 0xb5};
  27. #endif
  28. static uint8_t cs;
  29. static __maybe_unused struct nand_ecclayout omap_ecclayout;
  30. /*
  31. * omap_nand_hwcontrol - Set the address pointers corretly for the
  32. * following address/data/command operation
  33. */
  34. static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
  35. uint32_t ctrl)
  36. {
  37. register struct nand_chip *this = mtd->priv;
  38. /*
  39. * Point the IO_ADDR to DATA and ADDRESS registers instead
  40. * of chip address
  41. */
  42. switch (ctrl) {
  43. case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
  44. this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
  45. break;
  46. case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
  47. this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
  48. break;
  49. case NAND_CTRL_CHANGE | NAND_NCE:
  50. this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
  51. break;
  52. }
  53. if (cmd != NAND_CMD_NONE)
  54. writeb(cmd, this->IO_ADDR_W);
  55. }
  56. #ifdef CONFIG_SPL_BUILD
  57. /* Check wait pin as dev ready indicator */
  58. int omap_spl_dev_ready(struct mtd_info *mtd)
  59. {
  60. return gpmc_cfg->status & (1 << 8);
  61. }
  62. #endif
  63. /*
  64. * gen_true_ecc - This function will generate true ECC value, which
  65. * can be used when correcting data read from NAND flash memory core
  66. *
  67. * @ecc_buf: buffer to store ecc code
  68. *
  69. * @return: re-formatted ECC value
  70. */
  71. static uint32_t gen_true_ecc(uint8_t *ecc_buf)
  72. {
  73. return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
  74. ((ecc_buf[2] & 0x0F) << 8);
  75. }
  76. /*
  77. * omap_correct_data - Compares the ecc read from nand spare area with ECC
  78. * registers values and corrects one bit error if it has occured
  79. * Further details can be had from OMAP TRM and the following selected links:
  80. * http://en.wikipedia.org/wiki/Hamming_code
  81. * http://www.cs.utexas.edu/users/plaxton/c/337/05f/slides/ErrorCorrection-4.pdf
  82. *
  83. * @mtd: MTD device structure
  84. * @dat: page data
  85. * @read_ecc: ecc read from nand flash
  86. * @calc_ecc: ecc read from ECC registers
  87. *
  88. * @return 0 if data is OK or corrected, else returns -1
  89. */
  90. static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
  91. uint8_t *read_ecc, uint8_t *calc_ecc)
  92. {
  93. uint32_t orig_ecc, new_ecc, res, hm;
  94. uint16_t parity_bits, byte;
  95. uint8_t bit;
  96. /* Regenerate the orginal ECC */
  97. orig_ecc = gen_true_ecc(read_ecc);
  98. new_ecc = gen_true_ecc(calc_ecc);
  99. /* Get the XOR of real ecc */
  100. res = orig_ecc ^ new_ecc;
  101. if (res) {
  102. /* Get the hamming width */
  103. hm = hweight32(res);
  104. /* Single bit errors can be corrected! */
  105. if (hm == 12) {
  106. /* Correctable data! */
  107. parity_bits = res >> 16;
  108. bit = (parity_bits & 0x7);
  109. byte = (parity_bits >> 3) & 0x1FF;
  110. /* Flip the bit to correct */
  111. dat[byte] ^= (0x1 << bit);
  112. } else if (hm == 1) {
  113. printf("Error: Ecc is wrong\n");
  114. /* ECC itself is corrupted */
  115. return 2;
  116. } else {
  117. /*
  118. * hm distance != parity pairs OR one, could mean 2 bit
  119. * error OR potentially be on a blank page..
  120. * orig_ecc: contains spare area data from nand flash.
  121. * new_ecc: generated ecc while reading data area.
  122. * Note: if the ecc = 0, all data bits from which it was
  123. * generated are 0xFF.
  124. * The 3 byte(24 bits) ecc is generated per 512byte
  125. * chunk of a page. If orig_ecc(from spare area)
  126. * is 0xFF && new_ecc(computed now from data area)=0x0,
  127. * this means that data area is 0xFF and spare area is
  128. * 0xFF. A sure sign of a erased page!
  129. */
  130. if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
  131. return 0;
  132. printf("Error: Bad compare! failed\n");
  133. /* detected 2 bit error */
  134. return -1;
  135. }
  136. }
  137. return 0;
  138. }
  139. /*
  140. * Generic BCH interface
  141. */
  142. struct nand_bch_priv {
  143. uint8_t mode;
  144. uint8_t type;
  145. uint8_t nibbles;
  146. struct bch_control *control;
  147. enum omap_ecc ecc_scheme;
  148. };
  149. /* bch types */
  150. #define ECC_BCH4 0
  151. #define ECC_BCH8 1
  152. #define ECC_BCH16 2
  153. /* BCH nibbles for diff bch levels */
  154. #define ECC_BCH4_NIBBLES 13
  155. #define ECC_BCH8_NIBBLES 26
  156. #define ECC_BCH16_NIBBLES 52
  157. /*
  158. * This can be a single instance cause all current users have only one NAND
  159. * with nearly the same setup (BCH8, some with ELM and others with sw BCH
  160. * library).
  161. * When some users with other BCH strength will exists this have to change!
  162. */
  163. static __maybe_unused struct nand_bch_priv bch_priv = {
  164. .type = ECC_BCH8,
  165. .nibbles = ECC_BCH8_NIBBLES,
  166. .control = NULL
  167. };
  168. /*
  169. * omap_reverse_list - re-orders list elements in reverse order [internal]
  170. * @list: pointer to start of list
  171. * @length: length of list
  172. */
  173. void omap_reverse_list(u8 *list, unsigned int length)
  174. {
  175. unsigned int i, j;
  176. unsigned int half_length = length / 2;
  177. u8 tmp;
  178. for (i = 0, j = length - 1; i < half_length; i++, j--) {
  179. tmp = list[i];
  180. list[i] = list[j];
  181. list[j] = tmp;
  182. }
  183. }
  184. /*
  185. * omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
  186. * @mtd: MTD device structure
  187. * @mode: Read/Write mode
  188. */
  189. __maybe_unused
  190. static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
  191. {
  192. struct nand_chip *nand = mtd->priv;
  193. struct nand_bch_priv *bch = nand->priv;
  194. unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
  195. unsigned int ecc_algo = 0;
  196. unsigned int bch_type = 0;
  197. unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00;
  198. u32 ecc_size_config_val = 0;
  199. u32 ecc_config_val = 0;
  200. /* configure GPMC for specific ecc-scheme */
  201. switch (bch->ecc_scheme) {
  202. case OMAP_ECC_HAM1_CODE_SW:
  203. return;
  204. case OMAP_ECC_HAM1_CODE_HW:
  205. ecc_algo = 0x0;
  206. bch_type = 0x0;
  207. bch_wrapmode = 0x00;
  208. eccsize0 = 0xFF;
  209. eccsize1 = 0xFF;
  210. break;
  211. case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
  212. case OMAP_ECC_BCH8_CODE_HW:
  213. ecc_algo = 0x1;
  214. bch_type = 0x1;
  215. if (mode == NAND_ECC_WRITE) {
  216. bch_wrapmode = 0x01;
  217. eccsize0 = 0; /* extra bits in nibbles per sector */
  218. eccsize1 = 28; /* OOB bits in nibbles per sector */
  219. } else {
  220. bch_wrapmode = 0x01;
  221. eccsize0 = 26; /* ECC bits in nibbles per sector */
  222. eccsize1 = 2; /* non-ECC bits in nibbles per sector */
  223. }
  224. break;
  225. default:
  226. return;
  227. }
  228. /* Clear ecc and enable bits */
  229. writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
  230. /* Configure ecc size for BCH */
  231. ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12);
  232. writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config);
  233. /* Configure device details for BCH engine */
  234. ecc_config_val = ((ecc_algo << 16) | /* HAM1 | BCHx */
  235. (bch_type << 12) | /* BCH4/BCH8/BCH16 */
  236. (bch_wrapmode << 8) | /* wrap mode */
  237. (dev_width << 7) | /* bus width */
  238. (0x0 << 4) | /* number of sectors */
  239. (cs << 1) | /* ECC CS */
  240. (0x1)); /* enable ECC */
  241. writel(ecc_config_val, &gpmc_cfg->ecc_config);
  242. }
  243. /*
  244. * omap_calculate_ecc - Read ECC result
  245. * @mtd: MTD structure
  246. * @dat: unused
  247. * @ecc_code: ecc_code buffer
  248. * Using noninverted ECC can be considered ugly since writing a blank
  249. * page ie. padding will clear the ECC bytes. This is no problem as
  250. * long nobody is trying to write data on the seemingly unused page.
  251. * Reading an erased page will produce an ECC mismatch between
  252. * generated and read ECC bytes that has to be dealt with separately.
  253. * E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
  254. * is used, the result of read will be 0x0 while the ECC offsets of the
  255. * spare area will be 0xFF which will result in an ECC mismatch.
  256. */
  257. static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
  258. uint8_t *ecc_code)
  259. {
  260. struct nand_chip *chip = mtd->priv;
  261. struct nand_bch_priv *bch = chip->priv;
  262. uint32_t *ptr, val = 0;
  263. int8_t i = 0, j;
  264. switch (bch->ecc_scheme) {
  265. case OMAP_ECC_HAM1_CODE_HW:
  266. val = readl(&gpmc_cfg->ecc1_result);
  267. ecc_code[0] = val & 0xFF;
  268. ecc_code[1] = (val >> 16) & 0xFF;
  269. ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
  270. break;
  271. #ifdef CONFIG_BCH
  272. case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
  273. #endif
  274. case OMAP_ECC_BCH8_CODE_HW:
  275. ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
  276. val = readl(ptr);
  277. ecc_code[i++] = (val >> 0) & 0xFF;
  278. ptr--;
  279. for (j = 0; j < 3; j++) {
  280. val = readl(ptr);
  281. ecc_code[i++] = (val >> 24) & 0xFF;
  282. ecc_code[i++] = (val >> 16) & 0xFF;
  283. ecc_code[i++] = (val >> 8) & 0xFF;
  284. ecc_code[i++] = (val >> 0) & 0xFF;
  285. ptr--;
  286. }
  287. break;
  288. default:
  289. return -EINVAL;
  290. }
  291. /* ECC scheme specific syndrome customizations */
  292. switch (bch->ecc_scheme) {
  293. case OMAP_ECC_HAM1_CODE_HW:
  294. break;
  295. #ifdef CONFIG_BCH
  296. case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
  297. for (i = 0; i < chip->ecc.bytes; i++)
  298. *(ecc_code + i) = *(ecc_code + i) ^
  299. bch8_polynomial[i];
  300. break;
  301. #endif
  302. case OMAP_ECC_BCH8_CODE_HW:
  303. ecc_code[chip->ecc.bytes - 1] = 0x00;
  304. break;
  305. default:
  306. return -EINVAL;
  307. }
  308. return 0;
  309. }
  310. #ifdef CONFIG_NAND_OMAP_ELM
  311. /*
  312. * omap_correct_data_bch - Compares the ecc read from nand spare area
  313. * with ECC registers values and corrects one bit error if it has occured
  314. *
  315. * @mtd: MTD device structure
  316. * @dat: page data
  317. * @read_ecc: ecc read from nand flash (ignored)
  318. * @calc_ecc: ecc read from ECC registers
  319. *
  320. * @return 0 if data is OK or corrected, else returns -1
  321. */
  322. static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
  323. uint8_t *read_ecc, uint8_t *calc_ecc)
  324. {
  325. struct nand_chip *chip = mtd->priv;
  326. struct nand_bch_priv *bch = chip->priv;
  327. uint32_t eccbytes = chip->ecc.bytes;
  328. uint32_t error_count = 0, error_max;
  329. uint32_t error_loc[8];
  330. uint32_t i, ecc_flag = 0;
  331. uint8_t count, err = 0;
  332. uint32_t byte_pos, bit_pos;
  333. /* check calculated ecc */
  334. for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++) {
  335. if (calc_ecc[i] != 0x00)
  336. ecc_flag = 1;
  337. }
  338. if (!ecc_flag)
  339. return 0;
  340. /* check for whether its a erased-page */
  341. ecc_flag = 0;
  342. for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++) {
  343. if (read_ecc[i] != 0xff)
  344. ecc_flag = 1;
  345. }
  346. if (!ecc_flag)
  347. return 0;
  348. /*
  349. * while reading ECC result we read it in big endian.
  350. * Hence while loading to ELM we have rotate to get the right endian.
  351. */
  352. switch (bch->ecc_scheme) {
  353. case OMAP_ECC_BCH8_CODE_HW:
  354. omap_reverse_list(calc_ecc, eccbytes - 1);
  355. break;
  356. default:
  357. return -EINVAL;
  358. }
  359. /* use elm module to check for errors */
  360. elm_config((enum bch_level)(bch->type));
  361. if (elm_check_error(calc_ecc, bch->nibbles, &error_count, error_loc)) {
  362. printf("nand: error: uncorrectable ECC errors\n");
  363. return -EINVAL;
  364. }
  365. /* correct bch error */
  366. for (count = 0; count < error_count; count++) {
  367. switch (bch->type) {
  368. case ECC_BCH8:
  369. /* 14th byte in ECC is reserved to match ROM layout */
  370. error_max = SECTOR_BYTES + (eccbytes - 1);
  371. break;
  372. default:
  373. return -EINVAL;
  374. }
  375. byte_pos = error_max - (error_loc[count] / 8) - 1;
  376. bit_pos = error_loc[count] % 8;
  377. if (byte_pos < SECTOR_BYTES) {
  378. dat[byte_pos] ^= 1 << bit_pos;
  379. printf("nand: bit-flip corrected @data=%d\n", byte_pos);
  380. } else if (byte_pos < error_max) {
  381. read_ecc[byte_pos - SECTOR_BYTES] = 1 << bit_pos;
  382. printf("nand: bit-flip corrected @oob=%d\n", byte_pos -
  383. SECTOR_BYTES);
  384. } else {
  385. err = -EBADMSG;
  386. printf("nand: error: invalid bit-flip location\n");
  387. }
  388. }
  389. return (err) ? err : error_count;
  390. }
  391. /**
  392. * omap_read_page_bch - hardware ecc based page read function
  393. * @mtd: mtd info structure
  394. * @chip: nand chip info structure
  395. * @buf: buffer to store read data
  396. * @oob_required: caller expects OOB data read to chip->oob_poi
  397. * @page: page number to read
  398. *
  399. */
  400. static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
  401. uint8_t *buf, int oob_required, int page)
  402. {
  403. int i, eccsize = chip->ecc.size;
  404. int eccbytes = chip->ecc.bytes;
  405. int eccsteps = chip->ecc.steps;
  406. uint8_t *p = buf;
  407. uint8_t *ecc_calc = chip->buffers->ecccalc;
  408. uint8_t *ecc_code = chip->buffers->ecccode;
  409. uint32_t *eccpos = chip->ecc.layout->eccpos;
  410. uint8_t *oob = chip->oob_poi;
  411. uint32_t data_pos;
  412. uint32_t oob_pos;
  413. data_pos = 0;
  414. /* oob area start */
  415. oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
  416. oob += chip->ecc.layout->eccpos[0];
  417. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
  418. oob += eccbytes) {
  419. chip->ecc.hwctl(mtd, NAND_ECC_READ);
  420. /* read data */
  421. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
  422. chip->read_buf(mtd, p, eccsize);
  423. /* read respective ecc from oob area */
  424. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
  425. chip->read_buf(mtd, oob, eccbytes);
  426. /* read syndrome */
  427. chip->ecc.calculate(mtd, p, &ecc_calc[i]);
  428. data_pos += eccsize;
  429. oob_pos += eccbytes;
  430. }
  431. for (i = 0; i < chip->ecc.total; i++)
  432. ecc_code[i] = chip->oob_poi[eccpos[i]];
  433. eccsteps = chip->ecc.steps;
  434. p = buf;
  435. for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  436. int stat;
  437. stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
  438. if (stat < 0)
  439. mtd->ecc_stats.failed++;
  440. else
  441. mtd->ecc_stats.corrected += stat;
  442. }
  443. return 0;
  444. }
  445. #endif /* CONFIG_NAND_OMAP_ELM */
  446. /*
  447. * OMAP3 BCH8 support (with BCH library)
  448. */
  449. #ifdef CONFIG_BCH
  450. /**
  451. * omap_correct_data_bch_sw - Decode received data and correct errors
  452. * @mtd: MTD device structure
  453. * @data: page data
  454. * @read_ecc: ecc read from nand flash
  455. * @calc_ecc: ecc read from HW ECC registers
  456. */
  457. static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
  458. u_char *read_ecc, u_char *calc_ecc)
  459. {
  460. int i, count;
  461. /* cannot correct more than 8 errors */
  462. unsigned int errloc[8];
  463. struct nand_chip *chip = mtd->priv;
  464. struct nand_bch_priv *chip_priv = chip->priv;
  465. struct bch_control *bch = chip_priv->control;
  466. count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
  467. if (count > 0) {
  468. /* correct errors */
  469. for (i = 0; i < count; i++) {
  470. /* correct data only, not ecc bytes */
  471. if (errloc[i] < 8*512)
  472. data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
  473. printf("corrected bitflip %u\n", errloc[i]);
  474. #ifdef DEBUG
  475. puts("read_ecc: ");
  476. /*
  477. * BCH8 have 13 bytes of ECC; BCH4 needs adoption
  478. * here!
  479. */
  480. for (i = 0; i < 13; i++)
  481. printf("%02x ", read_ecc[i]);
  482. puts("\n");
  483. puts("calc_ecc: ");
  484. for (i = 0; i < 13; i++)
  485. printf("%02x ", calc_ecc[i]);
  486. puts("\n");
  487. #endif
  488. }
  489. } else if (count < 0) {
  490. puts("ecc unrecoverable error\n");
  491. }
  492. return count;
  493. }
  494. /**
  495. * omap_free_bch - Release BCH ecc resources
  496. * @mtd: MTD device structure
  497. */
  498. static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
  499. {
  500. struct nand_chip *chip = mtd->priv;
  501. struct nand_bch_priv *chip_priv = chip->priv;
  502. struct bch_control *bch = NULL;
  503. if (chip_priv)
  504. bch = chip_priv->control;
  505. if (bch) {
  506. free_bch(bch);
  507. chip_priv->control = NULL;
  508. }
  509. }
  510. #endif /* CONFIG_BCH */
  511. /**
  512. * omap_select_ecc_scheme - configures driver for particular ecc-scheme
  513. * @nand: NAND chip device structure
  514. * @ecc_scheme: ecc scheme to configure
  515. * @pagesize: number of main-area bytes per page of NAND device
  516. * @oobsize: number of OOB/spare bytes per page of NAND device
  517. */
  518. static int omap_select_ecc_scheme(struct nand_chip *nand,
  519. enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
  520. struct nand_bch_priv *bch = nand->priv;
  521. struct nand_ecclayout *ecclayout = &omap_ecclayout;
  522. int eccsteps = pagesize / SECTOR_BYTES;
  523. int i;
  524. switch (ecc_scheme) {
  525. case OMAP_ECC_HAM1_CODE_SW:
  526. debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
  527. /* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
  528. * initialized in nand_scan_tail(), so just set ecc.mode */
  529. bch_priv.control = NULL;
  530. bch_priv.type = 0;
  531. nand->ecc.mode = NAND_ECC_SOFT;
  532. nand->ecc.layout = NULL;
  533. nand->ecc.size = 0;
  534. bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW;
  535. break;
  536. case OMAP_ECC_HAM1_CODE_HW:
  537. debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
  538. /* check ecc-scheme requirements before updating ecc info */
  539. if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
  540. printf("nand: error: insufficient OOB: require=%d\n", (
  541. (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
  542. return -EINVAL;
  543. }
  544. bch_priv.control = NULL;
  545. bch_priv.type = 0;
  546. /* populate ecc specific fields */
  547. memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
  548. nand->ecc.mode = NAND_ECC_HW;
  549. nand->ecc.strength = 1;
  550. nand->ecc.size = SECTOR_BYTES;
  551. nand->ecc.bytes = 3;
  552. nand->ecc.hwctl = omap_enable_hwecc;
  553. nand->ecc.correct = omap_correct_data;
  554. nand->ecc.calculate = omap_calculate_ecc;
  555. /* define ecc-layout */
  556. ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
  557. for (i = 0; i < ecclayout->eccbytes; i++) {
  558. if (nand->options & NAND_BUSWIDTH_16)
  559. ecclayout->eccpos[i] = i + 2;
  560. else
  561. ecclayout->eccpos[i] = i + 1;
  562. }
  563. ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
  564. ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
  565. BADBLOCK_MARKER_LENGTH;
  566. bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW;
  567. break;
  568. case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
  569. #ifdef CONFIG_BCH
  570. debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
  571. /* check ecc-scheme requirements before updating ecc info */
  572. if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
  573. printf("nand: error: insufficient OOB: require=%d\n", (
  574. (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
  575. return -EINVAL;
  576. }
  577. /* check if BCH S/W library can be used for error detection */
  578. bch_priv.control = init_bch(13, 8, 0x201b);
  579. if (!bch_priv.control) {
  580. printf("nand: error: could not init_bch()\n");
  581. return -ENODEV;
  582. }
  583. bch_priv.type = ECC_BCH8;
  584. /* populate ecc specific fields */
  585. memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
  586. nand->ecc.mode = NAND_ECC_HW;
  587. nand->ecc.strength = 8;
  588. nand->ecc.size = SECTOR_BYTES;
  589. nand->ecc.bytes = 13;
  590. nand->ecc.hwctl = omap_enable_hwecc;
  591. nand->ecc.correct = omap_correct_data_bch_sw;
  592. nand->ecc.calculate = omap_calculate_ecc;
  593. /* define ecc-layout */
  594. ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
  595. ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
  596. for (i = 1; i < ecclayout->eccbytes; i++) {
  597. if (i % nand->ecc.bytes)
  598. ecclayout->eccpos[i] =
  599. ecclayout->eccpos[i - 1] + 1;
  600. else
  601. ecclayout->eccpos[i] =
  602. ecclayout->eccpos[i - 1] + 2;
  603. }
  604. ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
  605. ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
  606. BADBLOCK_MARKER_LENGTH;
  607. bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
  608. break;
  609. #else
  610. printf("nand: error: CONFIG_BCH required for ECC\n");
  611. return -EINVAL;
  612. #endif
  613. case OMAP_ECC_BCH8_CODE_HW:
  614. #ifdef CONFIG_NAND_OMAP_ELM
  615. debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
  616. /* check ecc-scheme requirements before updating ecc info */
  617. if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
  618. printf("nand: error: insufficient OOB: require=%d\n", (
  619. (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
  620. return -EINVAL;
  621. }
  622. /* intialize ELM for ECC error detection */
  623. elm_init();
  624. bch_priv.type = ECC_BCH8;
  625. /* populate ecc specific fields */
  626. memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
  627. nand->ecc.mode = NAND_ECC_HW;
  628. nand->ecc.strength = 8;
  629. nand->ecc.size = SECTOR_BYTES;
  630. nand->ecc.bytes = 14;
  631. nand->ecc.hwctl = omap_enable_hwecc;
  632. nand->ecc.correct = omap_correct_data_bch;
  633. nand->ecc.calculate = omap_calculate_ecc;
  634. nand->ecc.read_page = omap_read_page_bch;
  635. /* define ecc-layout */
  636. ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
  637. for (i = 0; i < ecclayout->eccbytes; i++)
  638. ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
  639. ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
  640. ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
  641. BADBLOCK_MARKER_LENGTH;
  642. bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW;
  643. break;
  644. #else
  645. printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
  646. return -EINVAL;
  647. #endif
  648. default:
  649. debug("nand: error: ecc scheme not enabled or supported\n");
  650. return -EINVAL;
  651. }
  652. /* nand_scan_tail() sets ham1 sw ecc; hw ecc layout is set by driver */
  653. if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
  654. nand->ecc.layout = ecclayout;
  655. return 0;
  656. }
  657. #ifndef CONFIG_SPL_BUILD
  658. /*
  659. * omap_nand_switch_ecc - switch the ECC operation between different engines
  660. * (h/w and s/w) and different algorithms (hamming and BCHx)
  661. *
  662. * @hardware - true if one of the HW engines should be used
  663. * @eccstrength - the number of bits that could be corrected
  664. * (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
  665. */
  666. int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
  667. {
  668. struct nand_chip *nand;
  669. struct mtd_info *mtd;
  670. int err = 0;
  671. if (nand_curr_device < 0 ||
  672. nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
  673. !nand_info[nand_curr_device].name) {
  674. printf("nand: error: no NAND devices found\n");
  675. return -ENODEV;
  676. }
  677. mtd = &nand_info[nand_curr_device];
  678. nand = mtd->priv;
  679. nand->options |= NAND_OWN_BUFFERS;
  680. nand->options &= ~NAND_SUBPAGE_READ;
  681. /* Setup the ecc configurations again */
  682. if (hardware) {
  683. if (eccstrength == 1) {
  684. err = omap_select_ecc_scheme(nand,
  685. OMAP_ECC_HAM1_CODE_HW,
  686. mtd->writesize, mtd->oobsize);
  687. } else if (eccstrength == 8) {
  688. err = omap_select_ecc_scheme(nand,
  689. OMAP_ECC_BCH8_CODE_HW,
  690. mtd->writesize, mtd->oobsize);
  691. } else {
  692. printf("nand: error: unsupported ECC scheme\n");
  693. return -EINVAL;
  694. }
  695. } else {
  696. err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
  697. mtd->writesize, mtd->oobsize);
  698. }
  699. /* Update NAND handling after ECC mode switch */
  700. if (!err)
  701. err = nand_scan_tail(mtd);
  702. return err;
  703. }
  704. #endif /* CONFIG_SPL_BUILD */
  705. /*
  706. * Board-specific NAND initialization. The following members of the
  707. * argument are board-specific:
  708. * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
  709. * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
  710. * - cmd_ctrl: hardwarespecific function for accesing control-lines
  711. * - waitfunc: hardwarespecific function for accesing device ready/busy line
  712. * - ecc.hwctl: function to enable (reset) hardware ecc generator
  713. * - ecc.mode: mode of ecc, see defines
  714. * - chip_delay: chip dependent delay for transfering data from array to
  715. * read regs (tR)
  716. * - options: various chip options. They can partly be set to inform
  717. * nand_scan about special functionality. See the defines for further
  718. * explanation
  719. */
  720. int board_nand_init(struct nand_chip *nand)
  721. {
  722. int32_t gpmc_config = 0;
  723. cs = 0;
  724. int err = 0;
  725. /*
  726. * xloader/Uboot's gpmc configuration would have configured GPMC for
  727. * nand type of memory. The following logic scans and latches on to the
  728. * first CS with NAND type memory.
  729. * TBD: need to make this logic generic to handle multiple CS NAND
  730. * devices.
  731. */
  732. while (cs < GPMC_MAX_CS) {
  733. /* Check if NAND type is set */
  734. if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
  735. /* Found it!! */
  736. break;
  737. }
  738. cs++;
  739. }
  740. if (cs >= GPMC_MAX_CS) {
  741. printf("nand: error: Unable to find NAND settings in "
  742. "GPMC Configuration - quitting\n");
  743. return -ENODEV;
  744. }
  745. gpmc_config = readl(&gpmc_cfg->config);
  746. /* Disable Write protect */
  747. gpmc_config |= 0x10;
  748. writel(gpmc_config, &gpmc_cfg->config);
  749. nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
  750. nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
  751. nand->priv = &bch_priv;
  752. nand->cmd_ctrl = omap_nand_hwcontrol;
  753. nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
  754. /* If we are 16 bit dev, our gpmc config tells us that */
  755. if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
  756. nand->options |= NAND_BUSWIDTH_16;
  757. nand->chip_delay = 100;
  758. nand->ecc.layout = &omap_ecclayout;
  759. /* select ECC scheme */
  760. #if defined(CONFIG_NAND_OMAP_ECCSCHEME)
  761. err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
  762. CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
  763. #else
  764. /* pagesize and oobsize are not required to configure sw ecc-scheme */
  765. err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
  766. 0, 0);
  767. #endif
  768. if (err)
  769. return err;
  770. #ifdef CONFIG_SPL_BUILD
  771. if (nand->options & NAND_BUSWIDTH_16)
  772. nand->read_buf = nand_read_buf16;
  773. else
  774. nand->read_buf = nand_read_buf;
  775. nand->dev_ready = omap_spl_dev_ready;
  776. #endif
  777. return 0;
  778. }