summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mediatek/mt76/mt76x0
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt76x0')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/dma.h126
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c55
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/init.c9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/main.c22
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/pci.c49
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/phy.c311
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c7
11 files changed, 272 insertions, 320 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/dma.h b/drivers/net/wireless/mediatek/mt76/mt76x0/dma.h
deleted file mode 100644
index 891ce1c3461f..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/dma.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MT76X0U_DMA_H
-#define __MT76X0U_DMA_H
-
-#include <asm/unaligned.h>
-#include <linux/skbuff.h>
-
-#define MT_DMA_HDR_LEN 4
-#define MT_RX_INFO_LEN 4
-#define MT_FCE_INFO_LEN 4
-#define MT_DMA_HDRS (MT_DMA_HDR_LEN + MT_RX_INFO_LEN)
-
-/* Common Tx DMA descriptor fields */
-#define MT_TXD_INFO_LEN GENMASK(15, 0)
-#define MT_TXD_INFO_D_PORT GENMASK(29, 27)
-#define MT_TXD_INFO_TYPE GENMASK(31, 30)
-
-/* Tx DMA MCU command specific flags */
-#define MT_TXD_CMD_SEQ GENMASK(19, 16)
-#define MT_TXD_CMD_TYPE GENMASK(26, 20)
-
-enum mt76_msg_port {
- WLAN_PORT,
- CPU_RX_PORT,
- CPU_TX_PORT,
- HOST_PORT,
- VIRTUAL_CPU_RX_PORT,
- VIRTUAL_CPU_TX_PORT,
- DISCARD,
-};
-
-enum mt76_info_type {
- DMA_PACKET,
- DMA_COMMAND,
-};
-
-/* Tx DMA packet specific flags */
-#define MT_TXD_PKT_INFO_NEXT_VLD BIT(16)
-#define MT_TXD_PKT_INFO_TX_BURST BIT(17)
-#define MT_TXD_PKT_INFO_80211 BIT(19)
-#define MT_TXD_PKT_INFO_TSO BIT(20)
-#define MT_TXD_PKT_INFO_CSO BIT(21)
-#define MT_TXD_PKT_INFO_WIV BIT(24)
-#define MT_TXD_PKT_INFO_QSEL GENMASK(26, 25)
-
-enum mt76_qsel {
- MT_QSEL_MGMT,
- MT_QSEL_HCCA,
- MT_QSEL_EDCA,
- MT_QSEL_EDCA_2,
-};
-
-
-static inline int mt76x0_dma_skb_wrap(struct sk_buff *skb,
- enum mt76_msg_port d_port,
- enum mt76_info_type type, u32 flags)
-{
- u32 info;
-
- /* Buffer layout:
- * | 4B | xfer len | pad | 4B |
- * | TXINFO | pkt/cmd | zero pad to 4B | zero |
- *
- * length field of TXINFO should be set to 'xfer len'.
- */
-
- info = flags |
- FIELD_PREP(MT_TXD_INFO_LEN, round_up(skb->len, 4)) |
- FIELD_PREP(MT_TXD_INFO_D_PORT, d_port) |
- FIELD_PREP(MT_TXD_INFO_TYPE, type);
-
- put_unaligned_le32(info, skb_push(skb, sizeof(info)));
- return skb_put_padto(skb, round_up(skb->len, 4) + 4);
-}
-
-static inline int
-mt76x0_dma_skb_wrap_pkt(struct sk_buff *skb, enum mt76_qsel qsel, u32 flags)
-{
- flags |= FIELD_PREP(MT_TXD_PKT_INFO_QSEL, qsel);
- return mt76x0_dma_skb_wrap(skb, WLAN_PORT, DMA_PACKET, flags);
-}
-
-/* Common Rx DMA descriptor fields */
-#define MT_RXD_INFO_LEN GENMASK(13, 0)
-#define MT_RXD_INFO_PCIE_INTR BIT(24)
-#define MT_RXD_INFO_QSEL GENMASK(26, 25)
-#define MT_RXD_INFO_PORT GENMASK(29, 27)
-#define MT_RXD_INFO_TYPE GENMASK(31, 30)
-
-/* Rx DMA packet specific flags */
-#define MT_RXD_PKT_INFO_UDP_ERR BIT(16)
-#define MT_RXD_PKT_INFO_TCP_ERR BIT(17)
-#define MT_RXD_PKT_INFO_IP_ERR BIT(18)
-#define MT_RXD_PKT_INFO_PKT_80211 BIT(19)
-#define MT_RXD_PKT_INFO_L3L4_DONE BIT(20)
-#define MT_RXD_PKT_INFO_MAC_LEN GENMASK(23, 21)
-
-/* Rx DMA MCU command specific flags */
-#define MT_RXD_CMD_INFO_SELF_GEN BIT(15)
-#define MT_RXD_CMD_INFO_CMD_SEQ GENMASK(19, 16)
-#define MT_RXD_CMD_INFO_EVT_TYPE GENMASK(23, 20)
-
-enum mt76_evt_type {
- CMD_DONE,
- CMD_ERROR,
- CMD_RETRY,
- EVENT_PWR_RSP,
- EVENT_WOW_RSP,
- EVENT_CARRIER_DETECT_RSP,
- EVENT_DFS_DETECT_RSP,
-};
-
-#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 5735038c0e2d..ab4fd6e0f23a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -31,8 +31,8 @@ mt76x0_efuse_physical_size_check(struct mt76x02_dev *dev)
int ret, i;
u32 start = 0, end = 0, cnt_free;
- ret = mt76x02_get_efuse_data(&dev->mt76, MT_EE_USAGE_MAP_START,
- data, sizeof(data), MT_EE_PHYSICAL_READ);
+ ret = mt76x02_get_efuse_data(dev, MT_EE_USAGE_MAP_START, data,
+ sizeof(data), MT_EE_PHYSICAL_READ);
if (ret)
return ret;
@@ -55,10 +55,10 @@ mt76x0_efuse_physical_size_check(struct mt76x02_dev *dev)
static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
{
- u16 nic_conf0 = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_0);
- u16 nic_conf1 = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_1);
+ u16 nic_conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
+ u16 nic_conf1 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
- mt76x02_eeprom_parse_hw_cap(&dev->mt76);
+ mt76x02_eeprom_parse_hw_cap(dev);
dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n",
dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz);
@@ -86,7 +86,7 @@ static void mt76x0_set_temp_offset(struct mt76x02_dev *dev)
{
u8 val;
- val = mt76x02_eeprom_get(&dev->mt76, MT_EE_2G_TARGET_POWER) >> 8;
+ val = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER) >> 8;
if (mt76x02_field_valid(val))
dev->cal.rx.temp_offset = mt76x02_sign_extend(val, 8);
else
@@ -98,12 +98,12 @@ static void mt76x0_set_freq_offset(struct mt76x02_dev *dev)
struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx;
u8 val;
- val = mt76x02_eeprom_get(&dev->mt76, MT_EE_FREQ_OFFSET);
+ val = mt76x02_eeprom_get(dev, MT_EE_FREQ_OFFSET);
if (!mt76x02_field_valid(val))
val = 0;
caldata->freq_offset = val;
- val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TSSI_BOUND4) >> 8;
+ val = mt76x02_eeprom_get(dev, MT_EE_TSSI_BOUND4) >> 8;
if (!mt76x02_field_valid(val))
val = 0;
@@ -118,10 +118,8 @@ void mt76x0_read_rx_gain(struct mt76x02_dev *dev)
u16 rssi_offset;
int i;
- mt76x02_get_rx_gain(&dev->mt76, chan->band, &rssi_offset,
- &lna_2g, lna_5g);
- caldata->lna_gain = mt76x02_get_lna_gain(&dev->mt76, &lna_2g,
- lna_5g, chan);
+ mt76x02_get_rx_gain(dev, chan->band, &rssi_offset, &lna_2g, lna_5g);
+ caldata->lna_gain = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan);
for (i = 0; i < ARRAY_SIZE(caldata->rssi_offset); i++) {
val = rssi_offset >> (8 * i);
@@ -132,12 +130,12 @@ void mt76x0_read_rx_gain(struct mt76x02_dev *dev)
}
}
-static s8 mt76x0_get_delta(struct mt76_dev *dev)
+static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
{
- struct cfg80211_chan_def *chandef = &dev->chandef;
+ struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
u8 val;
- if (mt76x02_tssi_enabled(dev))
+ if (mt76x0_tssi_enabled(dev))
return 0;
if (chandef->width == NL80211_CHAN_WIDTH_80) {
@@ -162,54 +160,54 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
bool is_2ghz = chan->band == NL80211_BAND_2GHZ;
struct mt76_rate_power *t = &dev->mt76.rate_power;
- s8 delta = mt76x0_get_delta(&dev->mt76);
+ s8 delta = mt76x0_get_delta(dev);
u16 val, addr;
memset(t, 0, sizeof(*t));
/* cck 1M, 2M, 5.5M, 11M */
- val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_BYRATE_BASE);
+ val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_BYRATE_BASE);
t->cck[0] = t->cck[1] = s6_to_s8(val);
t->cck[2] = t->cck[3] = s6_to_s8(val >> 8);
/* ofdm 6M, 9M, 12M, 18M */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 2 : 0x120;
- val = mt76x02_eeprom_get(&dev->mt76, addr);
+ val = mt76x02_eeprom_get(dev, addr);
t->ofdm[0] = t->ofdm[1] = s6_to_s8(val);
t->ofdm[2] = t->ofdm[3] = s6_to_s8(val >> 8);
/* ofdm 24M, 36M, 48M, 54M */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 4 : 0x122;
- val = mt76x02_eeprom_get(&dev->mt76, addr);
+ val = mt76x02_eeprom_get(dev, addr);
t->ofdm[4] = t->ofdm[5] = s6_to_s8(val);
t->ofdm[6] = t->ofdm[7] = s6_to_s8(val >> 8);
/* ht-vht mcs 1ss 0, 1, 2, 3 */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 6 : 0x124;
- val = mt76x02_eeprom_get(&dev->mt76, addr);
+ val = mt76x02_eeprom_get(dev, addr);
t->ht[0] = t->ht[1] = t->vht[0] = t->vht[1] = s6_to_s8(val);
t->ht[2] = t->ht[3] = t->vht[2] = t->vht[3] = s6_to_s8(val >> 8);
/* ht-vht mcs 1ss 4, 5, 6 */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 8 : 0x126;
- val = mt76x02_eeprom_get(&dev->mt76, addr);
+ val = mt76x02_eeprom_get(dev, addr);
t->ht[4] = t->ht[5] = t->vht[4] = t->vht[5] = s6_to_s8(val);
t->ht[6] = t->vht[6] = s6_to_s8(val >> 8);
/* ht-vht mcs 1ss 0, 1, 2, 3 stbc */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 14 : 0xec;
- val = mt76x02_eeprom_get(&dev->mt76, addr);
+ val = mt76x02_eeprom_get(dev, addr);
t->stbc[0] = t->stbc[1] = s6_to_s8(val);
t->stbc[2] = t->stbc[3] = s6_to_s8(val >> 8);
/* ht-vht mcs 1ss 4, 5, 6 stbc */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 16 : 0xee;
- val = mt76x02_eeprom_get(&dev->mt76, addr);
+ val = mt76x02_eeprom_get(dev, addr);
t->stbc[4] = t->stbc[5] = s6_to_s8(val);
t->stbc[6] = t->stbc[7] = s6_to_s8(val >> 8);
/* vht mcs 8, 9 5GHz */
- val = mt76x02_eeprom_get(&dev->mt76, 0x132);
+ val = mt76x02_eeprom_get(dev, 0x132);
t->vht[7] = s6_to_s8(val);
t->vht[8] = s6_to_s8(val >> 8);
@@ -266,7 +264,7 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
addr = MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE + 2 + offset;
}
- data = mt76x02_eeprom_get(&dev->mt76, addr);
+ data = mt76x02_eeprom_get(dev, addr);
info[0] = data;
if (!info[0] || info[0] > 0x3f)
@@ -312,7 +310,7 @@ static int mt76x0_load_eeprom(struct mt76x02_dev *dev)
if (found < 0)
return found;
- return mt76x02_get_efuse_data(&dev->mt76, 0, dev->mt76.eeprom.data,
+ return mt76x02_get_efuse_data(dev, 0, dev->mt76.eeprom.data,
MT76X0_EEPROM_SIZE, MT_EE_READ);
}
@@ -326,7 +324,7 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)
if (err < 0)
return err;
- data = mt76x02_eeprom_get(&dev->mt76, MT_EE_VERSION);
+ data = mt76x02_eeprom_get(dev, MT_EE_VERSION);
version = data >> 8;
fae = data;
@@ -337,8 +335,7 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)
dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n",
version, fae);
- mt76x02_mac_setaddr(&dev->mt76,
- dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
+ mt76x02_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
mt76x0_set_chip_cap(dev);
mt76x0_set_freq_offset(dev);
mt76x0_set_temp_offset(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
index 40fd4e61769b..ee9ade9f3c8b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
@@ -37,4 +37,10 @@ static inline s8 s6_to_s8(u32 val)
return ret;
}
+static inline bool mt76x0_tssi_enabled(struct mt76x02_dev *dev)
+{
+ return (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) &
+ MT_EE_NIC_CONF_1_TX_ALC_EN);
+}
+
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index ee2b8e885608..4a9408801260 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -138,7 +138,7 @@ static void mt76x0_init_mac_registers(struct mt76x02_dev *dev)
RANDOM_WRITE(dev, common_mac_reg_table);
- mt76x02_set_beacon_offsets(&dev->mt76);
+ mt76x02_set_beacon_offsets(dev);
/* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */
RANDOM_WRITE(dev, mt76x0_mac_reg_table);
@@ -280,7 +280,7 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev)
return -ETIMEDOUT;
mt76x0_reset_csr_bbp(dev);
- ret = mt76x02_mcu_function_select(&dev->mt76, Q_SELECT, 1, false);
+ ret = mt76x02_mcu_function_select(dev, Q_SELECT, 1, false);
if (ret)
return ret;
@@ -368,7 +368,10 @@ int mt76x0_register_device(struct mt76x02_dev *dev)
hw->max_rates = 1;
hw->max_report_rates = 7;
hw->max_rate_tries = 1;
- hw->extra_tx_headroom = sizeof(struct mt76x02_txwi) + 4 + 2;
+ hw->extra_tx_headroom = 2;
+ if (mt76_is_usb(dev))
+ hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) +
+ MT_DMA_HDR_LEN;
hw->sta_data_size = sizeof(struct mt76x02_sta);
hw->vif_data_size = sizeof(struct mt76x02_vif);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
index c9cd0254a979..9273d2d2764a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
@@ -16,6 +16,20 @@
#include <linux/etherdevice.h>
#include "mt76x0.h"
+static int
+mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
+{
+ int ret;
+
+ cancel_delayed_work_sync(&dev->cal_work);
+
+ mt76_set_channel(&dev->mt76);
+ ret = mt76x0_phy_set_channel(dev, chandef);
+ mt76_txq_schedule_all(&dev->mt76);
+
+ return ret;
+}
+
int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
{
struct mt76x02_dev *dev = hw->priv;
@@ -25,7 +39,7 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
ieee80211_stop_queues(hw);
- ret = mt76x0_phy_set_channel(dev, &hw->conf.chandef);
+ ret = mt76x0_set_channel(dev, &hw->conf.chandef);
ieee80211_wake_queues(hw);
}
@@ -114,8 +128,6 @@ void mt76x0_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
{
struct mt76x02_dev *dev = hw->priv;
- cancel_delayed_work_sync(&dev->cal_work);
- mt76x0_agc_save(dev);
set_bit(MT76_SCANNING, &dev->mt76.state);
}
EXPORT_SYMBOL_GPL(mt76x0_sw_scan);
@@ -125,11 +137,7 @@ void mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
{
struct mt76x02_dev *dev = hw->priv;
- mt76x0_agc_restore(dev);
clear_bit(MT76_SCANNING, &dev->mt76.state);
-
- ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
- MT_CALIBRATE_INTERVAL);
}
EXPORT_SYMBOL_GPL(mt76x0_sw_scan_complete);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
index b66e70f6cd89..3b34e1d2769f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
@@ -39,6 +39,9 @@ enum mcu_calibrate {
MCU_CAL_TXDCOC,
MCU_CAL_RX_GROUP_DELAY,
MCU_CAL_TX_GROUP_DELAY,
+ MCU_CAL_VCO,
+ MCU_CAL_NO_SIGNAL = 0xfe,
+ MCU_CAL_FULL = 0xff,
};
int mt76x0e_mcu_init(struct mt76x02_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index 1bff2be45a13..2187bafaf2e9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -66,12 +66,11 @@ int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
/* PHY */
void mt76x0_phy_init(struct mt76x02_dev *dev);
int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev);
-void mt76x0_agc_save(struct mt76x02_dev *dev);
-void mt76x0_agc_restore(struct mt76x02_dev *dev);
int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef);
void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev);
void mt76x0_phy_set_txpower(struct mt76x02_dev *dev);
+void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on);
/* MAC */
void mt76x0_mac_work(struct work_struct *work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index 87997cddf0d6..522c86059bcb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -28,6 +28,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)
mutex_lock(&dev->mt76.mutex);
mt76x02_mac_start(dev);
+ mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
MT_CALIBRATE_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
@@ -71,10 +72,19 @@ static const struct ieee80211_ops mt76x0e_ops = {
.tx = mt76x02_tx,
.start = mt76x0e_start,
.stop = mt76x0e_stop,
- .config = mt76x0_config,
.add_interface = mt76x02_add_interface,
.remove_interface = mt76x02_remove_interface,
+ .config = mt76x0_config,
.configure_filter = mt76x02_configure_filter,
+ .sta_add = mt76x02_sta_add,
+ .sta_remove = mt76x02_sta_remove,
+ .set_key = mt76x02_set_key,
+ .conf_tx = mt76x02_conf_tx,
+ .sw_scan_start = mt76x0_sw_scan,
+ .sw_scan_complete = mt76x0_sw_scan_complete,
+ .ampdu_action = mt76x02_ampdu_action,
+ .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
+ .wake_tx_queue = mt76_wake_tx_queue,
};
static int mt76x0e_register_device(struct mt76x02_dev *dev)
@@ -102,28 +112,34 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev)
u16 val;
mt76_clear(dev, MT_COEXCFG0, BIT(0));
- val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_0);
- if (val & MT_EE_NIC_CONF_0_PA_IO_CURRENT) {
- u32 data;
-
- /* set external external PA I/O
- * current to 16mA
- */
- data = mt76_rr(dev, 0x11c);
- val |= 0xc03;
- mt76_wr(dev, 0x11c, val);
- }
+
+ val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
+ if (!(val & MT_EE_NIC_CONF_0_PA_IO_CURRENT))
+ mt76_set(dev, MT_XO_CTRL7, 0xc03);
}
mt76_clear(dev, 0x110, BIT(9));
mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
+ err = mt76x0_register_device(dev);
+ if (err < 0)
+ return err;
+
+ set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
+
return 0;
}
static int
mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ static const struct mt76_driver_ops drv_ops = {
+ .txwi_size = sizeof(struct mt76x02_txwi),
+ .tx_prepare_skb = mt76x02_tx_prepare_skb,
+ .tx_complete_skb = mt76x02_tx_complete_skb,
+ .rx_skb = mt76x02_queue_rx_skb,
+ .rx_poll_complete = mt76x02_rx_poll_complete,
+ };
struct mt76x02_dev *dev;
int ret;
@@ -141,7 +157,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
return ret;
- dev = mt76x0_alloc_device(&pdev->dev, NULL, &mt76x0e_ops);
+ dev = mt76x0_alloc_device(&pdev->dev, &drv_ops, &mt76x0e_ops);
if (!dev)
return -ENOMEM;
@@ -150,6 +166,11 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev);
+ ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler,
+ IRQF_SHARED, KBUILD_MODNAME, dev);
+ if (ret)
+ goto error;
+
ret = mt76x0e_register_device(dev);
if (ret < 0)
goto error;
@@ -167,7 +188,7 @@ static void mt76x0e_cleanup(struct mt76x02_dev *dev)
mt76x0_chip_onoff(dev, false, false);
mt76x0e_stop_hw(dev);
mt76x02_dma_cleanup(dev);
- mt76x02_mcu_cleanup(&dev->mt76);
+ mt76x02_mcu_cleanup(dev);
}
static void
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c
index 6c66656c21f4..569861289aa5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c
@@ -116,6 +116,7 @@ static int mt76x0e_load_firmware(struct mt76x02_dev *dev)
goto out;
}
+ mt76x02_set_ethtool_fwver(dev, hdr);
dev_dbg(dev->mt76.dev, "Firmware running!\n");
out:
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 4850a2db18d7..cf024950e0ed 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -14,6 +14,9 @@
* GNU General Public License for more details.
*/
+#include <linux/kernel.h>
+#include <linux/etherdevice.h>
+
#include "mt76x0.h"
#include "mcu.h"
#include "eeprom.h"
@@ -23,8 +26,6 @@
#include "initvals_phy.h"
#include "../mt76x02_phy.h"
-#include <linux/etherdevice.h>
-
static int
mt76x0_rf_csr_wr(struct mt76x02_dev *dev, u32 offset, u8 value)
{
@@ -37,7 +38,7 @@ mt76x0_rf_csr_wr(struct mt76x02_dev *dev, u32 offset, u8 value)
bank = MT_RF_BANK(offset);
reg = MT_RF_REG(offset);
- if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8)
+ if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank > 8))
return -EINVAL;
mutex_lock(&dev->phy_mutex);
@@ -76,7 +77,7 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 offset)
bank = MT_RF_BANK(offset);
reg = MT_RF_REG(offset);
- if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8)
+ if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank > 8))
return -EINVAL;
mutex_lock(&dev->phy_mutex);
@@ -111,15 +112,16 @@ out:
static int
rf_wr(struct mt76x02_dev *dev, u32 offset, u8 val)
{
- if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) {
+ if (mt76_is_usb(dev)) {
struct mt76_reg_pair pair = {
.reg = offset,
.value = val,
};
+ WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING,
+ &dev->mt76.state));
return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
} else {
- WARN_ON_ONCE(1);
return mt76x0_rf_csr_wr(dev, offset, val);
}
}
@@ -130,15 +132,16 @@ rf_rr(struct mt76x02_dev *dev, u32 offset)
int ret;
u32 val;
- if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) {
+ if (mt76_is_usb(dev)) {
struct mt76_reg_pair pair = {
.reg = offset,
};
+ WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING,
+ &dev->mt76.state));
ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
val = pair.value;
} else {
- WARN_ON_ONCE(1);
ret = val = mt76x0_rf_csr_rr(dev, offset);
}
@@ -175,9 +178,22 @@ rf_clear(struct mt76x02_dev *dev, u32 offset, u8 mask)
}
#endif
-#define RF_RANDOM_WRITE(dev, tab) \
- mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, \
- tab, ARRAY_SIZE(tab))
+static void
+mt76x0_rf_csr_wr_rp(struct mt76x02_dev *dev, const struct mt76_reg_pair *data,
+ int n)
+{
+ while (n-- > 0) {
+ mt76x0_rf_csr_wr(dev, data->reg, data->value);
+ data++;
+ }
+}
+
+#define RF_RANDOM_WRITE(dev, tab) do { \
+ if (mt76_is_mmio(dev)) \
+ mt76x0_rf_csr_wr_rp(dev, tab, ARRAY_SIZE(tab)); \
+ else \
+ mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, tab, ARRAY_SIZE(tab));\
+} while (0)
int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev)
{
@@ -186,7 +202,6 @@ int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev)
do {
val = mt76_rr(dev, MT_BBP(CORE, 0));
- printk("BBP version %08x\n", val);
if (val && ~val)
break;
} while (--i);
@@ -196,36 +211,10 @@ int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev)
return -EIO;
}
+ dev_dbg(dev->mt76.dev, "BBP version %08x\n", val);
return 0;
}
-static void
-mt76x0_bbp_set_ctrlch(struct mt76x02_dev *dev, enum nl80211_chan_width width,
- u8 ctrl)
-{
- int core_val, agc_val;
-
- switch (width) {
- case NL80211_CHAN_WIDTH_80:
- core_val = 3;
- agc_val = 7;
- break;
- case NL80211_CHAN_WIDTH_40:
- core_val = 2;
- agc_val = 3;
- break;
- default:
- core_val = 0;
- agc_val = 1;
- break;
- }
-
- mt76_rmw_field(dev, MT_BBP(CORE, 1), MT_BBP_CORE_R1_BW, core_val);
- mt76_rmw_field(dev, MT_BBP(AGC, 0), MT_BBP_AGC_R0_BW, agc_val);
- mt76_rmw_field(dev, MT_BBP(AGC, 0), MT_BBP_AGC_R0_CTRL_CHAN, ctrl);
- mt76_rmw_field(dev, MT_BBP(TXBE, 0), MT_BBP_TXBE_R0_CTRL_CHAN, ctrl);
-}
-
static void mt76x0_vco_cal(struct mt76x02_dev *dev, u8 channel)
{
u8 val;
@@ -283,13 +272,6 @@ static void mt76x0_vco_cal(struct mt76x02_dev *dev, u8 channel)
}
static void
-mt76x0_mac_set_ctrlch(struct mt76x02_dev *dev, bool primary_upper)
-{
- mt76_rmw_field(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_UPPER_40M,
- primary_upper);
-}
-
-static void
mt76x0_phy_set_band(struct mt76x02_dev *dev, enum nl80211_band band)
{
switch (band) {
@@ -299,9 +281,6 @@ mt76x0_phy_set_band(struct mt76x02_dev *dev, enum nl80211_band band)
rf_wr(dev, MT_RF(5, 0), 0x45);
rf_wr(dev, MT_RF(6, 0), 0x44);
- mt76_set(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_2G);
- mt76_clear(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_5G);
-
mt76_wr(dev, MT_TX_ALC_VGA3, 0x00050007);
mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x003E0002);
break;
@@ -311,9 +290,6 @@ mt76x0_phy_set_band(struct mt76x02_dev *dev, enum nl80211_band band)
rf_wr(dev, MT_RF(5, 0), 0x44);
rf_wr(dev, MT_RF(6, 0), 0x45);
- mt76_clear(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_2G);
- mt76_set(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_5G);
-
mt76_wr(dev, MT_TX_ALC_VGA3, 0x00000005);
mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x01010102);
break;
@@ -475,7 +451,7 @@ mt76x0_phy_set_chan_rf_params(struct mt76x02_dev *dev, u8 channel, u16 rf_bw_ban
mt76_wr(dev, MT_RF_MISC, mac_reg);
band = (rf_band & RF_G_BAND) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
- if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
+ if (mt76x02_ext_pa_enabled(dev, band)) {
/*
MT_RF_MISC (offset: 0x0518)
[2]1'b1: enable external A band PA, 1'b0: disable external A band PA
@@ -514,7 +490,7 @@ mt76x0_phy_set_chan_rf_params(struct mt76x02_dev *dev, u8 channel, u16 rf_bw_ban
}
static void
-mt76x0_phy_set_chan_bbp_params(struct mt76x02_dev *dev, u8 channel, u16 rf_bw_band)
+mt76x0_phy_set_chan_bbp_params(struct mt76x02_dev *dev, u16 rf_bw_band)
{
int i;
@@ -587,7 +563,7 @@ mt76x0_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width)
return ;
}
- mt76x02_mcu_function_select(&dev->mt76, BW_SETTING, bw, false);
+ mt76x02_mcu_function_select(dev, BW_SETTING, bw, false);
}
void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
@@ -603,8 +579,50 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t);
mt76x02_add_rate_power_offset(t, -info[0]);
- mt76x02_phy_set_txpower(&dev->mt76, info[0], info[1]);
+ mt76x02_phy_set_txpower(dev, info[0], info[1]);
+}
+
+void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
+{
+ struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+ u32 val, tx_alc, reg_val;
+
+ if (power_on) {
+ mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, chan->hw_value,
+ false);
+ usleep_range(10, 20);
+ /* XXX: tssi */
+ }
+
+ tx_alc = mt76_rr(dev, MT_TX_ALC_CFG_0);
+ mt76_wr(dev, MT_TX_ALC_CFG_0, 0);
+ usleep_range(500, 700);
+
+ reg_val = mt76_rr(dev, MT_BBP(IBI, 9));
+ mt76_wr(dev, MT_BBP(IBI, 9), 0xffffff7e);
+
+ if (chan->band == NL80211_BAND_5GHZ) {
+ if (chan->hw_value < 100)
+ val = 0x701;
+ else if (chan->hw_value < 140)
+ val = 0x801;
+ else
+ val = 0x901;
+ } else {
+ val = 0x600;
+ }
+
+ mt76x02_mcu_calibrate(dev, MCU_CAL_FULL, val, false);
+ msleep(350);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 1, false);
+ usleep_range(15000, 20000);
+
+ mt76_wr(dev, MT_BBP(IBI, 9), reg_val);
+ mt76_wr(dev, MT_TX_ALC_CFG_0, tx_alc);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1, false);
}
+EXPORT_SYMBOL_GPL(mt76x0_phy_calibrate);
int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef)
@@ -665,9 +683,19 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
break;
}
- mt76x0_bbp_set_bw(dev, chandef->width);
- mt76x0_bbp_set_ctrlch(dev, chandef->width, ch_group_index);
- mt76x0_mac_set_ctrlch(dev, ch_group_index & 1);
+ if (mt76_is_usb(dev)) {
+ mt76x0_bbp_set_bw(dev, chandef->width);
+ } else {
+ if (chandef->width == NL80211_CHAN_WIDTH_80 ||
+ chandef->width == NL80211_CHAN_WIDTH_40)
+ val = 0x201;
+ else
+ val = 0x601;
+ mt76_wr(dev, MT_TX_SW_CFG0, val);
+ }
+ mt76x02_phy_set_bw(dev, chandef->width, ch_group_index);
+ mt76x02_phy_set_band(dev, chandef->chan->band,
+ ch_group_index & 1);
mt76x0_ant_select(dev);
mt76_rmw(dev, MT_EXT_CCA_CFG,
@@ -680,7 +708,6 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
mt76x0_phy_set_band(dev, chandef->chan->band);
mt76x0_phy_set_chan_rf_params(dev, channel, rf_bw_band);
- mt76x0_read_rx_gain(dev);
/* set Japan Tx filter at channel 14 */
val = mt76_rr(dev, MT_BBP(CORE, 1));
@@ -690,17 +717,27 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
val &= ~0x20;
mt76_wr(dev, MT_BBP(CORE, 1), val);
- mt76x0_phy_set_chan_bbp_params(dev, channel, rf_bw_band);
+ mt76x0_read_rx_gain(dev);
+ mt76x0_phy_set_chan_bbp_params(dev, rf_bw_band);
+ mt76x02_init_agc_gain(dev);
- /* Vendor driver don't do it */
- /* mt76x0_phy_set_tx_power(dev, channel, rf_bw_band); */
+ if (mt76_is_usb(dev)) {
+ mt76x0_vco_cal(dev, channel);
+ } else {
+ /* enable vco */
+ rf_set(dev, MT_RF(0, 4), BIT(7));
+ }
- mt76x0_vco_cal(dev, channel);
if (scan)
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 1, false);
+ return 0;
+ if (mt76_is_mmio(dev))
+ mt76x0_phy_calibrate(dev, false);
mt76x0_phy_set_txpower(dev);
+ ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
+ MT_CALIBRATE_INTERVAL);
+
return 0;
}
@@ -710,7 +747,7 @@ void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev)
u8 channel = dev->mt76.chandef.chan->hw_value;
int is_5ghz = (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) ? 1 : 0;
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_R, 0, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, false);
mt76x0_vco_cal(dev, channel);
@@ -718,109 +755,113 @@ void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev)
mt76_wr(dev, MT_TX_ALC_CFG_0, 0);
usleep_range(500, 700);
- reg_val = mt76_rr(dev, 0x2124);
- reg_val &= 0xffffff7e;
- mt76_wr(dev, 0x2124, reg_val);
+ reg_val = mt76_rr(dev, MT_BBP(IBI, 9));
+ mt76_wr(dev, MT_BBP(IBI, 9), 0xffffff7e);
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 0, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 0, false);
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_LC, is_5ghz, false);
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_LOFT, is_5ghz, false);
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TXIQ, is_5ghz, false);
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TX_GROUP_DELAY,
- is_5ghz, false);
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXIQ, is_5ghz, false);
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RX_GROUP_DELAY,
- is_5ghz, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_LC, is_5ghz, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_LOFT, is_5ghz, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_TX_GROUP_DELAY, is_5ghz, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQ, is_5ghz, false);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_RX_GROUP_DELAY, is_5ghz, false);
- mt76_wr(dev, 0x2124, reg_val);
+ mt76_wr(dev, MT_BBP(IBI, 9), reg_val);
mt76_wr(dev, MT_TX_ALC_CFG_0, tx_alc);
msleep(100);
- mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 1, false);
-}
-
-void mt76x0_agc_save(struct mt76x02_dev *dev)
-{
- /* Only one RX path */
- dev->agc_save = FIELD_GET(MT_BBP_AGC_GAIN, mt76_rr(dev, MT_BBP(AGC, 8)));
-}
-
-void mt76x0_agc_restore(struct mt76x02_dev *dev)
-{
- mt76_rmw_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN, dev->agc_save);
+ mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1, false);
}
static void mt76x0_temp_sensor(struct mt76x02_dev *dev)
{
u8 rf_b7_73, rf_b0_66, rf_b0_67;
- int cycle, temp;
- u32 val;
- s32 sval;
+ s8 val;
rf_b7_73 = rf_rr(dev, MT_RF(7, 73));
rf_b0_66 = rf_rr(dev, MT_RF(0, 66));
- rf_b0_67 = rf_rr(dev, MT_RF(0, 73));
+ rf_b0_67 = rf_rr(dev, MT_RF(0, 67));
rf_wr(dev, MT_RF(7, 73), 0x02);
rf_wr(dev, MT_RF(0, 66), 0x23);
- rf_wr(dev, MT_RF(0, 73), 0x01);
+ rf_wr(dev, MT_RF(0, 67), 0x01);
mt76_wr(dev, MT_BBP(CORE, 34), 0x00080055);
- for (cycle = 0; cycle < 2000; cycle++) {
- val = mt76_rr(dev, MT_BBP(CORE, 34));
- if (!(val & 0x10))
- break;
- udelay(3);
- }
-
- if (cycle >= 2000) {
- val &= 0x10;
- mt76_wr(dev, MT_BBP(CORE, 34), val);
+ if (!mt76_poll(dev, MT_BBP(CORE, 34), BIT(4), 0, 2000)) {
+ mt76_clear(dev, MT_BBP(CORE, 34), BIT(4));
goto done;
}
- sval = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
- if (!(sval & 0x80))
- sval &= 0x7f; /* Positive */
- else
- sval |= 0xffffff00; /* Negative */
+ val = mt76_rr(dev, MT_BBP(CORE, 35));
+ val = (35 * (val - dev->cal.rx.temp_offset)) / 10 + 25;
- temp = (35 * (sval - dev->cal.rx.temp_offset)) / 10 + 25;
+ if (abs(val - dev->cal.temp_vco) > 20) {
+ mt76x02_mcu_calibrate(dev, MCU_CAL_VCO,
+ dev->mt76.chandef.chan->hw_value,
+ false);
+ dev->cal.temp_vco = val;
+ }
+ if (abs(val - dev->cal.temp) > 30) {
+ mt76x0_phy_calibrate(dev, false);
+ dev->cal.temp = val;
+ }
done:
rf_wr(dev, MT_RF(7, 73), rf_b7_73);
rf_wr(dev, MT_RF(0, 66), rf_b0_66);
- rf_wr(dev, MT_RF(0, 73), rf_b0_67);
+ rf_wr(dev, MT_RF(0, 67), rf_b0_67);
}
-static void mt76x0_dynamic_vga_tuning(struct mt76x02_dev *dev)
+static void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev)
{
- struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
- u32 val, init_vga;
- int avg_rssi;
-
- init_vga = chandef->chan->band == NL80211_BAND_5GHZ ? 0x54 : 0x4E;
- avg_rssi = mt76x02_phy_get_min_avg_rssi(&dev->mt76);
- if (avg_rssi > -60)
- init_vga -= 0x20;
- else if (avg_rssi > -70)
- init_vga -= 0x10;
-
- val = mt76_rr(dev, MT_BBP(AGC, 8));
- val &= 0xFFFF80FF;
- val |= init_vga << 8;
- mt76_wr(dev, MT_BBP(AGC,8), val);
+ u8 gain = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust;
+ u32 val = 0x122c << 16 | 0xf2;
+
+ mt76_wr(dev, MT_BBP(AGC, 8),
+ val | FIELD_PREP(MT_BBP_AGC_GAIN, gain));
+}
+
+static void
+mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev)
+{
+ bool gain_change;
+ u8 gain_delta;
+ int low_gain;
+
+ dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev);
+
+ low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
+ (dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
+
+ gain_change = (dev->cal.low_gain & 2) ^ (low_gain & 2);
+ dev->cal.low_gain = low_gain;
+
+ if (!gain_change) {
+ if (mt76x02_phy_adjust_vga_gain(dev))
+ mt76x0_phy_set_gain_val(dev);
+ return;
+ }
+
+ dev->cal.agc_gain_adjust = (low_gain == 2) ? 0 : 10;
+ gain_delta = (low_gain == 2) ? 10 : 0;
+
+ dev->cal.agc_gain_cur[0] = dev->cal.agc_gain_init[0] - gain_delta;
+ mt76x0_phy_set_gain_val(dev);
+
+ /* clear false CCA counters */
+ mt76_rr(dev, MT_RX_STAT_1);
}
-static void mt76x0_phy_calibrate(struct work_struct *work)
+static void mt76x0_phy_calibration_work(struct work_struct *work)
{
struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
cal_work.work);
- mt76x0_dynamic_vga_tuning(dev);
- mt76x0_temp_sensor(dev);
+ mt76x0_phy_update_channel_gain(dev);
+ if (!mt76x0_tssi_enabled(dev))
+ mt76x0_temp_sensor(dev);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
@@ -881,9 +922,9 @@ static void mt76x0_rf_init(struct mt76x02_dev *dev)
void mt76x0_phy_init(struct mt76x02_dev *dev)
{
- INIT_DELAYED_WORK(&dev->cal_work, mt76x0_phy_calibrate);
+ INIT_DELAYED_WORK(&dev->cal_work, mt76x0_phy_calibration_work);
mt76x0_rf_init(dev);
- mt76x02_phy_set_rxpath(&dev->mt76);
- mt76x02_phy_set_txdac(&dev->mt76);
+ mt76x02_phy_set_rxpath(dev);
+ mt76x02_phy_set_txdac(dev);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
index fb6fa1fa5548..a9f14d5149d1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
@@ -40,8 +40,7 @@ mt76x0u_upload_firmware(struct mt76x02_dev *dev,
ilm_len = le32_to_cpu(hdr->ilm_len) - MT_MCU_IVB_SIZE;
dev_dbg(dev->mt76.dev, "loading FW - ILM %u + IVB %u\n",
ilm_len, MT_MCU_IVB_SIZE);
- err = mt76x02u_mcu_fw_send_data(&dev->mt76,
- fw_payload + MT_MCU_IVB_SIZE,
+ err = mt76x02u_mcu_fw_send_data(dev, fw_payload + MT_MCU_IVB_SIZE,
ilm_len, MCU_FW_URB_MAX_PAYLOAD,
MT_MCU_IVB_SIZE);
if (err)
@@ -49,7 +48,7 @@ mt76x0u_upload_firmware(struct mt76x02_dev *dev,
dlm_len = le32_to_cpu(hdr->dlm_len);
dev_dbg(dev->mt76.dev, "loading FW - DLM %u\n", dlm_len);
- err = mt76x02u_mcu_fw_send_data(&dev->mt76,
+ err = mt76x02u_mcu_fw_send_data(dev,
fw_payload + le32_to_cpu(hdr->ilm_len),
dlm_len, MCU_FW_URB_MAX_PAYLOAD,
MT_MCU_DLM_OFFSET);
@@ -121,7 +120,7 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
mt76_set(dev, MT_USB_DMA_CFG,
(MT_USB_DMA_CFG_RX_BULK_EN | MT_USB_DMA_CFG_TX_BULK_EN) |
FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20));
- mt76x02u_mcu_fw_reset(&dev->mt76);
+ mt76x02u_mcu_fw_reset(dev);
usleep_range(5000, 6000);
/*
mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |