nand_bcm_umi.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*****************************************************************************
  2. * Copyright 2004 - 2009 Broadcom Corporation. All rights reserved.
  3. *
  4. * Unless you and Broadcom execute a separate written software license
  5. * agreement governing use of this software, this software is licensed to you
  6. * under the terms of the GNU General Public License version 2, available at
  7. * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
  8. *
  9. * Notwithstanding the above, under no circumstances may you combine this
  10. * software in any way with any other Broadcom software provided under a
  11. * license other than the GPL, without Broadcom's express prior written
  12. * consent.
  13. *****************************************************************************/
  14. /* ---- Include Files ---------------------------------------------------- */
  15. #include <mach/reg_umi.h>
  16. #include "nand_bcm_umi.h"
  17. #ifdef BOOT0_BUILD
  18. #include <uart.h>
  19. #endif
  20. /* ---- External Variable Declarations ----------------------------------- */
  21. /* ---- External Function Prototypes ------------------------------------- */
  22. /* ---- Public Variables ------------------------------------------------- */
  23. /* ---- Private Constants and Types -------------------------------------- */
  24. /* ---- Private Function Prototypes -------------------------------------- */
  25. /* ---- Private Variables ------------------------------------------------ */
  26. /* ---- Private Functions ------------------------------------------------ */
  27. #if NAND_ECC_BCH
  28. /****************************************************************************
  29. * nand_bch_ecc_flip_bit - Routine to flip an errored bit
  30. *
  31. * PURPOSE:
  32. * This is a helper routine that flips the bit (0 -> 1 or 1 -> 0) of the
  33. * errored bit specified
  34. *
  35. * PARAMETERS:
  36. * datap - Container that holds the 512 byte data
  37. * errorLocation - Location of the bit that needs to be flipped
  38. *
  39. * RETURNS:
  40. * None
  41. ****************************************************************************/
  42. static void nand_bcm_umi_bch_ecc_flip_bit(uint8_t *datap, int errorLocation)
  43. {
  44. int locWithinAByte = (errorLocation & REG_UMI_BCH_ERR_LOC_BYTE) >> 0;
  45. int locWithinAWord = (errorLocation & REG_UMI_BCH_ERR_LOC_WORD) >> 3;
  46. int locWithinAPage = (errorLocation & REG_UMI_BCH_ERR_LOC_PAGE) >> 5;
  47. uint8_t errorByte = 0;
  48. uint8_t byteMask = 1 << locWithinAByte;
  49. /* BCH uses big endian, need to change the location
  50. * bits to little endian */
  51. locWithinAWord = 3 - locWithinAWord;
  52. errorByte = datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord];
  53. #ifdef BOOT0_BUILD
  54. puthexs("\nECC Correct Offset: ",
  55. locWithinAPage * sizeof(uint32_t) + locWithinAWord);
  56. puthexs(" errorByte:", errorByte);
  57. puthex8(" Bit: ", locWithinAByte);
  58. #endif
  59. if (errorByte & byteMask) {
  60. /* bit needs to be cleared */
  61. errorByte &= ~byteMask;
  62. } else {
  63. /* bit needs to be set */
  64. errorByte |= byteMask;
  65. }
  66. /* write back the value with the fixed bit */
  67. datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord] = errorByte;
  68. }
  69. /****************************************************************************
  70. * nand_correct_page_bch - Routine to correct bit errors when reading NAND
  71. *
  72. * PURPOSE:
  73. * This routine reads the BCH registers to determine if there are any bit
  74. * errors during the read of the last 512 bytes of data + ECC bytes. If
  75. * errors exists, the routine fixes it.
  76. *
  77. * PARAMETERS:
  78. * datap - Container that holds the 512 byte data
  79. *
  80. * RETURNS:
  81. * 0 or greater = Number of errors corrected
  82. * (No errors are found or errors have been fixed)
  83. * -1 = Error(s) cannot be fixed
  84. ****************************************************************************/
  85. int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
  86. int numEccBytes)
  87. {
  88. int numErrors;
  89. int errorLocation;
  90. int idx;
  91. uint32_t regValue;
  92. /* wait for read ECC to be valid */
  93. regValue = nand_bcm_umi_bch_poll_read_ecc_calc();
  94. /*
  95. * read the control status register to determine if there
  96. * are error'ed bits
  97. * see if errors are correctible
  98. */
  99. if ((regValue & REG_UMI_BCH_CTRL_STATUS_UNCORR_ERR) > 0) {
  100. int i;
  101. for (i = 0; i < numEccBytes; i++) {
  102. if (readEccData[i] != 0xff) {
  103. /* errors cannot be fixed, return -1 */
  104. return -1;
  105. }
  106. }
  107. /* If ECC is unprogrammed then we can't correct,
  108. * assume everything OK */
  109. return 0;
  110. }
  111. if ((regValue & REG_UMI_BCH_CTRL_STATUS_CORR_ERR) == 0) {
  112. /* no errors */
  113. return 0;
  114. }
  115. /*
  116. * Fix errored bits by doing the following:
  117. * 1. Read the number of errors in the control and status register
  118. * 2. Read the error location registers that corresponds to the number
  119. * of errors reported
  120. * 3. Invert the bit in the data
  121. */
  122. numErrors = (regValue & REG_UMI_BCH_CTRL_STATUS_NB_CORR_ERROR) >> 20;
  123. for (idx = 0; idx < numErrors; idx++) {
  124. errorLocation =
  125. REG_UMI_BCH_ERR_LOC_ADDR(idx) & REG_UMI_BCH_ERR_LOC_MASK;
  126. /* Flip bit */
  127. nand_bcm_umi_bch_ecc_flip_bit(datap, errorLocation);
  128. }
  129. /* Errors corrected */
  130. return numErrors;
  131. }
  132. #endif