Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for the simplest of MediaTek Wi-Fi devices - MT7601U. It is a single stream bgn chip with no bells or whistles. This driver is partially based on Felix's mt76 but IMHO it doesn't make sense to merge the two right now because MT7601U is a design somewhere between old Ralink devices and new Mediatek chips. There wouldn't be all that much code sharing with the devices mt76 supports. Situation may obviously change when someone decides to extend m76 with support for the more recent USB dongles. The driver supports only station mode. I'm hoping to add AP support when time allows. This driver sat on GitHub for quite a while and got some testing there: http://github.com/kuba-moo/mt7601u Signed-off-by: Jakub Kicinski <kubakici@wp.pl> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
- Loading branch information
Showing
31 changed files
with
7,950 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
menuconfig WL_MEDIATEK | ||
bool "Mediatek Wireless LAN support" | ||
---help--- | ||
Enable community drivers for MediaTek WiFi devices. | ||
Those drivers make use of the Linux mac80211 stack. | ||
|
||
|
||
if WL_MEDIATEK | ||
source "drivers/net/wireless/mediatek/mt7601u/Kconfig" | ||
endif # WL_MEDIATEK |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
obj-$(CONFIG_MT7601U) += mt7601u/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
config MT7601U | ||
tristate "MediaTek MT7601U (USB) support" | ||
depends on MAC80211 | ||
depends on USB | ||
---help--- | ||
This adds support for MT7601U-based wireless USB dongles. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
ccflags-y += -D__CHECK_ENDIAN__ | ||
|
||
obj-$(CONFIG_MT7601U) += mt7601u.o | ||
|
||
mt7601u-objs = \ | ||
usb.o init.o main.o mcu.o trace.o dma.o core.o eeprom.o phy.o \ | ||
mac.o util.o debugfs.o tx.o | ||
|
||
CFLAGS_trace.o := -I$(src) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> | ||
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 | ||
* as published by the Free Software Foundation | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#include "mt7601u.h" | ||
|
||
int mt7601u_wait_asic_ready(struct mt7601u_dev *dev) | ||
{ | ||
int i = 100; | ||
u32 val; | ||
|
||
do { | ||
if (test_bit(MT7601U_STATE_REMOVED, &dev->state)) | ||
return -EIO; | ||
|
||
val = mt7601u_rr(dev, MT_MAC_CSR0); | ||
if (val && ~val) | ||
return 0; | ||
|
||
udelay(10); | ||
} while (i--); | ||
|
||
return -EIO; | ||
} | ||
|
||
bool mt76_poll(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val, | ||
int timeout) | ||
{ | ||
u32 cur; | ||
|
||
timeout /= 10; | ||
do { | ||
if (test_bit(MT7601U_STATE_REMOVED, &dev->state)) | ||
return false; | ||
|
||
cur = mt7601u_rr(dev, offset) & mask; | ||
if (cur == val) | ||
return true; | ||
|
||
udelay(10); | ||
} while (timeout-- > 0); | ||
|
||
dev_err(dev->dev, "Error: Time out with reg %08x\n", offset); | ||
|
||
return false; | ||
} | ||
|
||
bool mt76_poll_msec(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val, | ||
int timeout) | ||
{ | ||
u32 cur; | ||
|
||
timeout /= 10; | ||
do { | ||
if (test_bit(MT7601U_STATE_REMOVED, &dev->state)) | ||
return false; | ||
|
||
cur = mt7601u_rr(dev, offset) & mask; | ||
if (cur == val) | ||
return true; | ||
|
||
msleep(10); | ||
} while (timeout-- > 0); | ||
|
||
dev_err(dev->dev, "Error: Time out with reg %08x\n", offset); | ||
|
||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/* | ||
* Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> | ||
* Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 | ||
* as published by the Free Software Foundation | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#include <linux/debugfs.h> | ||
|
||
#include "mt7601u.h" | ||
#include "eeprom.h" | ||
|
||
static int | ||
mt76_reg_set(void *data, u64 val) | ||
{ | ||
struct mt7601u_dev *dev = data; | ||
|
||
mt76_wr(dev, dev->debugfs_reg, val); | ||
return 0; | ||
} | ||
|
||
static int | ||
mt76_reg_get(void *data, u64 *val) | ||
{ | ||
struct mt7601u_dev *dev = data; | ||
|
||
*val = mt76_rr(dev, dev->debugfs_reg); | ||
return 0; | ||
} | ||
|
||
DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n"); | ||
|
||
static int | ||
mt7601u_ampdu_stat_read(struct seq_file *file, void *data) | ||
{ | ||
struct mt7601u_dev *dev = file->private; | ||
int i, j; | ||
|
||
#define stat_printf(grp, off, name) \ | ||
seq_printf(file, #name ":\t%llu\n", dev->stats.grp[off]) | ||
|
||
stat_printf(rx_stat, 0, rx_crc_err); | ||
stat_printf(rx_stat, 1, rx_phy_err); | ||
stat_printf(rx_stat, 2, rx_false_cca); | ||
stat_printf(rx_stat, 3, rx_plcp_err); | ||
stat_printf(rx_stat, 4, rx_fifo_overflow); | ||
stat_printf(rx_stat, 5, rx_duplicate); | ||
|
||
stat_printf(tx_stat, 0, tx_fail_cnt); | ||
stat_printf(tx_stat, 1, tx_bcn_cnt); | ||
stat_printf(tx_stat, 2, tx_success); | ||
stat_printf(tx_stat, 3, tx_retransmit); | ||
stat_printf(tx_stat, 4, tx_zero_len); | ||
stat_printf(tx_stat, 5, tx_underflow); | ||
|
||
stat_printf(aggr_stat, 0, non_aggr_tx); | ||
stat_printf(aggr_stat, 1, aggr_tx); | ||
|
||
stat_printf(zero_len_del, 0, tx_zero_len_del); | ||
stat_printf(zero_len_del, 1, rx_zero_len_del); | ||
#undef stat_printf | ||
|
||
seq_puts(file, "Aggregations stats:\n"); | ||
for (i = 0; i < 4; i++) { | ||
for (j = 0; j < 8; j++) | ||
seq_printf(file, "%08llx ", | ||
dev->stats.aggr_n[i * 8 + j]); | ||
seq_putc(file, '\n'); | ||
} | ||
|
||
seq_printf(file, "recent average AMPDU len: %d\n", | ||
atomic_read(&dev->avg_ampdu_len)); | ||
|
||
return 0; | ||
} | ||
|
||
static int | ||
mt7601u_ampdu_stat_open(struct inode *inode, struct file *f) | ||
{ | ||
return single_open(f, mt7601u_ampdu_stat_read, inode->i_private); | ||
} | ||
|
||
static const struct file_operations fops_ampdu_stat = { | ||
.open = mt7601u_ampdu_stat_open, | ||
.read = seq_read, | ||
.llseek = seq_lseek, | ||
.release = single_release, | ||
}; | ||
|
||
static int | ||
mt7601u_eeprom_param_read(struct seq_file *file, void *data) | ||
{ | ||
struct mt7601u_dev *dev = file->private; | ||
struct mt7601u_rate_power *rp = &dev->ee->power_rate_table; | ||
struct tssi_data *td = &dev->ee->tssi_data; | ||
int i; | ||
|
||
seq_printf(file, "RF freq offset: %hhx\n", dev->ee->rf_freq_off); | ||
seq_printf(file, "RSSI offset: %hhx %hhx\n", | ||
dev->ee->rssi_offset[0], dev->ee->rssi_offset[1]); | ||
seq_printf(file, "Reference temp: %hhx\n", dev->ee->ref_temp); | ||
seq_printf(file, "LNA gain: %hhx\n", dev->ee->lna_gain); | ||
seq_printf(file, "Reg channels: %hhu-%hhu\n", dev->ee->reg.start, | ||
dev->ee->reg.start + dev->ee->reg.num - 1); | ||
|
||
seq_puts(file, "Per rate power:\n"); | ||
for (i = 0; i < 2; i++) | ||
seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n", | ||
rp->cck[i].raw, rp->cck[i].bw20, rp->cck[i].bw40); | ||
for (i = 0; i < 4; i++) | ||
seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n", | ||
rp->ofdm[i].raw, rp->ofdm[i].bw20, rp->ofdm[i].bw40); | ||
for (i = 0; i < 4; i++) | ||
seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n", | ||
rp->ht[i].raw, rp->ht[i].bw20, rp->ht[i].bw40); | ||
|
||
seq_puts(file, "Per channel power:\n"); | ||
for (i = 0; i < 7; i++) | ||
seq_printf(file, "\t tx_power ch%u:%02hhx ch%u:%02hhx\n", | ||
i * 2 + 1, dev->ee->chan_pwr[i * 2], | ||
i * 2 + 2, dev->ee->chan_pwr[i * 2 + 1]); | ||
|
||
if (!dev->ee->tssi_enabled) | ||
return 0; | ||
|
||
seq_puts(file, "TSSI:\n"); | ||
seq_printf(file, "\t slope:%02hhx\n", td->slope); | ||
seq_printf(file, "\t offset=%02hhx %02hhx %02hhx\n", | ||
td->offset[0], td->offset[1], td->offset[2]); | ||
seq_printf(file, "\t delta_off:%08x\n", td->tx0_delta_offset); | ||
|
||
return 0; | ||
} | ||
|
||
static int | ||
mt7601u_eeprom_param_open(struct inode *inode, struct file *f) | ||
{ | ||
return single_open(f, mt7601u_eeprom_param_read, inode->i_private); | ||
} | ||
|
||
static const struct file_operations fops_eeprom_param = { | ||
.open = mt7601u_eeprom_param_open, | ||
.read = seq_read, | ||
.llseek = seq_lseek, | ||
.release = single_release, | ||
}; | ||
|
||
void mt7601u_init_debugfs(struct mt7601u_dev *dev) | ||
{ | ||
struct dentry *dir; | ||
|
||
dir = debugfs_create_dir("mt7601u", dev->hw->wiphy->debugfsdir); | ||
if (!dir) | ||
return; | ||
|
||
debugfs_create_u8("temperature", S_IRUSR, dir, &dev->raw_temp); | ||
debugfs_create_u32("temp_mode", S_IRUSR, dir, &dev->temp_mode); | ||
|
||
debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg); | ||
debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev, | ||
&fops_regval); | ||
debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat); | ||
debugfs_create_file("eeprom_param", S_IRUSR, dir, dev, | ||
&fops_eeprom_param); | ||
} |
Oops, something went wrong.