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