Skip to content

Commit

Permalink
mt76: add driver code for MT76x2u based devices
Browse files Browse the repository at this point in the history
MT76x2u is a 2x2 USB 802.11ac chipset by MediaTek. This driver currently
support station mode

Tested-by: <cug_yangyuancong@hotmail.com>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  • Loading branch information
Lorenzo Bianconi authored and Kalle Valo committed Aug 2, 2018
1 parent b40b15e commit ee676cd
Show file tree
Hide file tree
Showing 12 changed files with 1,891 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/net/wireless/mediatek/mt76/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ config MT76x2E
depends on PCI
---help---
This adds support for MT7612/MT7602/MT7662-based wireless PCIe devices.

config MT76x2U
tristate "MediaTek MT76x2U (USB) support"
select MT76_CORE
select MT76_USB
select MT76x2_COMMON
depends on MAC80211
depends on USB
help
This adds support for MT7612U-based wireless USB dongles.
5 changes: 5 additions & 0 deletions drivers/net/wireless/mediatek/mt76/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ obj-$(CONFIG_MT76_CORE) += mt76.o
obj-$(CONFIG_MT76_USB) += mt76-usb.o
obj-$(CONFIG_MT76x2_COMMON) += mt76x2-common.o
obj-$(CONFIG_MT76x2E) += mt76x2e.o
obj-$(CONFIG_MT76x2U) += mt76x2u.o

mt76-y := \
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o
Expand All @@ -22,4 +23,8 @@ mt76x2e-y := \
mt76x2_core.o mt76x2_mac.o mt76x2_mcu.o mt76x2_phy.o \
mt76x2_dfs.o mt76x2_trace.o

mt76x2u-y := \
mt76x2_usb.o mt76x2u_init.o mt76x2u_main.o mt76x2u_mac.o \
mt76x2u_mcu.o mt76x2u_phy.o mt76x2u_core.o

CFLAGS_mt76x2_trace.o := -I$(src)
4 changes: 4 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt76x2.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
#define MT7662_ROM_PATCH "mt7662_rom_patch.bin"
#define MT7662_EEPROM_SIZE 512

#define MT7662U_FIRMWARE "mediatek/mt7662u.bin"
#define MT7662U_ROM_PATCH "mediatek/mt7662u_rom_patch.bin"

#define MT76x2_RX_RING_SIZE 256
#define MT_RX_HEADROOM 32

Expand All @@ -55,6 +58,7 @@ struct mt76x2_mcu {

wait_queue_head_t wait;
struct sk_buff_head res_q;
struct mt76u_buf res_u;

u32 msg_seq;
};
Expand Down
30 changes: 30 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt76x2_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@

#define MT_XO_CTRL7 0x011c

#define MT_USB_U3DMA_CFG 0x9018
#define MT_USB_DMA_CFG_RX_BULK_AGG_TOUT GENMASK(7, 0)
#define MT_USB_DMA_CFG_RX_BULK_AGG_LMT GENMASK(15, 8)
#define MT_USB_DMA_CFG_UDMA_TX_WL_DROP BIT(16)
#define MT_USB_DMA_CFG_WAKE_UP_EN BIT(17)
#define MT_USB_DMA_CFG_RX_DROP_OR_PAD BIT(18)
#define MT_USB_DMA_CFG_TX_CLR BIT(19)
#define MT_USB_DMA_CFG_TXOP_HALT BIT(20)
#define MT_USB_DMA_CFG_RX_BULK_AGG_EN BIT(21)
#define MT_USB_DMA_CFG_RX_BULK_EN BIT(22)
#define MT_USB_DMA_CFG_TX_BULK_EN BIT(23)
#define MT_USB_DMA_CFG_EP_OUT_VALID GENMASK(29, 24)
#define MT_USB_DMA_CFG_RX_BUSY BIT(30)
#define MT_USB_DMA_CFG_TX_BUSY BIT(31)

#define MT_WLAN_MTC_CTRL 0x10148
#define MT_WLAN_MTC_CTRL_MTCMOS_PWR_UP BIT(0)
#define MT_WLAN_MTC_CTRL_PWR_ACK BIT(12)
Expand Down Expand Up @@ -150,6 +165,9 @@
#define MT_TX_HW_QUEUE_MCU 8
#define MT_TX_HW_QUEUE_MGMT 9

#define MT_US_CYC_CFG 0x02a4
#define MT_US_CYC_CNT GENMASK(7, 0)

#define MT_PBF_SYS_CTRL 0x0400
#define MT_PBF_SYS_CTRL_MCU_RESET BIT(0)
#define MT_PBF_SYS_CTRL_DMA_RESET BIT(1)
Expand Down Expand Up @@ -202,6 +220,11 @@

#define MT_FCE_WLAN_FLOW_CONTROL1 0x0824

#define MT_TX_CPU_FROM_FCE_BASE_PTR 0x09a0
#define MT_TX_CPU_FROM_FCE_MAX_COUNT 0x09a4
#define MT_FCE_PDMA_GLOBAL_CONF 0x09c4
#define MT_FCE_SKIP_FS 0x0a6c

#define MT_PAUSE_ENABLE_CONTROL1 0x0a38

#define MT_MAC_CSR0 0x1000
Expand All @@ -214,6 +237,7 @@

#define MT_MAC_ADDR_DW0 0x1008
#define MT_MAC_ADDR_DW1 0x100c
#define MT_MAC_ADDR_DW1_U2ME_MASK GENMASK(23, 16)

#define MT_MAC_BSSID_DW0 0x1010
#define MT_MAC_BSSID_DW1 0x1014
Expand Down Expand Up @@ -351,6 +375,7 @@
#define MT_TX_TIMEOUT_CFG_ACKTO GENMASK(15, 8)

#define MT_TX_RETRY_CFG 0x134c
#define MT_TX_LINK_CFG 0x1350
#define MT_VHT_HT_FBK_CFG1 0x1358

#define MT_PROT_CFG_RATE GENMASK(15, 0)
Expand Down Expand Up @@ -425,6 +450,7 @@
#define MT_RX_FILTR_CFG_BAR BIT(15)
#define MT_RX_FILTR_CFG_CTRL_RSV BIT(16)

#define MT_AUTO_RSP_CFG 0x1404
#define MT_LEGACY_BASIC_RATE 0x1408
#define MT_HT_BASIC_RATE 0x140c

Expand Down Expand Up @@ -460,6 +486,10 @@
#define MT_RX_STAT_2_DUP_ERRORS GENMASK(15, 0)
#define MT_RX_STAT_2_OVERFLOW_ERRORS GENMASK(31, 16)

#define MT_TX_STA_0 0x170c
#define MT_TX_STA_1 0x1710
#define MT_TX_STA_2 0x1714

#define MT_TX_STAT_FIFO 0x1718
#define MT_TX_STAT_FIFO_VALID BIT(0)
#define MT_TX_STAT_FIFO_SUCCESS BIT(5)
Expand Down
142 changes: 142 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt76x2_usb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include <linux/kernel.h>
#include <linux/module.h>

#include "mt76x2u.h"

static const struct usb_device_id mt76x2u_device_table[] = {
{ USB_DEVICE(0x0b05, 0x1833) }, /* Asus USB-AC54 */
{ USB_DEVICE(0x0b05, 0x17eb) }, /* Asus USB-AC55 */
{ USB_DEVICE(0x0b05, 0x180b) }, /* Asus USB-N53 B1 */
{ USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USB-AC1200 */
{ USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */
{ USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */
{ USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */
{ USB_DEVICE(0x045e, 0x02e6) }, /* XBox One Wireless Adapter */
{ },
};

static int mt76x2u_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct mt76x2_dev *dev;
int err;

dev = mt76x2u_alloc_device(&intf->dev);
if (!dev)
return -ENOMEM;

udev = usb_get_dev(udev);
usb_reset_device(udev);

err = mt76u_init(&dev->mt76, intf);
if (err < 0)
goto err;

dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev);

err = mt76x2u_register_device(dev);
if (err < 0)
goto err;

return 0;

err:
ieee80211_free_hw(mt76_hw(dev));
usb_set_intfdata(intf, NULL);
usb_put_dev(udev);

return err;
}

static void mt76x2u_disconnect(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct mt76x2_dev *dev = usb_get_intfdata(intf);
struct ieee80211_hw *hw = mt76_hw(dev);

set_bit(MT76_REMOVED, &dev->mt76.state);
ieee80211_unregister_hw(hw);
mt76x2u_cleanup(dev);

ieee80211_free_hw(hw);
usb_set_intfdata(intf, NULL);
usb_put_dev(udev);
}

static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf,
pm_message_t state)
{
struct mt76x2_dev *dev = usb_get_intfdata(intf);
struct mt76_usb *usb = &dev->mt76.usb;

mt76u_stop_queues(&dev->mt76);
mt76x2u_stop_hw(dev);
usb_kill_urb(usb->mcu.res.urb);

return 0;
}

static int __maybe_unused mt76x2u_resume(struct usb_interface *intf)
{
struct mt76x2_dev *dev = usb_get_intfdata(intf);
struct mt76_usb *usb = &dev->mt76.usb;
int err;

reinit_completion(&usb->mcu.cmpl);
err = mt76u_submit_buf(&dev->mt76, USB_DIR_IN,
MT_EP_IN_CMD_RESP,
&usb->mcu.res, GFP_KERNEL,
mt76u_mcu_complete_urb,
&usb->mcu.cmpl);
if (err < 0)
return err;

err = mt76u_submit_rx_buffers(&dev->mt76);
if (err < 0)
return err;

tasklet_enable(&usb->rx_tasklet);
tasklet_enable(&usb->tx_tasklet);

return mt76x2u_init_hardware(dev);
}

MODULE_DEVICE_TABLE(usb, mt76x2u_device_table);
MODULE_FIRMWARE(MT7662U_FIRMWARE);
MODULE_FIRMWARE(MT7662U_ROM_PATCH);

static struct usb_driver mt76x2u_driver = {
.name = KBUILD_MODNAME,
.id_table = mt76x2u_device_table,
.probe = mt76x2u_probe,
.disconnect = mt76x2u_disconnect,
#ifdef CONFIG_PM
.suspend = mt76x2u_suspend,
.resume = mt76x2u_resume,
.reset_resume = mt76x2u_resume,
#endif /* CONFIG_PM */
.soft_unbind = 1,
.disable_hub_initiated_lpm = 1,
};
module_usb_driver(mt76x2u_driver);

MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
MODULE_LICENSE("Dual BSD/GPL");
83 changes: 83 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt76x2u.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef __MT76x2U_H
#define __MT76x2U_H

#include <linux/device.h>

#include "mt76x2.h"
#include "mt76x2_dma.h"
#include "mt76x2_mcu.h"

#define MT7612U_EEPROM_SIZE 512

#define MT_USB_AGGR_SIZE_LIMIT 21 /* 1024B unit */
#define MT_USB_AGGR_TIMEOUT 0x80 /* 33ns unit */

extern const struct ieee80211_ops mt76x2u_ops;

struct mt76x2_dev *mt76x2u_alloc_device(struct device *pdev);
int mt76x2u_register_device(struct mt76x2_dev *dev);
int mt76x2u_init_hardware(struct mt76x2_dev *dev);
void mt76x2u_cleanup(struct mt76x2_dev *dev);
void mt76x2u_stop_hw(struct mt76x2_dev *dev);

void mt76x2u_mac_setaddr(struct mt76x2_dev *dev, u8 *addr);
int mt76x2u_mac_reset(struct mt76x2_dev *dev);
void mt76x2u_mac_resume(struct mt76x2_dev *dev);
int mt76x2u_mac_start(struct mt76x2_dev *dev);
int mt76x2u_mac_stop(struct mt76x2_dev *dev);

int mt76x2u_phy_set_channel(struct mt76x2_dev *dev,
struct cfg80211_chan_def *chandef);
void mt76x2u_phy_calibrate(struct work_struct *work);
void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev);
void mt76x2u_phy_set_txdac(struct mt76x2_dev *dev);
void mt76x2u_phy_set_rxpath(struct mt76x2_dev *dev);

void mt76x2u_mcu_complete_urb(struct urb *urb);
int mt76x2u_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw,
u8 bw_index, bool scan);
int mt76x2u_mcu_calibrate(struct mt76x2_dev *dev, enum mcu_calibration type,
u32 val);
int mt76x2u_mcu_tssi_comp(struct mt76x2_dev *dev,
struct mt76x2_tssi_comp *tssi_data);
int mt76x2u_mcu_init_gain(struct mt76x2_dev *dev, u8 channel, u32 gain,
bool force);
int mt76x2u_mcu_set_dynamic_vga(struct mt76x2_dev *dev, u8 channel, bool ap,
bool ext, int rssi, u32 false_cca);
int mt76x2u_mcu_set_radio_state(struct mt76x2_dev *dev, bool val);
int mt76x2u_mcu_load_cr(struct mt76x2_dev *dev, u8 type,
u8 temp_level, u8 channel);
int mt76x2u_mcu_init(struct mt76x2_dev *dev);
int mt76x2u_mcu_fw_init(struct mt76x2_dev *dev);
void mt76x2u_mcu_deinit(struct mt76x2_dev *dev);

int mt76x2u_alloc_queues(struct mt76x2_dev *dev);
void mt76x2u_queues_deinit(struct mt76x2_dev *dev);
void mt76x2u_stop_queues(struct mt76x2_dev *dev);
bool mt76x2u_tx_status_data(struct mt76_dev *mdev, u8 *update);
int mt76x2u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
struct sk_buff *skb, struct mt76_queue *q,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
u32 *tx_info);
void mt76x2u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
struct mt76_queue_entry *e, bool flush);
int mt76x2u_skb_dma_info(struct sk_buff *skb, enum dma_msg_port port,
u32 flags);

#endif /* __MT76x2U_H */
Loading

0 comments on commit ee676cd

Please sign in to comment.