ecc.c 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Calculate Error-correcting Codes. Used by NAND Flash controllers
  3. * (not by NAND chips).
  4. *
  5. * Copyright (c) 2006 Openedhand Ltd.
  6. * Written by Andrzej Zaborowski <balrog@zabor.org>
  7. *
  8. * This code is licensed under the GNU GPL v2.
  9. *
  10. * Contributions after 2012-01-13 are licensed under the terms of the
  11. * GNU GPL, version 2 or (at your option) any later version.
  12. */
  13. #include "hw.h"
  14. #include "flash.h"
  15. /*
  16. * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
  17. */
  18. static const uint8_t nand_ecc_precalc_table[] = {
  19. 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
  20. 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
  21. 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
  22. 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
  23. 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
  24. 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
  25. 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
  26. 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
  27. 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
  28. 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
  29. 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
  30. 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
  31. 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
  32. 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
  33. 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
  34. 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
  35. 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
  36. 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
  37. 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
  38. 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
  39. 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
  40. 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
  41. 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
  42. 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
  43. 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
  44. 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
  45. 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
  46. 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
  47. 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
  48. 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
  49. 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
  50. 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
  51. };
  52. /* Update ECC parity count. */
  53. uint8_t ecc_digest(ECCState *s, uint8_t sample)
  54. {
  55. uint8_t idx = nand_ecc_precalc_table[sample];
  56. s->cp ^= idx & 0x3f;
  57. if (idx & 0x40) {
  58. s->lp[0] ^= ~s->count;
  59. s->lp[1] ^= s->count;
  60. }
  61. s->count ++;
  62. return sample;
  63. }
  64. /* Reinitialise the counters. */
  65. void ecc_reset(ECCState *s)
  66. {
  67. s->lp[0] = 0x0000;
  68. s->lp[1] = 0x0000;
  69. s->cp = 0x00;
  70. s->count = 0;
  71. }
  72. /* Save/restore */
  73. VMStateDescription vmstate_ecc_state = {
  74. .name = "ecc-state",
  75. .version_id = 0,
  76. .minimum_version_id = 0,
  77. .minimum_version_id_old = 0,
  78. .fields = (VMStateField []) {
  79. VMSTATE_UINT8(cp, ECCState),
  80. VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
  81. VMSTATE_UINT16(count, ECCState),
  82. VMSTATE_END_OF_LIST(),
  83. },
  84. };