114-mtd-randomizer-into-nand-framework.patch 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. From 293984c7f167a08285596ef2166d8ab9cb571778 Mon Sep 17 00:00:00 2001
  2. From: Boris BREZILLON <boris.brezillon@free-electrons.com>
  3. Date: Mon, 28 Jul 2014 14:46:26 +0200
  4. Subject: [PATCH] mtd: nand: Introduce a randomizer layer in the NAND framework
  5. This patch introduce a new layer in the NAND framework to support both HW
  6. and SW randomizers.
  7. This randomization is required on some MLC/TLC NAND chips which do not
  8. support large islands of same patterns.
  9. The randomizer layer defines a nand_rnd_ctrl struct which is intended to
  10. be used by NAND core functions or NAND drivers to randomize/derandomize
  11. data stored on NAND chips.
  12. The implementation can implement any of these functions:
  13. - config: prepare a random transfer to/from the NAND chip
  14. - write_buf: randomize and write data to the NAND chip
  15. - read_buf: read and derandomize data from the NAND chip
  16. read/write_buf functions are always called after a config call.
  17. The config call specify the page, the column within the page and the action
  18. that will take place after the config (either read or write).
  19. If column is set to -1, the randomizer is disabled.
  20. If page is set to -1, we keep working on the same page.
  21. The randomizer layer provides helper functions that choose wether the
  22. randomizer or the chip read/write_buf should be used.
  23. Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
  24. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  25. ---
  26. drivers/mtd/nand/nand_base.c | 278 ++++++++++++++++++++++++++++++++++---------
  27. include/linux/mtd/nand.h | 98 +++++++++++++++
  28. 2 files changed, 321 insertions(+), 55 deletions(-)
  29. --- a/drivers/mtd/nand/nand_base.c
  30. +++ b/drivers/mtd/nand/nand_base.c
  31. @@ -1102,6 +1102,62 @@ out:
  32. EXPORT_SYMBOL(nand_lock);
  33. /**
  34. + * nand_rnd_is_activ - check wether a region of a NAND page requires NAND
  35. + * randomizer to be disabled
  36. + * @mtd: mtd info
  37. + * @page: NAND page
  38. + * @column: offset within the page
  39. + * @len: len of the region
  40. + *
  41. + * Returns 1 if the randomizer should be enabled, 0 if not, or -ERR in case of
  42. + * error.
  43. + *
  44. + * In case of success len will contain the size of the region:
  45. + * - if the requested region fits in a NAND random region len will not change
  46. + * - else len will be replaced by the available length within the NAND random
  47. + * region
  48. + */
  49. +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len)
  50. +{
  51. + struct nand_chip *chip = mtd->priv;
  52. + struct nand_rnd_layout *layout = chip->cur_rnd->layout;
  53. + struct nand_rndfree *range;
  54. + int ret = 1;
  55. + int tmp;
  56. + int i;
  57. +
  58. + if (!len || *len < 0 || column < 0 ||
  59. + column + *len > mtd->writesize + mtd->oobsize)
  60. + return -EINVAL;
  61. +
  62. + if (layout) {
  63. + for (i = 0; i < layout->nranges; i++) {
  64. + range = &layout->ranges[i];
  65. + if (column + *len <= range->offset) {
  66. + break;
  67. + } else if (column >= range->offset + range->length) {
  68. + continue;
  69. + } else if (column < range->offset) {
  70. + tmp = range->offset - column;
  71. + if (*len > tmp)
  72. + *len = tmp;
  73. + break;
  74. + } else {
  75. + tmp = range->offset + range->length - column;
  76. + if (*len > tmp)
  77. + *len = tmp;
  78. + ret = 0;
  79. + break;
  80. + }
  81. +
  82. + }
  83. + }
  84. +
  85. + return ret;
  86. +}
  87. +EXPORT_SYMBOL(nand_rnd_is_activ);
  88. +
  89. +/**
  90. * nand_page_is_empty - check wether a NAND page contains only FFs
  91. * @mtd: mtd info
  92. * @data: data buffer
  93. @@ -1246,9 +1302,14 @@ EXPORT_SYMBOL(nand_pst_create);
  94. static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
  95. uint8_t *buf, int oob_required, int page)
  96. {
  97. - chip->read_buf(mtd, buf, mtd->writesize);
  98. - if (oob_required)
  99. - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  100. + nand_rnd_config(mtd, page, 0, NAND_RND_READ);
  101. + nand_rnd_read_buf(mtd, buf, mtd->writesize);
  102. + if (oob_required) {
  103. + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
  104. + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
  105. + }
  106. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  107. +
  108. return 0;
  109. }
  110. @@ -1270,28 +1331,40 @@ static int nand_read_page_raw_syndrome(s
  111. int eccbytes = chip->cur_ecc->bytes;
  112. uint8_t *oob = chip->oob_poi;
  113. int steps, size;
  114. + int column = 0;
  115. for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
  116. - chip->read_buf(mtd, buf, eccsize);
  117. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  118. + nand_rnd_read_buf(mtd, buf, eccsize);
  119. buf += eccsize;
  120. + column += eccsize;
  121. if (chip->cur_ecc->prepad) {
  122. - chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
  123. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  124. + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->prepad);
  125. oob += chip->cur_ecc->prepad;
  126. + column += chip->cur_ecc->prepad;
  127. }
  128. - chip->read_buf(mtd, oob, eccbytes);
  129. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  130. + nand_rnd_read_buf(mtd, oob, eccbytes);
  131. oob += eccbytes;
  132. + column += eccbytes;
  133. if (chip->cur_ecc->postpad) {
  134. - chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
  135. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  136. + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->postpad);
  137. oob += chip->cur_ecc->postpad;
  138. + column += chip->cur_ecc->postpad;
  139. }
  140. }
  141. size = mtd->oobsize - (oob - chip->oob_poi);
  142. - if (size)
  143. - chip->read_buf(mtd, oob, size);
  144. + if (size) {
  145. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  146. + nand_rnd_read_buf(mtd, oob, size);
  147. + }
  148. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  149. return 0;
  150. }
  151. @@ -1380,7 +1453,8 @@ static int nand_read_subpage(struct mtd_
  152. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
  153. p = bufpoi + data_col_addr;
  154. - chip->read_buf(mtd, p, datafrag_len);
  155. + nand_rnd_config(mtd, -1, data_col_addr, NAND_RND_READ);
  156. + nand_rnd_read_buf(mtd, p, datafrag_len);
  157. /* Calculate ECC */
  158. for (i = 0; i < eccfrag_len;
  159. @@ -1399,7 +1473,8 @@ static int nand_read_subpage(struct mtd_
  160. }
  161. if (gaps) {
  162. chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
  163. - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  164. + nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_READ);
  165. + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
  166. } else {
  167. /*
  168. * Send the command to read the particular ECC bytes take care
  169. @@ -1415,7 +1490,8 @@ static int nand_read_subpage(struct mtd_
  170. chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
  171. mtd->writesize + aligned_pos, -1);
  172. - chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
  173. + nand_rnd_config(mtd, -1, mtd->writesize + aligned_pos, NAND_RND_READ);
  174. + nand_rnd_read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
  175. }
  176. for (i = 0; i < eccfrag_len; i++)
  177. @@ -1436,6 +1512,7 @@ static int nand_read_subpage(struct mtd_
  178. max_bitflips = max_t(unsigned int, max_bitflips, stat);
  179. }
  180. }
  181. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  182. return max_bitflips;
  183. }
  184. @@ -1460,13 +1537,17 @@ static int nand_read_page_hwecc(struct m
  185. uint8_t *ecc_code = chip->buffers->ecccode;
  186. uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
  187. unsigned int max_bitflips = 0;
  188. + int column = 0;
  189. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  190. chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
  191. - chip->read_buf(mtd, p, eccsize);
  192. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  193. + nand_rnd_read_buf(mtd, p, eccsize);
  194. chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
  195. + column += eccsize;
  196. }
  197. - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  198. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  199. + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
  200. for (i = 0; i < chip->cur_ecc->total; i++)
  201. ecc_code[i] = chip->oob_poi[eccpos[i]];
  202. @@ -1486,6 +1567,7 @@ static int nand_read_page_hwecc(struct m
  203. max_bitflips = max_t(unsigned int, max_bitflips, stat);
  204. }
  205. }
  206. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  207. return max_bitflips;
  208. }
  209. @@ -1514,11 +1596,14 @@ static int nand_read_page_hwecc_oob_firs
  210. uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
  211. uint8_t *ecc_calc = chip->buffers->ecccalc;
  212. unsigned int max_bitflips = 0;
  213. + int column = 0;
  214. /* Read the OOB area first */
  215. chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
  216. - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  217. + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
  218. + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
  219. chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
  220. + column = 0;
  221. for (i = 0; i < chip->cur_ecc->total; i++)
  222. ecc_code[i] = chip->oob_poi[eccpos[i]];
  223. @@ -1527,7 +1612,8 @@ static int nand_read_page_hwecc_oob_firs
  224. int stat;
  225. chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
  226. - chip->read_buf(mtd, p, eccsize);
  227. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  228. + nand_rnd_read_buf(mtd, p, eccsize);
  229. chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
  230. stat = chip->cur_ecc->correct(mtd, p, &ecc_code[i], NULL);
  231. @@ -1538,6 +1624,7 @@ static int nand_read_page_hwecc_oob_firs
  232. max_bitflips = max_t(unsigned int, max_bitflips, stat);
  233. }
  234. }
  235. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  236. return max_bitflips;
  237. }
  238. @@ -1561,20 +1648,27 @@ static int nand_read_page_syndrome(struc
  239. uint8_t *p = buf;
  240. uint8_t *oob = chip->oob_poi;
  241. unsigned int max_bitflips = 0;
  242. + int column = 0;
  243. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  244. int stat;
  245. chip->cur_ecc->hwctl(mtd, NAND_ECC_READ);
  246. - chip->read_buf(mtd, p, eccsize);
  247. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  248. + nand_rnd_read_buf(mtd, p, eccsize);
  249. + column += eccsize;
  250. if (chip->cur_ecc->prepad) {
  251. - chip->read_buf(mtd, oob, chip->cur_ecc->prepad);
  252. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  253. + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->prepad);
  254. oob += chip->cur_ecc->prepad;
  255. }
  256. chip->cur_ecc->hwctl(mtd, NAND_ECC_READSYN);
  257. - chip->read_buf(mtd, oob, eccbytes);
  258. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  259. + nand_rnd_read_buf(mtd, oob, eccbytes);
  260. + column += eccbytes;
  261. +
  262. stat = chip->cur_ecc->correct(mtd, p, oob, NULL);
  263. if (stat < 0) {
  264. @@ -1587,29 +1681,36 @@ static int nand_read_page_syndrome(struc
  265. oob += eccbytes;
  266. if (chip->cur_ecc->postpad) {
  267. - chip->read_buf(mtd, oob, chip->cur_ecc->postpad);
  268. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  269. + nand_rnd_read_buf(mtd, oob, chip->cur_ecc->postpad);
  270. + column += chip->cur_ecc->postpad;
  271. oob += chip->cur_ecc->postpad;
  272. }
  273. }
  274. /* Calculate remaining oob bytes */
  275. i = mtd->oobsize - (oob - chip->oob_poi);
  276. - if (i)
  277. - chip->read_buf(mtd, oob, i);
  278. + if (i) {
  279. + nand_rnd_config(mtd, page, column, NAND_RND_READ);
  280. + nand_rnd_read_buf(mtd, oob, i);
  281. + }
  282. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  283. return max_bitflips;
  284. }
  285. /**
  286. * nand_transfer_oob - [INTERN] Transfer oob to client buffer
  287. - * @chip: nand chip structure
  288. + * @mtd: mtd structure
  289. * @oob: oob destination address
  290. * @ops: oob ops structure
  291. * @len: size of oob to transfer
  292. */
  293. -static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
  294. +static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
  295. struct mtd_oob_ops *ops, size_t len)
  296. {
  297. + struct nand_chip *chip = mtd->priv;
  298. +
  299. switch (ops->mode) {
  300. case MTD_OPS_PLACE_OOB:
  301. @@ -1737,6 +1838,7 @@ read_retry:
  302. * Now read the page into the buffer. Absent an error,
  303. * the read methods return max bitflips per ecc step.
  304. */
  305. + nand_rnd_config(mtd, page, -1, NAND_RND_READ);
  306. if (unlikely(ops->mode == MTD_OPS_RAW))
  307. ret = chip->cur_ecc->read_page_raw(mtd, chip,
  308. bufpoi,
  309. @@ -1753,6 +1855,8 @@ read_retry:
  310. bufpoi,
  311. oob_required,
  312. page);
  313. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  314. +
  315. if (ret < 0) {
  316. if (use_bufpoi)
  317. /* Invalidate page cache */
  318. @@ -1780,8 +1884,8 @@ read_retry:
  319. int toread = min(oobreadlen, max_oobsize);
  320. if (toread) {
  321. - oob = nand_transfer_oob(chip,
  322. - oob, ops, toread);
  323. + oob = nand_transfer_oob(mtd, oob, ops,
  324. + toread);
  325. oobreadlen -= toread;
  326. }
  327. }
  328. @@ -1909,12 +2013,15 @@ static int nand_part_read(struct mtd_inf
  329. nand_get_device(part->master, FL_READING);
  330. if (part->ecc)
  331. chip->cur_ecc = part->ecc;
  332. + if (part->rnd)
  333. + chip->cur_rnd = part->rnd;
  334. ops.len = len;
  335. ops.datbuf = buf;
  336. ops.oobbuf = NULL;
  337. ops.mode = MTD_OPS_PLACE_OOB;
  338. ret = nand_do_read_ops(part->master, from, &ops);
  339. *retlen = ops.retlen;
  340. + chip->cur_rnd = &chip->rnd;
  341. chip->cur_ecc = &chip->ecc;
  342. nand_release_device(part->master);
  343. return ret;
  344. @@ -1930,7 +2037,9 @@ static int nand_read_oob_std(struct mtd_
  345. int page)
  346. {
  347. chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
  348. - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  349. + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_READ);
  350. + nand_rnd_read_buf(mtd, chip->oob_poi, mtd->oobsize);
  351. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  352. return 0;
  353. }
  354. @@ -1949,7 +2058,7 @@ static int nand_read_oob_syndrome(struct
  355. chip->cur_ecc->postpad;
  356. int eccsize = chip->cur_ecc->size;
  357. uint8_t *bufpoi = chip->oob_poi;
  358. - int i, toread, sndrnd = 0, pos;
  359. + int i, toread, sndrnd = 0, pos = eccsize;
  360. chip->cmdfunc(mtd, NAND_CMD_READ0, chip->cur_ecc->size, page);
  361. for (i = 0; i < chip->cur_ecc->steps; i++) {
  362. @@ -1962,12 +2071,17 @@ static int nand_read_oob_syndrome(struct
  363. } else
  364. sndrnd = 1;
  365. toread = min_t(int, length, chunk);
  366. - chip->read_buf(mtd, bufpoi, toread);
  367. + nand_rnd_config(mtd, page, pos, NAND_RND_READ);
  368. + nand_rnd_read_buf(mtd, bufpoi, toread);
  369. bufpoi += toread;
  370. length -= toread;
  371. }
  372. - if (length > 0)
  373. - chip->read_buf(mtd, bufpoi, length);
  374. + if (length > 0) {
  375. + pos = mtd->writesize + mtd->oobsize - length;
  376. + nand_rnd_config(mtd, page, pos, NAND_RND_READ);
  377. + nand_rnd_read_buf(mtd, bufpoi, length);
  378. + }
  379. + nand_rnd_config(mtd, -1, -1, NAND_RND_READ);
  380. return 0;
  381. }
  382. @@ -1986,7 +2100,9 @@ static int nand_write_oob_std(struct mtd
  383. int length = mtd->oobsize;
  384. chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
  385. - chip->write_buf(mtd, buf, length);
  386. + nand_rnd_config(mtd, page, mtd->writesize, NAND_RND_WRITE);
  387. + nand_rnd_write_buf(mtd, buf, length);
  388. + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
  389. /* Send command to program the OOB data */
  390. chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
  391. @@ -2042,12 +2158,18 @@ static int nand_write_oob_syndrome(struc
  392. } else
  393. sndcmd = 1;
  394. len = min_t(int, length, chunk);
  395. - chip->write_buf(mtd, bufpoi, len);
  396. + nand_rnd_config(mtd, page, pos, NAND_RND_WRITE);
  397. + nand_rnd_write_buf(mtd, bufpoi, len);
  398. bufpoi += len;
  399. length -= len;
  400. }
  401. - if (length > 0)
  402. - chip->write_buf(mtd, bufpoi, length);
  403. + if (length > 0) {
  404. + pos = mtd->writesize + mtd->oobsize - length;
  405. + nand_rnd_config(mtd, page, pos, NAND_RND_WRITE);
  406. + nand_rnd_write_buf(mtd, bufpoi, length);
  407. + }
  408. +
  409. + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
  410. chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
  411. status = chip->waitfunc(mtd, chip);
  412. @@ -2116,7 +2238,7 @@ static int nand_do_read_oob(struct mtd_i
  413. break;
  414. len = min(len, readlen);
  415. - buf = nand_transfer_oob(chip, buf, ops, len);
  416. + buf = nand_transfer_oob(mtd, buf, ops, len);
  417. if (chip->options & NAND_NEED_READRDY) {
  418. /* Apply delay or wait for ready/busy pin */
  419. @@ -2226,6 +2348,8 @@ static int nand_part_read_oob(struct mtd
  420. nand_get_device(part->master, FL_READING);
  421. if (part->ecc)
  422. chip->cur_ecc = part->ecc;
  423. + if (part->rnd)
  424. + chip->cur_rnd = part->rnd;
  425. switch (ops->mode) {
  426. case MTD_OPS_PLACE_OOB:
  427. @@ -2243,6 +2367,7 @@ static int nand_part_read_oob(struct mtd
  428. ret = nand_do_read_ops(part->master, from, ops);
  429. out:
  430. + chip->cur_rnd = &chip->rnd;
  431. chip->cur_ecc = &chip->ecc;
  432. nand_release_device(part->master);
  433. return ret;
  434. @@ -2261,9 +2386,11 @@ out:
  435. static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
  436. const uint8_t *buf, int oob_required)
  437. {
  438. - chip->write_buf(mtd, buf, mtd->writesize);
  439. - if (oob_required)
  440. - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
  441. + nand_rnd_write_buf(mtd, buf, mtd->writesize);
  442. + if (oob_required) {
  443. + nand_rnd_config(mtd, -1, mtd->writesize, NAND_RND_WRITE);
  444. + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
  445. + }
  446. return 0;
  447. }
  448. @@ -2285,28 +2412,39 @@ static int nand_write_page_raw_syndrome(
  449. int eccbytes = chip->cur_ecc->bytes;
  450. uint8_t *oob = chip->oob_poi;
  451. int steps, size;
  452. + int column = 0;
  453. for (steps = chip->cur_ecc->steps; steps > 0; steps--) {
  454. - chip->write_buf(mtd, buf, eccsize);
  455. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  456. + nand_rnd_write_buf(mtd, buf, eccsize);
  457. buf += eccsize;
  458. + column += eccsize;
  459. if (chip->cur_ecc->prepad) {
  460. - chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
  461. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  462. + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->prepad);
  463. oob += chip->cur_ecc->prepad;
  464. + column += chip->cur_ecc->prepad;
  465. }
  466. - chip->write_buf(mtd, oob, eccbytes);
  467. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  468. + nand_rnd_write_buf(mtd, oob, eccbytes);
  469. oob += eccbytes;
  470. + column += eccbytes;
  471. if (chip->cur_ecc->postpad) {
  472. - chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
  473. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  474. + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->postpad);
  475. oob += chip->cur_ecc->postpad;
  476. + column += chip->cur_ecc->postpad;
  477. }
  478. }
  479. size = mtd->oobsize - (oob - chip->oob_poi);
  480. - if (size)
  481. - chip->write_buf(mtd, oob, size);
  482. + if (size) {
  483. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  484. + nand_rnd_write_buf(mtd, oob, size);
  485. + }
  486. return 0;
  487. }
  488. @@ -2353,17 +2491,21 @@ static int nand_write_page_hwecc(struct
  489. uint8_t *ecc_calc = chip->buffers->ecccalc;
  490. const uint8_t *p = buf;
  491. uint32_t *eccpos = chip->cur_ecc->layout->eccpos;
  492. + int column = 0;
  493. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  494. chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
  495. - chip->write_buf(mtd, p, eccsize);
  496. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  497. + nand_rnd_write_buf(mtd, p, eccsize);
  498. chip->cur_ecc->calculate(mtd, p, &ecc_calc[i]);
  499. + column += eccsize;
  500. }
  501. for (i = 0; i < chip->cur_ecc->total; i++)
  502. chip->oob_poi[eccpos[i]] = ecc_calc[i];
  503. - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
  504. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  505. + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
  506. return 0;
  507. }
  508. @@ -2399,7 +2541,9 @@ static int nand_write_subpage_hwecc(stru
  509. chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
  510. /* write data (untouched subpages already masked by 0xFF) */
  511. - chip->write_buf(mtd, buf, ecc_size);
  512. + nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE);
  513. + nand_rnd_write_buf(mtd, buf, ecc_size);
  514. + offset += ecc_size;
  515. /* mask ECC of un-touched subpages by padding 0xFF */
  516. if ((step < start_step) || (step > end_step))
  517. @@ -2424,7 +2568,8 @@ static int nand_write_subpage_hwecc(stru
  518. chip->oob_poi[eccpos[i]] = ecc_calc[i];
  519. /* write OOB buffer to NAND device */
  520. - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
  521. + nand_rnd_config(mtd, -1, offset, NAND_RND_WRITE);
  522. + nand_rnd_write_buf(mtd, chip->oob_poi, mtd->oobsize);
  523. return 0;
  524. }
  525. @@ -2449,31 +2594,42 @@ static int nand_write_page_syndrome(stru
  526. int eccsteps = chip->cur_ecc->steps;
  527. const uint8_t *p = buf;
  528. uint8_t *oob = chip->oob_poi;
  529. + int column = 0;
  530. for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  531. chip->cur_ecc->hwctl(mtd, NAND_ECC_WRITE);
  532. - chip->write_buf(mtd, p, eccsize);
  533. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  534. + nand_rnd_write_buf(mtd, p, eccsize);
  535. + column += eccsize;
  536. if (chip->cur_ecc->prepad) {
  537. - chip->write_buf(mtd, oob, chip->cur_ecc->prepad);
  538. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  539. + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->prepad);
  540. oob += chip->cur_ecc->prepad;
  541. + column += chip->cur_ecc->prepad;
  542. }
  543. chip->cur_ecc->calculate(mtd, p, oob);
  544. - chip->write_buf(mtd, oob, eccbytes);
  545. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  546. + nand_rnd_write_buf(mtd, oob, eccbytes);
  547. oob += eccbytes;
  548. + column += eccbytes;
  549. if (chip->cur_ecc->postpad) {
  550. - chip->write_buf(mtd, oob, chip->cur_ecc->postpad);
  551. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  552. + nand_rnd_write_buf(mtd, oob, chip->cur_ecc->postpad);
  553. oob += chip->cur_ecc->postpad;
  554. + column += chip->cur_ecc->postpad;
  555. }
  556. }
  557. /* Calculate remaining oob bytes */
  558. i = mtd->oobsize - (oob - chip->oob_poi);
  559. - if (i)
  560. - chip->write_buf(mtd, oob, i);
  561. + if (i) {
  562. + nand_rnd_config(mtd, -1, column, NAND_RND_WRITE);
  563. + nand_rnd_write_buf(mtd, oob, i);
  564. + }
  565. return 0;
  566. }
  567. @@ -2504,6 +2660,7 @@ static int nand_write_page(struct mtd_in
  568. chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
  569. + nand_rnd_config(mtd, page, 0, NAND_RND_WRITE);
  570. if (unlikely(raw))
  571. status = chip->cur_ecc->write_page_raw(mtd, chip, buf,
  572. oob_required);
  573. @@ -2514,6 +2671,7 @@ static int nand_write_page(struct mtd_in
  574. else
  575. status = chip->cur_ecc->write_page(mtd, chip, buf,
  576. oob_required);
  577. + nand_rnd_config(mtd, -1, -1, NAND_RND_WRITE);
  578. if (status < 0)
  579. return status;
  580. @@ -2803,6 +2961,8 @@ static int panic_nand_part_write(struct
  581. panic_nand_get_device(chip, part->master, FL_WRITING);
  582. if (part->ecc)
  583. chip->cur_ecc = part->ecc;
  584. + if (part->rnd)
  585. + chip->cur_rnd = part->rnd;
  586. ops.len = len;
  587. ops.datbuf = (uint8_t *)buf;
  588. @@ -2811,6 +2971,7 @@ static int panic_nand_part_write(struct
  589. ret = nand_do_write_ops(part->master, to, &ops);
  590. + chip->cur_rnd = &chip->rnd;
  591. chip->cur_ecc = &chip->ecc;
  592. *retlen = ops.retlen;
  593. return ret;
  594. @@ -2865,12 +3026,15 @@ static int nand_part_write(struct mtd_in
  595. nand_get_device(part->master, FL_WRITING);
  596. if (part->ecc)
  597. chip->cur_ecc = part->ecc;
  598. + if (part->rnd)
  599. + chip->cur_rnd = part->rnd;
  600. ops.len = len;
  601. ops.datbuf = (uint8_t *)buf;
  602. ops.oobbuf = NULL;
  603. ops.mode = MTD_OPS_PLACE_OOB;
  604. ret = nand_do_write_ops(part->master, to, &ops);
  605. *retlen = ops.retlen;
  606. + chip->cur_rnd = &chip->rnd;
  607. chip->cur_ecc = &chip->ecc;
  608. nand_release_device(part->master);
  609. return ret;
  610. @@ -3032,6 +3196,8 @@ static int nand_part_write_oob(struct mt
  611. nand_get_device(part->master, FL_WRITING);
  612. if (part->ecc)
  613. chip->cur_ecc = part->ecc;
  614. + if (part->rnd)
  615. + chip->cur_rnd = part->rnd;
  616. switch (ops->mode) {
  617. case MTD_OPS_PLACE_OOB:
  618. @@ -3049,6 +3215,7 @@ static int nand_part_write_oob(struct mt
  619. ret = nand_do_write_ops(part->master, to, ops);
  620. out:
  621. + chip->cur_rnd = &chip->rnd;
  622. chip->cur_ecc = &chip->ecc;
  623. nand_release_device(part->master);
  624. return ret;
  625. @@ -4749,6 +4916,7 @@ int nand_scan_tail(struct mtd_info *mtd)
  626. mutex_init(&chip->part_lock);
  627. chip->cur_ecc = &chip->ecc;
  628. + chip->cur_rnd = &chip->rnd;
  629. /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
  630. if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
  631. --- a/include/linux/mtd/nand.h
  632. +++ b/include/linux/mtd/nand.h
  633. @@ -539,6 +539,64 @@ void nand_page_set_status(struct mtd_inf
  634. int nand_pst_create(struct mtd_info *mtd);
  635. +/*
  636. + * Constants for randomizer modes
  637. + */
  638. +typedef enum {
  639. + NAND_RND_NONE,
  640. + NAND_RND_SOFT,
  641. + NAND_RND_HW,
  642. +} nand_rnd_modes_t;
  643. +
  644. +/*
  645. + * Constants for randomizer actions
  646. + */
  647. +enum nand_rnd_action {
  648. + NAND_RND_NO_ACTION,
  649. + NAND_RND_READ,
  650. + NAND_RND_WRITE,
  651. +};
  652. +
  653. +/**
  654. + * struct nand_rndfree - Structure defining a NAND page region where the
  655. + * randomizer should be disabled
  656. + * @offset: range offset
  657. + * @length: range length
  658. + */
  659. +struct nand_rndfree {
  660. + u32 offset;
  661. + u32 length;
  662. +};
  663. +
  664. +/**
  665. + * struct nand_rnd_layout - Structure defining rndfree regions
  666. + * @nranges: number of ranges
  667. + * @ranges: array defining the rndfree regions
  668. + */
  669. +struct nand_rnd_layout {
  670. + int nranges;
  671. + struct nand_rndfree ranges[0];
  672. +};
  673. +
  674. +/**
  675. + * struct nand_rnd_ctrl - Randomizer Control structure
  676. + * @mode: Randomizer mode
  677. + * @config: function to prepare the randomizer (i.e.: set the appropriate
  678. + * seed/init value).
  679. + * @read_buf: function that read from the NAND and descramble the retrieved
  680. + * data.
  681. + * @write_buf: function that scramble data before writing it to the NAND.
  682. + */
  683. +struct nand_rnd_ctrl {
  684. + nand_rnd_modes_t mode;
  685. + struct nand_rnd_layout *layout;
  686. + void *priv;
  687. + int (*config)(struct mtd_info *mtd, int page, int column,
  688. + enum nand_rnd_action action);
  689. + void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
  690. + void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
  691. +};
  692. +
  693. /**
  694. * struct nand_buffers - buffer structure for read/write
  695. * @ecccalc: buffer pointer for calculated ECC, size is oobsize.
  696. @@ -731,6 +789,9 @@ struct nand_chip {
  697. struct nand_buffers *buffers;
  698. struct nand_hw_control hwcontrol;
  699. + struct nand_rnd_ctrl rnd;
  700. + struct nand_rnd_ctrl *cur_rnd;
  701. +
  702. uint8_t *bbt;
  703. struct nand_bbt_descr *bbt_td;
  704. struct nand_bbt_descr *bbt_md;
  705. @@ -752,6 +813,7 @@ struct nand_chip {
  706. * @master: MTD device representing the NAND chip
  707. * @offset: partition offset
  708. * @ecc: partition specific ECC struct
  709. + * @rnd: partition specific randomizer struct
  710. * @release: function used to release this nand_part struct
  711. *
  712. * NAND partitions work as standard MTD partitions except it can override
  713. @@ -765,6 +827,7 @@ struct nand_part {
  714. struct mtd_info *master;
  715. uint64_t offset;
  716. struct nand_ecc_ctrl *ecc;
  717. + struct nand_rnd_ctrl *rnd;
  718. void (*release)(struct nand_part *part);
  719. };
  720. @@ -902,6 +965,41 @@ extern int nand_erase_nand(struct mtd_in
  721. extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
  722. size_t *retlen, uint8_t *buf);
  723. +static inline int nand_rnd_config(struct mtd_info *mtd, int page, int column,
  724. + enum nand_rnd_action action)
  725. +{
  726. + struct nand_chip *chip = mtd->priv;
  727. +
  728. + if (chip->cur_rnd && chip->cur_rnd->config)
  729. + return chip->cur_rnd->config(mtd, page, column, action);
  730. +
  731. + return 0;
  732. +}
  733. +
  734. +static inline void nand_rnd_write_buf(struct mtd_info *mtd, const uint8_t *buf,
  735. + int len)
  736. +{
  737. + struct nand_chip *chip = mtd->priv;
  738. +
  739. + if (chip->cur_rnd && chip->cur_rnd->read_buf)
  740. + chip->cur_rnd->write_buf(mtd, buf, len);
  741. + else
  742. + chip->write_buf(mtd, buf, len);
  743. +}
  744. +
  745. +static inline void nand_rnd_read_buf(struct mtd_info *mtd, uint8_t *buf,
  746. + int len)
  747. +{
  748. + struct nand_chip *chip = mtd->priv;
  749. +
  750. + if (chip->cur_rnd && chip->cur_rnd->read_buf)
  751. + chip->cur_rnd->read_buf(mtd, buf, len);
  752. + else
  753. + chip->read_buf(mtd, buf, len);
  754. +}
  755. +
  756. +int nand_rnd_is_activ(struct mtd_info *mtd, int page, int column, int *len);
  757. +
  758. /**
  759. * struct platform_nand_chip - chip level device structure
  760. * @nr_chips: max. number of chips to scan for