287 lines · c
1// SPDX-License-Identifier: ISC2/* Copyright (C) 2019 MediaTek Inc.3 *4 * Author: Felix Fietkau <nbd@nbd.name>5 * Lorenzo Bianconi <lorenzo@kernel.org>6 * Sean Wang <sean.wang@mediatek.com>7 */8 9#include <linux/kernel.h>10#include <linux/module.h>11#include <linux/usb.h>12 13#include "mt7615.h"14#include "mac.h"15#include "mcu.h"16#include "regs.h"17 18static const struct usb_device_id mt7615_device_table[] = {19 { USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7663, 0xff, 0xff, 0xff) },20 { USB_DEVICE_AND_INTERFACE_INFO(0x043e, 0x310c, 0xff, 0xff, 0xff) },21 { },22};23 24static u32 mt7663u_rr(struct mt76_dev *dev, u32 addr)25{26 u32 ret;27 28 mutex_lock(&dev->usb.usb_ctrl_mtx);29 ret = ___mt76u_rr(dev, MT_VEND_READ_EXT,30 USB_DIR_IN | USB_TYPE_VENDOR, addr);31 mutex_unlock(&dev->usb.usb_ctrl_mtx);32 33 return ret;34}35 36static void mt7663u_wr(struct mt76_dev *dev, u32 addr, u32 val)37{38 mutex_lock(&dev->usb.usb_ctrl_mtx);39 ___mt76u_wr(dev, MT_VEND_WRITE_EXT,40 USB_DIR_OUT | USB_TYPE_VENDOR, addr, val);41 mutex_unlock(&dev->usb.usb_ctrl_mtx);42}43 44static u32 mt7663u_rmw(struct mt76_dev *dev, u32 addr,45 u32 mask, u32 val)46{47 mutex_lock(&dev->usb.usb_ctrl_mtx);48 val |= ___mt76u_rr(dev, MT_VEND_READ_EXT,49 USB_DIR_IN | USB_TYPE_VENDOR, addr) & ~mask;50 ___mt76u_wr(dev, MT_VEND_WRITE_EXT,51 USB_DIR_OUT | USB_TYPE_VENDOR, addr, val);52 mutex_unlock(&dev->usb.usb_ctrl_mtx);53 54 return val;55}56 57static void mt7663u_copy(struct mt76_dev *dev, u32 offset,58 const void *data, int len)59{60 struct mt76_usb *usb = &dev->usb;61 int ret, i = 0, batch_len;62 const u8 *val = data;63 64 len = round_up(len, 4);65 66 mutex_lock(&usb->usb_ctrl_mtx);67 while (i < len) {68 batch_len = min_t(int, usb->data_len, len - i);69 memcpy(usb->data, val + i, batch_len);70 ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,71 USB_DIR_OUT | USB_TYPE_VENDOR,72 (offset + i) >> 16, offset + i,73 usb->data, batch_len);74 if (ret < 0)75 break;76 77 i += batch_len;78 }79 mutex_unlock(&usb->usb_ctrl_mtx);80}81 82static void mt7663u_stop(struct ieee80211_hw *hw, bool suspend)83{84 struct mt7615_phy *phy = mt7615_hw_phy(hw);85 struct mt7615_dev *dev = hw->priv;86 87 clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);88 del_timer_sync(&phy->roc_timer);89 cancel_work_sync(&phy->roc_work);90 cancel_delayed_work_sync(&phy->scan_work);91 cancel_delayed_work_sync(&phy->mt76->mac_work);92 mt76u_stop_tx(&dev->mt76);93}94 95static void mt7663u_cleanup(struct mt7615_dev *dev)96{97 clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);98 mt76u_queues_deinit(&dev->mt76);99}100 101static void mt7663u_init_work(struct work_struct *work)102{103 struct mt7615_dev *dev;104 105 dev = container_of(work, struct mt7615_dev, mcu_work);106 if (mt7663u_mcu_init(dev))107 return;108 109 mt7615_init_work(dev);110}111 112static int mt7663u_probe(struct usb_interface *usb_intf,113 const struct usb_device_id *id)114{115 static const struct mt76_driver_ops drv_ops = {116 .txwi_size = MT_USB_TXD_SIZE,117 .drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ,118 .tx_prepare_skb = mt7663_usb_sdio_tx_prepare_skb,119 .tx_complete_skb = mt7663_usb_sdio_tx_complete_skb,120 .tx_status_data = mt7663_usb_sdio_tx_status_data,121 .rx_skb = mt7615_queue_rx_skb,122 .rx_check = mt7615_rx_check,123 .sta_add = mt7615_mac_sta_add,124 .sta_remove = mt7615_mac_sta_remove,125 .update_survey = mt7615_update_channel,126 .set_channel = mt7615_set_channel,127 };128 static struct mt76_bus_ops bus_ops = {129 .rr = mt7663u_rr,130 .wr = mt7663u_wr,131 .rmw = mt7663u_rmw,132 .read_copy = mt76u_read_copy,133 .write_copy = mt7663u_copy,134 .type = MT76_BUS_USB,135 };136 struct usb_device *udev = interface_to_usbdev(usb_intf);137 struct ieee80211_ops *ops;138 struct mt7615_dev *dev;139 struct mt76_dev *mdev;140 int ret;141 142 ops = devm_kmemdup(&usb_intf->dev, &mt7615_ops, sizeof(mt7615_ops),143 GFP_KERNEL);144 if (!ops)145 return -ENOMEM;146 147 ops->stop = mt7663u_stop;148 149 mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);150 if (!mdev)151 return -ENOMEM;152 153 dev = container_of(mdev, struct mt7615_dev, mt76);154 udev = usb_get_dev(udev);155 usb_reset_device(udev);156 157 usb_set_intfdata(usb_intf, dev);158 159 INIT_WORK(&dev->mcu_work, mt7663u_init_work);160 dev->reg_map = mt7663_usb_sdio_reg_map;161 dev->ops = ops;162 ret = __mt76u_init(mdev, usb_intf, &bus_ops);163 if (ret < 0)164 goto error;165 166 mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |167 (mt76_rr(dev, MT_HW_REV) & 0xff);168 dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);169 170 if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,171 FW_STATE_PWR_ON << 1, 500)) {172 ret = mt7663u_mcu_power_on(dev);173 if (ret)174 goto error;175 } else {176 set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state);177 }178 179 ret = mt76u_alloc_mcu_queue(&dev->mt76);180 if (ret)181 goto error;182 183 ret = mt76u_alloc_queues(&dev->mt76);184 if (ret)185 goto error;186 187 ret = mt7663_usb_sdio_register_device(dev);188 if (ret)189 goto error;190 191 return 0;192 193error:194 mt76u_queues_deinit(&dev->mt76);195 usb_set_intfdata(usb_intf, NULL);196 usb_put_dev(interface_to_usbdev(usb_intf));197 198 mt76_free_device(&dev->mt76);199 200 return ret;201}202 203static void mt7663u_disconnect(struct usb_interface *usb_intf)204{205 struct mt7615_dev *dev = usb_get_intfdata(usb_intf);206 207 if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))208 return;209 210 ieee80211_unregister_hw(dev->mt76.hw);211 mt7663u_cleanup(dev);212 213 usb_set_intfdata(usb_intf, NULL);214 usb_put_dev(interface_to_usbdev(usb_intf));215 216 mt76_free_device(&dev->mt76);217}218 219#ifdef CONFIG_PM220static int mt7663u_suspend(struct usb_interface *intf, pm_message_t state)221{222 struct mt7615_dev *dev = usb_get_intfdata(intf);223 224 if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&225 mt7615_firmware_offload(dev)) {226 int err;227 228 err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);229 if (err < 0)230 return err;231 }232 233 mt76u_stop_rx(&dev->mt76);234 mt76u_stop_tx(&dev->mt76);235 236 return 0;237}238 239static int mt7663u_resume(struct usb_interface *intf)240{241 struct mt7615_dev *dev = usb_get_intfdata(intf);242 int err;243 244 err = mt76u_vendor_request(&dev->mt76, MT_VEND_FEATURE_SET,245 USB_DIR_OUT | USB_TYPE_VENDOR,246 0x5, 0x0, NULL, 0);247 if (err)248 return err;249 250 err = mt76u_resume_rx(&dev->mt76);251 if (err < 0)252 return err;253 254 if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&255 mt7615_firmware_offload(dev))256 err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);257 258 return err;259}260#endif /* CONFIG_PM */261 262MODULE_DEVICE_TABLE(usb, mt7615_device_table);263MODULE_FIRMWARE(MT7663_OFFLOAD_FIRMWARE_N9);264MODULE_FIRMWARE(MT7663_OFFLOAD_ROM_PATCH);265MODULE_FIRMWARE(MT7663_FIRMWARE_N9);266MODULE_FIRMWARE(MT7663_ROM_PATCH);267 268static struct usb_driver mt7663u_driver = {269 .name = KBUILD_MODNAME,270 .id_table = mt7615_device_table,271 .probe = mt7663u_probe,272 .disconnect = mt7663u_disconnect,273#ifdef CONFIG_PM274 .suspend = mt7663u_suspend,275 .resume = mt7663u_resume,276 .reset_resume = mt7663u_resume,277#endif /* CONFIG_PM */278 .soft_unbind = 1,279 .disable_hub_initiated_lpm = 1,280};281module_usb_driver(mt7663u_driver);282 283MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");284MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");285MODULE_DESCRIPTION("MediaTek MT7663U (USB) wireless driver");286MODULE_LICENSE("Dual BSD/GPL");287