pmecc.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. /*
  2. * Copyright 2017 ATMEL
  3. * Copyright 2017 Free Electrons
  4. *
  5. * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
  6. *
  7. * Derived from the atmel_nand.c driver which contained the following
  8. * copyrights:
  9. *
  10. * Copyright 2003 Rick Bronson
  11. *
  12. * Derived from drivers/mtd/nand/autcpu12.c (removed in v3.8)
  13. * Copyright 2001 Thomas Gleixner (gleixner@autronix.de)
  14. *
  15. * Derived from drivers/mtd/spia.c (removed in v3.8)
  16. * Copyright 2000 Steven J. Hill (sjhill@cotw.com)
  17. *
  18. * Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
  19. * Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright 2007
  20. *
  21. * Derived from Das U-Boot source code
  22. * (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
  23. * Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
  24. *
  25. * Add Programmable Multibit ECC support for various AT91 SoC
  26. * Copyright 2012 ATMEL, Hong Xu
  27. *
  28. * Add Nand Flash Controller support for SAMA5 SoC
  29. * Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com)
  30. *
  31. * This program is free software; you can redistribute it and/or modify
  32. * it under the terms of the GNU General Public License version 2 as
  33. * published by the Free Software Foundation.
  34. *
  35. * The PMECC is an hardware assisted BCH engine, which means part of the
  36. * ECC algorithm is left to the software. The hardware/software repartition
  37. * is explained in the "PMECC Controller Functional Description" chapter in
  38. * Atmel datasheets, and some of the functions in this file are directly
  39. * implementing the algorithms described in the "Software Implementation"
  40. * sub-section.
  41. *
  42. * TODO: it seems that the software BCH implementation in lib/bch.c is already
  43. * providing some of the logic we are implementing here. It would be smart
  44. * to expose the needed lib/bch.c helpers/functions and re-use them here.
  45. */
  46. #include <linux/genalloc.h>
  47. #include <linux/iopoll.h>
  48. #include <linux/module.h>
  49. #include <linux/mtd/rawnand.h>
  50. #include <linux/of_irq.h>
  51. #include <linux/of_platform.h>
  52. #include <linux/platform_device.h>
  53. #include <linux/slab.h>
  54. #include "pmecc.h"
  55. /* Galois field dimension */
  56. #define PMECC_GF_DIMENSION_13 13
  57. #define PMECC_GF_DIMENSION_14 14
  58. /* Primitive Polynomial used by PMECC */
  59. #define PMECC_GF_13_PRIMITIVE_POLY 0x201b
  60. #define PMECC_GF_14_PRIMITIVE_POLY 0x4443
  61. #define PMECC_LOOKUP_TABLE_SIZE_512 0x2000
  62. #define PMECC_LOOKUP_TABLE_SIZE_1024 0x4000
  63. /* Time out value for reading PMECC status register */
  64. #define PMECC_MAX_TIMEOUT_MS 100
  65. /* PMECC Register Definitions */
  66. #define ATMEL_PMECC_CFG 0x0
  67. #define PMECC_CFG_BCH_STRENGTH(x) (x)
  68. #define PMECC_CFG_BCH_STRENGTH_MASK GENMASK(2, 0)
  69. #define PMECC_CFG_SECTOR512 (0 << 4)
  70. #define PMECC_CFG_SECTOR1024 (1 << 4)
  71. #define PMECC_CFG_NSECTORS(x) ((fls(x) - 1) << 8)
  72. #define PMECC_CFG_READ_OP (0 << 12)
  73. #define PMECC_CFG_WRITE_OP (1 << 12)
  74. #define PMECC_CFG_SPARE_ENABLE BIT(16)
  75. #define PMECC_CFG_AUTO_ENABLE BIT(20)
  76. #define ATMEL_PMECC_SAREA 0x4
  77. #define ATMEL_PMECC_SADDR 0x8
  78. #define ATMEL_PMECC_EADDR 0xc
  79. #define ATMEL_PMECC_CLK 0x10
  80. #define PMECC_CLK_133MHZ (2 << 0)
  81. #define ATMEL_PMECC_CTRL 0x14
  82. #define PMECC_CTRL_RST BIT(0)
  83. #define PMECC_CTRL_DATA BIT(1)
  84. #define PMECC_CTRL_USER BIT(2)
  85. #define PMECC_CTRL_ENABLE BIT(4)
  86. #define PMECC_CTRL_DISABLE BIT(5)
  87. #define ATMEL_PMECC_SR 0x18
  88. #define PMECC_SR_BUSY BIT(0)
  89. #define PMECC_SR_ENABLE BIT(4)
  90. #define ATMEL_PMECC_IER 0x1c
  91. #define ATMEL_PMECC_IDR 0x20
  92. #define ATMEL_PMECC_IMR 0x24
  93. #define ATMEL_PMECC_ISR 0x28
  94. #define PMECC_ERROR_INT BIT(0)
  95. #define ATMEL_PMECC_ECC(sector, n) \
  96. ((((sector) + 1) * 0x40) + (n))
  97. #define ATMEL_PMECC_REM(sector, n) \
  98. ((((sector) + 1) * 0x40) + ((n) * 4) + 0x200)
  99. /* PMERRLOC Register Definitions */
  100. #define ATMEL_PMERRLOC_ELCFG 0x0
  101. #define PMERRLOC_ELCFG_SECTOR_512 (0 << 0)
  102. #define PMERRLOC_ELCFG_SECTOR_1024 (1 << 0)
  103. #define PMERRLOC_ELCFG_NUM_ERRORS(n) ((n) << 16)
  104. #define ATMEL_PMERRLOC_ELPRIM 0x4
  105. #define ATMEL_PMERRLOC_ELEN 0x8
  106. #define ATMEL_PMERRLOC_ELDIS 0xc
  107. #define PMERRLOC_DISABLE BIT(0)
  108. #define ATMEL_PMERRLOC_ELSR 0x10
  109. #define PMERRLOC_ELSR_BUSY BIT(0)
  110. #define ATMEL_PMERRLOC_ELIER 0x14
  111. #define ATMEL_PMERRLOC_ELIDR 0x18
  112. #define ATMEL_PMERRLOC_ELIMR 0x1c
  113. #define ATMEL_PMERRLOC_ELISR 0x20
  114. #define PMERRLOC_ERR_NUM_MASK GENMASK(12, 8)
  115. #define PMERRLOC_CALC_DONE BIT(0)
  116. #define ATMEL_PMERRLOC_SIGMA(x) (((x) * 0x4) + 0x28)
  117. #define ATMEL_PMERRLOC_EL(offs, x) (((x) * 0x4) + (offs))
  118. struct atmel_pmecc_gf_tables {
  119. u16 *alpha_to;
  120. u16 *index_of;
  121. };
  122. struct atmel_pmecc_caps {
  123. const int *strengths;
  124. int nstrengths;
  125. int el_offset;
  126. bool correct_erased_chunks;
  127. };
  128. struct atmel_pmecc {
  129. struct device *dev;
  130. const struct atmel_pmecc_caps *caps;
  131. struct {
  132. void __iomem *base;
  133. void __iomem *errloc;
  134. } regs;
  135. struct mutex lock;
  136. };
  137. struct atmel_pmecc_user_conf_cache {
  138. u32 cfg;
  139. u32 sarea;
  140. u32 saddr;
  141. u32 eaddr;
  142. };
  143. struct atmel_pmecc_user {
  144. struct atmel_pmecc_user_conf_cache cache;
  145. struct atmel_pmecc *pmecc;
  146. const struct atmel_pmecc_gf_tables *gf_tables;
  147. int eccbytes;
  148. s16 *partial_syn;
  149. s16 *si;
  150. s16 *lmu;
  151. s16 *smu;
  152. s32 *mu;
  153. s32 *dmu;
  154. s32 *delta;
  155. u32 isr;
  156. };
  157. static DEFINE_MUTEX(pmecc_gf_tables_lock);
  158. static const struct atmel_pmecc_gf_tables *pmecc_gf_tables_512;
  159. static const struct atmel_pmecc_gf_tables *pmecc_gf_tables_1024;
  160. static inline int deg(unsigned int poly)
  161. {
  162. /* polynomial degree is the most-significant bit index */
  163. return fls(poly) - 1;
  164. }
  165. static int atmel_pmecc_build_gf_tables(int mm, unsigned int poly,
  166. struct atmel_pmecc_gf_tables *gf_tables)
  167. {
  168. unsigned int i, x = 1;
  169. const unsigned int k = BIT(deg(poly));
  170. unsigned int nn = BIT(mm) - 1;
  171. /* primitive polynomial must be of degree m */
  172. if (k != (1u << mm))
  173. return -EINVAL;
  174. for (i = 0; i < nn; i++) {
  175. gf_tables->alpha_to[i] = x;
  176. gf_tables->index_of[x] = i;
  177. if (i && (x == 1))
  178. /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
  179. return -EINVAL;
  180. x <<= 1;
  181. if (x & k)
  182. x ^= poly;
  183. }
  184. gf_tables->alpha_to[nn] = 1;
  185. gf_tables->index_of[0] = 0;
  186. return 0;
  187. }
  188. static const struct atmel_pmecc_gf_tables *
  189. atmel_pmecc_create_gf_tables(const struct atmel_pmecc_user_req *req)
  190. {
  191. struct atmel_pmecc_gf_tables *gf_tables;
  192. unsigned int poly, degree, table_size;
  193. int ret;
  194. if (req->ecc.sectorsize == 512) {
  195. degree = PMECC_GF_DIMENSION_13;
  196. poly = PMECC_GF_13_PRIMITIVE_POLY;
  197. table_size = PMECC_LOOKUP_TABLE_SIZE_512;
  198. } else {
  199. degree = PMECC_GF_DIMENSION_14;
  200. poly = PMECC_GF_14_PRIMITIVE_POLY;
  201. table_size = PMECC_LOOKUP_TABLE_SIZE_1024;
  202. }
  203. gf_tables = kzalloc(sizeof(*gf_tables) +
  204. (2 * table_size * sizeof(u16)),
  205. GFP_KERNEL);
  206. if (!gf_tables)
  207. return ERR_PTR(-ENOMEM);
  208. gf_tables->alpha_to = (void *)(gf_tables + 1);
  209. gf_tables->index_of = gf_tables->alpha_to + table_size;
  210. ret = atmel_pmecc_build_gf_tables(degree, poly, gf_tables);
  211. if (ret) {
  212. kfree(gf_tables);
  213. return ERR_PTR(ret);
  214. }
  215. return gf_tables;
  216. }
  217. static const struct atmel_pmecc_gf_tables *
  218. atmel_pmecc_get_gf_tables(const struct atmel_pmecc_user_req *req)
  219. {
  220. const struct atmel_pmecc_gf_tables **gf_tables, *ret;
  221. mutex_lock(&pmecc_gf_tables_lock);
  222. if (req->ecc.sectorsize == 512)
  223. gf_tables = &pmecc_gf_tables_512;
  224. else
  225. gf_tables = &pmecc_gf_tables_1024;
  226. ret = *gf_tables;
  227. if (!ret) {
  228. ret = atmel_pmecc_create_gf_tables(req);
  229. if (!IS_ERR(ret))
  230. *gf_tables = ret;
  231. }
  232. mutex_unlock(&pmecc_gf_tables_lock);
  233. return ret;
  234. }
  235. static int atmel_pmecc_prepare_user_req(struct atmel_pmecc *pmecc,
  236. struct atmel_pmecc_user_req *req)
  237. {
  238. int i, max_eccbytes, eccbytes = 0, eccstrength = 0;
  239. if (req->pagesize <= 0 || req->oobsize <= 0 || req->ecc.bytes <= 0)
  240. return -EINVAL;
  241. if (req->ecc.ooboffset >= 0 &&
  242. req->ecc.ooboffset + req->ecc.bytes > req->oobsize)
  243. return -EINVAL;
  244. if (req->ecc.sectorsize == ATMEL_PMECC_SECTOR_SIZE_AUTO) {
  245. if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH)
  246. return -EINVAL;
  247. if (req->pagesize > 512)
  248. req->ecc.sectorsize = 1024;
  249. else
  250. req->ecc.sectorsize = 512;
  251. }
  252. if (req->ecc.sectorsize != 512 && req->ecc.sectorsize != 1024)
  253. return -EINVAL;
  254. if (req->pagesize % req->ecc.sectorsize)
  255. return -EINVAL;
  256. req->ecc.nsectors = req->pagesize / req->ecc.sectorsize;
  257. max_eccbytes = req->ecc.bytes;
  258. for (i = 0; i < pmecc->caps->nstrengths; i++) {
  259. int nbytes, strength = pmecc->caps->strengths[i];
  260. if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH &&
  261. strength < req->ecc.strength)
  262. continue;
  263. nbytes = DIV_ROUND_UP(strength * fls(8 * req->ecc.sectorsize),
  264. 8);
  265. nbytes *= req->ecc.nsectors;
  266. if (nbytes > max_eccbytes)
  267. break;
  268. eccstrength = strength;
  269. eccbytes = nbytes;
  270. if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH)
  271. break;
  272. }
  273. if (!eccstrength)
  274. return -EINVAL;
  275. req->ecc.bytes = eccbytes;
  276. req->ecc.strength = eccstrength;
  277. if (req->ecc.ooboffset < 0)
  278. req->ecc.ooboffset = req->oobsize - eccbytes;
  279. return 0;
  280. }
  281. struct atmel_pmecc_user *
  282. atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
  283. struct atmel_pmecc_user_req *req)
  284. {
  285. struct atmel_pmecc_user *user;
  286. const struct atmel_pmecc_gf_tables *gf_tables;
  287. int strength, size, ret;
  288. ret = atmel_pmecc_prepare_user_req(pmecc, req);
  289. if (ret)
  290. return ERR_PTR(ret);
  291. size = sizeof(*user);
  292. size = ALIGN(size, sizeof(u16));
  293. /* Reserve space for partial_syn, si and smu */
  294. size += ((2 * req->ecc.strength) + 1) * sizeof(u16) *
  295. (2 + req->ecc.strength + 2);
  296. /* Reserve space for lmu. */
  297. size += (req->ecc.strength + 1) * sizeof(u16);
  298. /* Reserve space for mu, dmu and delta. */
  299. size = ALIGN(size, sizeof(s32));
  300. size += (req->ecc.strength + 1) * sizeof(s32) * 3;
  301. user = kzalloc(size, GFP_KERNEL);
  302. if (!user)
  303. return ERR_PTR(-ENOMEM);
  304. user->pmecc = pmecc;
  305. user->partial_syn = (s16 *)PTR_ALIGN(user + 1, sizeof(u16));
  306. user->si = user->partial_syn + ((2 * req->ecc.strength) + 1);
  307. user->lmu = user->si + ((2 * req->ecc.strength) + 1);
  308. user->smu = user->lmu + (req->ecc.strength + 1);
  309. user->mu = (s32 *)PTR_ALIGN(user->smu +
  310. (((2 * req->ecc.strength) + 1) *
  311. (req->ecc.strength + 2)),
  312. sizeof(s32));
  313. user->dmu = user->mu + req->ecc.strength + 1;
  314. user->delta = user->dmu + req->ecc.strength + 1;
  315. gf_tables = atmel_pmecc_get_gf_tables(req);
  316. if (IS_ERR(gf_tables)) {
  317. kfree(user);
  318. return ERR_CAST(gf_tables);
  319. }
  320. user->gf_tables = gf_tables;
  321. user->eccbytes = req->ecc.bytes / req->ecc.nsectors;
  322. for (strength = 0; strength < pmecc->caps->nstrengths; strength++) {
  323. if (pmecc->caps->strengths[strength] == req->ecc.strength)
  324. break;
  325. }
  326. user->cache.cfg = PMECC_CFG_BCH_STRENGTH(strength) |
  327. PMECC_CFG_NSECTORS(req->ecc.nsectors);
  328. if (req->ecc.sectorsize == 1024)
  329. user->cache.cfg |= PMECC_CFG_SECTOR1024;
  330. user->cache.sarea = req->oobsize - 1;
  331. user->cache.saddr = req->ecc.ooboffset;
  332. user->cache.eaddr = req->ecc.ooboffset + req->ecc.bytes - 1;
  333. return user;
  334. }
  335. EXPORT_SYMBOL_GPL(atmel_pmecc_create_user);
  336. void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user)
  337. {
  338. kfree(user);
  339. }
  340. EXPORT_SYMBOL_GPL(atmel_pmecc_destroy_user);
  341. static int get_strength(struct atmel_pmecc_user *user)
  342. {
  343. const int *strengths = user->pmecc->caps->strengths;
  344. return strengths[user->cache.cfg & PMECC_CFG_BCH_STRENGTH_MASK];
  345. }
  346. static int get_sectorsize(struct atmel_pmecc_user *user)
  347. {
  348. return user->cache.cfg & PMECC_CFG_SECTOR1024 ? 1024 : 512;
  349. }
  350. static void atmel_pmecc_gen_syndrome(struct atmel_pmecc_user *user, int sector)
  351. {
  352. int strength = get_strength(user);
  353. u32 value;
  354. int i;
  355. /* Fill odd syndromes */
  356. for (i = 0; i < strength; i++) {
  357. value = readl_relaxed(user->pmecc->regs.base +
  358. ATMEL_PMECC_REM(sector, i / 2));
  359. if (i & 1)
  360. value >>= 16;
  361. user->partial_syn[(2 * i) + 1] = value;
  362. }
  363. }
  364. static void atmel_pmecc_substitute(struct atmel_pmecc_user *user)
  365. {
  366. int degree = get_sectorsize(user) == 512 ? 13 : 14;
  367. int cw_len = BIT(degree) - 1;
  368. int strength = get_strength(user);
  369. s16 *alpha_to = user->gf_tables->alpha_to;
  370. s16 *index_of = user->gf_tables->index_of;
  371. s16 *partial_syn = user->partial_syn;
  372. s16 *si;
  373. int i, j;
  374. /*
  375. * si[] is a table that holds the current syndrome value,
  376. * an element of that table belongs to the field
  377. */
  378. si = user->si;
  379. memset(&si[1], 0, sizeof(s16) * ((2 * strength) - 1));
  380. /* Computation 2t syndromes based on S(x) */
  381. /* Odd syndromes */
  382. for (i = 1; i < 2 * strength; i += 2) {
  383. for (j = 0; j < degree; j++) {
  384. if (partial_syn[i] & BIT(j))
  385. si[i] = alpha_to[i * j] ^ si[i];
  386. }
  387. }
  388. /* Even syndrome = (Odd syndrome) ** 2 */
  389. for (i = 2, j = 1; j <= strength; i = ++j << 1) {
  390. if (si[j] == 0) {
  391. si[i] = 0;
  392. } else {
  393. s16 tmp;
  394. tmp = index_of[si[j]];
  395. tmp = (tmp * 2) % cw_len;
  396. si[i] = alpha_to[tmp];
  397. }
  398. }
  399. }
  400. static void atmel_pmecc_get_sigma(struct atmel_pmecc_user *user)
  401. {
  402. s16 *lmu = user->lmu;
  403. s16 *si = user->si;
  404. s32 *mu = user->mu;
  405. s32 *dmu = user->dmu;
  406. s32 *delta = user->delta;
  407. int degree = get_sectorsize(user) == 512 ? 13 : 14;
  408. int cw_len = BIT(degree) - 1;
  409. int strength = get_strength(user);
  410. int num = 2 * strength + 1;
  411. s16 *index_of = user->gf_tables->index_of;
  412. s16 *alpha_to = user->gf_tables->alpha_to;
  413. int i, j, k;
  414. u32 dmu_0_count, tmp;
  415. s16 *smu = user->smu;
  416. /* index of largest delta */
  417. int ro;
  418. int largest;
  419. int diff;
  420. dmu_0_count = 0;
  421. /* First Row */
  422. /* Mu */
  423. mu[0] = -1;
  424. memset(smu, 0, sizeof(s16) * num);
  425. smu[0] = 1;
  426. /* discrepancy set to 1 */
  427. dmu[0] = 1;
  428. /* polynom order set to 0 */
  429. lmu[0] = 0;
  430. delta[0] = (mu[0] * 2 - lmu[0]) >> 1;
  431. /* Second Row */
  432. /* Mu */
  433. mu[1] = 0;
  434. /* Sigma(x) set to 1 */
  435. memset(&smu[num], 0, sizeof(s16) * num);
  436. smu[num] = 1;
  437. /* discrepancy set to S1 */
  438. dmu[1] = si[1];
  439. /* polynom order set to 0 */
  440. lmu[1] = 0;
  441. delta[1] = (mu[1] * 2 - lmu[1]) >> 1;
  442. /* Init the Sigma(x) last row */
  443. memset(&smu[(strength + 1) * num], 0, sizeof(s16) * num);
  444. for (i = 1; i <= strength; i++) {
  445. mu[i + 1] = i << 1;
  446. /* Begin Computing Sigma (Mu+1) and L(mu) */
  447. /* check if discrepancy is set to 0 */
  448. if (dmu[i] == 0) {
  449. dmu_0_count++;
  450. tmp = ((strength - (lmu[i] >> 1) - 1) / 2);
  451. if ((strength - (lmu[i] >> 1) - 1) & 0x1)
  452. tmp += 2;
  453. else
  454. tmp += 1;
  455. if (dmu_0_count == tmp) {
  456. for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
  457. smu[(strength + 1) * num + j] =
  458. smu[i * num + j];
  459. lmu[strength + 1] = lmu[i];
  460. return;
  461. }
  462. /* copy polynom */
  463. for (j = 0; j <= lmu[i] >> 1; j++)
  464. smu[(i + 1) * num + j] = smu[i * num + j];
  465. /* copy previous polynom order to the next */
  466. lmu[i + 1] = lmu[i];
  467. } else {
  468. ro = 0;
  469. largest = -1;
  470. /* find largest delta with dmu != 0 */
  471. for (j = 0; j < i; j++) {
  472. if ((dmu[j]) && (delta[j] > largest)) {
  473. largest = delta[j];
  474. ro = j;
  475. }
  476. }
  477. /* compute difference */
  478. diff = (mu[i] - mu[ro]);
  479. /* Compute degree of the new smu polynomial */
  480. if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff))
  481. lmu[i + 1] = lmu[i];
  482. else
  483. lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2;
  484. /* Init smu[i+1] with 0 */
  485. for (k = 0; k < num; k++)
  486. smu[(i + 1) * num + k] = 0;
  487. /* Compute smu[i+1] */
  488. for (k = 0; k <= lmu[ro] >> 1; k++) {
  489. s16 a, b, c;
  490. if (!(smu[ro * num + k] && dmu[i]))
  491. continue;
  492. a = index_of[dmu[i]];
  493. b = index_of[dmu[ro]];
  494. c = index_of[smu[ro * num + k]];
  495. tmp = a + (cw_len - b) + c;
  496. a = alpha_to[tmp % cw_len];
  497. smu[(i + 1) * num + (k + diff)] = a;
  498. }
  499. for (k = 0; k <= lmu[i] >> 1; k++)
  500. smu[(i + 1) * num + k] ^= smu[i * num + k];
  501. }
  502. /* End Computing Sigma (Mu+1) and L(mu) */
  503. /* In either case compute delta */
  504. delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1;
  505. /* Do not compute discrepancy for the last iteration */
  506. if (i >= strength)
  507. continue;
  508. for (k = 0; k <= (lmu[i + 1] >> 1); k++) {
  509. tmp = 2 * (i - 1);
  510. if (k == 0) {
  511. dmu[i + 1] = si[tmp + 3];
  512. } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) {
  513. s16 a, b, c;
  514. a = index_of[smu[(i + 1) * num + k]];
  515. b = si[2 * (i - 1) + 3 - k];
  516. c = index_of[b];
  517. tmp = a + c;
  518. tmp %= cw_len;
  519. dmu[i + 1] = alpha_to[tmp] ^ dmu[i + 1];
  520. }
  521. }
  522. }
  523. }
  524. static int atmel_pmecc_err_location(struct atmel_pmecc_user *user)
  525. {
  526. int sector_size = get_sectorsize(user);
  527. int degree = sector_size == 512 ? 13 : 14;
  528. struct atmel_pmecc *pmecc = user->pmecc;
  529. int strength = get_strength(user);
  530. int ret, roots_nbr, i, err_nbr = 0;
  531. int num = (2 * strength) + 1;
  532. s16 *smu = user->smu;
  533. u32 val;
  534. writel(PMERRLOC_DISABLE, pmecc->regs.errloc + ATMEL_PMERRLOC_ELDIS);
  535. for (i = 0; i <= user->lmu[strength + 1] >> 1; i++) {
  536. writel_relaxed(smu[(strength + 1) * num + i],
  537. pmecc->regs.errloc + ATMEL_PMERRLOC_SIGMA(i));
  538. err_nbr++;
  539. }
  540. val = (err_nbr - 1) << 16;
  541. if (sector_size == 1024)
  542. val |= 1;
  543. writel(val, pmecc->regs.errloc + ATMEL_PMERRLOC_ELCFG);
  544. writel((sector_size * 8) + (degree * strength),
  545. pmecc->regs.errloc + ATMEL_PMERRLOC_ELEN);
  546. ret = readl_relaxed_poll_timeout(pmecc->regs.errloc +
  547. ATMEL_PMERRLOC_ELISR,
  548. val, val & PMERRLOC_CALC_DONE, 0,
  549. PMECC_MAX_TIMEOUT_MS * 1000);
  550. if (ret) {
  551. dev_err(pmecc->dev,
  552. "PMECC: Timeout to calculate error location.\n");
  553. return ret;
  554. }
  555. roots_nbr = (val & PMERRLOC_ERR_NUM_MASK) >> 8;
  556. /* Number of roots == degree of smu hence <= cap */
  557. if (roots_nbr == user->lmu[strength + 1] >> 1)
  558. return err_nbr - 1;
  559. /*
  560. * Number of roots does not match the degree of smu
  561. * unable to correct error.
  562. */
  563. return -EBADMSG;
  564. }
  565. int atmel_pmecc_correct_sector(struct atmel_pmecc_user *user, int sector,
  566. void *data, void *ecc)
  567. {
  568. struct atmel_pmecc *pmecc = user->pmecc;
  569. int sectorsize = get_sectorsize(user);
  570. int eccbytes = user->eccbytes;
  571. int i, nerrors;
  572. if (!(user->isr & BIT(sector)))
  573. return 0;
  574. atmel_pmecc_gen_syndrome(user, sector);
  575. atmel_pmecc_substitute(user);
  576. atmel_pmecc_get_sigma(user);
  577. nerrors = atmel_pmecc_err_location(user);
  578. if (nerrors < 0)
  579. return nerrors;
  580. for (i = 0; i < nerrors; i++) {
  581. const char *area;
  582. int byte, bit;
  583. u32 errpos;
  584. u8 *ptr;
  585. errpos = readl_relaxed(pmecc->regs.errloc +
  586. ATMEL_PMERRLOC_EL(pmecc->caps->el_offset, i));
  587. errpos--;
  588. byte = errpos / 8;
  589. bit = errpos % 8;
  590. if (byte < sectorsize) {
  591. ptr = data + byte;
  592. area = "data";
  593. } else if (byte < sectorsize + eccbytes) {
  594. ptr = ecc + byte - sectorsize;
  595. area = "ECC";
  596. } else {
  597. dev_dbg(pmecc->dev,
  598. "Invalid errpos value (%d, max is %d)\n",
  599. errpos, (sectorsize + eccbytes) * 8);
  600. return -EINVAL;
  601. }
  602. dev_dbg(pmecc->dev,
  603. "Bit flip in %s area, byte %d: 0x%02x -> 0x%02x\n",
  604. area, byte, *ptr, (unsigned int)(*ptr ^ BIT(bit)));
  605. *ptr ^= BIT(bit);
  606. }
  607. return nerrors;
  608. }
  609. EXPORT_SYMBOL_GPL(atmel_pmecc_correct_sector);
  610. bool atmel_pmecc_correct_erased_chunks(struct atmel_pmecc_user *user)
  611. {
  612. return user->pmecc->caps->correct_erased_chunks;
  613. }
  614. EXPORT_SYMBOL_GPL(atmel_pmecc_correct_erased_chunks);
  615. void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
  616. int sector, void *ecc)
  617. {
  618. struct atmel_pmecc *pmecc = user->pmecc;
  619. u8 *ptr = ecc;
  620. int i;
  621. for (i = 0; i < user->eccbytes; i++)
  622. ptr[i] = readb_relaxed(pmecc->regs.base +
  623. ATMEL_PMECC_ECC(sector, i));
  624. }
  625. EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes);
  626. void atmel_pmecc_reset(struct atmel_pmecc *pmecc)
  627. {
  628. writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
  629. writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
  630. }
  631. EXPORT_SYMBOL_GPL(atmel_pmecc_reset);
  632. int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op)
  633. {
  634. struct atmel_pmecc *pmecc = user->pmecc;
  635. u32 cfg;
  636. if (op != NAND_ECC_READ && op != NAND_ECC_WRITE) {
  637. dev_err(pmecc->dev, "Bad ECC operation!");
  638. return -EINVAL;
  639. }
  640. mutex_lock(&user->pmecc->lock);
  641. cfg = user->cache.cfg;
  642. if (op == NAND_ECC_WRITE)
  643. cfg |= PMECC_CFG_WRITE_OP;
  644. else
  645. cfg |= PMECC_CFG_AUTO_ENABLE;
  646. writel(cfg, pmecc->regs.base + ATMEL_PMECC_CFG);
  647. writel(user->cache.sarea, pmecc->regs.base + ATMEL_PMECC_SAREA);
  648. writel(user->cache.saddr, pmecc->regs.base + ATMEL_PMECC_SADDR);
  649. writel(user->cache.eaddr, pmecc->regs.base + ATMEL_PMECC_EADDR);
  650. writel(PMECC_CTRL_ENABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
  651. writel(PMECC_CTRL_DATA, pmecc->regs.base + ATMEL_PMECC_CTRL);
  652. return 0;
  653. }
  654. EXPORT_SYMBOL_GPL(atmel_pmecc_enable);
  655. void atmel_pmecc_disable(struct atmel_pmecc_user *user)
  656. {
  657. atmel_pmecc_reset(user->pmecc);
  658. mutex_unlock(&user->pmecc->lock);
  659. }
  660. EXPORT_SYMBOL_GPL(atmel_pmecc_disable);
  661. int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user)
  662. {
  663. struct atmel_pmecc *pmecc = user->pmecc;
  664. u32 status;
  665. int ret;
  666. ret = readl_relaxed_poll_timeout(pmecc->regs.base +
  667. ATMEL_PMECC_SR,
  668. status, !(status & PMECC_SR_BUSY), 0,
  669. PMECC_MAX_TIMEOUT_MS * 1000);
  670. if (ret) {
  671. dev_err(pmecc->dev,
  672. "Timeout while waiting for PMECC ready.\n");
  673. return ret;
  674. }
  675. user->isr = readl_relaxed(pmecc->regs.base + ATMEL_PMECC_ISR);
  676. return 0;
  677. }
  678. EXPORT_SYMBOL_GPL(atmel_pmecc_wait_rdy);
  679. static struct atmel_pmecc *atmel_pmecc_create(struct platform_device *pdev,
  680. const struct atmel_pmecc_caps *caps,
  681. int pmecc_res_idx, int errloc_res_idx)
  682. {
  683. struct device *dev = &pdev->dev;
  684. struct atmel_pmecc *pmecc;
  685. struct resource *res;
  686. pmecc = devm_kzalloc(dev, sizeof(*pmecc), GFP_KERNEL);
  687. if (!pmecc)
  688. return ERR_PTR(-ENOMEM);
  689. pmecc->caps = caps;
  690. pmecc->dev = dev;
  691. mutex_init(&pmecc->lock);
  692. res = platform_get_resource(pdev, IORESOURCE_MEM, pmecc_res_idx);
  693. pmecc->regs.base = devm_ioremap_resource(dev, res);
  694. if (IS_ERR(pmecc->regs.base))
  695. return ERR_CAST(pmecc->regs.base);
  696. res = platform_get_resource(pdev, IORESOURCE_MEM, errloc_res_idx);
  697. pmecc->regs.errloc = devm_ioremap_resource(dev, res);
  698. if (IS_ERR(pmecc->regs.errloc))
  699. return ERR_CAST(pmecc->regs.errloc);
  700. /* Disable all interrupts before registering the PMECC handler. */
  701. writel(0xffffffff, pmecc->regs.base + ATMEL_PMECC_IDR);
  702. atmel_pmecc_reset(pmecc);
  703. return pmecc;
  704. }
  705. static void devm_atmel_pmecc_put(struct device *dev, void *res)
  706. {
  707. struct atmel_pmecc **pmecc = res;
  708. put_device((*pmecc)->dev);
  709. }
  710. static struct atmel_pmecc *atmel_pmecc_get_by_node(struct device *userdev,
  711. struct device_node *np)
  712. {
  713. struct platform_device *pdev;
  714. struct atmel_pmecc *pmecc, **ptr;
  715. pdev = of_find_device_by_node(np);
  716. if (!pdev || !platform_get_drvdata(pdev))
  717. return ERR_PTR(-EPROBE_DEFER);
  718. ptr = devres_alloc(devm_atmel_pmecc_put, sizeof(*ptr), GFP_KERNEL);
  719. if (!ptr)
  720. return ERR_PTR(-ENOMEM);
  721. get_device(&pdev->dev);
  722. pmecc = platform_get_drvdata(pdev);
  723. *ptr = pmecc;
  724. devres_add(userdev, ptr);
  725. return pmecc;
  726. }
  727. static const int atmel_pmecc_strengths[] = { 2, 4, 8, 12, 24, 32 };
  728. static struct atmel_pmecc_caps at91sam9g45_caps = {
  729. .strengths = atmel_pmecc_strengths,
  730. .nstrengths = 5,
  731. .el_offset = 0x8c,
  732. };
  733. static struct atmel_pmecc_caps sama5d4_caps = {
  734. .strengths = atmel_pmecc_strengths,
  735. .nstrengths = 5,
  736. .el_offset = 0x8c,
  737. .correct_erased_chunks = true,
  738. };
  739. static struct atmel_pmecc_caps sama5d2_caps = {
  740. .strengths = atmel_pmecc_strengths,
  741. .nstrengths = 6,
  742. .el_offset = 0xac,
  743. .correct_erased_chunks = true,
  744. };
  745. static const struct of_device_id atmel_pmecc_legacy_match[] = {
  746. { .compatible = "atmel,sama5d4-nand", &sama5d4_caps },
  747. { .compatible = "atmel,sama5d2-nand", &sama5d2_caps },
  748. { /* sentinel */ }
  749. };
  750. struct atmel_pmecc *devm_atmel_pmecc_get(struct device *userdev)
  751. {
  752. struct atmel_pmecc *pmecc;
  753. struct device_node *np;
  754. if (!userdev)
  755. return ERR_PTR(-EINVAL);
  756. if (!userdev->of_node)
  757. return NULL;
  758. np = of_parse_phandle(userdev->of_node, "ecc-engine", 0);
  759. if (np) {
  760. pmecc = atmel_pmecc_get_by_node(userdev, np);
  761. of_node_put(np);
  762. } else {
  763. /*
  764. * Support old DT bindings: in this case the PMECC iomem
  765. * resources are directly defined in the user pdev at position
  766. * 1 and 2. Extract all relevant information from there.
  767. */
  768. struct platform_device *pdev = to_platform_device(userdev);
  769. const struct atmel_pmecc_caps *caps;
  770. const struct of_device_id *match;
  771. /* No PMECC engine available. */
  772. if (!of_property_read_bool(userdev->of_node,
  773. "atmel,has-pmecc"))
  774. return NULL;
  775. caps = &at91sam9g45_caps;
  776. /* Find the caps associated to the NAND dev node. */
  777. match = of_match_node(atmel_pmecc_legacy_match,
  778. userdev->of_node);
  779. if (match && match->data)
  780. caps = match->data;
  781. pmecc = atmel_pmecc_create(pdev, caps, 1, 2);
  782. }
  783. return pmecc;
  784. }
  785. EXPORT_SYMBOL(devm_atmel_pmecc_get);
  786. static const struct of_device_id atmel_pmecc_match[] = {
  787. { .compatible = "atmel,at91sam9g45-pmecc", &at91sam9g45_caps },
  788. { .compatible = "atmel,sama5d4-pmecc", &sama5d4_caps },
  789. { .compatible = "atmel,sama5d2-pmecc", &sama5d2_caps },
  790. { /* sentinel */ }
  791. };
  792. MODULE_DEVICE_TABLE(of, atmel_pmecc_match);
  793. static int atmel_pmecc_probe(struct platform_device *pdev)
  794. {
  795. struct device *dev = &pdev->dev;
  796. const struct atmel_pmecc_caps *caps;
  797. struct atmel_pmecc *pmecc;
  798. caps = of_device_get_match_data(&pdev->dev);
  799. if (!caps) {
  800. dev_err(dev, "Invalid caps\n");
  801. return -EINVAL;
  802. }
  803. pmecc = atmel_pmecc_create(pdev, caps, 0, 1);
  804. if (IS_ERR(pmecc))
  805. return PTR_ERR(pmecc);
  806. platform_set_drvdata(pdev, pmecc);
  807. return 0;
  808. }
  809. static struct platform_driver atmel_pmecc_driver = {
  810. .driver = {
  811. .name = "atmel-pmecc",
  812. .of_match_table = of_match_ptr(atmel_pmecc_match),
  813. },
  814. .probe = atmel_pmecc_probe,
  815. };
  816. module_platform_driver(atmel_pmecc_driver);
  817. MODULE_LICENSE("GPL");
  818. MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
  819. MODULE_DESCRIPTION("PMECC engine driver");
  820. MODULE_ALIAS("platform:atmel_pmecc");