igc_i225.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2018 Intel Corporation */
  3. #include <linux/delay.h>
  4. #include "igc_hw.h"
  5. /**
  6. * igc_get_hw_semaphore_i225 - Acquire hardware semaphore
  7. * @hw: pointer to the HW structure
  8. *
  9. * Acquire the necessary semaphores for exclusive access to the EEPROM.
  10. * Set the EEPROM access request bit and wait for EEPROM access grant bit.
  11. * Return successful if access grant bit set, else clear the request for
  12. * EEPROM access and return -IGC_ERR_NVM (-1).
  13. */
  14. static s32 igc_acquire_nvm_i225(struct igc_hw *hw)
  15. {
  16. return igc_acquire_swfw_sync_i225(hw, IGC_SWFW_EEP_SM);
  17. }
  18. /**
  19. * igc_release_nvm_i225 - Release exclusive access to EEPROM
  20. * @hw: pointer to the HW structure
  21. *
  22. * Stop any current commands to the EEPROM and clear the EEPROM request bit,
  23. * then release the semaphores acquired.
  24. */
  25. static void igc_release_nvm_i225(struct igc_hw *hw)
  26. {
  27. igc_release_swfw_sync_i225(hw, IGC_SWFW_EEP_SM);
  28. }
  29. /**
  30. * igc_get_hw_semaphore_i225 - Acquire hardware semaphore
  31. * @hw: pointer to the HW structure
  32. *
  33. * Acquire the HW semaphore to access the PHY or NVM
  34. */
  35. static s32 igc_get_hw_semaphore_i225(struct igc_hw *hw)
  36. {
  37. s32 timeout = hw->nvm.word_size + 1;
  38. s32 i = 0;
  39. u32 swsm;
  40. /* Get the SW semaphore */
  41. while (i < timeout) {
  42. swsm = rd32(IGC_SWSM);
  43. if (!(swsm & IGC_SWSM_SMBI))
  44. break;
  45. usleep_range(500, 600);
  46. i++;
  47. }
  48. if (i == timeout) {
  49. /* In rare circumstances, the SW semaphore may already be held
  50. * unintentionally. Clear the semaphore once before giving up.
  51. */
  52. if (hw->dev_spec._base.clear_semaphore_once) {
  53. hw->dev_spec._base.clear_semaphore_once = false;
  54. igc_put_hw_semaphore(hw);
  55. for (i = 0; i < timeout; i++) {
  56. swsm = rd32(IGC_SWSM);
  57. if (!(swsm & IGC_SWSM_SMBI))
  58. break;
  59. usleep_range(500, 600);
  60. }
  61. }
  62. /* If we do not have the semaphore here, we have to give up. */
  63. if (i == timeout) {
  64. hw_dbg("Driver can't access device - SMBI bit is set.\n");
  65. return -IGC_ERR_NVM;
  66. }
  67. }
  68. /* Get the FW semaphore. */
  69. for (i = 0; i < timeout; i++) {
  70. swsm = rd32(IGC_SWSM);
  71. wr32(IGC_SWSM, swsm | IGC_SWSM_SWESMBI);
  72. /* Semaphore acquired if bit latched */
  73. if (rd32(IGC_SWSM) & IGC_SWSM_SWESMBI)
  74. break;
  75. usleep_range(500, 600);
  76. }
  77. if (i == timeout) {
  78. /* Release semaphores */
  79. igc_put_hw_semaphore(hw);
  80. hw_dbg("Driver can't access the NVM\n");
  81. return -IGC_ERR_NVM;
  82. }
  83. return 0;
  84. }
  85. /**
  86. * igc_acquire_swfw_sync_i225 - Acquire SW/FW semaphore
  87. * @hw: pointer to the HW structure
  88. * @mask: specifies which semaphore to acquire
  89. *
  90. * Acquire the SW/FW semaphore to access the PHY or NVM. The mask
  91. * will also specify which port we're acquiring the lock for.
  92. */
  93. s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask)
  94. {
  95. s32 i = 0, timeout = 200;
  96. u32 fwmask = mask << 16;
  97. u32 swmask = mask;
  98. s32 ret_val = 0;
  99. u32 swfw_sync;
  100. while (i < timeout) {
  101. if (igc_get_hw_semaphore_i225(hw)) {
  102. ret_val = -IGC_ERR_SWFW_SYNC;
  103. goto out;
  104. }
  105. swfw_sync = rd32(IGC_SW_FW_SYNC);
  106. if (!(swfw_sync & (fwmask | swmask)))
  107. break;
  108. /* Firmware currently using resource (fwmask) */
  109. igc_put_hw_semaphore(hw);
  110. mdelay(5);
  111. i++;
  112. }
  113. if (i == timeout) {
  114. hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
  115. ret_val = -IGC_ERR_SWFW_SYNC;
  116. goto out;
  117. }
  118. swfw_sync |= swmask;
  119. wr32(IGC_SW_FW_SYNC, swfw_sync);
  120. igc_put_hw_semaphore(hw);
  121. out:
  122. return ret_val;
  123. }
  124. /**
  125. * igc_release_swfw_sync_i225 - Release SW/FW semaphore
  126. * @hw: pointer to the HW structure
  127. * @mask: specifies which semaphore to acquire
  128. *
  129. * Release the SW/FW semaphore used to access the PHY or NVM. The mask
  130. * will also specify which port we're releasing the lock for.
  131. */
  132. void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask)
  133. {
  134. u32 swfw_sync;
  135. while (igc_get_hw_semaphore_i225(hw))
  136. ; /* Empty */
  137. swfw_sync = rd32(IGC_SW_FW_SYNC);
  138. swfw_sync &= ~mask;
  139. wr32(IGC_SW_FW_SYNC, swfw_sync);
  140. igc_put_hw_semaphore(hw);
  141. }
  142. /**
  143. * igc_read_nvm_srrd_i225 - Reads Shadow Ram using EERD register
  144. * @hw: pointer to the HW structure
  145. * @offset: offset of word in the Shadow Ram to read
  146. * @words: number of words to read
  147. * @data: word read from the Shadow Ram
  148. *
  149. * Reads a 16 bit word from the Shadow Ram using the EERD register.
  150. * Uses necessary synchronization semaphores.
  151. */
  152. static s32 igc_read_nvm_srrd_i225(struct igc_hw *hw, u16 offset, u16 words,
  153. u16 *data)
  154. {
  155. s32 status = 0;
  156. u16 i, count;
  157. /* We cannot hold synchronization semaphores for too long,
  158. * because of forceful takeover procedure. However it is more efficient
  159. * to read in bursts than synchronizing access for each word.
  160. */
  161. for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) {
  162. count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ?
  163. IGC_EERD_EEWR_MAX_COUNT : (words - i);
  164. status = hw->nvm.ops.acquire(hw);
  165. if (status)
  166. break;
  167. status = igc_read_nvm_eerd(hw, offset, count, data + i);
  168. hw->nvm.ops.release(hw);
  169. if (status)
  170. break;
  171. }
  172. return status;
  173. }
  174. /**
  175. * igc_write_nvm_srwr - Write to Shadow Ram using EEWR
  176. * @hw: pointer to the HW structure
  177. * @offset: offset within the Shadow Ram to be written to
  178. * @words: number of words to write
  179. * @data: 16 bit word(s) to be written to the Shadow Ram
  180. *
  181. * Writes data to Shadow Ram at offset using EEWR register.
  182. *
  183. * If igc_update_nvm_checksum is not called after this function , the
  184. * Shadow Ram will most likely contain an invalid checksum.
  185. */
  186. static s32 igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words,
  187. u16 *data)
  188. {
  189. struct igc_nvm_info *nvm = &hw->nvm;
  190. u32 attempts = 100000;
  191. u32 i, k, eewr = 0;
  192. s32 ret_val = 0;
  193. /* A check for invalid values: offset too large, too many words,
  194. * too many words for the offset, and not enough words.
  195. */
  196. if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) ||
  197. words == 0) {
  198. hw_dbg("nvm parameter(s) out of bounds\n");
  199. ret_val = -IGC_ERR_NVM;
  200. goto out;
  201. }
  202. for (i = 0; i < words; i++) {
  203. eewr = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) |
  204. (data[i] << IGC_NVM_RW_REG_DATA) |
  205. IGC_NVM_RW_REG_START;
  206. wr32(IGC_SRWR, eewr);
  207. for (k = 0; k < attempts; k++) {
  208. if (IGC_NVM_RW_REG_DONE &
  209. rd32(IGC_SRWR)) {
  210. ret_val = 0;
  211. break;
  212. }
  213. udelay(5);
  214. }
  215. if (ret_val) {
  216. hw_dbg("Shadow RAM write EEWR timed out\n");
  217. break;
  218. }
  219. }
  220. out:
  221. return ret_val;
  222. }
  223. /**
  224. * igc_write_nvm_srwr_i225 - Write to Shadow RAM using EEWR
  225. * @hw: pointer to the HW structure
  226. * @offset: offset within the Shadow RAM to be written to
  227. * @words: number of words to write
  228. * @data: 16 bit word(s) to be written to the Shadow RAM
  229. *
  230. * Writes data to Shadow RAM at offset using EEWR register.
  231. *
  232. * If igc_update_nvm_checksum is not called after this function , the
  233. * data will not be committed to FLASH and also Shadow RAM will most likely
  234. * contain an invalid checksum.
  235. *
  236. * If error code is returned, data and Shadow RAM may be inconsistent - buffer
  237. * partially written.
  238. */
  239. static s32 igc_write_nvm_srwr_i225(struct igc_hw *hw, u16 offset, u16 words,
  240. u16 *data)
  241. {
  242. s32 status = 0;
  243. u16 i, count;
  244. /* We cannot hold synchronization semaphores for too long,
  245. * because of forceful takeover procedure. However it is more efficient
  246. * to write in bursts than synchronizing access for each word.
  247. */
  248. for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) {
  249. count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ?
  250. IGC_EERD_EEWR_MAX_COUNT : (words - i);
  251. status = hw->nvm.ops.acquire(hw);
  252. if (status)
  253. break;
  254. status = igc_write_nvm_srwr(hw, offset, count, data + i);
  255. hw->nvm.ops.release(hw);
  256. if (status)
  257. break;
  258. }
  259. return status;
  260. }
  261. /**
  262. * igc_validate_nvm_checksum_i225 - Validate EEPROM checksum
  263. * @hw: pointer to the HW structure
  264. *
  265. * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
  266. * and then verifies that the sum of the EEPROM is equal to 0xBABA.
  267. */
  268. static s32 igc_validate_nvm_checksum_i225(struct igc_hw *hw)
  269. {
  270. s32 (*read_op_ptr)(struct igc_hw *hw, u16 offset, u16 count,
  271. u16 *data);
  272. s32 status = 0;
  273. status = hw->nvm.ops.acquire(hw);
  274. if (status)
  275. goto out;
  276. /* Replace the read function with semaphore grabbing with
  277. * the one that skips this for a while.
  278. * We have semaphore taken already here.
  279. */
  280. read_op_ptr = hw->nvm.ops.read;
  281. hw->nvm.ops.read = igc_read_nvm_eerd;
  282. status = igc_validate_nvm_checksum(hw);
  283. /* Revert original read operation. */
  284. hw->nvm.ops.read = read_op_ptr;
  285. hw->nvm.ops.release(hw);
  286. out:
  287. return status;
  288. }
  289. /**
  290. * igc_pool_flash_update_done_i225 - Pool FLUDONE status
  291. * @hw: pointer to the HW structure
  292. */
  293. static s32 igc_pool_flash_update_done_i225(struct igc_hw *hw)
  294. {
  295. s32 ret_val = -IGC_ERR_NVM;
  296. u32 i, reg;
  297. for (i = 0; i < IGC_FLUDONE_ATTEMPTS; i++) {
  298. reg = rd32(IGC_EECD);
  299. if (reg & IGC_EECD_FLUDONE_I225) {
  300. ret_val = 0;
  301. break;
  302. }
  303. udelay(5);
  304. }
  305. return ret_val;
  306. }
  307. /**
  308. * igc_update_flash_i225 - Commit EEPROM to the flash
  309. * @hw: pointer to the HW structure
  310. */
  311. static s32 igc_update_flash_i225(struct igc_hw *hw)
  312. {
  313. s32 ret_val = 0;
  314. u32 flup;
  315. ret_val = igc_pool_flash_update_done_i225(hw);
  316. if (ret_val == -IGC_ERR_NVM) {
  317. hw_dbg("Flash update time out\n");
  318. goto out;
  319. }
  320. flup = rd32(IGC_EECD) | IGC_EECD_FLUPD_I225;
  321. wr32(IGC_EECD, flup);
  322. ret_val = igc_pool_flash_update_done_i225(hw);
  323. if (ret_val)
  324. hw_dbg("Flash update time out\n");
  325. else
  326. hw_dbg("Flash update complete\n");
  327. out:
  328. return ret_val;
  329. }
  330. /**
  331. * igc_update_nvm_checksum_i225 - Update EEPROM checksum
  332. * @hw: pointer to the HW structure
  333. *
  334. * Updates the EEPROM checksum by reading/adding each word of the EEPROM
  335. * up to the checksum. Then calculates the EEPROM checksum and writes the
  336. * value to the EEPROM. Next commit EEPROM data onto the Flash.
  337. */
  338. static s32 igc_update_nvm_checksum_i225(struct igc_hw *hw)
  339. {
  340. u16 checksum = 0;
  341. s32 ret_val = 0;
  342. u16 i, nvm_data;
  343. /* Read the first word from the EEPROM. If this times out or fails, do
  344. * not continue or we could be in for a very long wait while every
  345. * EEPROM read fails
  346. */
  347. ret_val = igc_read_nvm_eerd(hw, 0, 1, &nvm_data);
  348. if (ret_val) {
  349. hw_dbg("EEPROM read failed\n");
  350. goto out;
  351. }
  352. ret_val = hw->nvm.ops.acquire(hw);
  353. if (ret_val)
  354. goto out;
  355. /* Do not use hw->nvm.ops.write, hw->nvm.ops.read
  356. * because we do not want to take the synchronization
  357. * semaphores twice here.
  358. */
  359. for (i = 0; i < NVM_CHECKSUM_REG; i++) {
  360. ret_val = igc_read_nvm_eerd(hw, i, 1, &nvm_data);
  361. if (ret_val) {
  362. hw->nvm.ops.release(hw);
  363. hw_dbg("NVM Read Error while updating checksum.\n");
  364. goto out;
  365. }
  366. checksum += nvm_data;
  367. }
  368. checksum = (u16)NVM_SUM - checksum;
  369. ret_val = igc_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
  370. &checksum);
  371. if (ret_val) {
  372. hw->nvm.ops.release(hw);
  373. hw_dbg("NVM Write Error while updating checksum.\n");
  374. goto out;
  375. }
  376. hw->nvm.ops.release(hw);
  377. ret_val = igc_update_flash_i225(hw);
  378. out:
  379. return ret_val;
  380. }
  381. /**
  382. * igc_get_flash_presence_i225 - Check if flash device is detected
  383. * @hw: pointer to the HW structure
  384. */
  385. bool igc_get_flash_presence_i225(struct igc_hw *hw)
  386. {
  387. bool ret_val = false;
  388. u32 eec = 0;
  389. eec = rd32(IGC_EECD);
  390. if (eec & IGC_EECD_FLASH_DETECTED_I225)
  391. ret_val = true;
  392. return ret_val;
  393. }
  394. /**
  395. * igc_init_nvm_params_i225 - Init NVM func ptrs.
  396. * @hw: pointer to the HW structure
  397. */
  398. s32 igc_init_nvm_params_i225(struct igc_hw *hw)
  399. {
  400. struct igc_nvm_info *nvm = &hw->nvm;
  401. nvm->ops.acquire = igc_acquire_nvm_i225;
  402. nvm->ops.release = igc_release_nvm_i225;
  403. /* NVM Function Pointers */
  404. if (igc_get_flash_presence_i225(hw)) {
  405. hw->nvm.type = igc_nvm_flash_hw;
  406. nvm->ops.read = igc_read_nvm_srrd_i225;
  407. nvm->ops.write = igc_write_nvm_srwr_i225;
  408. nvm->ops.validate = igc_validate_nvm_checksum_i225;
  409. nvm->ops.update = igc_update_nvm_checksum_i225;
  410. } else {
  411. hw->nvm.type = igc_nvm_invm;
  412. nvm->ops.read = igc_read_nvm_eerd;
  413. nvm->ops.write = NULL;
  414. nvm->ops.validate = NULL;
  415. nvm->ops.update = NULL;
  416. }
  417. return 0;
  418. }