Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,29 @@
# SPDX-License-Identifier: GPL-2.0-only
config MT76x0_COMMON
tristate
select MT76x02_LIB
config MT76x0U
tristate "MediaTek MT76x0U (USB) support"
select MT76x0_COMMON
select MT76x02_USB
depends on MAC80211
depends on USB
help
This adds support for MT7610U-based USB 2.0 wireless dongles,
which comply with IEEE 802.11ac standards and support 1x1
433Mbps PHY rate.
To compile this driver as a module, choose M here.
config MT76x0E
tristate "MediaTek MT76x0E (PCIe) support"
select MT76x0_COMMON
depends on MAC80211
depends on PCI
help
This adds support for MT7610/MT7630-based PCIe wireless devices,
which comply with IEEE 802.11ac standards and support 1x1
433Mbps PHY rate.
To compile this driver as a module, choose M here.
@@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_MT76x0U) += mt76x0u.o
obj-$(CONFIG_MT76x0E) += mt76x0e.o
obj-$(CONFIG_MT76x0_COMMON) += mt76x0-common.o
mt76x0-common-y := init.o main.o eeprom.o phy.o
mt76x0u-y := usb.o usb_mcu.o
mt76x0e-y := pci.o pci_mcu.o
# ccflags-y := -DDEBUG
@@ -0,0 +1,350 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*/
#include <linux/module.h>
#include <linux/of.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/etherdevice.h>
#include <linux/unaligned.h>
#include "mt76x0.h"
#include "eeprom.h"
#include "../mt76x02_phy.h"
#define MT_MAP_READS DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16)
static int
mt76x0_efuse_physical_size_check(struct mt76x02_dev *dev)
{
u8 data[MT_MAP_READS * 16];
int ret, i;
u32 start = 0, end = 0, cnt_free;
ret = mt76x02_get_efuse_data(dev, 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]) {
if (!start)
start = MT_EE_USAGE_MAP_START + i;
end = MT_EE_USAGE_MAP_START + i;
}
cnt_free = end - start + 1;
if (MT_EFUSE_USAGE_MAP_SIZE - cnt_free < 5) {
dev_err(dev->mt76.dev,
"driver does not support default EEPROM\n");
return -EINVAL;
}
return 0;
}
static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
{
u16 nic_conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
u16 nic_conf1 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
mt76x02_eeprom_parse_hw_cap(dev);
dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n",
dev->mphy.cap.has_2ghz, dev->mphy.cap.has_5ghz);
if (dev->no_2ghz) {
dev->mphy.cap.has_2ghz = false;
dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");
}
if (is_mt7630(dev)) {
dev->mphy.cap.has_5ghz = false;
dev_dbg(dev->mt76.dev, "mask out 5GHz support\n");
}
if (!mt76x02_field_valid(nic_conf1 & 0xff))
nic_conf1 &= 0xff00;
if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL)
dev_dbg(dev->mt76.dev,
"driver does not support HW RF ctrl\n");
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, "invalid tx-rx stream\n");
}
static void mt76x0_set_temp_offset(struct mt76x02_dev *dev)
{
u8 val;
val = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER) >> 8;
if (mt76x02_field_valid(val))
dev->cal.rx.temp_offset = mt76x02_sign_extend(val, 8);
else
dev->cal.rx.temp_offset = -10;
}
static void mt76x0_set_freq_offset(struct mt76x02_dev *dev)
{
struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx;
u8 val;
val = mt76x02_eeprom_get(dev, MT_EE_FREQ_OFFSET);
if (!mt76x02_field_valid(val))
val = 0;
caldata->freq_offset = val;
val = mt76x02_eeprom_get(dev, 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 mt76x02_dev *dev)
{
struct ieee80211_channel *chan = dev->mphy.chandef.chan;
struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx;
s8 val, lna_5g[3], lna_2g;
u16 rssi_offset;
int i;
mt76x02_get_rx_gain(dev, chan->band, &rssi_offset, &lna_2g, lna_5g);
caldata->lna_gain = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan);
for (i = 0; i < ARRAY_SIZE(caldata->rssi_offset); i++) {
val = rssi_offset >> (8 * i);
if (val < -10 || val > 10)
val = 0;
caldata->rssi_offset[i] = val;
}
}
static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
{
struct cfg80211_chan_def *chandef = &dev->mphy.chandef;
u8 val;
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;
}
return mt76x02_rate_power_val(val);
}
void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev,
struct ieee80211_channel *chan,
struct mt76x02_rate_power *t)
{
bool is_2ghz = chan->band == NL80211_BAND_2GHZ;
u16 val, addr;
s8 delta;
memset(t, 0, sizeof(*t));
/* cck 1M, 2M, 5.5M, 11M */
val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_BYRATE_BASE);
t->cck[0] = t->cck[1] = s6_to_s8(val);
t->cck[2] = t->cck[3] = s6_to_s8(val >> 8);
/* ofdm 6M, 9M, 12M, 18M */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 2 : 0x120;
val = mt76x02_eeprom_get(dev, 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, 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, addr);
t->ht[0] = t->ht[1] = s6_to_s8(val);
t->ht[2] = t->ht[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, addr);
t->ht[4] = t->ht[5] = s6_to_s8(val);
t->ht[6] = t->ht[7] = s6_to_s8(val >> 8);
/* vht mcs 8, 9 5GHz */
val = mt76x02_eeprom_get(dev, 0x12c);
t->vht[0] = s6_to_s8(val);
t->vht[1] = s6_to_s8(val >> 8);
delta = mt76x0_tssi_enabled(dev) ? 0 : mt76x0_get_delta(dev);
mt76x02_add_rate_power_offset(t, delta);
}
void mt76x0_get_power_info(struct mt76x02_dev *dev,
struct ieee80211_channel *chan, s8 *tp)
{
static const struct mt76x0_chan_map {
u8 chan;
u8 offset;
} chan_map[] = {
{ 2, 0 }, { 4, 2 }, { 6, 4 }, { 8, 6 },
{ 10, 8 }, { 12, 10 }, { 14, 12 }, { 38, 0 },
{ 44, 2 }, { 48, 4 }, { 54, 6 }, { 60, 8 },
{ 64, 10 }, { 102, 12 }, { 108, 14 }, { 112, 16 },
{ 118, 18 }, { 124, 20 }, { 128, 22 }, { 134, 24 },
{ 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 },
{ 167, 34 }, { 171, 36 }, { 175, 38 },
};
u8 offset, addr;
int i, idx = 0;
u16 data;
if (mt76x0_tssi_enabled(dev)) {
s8 target_power;
if (chan->band == NL80211_BAND_5GHZ)
data = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER);
else
data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER);
target_power = (data & 0xff) - dev->rate_power.ofdm[7];
*tp = target_power + mt76x0_get_delta(dev);
return;
}
for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
if (chan->hw_value <= chan_map[i].chan) {
idx = (chan->hw_value == chan_map[i].chan);
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 42:
offset = 2;
break;
case 58:
offset = 8;
break;
case 106:
offset = 14;
break;
case 122:
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, addr);
*tp = data >> (8 * idx);
if (*tp < 0 || *tp > 0x3f)
*tp = 5;
}
static int mt76x0_check_eeprom(struct mt76x02_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 mt76x02_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, 0, dev->mt76.eeprom.data,
MT76X0_EEPROM_SIZE, MT_EE_READ);
}
int mt76x0_eeprom_init(struct mt76x02_dev *dev)
{
u8 version, fae;
u16 data;
int err;
err = mt76x0_load_eeprom(dev);
if (err < 0)
return err;
data = mt76x02_eeprom_get(dev, 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);
memcpy(dev->mphy.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
ETH_ALEN);
err = mt76_eeprom_override(&dev->mphy);
if (err)
return err;
mt76x02_mac_setaddr(dev, dev->mphy.macaddr);
mt76x0_set_chip_cap(dev);
mt76x0_set_freq_offset(dev);
mt76x0_set_temp_offset(dev);
return 0;
}
MODULE_DESCRIPTION("MediaTek MT76x EEPROM helpers");
MODULE_LICENSE("Dual BSD/GPL");
@@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*/
#ifndef __MT76X0U_EEPROM_H
#define __MT76X0U_EEPROM_H
#include "../mt76x02_eeprom.h"
struct mt76x02_dev;
#define MT76X0U_EE_MAX_VER 0x0c
#define MT76X0_EEPROM_SIZE 512
int mt76x0_eeprom_init(struct mt76x02_dev *dev);
void mt76x0_read_rx_gain(struct mt76x02_dev *dev);
void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev,
struct ieee80211_channel *chan,
struct mt76x02_rate_power *t);
void mt76x0_get_power_info(struct mt76x02_dev *dev,
struct ieee80211_channel *chan, s8 *tp);
static inline s8 s6_to_s8(u32 val)
{
s8 ret = val & GENMASK(5, 0);
if (ret & BIT(5))
ret -= BIT(6);
return ret;
}
static inline bool mt76x0_tssi_enabled(struct mt76x02_dev *dev)
{
return (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) &
MT_EE_NIC_CONF_1_TX_ALC_EN);
}
#endif
@@ -0,0 +1,266 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* (c) Copyright 2002-2010, Ralink Technology, Inc.
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*/
#include "mt76x0.h"
#include "eeprom.h"
#include "mcu.h"
#include "initvals.h"
#include "initvals_init.h"
#include "../mt76x02_phy.h"
static void
mt76x0_set_wlan_state(struct mt76x02_dev *dev, u32 val, bool enable)
{
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.
* In case anyone (PSM?) wants to use this function we can
* bring the clock stuff back and fixup the probe path.
*/
if (enable)
val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
else
val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN);
mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
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 (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 mt76x02_dev *dev, bool enable, bool reset)
{
u32 val;
val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
if (reset) {
val |= MT_WLAN_FUN_CTRL_GPIO_OUT_EN;
val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
if (val & MT_WLAN_FUN_CTRL_WLAN_EN) {
val |= (MT_WLAN_FUN_CTRL_WLAN_RESET |
MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
udelay(20);
val &= ~(MT_WLAN_FUN_CTRL_WLAN_RESET |
MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
}
}
mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
udelay(20);
mt76x0_set_wlan_state(dev, val, enable);
}
EXPORT_SYMBOL_GPL(mt76x0_chip_onoff);
static void mt76x0_reset_csr_bbp(struct mt76x02_dev *dev)
{
mt76_wr(dev, MT_MAC_SYS_CTRL,
MT_MAC_SYS_CTRL_RESET_CSR |
MT_MAC_SYS_CTRL_RESET_BBP);
msleep(200);
mt76_clear(dev, MT_MAC_SYS_CTRL,
MT_MAC_SYS_CTRL_RESET_CSR |
MT_MAC_SYS_CTRL_RESET_BBP);
}
#define RANDOM_WRITE(dev, tab) \
mt76_wr_rp(dev, MT_MCU_MEMMAP_WLAN, \
tab, ARRAY_SIZE(tab))
static int mt76x0_init_bbp(struct mt76x02_dev *dev)
{
int ret, i;
ret = mt76x0_phy_wait_bbp_ready(dev);
if (ret)
return ret;
RANDOM_WRITE(dev, mt76x0_bbp_init_tab);
for (i = 0; i < ARRAY_SIZE(mt76x0_bbp_switch_tab); i++) {
const struct mt76x0_bbp_switch_item *item = &mt76x0_bbp_switch_tab[i];
const struct mt76_reg_pair *pair = &item->reg_pair;
if (((RF_G_BAND | RF_BW_20) & item->bw_band) == (RF_G_BAND | RF_BW_20))
mt76_wr(dev, pair->reg, pair->value);
}
RANDOM_WRITE(dev, mt76x0_dcoc_tab);
return 0;
}
static void mt76x0_init_mac_registers(struct mt76x02_dev *dev)
{
RANDOM_WRITE(dev, common_mac_reg_table);
/* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */
RANDOM_WRITE(dev, mt76x0_mac_reg_table);
/* Release BBP and MAC reset MAC_SYS_CTRL[1:0] = 0x0 */
mt76_clear(dev, MT_MAC_SYS_CTRL, 0x3);
/* Set 0x141C[15:12]=0xF */
mt76_set(dev, MT_EXT_CCA_CFG, 0xf000);
mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
/*
* tx_ring 9 is for mgmt frame
* tx_ring 8 is for in-band command frame.
* WMM_RG0_TXQMA: this register setting is for FCE to
* define the rule of tx_ring 9
* WMM_RG1_TXQMA: this register setting is for FCE to
* define the rule of tx_ring 8
*/
mt76_rmw(dev, MT_WMM_CTRL, 0x3ff, 0x201);
}
void mt76x0_mac_stop(struct mt76x02_dev *dev)
{
int i = 200, ok = 0;
mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
/* Page count on TxQ */
while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
(mt76_rr(dev, 0x0a30) & 0x000000ff) ||
(mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
msleep(10);
if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000))
dev_warn(dev->mt76.dev, "Warning: MAC TX did not stop!\n");
mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX |
MT_MAC_SYS_CTRL_ENABLE_TX);
/* Page count on RxQ */
for (i = 0; i < 200; i++) {
if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
!mt76_rr(dev, 0x0a30) &&
!mt76_rr(dev, 0x0a34)) {
if (ok++ > 5)
break;
continue;
}
msleep(1);
}
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");
}
EXPORT_SYMBOL_GPL(mt76x0_mac_stop);
int mt76x0_init_hardware(struct mt76x02_dev *dev)
{
int ret, i, k;
if (!mt76x02_wait_for_wpdma(&dev->mt76, 1000))
return -EIO;
/* Wait for ASIC ready after FW load. */
if (!mt76x02_wait_for_mac(&dev->mt76))
return -ETIMEDOUT;
mt76x0_reset_csr_bbp(dev);
ret = mt76x02_mcu_function_select(dev, Q_SELECT, 1);
if (ret)
return ret;
mt76x0_init_mac_registers(dev);
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);
for (i = 0; i < 16; i++)
for (k = 0; k < 4; k++)
mt76x02_mac_shared_key_setup(dev, i, k, NULL);
for (i = 0; i < 256; i++)
mt76x02_mac_wcid_setup(dev, i, 0, NULL);
ret = mt76x0_eeprom_init(dev);
if (ret)
return ret;
mt76x0_phy_init(dev);
return 0;
}
EXPORT_SYMBOL_GPL(mt76x0_init_hardware);
static void
mt76x0_init_txpower(struct mt76x02_dev *dev,
struct ieee80211_supported_band *sband)
{
struct ieee80211_channel *chan;
struct mt76x02_rate_power t;
s8 tp;
int i;
for (i = 0; i < sband->n_channels; i++) {
chan = &sband->channels[i];
mt76x0_get_tx_power_per_rate(dev, chan, &t);
mt76x0_get_power_info(dev, chan, &tp);
chan->orig_mpwr = (mt76x02_get_max_rate_power(&t) + tp) / 2;
chan->max_power = min_t(int, chan->max_reg_power,
chan->orig_mpwr);
}
}
int mt76x0_register_device(struct mt76x02_dev *dev)
{
int ret;
ret = mt76x02_init_device(dev);
if (ret)
return ret;
mt76x02_config_mac_addr_list(dev);
ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
ARRAY_SIZE(mt76x02_rates));
if (ret)
return ret;
if (dev->mphy.cap.has_5ghz) {
struct ieee80211_supported_band *sband;
sband = &dev->mphy.sband_5g.sband;
sband->vht_cap.cap &= ~IEEE80211_VHT_CAP_RXLDPC;
mt76x0_init_txpower(dev, sband);
}
if (dev->mphy.cap.has_2ghz)
mt76x0_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt76x02_init_debugfs(dev);
return 0;
}
EXPORT_SYMBOL_GPL(mt76x0_register_device);
@@ -0,0 +1,85 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (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>
*/
#ifndef __MT76X0U_INITVALS_H
#define __MT76X0U_INITVALS_H
#include "phy.h"
static const struct mt76x0_bbp_switch_item mt76x0_bbp_switch_tab[] = {
{ 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, 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, 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, { 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, 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(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, 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, 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, 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_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, 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 | 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, 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, 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, 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, { 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 | 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, 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, 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(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 } },
};
#endif
@@ -0,0 +1,159 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (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>
*/
#ifndef __MT76X0U_INITVALS_INIT_H
#define __MT76X0U_INITVALS_INIT_H
#include "phy.h"
static const struct mt76_reg_pair common_mac_reg_table[] = {
{ 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, 0x07f40003 },
{ MT_OFDM_PROT_CFG, 0x07f42004 },
{ MT_PBF_CFG, 0x00f40006 },
{ MT_WPDMA_GLO_CFG, 0x00000030 },
{ MT_GF20_PROT_CFG, 0x01742004 },
{ MT_GF40_PROT_CFG, 0x03f42084 },
{ MT_MM20_PROT_CFG, 0x01742004 },
{ MT_MM40_PROT_CFG, 0x03f42084 },
{ MT_TXOP_CTRL_CFG, 0x0000583f },
{ MT_TX_RTS_CFG, 0x00ffff20 },
{ 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, 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 },
{ MT_PN_PAD_MODE, 0x00000003 },
{ MT_TX_PROT_CFG6, 0xe3f42004 },
{ MT_TX_PROT_CFG7, 0xe3f42084 },
{ MT_TX_PROT_CFG8, 0xe3f42104 },
{ MT_VHT_HT_FBK_CFG1, 0xedcba980 },
};
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), 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 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 },
};
#endif
@@ -0,0 +1,633 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (c) Copyright 2002-2010, Ralink Technology, Inc.
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*/
#ifndef __MT76X0U_PHY_INITVALS_H
#define __MT76X0U_PHY_INITVALS_H
static const struct mt76_reg_pair mt76x0_rf_central_tab[] = {
{ MT_RF(0, 1), 0x01 },
{ MT_RF(0, 2), 0x11 },
/* R3 ~ R7: VCO Cal */
{ MT_RF(0, 3), 0x73 }, /* VCO Freq Cal */
{ MT_RF(0, 4), 0x30 }, /* R4 b<7>=1, VCO cal */
{ MT_RF(0, 5), 0x00 },
{ MT_RF(0, 6), 0x41 },
{ MT_RF(0, 7), 0x00 },
{ MT_RF(0, 8), 0x00 },
{ MT_RF(0, 9), 0x00 },
{ MT_RF(0, 10), 0x0C },
{ MT_RF(0, 11), 0x00 },
{ MT_RF(0, 12), 0x00 },
/* BG */
{ MT_RF(0, 13), 0x00 },
{ MT_RF(0, 14), 0x00 },
{ MT_RF(0, 15), 0x00 },
/* LDO */
{ MT_RF(0, 19), 0x20 },
{ MT_RF(0, 20), 0x22 },
{ MT_RF(0, 21), 0x12 },
{ MT_RF(0, 23), 0x00 },
{ MT_RF(0, 24), 0x33 },
{ MT_RF(0, 25), 0x00 },
/* PLL */
{ MT_RF(0, 26), 0x00 },
{ MT_RF(0, 27), 0x00 },
{ MT_RF(0, 28), 0x00 },
{ MT_RF(0, 29), 0x00 },
{ MT_RF(0, 30), 0x00 },
{ MT_RF(0, 31), 0x00 },
{ MT_RF(0, 32), 0x00 },
{ MT_RF(0, 33), 0x00 },
{ MT_RF(0, 34), 0x00 },
{ MT_RF(0, 35), 0x00 },
{ MT_RF(0, 36), 0x00 },
{ MT_RF(0, 37), 0x00 },
/* LO Buffer */
{ MT_RF(0, 38), 0x2F },
/* Test Ports */
{ MT_RF(0, 64), 0x00 },
{ MT_RF(0, 65), 0x80 },
{ MT_RF(0, 66), 0x01 },
{ MT_RF(0, 67), 0x04 },
/* ADC-DAC */
{ MT_RF(0, 68), 0x00 },
{ MT_RF(0, 69), 0x08 },
{ MT_RF(0, 70), 0x08 },
{ MT_RF(0, 71), 0x40 },
{ MT_RF(0, 72), 0xD0 },
{ MT_RF(0, 73), 0x93 },
};
static const struct mt76_reg_pair mt76x0_rf_2g_channel_0_tab[] = {
/* RX logic operation */
{ MT_RF(5, 2), 0x0C }, /* 5G+2G */
{ MT_RF(5, 3), 0x00 },
/* TX logic operation */
{ MT_RF(5, 4), 0x00 },
{ MT_RF(5, 5), 0x84 },
{ MT_RF(5, 6), 0x02 },
/* LDO */
{ MT_RF(5, 7), 0x00 },
{ MT_RF(5, 8), 0x00 },
{ MT_RF(5, 9), 0x00 },
/* RX */
{ MT_RF(5, 10), 0x51 },
{ MT_RF(5, 11), 0x22 },
{ MT_RF(5, 12), 0x22 },
{ MT_RF(5, 13), 0x0F },
{ MT_RF(5, 14), 0x47 },
{ MT_RF(5, 15), 0x25 },
{ MT_RF(5, 16), 0xC7 },
{ MT_RF(5, 17), 0x00 },
{ MT_RF(5, 18), 0x00 },
{ MT_RF(5, 19), 0x30 },
{ MT_RF(5, 20), 0x33 },
{ MT_RF(5, 21), 0x02 },
{ MT_RF(5, 22), 0x32 },
{ MT_RF(5, 23), 0x00 },
{ MT_RF(5, 24), 0x25 },
{ MT_RF(5, 26), 0x00 },
{ MT_RF(5, 27), 0x12 },
{ MT_RF(5, 28), 0x0F },
{ MT_RF(5, 29), 0x00 },
/* LOGEN */
{ MT_RF(5, 30), 0x51 },
{ MT_RF(5, 31), 0x35 },
{ MT_RF(5, 32), 0x31 },
{ MT_RF(5, 33), 0x31 },
{ MT_RF(5, 34), 0x34 },
{ MT_RF(5, 35), 0x03 },
{ MT_RF(5, 36), 0x00 },
/* TX */
{ MT_RF(5, 37), 0xDD },
{ MT_RF(5, 38), 0xB3 },
{ MT_RF(5, 39), 0x33 },
{ MT_RF(5, 40), 0xB1 },
{ MT_RF(5, 41), 0x71 },
{ MT_RF(5, 42), 0xF2 },
{ MT_RF(5, 43), 0x47 },
{ MT_RF(5, 44), 0x77 },
{ MT_RF(5, 45), 0x0E },
{ MT_RF(5, 46), 0x10 },
{ MT_RF(5, 47), 0x00 },
{ MT_RF(5, 48), 0x53 },
{ MT_RF(5, 49), 0x03 },
{ MT_RF(5, 50), 0xEF },
{ MT_RF(5, 51), 0xC7 },
{ MT_RF(5, 52), 0x62 },
{ MT_RF(5, 53), 0x62 },
{ MT_RF(5, 54), 0x00 },
{ MT_RF(5, 55), 0x00 },
{ MT_RF(5, 56), 0x0F },
{ MT_RF(5, 57), 0x0F },
{ MT_RF(5, 58), 0x16 },
{ MT_RF(5, 59), 0x16 },
{ MT_RF(5, 60), 0x10 },
{ MT_RF(5, 61), 0x10 },
{ MT_RF(5, 62), 0xD0 },
{ MT_RF(5, 63), 0x6C },
{ MT_RF(5, 64), 0x58 },
{ MT_RF(5, 65), 0x58 },
{ MT_RF(5, 66), 0xF2 },
{ MT_RF(5, 67), 0xE8 },
{ MT_RF(5, 68), 0xF0 },
{ MT_RF(5, 69), 0xF0 },
{ MT_RF(5, 127), 0x04 },
};
static const struct mt76_reg_pair mt76x0_rf_5g_channel_0_tab[] = {
/* RX logic operation */
{ MT_RF(6, 2), 0x0C },
{ MT_RF(6, 3), 0x00 },
/* TX logic operation */
{ MT_RF(6, 4), 0x00 },
{ MT_RF(6, 5), 0x84 },
{ MT_RF(6, 6), 0x02 },
/* LDO */
{ MT_RF(6, 7), 0x00 },
{ MT_RF(6, 8), 0x00 },
{ MT_RF(6, 9), 0x00 },
/* RX */
{ MT_RF(6, 10), 0x00 },
{ MT_RF(6, 11), 0x01 },
{ MT_RF(6, 13), 0x23 },
{ MT_RF(6, 14), 0x00 },
{ MT_RF(6, 15), 0x04 },
{ MT_RF(6, 16), 0x22 },
{ MT_RF(6, 18), 0x08 },
{ MT_RF(6, 19), 0x00 },
{ MT_RF(6, 20), 0x00 },
{ MT_RF(6, 21), 0x00 },
{ MT_RF(6, 22), 0xFB },
/* LOGEN5G */
{ MT_RF(6, 25), 0x76 },
{ MT_RF(6, 26), 0x24 },
{ MT_RF(6, 27), 0x04 },
{ MT_RF(6, 28), 0x00 },
{ MT_RF(6, 29), 0x00 },
/* TX */
{ MT_RF(6, 37), 0xBB },
{ MT_RF(6, 38), 0xB3 },
{ MT_RF(6, 40), 0x33 },
{ MT_RF(6, 41), 0x33 },
{ MT_RF(6, 43), 0x03 },
{ MT_RF(6, 44), 0xB3 },
{ MT_RF(6, 46), 0x17 },
{ MT_RF(6, 47), 0x0E },
{ MT_RF(6, 48), 0x10 },
{ MT_RF(6, 49), 0x07 },
{ MT_RF(6, 62), 0x00 },
{ MT_RF(6, 63), 0x00 },
{ MT_RF(6, 64), 0xF1 },
{ MT_RF(6, 65), 0x0F },
};
static const struct mt76_reg_pair mt76x0_rf_vga_channel_0_tab[] = {
/* E3 CR */
{ MT_RF(7, 0), 0x47 },
{ MT_RF(7, 1), 0x00 },
{ MT_RF(7, 2), 0x00 },
{ MT_RF(7, 3), 0x00 },
{ MT_RF(7, 4), 0x00 },
{ MT_RF(7, 10), 0x13 },
{ MT_RF(7, 11), 0x0F },
{ MT_RF(7, 12), 0x13 },
{ MT_RF(7, 13), 0x13 },
{ MT_RF(7, 14), 0x13 },
{ MT_RF(7, 15), 0x20 },
{ MT_RF(7, 16), 0x22 },
{ MT_RF(7, 17), 0x7C },
{ MT_RF(7, 18), 0x00 },
{ MT_RF(7, 19), 0x00 },
{ MT_RF(7, 20), 0x00 },
{ MT_RF(7, 21), 0xF1 },
{ MT_RF(7, 22), 0x11 },
{ MT_RF(7, 23), 0xC2 },
{ MT_RF(7, 24), 0x41 },
{ MT_RF(7, 25), 0x20 },
{ MT_RF(7, 26), 0x40 },
{ MT_RF(7, 27), 0xD7 },
{ MT_RF(7, 28), 0xA2 },
{ MT_RF(7, 29), 0x60 },
{ MT_RF(7, 30), 0x49 },
{ MT_RF(7, 31), 0x20 },
{ MT_RF(7, 32), 0x44 },
{ MT_RF(7, 33), 0xC1 },
{ MT_RF(7, 34), 0x60 },
{ MT_RF(7, 35), 0xC0 },
{ MT_RF(7, 61), 0x01 },
{ MT_RF(7, 72), 0x3C },
{ MT_RF(7, 73), 0x34 },
{ MT_RF(7, 74), 0x00 },
};
static const struct mt76x0_rf_switch_item mt76x0_rf_bw_switch_tab[] = {
/* bank, reg bw/band value */
{ MT_RF(0, 17), RF_G_BAND | RF_BW_20, 0x00 },
{ MT_RF(0, 17), RF_G_BAND | RF_BW_40, 0x00 },
{ MT_RF(0, 17), RF_A_BAND | RF_BW_20, 0x00 },
{ MT_RF(0, 17), RF_A_BAND | RF_BW_40, 0x00 },
{ MT_RF(0, 17), RF_A_BAND | RF_BW_80, 0x00 },
{ MT_RF(7, 6), RF_G_BAND | RF_BW_20, 0x40 },
{ MT_RF(7, 6), RF_G_BAND | RF_BW_40, 0x1C },
{ MT_RF(7, 6), RF_A_BAND | RF_BW_20, 0x40 },
{ MT_RF(7, 6), RF_A_BAND | RF_BW_40, 0x20 },
{ MT_RF(7, 6), RF_A_BAND | RF_BW_80, 0x10 },
{ MT_RF(7, 7), RF_G_BAND | RF_BW_20, 0x40 },
{ MT_RF(7, 7), RF_G_BAND | RF_BW_40, 0x20 },
{ MT_RF(7, 7), RF_A_BAND | RF_BW_20, 0x40 },
{ MT_RF(7, 7), RF_A_BAND | RF_BW_40, 0x20 },
{ MT_RF(7, 7), RF_A_BAND | RF_BW_80, 0x10 },
{ MT_RF(7, 8), RF_G_BAND | RF_BW_20, 0x03 },
{ MT_RF(7, 8), RF_G_BAND | RF_BW_40, 0x01 },
{ MT_RF(7, 8), RF_A_BAND | RF_BW_20, 0x03 },
{ MT_RF(7, 8), RF_A_BAND | RF_BW_40, 0x01 },
{ MT_RF(7, 8), RF_A_BAND | RF_BW_80, 0x00 },
{ MT_RF(7, 58), RF_G_BAND | RF_BW_20, 0x40 },
{ MT_RF(7, 58), RF_G_BAND | RF_BW_40, 0x40 },
{ MT_RF(7, 58), RF_A_BAND | RF_BW_20, 0x40 },
{ MT_RF(7, 58), RF_A_BAND | RF_BW_40, 0x40 },
{ MT_RF(7, 58), RF_A_BAND | RF_BW_80, 0x10 },
{ MT_RF(7, 59), RF_G_BAND | RF_BW_20, 0x40 },
{ MT_RF(7, 59), RF_G_BAND | RF_BW_40, 0x40 },
{ MT_RF(7, 59), RF_A_BAND | RF_BW_20, 0x40 },
{ MT_RF(7, 59), RF_A_BAND | RF_BW_40, 0x40 },
{ MT_RF(7, 59), RF_A_BAND | RF_BW_80, 0x10 },
{ MT_RF(7, 60), RF_G_BAND | RF_BW_20, 0xAA },
{ MT_RF(7, 60), RF_G_BAND | RF_BW_40, 0xAA },
{ MT_RF(7, 60), RF_A_BAND | RF_BW_20, 0xAA },
{ MT_RF(7, 60), RF_A_BAND | RF_BW_40, 0xAA },
{ MT_RF(7, 60), RF_A_BAND | RF_BW_80, 0xAA },
{ MT_RF(7, 76), RF_BW_20, 0x40 },
{ MT_RF(7, 76), RF_BW_40, 0x40 },
{ MT_RF(7, 76), RF_BW_80, 0x10 },
{ MT_RF(7, 77), RF_BW_20, 0x40 },
{ MT_RF(7, 77), RF_BW_40, 0x40 },
{ MT_RF(7, 77), RF_BW_80, 0x10 },
};
static const struct mt76x0_rf_switch_item mt76x0_rf_band_switch_tab[] = {
/* bank, reg bw/band value */
{ MT_RF(0, 16), RF_G_BAND, 0x20 },
{ MT_RF(0, 16), RF_A_BAND, 0x20 },
{ MT_RF(0, 18), RF_G_BAND, 0x00 },
{ MT_RF(0, 18), RF_A_BAND, 0x00 },
{ MT_RF(0, 39), RF_G_BAND, 0x36 },
{ MT_RF(0, 39), RF_A_BAND_LB, 0x34 },
{ MT_RF(0, 39), RF_A_BAND_MB, 0x33 },
{ MT_RF(0, 39), RF_A_BAND_HB, 0x31 },
{ MT_RF(0, 39), RF_A_BAND_11J, 0x36 },
{ MT_RF(6, 12), RF_A_BAND_LB, 0x44 },
{ MT_RF(6, 12), RF_A_BAND_MB, 0x44 },
{ MT_RF(6, 12), RF_A_BAND_HB, 0x55 },
{ MT_RF(6, 12), RF_A_BAND_11J, 0x44 },
{ MT_RF(6, 17), RF_A_BAND_LB, 0x02 },
{ MT_RF(6, 17), RF_A_BAND_MB, 0x00 },
{ MT_RF(6, 17), RF_A_BAND_HB, 0x00 },
{ MT_RF(6, 17), RF_A_BAND_11J, 0x05 },
{ MT_RF(6, 24), RF_A_BAND_LB, 0xA1 },
{ MT_RF(6, 24), RF_A_BAND_MB, 0x41 },
{ MT_RF(6, 24), RF_A_BAND_HB, 0x21 },
{ MT_RF(6, 24), RF_A_BAND_11J, 0xE1 },
{ MT_RF(6, 39), RF_A_BAND_LB, 0x36 },
{ MT_RF(6, 39), RF_A_BAND_MB, 0x34 },
{ MT_RF(6, 39), RF_A_BAND_HB, 0x32 },
{ MT_RF(6, 39), RF_A_BAND_11J, 0x37 },
{ MT_RF(6, 42), RF_A_BAND_LB, 0xFB },
{ MT_RF(6, 42), RF_A_BAND_MB, 0xF3 },
{ MT_RF(6, 42), RF_A_BAND_HB, 0xEB },
{ MT_RF(6, 42), RF_A_BAND_11J, 0xEB },
{ MT_RF(6, 127), RF_G_BAND, 0x84 },
{ MT_RF(6, 127), RF_A_BAND, 0x04 },
{ MT_RF(7, 5), RF_G_BAND, 0x40 },
{ MT_RF(7, 5), RF_A_BAND, 0x00 },
{ MT_RF(7, 9), RF_G_BAND, 0x00 },
{ MT_RF(7, 9), RF_A_BAND, 0x00 },
{ MT_RF(7, 70), RF_G_BAND, 0x00 },
{ MT_RF(7, 70), RF_A_BAND, 0x6D },
{ MT_RF(7, 71), RF_G_BAND, 0x00 },
{ MT_RF(7, 71), RF_A_BAND, 0xB0 },
{ MT_RF(7, 78), RF_G_BAND, 0x00 },
{ MT_RF(7, 78), RF_A_BAND, 0x55 },
{ MT_RF(7, 79), RF_G_BAND, 0x00 },
{ MT_RF(7, 79), RF_A_BAND, 0x55 },
};
static const struct mt76x0_freq_item mt76x0_frequency_plan[] = {
{ 1, RF_G_BAND, 0x02, 0x3F, 0x28, 0xDD, 0xE2, 0x40, 0x02, 0x40, 0x02, 0, 0, 1, 0x28, 0, 0x30, 0, 0, 0x3 }, /* Freq 2412 */
{ 2, RF_G_BAND, 0x02, 0x3F, 0x3C, 0xDD, 0xE4, 0x40, 0x07, 0x40, 0x02, 0, 0, 1, 0xA1, 0, 0x30, 0, 0, 0x1 }, /* Freq 2417 */
{ 3, RF_G_BAND, 0x02, 0x3F, 0x3C, 0xDD, 0xE2, 0x40, 0x07, 0x40, 0x0B, 0, 0, 1, 0x50, 0, 0x30, 0, 0, 0x0 }, /* Freq 2422 */
{ 4, RF_G_BAND, 0x02, 0x3F, 0x28, 0xDD, 0xD4, 0x40, 0x02, 0x40, 0x09, 0, 0, 1, 0x50, 0, 0x30, 0, 0, 0x0 }, /* Freq 2427 */
{ 5, RF_G_BAND, 0x02, 0x3F, 0x3C, 0xDD, 0xD4, 0x40, 0x07, 0x40, 0x02, 0, 0, 1, 0xA2, 0, 0x30, 0, 0, 0x1 }, /* Freq 2432 */
{ 6, RF_G_BAND, 0x02, 0x3F, 0x3C, 0xDD, 0xD4, 0x40, 0x07, 0x40, 0x07, 0, 0, 1, 0xA2, 0, 0x30, 0, 0, 0x1 }, /* Freq 2437 */
{ 7, RF_G_BAND, 0x02, 0x3F, 0x28, 0xDD, 0xE2, 0x40, 0x02, 0x40, 0x07, 0, 0, 1, 0x28, 0, 0x30, 0, 0, 0x3 }, /* Freq 2442 */
{ 8, RF_G_BAND, 0x02, 0x3F, 0x3C, 0xDD, 0xD4, 0x40, 0x07, 0x40, 0x02, 0, 0, 1, 0xA3, 0, 0x30, 0, 0, 0x1 }, /* Freq 2447 */
{ 9, RF_G_BAND, 0x02, 0x3F, 0x3C, 0xDD, 0xF2, 0x40, 0x07, 0x40, 0x0D, 0, 0, 1, 0x28, 0, 0x30, 0, 0, 0x3 }, /* Freq 2452 */
{ 10, RF_G_BAND, 0x02, 0x3F, 0x28, 0xDD, 0xD4, 0x40, 0x02, 0x40, 0x09, 0, 0, 1, 0x51, 0, 0x30, 0, 0, 0x0 }, /* Freq 2457 */
{ 11, RF_G_BAND, 0x02, 0x3F, 0x3C, 0xDD, 0xD4, 0x40, 0x07, 0x40, 0x02, 0, 0, 1, 0xA4, 0, 0x30, 0, 0, 0x1 }, /* Freq 2462 */
{ 12, RF_G_BAND, 0x02, 0x3F, 0x3C, 0xDD, 0xD4, 0x40, 0x07, 0x40, 0x07, 0, 0, 1, 0xA4, 0, 0x30, 0, 0, 0x1 }, /* Freq 2467 */
{ 13, RF_G_BAND, 0x02, 0x3F, 0x28, 0xDD, 0xF2, 0x40, 0x02, 0x40, 0x02, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 2472 */
{ 14, RF_G_BAND, 0x02, 0x3F, 0x28, 0xDD, 0xF2, 0x40, 0x02, 0x40, 0x04, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 2484 */
{ 183, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x70, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x17, 0, 0, 1, 0x28, 0, 0x30, 0, 0, 0x3 }, /* Freq 4915 */
{ 184, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x00, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 4920 */
{ 185, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x01, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 4925 */
{ 187, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x03, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 4935 */
{ 188, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x02, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 4940 */
{ 189, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x05, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 4945 */
{ 192, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x04, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 4960 */
{ 196, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x06, 0, 0, 1, 0x29, 0, 0x30, 0, 0, 0x3 }, /* Freq 4980 */
{ 36, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x02, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5180 */
{ 37, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x05, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5185 */
{ 38, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x03, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5190 */
{ 39, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x07, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5195 */
{ 40, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x04, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5200 */
{ 41, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x09, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5205 */
{ 42, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x05, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5210 */
{ 43, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0B, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5215 */
{ 44, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x06, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5220 */
{ 45, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0D, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5225 */
{ 46, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x07, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5230 */
{ 47, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0F, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5235 */
{ 48, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x08, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5240 */
{ 49, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x11, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5245 */
{ 50, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x09, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5250 */
{ 51, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x13, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5255 */
{ 52, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x0A, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5260 */
{ 53, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x15, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5265 */
{ 54, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x0B, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5270 */
{ 55, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x70, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x17, 0, 0, 1, 0x2B, 0, 0x30, 0, 0, 0x3 }, /* Freq 5275 */
{ 56, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x00, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5280 */
{ 57, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x01, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5285 */
{ 58, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x01, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5290 */
{ 59, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x03, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5295 */
{ 60, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x02, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5300 */
{ 61, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x05, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5305 */
{ 62, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x03, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5310 */
{ 63, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x07, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5315 */
{ 64, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x04, 0, 0, 1, 0x2C, 0, 0x30, 0, 0, 0x3 }, /* Freq 5320 */
{ 100, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x0A, 0, 0, 1, 0x2D, 0, 0x30, 0, 0, 0x3 }, /* Freq 5500 */
{ 101, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x15, 0, 0, 1, 0x2D, 0, 0x30, 0, 0, 0x3 }, /* Freq 5505 */
{ 102, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x0B, 0, 0, 1, 0x2D, 0, 0x30, 0, 0, 0x3 }, /* Freq 5510 */
{ 103, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x70, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x17, 0, 0, 1, 0x2D, 0, 0x30, 0, 0, 0x3 }, /* Freq 5515 */
{ 104, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x00, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5520 */
{ 105, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x01, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5525 */
{ 106, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x01, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5530 */
{ 107, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x03, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5535 */
{ 108, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x02, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5540 */
{ 109, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x05, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5545 */
{ 110, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x03, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5550 */
{ 111, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x07, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5555 */
{ 112, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x04, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5560 */
{ 113, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x09, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5565 */
{ 114, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x05, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5570 */
{ 115, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0B, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5575 */
{ 116, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x06, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5580 */
{ 117, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0D, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5585 */
{ 118, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x07, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5590 */
{ 119, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0F, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5595 */
{ 120, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x08, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5600 */
{ 121, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x11, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5605 */
{ 122, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x09, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5610 */
{ 123, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x13, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5615 */
{ 124, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x0A, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5620 */
{ 125, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x15, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5625 */
{ 126, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x0B, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5630 */
{ 127, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x70, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x17, 0, 0, 1, 0x2E, 0, 0x30, 0, 0, 0x3 }, /* Freq 5635 */
{ 128, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x00, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5640 */
{ 129, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x01, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5645 */
{ 130, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x01, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5650 */
{ 131, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x03, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5655 */
{ 132, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x02, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5660 */
{ 133, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x05, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5665 */
{ 134, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x03, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5670 */
{ 135, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x07, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5675 */
{ 136, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x04, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5680 */
{ 137, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x09, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5685 */
{ 138, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x05, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5690 */
{ 139, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0B, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5695 */
{ 140, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x06, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5700 */
{ 141, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0D, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5705 */
{ 142, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x07, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5710 */
{ 143, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0F, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5715 */
{ 144, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x08, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5720 */
{ 145, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x11, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5725 */
{ 146, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x09, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5730 */
{ 147, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x13, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5735 */
{ 148, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x0A, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5740 */
{ 149, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x15, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5745 */
{ 150, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x0B, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5750 */
{ 151, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x70, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x17, 0, 0, 1, 0x2F, 0, 0x30, 0, 0, 0x3 }, /* Freq 5755 */
{ 152, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x00, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5760 */
{ 153, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x01, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5765 */
{ 154, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x01, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5770 */
{ 155, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x03, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5775 */
{ 156, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x02, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5780 */
{ 157, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x05, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5785 */
{ 158, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x03, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5790 */
{ 159, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x07, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5795 */
{ 160, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x04, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5800 */
{ 161, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x09, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5805 */
{ 162, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x05, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5810 */
{ 163, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0B, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5815 */
{ 164, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x06, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5820 */
{ 165, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0D, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5825 */
{ 166, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0xDD, 0xD2, 0x40, 0x04, 0x40, 0x07, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5830 */
{ 167, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x0F, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5835 */
{ 168, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x08, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5840 */
{ 169, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x11, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5845 */
{ 170, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x09, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5850 */
{ 171, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x13, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5855 */
{ 172, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x30, 0x97, 0xD2, 0x40, 0x04, 0x40, 0x0A, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5860 */
{ 173, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x68, 0xDD, 0xD2, 0x40, 0x10, 0x40, 0x15, 0, 0, 1, 0x30, 0, 0x30, 0, 0, 0x3 }, /* Freq 5865 */
};
static const struct mt76x0_freq_item mt76x0_sdm_frequency_plan[] = {
{ 1, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x0CCCC, 0x3 }, /* Freq 2412 */
{ 2, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x12222, 0x3 }, /* Freq 2417 */
{ 3, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x17777, 0x3 }, /* Freq 2422 */
{ 4, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x1CCCC, 0x3 }, /* Freq 2427 */
{ 5, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x22222, 0x3 }, /* Freq 2432 */
{ 6, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x27777, 0x3 }, /* Freq 2437 */
{ 7, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x2CCCC, 0x3 }, /* Freq 2442 */
{ 8, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x32222, 0x3 }, /* Freq 2447 */
{ 9, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x37777, 0x3 }, /* Freq 2452 */
{ 10, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x3CCCC, 0x3 }, /* Freq 2457 */
{ 11, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x02222, 0x3 }, /* Freq 2462 */
{ 12, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x07777, 0x3 }, /* Freq 2467 */
{ 13, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x0CCCC, 0x3 }, /* Freq 2472 */
{ 14, RF_G_BAND, 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x19999, 0x3 }, /* Freq 2484 */
{ 183, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x28, 0, 0x0, 0x8, 0x3D555, 0x3 }, /* Freq 4915 */
{ 184, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x00000, 0x3 }, /* Freq 4920 */
{ 185, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x02AAA, 0x3 }, /* Freq 4925 */
{ 187, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x08000, 0x3 }, /* Freq 4935 */
{ 188, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x0AAAA, 0x3 }, /* Freq 4940 */
{ 189, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x0D555, 0x3 }, /* Freq 4945 */
{ 192, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x15555, 0x3 }, /* Freq 4960 */
{ 196, (RF_A_BAND | RF_A_BAND_11J), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x29, 0, 0x0, 0x8, 0x20000, 0x3 }, /* Freq 4980 */
{ 36, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x0AAAA, 0x3 }, /* Freq 5180 */
{ 37, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x0D555, 0x3 }, /* Freq 5185 */
{ 38, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x10000, 0x3 }, /* Freq 5190 */
{ 39, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x12AAA, 0x3 }, /* Freq 5195 */
{ 40, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x15555, 0x3 }, /* Freq 5200 */
{ 41, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x18000, 0x3 }, /* Freq 5205 */
{ 42, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x1AAAA, 0x3 }, /* Freq 5210 */
{ 43, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x1D555, 0x3 }, /* Freq 5215 */
{ 44, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x20000, 0x3 }, /* Freq 5220 */
{ 45, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x22AAA, 0x3 }, /* Freq 5225 */
{ 46, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x25555, 0x3 }, /* Freq 5230 */
{ 47, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x28000, 0x3 }, /* Freq 5235 */
{ 48, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x2AAAA, 0x3 }, /* Freq 5240 */
{ 49, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x2D555, 0x3 }, /* Freq 5245 */
{ 50, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x30000, 0x3 }, /* Freq 5250 */
{ 51, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x32AAA, 0x3 }, /* Freq 5255 */
{ 52, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x35555, 0x3 }, /* Freq 5260 */
{ 53, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x38000, 0x3 }, /* Freq 5265 */
{ 54, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x3AAAA, 0x3 }, /* Freq 5270 */
{ 55, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2B, 0, 0x0, 0x8, 0x3D555, 0x3 }, /* Freq 5275 */
{ 56, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x00000, 0x3 }, /* Freq 5280 */
{ 57, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x02AAA, 0x3 }, /* Freq 5285 */
{ 58, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x05555, 0x3 }, /* Freq 5290 */
{ 59, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x08000, 0x3 }, /* Freq 5295 */
{ 60, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x0AAAA, 0x3 }, /* Freq 5300 */
{ 61, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x0D555, 0x3 }, /* Freq 5305 */
{ 62, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x10000, 0x3 }, /* Freq 5310 */
{ 63, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x12AAA, 0x3 }, /* Freq 5315 */
{ 64, (RF_A_BAND | RF_A_BAND_LB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2C, 0, 0x0, 0x8, 0x15555, 0x3 }, /* Freq 5320 */
{ 100, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2D, 0, 0x0, 0x8, 0x35555, 0x3 }, /* Freq 5500 */
{ 101, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2D, 0, 0x0, 0x8, 0x38000, 0x3 }, /* Freq 5505 */
{ 102, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2D, 0, 0x0, 0x8, 0x3AAAA, 0x3 }, /* Freq 5510 */
{ 103, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2D, 0, 0x0, 0x8, 0x3D555, 0x3 }, /* Freq 5515 */
{ 104, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x00000, 0x3 }, /* Freq 5520 */
{ 105, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x02AAA, 0x3 }, /* Freq 5525 */
{ 106, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x05555, 0x3 }, /* Freq 5530 */
{ 107, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x08000, 0x3 }, /* Freq 5535 */
{ 108, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x0AAAA, 0x3 }, /* Freq 5540 */
{ 109, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x0D555, 0x3 }, /* Freq 5545 */
{ 110, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x10000, 0x3 }, /* Freq 5550 */
{ 111, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x12AAA, 0x3 }, /* Freq 5555 */
{ 112, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x15555, 0x3 }, /* Freq 5560 */
{ 113, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x18000, 0x3 }, /* Freq 5565 */
{ 114, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x1AAAA, 0x3 }, /* Freq 5570 */
{ 115, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x1D555, 0x3 }, /* Freq 5575 */
{ 116, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x20000, 0x3 }, /* Freq 5580 */
{ 117, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x22AAA, 0x3 }, /* Freq 5585 */
{ 118, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x25555, 0x3 }, /* Freq 5590 */
{ 119, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x28000, 0x3 }, /* Freq 5595 */
{ 120, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x2AAAA, 0x3 }, /* Freq 5600 */
{ 121, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x2D555, 0x3 }, /* Freq 5605 */
{ 122, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x30000, 0x3 }, /* Freq 5610 */
{ 123, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x32AAA, 0x3 }, /* Freq 5615 */
{ 124, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x35555, 0x3 }, /* Freq 5620 */
{ 125, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x38000, 0x3 }, /* Freq 5625 */
{ 126, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x3AAAA, 0x3 }, /* Freq 5630 */
{ 127, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2E, 0, 0x0, 0x8, 0x3D555, 0x3 }, /* Freq 5635 */
{ 128, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x00000, 0x3 }, /* Freq 5640 */
{ 129, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x02AAA, 0x3 }, /* Freq 5645 */
{ 130, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x05555, 0x3 }, /* Freq 5650 */
{ 131, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x08000, 0x3 }, /* Freq 5655 */
{ 132, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x0AAAA, 0x3 }, /* Freq 5660 */
{ 133, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x0D555, 0x3 }, /* Freq 5665 */
{ 134, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x10000, 0x3 }, /* Freq 5670 */
{ 135, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x12AAA, 0x3 }, /* Freq 5675 */
{ 136, (RF_A_BAND | RF_A_BAND_MB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x15555, 0x3 }, /* Freq 5680 */
{ 137, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x18000, 0x3 }, /* Freq 5685 */
{ 138, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x1AAAA, 0x3 }, /* Freq 5690 */
{ 139, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x1D555, 0x3 }, /* Freq 5695 */
{ 140, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x20000, 0x3 }, /* Freq 5700 */
{ 141, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x22AAA, 0x3 }, /* Freq 5705 */
{ 142, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x25555, 0x3 }, /* Freq 5710 */
{ 143, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x28000, 0x3 }, /* Freq 5715 */
{ 144, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x2AAAA, 0x3 }, /* Freq 5720 */
{ 145, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x2D555, 0x3 }, /* Freq 5725 */
{ 146, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x30000, 0x3 }, /* Freq 5730 */
{ 147, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x32AAA, 0x3 }, /* Freq 5735 */
{ 148, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x35555, 0x3 }, /* Freq 5740 */
{ 149, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x38000, 0x3 }, /* Freq 5745 */
{ 150, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x3AAAA, 0x3 }, /* Freq 5750 */
{ 151, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x2F, 0, 0x0, 0x8, 0x3D555, 0x3 }, /* Freq 5755 */
{ 152, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x00000, 0x3 }, /* Freq 5760 */
{ 153, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x02AAA, 0x3 }, /* Freq 5765 */
{ 154, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x05555, 0x3 }, /* Freq 5770 */
{ 155, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x08000, 0x3 }, /* Freq 5775 */
{ 156, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x0AAAA, 0x3 }, /* Freq 5780 */
{ 157, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x0D555, 0x3 }, /* Freq 5785 */
{ 158, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x10000, 0x3 }, /* Freq 5790 */
{ 159, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x12AAA, 0x3 }, /* Freq 5795 */
{ 160, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x15555, 0x3 }, /* Freq 5800 */
{ 161, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x18000, 0x3 }, /* Freq 5805 */
{ 162, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x1AAAA, 0x3 }, /* Freq 5810 */
{ 163, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x1D555, 0x3 }, /* Freq 5815 */
{ 164, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x20000, 0x3 }, /* Freq 5820 */
{ 165, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x22AAA, 0x3 }, /* Freq 5825 */
{ 166, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x25555, 0x3 }, /* Freq 5830 */
{ 167, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x28000, 0x3 }, /* Freq 5835 */
{ 168, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x2AAAA, 0x3 }, /* Freq 5840 */
{ 169, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x2D555, 0x3 }, /* Freq 5845 */
{ 170, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x30000, 0x3 }, /* Freq 5850 */
{ 171, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x32AAA, 0x3 }, /* Freq 5855 */
{ 172, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x35555, 0x3 }, /* Freq 5860 */
{ 173, (RF_A_BAND | RF_A_BAND_HB), 0x02, 0x3F, 0x7F, 0xDD, 0xC3, 0x40, 0x0, 0x80, 0x0, 0, 0, 0, 0x30, 0, 0x0, 0x8, 0x38000, 0x3 }, /* Freq 5865 */
};
static const u8 mt76x0_sdm_channel[] = {
183, 185, 43, 45,
54, 55, 57, 58,
102, 103, 105, 106,
115, 117, 126, 127,
129, 130, 139, 141,
150, 151, 153, 154,
163, 165
};
static const struct mt76x0_rf_switch_item mt76x0_rf_ext_pa_tab[] = {
{ MT_RF(6, 45), RF_A_BAND_LB, 0x63 },
{ MT_RF(6, 45), RF_A_BAND_MB, 0x43 },
{ MT_RF(6, 45), RF_A_BAND_HB, 0x33 },
{ MT_RF(6, 45), RF_A_BAND_11J, 0x73 },
{ MT_RF(6, 50), RF_A_BAND_LB, 0x02 },
{ MT_RF(6, 50), RF_A_BAND_MB, 0x02 },
{ MT_RF(6, 50), RF_A_BAND_HB, 0x02 },
{ MT_RF(6, 50), RF_A_BAND_11J, 0x02 },
{ MT_RF(6, 51), RF_A_BAND_LB, 0x02 },
{ MT_RF(6, 51), RF_A_BAND_MB, 0x02 },
{ MT_RF(6, 51), RF_A_BAND_HB, 0x02 },
{ MT_RF(6, 51), RF_A_BAND_11J, 0x02 },
{ MT_RF(6, 52), RF_A_BAND_LB, 0x08 },
{ MT_RF(6, 52), RF_A_BAND_MB, 0x08 },
{ MT_RF(6, 52), RF_A_BAND_HB, 0x08 },
{ MT_RF(6, 52), RF_A_BAND_11J, 0x08 },
{ MT_RF(6, 53), RF_A_BAND_LB, 0x08 },
{ MT_RF(6, 53), RF_A_BAND_MB, 0x08 },
{ MT_RF(6, 53), RF_A_BAND_HB, 0x08 },
{ MT_RF(6, 53), RF_A_BAND_11J, 0x08 },
{ MT_RF(6, 54), RF_A_BAND_LB, 0x0A },
{ MT_RF(6, 54), RF_A_BAND_MB, 0x0A },
{ MT_RF(6, 54), RF_A_BAND_HB, 0x0A },
{ MT_RF(6, 54), RF_A_BAND_11J, 0x0A },
{ MT_RF(6, 55), RF_A_BAND_LB, 0x0A },
{ MT_RF(6, 55), RF_A_BAND_MB, 0x0A },
{ MT_RF(6, 55), RF_A_BAND_HB, 0x0A },
{ MT_RF(6, 55), RF_A_BAND_11J, 0x0A },
{ MT_RF(6, 56), RF_A_BAND_LB, 0x05 },
{ MT_RF(6, 56), RF_A_BAND_MB, 0x05 },
{ MT_RF(6, 56), RF_A_BAND_HB, 0x05 },
{ MT_RF(6, 56), RF_A_BAND_11J, 0x05 },
{ MT_RF(6, 57), RF_A_BAND_LB, 0x05 },
{ MT_RF(6, 57), RF_A_BAND_MB, 0x05 },
{ MT_RF(6, 57), RF_A_BAND_HB, 0x05 },
{ MT_RF(6, 57), RF_A_BAND_11J, 0x05 },
{ MT_RF(6, 58), RF_A_BAND_LB, 0x05 },
{ MT_RF(6, 58), RF_A_BAND_MB, 0x03 },
{ MT_RF(6, 58), RF_A_BAND_HB, 0x02 },
{ MT_RF(6, 58), RF_A_BAND_11J, 0x07 },
{ MT_RF(6, 59), RF_A_BAND_LB, 0x05 },
{ MT_RF(6, 59), RF_A_BAND_MB, 0x03 },
{ MT_RF(6, 59), RF_A_BAND_HB, 0x02 },
{ MT_RF(6, 59), RF_A_BAND_11J, 0x07 },
};
#endif
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*/
#include <linux/etherdevice.h>
#include "mt76x0.h"
int mt76x0_set_channel(struct mt76_phy *mphy)
{
struct mt76x02_dev *dev = container_of(mphy->dev, struct mt76x02_dev, mt76);
mt76x02_pre_tbtt_enable(dev, false);
if (mt76_is_mmio(&dev->mt76))
tasklet_disable(&dev->dfs_pd.dfs_tasklet);
mt76x0_phy_set_channel(dev, &mphy->chandef);
mt76x02_mac_cc_reset(dev);
mt76x02_edcca_init(dev);
if (mt76_is_mmio(&dev->mt76)) {
mt76x02_dfs_init_params(dev);
tasklet_enable(&dev->dfs_pd.dfs_tasklet);
}
mt76x02_pre_tbtt_enable(dev, true);
return 0;
}
EXPORT_SYMBOL_GPL(mt76x0_set_channel);
int mt76x0_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar)
{
int err = -EINVAL, power = hw->conf.power_level * 2;
struct mt76x02_dev *dev = hw->priv;
struct mt76_phy *mphy = &dev->mphy;
mutex_lock(&dev->mt76.mutex);
if (!cfg80211_chandef_valid(&mphy->chandef))
goto out;
err = mt76_init_sar_power(hw, sar);
if (err)
goto out;
dev->txpower_conf = mt76_get_sar_power(mphy, mphy->chandef.chan,
power);
if (test_bit(MT76_STATE_RUNNING, &mphy->state))
mt76x0_phy_set_txpower(dev);
out:
mutex_unlock(&dev->mt76.mutex);
return err;
}
EXPORT_SYMBOL_GPL(mt76x0_set_sar_specs);
int mt76x0_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
{
struct mt76x02_dev *dev = hw->priv;
if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
mt76_update_channel(&dev->mphy);
mutex_lock(&dev->mt76.mutex);
if (changed & IEEE80211_CONF_CHANGE_POWER) {
struct mt76_phy *mphy = &dev->mphy;
dev->txpower_conf = hw->conf.power_level * 2;
dev->txpower_conf = mt76_get_sar_power(mphy,
mphy->chandef.chan,
dev->txpower_conf);
if (test_bit(MT76_STATE_RUNNING, &mphy->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 0;
}
EXPORT_SYMBOL_GPL(mt76x0_config);
@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
*/
#ifndef __MT76X0U_MCU_H
#define __MT76X0U_MCU_H
#include "../mt76x02_mcu.h"
struct mt76x02_dev;
#define MT_MCU_IVB_SIZE 0x40
#define MT_MCU_DLM_OFFSET 0x80000
/* We use same space for BBP as for MAC regs
* #define MT_MCU_MEMMAP_BBP 0x40000000
*/
#define MT_MCU_MEMMAP_RF 0x80000000
enum mcu_calibrate {
MCU_CAL_R = 1,
MCU_CAL_RXDCOC,
MCU_CAL_LC,
MCU_CAL_LOFT,
MCU_CAL_TXIQ,
MCU_CAL_BW,
MCU_CAL_DPD,
MCU_CAL_RXIQ,
MCU_CAL_TXDCOC,
MCU_CAL_RX_GROUP_DELAY,
MCU_CAL_TX_GROUP_DELAY,
MCU_CAL_VCO,
MCU_CAL_NO_SIGNAL = 0xfe,
MCU_CAL_FULL = 0xff,
};
int mt76x0e_mcu_init(struct mt76x02_dev *dev);
int mt76x0u_mcu_init(struct mt76x02_dev *dev);
static inline int mt76x0_firmware_running(struct mt76x02_dev *dev)
{
return mt76_rr(dev, MT_MCU_COM_REG0) == 1;
}
#endif
@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*/
#ifndef MT76X0U_H
#define MT76X0U_H
#include <linux/bitfield.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/usb.h>
#include <linux/completion.h>
#include <net/mac80211.h>
#include <linux/debugfs.h>
#include "../mt76x02.h"
#include "eeprom.h"
#define MT7610E_FIRMWARE "mediatek/mt7610e.bin"
#define MT7650E_FIRMWARE "mediatek/mt7650e.bin"
#define MT7610U_FIRMWARE "mediatek/mt7610u.bin"
#define MT_USB_AGGR_SIZE_LIMIT 21 /* * 1024B */
#define MT_USB_AGGR_TIMEOUT 0x80 /* * 33ns */
static inline bool is_mt7610e(struct mt76x02_dev *dev)
{
if (!mt76_is_mmio(&dev->mt76))
return false;
return mt76_chip(&dev->mt76) == 0x7610;
}
static inline bool is_mt7630(struct mt76x02_dev *dev)
{
return mt76_chip(&dev->mt76) == 0x7630;
}
/* Init */
int mt76x0_init_hardware(struct mt76x02_dev *dev);
int mt76x0_register_device(struct mt76x02_dev *dev);
void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset);
void mt76x0_mac_stop(struct mt76x02_dev *dev);
int mt76x0_config(struct ieee80211_hw *hw, int radio_idx, u32 changed);
int mt76x0_set_channel(struct mt76_phy *mphy);
int mt76x0_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
/* PHY */
void mt76x0_phy_init(struct mt76x02_dev *dev);
int mt76x0_phy_wait_bbp_ready(struct mt76x02_dev *dev);
void mt76x0_phy_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef);
void mt76x0_phy_set_txpower(struct mt76x02_dev *dev);
void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on);
#endif
@@ -0,0 +1,327 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "mt76x0.h"
#include "mcu.h"
static int mt76x0e_start(struct ieee80211_hw *hw)
{
struct mt76x02_dev *dev = hw->priv;
mt76x02_mac_start(dev);
mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mphy.mac_work,
MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mphy.state);
return 0;
}
static void mt76x0e_stop_hw(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
clear_bit(MT76_RESTART, &dev->mphy.state);
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);
}
static void mt76x0e_stop(struct ieee80211_hw *hw, bool suspend)
{
struct mt76x02_dev *dev = hw->priv;
clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
mt76x0e_stop_hw(dev);
}
static void
mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
}
static const struct ieee80211_ops mt76x0e_ops = {
.add_chanctx = ieee80211_emulate_add_chanctx,
.remove_chanctx = ieee80211_emulate_remove_chanctx,
.change_chanctx = ieee80211_emulate_change_chanctx,
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
.tx = mt76x02_tx,
.start = mt76x0e_start,
.stop = mt76x0e_stop,
.add_interface = mt76x02_add_interface,
.remove_interface = mt76x02_remove_interface,
.config = mt76x0_config,
.configure_filter = mt76x02_configure_filter,
.bss_info_changed = mt76x02_bss_info_changed,
.sta_state = mt76_sta_state,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
.set_key = mt76x02_set_key,
.conf_tx = mt76x02_conf_tx,
.sw_scan_start = mt76_sw_scan,
.sw_scan_complete = mt76x02_sw_scan_complete,
.ampdu_action = mt76x02_ampdu_action,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.wake_tx_queue = mt76_wake_tx_queue,
.get_survey = mt76_get_survey,
.get_txpower = mt76_get_txpower,
.flush = mt76x0e_flush,
.set_tim = mt76_set_tim,
.release_buffered_frames = mt76_release_buffered_frames,
.set_coverage_class = mt76x02_set_coverage_class,
.set_rts_threshold = mt76x02_set_rts_threshold,
.get_antenna = mt76_get_antenna,
.reconfig_complete = mt76x02_reconfig_complete,
.set_sar_specs = mt76x0_set_sar_specs,
};
static int mt76x0e_init_hardware(struct mt76x02_dev *dev, bool resume)
{
int err;
mt76x0_chip_onoff(dev, true, false);
if (!mt76x02_wait_for_mac(&dev->mt76))
return -ETIMEDOUT;
mt76x02_dma_disable(dev);
err = mt76x0e_mcu_init(dev);
if (err < 0)
return err;
if (!resume) {
err = mt76x02_dma_init(dev);
if (err < 0)
return err;
}
err = mt76x0_init_hardware(dev);
if (err < 0)
return err;
mt76x02e_init_beacon_config(dev);
if (mt76_chip(&dev->mt76) == 0x7610) {
u16 val;
mt76_clear(dev, MT_COEXCFG0, BIT(0));
val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);
if (!(val & MT_EE_NIC_CONF_0_PA_IO_CURRENT))
mt76_set(dev, MT_XO_CTRL7, 0xc03);
}
mt76_clear(dev, 0x110, BIT(9));
mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));
return 0;
}
static int mt76x0e_register_device(struct mt76x02_dev *dev)
{
int err;
err = mt76x0e_init_hardware(dev, false);
if (err < 0)
return err;
err = mt76x0_register_device(dev);
if (err < 0)
return err;
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
return 0;
}
static int
mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
MT_DRV_SW_RX_AIRTIME |
MT_DRV_IGNORE_TXS_FAILED,
.survey_flags = SURVEY_INFO_TIME_TX,
.update_survey = mt76x02_update_channel,
.set_channel = mt76x0_set_channel,
.tx_prepare_skb = mt76x02_tx_prepare_skb,
.tx_complete_skb = mt76x02_tx_complete_skb,
.rx_skb = mt76x02_queue_rx_skb,
.rx_poll_complete = mt76x02_rx_poll_complete,
.sta_ps = mt76x02_sta_ps,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
};
struct mt76x02_dev *dev;
struct mt76_dev *mdev;
int ret;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
if (ret)
return ret;
pci_set_master(pdev);
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
mt76_pci_disable_aspm(pdev);
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops,
&drv_ops);
if (!mdev)
return -ENOMEM;
dev = container_of(mdev, struct mt76x02_dev, mt76);
mutex_init(&dev->phy_mutex);
mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto error;
ret = mt76x0e_register_device(dev);
if (ret < 0)
goto error;
return 0;
error:
mt76_free_device(&dev->mt76);
return ret;
}
static void mt76x0e_cleanup(struct mt76x02_dev *dev)
{
clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
mt76x0_chip_onoff(dev, false, false);
mt76x0e_stop_hw(dev);
mt76_dma_cleanup(&dev->mt76);
mt76x02_mcu_cleanup(dev);
}
static void
mt76x0e_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
mt76_unregister_device(mdev);
mt76x0e_cleanup(dev);
mt76_free_device(mdev);
}
#ifdef CONFIG_PM
static int mt76x0e_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
int i;
mt76_worker_disable(&mdev->tx_worker);
for (i = 0; i < ARRAY_SIZE(mdev->phy.q_tx); i++)
mt76_queue_tx_cleanup(dev, mdev->phy.q_tx[i], true);
for (i = 0; i < ARRAY_SIZE(mdev->q_mcu); i++)
mt76_queue_tx_cleanup(dev, mdev->q_mcu[i], true);
napi_disable(&mdev->tx_napi);
mt76_for_each_q_rx(mdev, i)
napi_disable(&mdev->napi[i]);
mt76x02_dma_disable(dev);
mt76x02_mcu_cleanup(dev);
mt76x0_chip_onoff(dev, false, false);
pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
pci_save_state(pdev);
return pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
static int mt76x0e_resume(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
int err, i;
err = pci_set_power_state(pdev, PCI_D0);
if (err)
return err;
pci_restore_state(pdev);
mt76_worker_enable(&mdev->tx_worker);
mt76_for_each_q_rx(mdev, i) {
mt76_queue_rx_reset(dev, i);
napi_enable(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
local_bh_disable();
mt76_for_each_q_rx(mdev, i) {
napi_schedule(&mdev->napi[i]);
}
napi_schedule(&mdev->tx_napi);
local_bh_enable();
return mt76x0e_init_hardware(dev, true);
}
#endif /* CONFIG_PM */
static const struct pci_device_id mt76x0e_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7610) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7630) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7650) },
{ },
};
MODULE_DEVICE_TABLE(pci, mt76x0e_device_table);
MODULE_FIRMWARE(MT7610E_FIRMWARE);
MODULE_FIRMWARE(MT7650E_FIRMWARE);
MODULE_DESCRIPTION("MediaTek MT76x0E (PCIe) wireless driver");
MODULE_LICENSE("Dual BSD/GPL");
static struct pci_driver mt76x0e_driver = {
.name = KBUILD_MODNAME,
.id_table = mt76x0e_device_table,
.probe = mt76x0e_probe,
.remove = mt76x0e_remove,
#ifdef CONFIG_PM
.suspend = mt76x0e_suspend,
.resume = mt76x0e_resume,
#endif /* CONFIG_PM */
};
module_pci_driver(mt76x0e_driver);
@@ -0,0 +1,133 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*/
#include <linux/kernel.h>
#include <linux/firmware.h>
#include "mt76x0.h"
#include "mcu.h"
#define MT_MCU_IVB_ADDR (MT_MCU_ILM_ADDR + 0x54000 - MT_MCU_IVB_SIZE)
static int mt76x0e_load_firmware(struct mt76x02_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;
}
mt76x02_set_ethtool_fwver(dev, hdr);
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 mt76x02_dev *dev)
{
static const struct mt76_mcu_ops mt76x0e_mcu_ops = {
.mcu_send_msg = mt76x02_mcu_msg_send,
.mcu_parse_response = mt76x02_mcu_parse_response,
};
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->mphy.state);
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,90 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (c) Copyright 2002-2010, Ralink Technology, Inc.
* Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
*/
#ifndef _MT76X0_PHY_H_
#define _MT76X0_PHY_H_
#define RF_G_BAND 0x0100
#define RF_A_BAND 0x0200
#define RF_A_BAND_LB 0x0400
#define RF_A_BAND_MB 0x0800
#define RF_A_BAND_HB 0x1000
#define RF_A_BAND_11J 0x2000
#define RF_BW_20 1
#define RF_BW_40 2
#define RF_BW_10 4
#define RF_BW_80 8
#define MT_RF(bank, reg) ((bank) << 16 | (reg))
#define MT_RF_BANK(offset) ((offset) >> 16)
#define MT_RF_REG(offset) ((offset) & 0xff)
#define MT_RF_VCO_BP_CLOSE_LOOP BIT(3)
#define MT_RF_VCO_BP_CLOSE_LOOP_MASK GENMASK(3, 0)
#define MT_RF_VCO_CAL_MASK GENMASK(2, 0)
#define MT_RF_START_TIME 0x3
#define MT_RF_START_TIME_MASK GENMASK(2, 0)
#define MT_RF_SETTLE_TIME_MASK GENMASK(6, 4)
#define MT_RF_PLL_DEN_MASK GENMASK(4, 0)
#define MT_RF_PLL_K_MASK GENMASK(4, 0)
#define MT_RF_SDM_RESET_MASK BIT(7)
#define MT_RF_SDM_MASH_PRBS_MASK GENMASK(6, 2)
#define MT_RF_SDM_BP_MASK BIT(1)
#define MT_RF_ISI_ISO_MASK GENMASK(7, 6)
#define MT_RF_PFD_DLY_MASK GENMASK(5, 4)
#define MT_RF_CLK_SEL_MASK GENMASK(3, 2)
#define MT_RF_XO_DIV_MASK GENMASK(1, 0)
struct mt76x0_bbp_switch_item {
u16 bw_band;
struct mt76_reg_pair reg_pair;
};
struct mt76x0_rf_switch_item {
u32 rf_bank_reg;
u16 bw_band;
u8 value;
};
struct mt76x0_freq_item {
u8 channel;
u32 band;
u8 pllR37;
u8 pllR36;
u8 pllR35;
u8 pllR34;
u8 pllR33;
u8 pllR32_b7b5;
u8 pllR32_b4b0; /* PLL_DEN (Denomina - 8) */
u8 pllR31_b7b5;
u8 pllR31_b4b0; /* PLL_K (Nominator *)*/
u8 pllR30_b7; /* sdm_reset_n */
u8 pllR30_b6b2; /* sdmmash_prbs,sin */
u8 pllR30_b1; /* sdm_bp */
u16 pll_n; /* R30<0>, R29<7:0> (hex) */
u8 pllR28_b7b6; /* isi,iso */
u8 pllR28_b5b4; /* pfd_dly */
u8 pllR28_b3b2; /* clksel option */
u32 pll_sdm_k; /* R28<1:0>, R27<7:0>, R26<7:0> (hex) SDM_k */
u8 pllR24_b1b0; /* xo_div */
};
struct mt76x0_rate_pwr_item {
s8 mcs_power;
u8 rf_pa_mode;
};
struct mt76x0_rate_pwr_tab {
struct mt76x0_rate_pwr_item cck[4];
struct mt76x0_rate_pwr_item ofdm[8];
struct mt76x0_rate_pwr_item ht[8];
struct mt76x0_rate_pwr_item vht[10];
struct mt76x0_rate_pwr_item stbc[8];
struct mt76x0_rate_pwr_item mcs32;
};
#endif /* _MT76X0_PHY_H_ */
@@ -0,0 +1,356 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "mt76x0.h"
#include "mcu.h"
#include "../mt76x02_usb.h"
static struct usb_device_id mt76x0_device_table[] = {
{ USB_DEVICE(0x148F, 0x7610) }, /* MT7610U */
{ USB_DEVICE(0x13B1, 0x003E) }, /* Linksys AE6000 */
{ USB_DEVICE(0x0E8D, 0x7610) }, /* Sabrent NTWLAC */
{ USB_DEVICE(0x7392, 0xa711) }, /* Edimax 7711mac */
{ USB_DEVICE(0x7392, 0xb711) }, /* Edimax / Elecom */
{ USB_DEVICE(0x148f, 0x761a) }, /* TP-Link TL-WDN5200 */
{ USB_DEVICE(0x148f, 0x760a) }, /* TP-Link unknown */
{ USB_DEVICE(0x0b05, 0x17d1) }, /* Asus USB-AC51 */
{ USB_DEVICE(0x0b05, 0x17db) }, /* Asus USB-AC50 */
{ USB_DEVICE(0x0df6, 0x0075) }, /* Sitecom WLA-3100 */
{ USB_DEVICE(0x2019, 0xab31) }, /* Planex GW-450D */
{ USB_DEVICE(0x2001, 0x3d02) }, /* D-LINK DWA-171 rev B1 */
{ USB_DEVICE(0x0586, 0x3425) }, /* Zyxel NWD6505 */
{ USB_DEVICE(0x07b8, 0x7610) }, /* AboCom AU7212 */
{ USB_DEVICE(0x04bb, 0x0951) }, /* I-O DATA WN-AC433UK */
{ USB_DEVICE(0x057c, 0x8502) }, /* AVM FRITZ!WLAN USB Stick AC 430 */
{ USB_DEVICE(0x293c, 0x5702) }, /* Comcast Xfinity KXW02AAA */
{ 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, 0x0123) }, /* TP-LINK T2UHP_US_v1 */
{ USB_DEVICE(0x2357, 0x010b) }, /* TP-LINK T2UHP_UN_v1 */
/* TP-LINK Archer T1U */
{ USB_DEVICE(0x2357, 0x0105), .driver_info = 1, },
/* MT7630U */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7630, 0xff, 0x2, 0xff)},
/* MT7650U */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7650, 0xff, 0x2, 0xff)},
{ 0, }
};
static void mt76x0_init_usb_dma(struct mt76x02_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);
}
static void mt76x0u_cleanup(struct mt76x02_dev *dev)
{
clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
mt76x0_chip_onoff(dev, false, false);
mt76u_queues_deinit(&dev->mt76);
}
static void mt76x0u_stop(struct ieee80211_hw *hw, bool suspend)
{
struct mt76x02_dev *dev = hw->priv;
clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
mt76u_stop_tx(&dev->mt76);
mt76x02u_exit_beacon_config(dev);
if (test_bit(MT76_REMOVED, &dev->mphy.state))
return;
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 mt76x02_dev *dev = hw->priv;
int ret;
ret = mt76x02u_mac_start(dev);
if (ret)
return ret;
mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mphy.mac_work,
MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mphy.state);
return 0;
}
static const struct ieee80211_ops mt76x0u_ops = {
.add_chanctx = ieee80211_emulate_add_chanctx,
.remove_chanctx = ieee80211_emulate_remove_chanctx,
.change_chanctx = ieee80211_emulate_change_chanctx,
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
.tx = mt76x02_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 = mt76x02_bss_info_changed,
.sta_state = mt76_sta_state,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
.set_key = mt76x02_set_key,
.conf_tx = mt76x02_conf_tx,
.sw_scan_start = mt76_sw_scan,
.sw_scan_complete = mt76x02_sw_scan_complete,
.ampdu_action = mt76x02_ampdu_action,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.set_rts_threshold = mt76x02_set_rts_threshold,
.wake_tx_queue = mt76_wake_tx_queue,
.get_txpower = mt76_get_txpower,
.get_survey = mt76_get_survey,
.set_tim = mt76_set_tim,
.release_buffered_frames = mt76_release_buffered_frames,
.get_antenna = mt76_get_antenna,
.set_sar_specs = mt76x0_set_sar_specs,
};
static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset)
{
int err;
mt76x0_chip_onoff(dev, true, reset);
if (!mt76x02_wait_for_mac(&dev->mt76))
return -ETIMEDOUT;
err = mt76x0u_mcu_init(dev);
if (err < 0)
return err;
mt76x0_init_usb_dma(dev);
err = mt76x0_init_hardware(dev);
if (err < 0)
return err;
mt76x02u_init_beacon_config(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));
return 0;
}
static int mt76x0u_register_device(struct mt76x02_dev *dev)
{
struct ieee80211_hw *hw = dev->mt76.hw;
struct mt76_usb *usb = &dev->mt76.usb;
int err;
usb->mcu.data = devm_kmalloc(dev->mt76.dev, MCU_RESP_URB_SIZE,
GFP_KERNEL);
if (!usb->mcu.data)
return -ENOMEM;
err = mt76u_alloc_queues(&dev->mt76);
if (err < 0)
goto out_err;
err = mt76x0u_init_hardware(dev, true);
if (err < 0)
goto out_err;
/* check hw sg support in order to enable AMSDU */
hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1;
err = mt76x0_register_device(dev);
if (err < 0)
goto out_err;
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
return 0;
out_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 = {
.drv_flags = MT_DRV_SW_RX_AIRTIME |
MT_DRV_IGNORE_TXS_FAILED,
.survey_flags = SURVEY_INFO_TIME_TX,
.update_survey = mt76x02_update_channel,
.set_channel = mt76x0_set_channel,
.tx_prepare_skb = mt76x02u_tx_prepare_skb,
.tx_complete_skb = mt76x02u_tx_complete_skb,
.tx_status_data = mt76x02_tx_status_data,
.rx_skb = mt76x02_queue_rx_skb,
.sta_ps = mt76x02_sta_ps,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
};
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
struct mt76x02_dev *dev;
struct mt76_dev *mdev;
u32 mac_rev;
int ret;
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops,
&drv_ops);
if (!mdev)
return -ENOMEM;
dev = container_of(mdev, struct mt76x02_dev, mt76);
mutex_init(&dev->phy_mutex);
/* Quirk for Archer T1U */
if (id->driver_info)
dev->no_2ghz = true;
usb_reset_device(usb_dev);
usb_set_intfdata(usb_intf, dev);
mt76x02u_init_mcu(mdev);
ret = mt76u_init(mdev, usb_intf);
if (ret)
goto err;
/* Disable the HW, otherwise MCU fail to initialize on hot reboot */
mt76x0_chip_onoff(dev, false, false);
if (!mt76x02_wait_for_mac(mdev)) {
ret = -ETIMEDOUT;
goto err;
}
mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
mac_rev = mt76_rr(dev, MT_MAC_CSR0);
dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n",
mdev->rev, mac_rev);
if (!is_mt76x0(dev)) {
ret = -ENODEV;
goto err;
}
/* Note: vendor driver skips this check for MT76X0U */
if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
dev_warn(mdev->dev, "Warning: eFUSE not present\n");
ret = mt76x0u_register_device(dev);
if (ret < 0)
goto err;
return 0;
err:
usb_set_intfdata(usb_intf, NULL);
mt76u_queues_deinit(&dev->mt76);
mt76_free_device(&dev->mt76);
return ret;
}
static void mt76x0_disconnect(struct usb_interface *usb_intf)
{
struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
bool initialized = test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
if (!initialized)
return;
ieee80211_unregister_hw(dev->mt76.hw);
mt76x0u_cleanup(dev);
usb_set_intfdata(usb_intf, NULL);
mt76_free_device(&dev->mt76);
}
static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
pm_message_t state)
{
struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
mt76u_stop_rx(&dev->mt76);
clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
mt76x0_chip_onoff(dev, false, false);
return 0;
}
static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
{
struct mt76x02_dev *dev = usb_get_intfdata(usb_intf);
int ret;
ret = mt76u_resume_rx(&dev->mt76);
if (ret < 0)
goto err;
ret = mt76x0u_init_hardware(dev, false);
if (ret)
goto err;
return 0;
err:
mt76x0u_cleanup(dev);
return ret;
}
MODULE_DEVICE_TABLE(usb, mt76x0_device_table);
MODULE_FIRMWARE(MT7610E_FIRMWARE);
MODULE_FIRMWARE(MT7610U_FIRMWARE);
MODULE_DESCRIPTION("MediaTek MT76x0U (USB) wireless driver");
MODULE_LICENSE("GPL");
static struct usb_driver mt76x0_driver = {
.name = KBUILD_MODNAME,
.id_table = mt76x0_device_table,
.probe = mt76x0u_probe,
.disconnect = mt76x0_disconnect,
.suspend = mt76x0_suspend,
.resume = mt76x0_resume,
.reset_resume = mt76x0_resume,
.soft_unbind = 1,
.disable_hub_initiated_lpm = 1,
};
module_usb_driver(mt76x0_driver);
@@ -0,0 +1,175 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*/
#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/module.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)
static int
mt76x0u_upload_firmware(struct mt76x02_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, 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,
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 mt76x0_get_firmware(struct mt76x02_dev *dev,
const struct firmware **fw)
{
int err;
/* try to load mt7610e fw if available
* otherwise fall back to mt7610u one
*/
err = firmware_request_nowarn(fw, MT7610E_FIRMWARE, dev->mt76.dev);
if (err) {
dev_info(dev->mt76.dev, "%s not found, switching to %s",
MT7610E_FIRMWARE, MT7610U_FIRMWARE);
return request_firmware(fw, MT7610U_FIRMWARE,
dev->mt76.dev);
}
return 0;
}
static int mt76x0u_load_firmware(struct mt76x02_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 = mt76x0_get_firmware(dev, &fw);
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);
usleep_range(5000, 6000);
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);
mt76x02_set_ethtool_fwver(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 mt76x02_dev *dev)
{
int ret;
ret = mt76x0u_load_firmware(dev);
if (ret < 0)
return ret;
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
return 0;
}