Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /*
0003  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
0004  * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
0005  */
0006 
0007 #include <asm/unaligned.h>
0008 
0009 #include "mt76x02_eeprom.h"
0010 
0011 static int
0012 mt76x02_efuse_read(struct mt76x02_dev *dev, u16 addr, u8 *data,
0013            enum mt76x02_eeprom_modes mode)
0014 {
0015     u32 val;
0016     int i;
0017 
0018     val = mt76_rr(dev, MT_EFUSE_CTRL);
0019     val &= ~(MT_EFUSE_CTRL_AIN |
0020          MT_EFUSE_CTRL_MODE);
0021     val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
0022     val |= FIELD_PREP(MT_EFUSE_CTRL_MODE, mode);
0023     val |= MT_EFUSE_CTRL_KICK;
0024     mt76_wr(dev, MT_EFUSE_CTRL, val);
0025 
0026     if (!mt76_poll_msec(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
0027         return -ETIMEDOUT;
0028 
0029     udelay(2);
0030 
0031     val = mt76_rr(dev, MT_EFUSE_CTRL);
0032     if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
0033         memset(data, 0xff, 16);
0034         return 0;
0035     }
0036 
0037     for (i = 0; i < 4; i++) {
0038         val = mt76_rr(dev, MT_EFUSE_DATA(i));
0039         put_unaligned_le32(val, data + 4 * i);
0040     }
0041 
0042     return 0;
0043 }
0044 
0045 int mt76x02_eeprom_copy(struct mt76x02_dev *dev,
0046             enum mt76x02_eeprom_field field,
0047             void *dest, int len)
0048 {
0049     if (field + len > dev->mt76.eeprom.size)
0050         return -1;
0051 
0052     memcpy(dest, dev->mt76.eeprom.data + field, len);
0053     return 0;
0054 }
0055 EXPORT_SYMBOL_GPL(mt76x02_eeprom_copy);
0056 
0057 int mt76x02_get_efuse_data(struct mt76x02_dev *dev, u16 base, void *buf,
0058                int len, enum mt76x02_eeprom_modes mode)
0059 {
0060     int ret, i;
0061 
0062     for (i = 0; i + 16 <= len; i += 16) {
0063         ret = mt76x02_efuse_read(dev, base + i, buf + i, mode);
0064         if (ret)
0065             return ret;
0066     }
0067 
0068     return 0;
0069 }
0070 EXPORT_SYMBOL_GPL(mt76x02_get_efuse_data);
0071 
0072 void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev)
0073 {
0074     u16 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
0075 
0076     switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {
0077     case BOARD_TYPE_5GHZ:
0078         dev->mphy.cap.has_5ghz = true;
0079         break;
0080     case BOARD_TYPE_2GHZ:
0081         dev->mphy.cap.has_2ghz = true;
0082         break;
0083     default:
0084         dev->mphy.cap.has_2ghz = true;
0085         dev->mphy.cap.has_5ghz = true;
0086         break;
0087     }
0088 }
0089 EXPORT_SYMBOL_GPL(mt76x02_eeprom_parse_hw_cap);
0090 
0091 bool mt76x02_ext_pa_enabled(struct mt76x02_dev *dev, enum nl80211_band band)
0092 {
0093     u16 conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
0094 
0095     if (band == NL80211_BAND_5GHZ)
0096         return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_5G);
0097     else
0098         return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_2G);
0099 }
0100 EXPORT_SYMBOL_GPL(mt76x02_ext_pa_enabled);
0101 
0102 void mt76x02_get_rx_gain(struct mt76x02_dev *dev, enum nl80211_band band,
0103              u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g)
0104 {
0105     u16 val;
0106 
0107     val = mt76x02_eeprom_get(dev, MT_EE_LNA_GAIN);
0108     *lna_2g = val & 0xff;
0109     lna_5g[0] = val >> 8;
0110 
0111     val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_1);
0112     lna_5g[1] = val >> 8;
0113 
0114     val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_1);
0115     lna_5g[2] = val >> 8;
0116 
0117     if (!mt76x02_field_valid(lna_5g[1]))
0118         lna_5g[1] = lna_5g[0];
0119 
0120     if (!mt76x02_field_valid(lna_5g[2]))
0121         lna_5g[2] = lna_5g[0];
0122 
0123     if (band == NL80211_BAND_2GHZ)
0124         *rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_0);
0125     else
0126         *rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_0);
0127 }
0128 EXPORT_SYMBOL_GPL(mt76x02_get_rx_gain);
0129 
0130 u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev,
0131             s8 *lna_2g, s8 *lna_5g,
0132             struct ieee80211_channel *chan)
0133 {
0134     u16 val;
0135     u8 lna;
0136 
0137     val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
0138     if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
0139         *lna_2g = 0;
0140     if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
0141         memset(lna_5g, 0, sizeof(s8) * 3);
0142 
0143     if (chan->band == NL80211_BAND_2GHZ)
0144         lna = *lna_2g;
0145     else if (chan->hw_value <= 64)
0146         lna = lna_5g[0];
0147     else if (chan->hw_value <= 128)
0148         lna = lna_5g[1];
0149     else
0150         lna = lna_5g[2];
0151 
0152     return lna != 0xff ? lna : 0;
0153 }
0154 EXPORT_SYMBOL_GPL(mt76x02_get_lna_gain);