ice_nvm.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2018, Intel Corporation. */
  3. #include "ice_common.h"
  4. /**
  5. * ice_aq_read_nvm
  6. * @hw: pointer to the hw struct
  7. * @module_typeid: module pointer location in words from the NVM beginning
  8. * @offset: byte offset from the module beginning
  9. * @length: length of the section to be read (in bytes from the offset)
  10. * @data: command buffer (size [bytes] = length)
  11. * @last_command: tells if this is the last command in a series
  12. * @cd: pointer to command details structure or NULL
  13. *
  14. * Read the NVM using the admin queue commands (0x0701)
  15. */
  16. static enum ice_status
  17. ice_aq_read_nvm(struct ice_hw *hw, u8 module_typeid, u32 offset, u16 length,
  18. void *data, bool last_command, struct ice_sq_cd *cd)
  19. {
  20. struct ice_aq_desc desc;
  21. struct ice_aqc_nvm *cmd;
  22. cmd = &desc.params.nvm;
  23. /* In offset the highest byte must be zeroed. */
  24. if (offset & 0xFF000000)
  25. return ICE_ERR_PARAM;
  26. ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_read);
  27. /* If this is the last command in a series, set the proper flag. */
  28. if (last_command)
  29. cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD;
  30. cmd->module_typeid = module_typeid;
  31. cmd->offset = cpu_to_le32(offset);
  32. cmd->length = cpu_to_le16(length);
  33. return ice_aq_send_cmd(hw, &desc, data, length, cd);
  34. }
  35. /**
  36. * ice_check_sr_access_params - verify params for Shadow RAM R/W operations.
  37. * @hw: pointer to the HW structure
  38. * @offset: offset in words from module start
  39. * @words: number of words to access
  40. */
  41. static enum ice_status
  42. ice_check_sr_access_params(struct ice_hw *hw, u32 offset, u16 words)
  43. {
  44. if ((offset + words) > hw->nvm.sr_words) {
  45. ice_debug(hw, ICE_DBG_NVM,
  46. "NVM error: offset beyond SR lmt.\n");
  47. return ICE_ERR_PARAM;
  48. }
  49. if (words > ICE_SR_SECTOR_SIZE_IN_WORDS) {
  50. /* We can access only up to 4KB (one sector), in one AQ write */
  51. ice_debug(hw, ICE_DBG_NVM,
  52. "NVM error: tried to access %d words, limit is %d.\n",
  53. words, ICE_SR_SECTOR_SIZE_IN_WORDS);
  54. return ICE_ERR_PARAM;
  55. }
  56. if (((offset + (words - 1)) / ICE_SR_SECTOR_SIZE_IN_WORDS) !=
  57. (offset / ICE_SR_SECTOR_SIZE_IN_WORDS)) {
  58. /* A single access cannot spread over two sectors */
  59. ice_debug(hw, ICE_DBG_NVM,
  60. "NVM error: cannot spread over two sectors.\n");
  61. return ICE_ERR_PARAM;
  62. }
  63. return 0;
  64. }
  65. /**
  66. * ice_read_sr_aq - Read Shadow RAM.
  67. * @hw: pointer to the HW structure
  68. * @offset: offset in words from module start
  69. * @words: number of words to read
  70. * @data: buffer for words reads from Shadow RAM
  71. * @last_command: tells the AdminQ that this is the last command
  72. *
  73. * Reads 16-bit word buffers from the Shadow RAM using the admin command.
  74. */
  75. static enum ice_status
  76. ice_read_sr_aq(struct ice_hw *hw, u32 offset, u16 words, u16 *data,
  77. bool last_command)
  78. {
  79. enum ice_status status;
  80. status = ice_check_sr_access_params(hw, offset, words);
  81. /* values in "offset" and "words" parameters are sized as words
  82. * (16 bits) but ice_aq_read_nvm expects these values in bytes.
  83. * So do this conversion while calling ice_aq_read_nvm.
  84. */
  85. if (!status)
  86. status = ice_aq_read_nvm(hw, 0, 2 * offset, 2 * words, data,
  87. last_command, NULL);
  88. return status;
  89. }
  90. /**
  91. * ice_read_sr_word_aq - Reads Shadow RAM via AQ
  92. * @hw: pointer to the HW structure
  93. * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
  94. * @data: word read from the Shadow RAM
  95. *
  96. * Reads one 16 bit word from the Shadow RAM using the ice_read_sr_aq method.
  97. */
  98. static enum ice_status
  99. ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data)
  100. {
  101. enum ice_status status;
  102. status = ice_read_sr_aq(hw, offset, 1, data, true);
  103. if (!status)
  104. *data = le16_to_cpu(*(__le16 *)data);
  105. return status;
  106. }
  107. /**
  108. * ice_acquire_nvm - Generic request for acquiring the NVM ownership
  109. * @hw: pointer to the HW structure
  110. * @access: NVM access type (read or write)
  111. *
  112. * This function will request NVM ownership.
  113. */
  114. static enum
  115. ice_status ice_acquire_nvm(struct ice_hw *hw,
  116. enum ice_aq_res_access_type access)
  117. {
  118. if (hw->nvm.blank_nvm_mode)
  119. return 0;
  120. return ice_acquire_res(hw, ICE_NVM_RES_ID, access);
  121. }
  122. /**
  123. * ice_release_nvm - Generic request for releasing the NVM ownership
  124. * @hw: pointer to the HW structure
  125. *
  126. * This function will release NVM ownership.
  127. */
  128. static void ice_release_nvm(struct ice_hw *hw)
  129. {
  130. if (hw->nvm.blank_nvm_mode)
  131. return;
  132. ice_release_res(hw, ICE_NVM_RES_ID);
  133. }
  134. /**
  135. * ice_read_sr_word - Reads Shadow RAM word and acquire NVM if necessary
  136. * @hw: pointer to the HW structure
  137. * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
  138. * @data: word read from the Shadow RAM
  139. *
  140. * Reads one 16 bit word from the Shadow RAM using the ice_read_sr_word_aq.
  141. */
  142. static enum ice_status
  143. ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data)
  144. {
  145. enum ice_status status;
  146. status = ice_acquire_nvm(hw, ICE_RES_READ);
  147. if (!status) {
  148. status = ice_read_sr_word_aq(hw, offset, data);
  149. ice_release_nvm(hw);
  150. }
  151. return status;
  152. }
  153. /**
  154. * ice_init_nvm - initializes NVM setting
  155. * @hw: pointer to the hw struct
  156. *
  157. * This function reads and populates NVM settings such as Shadow RAM size,
  158. * max_timeout, and blank_nvm_mode
  159. */
  160. enum ice_status ice_init_nvm(struct ice_hw *hw)
  161. {
  162. struct ice_nvm_info *nvm = &hw->nvm;
  163. u16 eetrack_lo, eetrack_hi;
  164. enum ice_status status = 0;
  165. u32 fla, gens_stat;
  166. u8 sr_size;
  167. /* The SR size is stored regardless of the nvm programming mode
  168. * as the blank mode may be used in the factory line.
  169. */
  170. gens_stat = rd32(hw, GLNVM_GENS);
  171. sr_size = (gens_stat & GLNVM_GENS_SR_SIZE_M) >> GLNVM_GENS_SR_SIZE_S;
  172. /* Switching to words (sr_size contains power of 2) */
  173. nvm->sr_words = BIT(sr_size) * ICE_SR_WORDS_IN_1KB;
  174. /* Check if we are in the normal or blank NVM programming mode */
  175. fla = rd32(hw, GLNVM_FLA);
  176. if (fla & GLNVM_FLA_LOCKED_M) { /* Normal programming mode */
  177. nvm->blank_nvm_mode = false;
  178. } else { /* Blank programming mode */
  179. nvm->blank_nvm_mode = true;
  180. status = ICE_ERR_NVM_BLANK_MODE;
  181. ice_debug(hw, ICE_DBG_NVM,
  182. "NVM init error: unsupported blank mode.\n");
  183. return status;
  184. }
  185. status = ice_read_sr_word(hw, ICE_SR_NVM_DEV_STARTER_VER, &hw->nvm.ver);
  186. if (status) {
  187. ice_debug(hw, ICE_DBG_INIT,
  188. "Failed to read DEV starter version.\n");
  189. return status;
  190. }
  191. status = ice_read_sr_word(hw, ICE_SR_NVM_EETRACK_LO, &eetrack_lo);
  192. if (status) {
  193. ice_debug(hw, ICE_DBG_INIT, "Failed to read EETRACK lo.\n");
  194. return status;
  195. }
  196. status = ice_read_sr_word(hw, ICE_SR_NVM_EETRACK_HI, &eetrack_hi);
  197. if (status) {
  198. ice_debug(hw, ICE_DBG_INIT, "Failed to read EETRACK hi.\n");
  199. return status;
  200. }
  201. hw->nvm.eetrack = (eetrack_hi << 16) | eetrack_lo;
  202. return status;
  203. }