mt76x02_eeprom.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // SPDX-License-Identifier: ISC
  2. /*
  3. * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
  4. * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
  5. */
  6. #include <asm/unaligned.h>
  7. #include "mt76x02_eeprom.h"
  8. static int
  9. mt76x02_efuse_read(struct mt76x02_dev *dev, u16 addr, u8 *data,
  10. enum mt76x02_eeprom_modes mode)
  11. {
  12. u32 val;
  13. int i;
  14. val = mt76_rr(dev, MT_EFUSE_CTRL);
  15. val &= ~(MT_EFUSE_CTRL_AIN |
  16. MT_EFUSE_CTRL_MODE);
  17. val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
  18. val |= FIELD_PREP(MT_EFUSE_CTRL_MODE, mode);
  19. val |= MT_EFUSE_CTRL_KICK;
  20. mt76_wr(dev, MT_EFUSE_CTRL, val);
  21. if (!mt76_poll_msec(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
  22. return -ETIMEDOUT;
  23. udelay(2);
  24. val = mt76_rr(dev, MT_EFUSE_CTRL);
  25. if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
  26. memset(data, 0xff, 16);
  27. return 0;
  28. }
  29. for (i = 0; i < 4; i++) {
  30. val = mt76_rr(dev, MT_EFUSE_DATA(i));
  31. put_unaligned_le32(val, data + 4 * i);
  32. }
  33. return 0;
  34. }
  35. int mt76x02_eeprom_copy(struct mt76x02_dev *dev,
  36. enum mt76x02_eeprom_field field,
  37. void *dest, int len)
  38. {
  39. if (field + len > dev->mt76.eeprom.size)
  40. return -1;
  41. memcpy(dest, dev->mt76.eeprom.data + field, len);
  42. return 0;
  43. }
  44. EXPORT_SYMBOL_GPL(mt76x02_eeprom_copy);
  45. int mt76x02_get_efuse_data(struct mt76x02_dev *dev, u16 base, void *buf,
  46. int len, enum mt76x02_eeprom_modes mode)
  47. {
  48. int ret, i;
  49. for (i = 0; i + 16 <= len; i += 16) {
  50. ret = mt76x02_efuse_read(dev, base + i, buf + i, mode);
  51. if (ret)
  52. return ret;
  53. }
  54. return 0;
  55. }
  56. EXPORT_SYMBOL_GPL(mt76x02_get_efuse_data);
  57. void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev)
  58. {
  59. u16 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
  60. switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {
  61. case BOARD_TYPE_5GHZ:
  62. dev->mphy.cap.has_5ghz = true;
  63. break;
  64. case BOARD_TYPE_2GHZ:
  65. dev->mphy.cap.has_2ghz = true;
  66. break;
  67. default:
  68. dev->mphy.cap.has_2ghz = true;
  69. dev->mphy.cap.has_5ghz = true;
  70. break;
  71. }
  72. }
  73. EXPORT_SYMBOL_GPL(mt76x02_eeprom_parse_hw_cap);
  74. bool mt76x02_ext_pa_enabled(struct mt76x02_dev *dev, enum nl80211_band band)
  75. {
  76. u16 conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
  77. if (band == NL80211_BAND_5GHZ)
  78. return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_5G);
  79. else
  80. return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_2G);
  81. }
  82. EXPORT_SYMBOL_GPL(mt76x02_ext_pa_enabled);
  83. void mt76x02_get_rx_gain(struct mt76x02_dev *dev, enum nl80211_band band,
  84. u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g)
  85. {
  86. u16 val;
  87. val = mt76x02_eeprom_get(dev, MT_EE_LNA_GAIN);
  88. *lna_2g = val & 0xff;
  89. lna_5g[0] = val >> 8;
  90. val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_1);
  91. lna_5g[1] = val >> 8;
  92. val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_1);
  93. lna_5g[2] = val >> 8;
  94. if (!mt76x02_field_valid(lna_5g[1]))
  95. lna_5g[1] = lna_5g[0];
  96. if (!mt76x02_field_valid(lna_5g[2]))
  97. lna_5g[2] = lna_5g[0];
  98. if (band == NL80211_BAND_2GHZ)
  99. *rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_0);
  100. else
  101. *rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_0);
  102. }
  103. EXPORT_SYMBOL_GPL(mt76x02_get_rx_gain);
  104. u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev,
  105. s8 *lna_2g, s8 *lna_5g,
  106. struct ieee80211_channel *chan)
  107. {
  108. u16 val;
  109. u8 lna;
  110. val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
  111. if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
  112. *lna_2g = 0;
  113. if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
  114. memset(lna_5g, 0, sizeof(s8) * 3);
  115. if (chan->band == NL80211_BAND_2GHZ)
  116. lna = *lna_2g;
  117. else if (chan->hw_value <= 64)
  118. lna = lna_5g[0];
  119. else if (chan->hw_value <= 128)
  120. lna = lna_5g[1];
  121. else
  122. lna = lna_5g[2];
  123. return lna != 0xff ? lna : 0;
  124. }
  125. EXPORT_SYMBOL_GPL(mt76x02_get_lna_gain);