mt76 patches for 4.20
* unify code between mt76x0, mt76x2 * mt76x0 fixes * tx power configuration fix for 76x2 * more progress on mt76x0e support * support for getting firmware version via ethtool * fix for rx buffer allocation regression on usb * fix for handling powersave responses * fix for mt76x2 beacon transmission -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2 Comment: GPGTools - http://gpgtools.org iEYEABECAAYFAluyBLsACgkQ130UHQKnbvVy7wCeN1zcfGDCAZulOwND9+wO6P7d /ZEAoKPedreI+0u+DJ5w6H8cZR6THGxb =MYwe -----END PGP SIGNATURE----- Merge tag 'mt76-for-kvalo-2018-10-01' of https://github.com/nbd168/wireless mt76 patches for 4.20 * unify code between mt76x0, mt76x2 * mt76x0 fixes * tx power configuration fix for 76x2 * more progress on mt76x0e support * support for getting firmware version via ethtool * fix for rx buffer allocation regression on usb * fix for handling powersave responses * fix for mt76x2 beacon transmission
This commit is contained in:
commit
9434dca951
@ -15,7 +15,8 @@ mt76-usb-y := usb.o usb_trace.o usb_mcu.o
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
CFLAGS_usb_trace.o := -I$(src)
|
||||
|
||||
mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o
|
||||
mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \
|
||||
mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o
|
||||
|
||||
mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
|
||||
|
||||
|
@ -56,6 +56,35 @@ mt76_queues_read(struct seq_file *s, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt76_seq_puts_array(struct seq_file *file, const char *str,
|
||||
s8 *val, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
seq_printf(file, "%10s:", str);
|
||||
for (i = 0; i < len; i++)
|
||||
seq_printf(file, " %2d", val[i]);
|
||||
seq_puts(file, "\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_seq_puts_array);
|
||||
|
||||
static int mt76_read_rate_txpower(struct seq_file *s, void *data)
|
||||
{
|
||||
struct mt76_dev *dev = dev_get_drvdata(s->private);
|
||||
|
||||
mt76_seq_puts_array(s, "CCK", dev->rate_power.cck,
|
||||
ARRAY_SIZE(dev->rate_power.cck));
|
||||
mt76_seq_puts_array(s, "OFDM", dev->rate_power.ofdm,
|
||||
ARRAY_SIZE(dev->rate_power.ofdm));
|
||||
mt76_seq_puts_array(s, "STBC", dev->rate_power.stbc,
|
||||
ARRAY_SIZE(dev->rate_power.stbc));
|
||||
mt76_seq_puts_array(s, "HT", dev->rate_power.ht,
|
||||
ARRAY_SIZE(dev->rate_power.ht));
|
||||
mt76_seq_puts_array(s, "VHT", dev->rate_power.vht,
|
||||
ARRAY_SIZE(dev->rate_power.vht));
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
|
||||
{
|
||||
struct dentry *dir;
|
||||
@ -72,6 +101,8 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
|
||||
if (dev->otp.data)
|
||||
debugfs_create_blob("otp", 0400, dir, &dev->otp);
|
||||
debugfs_create_devm_seqfile(dev->dev, "queues", dir, mt76_queues_read);
|
||||
debugfs_create_devm_seqfile(dev->dev, "rate_txpower", dir,
|
||||
mt76_read_rate_txpower);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
@ -550,6 +550,12 @@ mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
struct mt76_wcid *wcid = status->wcid;
|
||||
bool ps;
|
||||
|
||||
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(dev->hw, hdr->addr2, NULL);
|
||||
if (sta)
|
||||
wcid = status->wcid = (struct mt76_wcid *) sta->drv_priv;
|
||||
}
|
||||
|
||||
if (!wcid || !wcid->sta)
|
||||
return;
|
||||
|
||||
|
@ -46,6 +46,30 @@ static void mt76_mmio_copy(struct mt76_dev *dev, u32 offset, const void *data,
|
||||
__iowrite32_copy(dev->mmio.regs + offset, data, len >> 2);
|
||||
}
|
||||
|
||||
static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base,
|
||||
const struct mt76_reg_pair *data, int len)
|
||||
{
|
||||
while (len > 0) {
|
||||
mt76_mmio_wr(dev, data->reg, data->value);
|
||||
data++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt76_mmio_rd_rp(struct mt76_dev *dev, u32 base,
|
||||
struct mt76_reg_pair *data, int len)
|
||||
{
|
||||
while (len > 0) {
|
||||
data->value = mt76_mmio_rr(dev, data->reg);
|
||||
data++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
|
||||
{
|
||||
static const struct mt76_bus_ops mt76_mmio_ops = {
|
||||
@ -53,6 +77,8 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
|
||||
.rmw = mt76_mmio_rmw,
|
||||
.wr = mt76_mmio_wr,
|
||||
.copy = mt76_mmio_copy,
|
||||
.wr_rp = mt76_mmio_wr_rp,
|
||||
.rd_rp = mt76_mmio_rd_rp,
|
||||
};
|
||||
|
||||
dev->bus = &mt76_mmio_ops;
|
||||
@ -60,6 +86,7 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
|
||||
|
||||
skb_queue_head_init(&dev->mmio.mcu.res_q);
|
||||
init_waitqueue_head(&dev->mmio.mcu.wait);
|
||||
spin_lock_init(&dev->mmio.irq_lock);
|
||||
mutex_init(&dev->mmio.mcu.mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_mmio_init);
|
||||
|
@ -122,6 +122,7 @@ struct mt76_queue {
|
||||
dma_addr_t desc_dma;
|
||||
struct sk_buff *rx_head;
|
||||
struct page_frag_cache rx_page;
|
||||
spinlock_t rx_page_lock;
|
||||
};
|
||||
|
||||
struct mt76_mcu_ops {
|
||||
@ -275,6 +276,19 @@ struct mt76_sband {
|
||||
struct mt76_channel_state *chan;
|
||||
};
|
||||
|
||||
struct mt76_rate_power {
|
||||
union {
|
||||
struct {
|
||||
s8 cck[4];
|
||||
s8 ofdm[8];
|
||||
s8 stbc[10];
|
||||
s8 ht[16];
|
||||
s8 vht[10];
|
||||
};
|
||||
s8 all[48];
|
||||
};
|
||||
};
|
||||
|
||||
/* addr req mask */
|
||||
#define MT_VEND_TYPE_EEPROM BIT(31)
|
||||
#define MT_VEND_TYPE_CFG BIT(30)
|
||||
@ -349,6 +363,8 @@ struct mt76_mmio {
|
||||
u32 msg_seq;
|
||||
} mcu;
|
||||
void __iomem *regs;
|
||||
spinlock_t irq_lock;
|
||||
u32 irqmask;
|
||||
};
|
||||
|
||||
struct mt76_dev {
|
||||
@ -388,6 +404,7 @@ struct mt76_dev {
|
||||
unsigned long state;
|
||||
|
||||
u8 antenna_mask;
|
||||
u16 chainmask;
|
||||
|
||||
struct mt76_sband sband_2g;
|
||||
struct mt76_sband sband_5g;
|
||||
@ -395,6 +412,10 @@ struct mt76_dev {
|
||||
struct debugfs_blob_wrapper otp;
|
||||
struct mt76_hw_cap cap;
|
||||
|
||||
struct mt76_rate_power rate_power;
|
||||
int txpower_conf;
|
||||
int txpower_cur;
|
||||
|
||||
u32 debugfs_reg;
|
||||
|
||||
struct led_classdev led_cdev;
|
||||
@ -418,18 +439,6 @@ enum mt76_phy_type {
|
||||
MT_PHY_TYPE_VHT,
|
||||
};
|
||||
|
||||
struct mt76_rate_power {
|
||||
union {
|
||||
struct {
|
||||
s8 cck[4];
|
||||
s8 ofdm[8];
|
||||
s8 ht[16];
|
||||
s8 vht[10];
|
||||
};
|
||||
s8 all[38];
|
||||
};
|
||||
};
|
||||
|
||||
struct mt76_rx_status {
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
@ -510,8 +519,8 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
|
||||
#define mt76xx_chip(dev) mt76_chip(&((dev)->mt76))
|
||||
#define mt76xx_rev(dev) mt76_rev(&((dev)->mt76))
|
||||
|
||||
#define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76))
|
||||
#define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__)
|
||||
#define __mt76_init_queues(dev) (dev)->queue_ops->init((dev))
|
||||
#define __mt76_queue_alloc(dev, ...) (dev)->queue_ops->alloc((dev), __VA_ARGS__)
|
||||
#define mt76_queue_add_buf(dev, ...) (dev)->mt76.queue_ops->add_buf(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
|
||||
@ -539,6 +548,8 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
void mt76_unregister_device(struct mt76_dev *dev);
|
||||
|
||||
struct dentry *mt76_register_debugfs(struct mt76_dev *dev);
|
||||
void mt76_seq_puts_array(struct seq_file *file, const char *str,
|
||||
s8 *val, int len);
|
||||
|
||||
int mt76_eeprom_init(struct mt76_dev *dev, int len);
|
||||
void mt76_eeprom_override(struct mt76_dev *dev);
|
||||
|
@ -5,8 +5,8 @@ obj-$(CONFIG_MT76x0_COMMON) += mt76x0-common.o
|
||||
mt76x0-common-y := \
|
||||
init.o main.o trace.o eeprom.o phy.o \
|
||||
mac.o debugfs.o tx.o
|
||||
mt76x0u-y := usb.o
|
||||
mt76x0e-y := pci.o
|
||||
mt76x0u-y := usb.o usb_mcu.o
|
||||
mt76x0e-y := pci.o pci_mcu.o
|
||||
|
||||
# ccflags-y := -DDEBUG
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
@ -18,26 +18,6 @@
|
||||
#include "mt76x0.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
static int
|
||||
mt76_reg_set(void *data, u64 val)
|
||||
{
|
||||
struct mt76x0_dev *dev = data;
|
||||
|
||||
mt76_wr(dev, dev->debugfs_reg, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_reg_get(void *data, u64 *val)
|
||||
{
|
||||
struct mt76x0_dev *dev = data;
|
||||
|
||||
*val = mt76_rr(dev, dev->debugfs_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n");
|
||||
|
||||
static int
|
||||
mt76x0_ampdu_stat_read(struct seq_file *file, void *data)
|
||||
{
|
||||
@ -95,72 +75,13 @@ static const struct file_operations fops_ampdu_stat = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int
|
||||
mt76x0_eeprom_param_read(struct seq_file *file, void *data)
|
||||
{
|
||||
struct mt76x0_dev *dev = file->private;
|
||||
int i;
|
||||
|
||||
seq_printf(file, "RF freq offset: %hhx\n", dev->ee->rf_freq_off);
|
||||
seq_printf(file, "RSSI offset 2GHz: %hhx %hhx\n",
|
||||
dev->ee->rssi_offset_2ghz[0], dev->ee->rssi_offset_2ghz[1]);
|
||||
seq_printf(file, "RSSI offset 5GHz: %hhx %hhx %hhx\n",
|
||||
dev->ee->rssi_offset_5ghz[0], dev->ee->rssi_offset_5ghz[1],
|
||||
dev->ee->rssi_offset_5ghz[2]);
|
||||
seq_printf(file, "Temperature offset: %hhx\n", dev->ee->temp_off);
|
||||
seq_printf(file, "LNA gain 2Ghz: %hhx\n", dev->ee->lna_gain_2ghz);
|
||||
seq_printf(file, "LNA gain 5Ghz: %hhx %hhx %hhx\n",
|
||||
dev->ee->lna_gain_5ghz[0], dev->ee->lna_gain_5ghz[1],
|
||||
dev->ee->lna_gain_5ghz[2]);
|
||||
seq_printf(file, "Power Amplifier type %hhx\n", dev->ee->pa_type);
|
||||
seq_printf(file, "Reg channels: %hhu-%hhu\n", dev->ee->reg.start,
|
||||
dev->ee->reg.start + dev->ee->reg.num - 1);
|
||||
|
||||
seq_puts(file, "Per channel power:\n");
|
||||
for (i = 0; i < 58; i++)
|
||||
seq_printf(file, "\t%d chan:%d pwr:%d\n", i, i,
|
||||
dev->ee->tx_pwr_per_chan[i]);
|
||||
|
||||
seq_puts(file, "Per rate power 2GHz:\n");
|
||||
for (i = 0; i < 5; i++)
|
||||
seq_printf(file, "\t %d bw20:%d bw40:%d\n",
|
||||
i, dev->ee->tx_pwr_cfg_2g[i][0],
|
||||
dev->ee->tx_pwr_cfg_5g[i][1]);
|
||||
|
||||
seq_puts(file, "Per rate power 5GHz:\n");
|
||||
for (i = 0; i < 5; i++)
|
||||
seq_printf(file, "\t %d bw20:%d bw40:%d\n",
|
||||
i, dev->ee->tx_pwr_cfg_5g[i][0],
|
||||
dev->ee->tx_pwr_cfg_5g[i][1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x0_eeprom_param_open(struct inode *inode, struct file *f)
|
||||
{
|
||||
return single_open(f, mt76x0_eeprom_param_read, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_eeprom_param = {
|
||||
.open = mt76x0_eeprom_param_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void mt76x0_init_debugfs(struct mt76x0_dev *dev)
|
||||
{
|
||||
struct dentry *dir;
|
||||
|
||||
dir = debugfs_create_dir("mt76x0", dev->mt76.hw->wiphy->debugfsdir);
|
||||
dir = mt76_register_debugfs(&dev->mt76);
|
||||
if (!dir)
|
||||
return;
|
||||
|
||||
debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg);
|
||||
debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev,
|
||||
&fops_regval);
|
||||
debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
|
||||
debugfs_create_file("eeprom_param", S_IRUSR, dir, dev,
|
||||
&fops_eeprom_param);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
@ -20,66 +21,7 @@
|
||||
#include <asm/unaligned.h>
|
||||
#include "mt76x0.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
static bool
|
||||
field_valid(u8 val)
|
||||
{
|
||||
return val != 0xff;
|
||||
}
|
||||
|
||||
static s8
|
||||
field_validate(u8 val)
|
||||
{
|
||||
if (!field_valid(val))
|
||||
return 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline int
|
||||
sign_extend(u32 val, unsigned int size)
|
||||
{
|
||||
bool sign = val & BIT(size - 1);
|
||||
|
||||
val &= BIT(size - 1) - 1;
|
||||
|
||||
return sign ? val : -val;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x0_efuse_read(struct mt76x0_dev *dev, u16 addr, u8 *data,
|
||||
enum mt76x0_eeprom_access_modes mode)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
val = mt76_rr(dev, MT_EFUSE_CTRL);
|
||||
val &= ~(MT_EFUSE_CTRL_AIN |
|
||||
MT_EFUSE_CTRL_MODE);
|
||||
val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf) |
|
||||
FIELD_PREP(MT_EFUSE_CTRL_MODE, mode) |
|
||||
MT_EFUSE_CTRL_KICK;
|
||||
mt76_wr(dev, MT_EFUSE_CTRL, val);
|
||||
|
||||
if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
val = mt76_rr(dev, MT_EFUSE_CTRL);
|
||||
if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
|
||||
/* Parts of eeprom not in the usage map (0x80-0xc0,0xf0)
|
||||
* will not return valid data but it's ok.
|
||||
*/
|
||||
memset(data, 0xff, 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val = mt76_rr(dev, MT_EFUSE_DATA(i));
|
||||
put_unaligned_le32(val, data + 4 * i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#include "../mt76x02_phy.h"
|
||||
|
||||
#define MT_MAP_READS DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16)
|
||||
static int
|
||||
@ -89,12 +31,10 @@ mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev)
|
||||
int ret, i;
|
||||
u32 start = 0, end = 0, cnt_free;
|
||||
|
||||
for (i = 0; i < MT_MAP_READS; i++) {
|
||||
ret = mt76x0_efuse_read(dev, MT_EE_USAGE_MAP_START + i * 16,
|
||||
data + i * 16, MT_EE_PHYSICAL_READ);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = mt76x02_get_efuse_data(&dev->mt76, MT_EE_USAGE_MAP_START,
|
||||
data, sizeof(data), MT_EE_PHYSICAL_READ);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < MT_EFUSE_USAGE_MAP_SIZE; i++)
|
||||
if (!data[i]) {
|
||||
@ -105,345 +45,307 @@ mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev)
|
||||
cnt_free = end - start + 1;
|
||||
|
||||
if (MT_EFUSE_USAGE_MAP_SIZE - cnt_free < 5) {
|
||||
dev_err(dev->mt76.dev, "Error: your device needs default EEPROM file and this driver doesn't support it!\n");
|
||||
dev_err(dev->mt76.dev,
|
||||
"driver does not support default EEPROM\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_chip_cap(struct mt76x0_dev *dev, u8 *eeprom)
|
||||
static void mt76x0_set_chip_cap(struct mt76x0_dev *dev)
|
||||
{
|
||||
enum mt76x2_board_type { BOARD_TYPE_2GHZ = 1, BOARD_TYPE_5GHZ = 2 };
|
||||
u16 nic_conf0 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_0);
|
||||
u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
|
||||
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);
|
||||
|
||||
dev_dbg(dev->mt76.dev, "NIC_CONF0: %04x NIC_CONF1: %04x\n", nic_conf0, nic_conf1);
|
||||
|
||||
switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, nic_conf0)) {
|
||||
case BOARD_TYPE_5GHZ:
|
||||
dev->mt76.cap.has_5ghz = true;
|
||||
break;
|
||||
case BOARD_TYPE_2GHZ:
|
||||
dev->mt76.cap.has_2ghz = true;
|
||||
break;
|
||||
default:
|
||||
dev->mt76.cap.has_2ghz = true;
|
||||
dev->mt76.cap.has_5ghz = true;
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(dev->mt76.dev, "Has 2GHZ %d 5GHZ %d\n",
|
||||
mt76x02_eeprom_parse_hw_cap(&dev->mt76);
|
||||
dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n",
|
||||
dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz);
|
||||
|
||||
if (!field_valid(nic_conf1 & 0xff))
|
||||
if (dev->no_2ghz) {
|
||||
dev->mt76.cap.has_2ghz = false;
|
||||
dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");
|
||||
}
|
||||
|
||||
if (!mt76x02_field_valid(nic_conf1 & 0xff))
|
||||
nic_conf1 &= 0xff00;
|
||||
|
||||
if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL)
|
||||
dev_err(dev->mt76.dev,
|
||||
"Error: this driver does not support HW RF ctrl\n");
|
||||
"driver does not support HW RF ctrl\n");
|
||||
|
||||
if (!field_valid(nic_conf0 >> 8))
|
||||
if (!mt76x02_field_valid(nic_conf0 >> 8))
|
||||
return;
|
||||
|
||||
if (FIELD_GET(MT_EE_NIC_CONF_0_RX_PATH, nic_conf0) > 1 ||
|
||||
FIELD_GET(MT_EE_NIC_CONF_0_TX_PATH, nic_conf0) > 1)
|
||||
dev_err(dev->mt76.dev,
|
||||
"Error: device has more than 1 RX/TX stream!\n");
|
||||
|
||||
dev->ee->pa_type = FIELD_GET(MT_EE_NIC_CONF_0_PA_TYPE, nic_conf0);
|
||||
dev_dbg(dev->mt76.dev, "PA Type %d\n", dev->ee->pa_type);
|
||||
dev_err(dev->mt76.dev, "invalid tx-rx stream\n");
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x0_set_macaddr(struct mt76x0_dev *dev, const u8 *eeprom)
|
||||
static void mt76x0_set_temp_offset(struct mt76x0_dev *dev)
|
||||
{
|
||||
const void *src = eeprom + MT_EE_MAC_ADDR;
|
||||
u8 *dst = dev->mt76.macaddr;
|
||||
u8 val;
|
||||
|
||||
ether_addr_copy(dev->mt76.macaddr, src);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_2G_TARGET_POWER) >> 8;
|
||||
if (mt76x02_field_valid(val))
|
||||
dev->caldata.temp_offset = mt76x02_sign_extend(val, 8);
|
||||
else
|
||||
dev->caldata.temp_offset = -10;
|
||||
}
|
||||
|
||||
if (!is_valid_ether_addr(dst)) {
|
||||
eth_random_addr(dst);
|
||||
dev_info(dev->mt76.dev,
|
||||
"Invalid MAC address, using random address %pM\n",
|
||||
dst);
|
||||
static void mt76x0_set_freq_offset(struct mt76x0_dev *dev)
|
||||
{
|
||||
struct mt76x0_caldata *caldata = &dev->caldata;
|
||||
u8 val;
|
||||
|
||||
val = mt76x02_eeprom_get(&dev->mt76, 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;
|
||||
if (!mt76x02_field_valid(val))
|
||||
val = 0;
|
||||
|
||||
caldata->freq_offset -= mt76x02_sign_extend(val, 8);
|
||||
}
|
||||
|
||||
void mt76x0_read_rx_gain(struct mt76x0_dev *dev)
|
||||
{
|
||||
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
|
||||
struct mt76x0_caldata *caldata = &dev->caldata;
|
||||
s8 val, lna_5g[3], lna_2g;
|
||||
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);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(caldata->rssi_offset); i++) {
|
||||
val = rssi_offset >> (8 * i);
|
||||
if (val < -10 || val > 10)
|
||||
val = 0;
|
||||
|
||||
caldata->rssi_offset[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
static s8 mt76x0_get_delta(struct mt76_dev *dev)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &dev->chandef;
|
||||
u8 val;
|
||||
|
||||
if (mt76x02_tssi_enabled(dev))
|
||||
return 0;
|
||||
|
||||
if (chandef->width == NL80211_CHAN_WIDTH_80) {
|
||||
val = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER) >> 8;
|
||||
} else if (chandef->width == NL80211_CHAN_WIDTH_40) {
|
||||
u16 data;
|
||||
|
||||
data = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
|
||||
if (chandef->chan->band == NL80211_BAND_5GHZ)
|
||||
val = data >> 8;
|
||||
else
|
||||
val = data;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dst));
|
||||
mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dst + 4) |
|
||||
FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
|
||||
return mt76x02_rate_power_val(val);
|
||||
}
|
||||
|
||||
void mt76x0_get_tx_power_per_rate(struct mt76x0_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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
t->vht[7] = s6_to_s8(val);
|
||||
t->vht[8] = s6_to_s8(val >> 8);
|
||||
|
||||
mt76x02_add_rate_power_offset(t, delta);
|
||||
}
|
||||
|
||||
void mt76x0_get_power_info(struct mt76x0_dev *dev, u8 *info)
|
||||
{
|
||||
struct mt76x0_chan_map {
|
||||
u8 chan;
|
||||
u8 offset;
|
||||
} chan_map[] = {
|
||||
{ 2, 0 }, { 4, 1 }, { 6, 2 }, { 8, 3 },
|
||||
{ 10, 4 }, { 12, 5 }, { 14, 6 }, { 38, 0 },
|
||||
{ 44, 1 }, { 48, 2 }, { 54, 3 }, { 60, 4 },
|
||||
{ 64, 5 }, { 102, 6 }, { 108, 7 }, { 112, 8 },
|
||||
{ 118, 9 }, { 124, 10 }, { 128, 11 }, { 134, 12 },
|
||||
{ 140, 13 }, { 151, 14 }, { 157, 15 }, { 161, 16 },
|
||||
{ 167, 17 }, { 171, 18 }, { 173, 19 },
|
||||
};
|
||||
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
|
||||
u8 offset, addr;
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
|
||||
if (chan_map[i].chan <= chan->hw_value) {
|
||||
offset = chan_map[i].offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(chan_map))
|
||||
offset = chan_map[0].offset;
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ) {
|
||||
addr = MT_EE_TX_POWER_DELTA_BW80 + offset;
|
||||
} else {
|
||||
switch (chan->hw_value) {
|
||||
case 58:
|
||||
offset = 8;
|
||||
break;
|
||||
case 106:
|
||||
offset = 14;
|
||||
break;
|
||||
case 112:
|
||||
offset = 20;
|
||||
break;
|
||||
case 155:
|
||||
offset = 30;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
addr = MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE + 2 + offset;
|
||||
}
|
||||
|
||||
data = mt76x02_eeprom_get(&dev->mt76, addr);
|
||||
|
||||
info[0] = data;
|
||||
if (!info[0] || info[0] > 0x3f)
|
||||
info[0] = 5;
|
||||
|
||||
info[1] = data >> 8;
|
||||
if (!info[1] || info[1] > 0x3f)
|
||||
info[1] = 5;
|
||||
}
|
||||
|
||||
static int mt76x0_check_eeprom(struct mt76x0_dev *dev)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
val = get_unaligned_le16(dev->mt76.eeprom.data);
|
||||
if (!val)
|
||||
val = get_unaligned_le16(dev->mt76.eeprom.data +
|
||||
MT_EE_PCI_ID);
|
||||
|
||||
switch (val) {
|
||||
case 0x7650:
|
||||
case 0x7610:
|
||||
return 0;
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "EEPROM data check failed: %04x\n",
|
||||
val);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int mt76x0_load_eeprom(struct mt76x0_dev *dev)
|
||||
{
|
||||
int found;
|
||||
|
||||
found = mt76_eeprom_init(&dev->mt76, MT76X0_EEPROM_SIZE);
|
||||
if (found < 0)
|
||||
return found;
|
||||
|
||||
if (found && !mt76x0_check_eeprom(dev))
|
||||
return 0;
|
||||
|
||||
found = mt76x0_efuse_physical_size_check(dev);
|
||||
if (found < 0)
|
||||
return found;
|
||||
|
||||
return mt76x02_get_efuse_data(&dev->mt76, 0, dev->mt76.eeprom.data,
|
||||
MT76X0_EEPROM_SIZE, MT_EE_READ);
|
||||
}
|
||||
|
||||
int mt76x0_eeprom_init(struct mt76x0_dev *dev)
|
||||
{
|
||||
u8 version, fae;
|
||||
u16 data;
|
||||
int err;
|
||||
|
||||
err = mt76x0_load_eeprom(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
data = mt76x02_eeprom_get(&dev->mt76, MT_EE_VERSION);
|
||||
version = data >> 8;
|
||||
fae = data;
|
||||
|
||||
if (version > MT76X0U_EE_MAX_VER)
|
||||
dev_warn(dev->mt76.dev,
|
||||
"Warning: unsupported EEPROM version %02hhx\n",
|
||||
version);
|
||||
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);
|
||||
mt76x0_set_chip_cap(dev);
|
||||
mt76x0_set_freq_offset(dev);
|
||||
mt76x0_set_temp_offset(dev);
|
||||
|
||||
dev->mt76.chainmask = 0x0101;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_temp_offset(struct mt76x0_dev *dev, u8 *eeprom)
|
||||
{
|
||||
u8 temp = eeprom[MT_EE_TEMP_OFFSET];
|
||||
|
||||
if (field_valid(temp))
|
||||
dev->ee->temp_off = sign_extend(temp, 8);
|
||||
else
|
||||
dev->ee->temp_off = -10;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_country_reg(struct mt76x0_dev *dev, u8 *eeprom)
|
||||
{
|
||||
/* Note: - region 31 is not valid for mt76x0 (see rtmp_init.c)
|
||||
* - comments in rtmp_def.h are incorrect (see rt_channel.c)
|
||||
*/
|
||||
static const struct reg_channel_bounds chan_bounds[] = {
|
||||
/* EEPROM country regions 0 - 7 */
|
||||
{ 1, 11 }, { 1, 13 }, { 10, 2 }, { 10, 4 },
|
||||
{ 14, 1 }, { 1, 14 }, { 3, 7 }, { 5, 9 },
|
||||
/* EEPROM country regions 32 - 33 */
|
||||
{ 1, 11 }, { 1, 14 }
|
||||
};
|
||||
u8 val = eeprom[MT_EE_COUNTRY_REGION_2GHZ];
|
||||
int idx = -1;
|
||||
|
||||
dev_dbg(dev->mt76.dev, "REG 2GHZ %u REG 5GHZ %u\n", val, eeprom[MT_EE_COUNTRY_REGION_5GHZ]);
|
||||
if (val < 8)
|
||||
idx = val;
|
||||
if (val > 31 && val < 33)
|
||||
idx = val - 32 + 8;
|
||||
|
||||
if (idx != -1)
|
||||
dev_info(dev->mt76.dev,
|
||||
"EEPROM country region %02hhx (channels %hhd-%hhd)\n",
|
||||
val, chan_bounds[idx].start,
|
||||
chan_bounds[idx].start + chan_bounds[idx].num - 1);
|
||||
else
|
||||
idx = 5; /* channels 1 - 14 */
|
||||
|
||||
dev->ee->reg = chan_bounds[idx];
|
||||
|
||||
/* TODO: country region 33 is special - phy should be set to B-mode
|
||||
* before entering channel 14 (see sta/connect.c)
|
||||
*/
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_rf_freq_off(struct mt76x0_dev *dev, u8 *eeprom)
|
||||
{
|
||||
u8 comp;
|
||||
|
||||
dev->ee->rf_freq_off = field_validate(eeprom[MT_EE_FREQ_OFFSET]);
|
||||
comp = field_validate(eeprom[MT_EE_FREQ_OFFSET_COMPENSATION]);
|
||||
|
||||
if (comp & BIT(7))
|
||||
dev->ee->rf_freq_off -= comp & 0x7f;
|
||||
else
|
||||
dev->ee->rf_freq_off += comp;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_lna_gain(struct mt76x0_dev *dev, u8 *eeprom)
|
||||
{
|
||||
u8 gain;
|
||||
|
||||
dev->ee->lna_gain_2ghz = eeprom[MT_EE_LNA_GAIN_2GHZ];
|
||||
dev->ee->lna_gain_5ghz[0] = eeprom[MT_EE_LNA_GAIN_5GHZ_0];
|
||||
|
||||
gain = eeprom[MT_EE_LNA_GAIN_5GHZ_1];
|
||||
if (gain == 0xff || gain == 0)
|
||||
dev->ee->lna_gain_5ghz[1] = dev->ee->lna_gain_5ghz[0];
|
||||
else
|
||||
dev->ee->lna_gain_5ghz[1] = gain;
|
||||
|
||||
gain = eeprom[MT_EE_LNA_GAIN_5GHZ_2];
|
||||
if (gain == 0xff || gain == 0)
|
||||
dev->ee->lna_gain_5ghz[2] = dev->ee->lna_gain_5ghz[0];
|
||||
else
|
||||
dev->ee->lna_gain_5ghz[2] = gain;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_rssi_offset(struct mt76x0_dev *dev, u8 *eeprom)
|
||||
{
|
||||
int i;
|
||||
s8 *rssi_offset = dev->ee->rssi_offset_2ghz;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET + i];
|
||||
|
||||
if (rssi_offset[i] < -10 || rssi_offset[i] > 10) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"Warning: EEPROM RSSI is invalid %02hhx\n",
|
||||
rssi_offset[i]);
|
||||
rssi_offset[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rssi_offset = dev->ee->rssi_offset_5ghz;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET_5GHZ + i];
|
||||
|
||||
if (rssi_offset[i] < -10 || rssi_offset[i] > 10) {
|
||||
dev_warn(dev->mt76.dev,
|
||||
"Warning: EEPROM RSSI is invalid %02hhx\n",
|
||||
rssi_offset[i]);
|
||||
rssi_offset[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u32
|
||||
calc_bw40_power_rate(u32 value, int delta)
|
||||
{
|
||||
u32 ret = 0;
|
||||
int i, tmp;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
tmp = s6_to_int((value >> i*8) & 0xff) + delta;
|
||||
ret |= (u32)(int_to_s6(tmp)) << i*8;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static s8
|
||||
get_delta(u8 val)
|
||||
{
|
||||
s8 ret;
|
||||
|
||||
if (!field_valid(val) || !(val & BIT(7)))
|
||||
return 0;
|
||||
|
||||
ret = val & 0x1f;
|
||||
if (ret > 8)
|
||||
ret = 8;
|
||||
if (val & BIT(6))
|
||||
ret = -ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_tx_power_per_rate(struct mt76x0_dev *dev, u8 *eeprom)
|
||||
{
|
||||
s8 bw40_delta_2g, bw40_delta_5g;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
bw40_delta_2g = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40]);
|
||||
bw40_delta_5g = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40 + 1]);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
val = get_unaligned_le32(eeprom + MT_EE_TX_POWER_BYRATE(i));
|
||||
|
||||
/* Skip last 16 bits. */
|
||||
if (i == 4)
|
||||
val &= 0x0000ffff;
|
||||
|
||||
dev->ee->tx_pwr_cfg_2g[i][0] = val;
|
||||
dev->ee->tx_pwr_cfg_2g[i][1] = calc_bw40_power_rate(val, bw40_delta_2g);
|
||||
}
|
||||
|
||||
/* Reading per rate tx power for 5 GHz band is a bit more complex. Note
|
||||
* we mix 16 bit and 32 bit reads and sometimes do shifts.
|
||||
*/
|
||||
val = get_unaligned_le16(eeprom + 0x120);
|
||||
val <<= 16;
|
||||
dev->ee->tx_pwr_cfg_5g[0][0] = val;
|
||||
dev->ee->tx_pwr_cfg_5g[0][1] = calc_bw40_power_rate(val, bw40_delta_5g);
|
||||
|
||||
val = get_unaligned_le32(eeprom + 0x122);
|
||||
dev->ee->tx_pwr_cfg_5g[1][0] = val;
|
||||
dev->ee->tx_pwr_cfg_5g[1][1] = calc_bw40_power_rate(val, bw40_delta_5g);
|
||||
|
||||
val = get_unaligned_le16(eeprom + 0x126);
|
||||
dev->ee->tx_pwr_cfg_5g[2][0] = val;
|
||||
dev->ee->tx_pwr_cfg_5g[2][1] = calc_bw40_power_rate(val, bw40_delta_5g);
|
||||
|
||||
val = get_unaligned_le16(eeprom + 0xec);
|
||||
val <<= 16;
|
||||
dev->ee->tx_pwr_cfg_5g[3][0] = val;
|
||||
dev->ee->tx_pwr_cfg_5g[3][1] = calc_bw40_power_rate(val, bw40_delta_5g);
|
||||
|
||||
val = get_unaligned_le16(eeprom + 0xee);
|
||||
dev->ee->tx_pwr_cfg_5g[4][0] = val;
|
||||
dev->ee->tx_pwr_cfg_5g[4][1] = calc_bw40_power_rate(val, bw40_delta_5g);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_tx_power_per_chan(struct mt76x0_dev *dev, u8 *eeprom)
|
||||
{
|
||||
int i;
|
||||
u8 tx_pwr;
|
||||
|
||||
for (i = 0; i < 14; i++) {
|
||||
tx_pwr = eeprom[MT_EE_TX_POWER_OFFSET_2GHZ + i];
|
||||
if (tx_pwr <= 0x3f && tx_pwr > 0)
|
||||
dev->ee->tx_pwr_per_chan[i] = tx_pwr;
|
||||
else
|
||||
dev->ee->tx_pwr_per_chan[i] = 5;
|
||||
}
|
||||
|
||||
for (i = 0; i < 40; i++) {
|
||||
tx_pwr = eeprom[MT_EE_TX_POWER_OFFSET_5GHZ + i];
|
||||
if (tx_pwr <= 0x3f && tx_pwr > 0)
|
||||
dev->ee->tx_pwr_per_chan[14 + i] = tx_pwr;
|
||||
else
|
||||
dev->ee->tx_pwr_per_chan[14 + i] = 5;
|
||||
}
|
||||
|
||||
dev->ee->tx_pwr_per_chan[54] = dev->ee->tx_pwr_per_chan[22];
|
||||
dev->ee->tx_pwr_per_chan[55] = dev->ee->tx_pwr_per_chan[28];
|
||||
dev->ee->tx_pwr_per_chan[56] = dev->ee->tx_pwr_per_chan[34];
|
||||
dev->ee->tx_pwr_per_chan[57] = dev->ee->tx_pwr_per_chan[44];
|
||||
}
|
||||
|
||||
int
|
||||
mt76x0_eeprom_init(struct mt76x0_dev *dev)
|
||||
{
|
||||
u8 *eeprom;
|
||||
int i, ret;
|
||||
|
||||
ret = mt76x0_efuse_physical_size_check(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->ee = devm_kzalloc(dev->mt76.dev, sizeof(*dev->ee), GFP_KERNEL);
|
||||
if (!dev->ee)
|
||||
return -ENOMEM;
|
||||
|
||||
eeprom = kmalloc(MT76X0_EEPROM_SIZE, GFP_KERNEL);
|
||||
if (!eeprom)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i + 16 <= MT76X0_EEPROM_SIZE; i += 16) {
|
||||
ret = mt76x0_efuse_read(dev, i, eeprom + i, MT_EE_READ);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (eeprom[MT_EE_VERSION_EE] > MT76X0U_EE_MAX_VER)
|
||||
dev_warn(dev->mt76.dev,
|
||||
"Warning: unsupported EEPROM version %02hhx\n",
|
||||
eeprom[MT_EE_VERSION_EE]);
|
||||
dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n",
|
||||
eeprom[MT_EE_VERSION_EE], eeprom[MT_EE_VERSION_FAE]);
|
||||
|
||||
mt76x0_set_macaddr(dev, eeprom);
|
||||
mt76x0_set_chip_cap(dev, eeprom);
|
||||
mt76x0_set_country_reg(dev, eeprom);
|
||||
mt76x0_set_rf_freq_off(dev, eeprom);
|
||||
mt76x0_set_temp_offset(dev, eeprom);
|
||||
mt76x0_set_lna_gain(dev, eeprom);
|
||||
mt76x0_set_rssi_offset(dev, eeprom);
|
||||
dev->chainmask = 0x0101;
|
||||
|
||||
mt76x0_set_tx_power_per_rate(dev, eeprom);
|
||||
mt76x0_set_tx_power_per_chan(dev, eeprom);
|
||||
|
||||
out:
|
||||
kfree(eeprom);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
@ -16,131 +16,33 @@
|
||||
#ifndef __MT76X0U_EEPROM_H
|
||||
#define __MT76X0U_EEPROM_H
|
||||
|
||||
#include "../mt76x02_eeprom.h"
|
||||
|
||||
struct mt76x0_dev;
|
||||
|
||||
#define MT76X0U_EE_MAX_VER 0x0c
|
||||
#define MT76X0_EEPROM_SIZE 512
|
||||
#define MT76X0U_EE_MAX_VER 0x0c
|
||||
#define MT76X0_EEPROM_SIZE 512
|
||||
|
||||
#define MT76X0U_DEFAULT_TX_POWER 6
|
||||
struct mt76x0_caldata {
|
||||
s8 rssi_offset[2];
|
||||
s8 lna_gain;
|
||||
|
||||
enum mt76_eeprom_field {
|
||||
MT_EE_CHIP_ID = 0x00,
|
||||
MT_EE_VERSION_FAE = 0x02,
|
||||
MT_EE_VERSION_EE = 0x03,
|
||||
MT_EE_MAC_ADDR = 0x04,
|
||||
MT_EE_NIC_CONF_0 = 0x34,
|
||||
MT_EE_NIC_CONF_1 = 0x36,
|
||||
MT_EE_COUNTRY_REGION_5GHZ = 0x38,
|
||||
MT_EE_COUNTRY_REGION_2GHZ = 0x39,
|
||||
MT_EE_FREQ_OFFSET = 0x3a,
|
||||
MT_EE_NIC_CONF_2 = 0x42,
|
||||
|
||||
MT_EE_LNA_GAIN_2GHZ = 0x44,
|
||||
MT_EE_LNA_GAIN_5GHZ_0 = 0x45,
|
||||
MT_EE_RSSI_OFFSET = 0x46,
|
||||
MT_EE_RSSI_OFFSET_5GHZ = 0x4a,
|
||||
MT_EE_LNA_GAIN_5GHZ_1 = 0x49,
|
||||
MT_EE_LNA_GAIN_5GHZ_2 = 0x4d,
|
||||
|
||||
MT_EE_TX_POWER_DELTA_BW40 = 0x50,
|
||||
|
||||
MT_EE_TX_POWER_OFFSET_2GHZ = 0x52,
|
||||
|
||||
MT_EE_TX_TSSI_SLOPE = 0x6e,
|
||||
MT_EE_TX_TSSI_OFFSET_GROUP = 0x6f,
|
||||
MT_EE_TX_TSSI_OFFSET = 0x76,
|
||||
|
||||
MT_EE_TX_POWER_OFFSET_5GHZ = 0x78,
|
||||
|
||||
MT_EE_TEMP_OFFSET = 0xd1,
|
||||
MT_EE_FREQ_OFFSET_COMPENSATION = 0xdb,
|
||||
MT_EE_TX_POWER_BYRATE_BASE = 0xde,
|
||||
|
||||
MT_EE_TX_POWER_BYRATE_BASE_5GHZ = 0x120,
|
||||
|
||||
MT_EE_USAGE_MAP_START = 0x1e0,
|
||||
MT_EE_USAGE_MAP_END = 0x1fc,
|
||||
};
|
||||
|
||||
#define MT_EE_NIC_CONF_0_RX_PATH GENMASK(3, 0)
|
||||
#define MT_EE_NIC_CONF_0_TX_PATH GENMASK(7, 4)
|
||||
#define MT_EE_NIC_CONF_0_PA_TYPE GENMASK(9, 8)
|
||||
#define MT_EE_NIC_CONF_0_BOARD_TYPE GENMASK(13, 12)
|
||||
|
||||
#define MT_EE_NIC_CONF_1_HW_RF_CTRL BIT(0)
|
||||
#define MT_EE_NIC_CONF_1_TEMP_TX_ALC BIT(1)
|
||||
#define MT_EE_NIC_CONF_1_LNA_EXT_2G BIT(2)
|
||||
#define MT_EE_NIC_CONF_1_LNA_EXT_5G BIT(3)
|
||||
#define MT_EE_NIC_CONF_1_TX_ALC_EN BIT(13)
|
||||
|
||||
#define MT_EE_NIC_CONF_2_RX_STREAM GENMASK(3, 0)
|
||||
#define MT_EE_NIC_CONF_2_TX_STREAM GENMASK(7, 4)
|
||||
#define MT_EE_NIC_CONF_2_HW_ANTDIV BIT(8)
|
||||
#define MT_EE_NIC_CONF_2_XTAL_OPTION GENMASK(10, 9)
|
||||
#define MT_EE_NIC_CONF_2_TEMP_DISABLE BIT(11)
|
||||
#define MT_EE_NIC_CONF_2_COEX_METHOD GENMASK(15, 13)
|
||||
|
||||
#define MT_EE_TX_POWER_BYRATE(i) (MT_EE_TX_POWER_BYRATE_BASE + \
|
||||
(i) * 4)
|
||||
|
||||
#define MT_EFUSE_USAGE_MAP_SIZE (MT_EE_USAGE_MAP_END - \
|
||||
MT_EE_USAGE_MAP_START + 1)
|
||||
|
||||
enum mt76x0_eeprom_access_modes {
|
||||
MT_EE_READ = 0,
|
||||
MT_EE_PHYSICAL_READ = 1,
|
||||
};
|
||||
|
||||
struct reg_channel_bounds {
|
||||
u8 start;
|
||||
u8 num;
|
||||
};
|
||||
|
||||
struct mt76x0_eeprom_params {
|
||||
u8 rf_freq_off;
|
||||
s16 temp_off;
|
||||
s8 rssi_offset_2ghz[2];
|
||||
s8 rssi_offset_5ghz[3];
|
||||
s8 lna_gain_2ghz;
|
||||
s8 lna_gain_5ghz[3];
|
||||
u8 pa_type;
|
||||
|
||||
/* TX_PWR_CFG_* values from EEPROM for 20 and 40 Mhz bandwidths. */
|
||||
u32 tx_pwr_cfg_2g[5][2];
|
||||
u32 tx_pwr_cfg_5g[5][2];
|
||||
|
||||
u8 tx_pwr_per_chan[58];
|
||||
|
||||
struct reg_channel_bounds reg;
|
||||
s16 temp_offset;
|
||||
u8 freq_offset;
|
||||
};
|
||||
|
||||
int mt76x0_eeprom_init(struct mt76x0_dev *dev);
|
||||
void mt76x0_read_rx_gain(struct mt76x0_dev *dev);
|
||||
void mt76x0_get_tx_power_per_rate(struct mt76x0_dev *dev);
|
||||
void mt76x0_get_power_info(struct mt76x0_dev *dev, u8 *info);
|
||||
|
||||
static inline u32 s6_validate(u32 reg)
|
||||
static inline s8 s6_to_s8(u32 val)
|
||||
{
|
||||
WARN_ON(reg & ~GENMASK(5, 0));
|
||||
return reg & GENMASK(5, 0);
|
||||
}
|
||||
s8 ret = val & GENMASK(5, 0);
|
||||
|
||||
static inline int s6_to_int(u32 reg)
|
||||
{
|
||||
int s6;
|
||||
|
||||
s6 = s6_validate(reg);
|
||||
if (s6 & BIT(5))
|
||||
s6 -= BIT(6);
|
||||
|
||||
return s6;
|
||||
}
|
||||
|
||||
static inline u32 int_to_s6(int val)
|
||||
{
|
||||
if (val < -0x20)
|
||||
return 0x20;
|
||||
if (val > 0x1f)
|
||||
return 0x1f;
|
||||
|
||||
return val & 0x3f;
|
||||
if (ret & BIT(5))
|
||||
ret -= BIT(6);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "trace.h"
|
||||
#include "mcu.h"
|
||||
#include "../mt76x02_util.h"
|
||||
#include "../mt76x02_dma.h"
|
||||
|
||||
#include "initvals.h"
|
||||
|
||||
@ -43,7 +44,7 @@ static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
|
||||
static void
|
||||
mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable)
|
||||
{
|
||||
int i;
|
||||
u32 mask = MT_CMB_CTRL_XTAL_RDY | MT_CMB_CTRL_PLL_LD;
|
||||
|
||||
/* Note: we don't turn off WLAN_CLK because that makes the device
|
||||
* not respond properly on the probe path.
|
||||
@ -60,24 +61,12 @@ mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable)
|
||||
mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
|
||||
udelay(20);
|
||||
|
||||
if (!enable)
|
||||
return;
|
||||
|
||||
for (i = 200; i; i--) {
|
||||
val = mt76_rr(dev, MT_CMB_CTRL);
|
||||
|
||||
if (val & MT_CMB_CTRL_XTAL_RDY && val & MT_CMB_CTRL_PLL_LD)
|
||||
break;
|
||||
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
/* Note: vendor driver tries to disable/enable wlan here and retry
|
||||
* but the code which does it is so buggy it must have never
|
||||
* triggered, so don't bother.
|
||||
*/
|
||||
if (!i)
|
||||
dev_err(dev->mt76.dev, "Error: PLL and XTAL check failed!\n");
|
||||
if (enable && !mt76_poll(dev, MT_CMB_CTRL, mask, mask, 2000))
|
||||
dev_err(dev->mt76.dev, "PLL and XTAL check failed\n");
|
||||
}
|
||||
|
||||
void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset)
|
||||
@ -114,43 +103,13 @@ EXPORT_SYMBOL_GPL(mt76x0_chip_onoff);
|
||||
|
||||
static void mt76x0_reset_csr_bbp(struct mt76x0_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = mt76_rr(dev, MT_PBF_SYS_CTRL);
|
||||
val &= ~0x2000;
|
||||
mt76_wr(dev, MT_PBF_SYS_CTRL, val);
|
||||
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR |
|
||||
MT_MAC_SYS_CTRL_RESET_BBP);
|
||||
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_RESET_CSR |
|
||||
MT_MAC_SYS_CTRL_RESET_BBP);
|
||||
msleep(200);
|
||||
}
|
||||
|
||||
static void mt76x0_init_usb_dma(struct mt76x0_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = mt76_rr(dev, MT_USB_DMA_CFG);
|
||||
|
||||
val |= MT_USB_DMA_CFG_RX_BULK_EN |
|
||||
MT_USB_DMA_CFG_TX_BULK_EN;
|
||||
|
||||
/* disable AGGR_BULK_RX in order to receive one
|
||||
* frame in each rx urb and avoid copies
|
||||
*/
|
||||
val &= ~MT_USB_DMA_CFG_RX_BULK_AGG_EN;
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
|
||||
val = mt76_rr(dev, MT_COM_REG0);
|
||||
if (val & 1)
|
||||
dev_dbg(dev->mt76.dev, "MCU not ready\n");
|
||||
|
||||
val = mt76_rr(dev, MT_USB_DMA_CFG);
|
||||
|
||||
val |= MT_USB_DMA_CFG_RX_DROP_OR_PAD;
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
val &= ~MT_USB_DMA_CFG_RX_DROP_OR_PAD;
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
mt76_clear(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_RESET_CSR |
|
||||
MT_MAC_SYS_CTRL_RESET_BBP);
|
||||
}
|
||||
|
||||
#define RANDOM_WRITE(dev, tab) \
|
||||
@ -180,30 +139,13 @@ static int mt76x0_init_bbp(struct mt76x0_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_init_beacon_offsets(struct mt76x0_dev *dev)
|
||||
{
|
||||
u16 base = MT_BEACON_BASE;
|
||||
u32 regs[4] = {};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
u16 addr = dev->beacon_offsets[i];
|
||||
|
||||
regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4));
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
|
||||
}
|
||||
|
||||
static void mt76x0_init_mac_registers(struct mt76x0_dev *dev)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
RANDOM_WRITE(dev, common_mac_reg_table);
|
||||
|
||||
mt76_init_beacon_offsets(dev);
|
||||
mt76x02_set_beacon_offsets(&dev->mt76);
|
||||
|
||||
/* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */
|
||||
RANDOM_WRITE(dev, mt76x0_mac_reg_table);
|
||||
@ -213,13 +155,6 @@ static void mt76x0_init_mac_registers(struct mt76x0_dev *dev)
|
||||
reg &= ~0x3;
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL, reg);
|
||||
|
||||
if (is_mt7610e(dev)) {
|
||||
/* Disable COEX_EN */
|
||||
reg = mt76_rr(dev, MT_COEXCFG0);
|
||||
reg &= 0xFFFFFFFE;
|
||||
mt76_wr(dev, MT_COEXCFG0, reg);
|
||||
}
|
||||
|
||||
/* Set 0x141C[15:12]=0xF */
|
||||
reg = mt76_rr(dev, MT_EXT_CCA_CFG);
|
||||
reg |= 0x0000F000;
|
||||
@ -302,45 +237,22 @@ int mt76x0_mac_start(struct mt76x0_dev *dev)
|
||||
{
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
|
||||
|
||||
if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000))
|
||||
if (!mt76x02_wait_for_wpdma(&dev->mt76, 200000))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
dev->mt76.rxfilter = MT_RX_FILTR_CFG_CRC_ERR |
|
||||
MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC |
|
||||
MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP |
|
||||
MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND |
|
||||
MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS |
|
||||
MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL |
|
||||
MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV;
|
||||
mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
|
||||
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
|
||||
|
||||
if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
return !mt76x02_wait_for_wpdma(&dev->mt76, 50) ? -ETIMEDOUT : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_mac_start);
|
||||
|
||||
static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
|
||||
void mt76x0_mac_stop(struct mt76x0_dev *dev)
|
||||
{
|
||||
int i, ok;
|
||||
|
||||
if (test_bit(MT76_REMOVED, &dev->mt76.state))
|
||||
return;
|
||||
|
||||
mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
|
||||
MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
|
||||
MT_BEACON_TIME_CFG_BEACON_TX);
|
||||
|
||||
if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
|
||||
dev_warn(dev->mt76.dev, "Warning: TX DMA did not stop!\n");
|
||||
int i = 200, ok = 0;
|
||||
|
||||
/* Page count on TxQ */
|
||||
i = 200;
|
||||
while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
|
||||
(mt76_rr(dev, 0x0a30) & 0x000000ff) ||
|
||||
(mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
|
||||
@ -353,9 +265,7 @@ static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX);
|
||||
|
||||
/* Page count on RxQ */
|
||||
ok = 0;
|
||||
i = 200;
|
||||
while (i--) {
|
||||
for (i = 0; i < 200; i++) {
|
||||
if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
|
||||
!mt76_rr(dev, 0x0a30) &&
|
||||
!mt76_rr(dev, 0x0a34)) {
|
||||
@ -368,36 +278,14 @@ static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
|
||||
|
||||
if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000))
|
||||
dev_warn(dev->mt76.dev, "Warning: MAC RX did not stop!\n");
|
||||
|
||||
if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
|
||||
dev_warn(dev->mt76.dev, "Warning: RX DMA did not stop!\n");
|
||||
}
|
||||
|
||||
void mt76x0_mac_stop(struct mt76x0_dev *dev)
|
||||
{
|
||||
cancel_delayed_work_sync(&dev->cal_work);
|
||||
cancel_delayed_work_sync(&dev->mac_work);
|
||||
mt76u_stop_stat_wk(&dev->mt76);
|
||||
mt76x0_mac_stop_hw(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_mac_stop);
|
||||
|
||||
int mt76x0_init_hardware(struct mt76x0_dev *dev)
|
||||
{
|
||||
static const u16 beacon_offsets[16] = {
|
||||
/* 512 byte per beacon */
|
||||
0xc000, 0xc200, 0xc400, 0xc600,
|
||||
0xc800, 0xca00, 0xcc00, 0xce00,
|
||||
0xd000, 0xd200, 0xd400, 0xd600,
|
||||
0xd800, 0xda00, 0xdc00, 0xde00
|
||||
};
|
||||
int ret;
|
||||
|
||||
dev->beacon_offsets = beacon_offsets;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100))
|
||||
if (!mt76x02_wait_for_wpdma(&dev->mt76, 1000))
|
||||
return -EIO;
|
||||
|
||||
/* Wait for ASIC ready after FW load. */
|
||||
@ -405,25 +293,21 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
mt76x0_reset_csr_bbp(dev);
|
||||
mt76x0_init_usb_dma(dev);
|
||||
|
||||
mt76_wr(dev, MT_HEADER_TRANS_CTRL_REG, 0x0);
|
||||
mt76_wr(dev, MT_TSO_CTRL, 0x0);
|
||||
|
||||
ret = mt76x02_mcu_function_select(&dev->mt76, Q_SELECT, 1, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76x0_init_mac_registers(dev);
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_MAC_STATUS,
|
||||
MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 1000))
|
||||
if (!mt76x02_wait_for_txrx_idle(&dev->mt76))
|
||||
return -EIO;
|
||||
|
||||
ret = mt76x0_init_bbp(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
|
||||
|
||||
ret = mt76x0_init_wcid_mem(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -441,12 +325,6 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
|
||||
|
||||
mt76x0_reset_counters(dev);
|
||||
|
||||
mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
|
||||
|
||||
mt76_wr(dev, MT_TXOP_CTRL_CFG,
|
||||
FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
|
||||
FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
|
||||
|
||||
ret = mt76x0_eeprom_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -457,22 +335,15 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_init_hardware);
|
||||
|
||||
void mt76x0_cleanup(struct mt76x0_dev *dev)
|
||||
{
|
||||
clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
|
||||
mt76x0_chip_onoff(dev, false, false);
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
mt76u_mcu_deinit(&dev->mt76);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_cleanup);
|
||||
|
||||
struct mt76x0_dev *
|
||||
mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops *drv_ops)
|
||||
mt76x0_alloc_device(struct device *pdev,
|
||||
const struct mt76_driver_ops *drv_ops,
|
||||
const struct ieee80211_ops *ops)
|
||||
{
|
||||
struct mt76x0_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
|
||||
mdev = mt76_alloc_device(sizeof(*dev), &mt76x0_ops);
|
||||
mdev = mt76_alloc_device(sizeof(*dev), ops);
|
||||
if (!mdev)
|
||||
return NULL;
|
||||
|
||||
@ -497,10 +368,6 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
int ret;
|
||||
|
||||
ret = mt76x0_init_hardware(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
|
||||
* entry no. 1 like it does in the vendor driver.
|
||||
*/
|
||||
@ -535,12 +402,6 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
|
||||
if (mdev->cap.has_5ghz)
|
||||
mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband);
|
||||
|
||||
/* check hw sg support in order to enable AMSDU */
|
||||
if (mt76u_check_sg(mdev))
|
||||
hw->max_tx_fragments = MT_SG_MAX_SIZE;
|
||||
else
|
||||
hw->max_tx_fragments = 1;
|
||||
|
||||
mt76x0_init_debugfs(dev);
|
||||
|
||||
return 0;
|
||||
|
@ -2,6 +2,7 @@
|
||||
* (c) Copyright 2002-2010, Ralink Technology, Inc.
|
||||
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
|
||||
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
@ -19,264 +20,214 @@
|
||||
#include "phy.h"
|
||||
|
||||
static const struct mt76_reg_pair common_mac_reg_table[] = {
|
||||
#if 1
|
||||
{MT_BCN_OFFSET(0), 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */
|
||||
{MT_BCN_OFFSET(1), 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */
|
||||
#endif
|
||||
|
||||
{MT_LEGACY_BASIC_RATE, 0x0000013f}, /* Basic rate set bitmap*/
|
||||
{MT_HT_BASIC_RATE, 0x00008003}, /* Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI.*/
|
||||
{MT_MAC_SYS_CTRL, 0x00}, /* 0x1004, , default Disable RX*/
|
||||
{MT_RX_FILTR_CFG, 0x17f97}, /*0x1400 , RX filter control, */
|
||||
{MT_BKOFF_SLOT_CFG, 0x209}, /* default set short slot time, CC_DELAY_TIME should be 2 */
|
||||
/*{TX_SW_CFG0, 0x40a06}, Gary,2006-08-23 */
|
||||
{MT_TX_SW_CFG0, 0x0}, /* Gary,2008-05-21 for CWC test */
|
||||
{MT_TX_SW_CFG1, 0x80606}, /* Gary,2006-08-23 */
|
||||
{MT_TX_LINK_CFG, 0x1020}, /* Gary,2006-08-23 */
|
||||
/*{TX_TIMEOUT_CFG, 0x00182090}, CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT*/
|
||||
{MT_TX_TIMEOUT_CFG, 0x000a2090}, /* CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT , Modify for 2860E ,2007-08-01*/
|
||||
{MT_MAX_LEN_CFG, 0xa0fff | 0x00001000}, /* 0x3018, MAX frame length. Max PSDU = 16kbytes.*/
|
||||
{MT_LED_CFG, 0x7f031e46}, /* Gary, 2006-08-23*/
|
||||
|
||||
{MT_PBF_TX_MAX_PCNT, 0x1fbf1f1f /*0xbfbf3f1f*/},
|
||||
{MT_PBF_RX_MAX_PCNT, 0x9f},
|
||||
|
||||
/*{TX_RTY_CFG, 0x6bb80408}, Jan, 2006/11/16*/
|
||||
/* WMM_ACM_SUPPORT */
|
||||
/* {TX_RTY_CFG, 0x6bb80101}, sample*/
|
||||
{MT_TX_RETRY_CFG, 0x47d01f0f}, /* Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03*/
|
||||
|
||||
{MT_AUTO_RSP_CFG, 0x00000013}, /* Initial Auto_Responder, because QA will turn off Auto-Responder*/
|
||||
{MT_CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */
|
||||
{MT_OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */
|
||||
{MT_PBF_CFG, 0xf40006}, /* Only enable Queue 2*/
|
||||
{MT_MM40_PROT_CFG, 0x3F44084}, /* Initial Auto_Responder, because QA will turn off Auto-Responder*/
|
||||
{MT_WPDMA_GLO_CFG, 0x00000030},
|
||||
{MT_GF20_PROT_CFG, 0x01744004}, /* set 19:18 --> Short NAV for MIMO PS*/
|
||||
{MT_GF40_PROT_CFG, 0x03F44084},
|
||||
{MT_MM20_PROT_CFG, 0x01744004},
|
||||
{MT_TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, /*Extension channel backoff.*/
|
||||
{MT_TX_RTS_CFG, 0x00092b20},
|
||||
|
||||
{MT_EXP_ACK_TIME, 0x002400ca}, /* default value */
|
||||
{MT_TXOP_HLDR_ET, 0x00000002},
|
||||
|
||||
/* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us
|
||||
is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0
|
||||
and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping
|
||||
will always lost. So we change the SIFS of CCK from 10us to 16us. */
|
||||
{MT_XIFS_TIME_CFG, 0x33a41010},
|
||||
{MT_PWR_PIN_CFG, 0x00000000},
|
||||
{ MT_BCN_OFFSET(0), 0xf8f0e8e0 },
|
||||
{ MT_BCN_OFFSET(1), 0x6f77d0c8 },
|
||||
{ MT_LEGACY_BASIC_RATE, 0x0000013f },
|
||||
{ MT_HT_BASIC_RATE, 0x00008003 },
|
||||
{ MT_MAC_SYS_CTRL, 0x00000000 },
|
||||
{ MT_RX_FILTR_CFG, 0x00017f97 },
|
||||
{ MT_BKOFF_SLOT_CFG, 0x00000209 },
|
||||
{ MT_TX_SW_CFG0, 0x00000000 },
|
||||
{ MT_TX_SW_CFG1, 0x00080606 },
|
||||
{ MT_TX_LINK_CFG, 0x00001020 },
|
||||
{ MT_TX_TIMEOUT_CFG, 0x000a2090 },
|
||||
{ MT_MAX_LEN_CFG, 0xa0fff | 0x00001000 },
|
||||
{ MT_LED_CFG, 0x7f031e46 },
|
||||
{ MT_PBF_TX_MAX_PCNT, 0x1fbf1f1f },
|
||||
{ MT_PBF_RX_MAX_PCNT, 0x0000fe9f },
|
||||
{ MT_TX_RETRY_CFG, 0x47d01f0f },
|
||||
{ MT_AUTO_RSP_CFG, 0x00000013 },
|
||||
{ MT_CCK_PROT_CFG, 0x05740003 },
|
||||
{ MT_OFDM_PROT_CFG, 0x05740003 },
|
||||
{ MT_PBF_CFG, 0x00f40006 },
|
||||
{ MT_WPDMA_GLO_CFG, 0x00000030 },
|
||||
{ MT_GF20_PROT_CFG, 0x01744004 },
|
||||
{ MT_GF40_PROT_CFG, 0x03f44084 },
|
||||
{ MT_MM20_PROT_CFG, 0x01744004 },
|
||||
{ MT_MM40_PROT_CFG, 0x03f54084 },
|
||||
{ MT_TXOP_CTRL_CFG, 0x0000583f },
|
||||
{ MT_TX_RTS_CFG, 0x00092b20 },
|
||||
{ MT_EXP_ACK_TIME, 0x002400ca },
|
||||
{ MT_TXOP_HLDR_ET, 0x00000002 },
|
||||
{ MT_XIFS_TIME_CFG, 0x33a41010 },
|
||||
{ MT_PWR_PIN_CFG, 0x00000000 },
|
||||
};
|
||||
|
||||
static const struct mt76_reg_pair mt76x0_mac_reg_table[] = {
|
||||
/* {MT_IOCFG_6, 0xA0040080 }, */
|
||||
{MT_PBF_SYS_CTRL, 0x00080c00 },
|
||||
{MT_PBF_CFG, 0x77723c1f },
|
||||
{MT_FCE_PSE_CTRL, 0x00000001 },
|
||||
|
||||
{MT_AMPDU_MAX_LEN_20M1S, 0xBAA99887 },
|
||||
|
||||
/* Delay bb_tx_pe for proper tx_mcs_pwr update */
|
||||
{MT_TX_SW_CFG0, 0x00000601 },
|
||||
|
||||
/* Set rf_tx_pe deassert time to 1us by Chee's comment @MT7650_CR_setting_1018.xlsx */
|
||||
{MT_TX_SW_CFG1, 0x00040000 },
|
||||
{MT_TX_SW_CFG2, 0x00000000 },
|
||||
|
||||
/* disable Tx info report */
|
||||
{0xa44, 0x0000000 },
|
||||
|
||||
{MT_HEADER_TRANS_CTRL_REG, 0x0},
|
||||
{MT_TSO_CTRL, 0x0},
|
||||
|
||||
/* BB_PA_MODE_CFG0(0x1214) Keep default value @20120903 */
|
||||
{MT_BB_PA_MODE_CFG1, 0x00500055},
|
||||
|
||||
/* RF_PA_MODE_CFG0(0x121C) Keep default value @20120903 */
|
||||
{MT_RF_PA_MODE_CFG1, 0x00500055},
|
||||
|
||||
{MT_TX_ALC_CFG_0, 0x2F2F000C},
|
||||
{MT_TX0_BB_GAIN_ATTEN, 0x00000000}, /* set BBP atten gain = 0 */
|
||||
|
||||
{MT_TX_PWR_CFG_0, 0x3A3A3A3A},
|
||||
{MT_TX_PWR_CFG_1, 0x3A3A3A3A},
|
||||
{MT_TX_PWR_CFG_2, 0x3A3A3A3A},
|
||||
{MT_TX_PWR_CFG_3, 0x3A3A3A3A},
|
||||
{MT_TX_PWR_CFG_4, 0x3A3A3A3A},
|
||||
{MT_TX_PWR_CFG_7, 0x3A3A3A3A},
|
||||
{MT_TX_PWR_CFG_8, 0x3A},
|
||||
{MT_TX_PWR_CFG_9, 0x3A},
|
||||
/* Enable Tx length > 4095 byte */
|
||||
{0x150C, 0x00000002},
|
||||
|
||||
/* Disable bt_abort_tx_en(0x1238[21] = 0) which is not used at MT7650 */
|
||||
{0x1238, 0x001700C8},
|
||||
/* PMU_OCLEVEL<5:1> from default <5'b10010> to <5'b11011> for normal driver */
|
||||
/* {MT_LDO_CTRL_0, 0x00A647B6}, */
|
||||
|
||||
/* Default LDO_DIG supply 1.26V, change to 1.2V */
|
||||
{MT_LDO_CTRL_1, 0x6B006464 },
|
||||
/*
|
||||
{MT_HT_BASIC_RATE, 0x00004003 },
|
||||
{MT_HT_CTRL_CFG, 0x000001FF },
|
||||
*/
|
||||
{ MT_IOCFG_6, 0xa0040080 },
|
||||
{ MT_PBF_SYS_CTRL, 0x00080c00 },
|
||||
{ MT_PBF_CFG, 0x77723c1f },
|
||||
{ MT_FCE_PSE_CTRL, 0x00000001 },
|
||||
{ MT_AMPDU_MAX_LEN_20M1S, 0xAAA99887 },
|
||||
{ MT_TX_SW_CFG0, 0x00000601 },
|
||||
{ MT_TX_SW_CFG1, 0x00040000 },
|
||||
{ MT_TX_SW_CFG2, 0x00000000 },
|
||||
{ 0xa44, 0x00000000 },
|
||||
{ MT_HEADER_TRANS_CTRL_REG, 0x00000000 },
|
||||
{ MT_TSO_CTRL, 0x00000000 },
|
||||
{ MT_BB_PA_MODE_CFG1, 0x00500055 },
|
||||
{ MT_RF_PA_MODE_CFG1, 0x00500055 },
|
||||
{ MT_TX_ALC_CFG_0, 0x2F2F000C },
|
||||
{ MT_TX0_BB_GAIN_ATTEN, 0x00000000 },
|
||||
{ MT_TX_PWR_CFG_0, 0x3A3A3A3A },
|
||||
{ MT_TX_PWR_CFG_1, 0x3A3A3A3A },
|
||||
{ MT_TX_PWR_CFG_2, 0x3A3A3A3A },
|
||||
{ MT_TX_PWR_CFG_3, 0x3A3A3A3A },
|
||||
{ MT_TX_PWR_CFG_4, 0x3A3A3A3A },
|
||||
{ MT_TX_PWR_CFG_7, 0x3A3A3A3A },
|
||||
{ MT_TX_PWR_CFG_8, 0x0000003A },
|
||||
{ MT_TX_PWR_CFG_9, 0x0000003A },
|
||||
{ 0x150C, 0x00000002 },
|
||||
{ 0x1238, 0x001700C8 },
|
||||
{ MT_LDO_CTRL_0, 0x00A647B6 },
|
||||
{ MT_LDO_CTRL_1, 0x6B006464 },
|
||||
{ MT_HT_BASIC_RATE, 0x00004003 },
|
||||
{ MT_HT_CTRL_CFG, 0x000001FF },
|
||||
{ MT_TXOP_HLDR_ET, 0x00000000 }
|
||||
};
|
||||
|
||||
|
||||
static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = {
|
||||
{MT_BBP(CORE, 1), 0x00000002},
|
||||
{MT_BBP(CORE, 4), 0x00000000},
|
||||
{MT_BBP(CORE, 24), 0x00000000},
|
||||
{MT_BBP(CORE, 32), 0x4003000a},
|
||||
{MT_BBP(CORE, 42), 0x00000000},
|
||||
{MT_BBP(CORE, 44), 0x00000000},
|
||||
|
||||
{MT_BBP(IBI, 11), 0x00000080},
|
||||
|
||||
/*
|
||||
0x2300[5] Default Antenna:
|
||||
0 for WIFI main antenna
|
||||
1 for WIFI aux antenna
|
||||
|
||||
*/
|
||||
{MT_BBP(AGC, 0), 0x00021400},
|
||||
{MT_BBP(AGC, 1), 0x00000003},
|
||||
{MT_BBP(AGC, 2), 0x003A6464},
|
||||
{MT_BBP(AGC, 15), 0x88A28CB8},
|
||||
{MT_BBP(AGC, 22), 0x00001E21},
|
||||
{MT_BBP(AGC, 23), 0x0000272C},
|
||||
{MT_BBP(AGC, 24), 0x00002F3A},
|
||||
{MT_BBP(AGC, 25), 0x8000005A},
|
||||
{MT_BBP(AGC, 26), 0x007C2005},
|
||||
{MT_BBP(AGC, 34), 0x000A0C0C},
|
||||
{MT_BBP(AGC, 37), 0x2121262C},
|
||||
{MT_BBP(AGC, 41), 0x38383E45},
|
||||
{MT_BBP(AGC, 57), 0x00001010},
|
||||
{MT_BBP(AGC, 59), 0xBAA20E96},
|
||||
{MT_BBP(AGC, 63), 0x00000001},
|
||||
|
||||
{MT_BBP(TXC, 0), 0x00280403},
|
||||
{MT_BBP(TXC, 1), 0x00000000},
|
||||
|
||||
{MT_BBP(RXC, 1), 0x00000012},
|
||||
{MT_BBP(RXC, 2), 0x00000011},
|
||||
{MT_BBP(RXC, 3), 0x00000005},
|
||||
{MT_BBP(RXC, 4), 0x00000000},
|
||||
{MT_BBP(RXC, 5), 0xF977C4EC},
|
||||
{MT_BBP(RXC, 7), 0x00000090},
|
||||
|
||||
{MT_BBP(TXO, 8), 0x00000000},
|
||||
|
||||
{MT_BBP(TXBE, 0), 0x00000000},
|
||||
{MT_BBP(TXBE, 4), 0x00000004},
|
||||
{MT_BBP(TXBE, 6), 0x00000000},
|
||||
{MT_BBP(TXBE, 8), 0x00000014},
|
||||
{MT_BBP(TXBE, 9), 0x20000000},
|
||||
{MT_BBP(TXBE, 10), 0x00000000},
|
||||
{MT_BBP(TXBE, 12), 0x00000000},
|
||||
{MT_BBP(TXBE, 13), 0x00000000},
|
||||
{MT_BBP(TXBE, 14), 0x00000000},
|
||||
{MT_BBP(TXBE, 15), 0x00000000},
|
||||
{MT_BBP(TXBE, 16), 0x00000000},
|
||||
{MT_BBP(TXBE, 17), 0x00000000},
|
||||
|
||||
{MT_BBP(RXFE, 1), 0x00008800}, /* Add for E3 */
|
||||
{MT_BBP(RXFE, 3), 0x00000000},
|
||||
{MT_BBP(RXFE, 4), 0x00000000},
|
||||
|
||||
{MT_BBP(RXO, 13), 0x00000092},
|
||||
{MT_BBP(RXO, 14), 0x00060612},
|
||||
{MT_BBP(RXO, 15), 0xC8321B18},
|
||||
{MT_BBP(RXO, 16), 0x0000001E},
|
||||
{MT_BBP(RXO, 17), 0x00000000},
|
||||
{MT_BBP(RXO, 18), 0xCC00A993},
|
||||
{MT_BBP(RXO, 19), 0xB9CB9CB9},
|
||||
{MT_BBP(RXO, 20), 0x26c00057},
|
||||
{MT_BBP(RXO, 21), 0x00000001},
|
||||
{MT_BBP(RXO, 24), 0x00000006},
|
||||
{ MT_BBP(CORE, 1), 0x00000002 },
|
||||
{ MT_BBP(CORE, 4), 0x00000000 },
|
||||
{ MT_BBP(CORE, 24), 0x00000000 },
|
||||
{ MT_BBP(CORE, 32), 0x4003000a },
|
||||
{ MT_BBP(CORE, 42), 0x00000000 },
|
||||
{ MT_BBP(CORE, 44), 0x00000000 },
|
||||
{ MT_BBP(IBI, 11), 0x0FDE8081 },
|
||||
{ MT_BBP(AGC, 0), 0x00021400 },
|
||||
{ MT_BBP(AGC, 1), 0x00000003 },
|
||||
{ MT_BBP(AGC, 2), 0x003A6464 },
|
||||
{ MT_BBP(AGC, 15), 0x88A28CB8 },
|
||||
{ MT_BBP(AGC, 22), 0x00001E21 },
|
||||
{ MT_BBP(AGC, 23), 0x0000272C },
|
||||
{ MT_BBP(AGC, 24), 0x00002F3A },
|
||||
{ MT_BBP(AGC, 25), 0x8000005A },
|
||||
{ MT_BBP(AGC, 26), 0x007C2005 },
|
||||
{ MT_BBP(AGC, 33), 0x00003238 },
|
||||
{ MT_BBP(AGC, 34), 0x000A0C0C },
|
||||
{ MT_BBP(AGC, 37), 0x2121262C },
|
||||
{ MT_BBP(AGC, 41), 0x38383E45 },
|
||||
{ MT_BBP(AGC, 57), 0x00001010 },
|
||||
{ MT_BBP(AGC, 59), 0xBAA20E96 },
|
||||
{ MT_BBP(AGC, 63), 0x00000001 },
|
||||
{ MT_BBP(TXC, 0), 0x00280403 },
|
||||
{ MT_BBP(TXC, 1), 0x00000000 },
|
||||
{ MT_BBP(RXC, 1), 0x00000012 },
|
||||
{ MT_BBP(RXC, 2), 0x00000011 },
|
||||
{ MT_BBP(RXC, 3), 0x00000005 },
|
||||
{ MT_BBP(RXC, 4), 0x00000000 },
|
||||
{ MT_BBP(RXC, 5), 0xF977C4EC },
|
||||
{ MT_BBP(RXC, 7), 0x00000090 },
|
||||
{ MT_BBP(TXO, 8), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 0), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 4), 0x00000004 },
|
||||
{ MT_BBP(TXBE, 6), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 8), 0x00000014 },
|
||||
{ MT_BBP(TXBE, 9), 0x20000000 },
|
||||
{ MT_BBP(TXBE, 10), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 12), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 13), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 14), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 15), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 16), 0x00000000 },
|
||||
{ MT_BBP(TXBE, 17), 0x00000000 },
|
||||
{ MT_BBP(RXFE, 1), 0x00008800 },
|
||||
{ MT_BBP(RXFE, 3), 0x00000000 },
|
||||
{ MT_BBP(RXFE, 4), 0x00000000 },
|
||||
{ MT_BBP(RXO, 13), 0x00000192 },
|
||||
{ MT_BBP(RXO, 14), 0x00060612 },
|
||||
{ MT_BBP(RXO, 15), 0xC8321B18 },
|
||||
{ MT_BBP(RXO, 16), 0x0000001E },
|
||||
{ MT_BBP(RXO, 17), 0x00000000 },
|
||||
{ MT_BBP(RXO, 18), 0xCC00A993 },
|
||||
{ MT_BBP(RXO, 19), 0xB9CB9CB9 },
|
||||
{ MT_BBP(RXO, 20), 0x26c00057 },
|
||||
{ MT_BBP(RXO, 21), 0x00000001 },
|
||||
{ MT_BBP(RXO, 24), 0x00000006 },
|
||||
{ MT_BBP(RXO, 28), 0x0000003F },
|
||||
};
|
||||
|
||||
static const struct mt76x0_bbp_switch_item mt76x0_bbp_switch_tab[] = {
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 8), 0x0E344EF0}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 8), 0x122C54F2}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 4), 0x1FEDA049 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 4), 0x1FECA054 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 14), 0x310F2E39}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 14), 0x310F2A3F}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 6), 0x00000045 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 6), 0x0000000A } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 32), 0x00003230}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 32), 0x0000181C}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 8), 0x16344EF0 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 8), 0x122C54F2 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 33), 0x00003240}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 33), 0x00003218}},
|
||||
{ RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 12), 0x05052879 } },
|
||||
{ RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 12), 0x050528F9 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 12), 0x050528F9 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 35), 0x11112016}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 35), 0x11112016}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 13), 0x35050004 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 13), 0x2C3A0406 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(RXO, 28), 0x0000008A}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(RXO, 28), 0x0000008A}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 14), 0x310F2E3C } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 14), 0x310F2A3F } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 4), 0x1FEDA049}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 4), 0x1FECA054}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 26), 0x007C2005 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 26), 0x007C2005 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 6), 0x00000045}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 6), 0x0000000A}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 27), 0x000000E1 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 27), 0x000000EC } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 12), 0x05052879}},
|
||||
{RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 12), 0x050528F9}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 12), 0x050528F9}},
|
||||
{ RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 28), 0x00060806 } },
|
||||
{ RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 28), 0x00050806 } },
|
||||
{ RF_A_BAND | RF_BW_40, { MT_BBP(AGC, 28), 0x00060801 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_80, { MT_BBP(AGC, 28), 0x00060806 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 13), 0x35050004}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 13), 0x2C3A0406}},
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(RXO, 28), 0x0000008A } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 27), 0x000000E1}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 27), 0x000000EC}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 31), 0x00000E23 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 31), 0x00000E13 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 28), 0x00060806}},
|
||||
{RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 28), 0x00050806}},
|
||||
{RF_A_BAND | RF_BW_40, {MT_BBP(AGC, 28), 0x00060801}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_80, {MT_BBP(AGC, 28), 0x00060806}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 32), 0x00003218 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 32), 0x0000181C } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 31), 0x00000F23}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 31), 0x00000F13}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 33), 0x00003240 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 33), 0x00003218 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 39), 0x2A2A3036}},
|
||||
{RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 39), 0x2A2A2C36}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 39), 0x2A2A3036}},
|
||||
{RF_A_BAND | RF_BW_80, {MT_BBP(AGC, 39), 0x2A2A2A36}},
|
||||
{ RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 35), 0x11111616 } },
|
||||
{ RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 35), 0x11111516 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 35), 0x11111111 } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 43), 0x27273438}},
|
||||
{RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 43), 0x27272D38}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 43), 0x27272B30}},
|
||||
{ RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 39), 0x2A2A3036 } },
|
||||
{ RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 39), 0x2A2A2C36 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 39), 0x2A2A2A2A } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 51), 0x17171C1C}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 51), 0xFFFFFFFF}},
|
||||
{ RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 43), 0x27273438 } },
|
||||
{ RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 43), 0x27272D38 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 43), 0x27271A1A } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 53), 0x26262A2F}},
|
||||
{RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 53), 0x2626322F}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 53), 0xFFFFFFFF}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 51), 0x17171C1C } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 51), 0xFFFFFFFF } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20, {MT_BBP(AGC, 55), 0x40404E58}},
|
||||
{RF_G_BAND | RF_BW_40, {MT_BBP(AGC, 55), 0x40405858}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 55), 0xFFFFFFFF}},
|
||||
{ RF_G_BAND | RF_BW_20, { MT_BBP(AGC, 53), 0x26262A2F } },
|
||||
{ RF_G_BAND | RF_BW_40, { MT_BBP(AGC, 53), 0x2626322F } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 53), 0xFFFFFFFF } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(AGC, 58), 0x00001010}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(AGC, 58), 0x00000000}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 55), 0x40404040 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 55), 0xFFFFFFFF } },
|
||||
|
||||
{RF_G_BAND | RF_BW_20 | RF_BW_40, {MT_BBP(RXFE, 0), 0x3D5000E0}},
|
||||
{RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, {MT_BBP(RXFE, 0), 0x895000E0}},
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(AGC, 58), 0x00001010 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(AGC, 58), 0x00000000 } },
|
||||
|
||||
{ RF_G_BAND | RF_BW_20 | RF_BW_40, { MT_BBP(RXFE, 0), 0x3D5000E0 } },
|
||||
{ RF_A_BAND | RF_BW_20 | RF_BW_40 | RF_BW_80, { MT_BBP(RXFE, 0), 0x895000E0 } },
|
||||
};
|
||||
|
||||
static const struct mt76_reg_pair mt76x0_dcoc_tab[] = {
|
||||
{MT_BBP(CAL, 47), 0x000010F0 },
|
||||
{MT_BBP(CAL, 48), 0x00008080 },
|
||||
{MT_BBP(CAL, 49), 0x00000F07 },
|
||||
{MT_BBP(CAL, 50), 0x00000040 },
|
||||
{MT_BBP(CAL, 51), 0x00000404 },
|
||||
{MT_BBP(CAL, 52), 0x00080803 },
|
||||
{MT_BBP(CAL, 53), 0x00000704 },
|
||||
{MT_BBP(CAL, 54), 0x00002828 },
|
||||
{MT_BBP(CAL, 55), 0x00005050 },
|
||||
{ MT_BBP(CAL, 47), 0x000010F0 },
|
||||
{ MT_BBP(CAL, 48), 0x00008080 },
|
||||
{ MT_BBP(CAL, 49), 0x00000F07 },
|
||||
{ MT_BBP(CAL, 50), 0x00000040 },
|
||||
{ MT_BBP(CAL, 51), 0x00000404 },
|
||||
{ MT_BBP(CAL, 52), 0x00080803 },
|
||||
{ MT_BBP(CAL, 53), 0x00000704 },
|
||||
{ MT_BBP(CAL, 54), 0x00002828 },
|
||||
{ MT_BBP(CAL, 55), 0x00005050 },
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -18,42 +18,7 @@
|
||||
#include "../mt76x02_util.h"
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
static int mt76x0_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
ret = mt76x0_mac_start(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
|
||||
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt76x0_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
|
||||
mt76x0_mac_stop(dev);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
static int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
|
||||
int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
int ret = 0;
|
||||
@ -66,10 +31,27 @@ static int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
|
||||
ieee80211_wake_queues(hw);
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
dev->mt76.txpower_conf = hw->conf.power_level * 2;
|
||||
|
||||
if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
|
||||
mt76x0_phy_set_txpower(dev);
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
|
||||
if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
|
||||
dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC;
|
||||
else
|
||||
dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
|
||||
|
||||
mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_config);
|
||||
|
||||
static void
|
||||
mt76x0_addr_wr(struct mt76x0_dev *dev, const u32 offset, const u8 *addr)
|
||||
@ -78,9 +60,9 @@ mt76x0_addr_wr(struct mt76x0_dev *dev, const u32 offset, const u8 *addr)
|
||||
mt76_wr(dev, offset + 4, addr[4] | addr[5] << 8);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info, u32 changed)
|
||||
void mt76x0_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info, u32 changed)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
|
||||
@ -130,11 +112,10 @@ mt76x0_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_bss_info_changed);
|
||||
|
||||
static void
|
||||
mt76x0_sw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
const u8 *mac_addr)
|
||||
void mt76x0_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
|
||||
@ -142,10 +123,10 @@ mt76x0_sw_scan(struct ieee80211_hw *hw,
|
||||
mt76x0_agc_save(dev);
|
||||
set_bit(MT76_SCANNING, &dev->mt76.state);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_sw_scan);
|
||||
|
||||
static void
|
||||
mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
void mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
|
||||
@ -155,8 +136,9 @@ mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_sw_scan_complete);
|
||||
|
||||
static int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
|
||||
@ -164,24 +146,4 @@ static int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt76x0_ops = {
|
||||
.tx = mt76x0_tx,
|
||||
.start = mt76x0_start,
|
||||
.stop = mt76x0_stop,
|
||||
.add_interface = mt76x02_add_interface,
|
||||
.remove_interface = mt76x02_remove_interface,
|
||||
.config = mt76x0_config,
|
||||
.configure_filter = mt76x02_configure_filter,
|
||||
.bss_info_changed = mt76x0_bss_info_changed,
|
||||
.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,
|
||||
.set_rts_threshold = mt76x0_set_rts_threshold,
|
||||
.wake_tx_queue = mt76_wake_tx_queue,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt76x0_set_rts_threshold);
|
||||
|
@ -41,4 +41,11 @@ enum mcu_calibrate {
|
||||
MCU_CAL_TX_GROUP_DELAY,
|
||||
};
|
||||
|
||||
int mt76x0e_mcu_init(struct mt76x0_dev *dev);
|
||||
int mt76x0u_mcu_init(struct mt76x0_dev *dev);
|
||||
static inline int mt76x0_firmware_running(struct mt76x0_dev *dev)
|
||||
{
|
||||
return mt76_rr(dev, MT_MCU_COM_REG0) == 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "../mt76.h"
|
||||
#include "../mt76x02_regs.h"
|
||||
#include "../mt76x02_mac.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
#define MT_CALIBRATE_INTERVAL (4 * HZ)
|
||||
|
||||
@ -86,15 +87,11 @@ struct mt76x0_dev {
|
||||
|
||||
spinlock_t mac_lock;
|
||||
|
||||
const u16 *beacon_offsets;
|
||||
|
||||
struct mt76x0_eeprom_params *ee;
|
||||
struct mt76x0_caldata caldata;
|
||||
|
||||
struct mutex reg_atomic_mutex;
|
||||
struct mutex hw_atomic_mutex;
|
||||
|
||||
u32 debugfs_reg;
|
||||
|
||||
atomic_t avg_ampdu_len;
|
||||
|
||||
/* Connection monitoring things */
|
||||
@ -107,13 +104,12 @@ struct mt76x0_dev {
|
||||
int avg_rssi; /* starts at 0 and converges */
|
||||
|
||||
u8 agc_save;
|
||||
u16 chainmask;
|
||||
|
||||
bool no_2ghz;
|
||||
|
||||
struct mac_stats stats;
|
||||
};
|
||||
|
||||
extern const struct ieee80211_ops mt76x0_ops;
|
||||
|
||||
static inline bool is_mt7610e(struct mt76x0_dev *dev)
|
||||
{
|
||||
/* TODO */
|
||||
@ -128,15 +124,26 @@ void mt76x0_init_debugfs(struct mt76x0_dev *dev);
|
||||
|
||||
/* Init */
|
||||
struct mt76x0_dev *
|
||||
mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops *drv_ops);
|
||||
mt76x0_alloc_device(struct device *pdev,
|
||||
const struct mt76_driver_ops *drv_ops,
|
||||
const struct ieee80211_ops *ops);
|
||||
int mt76x0_init_hardware(struct mt76x0_dev *dev);
|
||||
int mt76x0_register_device(struct mt76x0_dev *dev);
|
||||
void mt76x0_cleanup(struct mt76x0_dev *dev);
|
||||
void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset);
|
||||
|
||||
int mt76x0_mac_start(struct mt76x0_dev *dev);
|
||||
void mt76x0_mac_stop(struct mt76x0_dev *dev);
|
||||
|
||||
int mt76x0_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void mt76x0_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info, u32 changed);
|
||||
void mt76x0_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
const u8 *mac_addr);
|
||||
void mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
|
||||
|
||||
/* PHY */
|
||||
void mt76x0_phy_init(struct mt76x0_dev *dev);
|
||||
int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev);
|
||||
@ -148,6 +155,7 @@ void mt76x0_phy_recalibrate_after_assoc(struct mt76x0_dev *dev);
|
||||
int mt76x0_phy_get_rssi(struct mt76x0_dev *dev, struct mt76x02_rxwi *rxwi);
|
||||
void mt76x0_phy_con_cal_onoff(struct mt76x0_dev *dev,
|
||||
struct ieee80211_bss_conf *info);
|
||||
void mt76x0_phy_set_txpower(struct mt76x0_dev *dev);
|
||||
|
||||
/* MAC */
|
||||
void mt76x0_mac_work(struct work_struct *work);
|
||||
@ -160,12 +168,12 @@ void mt76x0_mac_set_ampdu_factor(struct mt76x0_dev *dev);
|
||||
/* TX */
|
||||
void mt76x0_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
|
||||
struct sk_buff *skb);
|
||||
struct mt76x02_txwi *
|
||||
mt76x0_push_txwi(struct mt76x0_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, struct mt76_wcid *wcid,
|
||||
int pkt_len);
|
||||
|
||||
void mt76x0_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb);
|
||||
|
||||
int mt76x0_tx_prepare_skb(struct mt76_dev *mdev, void *data,
|
||||
struct sk_buff *skb, struct mt76_queue *q,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
|
||||
u32 *tx_info);
|
||||
#endif
|
||||
|
@ -19,6 +19,106 @@
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "mt76x0.h"
|
||||
#include "mcu.h"
|
||||
#include "../mt76x02_dma.h"
|
||||
#include "../mt76x02_util.h"
|
||||
|
||||
static int mt76x0e_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
mt76x02_mac_start(&dev->mt76);
|
||||
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt76x0e_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
|
||||
cancel_delayed_work_sync(&dev->cal_work);
|
||||
cancel_delayed_work_sync(&dev->mac_work);
|
||||
|
||||
if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY,
|
||||
0, 1000))
|
||||
dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
|
||||
mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
|
||||
|
||||
mt76x0_mac_stop(dev);
|
||||
|
||||
if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
|
||||
0, 1000))
|
||||
dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
|
||||
mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops mt76x0e_ops = {
|
||||
.tx = mt76x0_tx,
|
||||
.start = mt76x0e_start,
|
||||
.stop = mt76x0e_stop,
|
||||
.config = mt76x0_config,
|
||||
.add_interface = mt76x02_add_interface,
|
||||
.remove_interface = mt76x02_remove_interface,
|
||||
.configure_filter = mt76x02_configure_filter,
|
||||
};
|
||||
|
||||
static int mt76x0e_register_device(struct mt76x0_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
mt76x0_chip_onoff(dev, true, false);
|
||||
if (!mt76x02_wait_for_mac(&dev->mt76))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
mt76x02_dma_disable(&dev->mt76);
|
||||
err = mt76x0e_mcu_init(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt76x02_dma_init(&dev->mt76);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt76x0_init_hardware(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (mt76_chip(&dev->mt76) == 0x7610) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
mt76_clear(dev, 0x110, BIT(9));
|
||||
mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
@ -40,7 +140,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev = mt76x0_alloc_device(&pdev->dev, NULL);
|
||||
dev = mt76x0_alloc_device(&pdev->dev, NULL, &mt76x0e_ops);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -49,7 +149,13 @@ 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);
|
||||
|
||||
/* error: */
|
||||
ret = mt76x0e_register_device(dev);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ieee80211_free_hw(mt76_hw(dev));
|
||||
return ret;
|
||||
}
|
||||
@ -65,6 +171,7 @@ mt76x0e_remove(struct pci_dev *pdev)
|
||||
|
||||
static const struct pci_device_id mt76x0e_device_table[] = {
|
||||
{ PCI_DEVICE(0x14c3, 0x7630) },
|
||||
{ PCI_DEVICE(0x14c3, 0x7650) },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
146
drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c
Normal file
146
drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "mt76x0.h"
|
||||
#include "mcu.h"
|
||||
|
||||
#define MT7610E_FIRMWARE "mediatek/mt7610e.bin"
|
||||
#define MT7650E_FIRMWARE "mediatek/mt7650e.bin"
|
||||
|
||||
#define MT_MCU_IVB_ADDR (MT_MCU_ILM_ADDR + 0x54000 - MT_MCU_IVB_SIZE)
|
||||
|
||||
static int mt76x0e_load_firmware(struct mt76x0_dev *dev)
|
||||
{
|
||||
bool is_combo_chip = mt76_chip(&dev->mt76) != 0x7610;
|
||||
u32 val, ilm_len, dlm_len, offset = 0;
|
||||
const struct mt76x02_fw_header *hdr;
|
||||
const struct firmware *fw;
|
||||
const char *firmware;
|
||||
const u8 *fw_payload;
|
||||
int len, err;
|
||||
|
||||
if (is_combo_chip)
|
||||
firmware = MT7650E_FIRMWARE;
|
||||
else
|
||||
firmware = MT7610E_FIRMWARE;
|
||||
|
||||
err = request_firmware(&fw, firmware, dev->mt76.dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt76x02_fw_header *)fw->data;
|
||||
|
||||
len = sizeof(*hdr);
|
||||
len += le32_to_cpu(hdr->ilm_len);
|
||||
len += le32_to_cpu(hdr->dlm_len);
|
||||
|
||||
if (fw->size != len) {
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fw_payload = fw->data + sizeof(*hdr);
|
||||
|
||||
val = le16_to_cpu(hdr->fw_ver);
|
||||
dev_info(dev->mt76.dev, "Firmware Version: %d.%d.%02d\n",
|
||||
(val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf);
|
||||
|
||||
val = le16_to_cpu(hdr->fw_ver);
|
||||
dev_dbg(dev->mt76.dev,
|
||||
"Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
|
||||
(val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
|
||||
le16_to_cpu(hdr->build_ver), hdr->build_time);
|
||||
|
||||
if (is_combo_chip && !mt76_poll(dev, MT_MCU_SEMAPHORE_00, 1, 1, 600)) {
|
||||
dev_err(dev->mt76.dev,
|
||||
"Could not get hardware semaphore for loading fw\n");
|
||||
err = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* upload ILM. */
|
||||
mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
|
||||
ilm_len = le32_to_cpu(hdr->ilm_len);
|
||||
if (is_combo_chip) {
|
||||
ilm_len -= MT_MCU_IVB_SIZE;
|
||||
offset = MT_MCU_IVB_SIZE;
|
||||
}
|
||||
dev_dbg(dev->mt76.dev, "loading FW - ILM %u\n", ilm_len);
|
||||
mt76_wr_copy(dev, MT_MCU_ILM_ADDR + offset, fw_payload + offset,
|
||||
ilm_len);
|
||||
|
||||
/* upload IVB. */
|
||||
if (is_combo_chip) {
|
||||
dev_dbg(dev->mt76.dev, "loading FW - IVB %u\n",
|
||||
MT_MCU_IVB_SIZE);
|
||||
mt76_wr_copy(dev, MT_MCU_IVB_ADDR, fw_payload, MT_MCU_IVB_SIZE);
|
||||
}
|
||||
|
||||
/* upload DLM. */
|
||||
mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, MT_MCU_DLM_OFFSET);
|
||||
dlm_len = le32_to_cpu(hdr->dlm_len);
|
||||
dev_dbg(dev->mt76.dev, "loading FW - DLM %u\n", dlm_len);
|
||||
mt76_wr_copy(dev, MT_MCU_ILM_ADDR,
|
||||
fw_payload + le32_to_cpu(hdr->ilm_len), dlm_len);
|
||||
|
||||
/* trigger firmware */
|
||||
mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
|
||||
if (is_combo_chip)
|
||||
mt76_wr(dev, MT_MCU_INT_LEVEL, 0x3);
|
||||
else
|
||||
mt76_wr(dev, MT_MCU_RESET_CTL, 0x300);
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 1000)) {
|
||||
dev_err(dev->mt76.dev, "Firmware failed to start\n");
|
||||
err = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(dev->mt76.dev, "Firmware running!\n");
|
||||
|
||||
out:
|
||||
if (is_combo_chip)
|
||||
mt76_wr(dev, MT_MCU_SEMAPHORE_00, 0x1);
|
||||
release_firmware(fw);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mt76x0e_mcu_init(struct mt76x0_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt76x0e_mcu_ops = {
|
||||
.mcu_msg_alloc = mt76x02_mcu_msg_alloc,
|
||||
.mcu_send_msg = mt76x02_mcu_msg_send,
|
||||
};
|
||||
int err;
|
||||
|
||||
dev->mt76.mcu_ops = &mt76x0e_mcu_ops;
|
||||
|
||||
err = mt76x0e_load_firmware(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
|
||||
|
||||
return 0;
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
#include "phy.h"
|
||||
#include "initvals.h"
|
||||
#include "initvals_phy.h"
|
||||
#include "../mt76x02_phy.h"
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
@ -228,20 +229,9 @@ mt76x0_bbp_set_ctrlch(struct mt76x0_dev *dev, enum nl80211_chan_width width,
|
||||
|
||||
int mt76x0_phy_get_rssi(struct mt76x0_dev *dev, struct mt76x02_rxwi *rxwi)
|
||||
{
|
||||
s8 lna_gain, rssi_offset;
|
||||
int val;
|
||||
struct mt76x0_caldata *caldata = &dev->caldata;
|
||||
|
||||
if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) {
|
||||
lna_gain = dev->ee->lna_gain_2ghz;
|
||||
rssi_offset = dev->ee->rssi_offset_2ghz[0];
|
||||
} else {
|
||||
lna_gain = dev->ee->lna_gain_5ghz[0];
|
||||
rssi_offset = dev->ee->rssi_offset_5ghz[0];
|
||||
}
|
||||
|
||||
val = rxwi->rssi[0] + rssi_offset - lna_gain;
|
||||
|
||||
return val;
|
||||
return rxwi->rssi[0] + caldata->rssi_offset[0] - caldata->lna_gain;
|
||||
}
|
||||
|
||||
static void mt76x0_vco_cal(struct mt76x0_dev *dev, u8 channel)
|
||||
@ -340,16 +330,12 @@ mt76x0_phy_set_band(struct mt76x0_dev *dev, enum nl80211_band band)
|
||||
}
|
||||
}
|
||||
|
||||
#define EXT_PA_2G_5G 0x0
|
||||
#define EXT_PA_5G_ONLY 0x1
|
||||
#define EXT_PA_2G_ONLY 0x2
|
||||
#define INT_PA_2G_5G 0x3
|
||||
|
||||
static void
|
||||
mt76x0_phy_set_chan_rf_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band)
|
||||
{
|
||||
u16 rf_band = rf_bw_band & 0xff00;
|
||||
u16 rf_bw = rf_bw_band & 0x00ff;
|
||||
enum nl80211_band band;
|
||||
u32 mac_reg;
|
||||
u8 rf_val;
|
||||
int i;
|
||||
@ -496,11 +482,8 @@ mt76x0_phy_set_chan_rf_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band
|
||||
mac_reg &= ~0xC; /* Clear 0x518[3:2] */
|
||||
mt76_wr(dev, MT_RF_MISC, mac_reg);
|
||||
|
||||
if (dev->ee->pa_type == INT_PA_2G_5G ||
|
||||
(dev->ee->pa_type == EXT_PA_5G_ONLY && (rf_band & RF_G_BAND)) ||
|
||||
(dev->ee->pa_type == EXT_PA_2G_ONLY && (rf_band & RF_A_BAND))) {
|
||||
; /* Internal PA - nothing to do. */
|
||||
} else {
|
||||
band = (rf_band & RF_G_BAND) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
|
||||
/*
|
||||
MT_RF_MISC (offset: 0x0518)
|
||||
[2]1'b1: enable external A band PA, 1'b0: disable external A band PA
|
||||
@ -552,20 +535,10 @@ mt76x0_phy_set_chan_bbp_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_ban
|
||||
|
||||
if (pair->reg == MT_BBP(AGC, 8)) {
|
||||
u32 val = pair->value;
|
||||
u8 gain = FIELD_GET(MT_BBP_AGC_GAIN, val);
|
||||
|
||||
if (channel > 14) {
|
||||
if (channel < 100)
|
||||
gain -= dev->ee->lna_gain_5ghz[0]*2;
|
||||
else if (channel < 137)
|
||||
gain -= dev->ee->lna_gain_5ghz[1]*2;
|
||||
else
|
||||
gain -= dev->ee->lna_gain_5ghz[2]*2;
|
||||
|
||||
} else {
|
||||
gain -= dev->ee->lna_gain_2ghz*2;
|
||||
}
|
||||
u8 gain;
|
||||
|
||||
gain = FIELD_GET(MT_BBP_AGC_GAIN, val);
|
||||
gain -= dev->caldata.lna_gain * 2;
|
||||
val &= ~MT_BBP_AGC_GAIN;
|
||||
val |= FIELD_PREP(MT_BBP_AGC_GAIN, gain);
|
||||
mt76_wr(dev, pair->reg, val);
|
||||
@ -575,43 +548,24 @@ mt76x0_phy_set_chan_bbp_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_ban
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
mt76x0_extra_power_over_mac(struct mt76x0_dev *dev)
|
||||
static void mt76x0_ant_select(struct mt76x0_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
|
||||
|
||||
val = ((mt76_rr(dev, MT_TX_PWR_CFG_1) & 0x00003f00) >> 8);
|
||||
val |= ((mt76_rr(dev, MT_TX_PWR_CFG_2) & 0x00003f00) << 8);
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_7, val);
|
||||
|
||||
/* TODO: fix VHT */
|
||||
val = ((mt76_rr(dev, MT_TX_PWR_CFG_3) & 0x0000ff00) >> 8);
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_8, val);
|
||||
|
||||
val = ((mt76_rr(dev, MT_TX_PWR_CFG_4) & 0x0000ff00) >> 8);
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_9, val);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_phy_set_tx_power(struct mt76x0_dev *dev, u8 channel, u8 rf_bw_band)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
int bw = (rf_bw_band & RF_BW_20) ? 0 : 1;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (channel <= 14)
|
||||
val = dev->ee->tx_pwr_cfg_2g[i][bw];
|
||||
else
|
||||
val = dev->ee->tx_pwr_cfg_5g[i][bw];
|
||||
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_0 + 4*i, val);
|
||||
/* single antenna mode */
|
||||
if (chan->band == NL80211_BAND_2GHZ) {
|
||||
mt76_rmw(dev, MT_COEXCFG3,
|
||||
BIT(5) | BIT(4) | BIT(3) | BIT(2), BIT(1));
|
||||
mt76_rmw(dev, MT_WLAN_FUN_CTRL, BIT(5), BIT(6));
|
||||
} else {
|
||||
mt76_rmw(dev, MT_COEXCFG3, BIT(5) | BIT(2),
|
||||
BIT(4) | BIT(3));
|
||||
mt76_clear(dev, MT_WLAN_FUN_CTRL,
|
||||
BIT(6) | BIT(5));
|
||||
}
|
||||
|
||||
mt76x0_extra_power_over_mac(dev);
|
||||
mt76_clear(dev, MT_CMB_CTRL, BIT(14) | BIT(12));
|
||||
mt76_clear(dev, MT_COEXCFG0, BIT(2));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
mt76x0_bbp_set_bw(struct mt76x0_dev *dev, enum nl80211_chan_width width)
|
||||
@ -644,31 +598,20 @@ mt76x0_bbp_set_bw(struct mt76x0_dev *dev, enum nl80211_chan_width width)
|
||||
mt76x02_mcu_function_select(&dev->mt76, BW_SETTING, bw, false);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_phy_set_chan_pwr(struct mt76x0_dev *dev, u8 channel)
|
||||
void mt76x0_phy_set_txpower(struct mt76x0_dev *dev)
|
||||
{
|
||||
static const int mt76x0_tx_pwr_ch_list[] = {
|
||||
1,2,3,4,5,6,7,8,9,10,11,12,13,14,
|
||||
36,38,40,44,46,48,52,54,56,60,62,64,
|
||||
100,102,104,108,110,112,116,118,120,124,126,128,132,134,136,140,
|
||||
149,151,153,157,159,161,165,167,169,171,173,
|
||||
42,58,106,122,155
|
||||
};
|
||||
int i;
|
||||
u32 val;
|
||||
struct mt76_rate_power *t = &dev->mt76.rate_power;
|
||||
u8 info[2];
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt76x0_tx_pwr_ch_list); i++)
|
||||
if (mt76x0_tx_pwr_ch_list[i] == channel)
|
||||
break;
|
||||
mt76x0_get_power_info(dev, info);
|
||||
mt76x0_get_tx_power_per_rate(dev);
|
||||
|
||||
if (WARN_ON(i == ARRAY_SIZE(mt76x0_tx_pwr_ch_list)))
|
||||
return;
|
||||
mt76x02_add_rate_power_offset(t, info[0]);
|
||||
mt76x02_limit_rate_power(t, dev->mt76.txpower_conf);
|
||||
dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t);
|
||||
mt76x02_add_rate_power_offset(t, -info[0]);
|
||||
|
||||
val = mt76_rr(dev, MT_TX_ALC_CFG_0);
|
||||
val &= ~0x3f3f;
|
||||
val |= dev->ee->tx_pwr_per_chan[i];
|
||||
val |= 0x2f2f << 16;
|
||||
mt76_wr(dev, MT_TX_ALC_CFG_0, val);
|
||||
mt76x02_phy_set_txpower(&dev->mt76, info[0], info[1]);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -707,6 +650,7 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev,
|
||||
freq1 = chandef->center_freq1;
|
||||
channel = chandef->chan->hw_value;
|
||||
rf_bw_band = (channel <= 14) ? RF_G_BAND : RF_A_BAND;
|
||||
dev->mt76.chandef = *chandef;
|
||||
|
||||
switch (chandef->width) {
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
@ -733,6 +677,7 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev,
|
||||
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);
|
||||
mt76x0_ant_select(dev);
|
||||
|
||||
mt76_rmw(dev, MT_EXT_CCA_CFG,
|
||||
(MT_EXT_CCA_CFG_CCA0 |
|
||||
@ -744,6 +689,7 @@ __mt76x0_phy_set_channel(struct mt76x0_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));
|
||||
@ -762,9 +708,8 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev,
|
||||
if (scan)
|
||||
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 1, false);
|
||||
|
||||
mt76x0_phy_set_chan_pwr(dev, channel);
|
||||
mt76x0_phy_set_txpower(dev);
|
||||
|
||||
dev->mt76.chandef = *chandef;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -863,7 +808,7 @@ static void mt76x0_temp_sensor(struct mt76x0_dev *dev)
|
||||
else
|
||||
sval |= 0xffffff00; /* Negative */
|
||||
|
||||
temp = (35 * (sval - dev->ee->temp_off))/ 10 + 25;
|
||||
temp = (35 * (sval - dev->caldata.temp_offset)) / 10 + 25;
|
||||
|
||||
done:
|
||||
rf_wr(dev, MT_RF(7, 73), rf_b7_73);
|
||||
@ -910,32 +855,6 @@ void mt76x0_phy_con_cal_onoff(struct mt76x0_dev *dev,
|
||||
spin_unlock_bh(&dev->con_mon_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_rx_chains(struct mt76x0_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = mt76_rr(dev, MT_BBP(AGC, 0));
|
||||
val &= ~(BIT(3) | BIT(4));
|
||||
|
||||
if (dev->chainmask & BIT(1))
|
||||
val |= BIT(3);
|
||||
|
||||
mt76_wr(dev, MT_BBP(AGC, 0), val);
|
||||
|
||||
mb();
|
||||
val = mt76_rr(dev, MT_BBP(AGC, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_set_tx_dac(struct mt76x0_dev *dev)
|
||||
{
|
||||
if (dev->chainmask & BIT(1))
|
||||
mt76_set(dev, MT_BBP(TXBE, 5), 3);
|
||||
else
|
||||
mt76_clear(dev, MT_BBP(TXBE, 5), 3);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x0_rf_init(struct mt76x0_dev *dev)
|
||||
{
|
||||
@ -969,7 +888,8 @@ mt76x0_rf_init(struct mt76x0_dev *dev)
|
||||
E1: B0.R22<6:0>: xo_cxo<6:0>
|
||||
E2: B0.R21<0>: xo_cxo<0>, B0.R22<7:0>: xo_cxo<8:1>
|
||||
*/
|
||||
rf_wr(dev, MT_RF(0, 22), min_t(u8, dev->ee->rf_freq_off, 0xBF));
|
||||
rf_wr(dev, MT_RF(0, 22),
|
||||
min_t(u8, dev->caldata.freq_offset, 0xbf));
|
||||
val = rf_rr(dev, MT_RF(0, 22));
|
||||
|
||||
/*
|
||||
@ -989,23 +909,11 @@ mt76x0_rf_init(struct mt76x0_dev *dev)
|
||||
rf_set(dev, MT_RF(0, 4), 0x80);
|
||||
}
|
||||
|
||||
static void mt76x0_ant_select(struct mt76x0_dev *dev)
|
||||
{
|
||||
/* Single antenna mode. */
|
||||
mt76_rmw(dev, MT_WLAN_FUN_CTRL, BIT(5), BIT(6));
|
||||
mt76_clear(dev, MT_CMB_CTRL, BIT(14) | BIT(12));
|
||||
mt76_clear(dev, MT_COEXCFG0, BIT(2));
|
||||
mt76_rmw(dev, MT_COEXCFG3, BIT(5) | BIT(4) | BIT(3) | BIT(2), BIT(1));
|
||||
}
|
||||
|
||||
void mt76x0_phy_init(struct mt76x0_dev *dev)
|
||||
{
|
||||
INIT_DELAYED_WORK(&dev->cal_work, mt76x0_phy_calibrate);
|
||||
|
||||
mt76x0_ant_select(dev);
|
||||
|
||||
mt76x0_rf_init(dev);
|
||||
|
||||
mt76x0_set_rx_chains(dev);
|
||||
mt76x0_set_tx_dac(dev);
|
||||
mt76x02_phy_set_rxpath(&dev->mt76);
|
||||
mt76x02_phy_set_txdac(&dev->mt76);
|
||||
}
|
||||
|
@ -17,10 +17,10 @@
|
||||
#include "../mt76x02_util.h"
|
||||
#include "../mt76x02_usb.h"
|
||||
|
||||
static struct mt76x02_txwi *
|
||||
struct mt76x02_txwi *
|
||||
mt76x0_push_txwi(struct mt76x0_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, struct mt76_wcid *wcid,
|
||||
int pkt_len)
|
||||
struct ieee80211_sta *sta, struct mt76_wcid *wcid,
|
||||
int pkt_len)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_rate *rate = &info->control.rates[0];
|
||||
@ -53,6 +53,7 @@ mt76x0_push_txwi(struct mt76x0_dev *dev, struct sk_buff *skb,
|
||||
|
||||
return txwi;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_push_txwi);
|
||||
|
||||
void mt76x0_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
|
||||
struct sk_buff *skb)
|
||||
@ -81,22 +82,7 @@ void mt76x0_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
|
||||
|
||||
mt76_tx(&dev->mt76, control->sta, wcid, skb);
|
||||
}
|
||||
|
||||
int mt76x0_tx_prepare_skb(struct mt76_dev *mdev, void *data,
|
||||
struct sk_buff *skb, struct mt76_queue *q,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
|
||||
u32 *tx_info)
|
||||
{
|
||||
struct mt76x0_dev *dev = container_of(mdev, struct mt76x0_dev, mt76);
|
||||
struct mt76x02_txwi *txwi;
|
||||
int len = skb->len;
|
||||
|
||||
mt76x02_insert_hdr_pad(skb);
|
||||
txwi = mt76x0_push_txwi(dev, skb, sta, wcid, len);
|
||||
|
||||
return mt76x02u_set_txinfo(skb, wcid, q2ep(q->hw_idx));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x0_tx_prepare_skb);
|
||||
EXPORT_SYMBOL_GPL(mt76x0_tx);
|
||||
|
||||
void mt76x0_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb)
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "mt76x0.h"
|
||||
@ -22,8 +21,6 @@
|
||||
#include "../mt76x02_util.h"
|
||||
#include "../mt76x02_usb.h"
|
||||
|
||||
#define MT7610U_FIRMWARE "mediatek/mt7610u.bin"
|
||||
|
||||
static struct usb_device_id mt76x0_device_table[] = {
|
||||
{ USB_DEVICE(0x148F, 0x7610) }, /* MT7610U */
|
||||
{ USB_DEVICE(0x13B1, 0x003E) }, /* Linksys AE6000 */
|
||||
@ -45,174 +42,195 @@ static struct usb_device_id mt76x0_device_table[] = {
|
||||
{ USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH */
|
||||
{ USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */
|
||||
{ USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac Stick */
|
||||
{ USB_DEVICE(0x2357, 0x0105) }, /* TP-LINK Archer T1U */
|
||||
{ USB_DEVICE(0x2357, 0x0105),
|
||||
.driver_info = 1, }, /* TP-LINK Archer T1U */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7630, 0xff, 0x2, 0xff)}, /* MT7630U */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7650, 0xff, 0x2, 0xff)}, /* MT7650U */
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
#define MCU_FW_URB_MAX_PAYLOAD 0x38f8
|
||||
#define MCU_FW_URB_SIZE (MCU_FW_URB_MAX_PAYLOAD + 12)
|
||||
|
||||
static inline int mt76x0_firmware_running(struct mt76x0_dev *dev)
|
||||
static void mt76x0_init_usb_dma(struct mt76x0_dev *dev)
|
||||
{
|
||||
return mt76_rr(dev, MT_MCU_COM_REG0) == 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x0u_upload_firmware(struct mt76x0_dev *dev,
|
||||
const struct mt76x02_fw_header *hdr)
|
||||
{
|
||||
u8 *fw_payload = (u8 *)(hdr + 1);
|
||||
u32 ilm_len, dlm_len;
|
||||
void *ivb;
|
||||
int err;
|
||||
|
||||
ivb = kmemdup(fw_payload, MT_MCU_IVB_SIZE, GFP_KERNEL);
|
||||
if (!ivb)
|
||||
return -ENOMEM;
|
||||
|
||||
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,
|
||||
ilm_len, MCU_FW_URB_MAX_PAYLOAD,
|
||||
MT_MCU_IVB_SIZE);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
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,
|
||||
fw_payload + le32_to_cpu(hdr->ilm_len),
|
||||
dlm_len, MCU_FW_URB_MAX_PAYLOAD,
|
||||
MT_MCU_DLM_OFFSET);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x12, 0, ivb, MT_MCU_IVB_SIZE);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 1000)) {
|
||||
dev_err(dev->mt76.dev, "Firmware failed to start\n");
|
||||
err = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(dev->mt76.dev, "Firmware running!\n");
|
||||
|
||||
out:
|
||||
kfree(ivb);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt76x0u_load_firmware(struct mt76x0_dev *dev)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const struct mt76x02_fw_header *hdr;
|
||||
int len, ret;
|
||||
u32 val;
|
||||
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
|
||||
MT_USB_DMA_CFG_TX_BULK_EN));
|
||||
val = mt76_rr(dev, MT_USB_DMA_CFG);
|
||||
|
||||
if (mt76x0_firmware_running(dev))
|
||||
return 0;
|
||||
val |= MT_USB_DMA_CFG_RX_BULK_EN |
|
||||
MT_USB_DMA_CFG_TX_BULK_EN;
|
||||
|
||||
ret = request_firmware(&fw, MT7610U_FIRMWARE, dev->mt76.dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* disable AGGR_BULK_RX in order to receive one
|
||||
* frame in each rx urb and avoid copies
|
||||
*/
|
||||
val &= ~MT_USB_DMA_CFG_RX_BULK_AGG_EN;
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr))
|
||||
goto err_inv_fw;
|
||||
|
||||
hdr = (const struct mt76x02_fw_header *)fw->data;
|
||||
|
||||
if (le32_to_cpu(hdr->ilm_len) <= MT_MCU_IVB_SIZE)
|
||||
goto err_inv_fw;
|
||||
|
||||
len = sizeof(*hdr);
|
||||
len += le32_to_cpu(hdr->ilm_len);
|
||||
len += le32_to_cpu(hdr->dlm_len);
|
||||
|
||||
if (fw->size != len)
|
||||
goto err_inv_fw;
|
||||
|
||||
val = le16_to_cpu(hdr->fw_ver);
|
||||
dev_dbg(dev->mt76.dev,
|
||||
"Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
|
||||
(val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
|
||||
le16_to_cpu(hdr->build_ver), hdr->build_time);
|
||||
|
||||
len = le32_to_cpu(hdr->ilm_len);
|
||||
|
||||
mt76_wr(dev, 0x1004, 0x2c);
|
||||
|
||||
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);
|
||||
msleep(5);
|
||||
/*
|
||||
mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |
|
||||
MT_PBF_CFG_TX1Q_EN |
|
||||
MT_PBF_CFG_TX2Q_EN |
|
||||
MT_PBF_CFG_TX3Q_EN));
|
||||
*/
|
||||
|
||||
mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
|
||||
|
||||
/* FCE tx_fs_base_ptr */
|
||||
mt76_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
|
||||
/* FCE tx_fs_max_cnt */
|
||||
mt76_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 1);
|
||||
/* FCE pdma enable */
|
||||
mt76_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
|
||||
/* FCE skip_fs_en */
|
||||
mt76_wr(dev, MT_FCE_SKIP_FS, 3);
|
||||
val = mt76_rr(dev, MT_COM_REG0);
|
||||
if (val & 1)
|
||||
dev_dbg(dev->mt76.dev, "MCU not ready\n");
|
||||
|
||||
val = mt76_rr(dev, MT_USB_DMA_CFG);
|
||||
val |= MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
|
||||
|
||||
val |= MT_USB_DMA_CFG_RX_DROP_OR_PAD;
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
val &= ~MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
|
||||
val &= ~MT_USB_DMA_CFG_RX_DROP_OR_PAD;
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
|
||||
ret = mt76x0u_upload_firmware(dev, hdr);
|
||||
release_firmware(fw);
|
||||
|
||||
mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
|
||||
|
||||
return ret;
|
||||
|
||||
err_inv_fw:
|
||||
dev_err(dev->mt76.dev, "Invalid firmware image\n");
|
||||
release_firmware(fw);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int mt76x0u_mcu_init(struct mt76x0_dev *dev)
|
||||
static void mt76x0u_cleanup(struct mt76x0_dev *dev)
|
||||
{
|
||||
clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
|
||||
mt76x0_chip_onoff(dev, false, false);
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
mt76u_mcu_deinit(&dev->mt76);
|
||||
}
|
||||
|
||||
static void mt76x0u_mac_stop(struct mt76x0_dev *dev)
|
||||
{
|
||||
if (test_bit(MT76_REMOVED, &dev->mt76.state))
|
||||
return;
|
||||
|
||||
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
|
||||
cancel_delayed_work_sync(&dev->cal_work);
|
||||
cancel_delayed_work_sync(&dev->mac_work);
|
||||
mt76u_stop_stat_wk(&dev->mt76);
|
||||
|
||||
mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
|
||||
MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
|
||||
MT_BEACON_TIME_CFG_BEACON_TX);
|
||||
|
||||
if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
|
||||
dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
|
||||
|
||||
mt76x0_mac_stop(dev);
|
||||
|
||||
if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
|
||||
dev_warn(dev->mt76.dev, "RX DMA did not stop\n");
|
||||
}
|
||||
|
||||
static int mt76x0u_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
int ret;
|
||||
|
||||
ret = mt76x0u_load_firmware(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
|
||||
ret = mt76x0_mac_start(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
|
||||
MT_CALIBRATE_INTERVAL);
|
||||
set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt76x0u_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt76x0_dev *dev = hw->priv;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mt76x0u_mac_stop(dev);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops mt76x0u_ops = {
|
||||
.tx = mt76x0_tx,
|
||||
.start = mt76x0u_start,
|
||||
.stop = mt76x0u_stop,
|
||||
.add_interface = mt76x02_add_interface,
|
||||
.remove_interface = mt76x02_remove_interface,
|
||||
.config = mt76x0_config,
|
||||
.configure_filter = mt76x02_configure_filter,
|
||||
.bss_info_changed = mt76x0_bss_info_changed,
|
||||
.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,
|
||||
.set_rts_threshold = mt76x0_set_rts_threshold,
|
||||
.wake_tx_queue = mt76_wake_tx_queue,
|
||||
};
|
||||
|
||||
static int mt76x0u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
|
||||
struct sk_buff *skb, struct mt76_queue *q,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
|
||||
u32 *tx_info)
|
||||
{
|
||||
struct mt76x0_dev *dev = container_of(mdev, struct mt76x0_dev, mt76);
|
||||
struct mt76x02_txwi *txwi;
|
||||
int len = skb->len;
|
||||
|
||||
mt76x02_insert_hdr_pad(skb);
|
||||
txwi = mt76x0_push_txwi(dev, skb, sta, wcid, len);
|
||||
|
||||
return mt76x02u_set_txinfo(skb, wcid, q2ep(q->hw_idx));
|
||||
}
|
||||
|
||||
static int mt76x0u_register_device(struct mt76x0_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = dev->mt76.hw;
|
||||
int err;
|
||||
|
||||
err = mt76u_mcu_init_rx(&dev->mt76);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt76u_alloc_queues(&dev->mt76);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
mt76x0_chip_onoff(dev, true, true);
|
||||
if (!mt76x02_wait_for_mac(&dev->mt76)) {
|
||||
err = -ETIMEDOUT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = mt76x0u_mcu_init(dev);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
mt76x0_init_usb_dma(dev);
|
||||
err = mt76x0_init_hardware(dev);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
|
||||
mt76_wr(dev, MT_TXOP_CTRL_CFG,
|
||||
FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
|
||||
FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
|
||||
|
||||
err = mt76x0_register_device(dev);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
/* check hw sg support in order to enable AMSDU */
|
||||
if (mt76u_check_sg(&dev->mt76))
|
||||
hw->max_tx_fragments = MT_SG_MAX_SIZE;
|
||||
else
|
||||
hw->max_tx_fragments = 1;
|
||||
|
||||
set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
mt76x0u_cleanup(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt76x0u_probe(struct usb_interface *usb_intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
.tx_prepare_skb = mt76x0_tx_prepare_skb,
|
||||
.tx_prepare_skb = mt76x0u_tx_prepare_skb,
|
||||
.tx_complete_skb = mt76x02_tx_complete_skb,
|
||||
.tx_status_data = mt76x02_tx_status_data,
|
||||
.rx_skb = mt76x0_queue_rx_skb,
|
||||
@ -222,10 +240,15 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
|
||||
u32 asic_rev, mac_rev;
|
||||
int ret;
|
||||
|
||||
dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops);
|
||||
dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops,
|
||||
&mt76x0u_ops);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Quirk for Archer T1U */
|
||||
if (id->driver_info)
|
||||
dev->no_2ghz = true;
|
||||
|
||||
usb_dev = usb_get_dev(usb_dev);
|
||||
usb_reset_device(usb_dev);
|
||||
|
||||
@ -253,32 +276,12 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
|
||||
if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
|
||||
dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n");
|
||||
|
||||
ret = mt76u_mcu_init_rx(&dev->mt76);
|
||||
ret = mt76x0u_register_device(dev);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = mt76u_alloc_queues(&dev->mt76);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
mt76x0_chip_onoff(dev, true, true);
|
||||
|
||||
if (!mt76x02_wait_for_mac(&dev->mt76))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
ret = mt76x0u_mcu_init(dev);
|
||||
if (ret)
|
||||
goto err_hw;
|
||||
|
||||
ret = mt76x0_register_device(dev);
|
||||
if (ret)
|
||||
goto err_hw;
|
||||
|
||||
set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
|
||||
|
||||
return 0;
|
||||
err_hw:
|
||||
mt76x0_cleanup(dev);
|
||||
|
||||
err:
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
@ -296,7 +299,7 @@ static void mt76x0_disconnect(struct usb_interface *usb_intf)
|
||||
return;
|
||||
|
||||
ieee80211_unregister_hw(dev->mt76.hw);
|
||||
mt76x0_cleanup(dev);
|
||||
mt76x0u_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
@ -311,7 +314,7 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
|
||||
struct mt76_usb *usb = &dev->mt76.usb;
|
||||
|
||||
mt76u_stop_queues(&dev->mt76);
|
||||
mt76x0_mac_stop(dev);
|
||||
mt76x0u_mac_stop(dev);
|
||||
usb_kill_urb(usb->mcu.res.urb);
|
||||
|
||||
return 0;
|
||||
@ -345,12 +348,11 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mt76x0_cleanup(dev);
|
||||
mt76x0u_cleanup(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, mt76x0_device_table);
|
||||
MODULE_FIRMWARE(MT7610U_FIRMWARE);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static struct usb_driver mt76x0_driver = {
|
||||
|
176
drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
Normal file
176
drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "mt76x0.h"
|
||||
#include "mcu.h"
|
||||
#include "../mt76x02_usb.h"
|
||||
|
||||
#define MCU_FW_URB_MAX_PAYLOAD 0x38f8
|
||||
#define MCU_FW_URB_SIZE (MCU_FW_URB_MAX_PAYLOAD + 12)
|
||||
#define MT7610U_FIRMWARE "mediatek/mt7610u.bin"
|
||||
|
||||
static int
|
||||
mt76x0u_upload_firmware(struct mt76x0_dev *dev,
|
||||
const struct mt76x02_fw_header *hdr)
|
||||
{
|
||||
u8 *fw_payload = (u8 *)(hdr + 1);
|
||||
u32 ilm_len, dlm_len;
|
||||
void *ivb;
|
||||
int err;
|
||||
|
||||
ivb = kmemdup(fw_payload, MT_MCU_IVB_SIZE, GFP_KERNEL);
|
||||
if (!ivb)
|
||||
return -ENOMEM;
|
||||
|
||||
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,
|
||||
ilm_len, MCU_FW_URB_MAX_PAYLOAD,
|
||||
MT_MCU_IVB_SIZE);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
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,
|
||||
fw_payload + le32_to_cpu(hdr->ilm_len),
|
||||
dlm_len, MCU_FW_URB_MAX_PAYLOAD,
|
||||
MT_MCU_DLM_OFFSET);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x12, 0, ivb, MT_MCU_IVB_SIZE);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 1000)) {
|
||||
dev_err(dev->mt76.dev, "Firmware failed to start\n");
|
||||
err = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(dev->mt76.dev, "Firmware running!\n");
|
||||
|
||||
out:
|
||||
kfree(ivb);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt76x0u_load_firmware(struct mt76x0_dev *dev)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const struct mt76x02_fw_header *hdr;
|
||||
int len, ret;
|
||||
u32 val;
|
||||
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
|
||||
MT_USB_DMA_CFG_TX_BULK_EN));
|
||||
|
||||
if (mt76x0_firmware_running(dev))
|
||||
return 0;
|
||||
|
||||
ret = request_firmware(&fw, MT7610U_FIRMWARE, dev->mt76.dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr))
|
||||
goto err_inv_fw;
|
||||
|
||||
hdr = (const struct mt76x02_fw_header *)fw->data;
|
||||
|
||||
if (le32_to_cpu(hdr->ilm_len) <= MT_MCU_IVB_SIZE)
|
||||
goto err_inv_fw;
|
||||
|
||||
len = sizeof(*hdr);
|
||||
len += le32_to_cpu(hdr->ilm_len);
|
||||
len += le32_to_cpu(hdr->dlm_len);
|
||||
|
||||
if (fw->size != len)
|
||||
goto err_inv_fw;
|
||||
|
||||
val = le16_to_cpu(hdr->fw_ver);
|
||||
dev_dbg(dev->mt76.dev,
|
||||
"Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
|
||||
(val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
|
||||
le16_to_cpu(hdr->build_ver), hdr->build_time);
|
||||
|
||||
len = le32_to_cpu(hdr->ilm_len);
|
||||
|
||||
mt76_wr(dev, 0x1004, 0x2c);
|
||||
|
||||
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);
|
||||
usleep_range(5000, 6000);
|
||||
/*
|
||||
mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |
|
||||
MT_PBF_CFG_TX1Q_EN |
|
||||
MT_PBF_CFG_TX2Q_EN |
|
||||
MT_PBF_CFG_TX3Q_EN));
|
||||
*/
|
||||
|
||||
mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
|
||||
|
||||
/* FCE tx_fs_base_ptr */
|
||||
mt76_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
|
||||
/* FCE tx_fs_max_cnt */
|
||||
mt76_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 1);
|
||||
/* FCE pdma enable */
|
||||
mt76_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
|
||||
/* FCE skip_fs_en */
|
||||
mt76_wr(dev, MT_FCE_SKIP_FS, 3);
|
||||
|
||||
val = mt76_rr(dev, MT_USB_DMA_CFG);
|
||||
val |= MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
val &= ~MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
|
||||
ret = mt76x0u_upload_firmware(dev, hdr);
|
||||
release_firmware(fw);
|
||||
|
||||
mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
|
||||
|
||||
return ret;
|
||||
|
||||
err_inv_fw:
|
||||
dev_err(dev->mt76.dev, "Invalid firmware image\n");
|
||||
release_firmware(fw);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int mt76x0u_mcu_init(struct mt76x0_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt76x0u_load_firmware(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_FIRMWARE(MT7610U_FIRMWARE);
|
@ -18,6 +18,7 @@
|
||||
#define __MT76x02_DMA_H
|
||||
|
||||
#include "dma.h"
|
||||
#include "mt76x02_regs.h"
|
||||
|
||||
#define MT_TXD_INFO_LEN GENMASK(15, 0)
|
||||
#define MT_TXD_INFO_NEXT_VLD BIT(16)
|
||||
@ -47,6 +48,9 @@
|
||||
#define MT_MCU_MSG_TYPE GENMASK(31, 30)
|
||||
#define MT_MCU_MSG_TYPE_CMD BIT(30)
|
||||
|
||||
#define MT_RX_HEADROOM 32
|
||||
#define MT76X02_RX_RING_SIZE 256
|
||||
|
||||
enum dma_msg_port {
|
||||
WLAN_PORT,
|
||||
CPU_RX_PORT,
|
||||
@ -57,4 +61,17 @@ enum dma_msg_port {
|
||||
DISCARD,
|
||||
};
|
||||
|
||||
static inline bool
|
||||
mt76x02_wait_for_wpdma(struct mt76_dev *dev, int timeout)
|
||||
{
|
||||
return __mt76_poll(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
|
||||
0, timeout);
|
||||
}
|
||||
|
||||
int mt76x02_dma_init(struct mt76_dev *dev);
|
||||
void mt76x02_dma_enable(struct mt76_dev *dev);
|
||||
void mt76x02_dma_disable(struct mt76_dev *dev);
|
||||
|
||||
#endif /* __MT76x02_DMA_H */
|
||||
|
156
drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
Normal file
156
drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "mt76.h"
|
||||
#include "mt76x02_eeprom.h"
|
||||
#include "mt76x02_regs.h"
|
||||
|
||||
static int
|
||||
mt76x02_efuse_read(struct mt76_dev *dev, u16 addr, u8 *data,
|
||||
enum mt76x02_eeprom_modes mode)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
val = __mt76_rr(dev, MT_EFUSE_CTRL);
|
||||
val &= ~(MT_EFUSE_CTRL_AIN |
|
||||
MT_EFUSE_CTRL_MODE);
|
||||
val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
|
||||
val |= FIELD_PREP(MT_EFUSE_CTRL_MODE, mode);
|
||||
val |= MT_EFUSE_CTRL_KICK;
|
||||
__mt76_wr(dev, MT_EFUSE_CTRL, val);
|
||||
|
||||
if (!__mt76_poll_msec(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK,
|
||||
0, 1000))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
udelay(2);
|
||||
|
||||
val = __mt76_rr(dev, MT_EFUSE_CTRL);
|
||||
if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
|
||||
memset(data, 0xff, 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val = __mt76_rr(dev, MT_EFUSE_DATA(i));
|
||||
put_unaligned_le32(val, data + 4 * i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt76x02_get_efuse_data(struct mt76_dev *dev, u16 base, void *buf,
|
||||
int len, enum mt76x02_eeprom_modes mode)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i + 16 <= len; i += 16) {
|
||||
ret = mt76x02_efuse_read(dev, base + i, buf + i, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_get_efuse_data);
|
||||
|
||||
void mt76x02_eeprom_parse_hw_cap(struct mt76_dev *dev)
|
||||
{
|
||||
u16 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
|
||||
|
||||
switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {
|
||||
case BOARD_TYPE_5GHZ:
|
||||
dev->cap.has_5ghz = true;
|
||||
break;
|
||||
case BOARD_TYPE_2GHZ:
|
||||
dev->cap.has_2ghz = true;
|
||||
break;
|
||||
default:
|
||||
dev->cap.has_2ghz = true;
|
||||
dev->cap.has_5ghz = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_eeprom_parse_hw_cap);
|
||||
|
||||
bool mt76x02_ext_pa_enabled(struct mt76_dev *dev, enum nl80211_band band)
|
||||
{
|
||||
u16 conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
|
||||
|
||||
if (band == NL80211_BAND_5GHZ)
|
||||
return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_5G);
|
||||
else
|
||||
return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_2G);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_ext_pa_enabled);
|
||||
|
||||
void mt76x02_get_rx_gain(struct mt76_dev *dev, enum nl80211_band band,
|
||||
u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
val = mt76x02_eeprom_get(dev, MT_EE_LNA_GAIN);
|
||||
*lna_2g = val & 0xff;
|
||||
lna_5g[0] = val >> 8;
|
||||
|
||||
val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_1);
|
||||
lna_5g[1] = val >> 8;
|
||||
|
||||
val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_1);
|
||||
lna_5g[2] = val >> 8;
|
||||
|
||||
if (!mt76x02_field_valid(lna_5g[1]))
|
||||
lna_5g[1] = lna_5g[0];
|
||||
|
||||
if (!mt76x02_field_valid(lna_5g[2]))
|
||||
lna_5g[2] = lna_5g[0];
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
*rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_0);
|
||||
else
|
||||
*rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_get_rx_gain);
|
||||
|
||||
u8 mt76x02_get_lna_gain(struct mt76_dev *dev,
|
||||
s8 *lna_2g, s8 *lna_5g,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
u16 val;
|
||||
u8 lna;
|
||||
|
||||
val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
|
||||
if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
|
||||
*lna_2g = 0;
|
||||
if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
|
||||
memset(lna_5g, 0, sizeof(s8) * 3);
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ)
|
||||
lna = *lna_2g;
|
||||
else if (chan->hw_value <= 64)
|
||||
lna = lna_5g[0];
|
||||
else if (chan->hw_value <= 128)
|
||||
lna = lna_5g[1];
|
||||
else
|
||||
lna = lna_5g[2];
|
||||
|
||||
return lna != 0xff ? lna : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_get_lna_gain);
|
211
drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
Normal file
211
drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MT76x02_EEPROM_H
|
||||
#define __MT76x02_EEPROM_H
|
||||
|
||||
enum mt76x02_eeprom_field {
|
||||
MT_EE_CHIP_ID = 0x000,
|
||||
MT_EE_VERSION = 0x002,
|
||||
MT_EE_MAC_ADDR = 0x004,
|
||||
MT_EE_PCI_ID = 0x00A,
|
||||
MT_EE_NIC_CONF_0 = 0x034,
|
||||
MT_EE_NIC_CONF_1 = 0x036,
|
||||
MT_EE_COUNTRY_REGION_5GHZ = 0x038,
|
||||
MT_EE_COUNTRY_REGION_2GHZ = 0x039,
|
||||
MT_EE_FREQ_OFFSET = 0x03a,
|
||||
MT_EE_NIC_CONF_2 = 0x042,
|
||||
|
||||
MT_EE_XTAL_TRIM_1 = 0x03a,
|
||||
MT_EE_XTAL_TRIM_2 = 0x09e,
|
||||
|
||||
MT_EE_LNA_GAIN = 0x044,
|
||||
MT_EE_RSSI_OFFSET_2G_0 = 0x046,
|
||||
MT_EE_RSSI_OFFSET_2G_1 = 0x048,
|
||||
MT_EE_LNA_GAIN_5GHZ_1 = 0x049,
|
||||
MT_EE_RSSI_OFFSET_5G_0 = 0x04a,
|
||||
MT_EE_RSSI_OFFSET_5G_1 = 0x04c,
|
||||
MT_EE_LNA_GAIN_5GHZ_2 = 0x04d,
|
||||
|
||||
MT_EE_TX_POWER_DELTA_BW40 = 0x050,
|
||||
MT_EE_TX_POWER_DELTA_BW80 = 0x052,
|
||||
|
||||
MT_EE_TX_POWER_EXT_PA_5G = 0x054,
|
||||
|
||||
MT_EE_TX_POWER_0_START_2G = 0x056,
|
||||
MT_EE_TX_POWER_1_START_2G = 0x05c,
|
||||
|
||||
/* used as byte arrays */
|
||||
#define MT_TX_POWER_GROUP_SIZE_5G 5
|
||||
#define MT_TX_POWER_GROUPS_5G 6
|
||||
MT_EE_TX_POWER_0_START_5G = 0x062,
|
||||
|
||||
MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA = 0x074,
|
||||
MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE = 0x076,
|
||||
|
||||
MT_EE_TX_POWER_1_START_5G = 0x080,
|
||||
|
||||
MT_EE_TX_POWER_CCK = 0x0a0,
|
||||
MT_EE_TX_POWER_OFDM_2G_6M = 0x0a2,
|
||||
MT_EE_TX_POWER_OFDM_2G_24M = 0x0a4,
|
||||
MT_EE_TX_POWER_OFDM_5G_6M = 0x0b2,
|
||||
MT_EE_TX_POWER_OFDM_5G_24M = 0x0b4,
|
||||
MT_EE_TX_POWER_HT_MCS0 = 0x0a6,
|
||||
MT_EE_TX_POWER_HT_MCS4 = 0x0a8,
|
||||
MT_EE_TX_POWER_HT_MCS8 = 0x0aa,
|
||||
MT_EE_TX_POWER_HT_MCS12 = 0x0ac,
|
||||
MT_EE_TX_POWER_VHT_MCS0 = 0x0ba,
|
||||
MT_EE_TX_POWER_VHT_MCS4 = 0x0bc,
|
||||
MT_EE_TX_POWER_VHT_MCS8 = 0x0be,
|
||||
|
||||
MT_EE_2G_TARGET_POWER = 0x0d0,
|
||||
MT_EE_TEMP_OFFSET = 0x0d1,
|
||||
MT_EE_5G_TARGET_POWER = 0x0d2,
|
||||
MT_EE_TSSI_BOUND1 = 0x0d4,
|
||||
MT_EE_TSSI_BOUND2 = 0x0d6,
|
||||
MT_EE_TSSI_BOUND3 = 0x0d8,
|
||||
MT_EE_TSSI_BOUND4 = 0x0da,
|
||||
MT_EE_FREQ_OFFSET_COMPENSATION = 0x0db,
|
||||
MT_EE_TSSI_BOUND5 = 0x0dc,
|
||||
MT_EE_TX_POWER_BYRATE_BASE = 0x0de,
|
||||
|
||||
MT_EE_RF_TEMP_COMP_SLOPE_5G = 0x0f2,
|
||||
MT_EE_RF_TEMP_COMP_SLOPE_2G = 0x0f4,
|
||||
|
||||
MT_EE_RF_2G_TSSI_OFF_TXPOWER = 0x0f6,
|
||||
MT_EE_RF_2G_RX_HIGH_GAIN = 0x0f8,
|
||||
MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN = 0x0fa,
|
||||
MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN = 0x0fc,
|
||||
MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN = 0x0fe,
|
||||
|
||||
MT_EE_BT_RCAL_RESULT = 0x138,
|
||||
MT_EE_BT_VCDL_CALIBRATION = 0x13c,
|
||||
MT_EE_BT_PMUCFG = 0x13e,
|
||||
|
||||
MT_EE_USAGE_MAP_START = 0x1e0,
|
||||
MT_EE_USAGE_MAP_END = 0x1fc,
|
||||
|
||||
__MT_EE_MAX
|
||||
};
|
||||
|
||||
#define MT_EE_NIC_CONF_0_RX_PATH GENMASK(3, 0)
|
||||
#define MT_EE_NIC_CONF_0_TX_PATH GENMASK(7, 4)
|
||||
#define MT_EE_NIC_CONF_0_PA_TYPE GENMASK(9, 8)
|
||||
#define MT_EE_NIC_CONF_0_PA_INT_2G BIT(8)
|
||||
#define MT_EE_NIC_CONF_0_PA_INT_5G BIT(9)
|
||||
#define MT_EE_NIC_CONF_0_PA_IO_CURRENT BIT(10)
|
||||
#define MT_EE_NIC_CONF_0_BOARD_TYPE GENMASK(13, 12)
|
||||
|
||||
#define MT_EE_NIC_CONF_1_HW_RF_CTRL BIT(0)
|
||||
#define MT_EE_NIC_CONF_1_TEMP_TX_ALC BIT(1)
|
||||
#define MT_EE_NIC_CONF_1_LNA_EXT_2G BIT(2)
|
||||
#define MT_EE_NIC_CONF_1_LNA_EXT_5G BIT(3)
|
||||
#define MT_EE_NIC_CONF_1_TX_ALC_EN BIT(13)
|
||||
|
||||
#define MT_EE_NIC_CONF_2_RX_STREAM GENMASK(3, 0)
|
||||
#define MT_EE_NIC_CONF_2_TX_STREAM GENMASK(7, 4)
|
||||
#define MT_EE_NIC_CONF_2_HW_ANTDIV BIT(8)
|
||||
#define MT_EE_NIC_CONF_2_XTAL_OPTION GENMASK(10, 9)
|
||||
#define MT_EE_NIC_CONF_2_TEMP_DISABLE BIT(11)
|
||||
#define MT_EE_NIC_CONF_2_COEX_METHOD GENMASK(15, 13)
|
||||
|
||||
#define MT_EFUSE_USAGE_MAP_SIZE (MT_EE_USAGE_MAP_END - \
|
||||
MT_EE_USAGE_MAP_START + 1)
|
||||
|
||||
enum mt76x02_eeprom_modes {
|
||||
MT_EE_READ,
|
||||
MT_EE_PHYSICAL_READ,
|
||||
};
|
||||
|
||||
enum mt76x02_board_type {
|
||||
BOARD_TYPE_2GHZ = 1,
|
||||
BOARD_TYPE_5GHZ = 2,
|
||||
};
|
||||
|
||||
static inline bool mt76x02_field_valid(u8 val)
|
||||
{
|
||||
return val != 0 && val != 0xff;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mt76x02_sign_extend(u32 val, unsigned int size)
|
||||
{
|
||||
bool sign = val & BIT(size - 1);
|
||||
|
||||
val &= BIT(size - 1) - 1;
|
||||
|
||||
return sign ? val : -val;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mt76x02_sign_extend_optional(u32 val, unsigned int size)
|
||||
{
|
||||
bool enable = val & BIT(size);
|
||||
|
||||
return enable ? mt76x02_sign_extend(val, size) : 0;
|
||||
}
|
||||
|
||||
static inline s8 mt76x02_rate_power_val(u8 val)
|
||||
{
|
||||
if (!mt76x02_field_valid(val))
|
||||
return 0;
|
||||
|
||||
return mt76x02_sign_extend_optional(val, 7);
|
||||
}
|
||||
|
||||
static inline int
|
||||
mt76x02_eeprom_get(struct mt76_dev *dev,
|
||||
enum mt76x02_eeprom_field field)
|
||||
{
|
||||
if ((field & 1) || field >= __MT_EE_MAX)
|
||||
return -1;
|
||||
|
||||
return get_unaligned_le16(dev->eeprom.data + field);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt76x02_temp_tx_alc_enabled(struct mt76_dev *dev)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G);
|
||||
if (!(val & BIT(15)))
|
||||
return false;
|
||||
|
||||
return mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) &
|
||||
MT_EE_NIC_CONF_1_TEMP_TX_ALC;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt76x02_tssi_enabled(struct mt76_dev *dev)
|
||||
{
|
||||
return !mt76x02_temp_tx_alc_enabled(dev) &&
|
||||
(mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) &
|
||||
MT_EE_NIC_CONF_1_TX_ALC_EN);
|
||||
}
|
||||
|
||||
bool mt76x02_ext_pa_enabled(struct mt76_dev *dev, enum nl80211_band band);
|
||||
int mt76x02_get_efuse_data(struct mt76_dev *dev, u16 base, void *buf,
|
||||
int len, enum mt76x02_eeprom_modes mode);
|
||||
void mt76x02_get_rx_gain(struct mt76_dev *dev, enum nl80211_band band,
|
||||
u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g);
|
||||
u8 mt76x02_get_lna_gain(struct mt76_dev *dev,
|
||||
s8 *lna_2g, s8 *lna_5g,
|
||||
struct ieee80211_channel *chan);
|
||||
void mt76x02_eeprom_parse_hw_cap(struct mt76_dev *dev);
|
||||
|
||||
#endif /* __MT76x02_EEPROM_H */
|
@ -502,3 +502,21 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate)
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_mac_process_rate);
|
||||
|
||||
void mt76x02_mac_setaddr(struct mt76_dev *dev, u8 *addr)
|
||||
{
|
||||
ether_addr_copy(dev->macaddr, addr);
|
||||
|
||||
if (!is_valid_ether_addr(dev->macaddr)) {
|
||||
eth_random_addr(dev->macaddr);
|
||||
dev_info(dev->dev,
|
||||
"Invalid MAC address, using random address %pM\n",
|
||||
dev->macaddr);
|
||||
}
|
||||
|
||||
__mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr));
|
||||
__mt76_wr(dev, MT_MAC_ADDR_DW1,
|
||||
get_unaligned_le16(dev->macaddr + 4) |
|
||||
FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr);
|
||||
|
@ -165,7 +165,7 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev *dev)
|
||||
|
||||
for (i = 0; i < 500; i++) {
|
||||
if (test_bit(MT76_REMOVED, &dev->state))
|
||||
return -EIO;
|
||||
return false;
|
||||
|
||||
switch (dev->bus->rr(dev, MAC_CSR0)) {
|
||||
case 0:
|
||||
@ -202,4 +202,5 @@ void mt76x02_send_tx_status(struct mt76_dev *dev,
|
||||
struct mt76x02_tx_status *stat, u8 *update);
|
||||
int
|
||||
mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate);
|
||||
void mt76x02_mac_setaddr(struct mt76_dev *dev, u8 *addr);
|
||||
#endif
|
||||
|
@ -211,3 +211,16 @@ int mt76x02_mcu_cleanup(struct mt76_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_mcu_cleanup);
|
||||
|
||||
void mt76x02_set_ethtool_fwver(struct mt76_dev *dev,
|
||||
const struct mt76x02_fw_header *h)
|
||||
{
|
||||
u16 bld = le16_to_cpu(h->build_ver);
|
||||
u16 ver = le16_to_cpu(h->fw_ver);
|
||||
|
||||
snprintf(dev->hw->wiphy->fw_version,
|
||||
sizeof(dev->hw->wiphy->fw_version),
|
||||
"%d.%d.%02d-b%x",
|
||||
(ver >> 12) & 0xf, (ver >> 8) & 0xf, ver & 0xf, bld);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_set_ethtool_fwver);
|
||||
|
@ -27,6 +27,15 @@
|
||||
#define MT_INBAND_PACKET_MAX_LEN 192
|
||||
#define MT_MCU_MEMMAP_WLAN 0x410000
|
||||
|
||||
#define MT_MCU_PCIE_REMAP_BASE4 0x074C
|
||||
|
||||
#define MT_MCU_SEMAPHORE_00 0x07B0
|
||||
#define MT_MCU_SEMAPHORE_01 0x07B4
|
||||
#define MT_MCU_SEMAPHORE_02 0x07B8
|
||||
#define MT_MCU_SEMAPHORE_03 0x07BC
|
||||
|
||||
#define MT_MCU_ILM_ADDR 0x80000
|
||||
|
||||
enum mcu_cmd {
|
||||
CMD_FUN_SET_OP = 1,
|
||||
CMD_LOAD_CR = 2,
|
||||
@ -96,5 +105,7 @@ int mt76x02_mcu_function_select(struct mt76_dev *dev,
|
||||
u32 val, bool wait_resp);
|
||||
int mt76x02_mcu_set_radio_state(struct mt76_dev *dev, bool on,
|
||||
bool wait_resp);
|
||||
void mt76x02_set_ethtool_fwver(struct mt76_dev *dev,
|
||||
const struct mt76x02_fw_header *h);
|
||||
|
||||
#endif /* __MT76x02_MCU_H */
|
||||
|
161
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
Normal file
161
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "mt76.h"
|
||||
#include "mt76x02_dma.h"
|
||||
#include "mt76x02_util.h"
|
||||
#include "mt76x02_mac.h"
|
||||
|
||||
static int
|
||||
mt76x02_init_tx_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
int idx, int n_desc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
q->regs = dev->mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
|
||||
q->ndesc = n_desc;
|
||||
q->hw_idx = idx;
|
||||
|
||||
ret = __mt76_queue_alloc(dev, q);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76x02_irq_enable(dev, MT_INT_TX_DONE(idx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x02_init_rx_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
int idx, int n_desc, int bufsize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
q->regs = dev->mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE;
|
||||
q->ndesc = n_desc;
|
||||
q->buf_size = bufsize;
|
||||
|
||||
ret = __mt76_queue_alloc(dev, q);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76x02_irq_enable(dev, MT_INT_RX_DONE(idx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt76x02_dma_init(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache __maybe_unused *t;
|
||||
struct mt76_queue *q;
|
||||
int i, ret;
|
||||
|
||||
BUILD_BUG_ON(sizeof(t->txwi) < sizeof(struct mt76x02_txwi));
|
||||
BUILD_BUG_ON(sizeof(struct mt76x02_rxwi) > MT_RX_HEADROOM);
|
||||
|
||||
mt76_dma_attach(dev);
|
||||
__mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
ret = mt76x02_init_tx_queue(dev, &dev->q_tx[i],
|
||||
mt76_ac_to_hwq(i),
|
||||
MT_TX_RING_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76x02_init_tx_queue(dev, &dev->q_tx[MT_TXQ_PSD],
|
||||
MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76x02_init_tx_queue(dev, &dev->q_tx[MT_TXQ_MCU],
|
||||
MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76x02_init_rx_queue(dev, &dev->q_rx[MT_RXQ_MCU], 1,
|
||||
MT_MCU_RING_SIZE, MT_RX_BUF_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
q = &dev->q_rx[MT_RXQ_MAIN];
|
||||
q->buf_offset = MT_RX_HEADROOM - sizeof(struct mt76x02_rxwi);
|
||||
ret = mt76x02_init_rx_queue(dev, q, 0, MT76X02_RX_RING_SIZE,
|
||||
MT_RX_BUF_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return __mt76_init_queues(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_dma_init);
|
||||
|
||||
void mt76x02_set_irq_mask(struct mt76_dev *dev, u32 clear, u32 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->mmio.irq_lock, flags);
|
||||
dev->mmio.irqmask &= ~clear;
|
||||
dev->mmio.irqmask |= set;
|
||||
__mt76_wr(dev, MT_INT_MASK_CSR, dev->mmio.irqmask);
|
||||
spin_unlock_irqrestore(&dev->mmio.irq_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_set_irq_mask);
|
||||
|
||||
void mt76x02_dma_enable(struct mt76_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
__mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
|
||||
mt76x02_wait_for_wpdma(dev, 1000);
|
||||
usleep_range(50, 100);
|
||||
|
||||
val = FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3) |
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_EN |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_EN;
|
||||
__mt76_set(dev, MT_WPDMA_GLO_CFG, val);
|
||||
__mt76_clear(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_dma_enable);
|
||||
|
||||
void mt76x02_dma_disable(struct mt76_dev *dev)
|
||||
{
|
||||
u32 val = __mt76_rr(dev, MT_WPDMA_GLO_CFG);
|
||||
|
||||
val &= MT_WPDMA_GLO_CFG_DMA_BURST_SIZE |
|
||||
MT_WPDMA_GLO_CFG_BIG_ENDIAN |
|
||||
MT_WPDMA_GLO_CFG_HDR_SEG_LEN;
|
||||
val |= MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE;
|
||||
__mt76_wr(dev, MT_WPDMA_GLO_CFG, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_dma_disable);
|
||||
|
||||
void mt76x02_mac_start(struct mt76_dev *dev)
|
||||
{
|
||||
mt76x02_dma_enable(dev);
|
||||
__mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
|
||||
__mt76_wr(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX |
|
||||
MT_MAC_SYS_CTRL_ENABLE_RX);
|
||||
mt76x02_irq_enable(dev,
|
||||
MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_TX_STAT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_mac_start);
|
135
drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
Normal file
135
drivers/net/wireless/mediatek/mt76/mt76x02_phy.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "mt76.h"
|
||||
#include "mt76x02_phy.h"
|
||||
|
||||
void mt76x02_phy_set_rxpath(struct mt76_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = __mt76_rr(dev, MT_BBP(AGC, 0));
|
||||
val &= ~BIT(4);
|
||||
|
||||
switch (dev->chainmask & 0xf) {
|
||||
case 2:
|
||||
val |= BIT(3);
|
||||
break;
|
||||
default:
|
||||
val &= ~BIT(3);
|
||||
break;
|
||||
}
|
||||
|
||||
__mt76_wr(dev, MT_BBP(AGC, 0), val);
|
||||
mb();
|
||||
val = __mt76_rr(dev, MT_BBP(AGC, 0));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_phy_set_rxpath);
|
||||
|
||||
void mt76x02_phy_set_txdac(struct mt76_dev *dev)
|
||||
{
|
||||
int txpath;
|
||||
|
||||
txpath = (dev->chainmask >> 8) & 0xf;
|
||||
switch (txpath) {
|
||||
case 2:
|
||||
__mt76_set(dev, MT_BBP(TXBE, 5), 0x3);
|
||||
break;
|
||||
default:
|
||||
__mt76_clear(dev, MT_BBP(TXBE, 5), 0x3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_phy_set_txdac);
|
||||
|
||||
static u32
|
||||
mt76x02_tx_power_mask(u8 v1, u8 v2, u8 v3, u8 v4)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val |= (v1 & (BIT(6) - 1)) << 0;
|
||||
val |= (v2 & (BIT(6) - 1)) << 8;
|
||||
val |= (v3 & (BIT(6) - 1)) << 16;
|
||||
val |= (v4 & (BIT(6) - 1)) << 24;
|
||||
return val;
|
||||
}
|
||||
|
||||
int mt76x02_get_max_rate_power(struct mt76_rate_power *r)
|
||||
{
|
||||
s8 ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(r->all); i++)
|
||||
ret = max(ret, r->all[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_get_max_rate_power);
|
||||
|
||||
void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(r->all); i++)
|
||||
if (r->all[i] > limit)
|
||||
r->all[i] = limit;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_limit_rate_power);
|
||||
|
||||
void mt76x02_add_rate_power_offset(struct mt76_rate_power *r, int offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(r->all); i++)
|
||||
r->all[i] += offset;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_add_rate_power_offset);
|
||||
|
||||
void mt76x02_phy_set_txpower(struct mt76_dev *dev, int txp_0, int txp_1)
|
||||
{
|
||||
struct mt76_rate_power *t = &dev->rate_power;
|
||||
|
||||
__mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_0,
|
||||
txp_0);
|
||||
__mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_1,
|
||||
txp_1);
|
||||
|
||||
__mt76_wr(dev, MT_TX_PWR_CFG_0,
|
||||
mt76x02_tx_power_mask(t->cck[0], t->cck[2], t->ofdm[0],
|
||||
t->ofdm[2]));
|
||||
__mt76_wr(dev, MT_TX_PWR_CFG_1,
|
||||
mt76x02_tx_power_mask(t->ofdm[4], t->ofdm[6], t->ht[0],
|
||||
t->ht[2]));
|
||||
__mt76_wr(dev, MT_TX_PWR_CFG_2,
|
||||
mt76x02_tx_power_mask(t->ht[4], t->ht[6], t->ht[8],
|
||||
t->ht[10]));
|
||||
__mt76_wr(dev, MT_TX_PWR_CFG_3,
|
||||
mt76x02_tx_power_mask(t->ht[12], t->ht[14], t->stbc[0],
|
||||
t->stbc[2]));
|
||||
__mt76_wr(dev, MT_TX_PWR_CFG_4,
|
||||
mt76x02_tx_power_mask(t->stbc[4], t->stbc[6], 0, 0));
|
||||
__mt76_wr(dev, MT_TX_PWR_CFG_7,
|
||||
mt76x02_tx_power_mask(t->ofdm[7], t->vht[8], t->ht[7],
|
||||
t->vht[9]));
|
||||
__mt76_wr(dev, MT_TX_PWR_CFG_8,
|
||||
mt76x02_tx_power_mask(t->ht[14], 0, t->vht[8], t->vht[9]));
|
||||
__mt76_wr(dev, MT_TX_PWR_CFG_9,
|
||||
mt76x02_tx_power_mask(t->ht[7], 0, t->stbc[8], t->stbc[9]));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_phy_set_txpower);
|
29
drivers/net/wireless/mediatek/mt76/mt76x02_phy.h
Normal file
29
drivers/net/wireless/mediatek/mt76/mt76x02_phy.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MT76x02_PHY_H
|
||||
#define __MT76x02_PHY_H
|
||||
|
||||
#include "mt76x02_regs.h"
|
||||
|
||||
void mt76x02_add_rate_power_offset(struct mt76_rate_power *r, int offset);
|
||||
void mt76x02_phy_set_txpower(struct mt76_dev *dev, int txp_0, int txp_2);
|
||||
void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit);
|
||||
int mt76x02_get_max_rate_power(struct mt76_rate_power *r);
|
||||
void mt76x02_phy_set_rxpath(struct mt76_dev *dev);
|
||||
void mt76x02_phy_set_txdac(struct mt76_dev *dev);
|
||||
|
||||
#endif /* __MT76x02_PHY_H */
|
@ -43,7 +43,7 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
|
||||
}
|
||||
|
||||
if (unlikely(pad)) {
|
||||
if (__skb_pad(last, pad, true))
|
||||
if (skb_pad(last, pad))
|
||||
return -ENOMEM;
|
||||
__skb_put(last, pad);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "mt76.h"
|
||||
|
@ -15,6 +15,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "mt76.h"
|
||||
#include "mt76x02_dma.h"
|
||||
#include "mt76x02_regs.h"
|
||||
@ -453,4 +454,42 @@ bool mt76x02_tx_status_data(struct mt76_dev *dev, u8 *update)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_tx_status_data);
|
||||
|
||||
const u16 mt76x02_beacon_offsets[16] = {
|
||||
/* 1024 byte per beacon */
|
||||
0xc000,
|
||||
0xc400,
|
||||
0xc800,
|
||||
0xcc00,
|
||||
0xd000,
|
||||
0xd400,
|
||||
0xd800,
|
||||
0xdc00,
|
||||
/* BSS idx 8-15 not used for beacons */
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets);
|
||||
|
||||
void mt76x02_set_beacon_offsets(struct mt76_dev *dev)
|
||||
{
|
||||
u16 val, base = MT_BEACON_BASE;
|
||||
u32 regs[4] = {};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
val = mt76x02_beacon_offsets[i] - base;
|
||||
regs[i / 4] |= (val / 64) << (8 * (i % 4));
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
__mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_set_beacon_offsets);
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
@ -51,4 +51,28 @@ void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb);
|
||||
void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
|
||||
struct mt76_queue_entry *e, bool flush);
|
||||
bool mt76x02_tx_status_data(struct mt76_dev *dev, u8 *update);
|
||||
|
||||
extern const u16 mt76x02_beacon_offsets[16];
|
||||
void mt76x02_set_beacon_offsets(struct mt76_dev *dev);
|
||||
void mt76x02_set_irq_mask(struct mt76_dev *dev, u32 clear, u32 set);
|
||||
void mt76x02_mac_start(struct mt76_dev *dev);
|
||||
|
||||
static inline void mt76x02_irq_enable(struct mt76_dev *dev, u32 mask)
|
||||
{
|
||||
mt76x02_set_irq_mask(dev, 0, mask);
|
||||
}
|
||||
|
||||
static inline void mt76x02_irq_disable(struct mt76_dev *dev, u32 mask)
|
||||
{
|
||||
mt76x02_set_irq_mask(dev, mask, 0);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt76x02_wait_for_txrx_idle(struct mt76_dev *dev)
|
||||
{
|
||||
return __mt76_poll_msec(dev, MT_MAC_STATUS,
|
||||
MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
|
||||
0, 100);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -35,9 +35,6 @@
|
||||
#define MT7662U_FIRMWARE "mediatek/mt7662u.bin"
|
||||
#define MT7662U_ROM_PATCH "mediatek/mt7662u_rom_patch.bin"
|
||||
|
||||
#define MT76x2_RX_RING_SIZE 256
|
||||
#define MT_RX_HEADROOM 32
|
||||
|
||||
#define MT_MAX_CHAINS 2
|
||||
|
||||
#define MT_CALIBRATE_INTERVAL HZ
|
||||
@ -81,10 +78,6 @@ struct mt76x2_dev {
|
||||
|
||||
struct mutex mutex;
|
||||
|
||||
const u16 *beacon_offsets;
|
||||
int txpower_conf;
|
||||
int txpower_cur;
|
||||
|
||||
u8 txdone_seq;
|
||||
DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
|
||||
|
||||
@ -97,9 +90,6 @@ struct mt76x2_dev {
|
||||
|
||||
u32 aggr_stats[32];
|
||||
|
||||
spinlock_t irq_lock;
|
||||
u32 irqmask;
|
||||
|
||||
struct sk_buff *beacons[8];
|
||||
u8 beacon_mask;
|
||||
u8 beacon_data_mask;
|
||||
@ -107,13 +97,10 @@ struct mt76x2_dev {
|
||||
u8 tbtt_count;
|
||||
u16 beacon_int;
|
||||
|
||||
u16 chainmask;
|
||||
|
||||
struct mt76x2_calibration cal;
|
||||
|
||||
s8 target_power;
|
||||
s8 target_power_delta[2];
|
||||
struct mt76_rate_power rate_power;
|
||||
bool enable_tpc;
|
||||
|
||||
u8 coverage_class;
|
||||
@ -127,8 +114,6 @@ static inline bool is_mt7612(struct mt76x2_dev *dev)
|
||||
return mt76_chip(&dev->mt76) == 0x7612;
|
||||
}
|
||||
|
||||
void mt76x2_set_irq_mask(struct mt76x2_dev *dev, u32 clear, u32 set);
|
||||
|
||||
static inline bool mt76x2_channel_silent(struct mt76x2_dev *dev)
|
||||
{
|
||||
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
|
||||
@ -137,31 +122,6 @@ static inline bool mt76x2_channel_silent(struct mt76x2_dev *dev)
|
||||
chan->dfs_state != NL80211_DFS_AVAILABLE);
|
||||
}
|
||||
|
||||
static inline void mt76x2_irq_enable(struct mt76x2_dev *dev, u32 mask)
|
||||
{
|
||||
mt76x2_set_irq_mask(dev, 0, mask);
|
||||
}
|
||||
|
||||
static inline void mt76x2_irq_disable(struct mt76x2_dev *dev, u32 mask)
|
||||
{
|
||||
mt76x2_set_irq_mask(dev, mask, 0);
|
||||
}
|
||||
|
||||
static inline bool mt76x2_wait_for_bbp(struct mt76x2_dev *dev)
|
||||
{
|
||||
return mt76_poll_msec(dev, MT_MAC_STATUS,
|
||||
MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
|
||||
0, 100);
|
||||
}
|
||||
|
||||
static inline bool wait_for_wpdma(struct mt76x2_dev *dev)
|
||||
{
|
||||
return mt76_poll(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_BUSY,
|
||||
0, 1000);
|
||||
}
|
||||
|
||||
extern const struct ieee80211_ops mt76x2_ops;
|
||||
|
||||
struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev);
|
||||
@ -191,7 +151,7 @@ int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw,
|
||||
int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level,
|
||||
u8 channel);
|
||||
|
||||
int mt76x2_dma_init(struct mt76x2_dev *dev);
|
||||
void mt76x2_tx_tasklet(unsigned long data);
|
||||
void mt76x2_dma_cleanup(struct mt76x2_dev *dev);
|
||||
|
||||
void mt76x2_cleanup(struct mt76x2_dev *dev);
|
||||
|
@ -17,23 +17,11 @@
|
||||
#include <linux/delay.h>
|
||||
#include "mt76x2.h"
|
||||
#include "mt76x2_trace.h"
|
||||
|
||||
void mt76x2_set_irq_mask(struct mt76x2_dev *dev, u32 clear, u32 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->irq_lock, flags);
|
||||
dev->irqmask &= ~clear;
|
||||
dev->irqmask |= set;
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, dev->irqmask);
|
||||
spin_unlock_irqrestore(&dev->irq_lock, flags);
|
||||
}
|
||||
#include "mt76x02_util.h"
|
||||
|
||||
void mt76x2_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
|
||||
{
|
||||
struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
|
||||
|
||||
mt76x2_irq_enable(dev, MT_INT_RX_DONE(q));
|
||||
mt76x02_irq_enable(mdev, MT_INT_RX_DONE(q));
|
||||
}
|
||||
|
||||
irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance)
|
||||
@ -47,22 +35,22 @@ irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance)
|
||||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
|
||||
return IRQ_NONE;
|
||||
|
||||
trace_dev_irq(dev, intr, dev->irqmask);
|
||||
trace_dev_irq(dev, intr, dev->mt76.mmio.irqmask);
|
||||
|
||||
intr &= dev->irqmask;
|
||||
intr &= dev->mt76.mmio.irqmask;
|
||||
|
||||
if (intr & MT_INT_TX_DONE_ALL) {
|
||||
mt76x2_irq_disable(dev, MT_INT_TX_DONE_ALL);
|
||||
mt76x02_irq_disable(&dev->mt76, MT_INT_TX_DONE_ALL);
|
||||
tasklet_schedule(&dev->tx_tasklet);
|
||||
}
|
||||
|
||||
if (intr & MT_INT_RX_DONE(0)) {
|
||||
mt76x2_irq_disable(dev, MT_INT_RX_DONE(0));
|
||||
mt76x02_irq_disable(&dev->mt76, MT_INT_RX_DONE(0));
|
||||
napi_schedule(&dev->mt76.napi[0]);
|
||||
}
|
||||
|
||||
if (intr & MT_INT_RX_DONE(1)) {
|
||||
mt76x2_irq_disable(dev, MT_INT_RX_DONE(1));
|
||||
mt76x02_irq_disable(&dev->mt76, MT_INT_RX_DONE(1));
|
||||
napi_schedule(&dev->mt76.napi[1]);
|
||||
}
|
||||
|
||||
@ -79,7 +67,7 @@ irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance)
|
||||
}
|
||||
|
||||
if (intr & MT_INT_GPTIMER) {
|
||||
mt76x2_irq_disable(dev, MT_INT_GPTIMER);
|
||||
mt76x02_irq_disable(&dev->mt76, MT_INT_GPTIMER);
|
||||
tasklet_schedule(&dev->dfs_pd.dfs_tasklet);
|
||||
}
|
||||
|
||||
|
@ -47,33 +47,14 @@ mt76x2_ampdu_stat_open(struct inode *inode, struct file *f)
|
||||
return single_open(f, mt76x2_ampdu_stat_read, inode->i_private);
|
||||
}
|
||||
|
||||
static void
|
||||
seq_puts_array(struct seq_file *file, const char *str, s8 *val, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
seq_printf(file, "%10s:", str);
|
||||
for (i = 0; i < len; i++)
|
||||
seq_printf(file, " %2d", val[i]);
|
||||
seq_puts(file, "\n");
|
||||
}
|
||||
|
||||
static int read_txpower(struct seq_file *file, void *data)
|
||||
{
|
||||
struct mt76x2_dev *dev = dev_get_drvdata(file->private);
|
||||
|
||||
seq_printf(file, "Target power: %d\n", dev->target_power);
|
||||
|
||||
seq_puts_array(file, "Delta", dev->target_power_delta,
|
||||
ARRAY_SIZE(dev->target_power_delta));
|
||||
seq_puts_array(file, "CCK", dev->rate_power.cck,
|
||||
ARRAY_SIZE(dev->rate_power.cck));
|
||||
seq_puts_array(file, "OFDM", dev->rate_power.ofdm,
|
||||
ARRAY_SIZE(dev->rate_power.ofdm));
|
||||
seq_puts_array(file, "HT", dev->rate_power.ht,
|
||||
ARRAY_SIZE(dev->rate_power.ht));
|
||||
seq_puts_array(file, "VHT", dev->rate_power.vht,
|
||||
ARRAY_SIZE(dev->rate_power.vht));
|
||||
mt76_seq_puts_array(file, "Delta", dev->target_power_delta,
|
||||
ARRAY_SIZE(dev->target_power_delta));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "mt76x2.h"
|
||||
#include "mt76x02_util.h"
|
||||
|
||||
#define RADAR_SPEC(m, len, el, eh, wl, wh, \
|
||||
w_tolerance, tl, th, t_tolerance, \
|
||||
@ -678,7 +679,7 @@ static void mt76x2_dfs_tasklet(unsigned long arg)
|
||||
mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
|
||||
|
||||
out:
|
||||
mt76x2_irq_enable(dev, MT_INT_GPTIMER);
|
||||
mt76x02_irq_enable(&dev->mt76, MT_INT_GPTIMER);
|
||||
}
|
||||
|
||||
static void mt76x2_dfs_init_sw_detector(struct mt76x2_dev *dev)
|
||||
@ -834,7 +835,7 @@ void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
|
||||
/* enable debug mode */
|
||||
mt76x2_dfs_set_capture_mode_ctrl(dev, true);
|
||||
|
||||
mt76x2_irq_enable(dev, MT_INT_GPTIMER);
|
||||
mt76x02_irq_enable(&dev->mt76, MT_INT_GPTIMER);
|
||||
mt76_rmw_field(dev, MT_INT_TIMER_EN,
|
||||
MT_INT_TIMER_EN_GP_TIMER_EN, 1);
|
||||
} else {
|
||||
@ -844,7 +845,7 @@ void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
|
||||
mt76_wr(dev, MT_BBP(DFS, 1), 0xf);
|
||||
mt76_wr(dev, 0x212c, 0);
|
||||
|
||||
mt76x2_irq_disable(dev, MT_INT_GPTIMER);
|
||||
mt76x02_irq_disable(&dev->mt76, MT_INT_GPTIMER);
|
||||
mt76_rmw_field(dev, MT_INT_TIMER_EN,
|
||||
MT_INT_TIMER_EN_GP_TIMER_EN, 0);
|
||||
}
|
||||
|
@ -16,47 +16,9 @@
|
||||
|
||||
#include "mt76x2.h"
|
||||
#include "mt76x02_dma.h"
|
||||
#include "mt76x02_util.h"
|
||||
|
||||
static int
|
||||
mt76x2_init_tx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
|
||||
int idx, int n_desc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
|
||||
q->ndesc = n_desc;
|
||||
q->hw_idx = idx;
|
||||
|
||||
ret = mt76_queue_alloc(dev, q);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76x2_irq_enable(dev, MT_INT_TX_DONE(idx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x2_init_rx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
|
||||
int idx, int n_desc, int bufsize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE;
|
||||
q->ndesc = n_desc;
|
||||
q->buf_size = bufsize;
|
||||
|
||||
ret = mt76_queue_alloc(dev, q);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76x2_irq_enable(dev, MT_INT_RX_DONE(idx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x2_tx_tasklet(unsigned long data)
|
||||
void mt76x2_tx_tasklet(unsigned long data)
|
||||
{
|
||||
struct mt76x2_dev *dev = (struct mt76x2_dev *) data;
|
||||
int i;
|
||||
@ -67,54 +29,7 @@ mt76x2_tx_tasklet(unsigned long data)
|
||||
mt76_queue_tx_cleanup(dev, i, false);
|
||||
|
||||
mt76x2_mac_poll_tx_status(dev, false);
|
||||
mt76x2_irq_enable(dev, MT_INT_TX_DONE_ALL);
|
||||
}
|
||||
|
||||
int mt76x2_dma_init(struct mt76x2_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
struct mt76_txwi_cache __maybe_unused *t;
|
||||
struct mt76_queue *q;
|
||||
|
||||
BUILD_BUG_ON(sizeof(t->txwi) < sizeof(struct mt76x02_txwi));
|
||||
BUILD_BUG_ON(sizeof(struct mt76x02_rxwi) > MT_RX_HEADROOM);
|
||||
|
||||
mt76_dma_attach(&dev->mt76);
|
||||
|
||||
tasklet_init(&dev->tx_tasklet, mt76x2_tx_tasklet, (unsigned long) dev);
|
||||
|
||||
mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[i],
|
||||
mt76_ac_to_hwq(i), MT_TX_RING_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
|
||||
MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76x2_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
|
||||
MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76x2_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
|
||||
MT_MCU_RING_SIZE, MT_RX_BUF_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
q = &dev->mt76.q_rx[MT_RXQ_MAIN];
|
||||
q->buf_offset = MT_RX_HEADROOM - sizeof(struct mt76x02_rxwi);
|
||||
ret = mt76x2_init_rx_queue(dev, q, 0, MT76x2_RX_RING_SIZE, MT_RX_BUF_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt76_init_queues(dev);
|
||||
mt76x02_irq_enable(&dev->mt76, MT_INT_TX_DONE_ALL);
|
||||
}
|
||||
|
||||
void mt76x2_dma_cleanup(struct mt76x2_dev *dev)
|
||||
|
@ -14,6 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "mt76x2.h"
|
||||
#include "mt76x2_eeprom.h"
|
||||
@ -21,7 +22,7 @@
|
||||
#define EE_FIELD(_name, _value) [MT_EE_##_name] = (_value) | 1
|
||||
|
||||
static int
|
||||
mt76x2_eeprom_copy(struct mt76x2_dev *dev, enum mt76x2_eeprom_field field,
|
||||
mt76x2_eeprom_copy(struct mt76x2_dev *dev, enum mt76x02_eeprom_field field,
|
||||
void *dest, int len)
|
||||
{
|
||||
if (field + len > dev->mt76.eeprom.size)
|
||||
@ -40,71 +41,6 @@ mt76x2_eeprom_get_macaddr(struct mt76x2_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt76x2_eeprom_parse_hw_cap(struct mt76x2_dev *dev)
|
||||
{
|
||||
u16 val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_0);
|
||||
|
||||
switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {
|
||||
case BOARD_TYPE_5GHZ:
|
||||
dev->mt76.cap.has_5ghz = true;
|
||||
break;
|
||||
case BOARD_TYPE_2GHZ:
|
||||
dev->mt76.cap.has_2ghz = true;
|
||||
break;
|
||||
default:
|
||||
dev->mt76.cap.has_2ghz = true;
|
||||
dev->mt76.cap.has_5ghz = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_eeprom_parse_hw_cap);
|
||||
|
||||
static int
|
||||
mt76x2_efuse_read(struct mt76x2_dev *dev, u16 addr, u8 *data)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
val = mt76_rr(dev, MT_EFUSE_CTRL);
|
||||
val &= ~(MT_EFUSE_CTRL_AIN |
|
||||
MT_EFUSE_CTRL_MODE);
|
||||
val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
|
||||
val |= MT_EFUSE_CTRL_KICK;
|
||||
mt76_wr(dev, MT_EFUSE_CTRL, val);
|
||||
|
||||
if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
udelay(2);
|
||||
|
||||
val = mt76_rr(dev, MT_EFUSE_CTRL);
|
||||
if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
|
||||
memset(data, 0xff, 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
val = mt76_rr(dev, MT_EFUSE_DATA(i));
|
||||
put_unaligned_le32(val, data + 4 * i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x2_get_efuse_data(struct mt76x2_dev *dev, void *buf, int len)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i + 16 <= len; i += 16) {
|
||||
ret = mt76x2_efuse_read(dev, i, buf + i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
mt76x2_has_cal_free_data(struct mt76x2_dev *dev, u8 *efuse)
|
||||
{
|
||||
@ -241,7 +177,8 @@ mt76x2_eeprom_load(struct mt76x2_dev *dev)
|
||||
|
||||
efuse = dev->mt76.otp.data;
|
||||
|
||||
if (mt76x2_get_efuse_data(dev, efuse, MT7662_EEPROM_SIZE))
|
||||
if (mt76x02_get_efuse_data(&dev->mt76, 0, efuse,
|
||||
MT7662_EEPROM_SIZE, MT_EE_READ))
|
||||
goto out;
|
||||
|
||||
if (found) {
|
||||
@ -259,43 +196,19 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mt76x2_sign_extend(u32 val, unsigned int size)
|
||||
{
|
||||
bool sign = val & BIT(size - 1);
|
||||
|
||||
val &= BIT(size - 1) - 1;
|
||||
|
||||
return sign ? val : -val;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mt76x2_sign_extend_optional(u32 val, unsigned int size)
|
||||
{
|
||||
bool enable = val & BIT(size);
|
||||
|
||||
return enable ? mt76x2_sign_extend(val, size) : 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
field_valid(u8 val)
|
||||
{
|
||||
return val != 0 && val != 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x2_set_rx_gain_group(struct mt76x2_dev *dev, u8 val)
|
||||
{
|
||||
s8 *dest = dev->cal.rx.high_gain;
|
||||
|
||||
if (!field_valid(val)) {
|
||||
if (!mt76x02_field_valid(val)) {
|
||||
dest[0] = 0;
|
||||
dest[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
dest[0] = mt76x2_sign_extend(val, 4);
|
||||
dest[1] = mt76x2_sign_extend(val >> 4, 4);
|
||||
dest[0] = mt76x02_sign_extend(val, 4);
|
||||
dest[1] = mt76x02_sign_extend(val >> 4, 4);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -303,12 +216,12 @@ mt76x2_set_rssi_offset(struct mt76x2_dev *dev, int chain, u8 val)
|
||||
{
|
||||
s8 *dest = dev->cal.rx.rssi_offset;
|
||||
|
||||
if (!field_valid(val)) {
|
||||
if (!mt76x02_field_valid(val)) {
|
||||
dest[chain] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
dest[chain] = mt76x2_sign_extend_optional(val, 7);
|
||||
dest[chain] = mt76x02_sign_extend_optional(val, 7);
|
||||
}
|
||||
|
||||
static enum mt76x2_cal_channel_group
|
||||
@ -335,17 +248,23 @@ mt76x2_get_5g_rx_gain(struct mt76x2_dev *dev, u8 channel)
|
||||
group = mt76x2_get_cal_channel_group(channel);
|
||||
switch (group) {
|
||||
case MT_CH_5G_JAPAN:
|
||||
return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN);
|
||||
return mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN);
|
||||
case MT_CH_5G_UNII_1:
|
||||
return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN) >> 8;
|
||||
return mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN) >> 8;
|
||||
case MT_CH_5G_UNII_2:
|
||||
return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN);
|
||||
return mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN);
|
||||
case MT_CH_5G_UNII_2E_1:
|
||||
return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN) >> 8;
|
||||
return mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN) >> 8;
|
||||
case MT_CH_5G_UNII_2E_2:
|
||||
return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN);
|
||||
return mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN);
|
||||
default:
|
||||
return mt76x2_eeprom_get(dev, MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN) >> 8;
|
||||
return mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN) >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,74 +277,27 @@ void mt76x2_read_rx_gain(struct mt76x2_dev *dev)
|
||||
u16 val;
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ)
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_RF_2G_RX_HIGH_GAIN) >> 8;
|
||||
val = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_2G_RX_HIGH_GAIN) >> 8;
|
||||
else
|
||||
val = mt76x2_get_5g_rx_gain(dev, channel);
|
||||
|
||||
mt76x2_set_rx_gain_group(dev, val);
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ) {
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_0);
|
||||
mt76x2_set_rssi_offset(dev, 0, val);
|
||||
mt76x2_set_rssi_offset(dev, 1, val >> 8);
|
||||
} else {
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_0);
|
||||
mt76x2_set_rssi_offset(dev, 0, val);
|
||||
mt76x2_set_rssi_offset(dev, 1, val >> 8);
|
||||
}
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_LNA_GAIN);
|
||||
lna_2g = val & 0xff;
|
||||
lna_5g[0] = val >> 8;
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_1);
|
||||
lna_5g[1] = val >> 8;
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_1);
|
||||
lna_5g[2] = val >> 8;
|
||||
|
||||
if (!field_valid(lna_5g[1]))
|
||||
lna_5g[1] = lna_5g[0];
|
||||
|
||||
if (!field_valid(lna_5g[2]))
|
||||
lna_5g[2] = lna_5g[0];
|
||||
mt76x02_get_rx_gain(&dev->mt76, chan->band, &val, &lna_2g, lna_5g);
|
||||
mt76x2_set_rssi_offset(dev, 0, val);
|
||||
mt76x2_set_rssi_offset(dev, 1, val >> 8);
|
||||
|
||||
dev->cal.rx.mcu_gain = (lna_2g & 0xff);
|
||||
dev->cal.rx.mcu_gain |= (lna_5g[0] & 0xff) << 8;
|
||||
dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16;
|
||||
dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24;
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1);
|
||||
if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
|
||||
lna_2g = 0;
|
||||
if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
|
||||
memset(lna_5g, 0, sizeof(lna_5g));
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ)
|
||||
lna = lna_2g;
|
||||
else if (channel <= 64)
|
||||
lna = lna_5g[0];
|
||||
else if (channel <= 128)
|
||||
lna = lna_5g[1];
|
||||
else
|
||||
lna = lna_5g[2];
|
||||
|
||||
if (lna == 0xff)
|
||||
lna = 0;
|
||||
|
||||
dev->cal.rx.lna_gain = mt76x2_sign_extend(lna, 8);
|
||||
lna = mt76x02_get_lna_gain(&dev->mt76, &lna_2g, lna_5g, chan);
|
||||
dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain);
|
||||
|
||||
static s8
|
||||
mt76x2_rate_power_val(u8 val)
|
||||
{
|
||||
if (!field_valid(val))
|
||||
return 0;
|
||||
|
||||
return mt76x2_sign_extend_optional(val, 7);
|
||||
}
|
||||
|
||||
void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
@ -436,67 +308,63 @@ void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t,
|
||||
|
||||
memset(t, 0, sizeof(*t));
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_CCK);
|
||||
t->cck[0] = t->cck[1] = mt76x2_rate_power_val(val);
|
||||
t->cck[2] = t->cck[3] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_CCK);
|
||||
t->cck[0] = t->cck[1] = mt76x02_rate_power_val(val);
|
||||
t->cck[2] = t->cck[3] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
if (is_5ghz)
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_OFDM_5G_6M);
|
||||
val = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_TX_POWER_OFDM_5G_6M);
|
||||
else
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_OFDM_2G_6M);
|
||||
t->ofdm[0] = t->ofdm[1] = mt76x2_rate_power_val(val);
|
||||
t->ofdm[2] = t->ofdm[3] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_TX_POWER_OFDM_2G_6M);
|
||||
t->ofdm[0] = t->ofdm[1] = mt76x02_rate_power_val(val);
|
||||
t->ofdm[2] = t->ofdm[3] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
if (is_5ghz)
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_OFDM_5G_24M);
|
||||
val = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_TX_POWER_OFDM_5G_24M);
|
||||
else
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_OFDM_2G_24M);
|
||||
t->ofdm[4] = t->ofdm[5] = mt76x2_rate_power_val(val);
|
||||
t->ofdm[6] = t->ofdm[7] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_TX_POWER_OFDM_2G_24M);
|
||||
t->ofdm[4] = t->ofdm[5] = mt76x02_rate_power_val(val);
|
||||
t->ofdm[6] = t->ofdm[7] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS0);
|
||||
t->ht[0] = t->ht[1] = mt76x2_rate_power_val(val);
|
||||
t->ht[2] = t->ht[3] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS0);
|
||||
t->ht[0] = t->ht[1] = mt76x02_rate_power_val(val);
|
||||
t->ht[2] = t->ht[3] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS4);
|
||||
t->ht[4] = t->ht[5] = mt76x2_rate_power_val(val);
|
||||
t->ht[6] = t->ht[7] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS4);
|
||||
t->ht[4] = t->ht[5] = mt76x02_rate_power_val(val);
|
||||
t->ht[6] = t->ht[7] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS8);
|
||||
t->ht[8] = t->ht[9] = mt76x2_rate_power_val(val);
|
||||
t->ht[10] = t->ht[11] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS8);
|
||||
t->ht[8] = t->ht[9] = mt76x02_rate_power_val(val);
|
||||
t->ht[10] = t->ht[11] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS12);
|
||||
t->ht[12] = t->ht[13] = mt76x2_rate_power_val(val);
|
||||
t->ht[14] = t->ht[15] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS12);
|
||||
t->ht[12] = t->ht[13] = mt76x02_rate_power_val(val);
|
||||
t->ht[14] = t->ht[15] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS0);
|
||||
t->vht[0] = t->vht[1] = mt76x2_rate_power_val(val);
|
||||
t->vht[2] = t->vht[3] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS0);
|
||||
t->vht[0] = t->vht[1] = mt76x02_rate_power_val(val);
|
||||
t->vht[2] = t->vht[3] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS4);
|
||||
t->vht[4] = t->vht[5] = mt76x2_rate_power_val(val);
|
||||
t->vht[6] = t->vht[7] = mt76x2_rate_power_val(val >> 8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS4);
|
||||
t->vht[4] = t->vht[5] = mt76x02_rate_power_val(val);
|
||||
t->vht[6] = t->vht[7] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS8);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS8);
|
||||
if (!is_5ghz)
|
||||
val >>= 8;
|
||||
t->vht[8] = t->vht[9] = mt76x2_rate_power_val(val >> 8);
|
||||
t->vht[8] = t->vht[9] = mt76x02_rate_power_val(val >> 8);
|
||||
|
||||
memcpy(t->stbc, t->ht, sizeof(t->stbc[0]) * 8);
|
||||
t->stbc[8] = t->vht[8];
|
||||
t->stbc[9] = t->vht[9];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_get_rate_power);
|
||||
|
||||
int mt76x2_get_max_rate_power(struct mt76_rate_power *r)
|
||||
{
|
||||
int i;
|
||||
s8 ret = 0;
|
||||
|
||||
for (i = 0; i < sizeof(r->all); i++)
|
||||
ret = max(ret, r->all[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_get_max_rate_power);
|
||||
|
||||
static void
|
||||
mt76x2_get_power_info_2g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
|
||||
struct ieee80211_channel *chan, int chain, int offset)
|
||||
@ -518,9 +386,9 @@ mt76x2_get_power_info_2g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
|
||||
t->chain[chain].tssi_slope = data[0];
|
||||
t->chain[chain].tssi_offset = data[1];
|
||||
t->chain[chain].target_power = data[2];
|
||||
t->chain[chain].delta = mt76x2_sign_extend_optional(data[delta_idx], 7);
|
||||
t->chain[chain].delta = mt76x02_sign_extend_optional(data[delta_idx], 7);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_RF_2G_TSSI_OFF_TXPOWER);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_RF_2G_TSSI_OFF_TXPOWER);
|
||||
t->target_power = val >> 8;
|
||||
}
|
||||
|
||||
@ -567,9 +435,9 @@ mt76x2_get_power_info_5g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t,
|
||||
t->chain[chain].tssi_slope = data[0];
|
||||
t->chain[chain].tssi_offset = data[1];
|
||||
t->chain[chain].target_power = data[2];
|
||||
t->chain[chain].delta = mt76x2_sign_extend_optional(data[delta_idx], 7);
|
||||
t->chain[chain].delta = mt76x02_sign_extend_optional(data[delta_idx], 7);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_RF_2G_RX_HIGH_GAIN);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_RF_2G_RX_HIGH_GAIN);
|
||||
t->target_power = val & 0xff;
|
||||
}
|
||||
|
||||
@ -581,8 +449,8 @@ void mt76x2_get_power_info(struct mt76x2_dev *dev,
|
||||
|
||||
memset(t, 0, sizeof(*t));
|
||||
|
||||
bw40 = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
|
||||
bw80 = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW80);
|
||||
bw40 = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_DELTA_BW40);
|
||||
bw80 = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_DELTA_BW80);
|
||||
|
||||
if (chan->band == NL80211_BAND_5GHZ) {
|
||||
bw40 >>= 8;
|
||||
@ -597,11 +465,12 @@ void mt76x2_get_power_info(struct mt76x2_dev *dev,
|
||||
MT_EE_TX_POWER_1_START_2G);
|
||||
}
|
||||
|
||||
if (mt76x2_tssi_enabled(dev) || !field_valid(t->target_power))
|
||||
if (mt76x02_tssi_enabled(&dev->mt76) ||
|
||||
!mt76x02_field_valid(t->target_power))
|
||||
t->target_power = t->chain[0].target_power;
|
||||
|
||||
t->delta_bw40 = mt76x2_rate_power_val(bw40);
|
||||
t->delta_bw80 = mt76x2_rate_power_val(bw80);
|
||||
t->delta_bw40 = mt76x02_rate_power_val(bw40);
|
||||
t->delta_bw80 = mt76x02_rate_power_val(bw80);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_get_power_info);
|
||||
|
||||
@ -613,20 +482,24 @@ int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t)
|
||||
|
||||
memset(t, 0, sizeof(*t));
|
||||
|
||||
if (!mt76x2_temp_tx_alc_enabled(dev))
|
||||
if (!mt76x02_temp_tx_alc_enabled(&dev->mt76))
|
||||
return -EINVAL;
|
||||
|
||||
if (!mt76x2_ext_pa_enabled(dev, band))
|
||||
if (!mt76x02_ext_pa_enabled(&dev->mt76, band))
|
||||
return -EINVAL;
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G) >> 8;
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_EXT_PA_5G) >> 8;
|
||||
t->temp_25_ref = val & 0x7f;
|
||||
if (band == NL80211_BAND_5GHZ) {
|
||||
slope = mt76x2_eeprom_get(dev, MT_EE_RF_TEMP_COMP_SLOPE_5G);
|
||||
bounds = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G);
|
||||
slope = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_TEMP_COMP_SLOPE_5G);
|
||||
bounds = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_TX_POWER_EXT_PA_5G);
|
||||
} else {
|
||||
slope = mt76x2_eeprom_get(dev, MT_EE_RF_TEMP_COMP_SLOPE_2G);
|
||||
bounds = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW80) >> 8;
|
||||
slope = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_RF_TEMP_COMP_SLOPE_2G);
|
||||
bounds = mt76x02_eeprom_get(&dev->mt76,
|
||||
MT_EE_TX_POWER_DELTA_BW80) >> 8;
|
||||
}
|
||||
|
||||
t->high_slope = slope & 0xff;
|
||||
@ -638,17 +511,6 @@ int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_get_temp_comp);
|
||||
|
||||
bool mt76x2_ext_pa_enabled(struct mt76x2_dev *dev, enum nl80211_band band)
|
||||
{
|
||||
u16 conf0 = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_0);
|
||||
|
||||
if (band == NL80211_BAND_5GHZ)
|
||||
return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_5G);
|
||||
else
|
||||
return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_2G);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_ext_pa_enabled);
|
||||
|
||||
int mt76x2_eeprom_init(struct mt76x2_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
@ -657,7 +519,7 @@ int mt76x2_eeprom_init(struct mt76x2_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76x2_eeprom_parse_hw_cap(dev);
|
||||
mt76x02_eeprom_parse_hw_cap(&dev->mt76);
|
||||
mt76x2_eeprom_get_macaddr(dev);
|
||||
mt76_eeprom_override(&dev->mt76);
|
||||
dev->mt76.macaddr[0] &= ~BIT(1);
|
||||
|
@ -17,93 +17,7 @@
|
||||
#ifndef __MT76x2_EEPROM_H
|
||||
#define __MT76x2_EEPROM_H
|
||||
|
||||
#include "mt76x2.h"
|
||||
|
||||
enum mt76x2_eeprom_field {
|
||||
MT_EE_CHIP_ID = 0x000,
|
||||
MT_EE_VERSION = 0x002,
|
||||
MT_EE_MAC_ADDR = 0x004,
|
||||
MT_EE_PCI_ID = 0x00A,
|
||||
MT_EE_NIC_CONF_0 = 0x034,
|
||||
MT_EE_NIC_CONF_1 = 0x036,
|
||||
MT_EE_NIC_CONF_2 = 0x042,
|
||||
|
||||
MT_EE_XTAL_TRIM_1 = 0x03a,
|
||||
MT_EE_XTAL_TRIM_2 = 0x09e,
|
||||
|
||||
MT_EE_LNA_GAIN = 0x044,
|
||||
MT_EE_RSSI_OFFSET_2G_0 = 0x046,
|
||||
MT_EE_RSSI_OFFSET_2G_1 = 0x048,
|
||||
MT_EE_RSSI_OFFSET_5G_0 = 0x04a,
|
||||
MT_EE_RSSI_OFFSET_5G_1 = 0x04c,
|
||||
|
||||
MT_EE_TX_POWER_DELTA_BW40 = 0x050,
|
||||
MT_EE_TX_POWER_DELTA_BW80 = 0x052,
|
||||
|
||||
MT_EE_TX_POWER_EXT_PA_5G = 0x054,
|
||||
|
||||
MT_EE_TX_POWER_0_START_2G = 0x056,
|
||||
MT_EE_TX_POWER_1_START_2G = 0x05c,
|
||||
|
||||
/* used as byte arrays */
|
||||
#define MT_TX_POWER_GROUP_SIZE_5G 5
|
||||
#define MT_TX_POWER_GROUPS_5G 6
|
||||
MT_EE_TX_POWER_0_START_5G = 0x062,
|
||||
|
||||
MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA = 0x074,
|
||||
MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE = 0x076,
|
||||
|
||||
MT_EE_TX_POWER_1_START_5G = 0x080,
|
||||
|
||||
MT_EE_TX_POWER_CCK = 0x0a0,
|
||||
MT_EE_TX_POWER_OFDM_2G_6M = 0x0a2,
|
||||
MT_EE_TX_POWER_OFDM_2G_24M = 0x0a4,
|
||||
MT_EE_TX_POWER_OFDM_5G_6M = 0x0b2,
|
||||
MT_EE_TX_POWER_OFDM_5G_24M = 0x0b4,
|
||||
MT_EE_TX_POWER_HT_MCS0 = 0x0a6,
|
||||
MT_EE_TX_POWER_HT_MCS4 = 0x0a8,
|
||||
MT_EE_TX_POWER_HT_MCS8 = 0x0aa,
|
||||
MT_EE_TX_POWER_HT_MCS12 = 0x0ac,
|
||||
MT_EE_TX_POWER_VHT_MCS0 = 0x0ba,
|
||||
MT_EE_TX_POWER_VHT_MCS4 = 0x0bc,
|
||||
MT_EE_TX_POWER_VHT_MCS8 = 0x0be,
|
||||
|
||||
MT_EE_RF_TEMP_COMP_SLOPE_5G = 0x0f2,
|
||||
MT_EE_RF_TEMP_COMP_SLOPE_2G = 0x0f4,
|
||||
|
||||
MT_EE_RF_2G_TSSI_OFF_TXPOWER = 0x0f6,
|
||||
MT_EE_RF_2G_RX_HIGH_GAIN = 0x0f8,
|
||||
MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN = 0x0fa,
|
||||
MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN = 0x0fc,
|
||||
MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN = 0x0fe,
|
||||
|
||||
MT_EE_BT_RCAL_RESULT = 0x138,
|
||||
MT_EE_BT_VCDL_CALIBRATION = 0x13c,
|
||||
MT_EE_BT_PMUCFG = 0x13e,
|
||||
|
||||
__MT_EE_MAX
|
||||
};
|
||||
|
||||
#define MT_EE_NIC_CONF_0_PA_INT_2G BIT(8)
|
||||
#define MT_EE_NIC_CONF_0_PA_INT_5G BIT(9)
|
||||
#define MT_EE_NIC_CONF_0_BOARD_TYPE GENMASK(13, 12)
|
||||
|
||||
#define MT_EE_NIC_CONF_1_TEMP_TX_ALC BIT(1)
|
||||
#define MT_EE_NIC_CONF_1_LNA_EXT_2G BIT(2)
|
||||
#define MT_EE_NIC_CONF_1_LNA_EXT_5G BIT(3)
|
||||
#define MT_EE_NIC_CONF_1_TX_ALC_EN BIT(13)
|
||||
|
||||
#define MT_EE_NIC_CONF_2_RX_STREAM GENMASK(3, 0)
|
||||
#define MT_EE_NIC_CONF_2_TX_STREAM GENMASK(7, 4)
|
||||
#define MT_EE_NIC_CONF_2_HW_ANTDIV BIT(8)
|
||||
#define MT_EE_NIC_CONF_2_XTAL_OPTION GENMASK(10, 9)
|
||||
#define MT_EE_NIC_CONF_2_TEMP_DISABLE BIT(11)
|
||||
#define MT_EE_NIC_CONF_2_COEX_METHOD GENMASK(15, 13)
|
||||
|
||||
enum mt76x2_board_type {
|
||||
BOARD_TYPE_2GHZ = 1,
|
||||
BOARD_TYPE_5GHZ = 2,
|
||||
};
|
||||
#include "mt76x02_eeprom.h"
|
||||
|
||||
enum mt76x2_cal_channel_group {
|
||||
MT_CH_5G_JAPAN,
|
||||
@ -137,51 +51,18 @@ struct mt76x2_temp_comp {
|
||||
unsigned int low_slope; /* J / dB */
|
||||
};
|
||||
|
||||
static inline int
|
||||
mt76x2_eeprom_get(struct mt76x2_dev *dev, enum mt76x2_eeprom_field field)
|
||||
{
|
||||
if ((field & 1) || field >= __MT_EE_MAX)
|
||||
return -1;
|
||||
|
||||
return get_unaligned_le16(dev->mt76.eeprom.data + field);
|
||||
}
|
||||
|
||||
void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t,
|
||||
struct ieee80211_channel *chan);
|
||||
int mt76x2_get_max_rate_power(struct mt76_rate_power *r);
|
||||
void mt76x2_get_power_info(struct mt76x2_dev *dev,
|
||||
struct mt76x2_tx_power_info *t,
|
||||
struct ieee80211_channel *chan);
|
||||
int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t);
|
||||
bool mt76x2_ext_pa_enabled(struct mt76x2_dev *dev, enum nl80211_band band);
|
||||
void mt76x2_read_rx_gain(struct mt76x2_dev *dev);
|
||||
void mt76x2_eeprom_parse_hw_cap(struct mt76x2_dev *dev);
|
||||
|
||||
static inline bool
|
||||
mt76x2_temp_tx_alc_enabled(struct mt76x2_dev *dev)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G);
|
||||
if (!(val & BIT(15)))
|
||||
return false;
|
||||
|
||||
return mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1) &
|
||||
MT_EE_NIC_CONF_1_TEMP_TX_ALC;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt76x2_tssi_enabled(struct mt76x2_dev *dev)
|
||||
{
|
||||
return !mt76x2_temp_tx_alc_enabled(dev) &&
|
||||
(mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1) &
|
||||
MT_EE_NIC_CONF_1_TX_ALC_EN);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt76x2_has_ext_lna(struct mt76x2_dev *dev)
|
||||
{
|
||||
u32 val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1);
|
||||
u32 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_1);
|
||||
|
||||
if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ)
|
||||
return val & MT_EE_NIC_CONF_1_LNA_EXT_2G;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "mt76x2_eeprom.h"
|
||||
#include "mt76x2_mcu.h"
|
||||
#include "mt76x02_util.h"
|
||||
#include "mt76x02_dma.h"
|
||||
|
||||
static void
|
||||
mt76x2_mac_pbf_init(struct mt76x2_dev *dev)
|
||||
@ -44,7 +45,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev)
|
||||
u16 eep_val;
|
||||
s8 offset = 0;
|
||||
|
||||
eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_2);
|
||||
eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_2);
|
||||
|
||||
offset = eep_val & 0x7f;
|
||||
if ((eep_val & 0xff) == 0xff)
|
||||
@ -54,7 +55,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev)
|
||||
|
||||
eep_val >>= 8;
|
||||
if (eep_val == 0x00 || eep_val == 0xff) {
|
||||
eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_1);
|
||||
eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_1);
|
||||
eep_val &= 0xff;
|
||||
|
||||
if (eep_val == 0x00 || eep_val == 0xff)
|
||||
@ -65,7 +66,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev)
|
||||
mt76_rmw_field(dev, MT_XO_CTRL5, MT_XO_CTRL5_C2_VAL, eep_val + offset);
|
||||
mt76_set(dev, MT_XO_CTRL6, MT_XO_CTRL6_C2_CTRL);
|
||||
|
||||
eep_val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_2);
|
||||
eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2);
|
||||
switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) {
|
||||
case 0:
|
||||
mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80);
|
||||
@ -78,23 +79,6 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x2_init_beacon_offsets(struct mt76x2_dev *dev)
|
||||
{
|
||||
u16 base = MT_BEACON_BASE;
|
||||
u32 regs[4] = {};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
u16 addr = dev->beacon_offsets[i];
|
||||
|
||||
regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4));
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
|
||||
}
|
||||
|
||||
static int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard)
|
||||
{
|
||||
static const u8 null_addr[ETH_ALEN] = {};
|
||||
@ -186,7 +170,7 @@ static int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard)
|
||||
MT_CH_TIME_CFG_EIFS_AS_BUSY |
|
||||
FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1));
|
||||
|
||||
mt76x2_init_beacon_offsets(dev);
|
||||
mt76x02_set_beacon_offsets(&dev->mt76);
|
||||
|
||||
mt76x2_set_tx_ackto(dev);
|
||||
|
||||
@ -204,25 +188,7 @@ int mt76x2_mac_start(struct mt76x2_dev *dev)
|
||||
mt76_rr(dev, MT_TX_STAT_FIFO);
|
||||
|
||||
memset(dev->aggr_stats, 0, sizeof(dev->aggr_stats));
|
||||
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
|
||||
wait_for_wpdma(dev);
|
||||
usleep_range(50, 100);
|
||||
|
||||
mt76_set(dev, MT_WPDMA_GLO_CFG,
|
||||
MT_WPDMA_GLO_CFG_TX_DMA_EN |
|
||||
MT_WPDMA_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
|
||||
|
||||
mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
|
||||
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL,
|
||||
MT_MAC_SYS_CTRL_ENABLE_TX |
|
||||
MT_MAC_SYS_CTRL_ENABLE_RX);
|
||||
|
||||
mt76x2_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
|
||||
MT_INT_TX_STAT);
|
||||
mt76x02_mac_start(&dev->mt76);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -332,41 +298,12 @@ void mt76x2_set_tx_ackto(struct mt76x2_dev *dev)
|
||||
|
||||
int mt76x2_init_hardware(struct mt76x2_dev *dev)
|
||||
{
|
||||
static const u16 beacon_offsets[16] = {
|
||||
/* 1024 byte per beacon */
|
||||
0xc000,
|
||||
0xc400,
|
||||
0xc800,
|
||||
0xcc00,
|
||||
0xd000,
|
||||
0xd400,
|
||||
0xd800,
|
||||
0xdc00,
|
||||
|
||||
/* BSS idx 8-15 not used for beacons */
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
0xc000,
|
||||
};
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
dev->beacon_offsets = beacon_offsets;
|
||||
tasklet_init(&dev->pre_tbtt_tasklet, mt76x2_pre_tbtt_tasklet,
|
||||
(unsigned long) dev);
|
||||
|
||||
val = mt76_rr(dev, MT_WPDMA_GLO_CFG);
|
||||
val &= MT_WPDMA_GLO_CFG_DMA_BURST_SIZE |
|
||||
MT_WPDMA_GLO_CFG_BIG_ENDIAN |
|
||||
MT_WPDMA_GLO_CFG_HDR_SEG_LEN;
|
||||
val |= MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE;
|
||||
mt76_wr(dev, MT_WPDMA_GLO_CFG, val);
|
||||
|
||||
mt76x02_dma_disable(&dev->mt76);
|
||||
mt76x2_reset_wlan(dev, true);
|
||||
mt76x2_power_on(dev);
|
||||
|
||||
@ -380,7 +317,7 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev)
|
||||
|
||||
dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
|
||||
|
||||
ret = mt76x2_dma_init(dev);
|
||||
ret = mt76x02_dma_init(&dev->mt76);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -437,7 +374,6 @@ struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev)
|
||||
dev = container_of(mdev, struct mt76x2_dev, mt76);
|
||||
mdev->dev = pdev;
|
||||
mdev->drv = &drv_ops;
|
||||
spin_lock_init(&dev->irq_lock);
|
||||
|
||||
return dev;
|
||||
}
|
||||
@ -540,6 +476,7 @@ int mt76x2_register_device(struct mt76x2_dev *dev)
|
||||
if (!status_fifo)
|
||||
return -ENOMEM;
|
||||
|
||||
tasklet_init(&dev->tx_tasklet, mt76x2_tx_tasklet, (unsigned long)dev);
|
||||
kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size);
|
||||
INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate);
|
||||
INIT_DELAYED_WORK(&dev->mac_work, mt76x2_mac_work);
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "mt76x2.h"
|
||||
#include "mt76x2_eeprom.h"
|
||||
#include "mt76x02_phy.h"
|
||||
|
||||
static void
|
||||
mt76x2_set_wlan_state(struct mt76x2_dev *dev, bool enable)
|
||||
@ -38,6 +39,9 @@ void mt76x2_reset_wlan(struct mt76x2_dev *dev, bool enable)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (!enable)
|
||||
goto out;
|
||||
|
||||
val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
|
||||
|
||||
val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
|
||||
@ -53,21 +57,11 @@ void mt76x2_reset_wlan(struct mt76x2_dev *dev, bool enable)
|
||||
mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
|
||||
udelay(20);
|
||||
|
||||
out:
|
||||
mt76x2_set_wlan_state(dev, enable);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_reset_wlan);
|
||||
|
||||
static void
|
||||
mt76x2_write_reg_pairs(struct mt76x2_dev *dev,
|
||||
const struct mt76_reg_pair *data, int len)
|
||||
{
|
||||
while (len > 0) {
|
||||
mt76_wr(dev, data->reg, data->value);
|
||||
len--;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
void mt76_write_mac_initvals(struct mt76x2_dev *dev)
|
||||
{
|
||||
#define DEFAULT_PROT_CFG_CCK \
|
||||
@ -159,8 +153,8 @@ void mt76_write_mac_initvals(struct mt76x2_dev *dev)
|
||||
{ MT_GF40_PROT_CFG, DEFAULT_PROT_CFG_40 },
|
||||
};
|
||||
|
||||
mt76x2_write_reg_pairs(dev, vals, ARRAY_SIZE(vals));
|
||||
mt76x2_write_reg_pairs(dev, prot_vals, ARRAY_SIZE(prot_vals));
|
||||
mt76_wr_rp(dev, 0, vals, ARRAY_SIZE(vals));
|
||||
mt76_wr_rp(dev, 0, prot_vals, ARRAY_SIZE(prot_vals));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_write_mac_initvals);
|
||||
|
||||
@ -183,7 +177,7 @@ void mt76x2_init_device(struct mt76x2_dev *dev)
|
||||
dev->mt76.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
dev->mt76.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
dev->chainmask = 0x202;
|
||||
dev->mt76.chainmask = 0x202;
|
||||
dev->mt76.global_wcid.idx = 255;
|
||||
dev->mt76.global_wcid.hw_key_idx = -1;
|
||||
dev->slottime = 9;
|
||||
@ -214,7 +208,7 @@ void mt76x2_init_txpower(struct mt76x2_dev *dev,
|
||||
|
||||
mt76x2_get_rate_power(dev, &t, chan);
|
||||
|
||||
chan->max_power = mt76x2_get_max_rate_power(&t) +
|
||||
chan->max_power = mt76x02_get_max_rate_power(&t) +
|
||||
target_power;
|
||||
chan->max_power /= 2;
|
||||
|
||||
|
@ -42,9 +42,9 @@ void mt76x2_mac_poll_tx_status(struct mt76x2_dev *dev, bool irq)
|
||||
trace_mac_txstat_poll(dev);
|
||||
|
||||
while (!irq || !kfifo_is_full(&dev->txstatus_fifo)) {
|
||||
spin_lock_irqsave(&dev->irq_lock, flags);
|
||||
spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags);
|
||||
ret = mt76x02_mac_load_tx_status(&dev->mt76, &stat);
|
||||
spin_unlock_irqrestore(&dev->irq_lock, flags);
|
||||
spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags);
|
||||
|
||||
if (!ret)
|
||||
break;
|
||||
@ -100,7 +100,7 @@ void mt76x2_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
|
||||
static int
|
||||
mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb)
|
||||
{
|
||||
int beacon_len = dev->beacon_offsets[1] - dev->beacon_offsets[0];
|
||||
int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
|
||||
struct mt76x02_txwi txwi;
|
||||
|
||||
if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi)))
|
||||
@ -118,8 +118,8 @@ mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb)
|
||||
static int
|
||||
__mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 bcn_idx, struct sk_buff *skb)
|
||||
{
|
||||
int beacon_len = dev->beacon_offsets[1] - dev->beacon_offsets[0];
|
||||
int beacon_addr = dev->beacon_offsets[bcn_idx];
|
||||
int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
|
||||
int beacon_addr = mt76x02_beacon_offsets[bcn_idx];
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
@ -129,8 +129,7 @@ __mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 bcn_idx, struct sk_buff *skb)
|
||||
if (skb) {
|
||||
ret = mt76_write_beacon(dev, beacon_addr, skb);
|
||||
if (!ret)
|
||||
dev->beacon_data_mask |= BIT(bcn_idx) &
|
||||
dev->beacon_mask;
|
||||
dev->beacon_data_mask |= BIT(bcn_idx);
|
||||
} else {
|
||||
dev->beacon_data_mask &= ~BIT(bcn_idx);
|
||||
for (i = 0; i < beacon_len; i += 4)
|
||||
@ -202,9 +201,9 @@ void mt76x2_mac_set_beacon_enable(struct mt76x2_dev *dev, u8 vif_idx, bool val)
|
||||
mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en);
|
||||
|
||||
if (en)
|
||||
mt76x2_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
|
||||
mt76x02_irq_enable(&dev->mt76, MT_INT_PRE_TBTT | MT_INT_TBTT);
|
||||
else
|
||||
mt76x2_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
|
||||
mt76x02_irq_disable(&dev->mt76, MT_INT_PRE_TBTT | MT_INT_TBTT);
|
||||
}
|
||||
|
||||
void mt76x2_update_channel(struct mt76_dev *mdev)
|
||||
|
@ -100,7 +100,7 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x02_txwi *txwi,
|
||||
}
|
||||
spin_unlock_bh(&dev->mt76.lock);
|
||||
|
||||
txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, dev->txpower_conf,
|
||||
txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, dev->mt76.txpower_conf,
|
||||
max_txpwr_adj);
|
||||
txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj);
|
||||
|
||||
|
@ -106,14 +106,14 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
dev->txpower_conf = hw->conf.power_level * 2;
|
||||
dev->mt76.txpower_conf = hw->conf.power_level * 2;
|
||||
|
||||
/* convert to per-chain power for 2x2 devices */
|
||||
dev->txpower_conf -= 6;
|
||||
dev->mt76.txpower_conf -= 6;
|
||||
|
||||
if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) {
|
||||
mt76x2_phy_set_txpower(dev);
|
||||
mt76x2_tx_set_txpwr_auto(dev, dev->txpower_conf);
|
||||
mt76x2_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +206,7 @@ mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)
|
||||
{
|
||||
struct mt76x2_dev *dev = hw->priv;
|
||||
|
||||
*dbm = dev->txpower_cur / 2;
|
||||
*dbm = dev->mt76.txpower_cur / 2;
|
||||
|
||||
/* convert from per-chain power to combined output on 2x2 devices */
|
||||
*dbm += 3;
|
||||
@ -241,7 +241,7 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
dev->chainmask = (tx_ant == 3) ? 0x202 : 0x101;
|
||||
dev->mt76.chainmask = (tx_ant == 3) ? 0x202 : 0x101;
|
||||
dev->mt76.antenna_mask = tx_ant;
|
||||
|
||||
mt76_set_stream_caps(&dev->mt76, true);
|
||||
|
@ -141,7 +141,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev)
|
||||
|
||||
mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
|
||||
|
||||
val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_2);
|
||||
val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2);
|
||||
if (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, val) == 1)
|
||||
mt76_set(dev, MT_MCU_COM_REG0, BIT(30));
|
||||
|
||||
@ -154,6 +154,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev)
|
||||
}
|
||||
|
||||
dev_info(dev->mt76.dev, "Firmware running!\n");
|
||||
mt76x02_set_ethtool_fwver(&dev->mt76, hdr);
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#define MT_MCU_PCIE_REMAP_BASE1 0x0740
|
||||
#define MT_MCU_PCIE_REMAP_BASE2 0x0744
|
||||
#define MT_MCU_PCIE_REMAP_BASE3 0x0748
|
||||
#define MT_MCU_PCIE_REMAP_BASE4 0x074C
|
||||
|
||||
#define MT_LED_CTRL 0x0770
|
||||
#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n)))
|
||||
@ -50,16 +49,10 @@
|
||||
#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \
|
||||
MT_LED_STATUS_DURATION_MASK)
|
||||
|
||||
#define MT_MCU_SEMAPHORE_00 0x07B0
|
||||
#define MT_MCU_SEMAPHORE_01 0x07B4
|
||||
#define MT_MCU_SEMAPHORE_02 0x07B8
|
||||
#define MT_MCU_SEMAPHORE_03 0x07BC
|
||||
|
||||
#define MT_MCU_ROM_PATCH_OFFSET 0x80000
|
||||
#define MT_MCU_ROM_PATCH_ADDR 0x90000
|
||||
|
||||
#define MT_MCU_ILM_OFFSET 0x80000
|
||||
#define MT_MCU_ILM_ADDR 0x80000
|
||||
|
||||
#define MT_MCU_DLM_OFFSET 0x100000
|
||||
#define MT_MCU_DLM_ADDR 0x90000
|
||||
|
@ -42,7 +42,7 @@ int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw,
|
||||
.idx = channel,
|
||||
.scan = scan,
|
||||
.bw = bw,
|
||||
.chainmask = cpu_to_le16(dev->chainmask),
|
||||
.chainmask = cpu_to_le16(dev->mt76.chainmask),
|
||||
};
|
||||
|
||||
/* first set the channel without the extension channel info */
|
||||
@ -60,6 +60,7 @@ EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel);
|
||||
int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level,
|
||||
u8 channel)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct sk_buff *skb;
|
||||
struct {
|
||||
u8 cr_mode;
|
||||
@ -76,8 +77,8 @@ int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level,
|
||||
u32 val;
|
||||
|
||||
val = BIT(31);
|
||||
val |= (mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff;
|
||||
val |= (mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_1) << 8) & 0xff00;
|
||||
val |= (mt76x02_eeprom_get(mdev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff;
|
||||
val |= (mt76x02_eeprom_get(mdev, MT_EE_NIC_CONF_1) << 8) & 0xff00;
|
||||
msg.cfg = cpu_to_le32(val);
|
||||
|
||||
/* first set the channel without the extension channel info */
|
||||
|
@ -53,6 +53,7 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
return -ENOMEM;
|
||||
|
||||
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
|
||||
mt76x2_reset_wlan(dev, false);
|
||||
|
||||
dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION);
|
||||
dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev);
|
||||
|
@ -25,7 +25,7 @@ mt76x2_phy_tssi_init_cal(struct mt76x2_dev *dev)
|
||||
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
|
||||
u32 flag = 0;
|
||||
|
||||
if (!mt76x2_tssi_enabled(dev))
|
||||
if (!mt76x02_tssi_enabled(&dev->mt76))
|
||||
return false;
|
||||
|
||||
if (mt76x2_channel_silent(dev))
|
||||
@ -34,7 +34,7 @@ mt76x2_phy_tssi_init_cal(struct mt76x2_dev *dev)
|
||||
if (chan->band == NL80211_BAND_5GHZ)
|
||||
flag |= BIT(0);
|
||||
|
||||
if (mt76x2_ext_pa_enabled(dev, chan->band))
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band))
|
||||
flag |= BIT(8);
|
||||
|
||||
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TSSI, flag, true);
|
||||
@ -360,7 +360,7 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
|
||||
mt76_set(dev, MT_BBP(RXO, 13), BIT(10));
|
||||
|
||||
if (!dev->cal.init_cal_done) {
|
||||
u8 val = mt76x2_eeprom_get(dev, MT_EE_BT_RCAL_RESULT);
|
||||
u8 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_BT_RCAL_RESULT);
|
||||
|
||||
if (val != 0xff)
|
||||
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_R, 0, true);
|
||||
@ -390,7 +390,7 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
|
||||
sizeof(dev->cal.agc_gain_cur));
|
||||
|
||||
/* init default values for temp compensation */
|
||||
if (mt76x2_tssi_enabled(dev)) {
|
||||
if (mt76x02_tssi_enabled(&dev->mt76)) {
|
||||
mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP,
|
||||
0x38);
|
||||
mt76_rmw_field(dev, MT_TX_ALC_CFG_2, MT_TX_ALC_CFG_2_TEMP_COMP,
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "mt76x2.h"
|
||||
#include "mt76x2_eeprom.h"
|
||||
#include "mt76x2_mcu.h"
|
||||
#include "mt76x02_phy.h"
|
||||
|
||||
static void
|
||||
mt76x2_adjust_high_lna_gain(struct mt76x2_dev *dev, int reg, s8 offset)
|
||||
@ -64,7 +65,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
|
||||
mt76_wr(dev, MT_TX_ALC_CFG_2, 0x35160a00);
|
||||
mt76_wr(dev, MT_TX_ALC_CFG_3, 0x35160a06);
|
||||
|
||||
if (mt76x2_ext_pa_enabled(dev, band)) {
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
|
||||
mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0x0000ec00);
|
||||
mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0x0000ec00);
|
||||
} else {
|
||||
@ -75,7 +76,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
|
||||
pa_mode[0] = 0x0000ffff;
|
||||
pa_mode[1] = 0x00ff00ff;
|
||||
|
||||
if (mt76x2_ext_pa_enabled(dev, band)) {
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
|
||||
mt76_wr(dev, MT_TX_ALC_CFG_2, 0x2f0f0400);
|
||||
mt76_wr(dev, MT_TX_ALC_CFG_3, 0x2f0f0476);
|
||||
} else {
|
||||
@ -83,7 +84,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
|
||||
mt76_wr(dev, MT_TX_ALC_CFG_3, 0x1b0f0476);
|
||||
}
|
||||
|
||||
if (mt76x2_ext_pa_enabled(dev, band))
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, band))
|
||||
pa_mode_adj = 0x04000000;
|
||||
else
|
||||
pa_mode_adj = 0;
|
||||
@ -97,7 +98,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
|
||||
mt76_wr(dev, MT_RF_PA_MODE_CFG0, pa_mode[0]);
|
||||
mt76_wr(dev, MT_RF_PA_MODE_CFG1, pa_mode[1]);
|
||||
|
||||
if (mt76x2_ext_pa_enabled(dev, band)) {
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
|
||||
u32 val;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
@ -124,37 +125,6 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower_regs);
|
||||
|
||||
static void
|
||||
mt76x2_limit_rate_power(struct mt76_rate_power *r, int limit)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(r->all); i++)
|
||||
if (r->all[i] > limit)
|
||||
r->all[i] = limit;
|
||||
}
|
||||
|
||||
static u32
|
||||
mt76x2_tx_power_mask(u8 v1, u8 v2, u8 v3, u8 v4)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val |= (v1 & (BIT(6) - 1)) << 0;
|
||||
val |= (v2 & (BIT(6) - 1)) << 8;
|
||||
val |= (v3 & (BIT(6) - 1)) << 16;
|
||||
val |= (v4 & (BIT(6) - 1)) << 24;
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x2_add_rate_power_offset(struct mt76_rate_power *r, int offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(r->all); i++)
|
||||
r->all[i] += offset;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x2_get_min_rate_power(struct mt76_rate_power *r)
|
||||
{
|
||||
@ -191,9 +161,9 @@ void mt76x2_phy_set_txpower(struct mt76x2_dev *dev)
|
||||
delta = txp.delta_bw80;
|
||||
|
||||
mt76x2_get_rate_power(dev, &t, chan);
|
||||
mt76x2_add_rate_power_offset(&t, txp.chain[0].target_power);
|
||||
mt76x2_limit_rate_power(&t, dev->txpower_conf);
|
||||
dev->txpower_cur = mt76x2_get_max_rate_power(&t);
|
||||
mt76x02_add_rate_power_offset(&t, txp.chain[0].target_power);
|
||||
mt76x02_limit_rate_power(&t, dev->mt76.txpower_conf);
|
||||
dev->mt76.txpower_cur = mt76x02_get_max_rate_power(&t);
|
||||
|
||||
base_power = mt76x2_get_min_rate_power(&t);
|
||||
delta += base_power - txp.chain[0].target_power;
|
||||
@ -211,31 +181,13 @@ void mt76x2_phy_set_txpower(struct mt76x2_dev *dev)
|
||||
txp_1 = 0x2f;
|
||||
}
|
||||
|
||||
mt76x2_add_rate_power_offset(&t, -base_power);
|
||||
mt76x02_add_rate_power_offset(&t, -base_power);
|
||||
dev->target_power = txp.chain[0].target_power;
|
||||
dev->target_power_delta[0] = txp_0 - txp.chain[0].target_power;
|
||||
dev->target_power_delta[1] = txp_1 - txp.chain[0].target_power;
|
||||
dev->rate_power = t;
|
||||
dev->mt76.rate_power = t;
|
||||
|
||||
mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_0, txp_0);
|
||||
mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_1, txp_1);
|
||||
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_0,
|
||||
mt76x2_tx_power_mask(t.cck[0], t.cck[2], t.ofdm[0], t.ofdm[2]));
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_1,
|
||||
mt76x2_tx_power_mask(t.ofdm[4], t.ofdm[6], t.ht[0], t.ht[2]));
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_2,
|
||||
mt76x2_tx_power_mask(t.ht[4], t.ht[6], t.ht[8], t.ht[10]));
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_3,
|
||||
mt76x2_tx_power_mask(t.ht[12], t.ht[14], t.ht[0], t.ht[2]));
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_4,
|
||||
mt76x2_tx_power_mask(t.ht[4], t.ht[6], 0, 0));
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_7,
|
||||
mt76x2_tx_power_mask(t.ofdm[6], t.vht[8], t.ht[6], t.vht[8]));
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_8,
|
||||
mt76x2_tx_power_mask(t.ht[14], t.vht[8], t.vht[8], 0));
|
||||
mt76_wr(dev, MT_TX_PWR_CFG_9,
|
||||
mt76x2_tx_power_mask(t.ht[6], t.vht[8], t.vht[8], 0));
|
||||
mt76x02_phy_set_txpower(&dev->mt76, txp_0, txp_1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower);
|
||||
|
||||
@ -244,7 +196,7 @@ void mt76x2_configure_tx_delay(struct mt76x2_dev *dev,
|
||||
{
|
||||
u32 cfg0, cfg1;
|
||||
|
||||
if (mt76x2_ext_pa_enabled(dev, band)) {
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, band)) {
|
||||
cfg0 = bw ? 0x000b0c01 : 0x00101101;
|
||||
cfg1 = 0x00011414;
|
||||
} else {
|
||||
@ -370,7 +322,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev, bool wait)
|
||||
dev->cal.tssi_comp_pending = false;
|
||||
mt76x2_get_power_info(dev, &txp, chan);
|
||||
|
||||
if (mt76x2_ext_pa_enabled(dev, chan->band))
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band))
|
||||
t.pa_mode = 1;
|
||||
|
||||
t.cal_mode = BIT(1);
|
||||
|
@ -57,23 +57,23 @@ s8 mt76x2_tx_get_max_txpwr_adj(struct mt76_dev *mdev,
|
||||
u8 mcs = ieee80211_rate_get_vht_mcs(rate);
|
||||
|
||||
if (mcs == 8 || mcs == 9) {
|
||||
max_txpwr = dev->rate_power.vht[8];
|
||||
max_txpwr = mdev->rate_power.vht[8];
|
||||
} else {
|
||||
u8 nss, idx;
|
||||
|
||||
nss = ieee80211_rate_get_vht_nss(rate);
|
||||
idx = ((nss - 1) << 3) + mcs;
|
||||
max_txpwr = dev->rate_power.ht[idx & 0xf];
|
||||
max_txpwr = mdev->rate_power.ht[idx & 0xf];
|
||||
}
|
||||
} else if (rate->flags & IEEE80211_TX_RC_MCS) {
|
||||
max_txpwr = dev->rate_power.ht[rate->idx & 0xf];
|
||||
max_txpwr = mdev->rate_power.ht[rate->idx & 0xf];
|
||||
} else {
|
||||
enum nl80211_band band = dev->mt76.chandef.chan->band;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ) {
|
||||
const struct ieee80211_rate *r;
|
||||
struct wiphy *wiphy = mt76_hw(dev)->wiphy;
|
||||
struct mt76_rate_power *rp = &dev->rate_power;
|
||||
struct mt76_rate_power *rp = &mdev->rate_power;
|
||||
|
||||
r = &wiphy->bands[band]->bitrates[rate->idx];
|
||||
if (r->flags & IEEE80211_RATE_SHORT_PREAMBLE)
|
||||
@ -81,7 +81,7 @@ s8 mt76x2_tx_get_max_txpwr_adj(struct mt76_dev *mdev,
|
||||
else
|
||||
max_txpwr = rp->ofdm[r->hw_value & 0x7];
|
||||
} else {
|
||||
max_txpwr = dev->rate_power.ofdm[rate->idx & 0x7];
|
||||
max_txpwr = mdev->rate_power.ofdm[rate->idx & 0x7];
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ EXPORT_SYMBOL_GPL(mt76x2_tx_get_max_txpwr_adj);
|
||||
|
||||
s8 mt76x2_tx_get_txpwr_adj(struct mt76x2_dev *dev, s8 txpwr, s8 max_txpwr_adj)
|
||||
{
|
||||
txpwr = min_t(s8, txpwr, dev->txpower_conf);
|
||||
txpwr = min_t(s8, txpwr, dev->mt76.txpower_conf);
|
||||
txpwr -= (dev->target_power + dev->target_power_delta[0]);
|
||||
txpwr = min_t(s8, txpwr, max_txpwr_adj);
|
||||
|
||||
@ -109,7 +109,7 @@ void mt76x2_tx_set_txpwr_auto(struct mt76x2_dev *dev, s8 txpwr)
|
||||
s8 txpwr_adj;
|
||||
|
||||
txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, txpwr,
|
||||
dev->rate_power.ofdm[4]);
|
||||
dev->mt76.rate_power.ofdm[4]);
|
||||
mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG,
|
||||
MT_PROT_AUTO_TX_CFG_PROT_PADJ, txpwr_adj);
|
||||
mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG,
|
||||
|
@ -36,7 +36,6 @@ int mt76x2u_init_hardware(struct mt76x2_dev *dev);
|
||||
void mt76x2u_cleanup(struct mt76x2_dev *dev);
|
||||
void mt76x2u_stop_hw(struct mt76x2_dev *dev);
|
||||
|
||||
void mt76x2u_mac_setaddr(struct mt76x2_dev *dev, u8 *addr);
|
||||
int mt76x2u_mac_reset(struct mt76x2_dev *dev);
|
||||
void mt76x2u_mac_resume(struct mt76x2_dev *dev);
|
||||
int mt76x2u_mac_start(struct mt76x2_dev *dev);
|
||||
@ -46,8 +45,6 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
void mt76x2u_phy_calibrate(struct work_struct *work);
|
||||
void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev);
|
||||
void mt76x2u_phy_set_txdac(struct mt76x2_dev *dev);
|
||||
void mt76x2u_phy_set_rxpath(struct mt76x2_dev *dev);
|
||||
|
||||
void mt76x2u_mcu_complete_urb(struct urb *urb);
|
||||
int mt76x2u_mcu_set_dynamic_vga(struct mt76x2_dev *dev, u8 channel, bool ap,
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "mt76x2u.h"
|
||||
#include "mt76x02_util.h"
|
||||
#include "mt76x02_phy.h"
|
||||
#include "mt76x2_eeprom.h"
|
||||
|
||||
static void mt76x2u_init_dma(struct mt76x2_dev *dev)
|
||||
@ -129,7 +130,7 @@ static int mt76x2u_init_eeprom(struct mt76x2_dev *dev)
|
||||
put_unaligned_le32(val, dev->mt76.eeprom.data + i);
|
||||
}
|
||||
|
||||
mt76x2_eeprom_parse_hw_cap(dev);
|
||||
mt76x02_eeprom_parse_hw_cap(&dev->mt76);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -165,21 +166,12 @@ static void mt76x2u_init_beacon_offsets(struct mt76x2_dev *dev)
|
||||
|
||||
int mt76x2u_init_hardware(struct mt76x2_dev *dev)
|
||||
{
|
||||
static const u16 beacon_offsets[] = {
|
||||
/* 512 byte per beacon */
|
||||
0xc000, 0xc200, 0xc400, 0xc600,
|
||||
0xc800, 0xca00, 0xcc00, 0xce00,
|
||||
0xd000, 0xd200, 0xd400, 0xd600,
|
||||
0xd800, 0xda00, 0xdc00, 0xde00
|
||||
};
|
||||
const struct mt76_wcid_addr addr = {
|
||||
.macaddr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
.ba_mask = 0,
|
||||
};
|
||||
int i, err;
|
||||
|
||||
dev->beacon_offsets = beacon_offsets;
|
||||
|
||||
mt76x2_reset_wlan(dev, true);
|
||||
mt76x2u_power_on(dev);
|
||||
|
||||
@ -212,12 +204,13 @@ int mt76x2u_init_hardware(struct mt76x2_dev *dev)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
mt76x2u_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
|
||||
mt76x02_mac_setaddr(&dev->mt76,
|
||||
dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
|
||||
dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
|
||||
|
||||
mt76x2u_init_beacon_offsets(dev);
|
||||
|
||||
if (!mt76x2_wait_for_bbp(dev))
|
||||
if (!mt76x02_wait_for_txrx_idle(&dev->mt76))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* reset wcid table */
|
||||
@ -244,8 +237,8 @@ int mt76x2u_init_hardware(struct mt76x2_dev *dev)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
mt76x2u_phy_set_rxpath(dev);
|
||||
mt76x2u_phy_set_txdac(dev);
|
||||
mt76x02_phy_set_rxpath(&dev->mt76);
|
||||
mt76x02_phy_set_txdac(&dev->mt76);
|
||||
|
||||
return mt76x2u_mac_stop(dev);
|
||||
}
|
||||
@ -263,14 +256,14 @@ int mt76x2u_register_device(struct mt76x2_dev *dev)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt76u_mcu_init_rx(&dev->mt76);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt76u_alloc_queues(&dev->mt76);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
err = mt76u_mcu_init_rx(&dev->mt76);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt76x2u_init_hardware(dev);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
@ -32,7 +32,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev)
|
||||
s8 offset = 0;
|
||||
u16 eep_val;
|
||||
|
||||
eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_2);
|
||||
eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_2);
|
||||
|
||||
offset = eep_val & 0x7f;
|
||||
if ((eep_val & 0xff) == 0xff)
|
||||
@ -42,7 +42,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev)
|
||||
|
||||
eep_val >>= 8;
|
||||
if (eep_val == 0x00 || eep_val == 0xff) {
|
||||
eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_1);
|
||||
eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_1);
|
||||
eep_val &= 0xff;
|
||||
|
||||
if (eep_val == 0x00 || eep_val == 0xff)
|
||||
@ -67,7 +67,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev)
|
||||
/* init fce */
|
||||
mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
|
||||
|
||||
eep_val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_2);
|
||||
eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2);
|
||||
switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) {
|
||||
case 0:
|
||||
mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80);
|
||||
@ -119,7 +119,7 @@ int mt76x2u_mac_start(struct mt76x2_dev *dev)
|
||||
mt76x2u_mac_reset_counters(dev);
|
||||
|
||||
mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
|
||||
wait_for_wpdma(dev);
|
||||
mt76x02_wait_for_wpdma(&dev->mt76, 1000);
|
||||
usleep_range(50, 100);
|
||||
|
||||
mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
|
||||
@ -220,21 +220,3 @@ void mt76x2u_mac_resume(struct mt76x2_dev *dev)
|
||||
mt76_set(dev, MT_TXOP_CTRL_CFG, BIT(20));
|
||||
mt76_set(dev, MT_TXOP_HLDR_ET, BIT(1));
|
||||
}
|
||||
|
||||
void mt76x2u_mac_setaddr(struct mt76x2_dev *dev, u8 *addr)
|
||||
{
|
||||
ether_addr_copy(dev->mt76.macaddr, addr);
|
||||
|
||||
if (!is_valid_ether_addr(dev->mt76.macaddr)) {
|
||||
eth_random_addr(dev->mt76.macaddr);
|
||||
dev_info(dev->mt76.dev,
|
||||
"Invalid MAC address, using random address %pM\n",
|
||||
dev->mt76.macaddr);
|
||||
}
|
||||
|
||||
mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->mt76.macaddr));
|
||||
mt76_wr(dev, MT_MAC_ADDR_DW1,
|
||||
get_unaligned_le16(dev->mt76.macaddr + 4) |
|
||||
FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ static int mt76x2u_add_interface(struct ieee80211_hw *hw,
|
||||
struct mt76x2_dev *dev = hw->priv;
|
||||
|
||||
if (!ether_addr_equal(dev->mt76.macaddr, vif->addr))
|
||||
mt76x2u_mac_setaddr(dev, vif->addr);
|
||||
mt76x02_mac_setaddr(&dev->mt76, vif->addr);
|
||||
|
||||
mt76x02_vif_init(&dev->mt76, vif, 0);
|
||||
return 0;
|
||||
@ -128,10 +128,10 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
dev->txpower_conf = hw->conf.power_level * 2;
|
||||
dev->mt76.txpower_conf = hw->conf.power_level * 2;
|
||||
|
||||
/* convert to per-chain power for 2x2 devices */
|
||||
dev->txpower_conf -= 6;
|
||||
dev->mt76.txpower_conf -= 6;
|
||||
|
||||
if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
|
||||
mt76x2_phy_set_txpower(dev);
|
||||
|
@ -261,6 +261,7 @@ static int mt76x2u_mcu_load_firmware(struct mt76x2_dev *dev)
|
||||
/* enable FCE to send in-band cmd */
|
||||
mt76_wr(dev, MT_FCE_PSE_CTRL, 0x1);
|
||||
dev_dbg(dev->mt76.dev, "firmware running\n");
|
||||
mt76x02_set_ethtool_fwver(&dev->mt76, hdr);
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
@ -17,39 +17,6 @@
|
||||
#include "mt76x2u.h"
|
||||
#include "mt76x2_eeprom.h"
|
||||
|
||||
void mt76x2u_phy_set_rxpath(struct mt76x2_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = mt76_rr(dev, MT_BBP(AGC, 0));
|
||||
val &= ~BIT(4);
|
||||
|
||||
switch (dev->chainmask & 0xf) {
|
||||
case 2:
|
||||
val |= BIT(3);
|
||||
break;
|
||||
default:
|
||||
val &= ~BIT(3);
|
||||
break;
|
||||
}
|
||||
mt76_wr(dev, MT_BBP(AGC, 0), val);
|
||||
}
|
||||
|
||||
void mt76x2u_phy_set_txdac(struct mt76x2_dev *dev)
|
||||
{
|
||||
int txpath;
|
||||
|
||||
txpath = (dev->chainmask >> 8) & 0xf;
|
||||
switch (txpath) {
|
||||
case 2:
|
||||
mt76_set(dev, MT_BBP(TXBE, 5), 0x3);
|
||||
break;
|
||||
default:
|
||||
mt76_clear(dev, MT_BBP(TXBE, 5), 0x3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev)
|
||||
{
|
||||
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
|
||||
@ -209,7 +176,7 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
|
||||
mt76_set(dev, MT_BBP(RXO, 13), BIT(10));
|
||||
|
||||
if (!dev->cal.init_cal_done) {
|
||||
u8 val = mt76x2_eeprom_get(dev, MT_EE_BT_RCAL_RESULT);
|
||||
u8 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_BT_RCAL_RESULT);
|
||||
|
||||
if (val != 0xff)
|
||||
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_R,
|
||||
@ -235,7 +202,7 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
|
||||
if (scan)
|
||||
return 0;
|
||||
|
||||
if (mt76x2_tssi_enabled(dev)) {
|
||||
if (mt76x02_tssi_enabled(&dev->mt76)) {
|
||||
/* init default values for temp compensation */
|
||||
mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP,
|
||||
0x38);
|
||||
@ -250,7 +217,7 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
|
||||
chan = dev->mt76.chandef.chan;
|
||||
if (chan->band == NL80211_BAND_5GHZ)
|
||||
flag |= BIT(0);
|
||||
if (mt76x2_ext_pa_enabled(dev, chan->band))
|
||||
if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band))
|
||||
flag |= BIT(8);
|
||||
mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TSSI,
|
||||
flag, false);
|
||||
|
@ -91,11 +91,23 @@ mt76_txq_get_qid(struct ieee80211_txq *txq)
|
||||
return txq->ac;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_check_agg_ssn(struct mt76_txq *mtxq, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
if (!ieee80211_is_data_qos(hdr->frame_control))
|
||||
return;
|
||||
|
||||
mtxq->agg_ssn = le16_to_cpu(hdr->seq_ctrl) + 0x10;
|
||||
}
|
||||
|
||||
void
|
||||
mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
||||
struct mt76_wcid *wcid, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct mt76_queue *q;
|
||||
int qid = skb_get_queue_mapping(skb);
|
||||
|
||||
@ -108,6 +120,19 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
||||
ieee80211_get_tx_rates(info->control.vif, sta, skb,
|
||||
info->control.rates, 1);
|
||||
|
||||
if (sta && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
struct ieee80211_txq *txq;
|
||||
struct mt76_txq *mtxq;
|
||||
u8 tid;
|
||||
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
txq = sta->txq[tid];
|
||||
mtxq = (struct mt76_txq *) txq->drv_priv;
|
||||
|
||||
if (mtxq->aggr)
|
||||
mt76_check_agg_ssn(mtxq, skb);
|
||||
}
|
||||
|
||||
q = &dev->q_tx[qid];
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
@ -143,17 +168,6 @@ mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps)
|
||||
return skb;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_check_agg_ssn(struct mt76_txq *mtxq, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
|
||||
if (!ieee80211_is_data_qos(hdr->frame_control))
|
||||
return;
|
||||
|
||||
mtxq->agg_ssn = le16_to_cpu(hdr->seq_ctrl) + 0x10;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
||||
struct sk_buff *skb, bool last)
|
||||
|
@ -14,6 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "mt76.h"
|
||||
#include "usb_trace.h"
|
||||
#include "dma.h"
|
||||
@ -279,6 +280,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
|
||||
struct urb *urb = buf->urb;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&q->rx_page_lock);
|
||||
for (i = 0; i < nsgs; i++) {
|
||||
struct page *page;
|
||||
void *data;
|
||||
@ -292,6 +294,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
|
||||
offset = data - page_address(page);
|
||||
sg_set_page(&urb->sg[i], page, sglen, offset);
|
||||
}
|
||||
spin_unlock_bh(&q->rx_page_lock);
|
||||
|
||||
if (i < nsgs) {
|
||||
int j;
|
||||
@ -383,9 +386,9 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
|
||||
min_len = MT_DMA_HDR_LEN + MT_RX_RXWI_LEN +
|
||||
MT_FCE_INFO_LEN;
|
||||
|
||||
if (data_len < min_len || WARN_ON(!dma_len) ||
|
||||
WARN_ON(dma_len + MT_DMA_HDR_LEN > data_len) ||
|
||||
WARN_ON(dma_len & 0x3))
|
||||
if (data_len < min_len || !dma_len ||
|
||||
dma_len + MT_DMA_HDR_LEN > data_len ||
|
||||
(dma_len & 0x3))
|
||||
return -EINVAL;
|
||||
return dma_len;
|
||||
}
|
||||
@ -520,6 +523,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
|
||||
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
|
||||
int i, err, nsgs;
|
||||
|
||||
spin_lock_init(&q->rx_page_lock);
|
||||
spin_lock_init(&q->lock);
|
||||
q->entry = devm_kzalloc(dev->dev,
|
||||
MT_NUM_RX_ENTRIES * sizeof(*q->entry),
|
||||
@ -557,12 +561,15 @@ static void mt76u_free_rx(struct mt76_dev *dev)
|
||||
for (i = 0; i < q->ndesc; i++)
|
||||
mt76u_buf_free(&q->entry[i].ubuf);
|
||||
|
||||
spin_lock_bh(&q->rx_page_lock);
|
||||
if (!q->rx_page.va)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
page = virt_to_page(q->rx_page.va);
|
||||
__page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
|
||||
memset(&q->rx_page, 0, sizeof(q->rx_page));
|
||||
out:
|
||||
spin_unlock_bh(&q->rx_page_lock);
|
||||
}
|
||||
|
||||
static void mt76u_stop_rx(struct mt76_dev *dev)
|
||||
|
Loading…
Reference in New Issue
Block a user