2
0

ecc.c 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. #include "hw.h"
  11. #include "flash.h"
  12. /*
  13. * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
  14. */
  15. static const uint8_t nand_ecc_precalc_table[] = {
  16. 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
  17. 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
  18. 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
  19. 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
  20. 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
  21. 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
  22. 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
  23. 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
  24. 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
  25. 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
  26. 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
  27. 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
  28. 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
  29. 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
  30. 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
  31. 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
  32. 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
  33. 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
  34. 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
  35. 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
  36. 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
  37. 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
  38. 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
  39. 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
  40. 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
  41. 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
  42. 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
  43. 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
  44. 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
  45. 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
  46. 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
  47. 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
  48. };
  49. /* Update ECC parity count. */
  50. uint8_t ecc_digest(ECCState *s, uint8_t sample)
  51. {
  52. uint8_t idx = nand_ecc_precalc_table[sample];
  53. s->cp ^= idx & 0x3f;
  54. if (idx & 0x40) {
  55. s->lp[0] ^= ~s->count;
  56. s->lp[1] ^= s->count;
  57. }
  58. s->count ++;
  59. return sample;
  60. }
  61. /* Reinitialise the counters. */
  62. void ecc_reset(ECCState *s)
  63. {
  64. s->lp[0] = 0x0000;
  65. s->lp[1] = 0x0000;
  66. s->cp = 0x00;
  67. s->count = 0;
  68. }
  69. /* Save/restore */
  70. VMStateDescription vmstate_ecc_state = {
  71. .name = "ecc-state",
  72. .version_id = 0,
  73. .minimum_version_id = 0,
  74. .minimum_version_id_old = 0,
  75. .fields = (VMStateField []) {
  76. VMSTATE_UINT8(cp, ECCState),
  77. VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
  78. VMSTATE_UINT16(count, ECCState),
  79. VMSTATE_END_OF_LIST(),
  80. },
  81. };