igc_nvm.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2018 Intel Corporation */
  3. #include "igc_mac.h"
  4. #include "igc_nvm.h"
  5. /**
  6. * igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion
  7. * @hw: pointer to the HW structure
  8. * @ee_reg: EEPROM flag for polling
  9. *
  10. * Polls the EEPROM status bit for either read or write completion based
  11. * upon the value of 'ee_reg'.
  12. */
  13. static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
  14. {
  15. s32 ret_val = -IGC_ERR_NVM;
  16. u32 attempts = 100000;
  17. u32 i, reg = 0;
  18. for (i = 0; i < attempts; i++) {
  19. if (ee_reg == IGC_NVM_POLL_READ)
  20. reg = rd32(IGC_EERD);
  21. else
  22. reg = rd32(IGC_EEWR);
  23. if (reg & IGC_NVM_RW_REG_DONE) {
  24. ret_val = 0;
  25. break;
  26. }
  27. udelay(5);
  28. }
  29. return ret_val;
  30. }
  31. /**
  32. * igc_acquire_nvm - Generic request for access to EEPROM
  33. * @hw: pointer to the HW structure
  34. *
  35. * Set the EEPROM access request bit and wait for EEPROM access grant bit.
  36. * Return successful if access grant bit set, else clear the request for
  37. * EEPROM access and return -IGC_ERR_NVM (-1).
  38. */
  39. s32 igc_acquire_nvm(struct igc_hw *hw)
  40. {
  41. s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
  42. u32 eecd = rd32(IGC_EECD);
  43. s32 ret_val = 0;
  44. wr32(IGC_EECD, eecd | IGC_EECD_REQ);
  45. eecd = rd32(IGC_EECD);
  46. while (timeout) {
  47. if (eecd & IGC_EECD_GNT)
  48. break;
  49. udelay(5);
  50. eecd = rd32(IGC_EECD);
  51. timeout--;
  52. }
  53. if (!timeout) {
  54. eecd &= ~IGC_EECD_REQ;
  55. wr32(IGC_EECD, eecd);
  56. hw_dbg("Could not acquire NVM grant\n");
  57. ret_val = -IGC_ERR_NVM;
  58. }
  59. return ret_val;
  60. }
  61. /**
  62. * igc_release_nvm - Release exclusive access to EEPROM
  63. * @hw: pointer to the HW structure
  64. *
  65. * Stop any current commands to the EEPROM and clear the EEPROM request bit.
  66. */
  67. void igc_release_nvm(struct igc_hw *hw)
  68. {
  69. u32 eecd;
  70. eecd = rd32(IGC_EECD);
  71. eecd &= ~IGC_EECD_REQ;
  72. wr32(IGC_EECD, eecd);
  73. }
  74. /**
  75. * igc_read_nvm_eerd - Reads EEPROM using EERD register
  76. * @hw: pointer to the HW structure
  77. * @offset: offset of word in the EEPROM to read
  78. * @words: number of words to read
  79. * @data: word read from the EEPROM
  80. *
  81. * Reads a 16 bit word from the EEPROM using the EERD register.
  82. */
  83. s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
  84. {
  85. struct igc_nvm_info *nvm = &hw->nvm;
  86. u32 i, eerd = 0;
  87. s32 ret_val = 0;
  88. /* A check for invalid values: offset too large, too many words,
  89. * and not enough words.
  90. */
  91. if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) ||
  92. words == 0) {
  93. hw_dbg("nvm parameter(s) out of bounds\n");
  94. ret_val = -IGC_ERR_NVM;
  95. goto out;
  96. }
  97. for (i = 0; i < words; i++) {
  98. eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) +
  99. IGC_NVM_RW_REG_START;
  100. wr32(IGC_EERD, eerd);
  101. ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ);
  102. if (ret_val)
  103. break;
  104. data[i] = (rd32(IGC_EERD) >> IGC_NVM_RW_REG_DATA);
  105. }
  106. out:
  107. return ret_val;
  108. }
  109. /**
  110. * igc_read_mac_addr - Read device MAC address
  111. * @hw: pointer to the HW structure
  112. */
  113. s32 igc_read_mac_addr(struct igc_hw *hw)
  114. {
  115. u32 rar_high;
  116. u32 rar_low;
  117. u16 i;
  118. rar_high = rd32(IGC_RAH(0));
  119. rar_low = rd32(IGC_RAL(0));
  120. for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++)
  121. hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8));
  122. for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++)
  123. hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8));
  124. for (i = 0; i < ETH_ALEN; i++)
  125. hw->mac.addr[i] = hw->mac.perm_addr[i];
  126. return 0;
  127. }
  128. /**
  129. * igc_validate_nvm_checksum - Validate EEPROM checksum
  130. * @hw: pointer to the HW structure
  131. *
  132. * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
  133. * and then verifies that the sum of the EEPROM is equal to 0xBABA.
  134. */
  135. s32 igc_validate_nvm_checksum(struct igc_hw *hw)
  136. {
  137. u16 checksum = 0;
  138. u16 i, nvm_data;
  139. s32 ret_val = 0;
  140. for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
  141. ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
  142. if (ret_val) {
  143. hw_dbg("NVM Read Error\n");
  144. goto out;
  145. }
  146. checksum += nvm_data;
  147. }
  148. if (checksum != (u16)NVM_SUM) {
  149. hw_dbg("NVM Checksum Invalid\n");
  150. ret_val = -IGC_ERR_NVM;
  151. goto out;
  152. }
  153. out:
  154. return ret_val;
  155. }
  156. /**
  157. * igc_update_nvm_checksum - Update EEPROM checksum
  158. * @hw: pointer to the HW structure
  159. *
  160. * Updates the EEPROM checksum by reading/adding each word of the EEPROM
  161. * up to the checksum. Then calculates the EEPROM checksum and writes the
  162. * value to the EEPROM.
  163. */
  164. s32 igc_update_nvm_checksum(struct igc_hw *hw)
  165. {
  166. u16 checksum = 0;
  167. u16 i, nvm_data;
  168. s32 ret_val;
  169. for (i = 0; i < NVM_CHECKSUM_REG; i++) {
  170. ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
  171. if (ret_val) {
  172. hw_dbg("NVM Read Error while updating checksum.\n");
  173. goto out;
  174. }
  175. checksum += nvm_data;
  176. }
  177. checksum = (u16)NVM_SUM - checksum;
  178. ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
  179. if (ret_val)
  180. hw_dbg("NVM Write Error while updating checksum.\n");
  181. out:
  182. return ret_val;
  183. }