diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 94 |
1 files changed, 77 insertions, 17 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index dfa9a08b896d..edac37e7847b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -5,6 +5,7 @@ * Felix Fietkau <nbd@nbd.name> */ +#include <linux/of.h> #include "mt7615.h" #include "eeprom.h" @@ -40,11 +41,11 @@ static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base, return 0; } -static int mt7615_efuse_init(struct mt7615_dev *dev) +static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base) { - u32 val, base = mt7615_reg_map(dev, MT_EFUSE_BASE); int i, len = MT7615_EEPROM_SIZE; void *buf; + u32 val; val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL); if (val & MT_EFUSE_BASE_CTRL_EMPTY) @@ -67,15 +68,16 @@ static int mt7615_efuse_init(struct mt7615_dev *dev) return 0; } -static int mt7615_eeprom_load(struct mt7615_dev *dev) +static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr) { int ret; - ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE); + ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE + + MT7615_EEPROM_EXTRA_DATA); if (ret < 0) return ret; - return mt7615_efuse_init(dev); + return mt7615_efuse_init(dev, addr); } static int mt7615_check_eeprom(struct mt76_dev *dev) @@ -109,6 +111,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) return; } + if (is_mt7611(&dev->mt76)) { + /* 5GHz only */ + dev->mt76.cap.has_5ghz = true; + return; + } + val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, eeprom[MT_EE_WIFI_CONF]); switch (val) { @@ -128,14 +136,15 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) { u8 *eeprom = dev->mt76.eeprom.data; - u8 tx_mask; + u8 tx_mask, max_nss; mt7615_eeprom_parse_hw_band_cap(dev); if (is_mt7663(&dev->mt76)) { - tx_mask = 2; + max_nss = 2; + tx_mask = FIELD_GET(MT_EE_HW_CONF1_TX_MASK, + eeprom[MT7663_EE_HW_CONF1]); } else { - u8 max_nss; u32 val; /* read tx-rx mask from eeprom */ @@ -144,21 +153,46 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK, eeprom[MT_EE_NIC_CONF_0]); - if (!tx_mask || tx_mask > max_nss) - tx_mask = max_nss; } + if (!tx_mask || tx_mask > max_nss) + tx_mask = max_nss; dev->chainmask = BIT(tx_mask) - 1; dev->mphy.antenna_mask = dev->chainmask; dev->phy.chainmask = dev->chainmask; } -int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, - struct ieee80211_channel *chan, - u8 chain_idx) +static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev, + struct ieee80211_channel *chan, + u8 chain_idx) +{ + int index, group; + + if (chain_idx > 1) + return -EINVAL; + + if (chan->band == NL80211_BAND_2GHZ) + return MT7663_EE_TX0_2G_TARGET_POWER + (chain_idx << 4); + + group = mt7615_get_channel_group(chan->hw_value); + if (chain_idx == 1) + index = MT7663_EE_TX1_5G_G0_TARGET_POWER; + else + index = MT7663_EE_TX0_5G_G0_TARGET_POWER; + + return index + group * 3; +} + +int mt7615_eeprom_get_target_power_index(struct mt7615_dev *dev, + struct ieee80211_channel *chan, + u8 chain_idx) { int index; + if (is_mt7663(&dev->mt76)) + return mt7663_eeprom_get_target_power_index(dev, chan, + chain_idx); + if (chain_idx > 3) return -EINVAL; @@ -197,6 +231,23 @@ int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, return index; } +int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev, + enum nl80211_band band) +{ + /* assume the first rate has the highest power offset */ + if (is_mt7663(&dev->mt76)) { + if (band == NL80211_BAND_2GHZ) + return MT_EE_TX0_5G_G0_TARGET_POWER; + else + return MT7663_EE_5G_RATE_POWER; + } + + if (band == NL80211_BAND_2GHZ) + return MT_EE_2G_RATE_POWER; + else + return MT_EE_5G_RATE_POWER; +} + static void mt7615_apply_cal_free_data(struct mt7615_dev *dev) { static const u16 ical[] = { @@ -255,30 +306,38 @@ static void mt7622_apply_cal_free_data(struct mt7615_dev *dev) static void mt7615_cal_free_data(struct mt7615_dev *dev) { + struct device_node *np = dev->mt76.dev->of_node; + + if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp")) + return; + switch (mt76_chip(&dev->mt76)) { case 0x7622: mt7622_apply_cal_free_data(dev); break; case 0x7615: + case 0x7611: mt7615_apply_cal_free_data(dev); break; } } -int mt7615_eeprom_init(struct mt7615_dev *dev) +int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr) { int ret; - ret = mt7615_eeprom_load(dev); + ret = mt7615_eeprom_load(dev, addr); if (ret < 0) return ret; ret = mt7615_check_eeprom(&dev->mt76); - if (ret && dev->mt76.otp.data) + if (ret && dev->mt76.otp.data) { memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); - else + } else { + dev->flash_eeprom = true; mt7615_cal_free_data(dev); + } mt7615_eeprom_parse_hw_cap(dev); memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, @@ -288,3 +347,4 @@ int mt7615_eeprom_init(struct mt7615_dev *dev) return 0; } +EXPORT_SYMBOL_GPL(mt7615_eeprom_init); |