igc_i225.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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 HW semaphore to access the PHY or NVM
  10. */
  11. static s32 igc_get_hw_semaphore_i225(struct igc_hw *hw)
  12. {
  13. s32 timeout = hw->nvm.word_size + 1;
  14. s32 i = 0;
  15. u32 swsm;
  16. /* Get the SW semaphore */
  17. while (i < timeout) {
  18. swsm = rd32(IGC_SWSM);
  19. if (!(swsm & IGC_SWSM_SMBI))
  20. break;
  21. usleep_range(500, 600);
  22. i++;
  23. }
  24. if (i == timeout) {
  25. /* In rare circumstances, the SW semaphore may already be held
  26. * unintentionally. Clear the semaphore once before giving up.
  27. */
  28. if (hw->dev_spec._base.clear_semaphore_once) {
  29. hw->dev_spec._base.clear_semaphore_once = false;
  30. igc_put_hw_semaphore(hw);
  31. for (i = 0; i < timeout; i++) {
  32. swsm = rd32(IGC_SWSM);
  33. if (!(swsm & IGC_SWSM_SMBI))
  34. break;
  35. usleep_range(500, 600);
  36. }
  37. }
  38. /* If we do not have the semaphore here, we have to give up. */
  39. if (i == timeout) {
  40. hw_dbg("Driver can't access device - SMBI bit is set.\n");
  41. return -IGC_ERR_NVM;
  42. }
  43. }
  44. /* Get the FW semaphore. */
  45. for (i = 0; i < timeout; i++) {
  46. swsm = rd32(IGC_SWSM);
  47. wr32(IGC_SWSM, swsm | IGC_SWSM_SWESMBI);
  48. /* Semaphore acquired if bit latched */
  49. if (rd32(IGC_SWSM) & IGC_SWSM_SWESMBI)
  50. break;
  51. usleep_range(500, 600);
  52. }
  53. if (i == timeout) {
  54. /* Release semaphores */
  55. igc_put_hw_semaphore(hw);
  56. hw_dbg("Driver can't access the NVM\n");
  57. return -IGC_ERR_NVM;
  58. }
  59. return 0;
  60. }
  61. /**
  62. * igc_acquire_swfw_sync_i225 - Acquire SW/FW semaphore
  63. * @hw: pointer to the HW structure
  64. * @mask: specifies which semaphore to acquire
  65. *
  66. * Acquire the SW/FW semaphore to access the PHY or NVM. The mask
  67. * will also specify which port we're acquiring the lock for.
  68. */
  69. s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask)
  70. {
  71. s32 i = 0, timeout = 200;
  72. u32 fwmask = mask << 16;
  73. u32 swmask = mask;
  74. s32 ret_val = 0;
  75. u32 swfw_sync;
  76. while (i < timeout) {
  77. if (igc_get_hw_semaphore_i225(hw)) {
  78. ret_val = -IGC_ERR_SWFW_SYNC;
  79. goto out;
  80. }
  81. swfw_sync = rd32(IGC_SW_FW_SYNC);
  82. if (!(swfw_sync & (fwmask | swmask)))
  83. break;
  84. /* Firmware currently using resource (fwmask) */
  85. igc_put_hw_semaphore(hw);
  86. mdelay(5);
  87. i++;
  88. }
  89. if (i == timeout) {
  90. hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
  91. ret_val = -IGC_ERR_SWFW_SYNC;
  92. goto out;
  93. }
  94. swfw_sync |= swmask;
  95. wr32(IGC_SW_FW_SYNC, swfw_sync);
  96. igc_put_hw_semaphore(hw);
  97. out:
  98. return ret_val;
  99. }
  100. /**
  101. * igc_release_swfw_sync_i225 - Release SW/FW semaphore
  102. * @hw: pointer to the HW structure
  103. * @mask: specifies which semaphore to acquire
  104. *
  105. * Release the SW/FW semaphore used to access the PHY or NVM. The mask
  106. * will also specify which port we're releasing the lock for.
  107. */
  108. void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask)
  109. {
  110. u32 swfw_sync;
  111. while (igc_get_hw_semaphore_i225(hw))
  112. ; /* Empty */
  113. swfw_sync = rd32(IGC_SW_FW_SYNC);
  114. swfw_sync &= ~mask;
  115. wr32(IGC_SW_FW_SYNC, swfw_sync);
  116. igc_put_hw_semaphore(hw);
  117. }