-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mt76: add driver code for MT76x2u based devices
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
Showing
12 changed files
with
1,891 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
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,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"); |
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,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 */ |
Oops, something went wrong.