1eb99cc95SLorenzo Bianconi // SPDX-License-Identifier: ISC 2eb99cc95SLorenzo Bianconi /* Copyright (C) 2019 MediaTek Inc. 3eb99cc95SLorenzo Bianconi * 4eb99cc95SLorenzo Bianconi * Author: Felix Fietkau <nbd@nbd.name> 5eb99cc95SLorenzo Bianconi * Lorenzo Bianconi <lorenzo@kernel.org> 6eb99cc95SLorenzo Bianconi * Sean Wang <sean.wang@mediatek.com> 7eb99cc95SLorenzo Bianconi */ 8eb99cc95SLorenzo Bianconi 9eb99cc95SLorenzo Bianconi #include <linux/kernel.h> 10eb99cc95SLorenzo Bianconi #include <linux/module.h> 11eb99cc95SLorenzo Bianconi #include <linux/usb.h> 12eb99cc95SLorenzo Bianconi 13eb99cc95SLorenzo Bianconi #include "mt7615.h" 14eb99cc95SLorenzo Bianconi #include "mac.h" 15eb99cc95SLorenzo Bianconi #include "mcu.h" 16eb99cc95SLorenzo Bianconi #include "regs.h" 17eb99cc95SLorenzo Bianconi 18eb99cc95SLorenzo Bianconi static const u32 mt7663u_reg_map[] = { 19eb99cc95SLorenzo Bianconi [MT_TOP_CFG_BASE] = 0x80020000, 20eb99cc95SLorenzo Bianconi [MT_HW_BASE] = 0x80000000, 21eb99cc95SLorenzo Bianconi [MT_DMA_SHDL_BASE] = 0x5000a000, 22eb99cc95SLorenzo Bianconi [MT_HIF_BASE] = 0x50000000, 23eb99cc95SLorenzo Bianconi [MT_CSR_BASE] = 0x40000000, 24eb99cc95SLorenzo Bianconi [MT_EFUSE_ADDR_BASE] = 0x78011000, 25eb99cc95SLorenzo Bianconi [MT_TOP_MISC_BASE] = 0x81020000, 26eb99cc95SLorenzo Bianconi [MT_PHY_BASE] = 0x82070000, 27eb99cc95SLorenzo Bianconi [MT_WTBL_BASE_ADDR] = 0x820e0000, 28eb99cc95SLorenzo Bianconi [MT_CFG_BASE] = 0x820f0000, 29eb99cc95SLorenzo Bianconi [MT_AGG_BASE] = 0x820f2000, 30eb99cc95SLorenzo Bianconi [MT_ARB_BASE] = 0x820f3000, 31eb99cc95SLorenzo Bianconi [MT_TMAC_BASE] = 0x820f4000, 32eb99cc95SLorenzo Bianconi [MT_RMAC_BASE] = 0x820f5000, 33eb99cc95SLorenzo Bianconi [MT_DMA_BASE] = 0x820f7000, 34dd89a013SLorenzo Bianconi [MT_PF_BASE] = 0x820f8000, 35eb99cc95SLorenzo Bianconi [MT_WTBL_BASE_ON] = 0x820f9000, 36eb99cc95SLorenzo Bianconi [MT_WTBL_BASE_OFF] = 0x820f9800, 37eb99cc95SLorenzo Bianconi [MT_LPON_BASE] = 0x820fb000, 38eb99cc95SLorenzo Bianconi [MT_MIB_BASE] = 0x820fd000, 39eb99cc95SLorenzo Bianconi }; 40eb99cc95SLorenzo Bianconi 41eb99cc95SLorenzo Bianconi static const struct usb_device_id mt7615_device_table[] = { 42eb99cc95SLorenzo Bianconi { USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7663, 0xff, 0xff, 0xff) }, 43eb99cc95SLorenzo Bianconi { }, 44eb99cc95SLorenzo Bianconi }; 45eb99cc95SLorenzo Bianconi 46eb99cc95SLorenzo Bianconi static void mt7663u_stop(struct ieee80211_hw *hw) 47eb99cc95SLorenzo Bianconi { 48eb99cc95SLorenzo Bianconi struct mt7615_phy *phy = mt7615_hw_phy(hw); 49eb99cc95SLorenzo Bianconi struct mt7615_dev *dev = hw->priv; 50eb99cc95SLorenzo Bianconi 51eb99cc95SLorenzo Bianconi clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); 52eb99cc95SLorenzo Bianconi cancel_delayed_work_sync(&phy->scan_work); 53eb99cc95SLorenzo Bianconi cancel_delayed_work_sync(&phy->mac_work); 54eb99cc95SLorenzo Bianconi mt76u_stop_tx(&dev->mt76); 55eb99cc95SLorenzo Bianconi } 56eb99cc95SLorenzo Bianconi 57eb99cc95SLorenzo Bianconi static void mt7663u_cleanup(struct mt7615_dev *dev) 58eb99cc95SLorenzo Bianconi { 59eb99cc95SLorenzo Bianconi clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); 60eb99cc95SLorenzo Bianconi mt76u_queues_deinit(&dev->mt76); 61eb99cc95SLorenzo Bianconi } 62eb99cc95SLorenzo Bianconi 63eb99cc95SLorenzo Bianconi static void 64eb99cc95SLorenzo Bianconi mt7663u_mac_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid, 65eb99cc95SLorenzo Bianconi enum mt76_txq_id qid, struct ieee80211_sta *sta, 66eb99cc95SLorenzo Bianconi struct sk_buff *skb) 67eb99cc95SLorenzo Bianconi { 68eb99cc95SLorenzo Bianconi struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 69eb99cc95SLorenzo Bianconi __le32 *txwi; 70eb99cc95SLorenzo Bianconi int pid; 71eb99cc95SLorenzo Bianconi 72eb99cc95SLorenzo Bianconi if (!wcid) 73eb99cc95SLorenzo Bianconi wcid = &dev->mt76.global_wcid; 74eb99cc95SLorenzo Bianconi 75eb99cc95SLorenzo Bianconi pid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); 76eb99cc95SLorenzo Bianconi 77eb99cc95SLorenzo Bianconi txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE); 78eb99cc95SLorenzo Bianconi memset(txwi, 0, MT_USB_TXD_SIZE); 79eb99cc95SLorenzo Bianconi mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, 80eb99cc95SLorenzo Bianconi pid, info->control.hw_key, false); 81eb99cc95SLorenzo Bianconi skb_push(skb, MT_USB_TXD_SIZE); 82eb99cc95SLorenzo Bianconi } 83eb99cc95SLorenzo Bianconi 84eb99cc95SLorenzo Bianconi static int 85eb99cc95SLorenzo Bianconi __mt7663u_mac_set_rates(struct mt7615_dev *dev, 86eb99cc95SLorenzo Bianconi struct mt7615_wtbl_desc *wd) 87eb99cc95SLorenzo Bianconi { 88eb99cc95SLorenzo Bianconi struct mt7615_rate_desc *rate = &wd->rate; 89eb99cc95SLorenzo Bianconi struct mt7615_sta *sta = wd->sta; 90eb99cc95SLorenzo Bianconi u32 w5, w27, addr, val; 91eb99cc95SLorenzo Bianconi 92eb99cc95SLorenzo Bianconi lockdep_assert_held(&dev->mt76.mutex); 93eb99cc95SLorenzo Bianconi 94eb99cc95SLorenzo Bianconi if (!sta) 95eb99cc95SLorenzo Bianconi return -EINVAL; 96eb99cc95SLorenzo Bianconi 97eb99cc95SLorenzo Bianconi if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) 98eb99cc95SLorenzo Bianconi return -ETIMEDOUT; 99eb99cc95SLorenzo Bianconi 100eb99cc95SLorenzo Bianconi addr = mt7615_mac_wtbl_addr(dev, sta->wcid.idx); 101eb99cc95SLorenzo Bianconi 102eb99cc95SLorenzo Bianconi w27 = mt76_rr(dev, addr + 27 * 4); 103eb99cc95SLorenzo Bianconi w27 &= ~MT_WTBL_W27_CC_BW_SEL; 104eb99cc95SLorenzo Bianconi w27 |= FIELD_PREP(MT_WTBL_W27_CC_BW_SEL, rate->bw); 105eb99cc95SLorenzo Bianconi 106eb99cc95SLorenzo Bianconi w5 = mt76_rr(dev, addr + 5 * 4); 107eb99cc95SLorenzo Bianconi w5 &= ~(MT_WTBL_W5_BW_CAP | MT_WTBL_W5_CHANGE_BW_RATE | 108eb99cc95SLorenzo Bianconi MT_WTBL_W5_MPDU_OK_COUNT | 109eb99cc95SLorenzo Bianconi MT_WTBL_W5_MPDU_FAIL_COUNT | 110eb99cc95SLorenzo Bianconi MT_WTBL_W5_RATE_IDX); 111eb99cc95SLorenzo Bianconi w5 |= FIELD_PREP(MT_WTBL_W5_BW_CAP, rate->bw) | 112eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_W5_CHANGE_BW_RATE, 113eb99cc95SLorenzo Bianconi rate->bw_idx ? rate->bw_idx - 1 : 7); 114eb99cc95SLorenzo Bianconi 115eb99cc95SLorenzo Bianconi mt76_wr(dev, MT_WTBL_RIUCR0, w5); 116eb99cc95SLorenzo Bianconi 117eb99cc95SLorenzo Bianconi mt76_wr(dev, MT_WTBL_RIUCR1, 118eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR1_RATE0, rate->probe_val) | 119eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR1_RATE1, rate->val[0]) | 120eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, rate->val[1])); 121eb99cc95SLorenzo Bianconi 122eb99cc95SLorenzo Bianconi mt76_wr(dev, MT_WTBL_RIUCR2, 123eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, rate->val[1] >> 8) | 124eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR2_RATE3, rate->val[1]) | 125eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR2_RATE4, rate->val[2]) | 126eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, rate->val[2])); 127eb99cc95SLorenzo Bianconi 128eb99cc95SLorenzo Bianconi mt76_wr(dev, MT_WTBL_RIUCR3, 129eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, rate->val[2] >> 4) | 130eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR3_RATE6, rate->val[3]) | 131eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_RIUCR3_RATE7, rate->val[3])); 132eb99cc95SLorenzo Bianconi 133eb99cc95SLorenzo Bianconi mt76_wr(dev, MT_WTBL_UPDATE, 134eb99cc95SLorenzo Bianconi FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, sta->wcid.idx) | 135eb99cc95SLorenzo Bianconi MT_WTBL_UPDATE_RATE_UPDATE | 136eb99cc95SLorenzo Bianconi MT_WTBL_UPDATE_TX_COUNT_CLEAR); 137eb99cc95SLorenzo Bianconi 138eb99cc95SLorenzo Bianconi mt76_wr(dev, addr + 27 * 4, w27); 139eb99cc95SLorenzo Bianconi 140eb99cc95SLorenzo Bianconi mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ 141eb99cc95SLorenzo Bianconi val = mt76_rr(dev, MT_LPON_UTTR0); 142eb99cc95SLorenzo Bianconi sta->rate_set_tsf = (val & ~BIT(0)) | rate->rateset; 143eb99cc95SLorenzo Bianconi 144eb99cc95SLorenzo Bianconi if (!(sta->wcid.tx_info & MT_WCID_TX_INFO_SET)) 145eb99cc95SLorenzo Bianconi mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); 146eb99cc95SLorenzo Bianconi 147eb99cc95SLorenzo Bianconi sta->rate_count = 2 * MT7615_RATE_RETRY * sta->n_rates; 148eb99cc95SLorenzo Bianconi sta->wcid.tx_info |= MT_WCID_TX_INFO_SET; 149eb99cc95SLorenzo Bianconi 150eb99cc95SLorenzo Bianconi return 0; 151eb99cc95SLorenzo Bianconi } 152eb99cc95SLorenzo Bianconi 153eb99cc95SLorenzo Bianconi static int 154eb99cc95SLorenzo Bianconi __mt7663u_mac_set_key(struct mt7615_dev *dev, 155eb99cc95SLorenzo Bianconi struct mt7615_wtbl_desc *wd) 156eb99cc95SLorenzo Bianconi { 157eb99cc95SLorenzo Bianconi struct mt7615_key_desc *key = &wd->key; 158eb99cc95SLorenzo Bianconi struct mt7615_sta *sta = wd->sta; 159eb99cc95SLorenzo Bianconi enum mt7615_cipher_type cipher; 160eb99cc95SLorenzo Bianconi struct mt76_wcid *wcid; 161eb99cc95SLorenzo Bianconi int err; 162eb99cc95SLorenzo Bianconi 163eb99cc95SLorenzo Bianconi lockdep_assert_held(&dev->mt76.mutex); 164eb99cc95SLorenzo Bianconi 165eb99cc95SLorenzo Bianconi if (!sta) 166eb99cc95SLorenzo Bianconi return -EINVAL; 167eb99cc95SLorenzo Bianconi 168eb99cc95SLorenzo Bianconi cipher = mt7615_mac_get_cipher(key->cipher); 169eb99cc95SLorenzo Bianconi if (cipher == MT_CIPHER_NONE) 170eb99cc95SLorenzo Bianconi return -EOPNOTSUPP; 171eb99cc95SLorenzo Bianconi 172eb99cc95SLorenzo Bianconi wcid = &wd->sta->wcid; 173eb99cc95SLorenzo Bianconi 174eb99cc95SLorenzo Bianconi mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, key->cmd); 175eb99cc95SLorenzo Bianconi err = mt7615_mac_wtbl_update_key(dev, wcid, key->key, key->keylen, 176eb99cc95SLorenzo Bianconi cipher, key->cmd); 177eb99cc95SLorenzo Bianconi if (err < 0) 178eb99cc95SLorenzo Bianconi return err; 179eb99cc95SLorenzo Bianconi 180eb99cc95SLorenzo Bianconi err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, 181eb99cc95SLorenzo Bianconi key->cmd); 182eb99cc95SLorenzo Bianconi if (err < 0) 183eb99cc95SLorenzo Bianconi return err; 184eb99cc95SLorenzo Bianconi 185eb99cc95SLorenzo Bianconi if (key->cmd == SET_KEY) 186eb99cc95SLorenzo Bianconi wcid->cipher |= BIT(cipher); 187eb99cc95SLorenzo Bianconi else 188eb99cc95SLorenzo Bianconi wcid->cipher &= ~BIT(cipher); 189eb99cc95SLorenzo Bianconi 190eb99cc95SLorenzo Bianconi return 0; 191eb99cc95SLorenzo Bianconi } 192eb99cc95SLorenzo Bianconi 193eb99cc95SLorenzo Bianconi void mt7663u_wtbl_work(struct work_struct *work) 194eb99cc95SLorenzo Bianconi { 195eb99cc95SLorenzo Bianconi struct mt7615_wtbl_desc *wd, *wd_next; 196eb99cc95SLorenzo Bianconi struct mt7615_dev *dev; 197eb99cc95SLorenzo Bianconi 198eb99cc95SLorenzo Bianconi dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev, 199eb99cc95SLorenzo Bianconi wtbl_work); 200eb99cc95SLorenzo Bianconi 201eb99cc95SLorenzo Bianconi list_for_each_entry_safe(wd, wd_next, &dev->wd_head, node) { 202eb99cc95SLorenzo Bianconi spin_lock_bh(&dev->mt76.lock); 203eb99cc95SLorenzo Bianconi list_del(&wd->node); 204eb99cc95SLorenzo Bianconi spin_unlock_bh(&dev->mt76.lock); 205eb99cc95SLorenzo Bianconi 206eb99cc95SLorenzo Bianconi mutex_lock(&dev->mt76.mutex); 207eb99cc95SLorenzo Bianconi switch (wd->type) { 208eb99cc95SLorenzo Bianconi case MT7615_WTBL_RATE_DESC: 209eb99cc95SLorenzo Bianconi __mt7663u_mac_set_rates(dev, wd); 210eb99cc95SLorenzo Bianconi break; 211eb99cc95SLorenzo Bianconi case MT7615_WTBL_KEY_DESC: 212eb99cc95SLorenzo Bianconi __mt7663u_mac_set_key(dev, wd); 213eb99cc95SLorenzo Bianconi break; 214eb99cc95SLorenzo Bianconi } 215eb99cc95SLorenzo Bianconi mutex_unlock(&dev->mt76.mutex); 216eb99cc95SLorenzo Bianconi 217eb99cc95SLorenzo Bianconi kfree(wd); 218eb99cc95SLorenzo Bianconi } 219eb99cc95SLorenzo Bianconi } 220eb99cc95SLorenzo Bianconi 221eb99cc95SLorenzo Bianconi static void 222eb99cc95SLorenzo Bianconi mt7663u_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, 223eb99cc95SLorenzo Bianconi struct mt76_queue_entry *e) 224eb99cc95SLorenzo Bianconi { 225eb99cc95SLorenzo Bianconi skb_pull(e->skb, MT_USB_HDR_SIZE + MT_USB_TXD_SIZE); 226eb99cc95SLorenzo Bianconi mt76_tx_complete_skb(mdev, e->skb); 227eb99cc95SLorenzo Bianconi } 228eb99cc95SLorenzo Bianconi 229eb99cc95SLorenzo Bianconi static int 230eb99cc95SLorenzo Bianconi mt7663u_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 231eb99cc95SLorenzo Bianconi enum mt76_txq_id qid, struct mt76_wcid *wcid, 232eb99cc95SLorenzo Bianconi struct ieee80211_sta *sta, 233eb99cc95SLorenzo Bianconi struct mt76_tx_info *tx_info) 234eb99cc95SLorenzo Bianconi { 235eb99cc95SLorenzo Bianconi struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); 236eb99cc95SLorenzo Bianconi struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); 237eb99cc95SLorenzo Bianconi 238eb99cc95SLorenzo Bianconi if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { 239eb99cc95SLorenzo Bianconi struct mt7615_sta *msta; 240eb99cc95SLorenzo Bianconi 241eb99cc95SLorenzo Bianconi msta = container_of(wcid, struct mt7615_sta, wcid); 242eb99cc95SLorenzo Bianconi spin_lock_bh(&dev->mt76.lock); 243eb99cc95SLorenzo Bianconi mt7615_mac_set_rates(&dev->phy, msta, &info->control.rates[0], 244eb99cc95SLorenzo Bianconi msta->rates); 245eb99cc95SLorenzo Bianconi msta->rate_probe = true; 246eb99cc95SLorenzo Bianconi spin_unlock_bh(&dev->mt76.lock); 247eb99cc95SLorenzo Bianconi } 248eb99cc95SLorenzo Bianconi mt7663u_mac_write_txwi(dev, wcid, qid, sta, tx_info->skb); 249eb99cc95SLorenzo Bianconi 250eb99cc95SLorenzo Bianconi return mt76u_skb_dma_info(tx_info->skb, tx_info->skb->len); 251eb99cc95SLorenzo Bianconi } 252eb99cc95SLorenzo Bianconi 2535416651cSLorenzo Bianconi static bool mt7663u_tx_status_data(struct mt76_dev *mdev, u8 *update) 2545416651cSLorenzo Bianconi { 2555416651cSLorenzo Bianconi struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); 2565416651cSLorenzo Bianconi 2575416651cSLorenzo Bianconi mutex_lock(&dev->mt76.mutex); 2585416651cSLorenzo Bianconi mt7615_mac_sta_poll(dev); 2595416651cSLorenzo Bianconi mutex_unlock(&dev->mt76.mutex); 2605416651cSLorenzo Bianconi 2615416651cSLorenzo Bianconi return 0; 2625416651cSLorenzo Bianconi } 2635416651cSLorenzo Bianconi 264eb99cc95SLorenzo Bianconi static int mt7663u_probe(struct usb_interface *usb_intf, 265eb99cc95SLorenzo Bianconi const struct usb_device_id *id) 266eb99cc95SLorenzo Bianconi { 267eb99cc95SLorenzo Bianconi static const struct mt76_driver_ops drv_ops = { 268eb99cc95SLorenzo Bianconi .txwi_size = MT_USB_TXD_SIZE, 269eb99cc95SLorenzo Bianconi .drv_flags = MT_DRV_RX_DMA_HDR, 270eb99cc95SLorenzo Bianconi .tx_prepare_skb = mt7663u_tx_prepare_skb, 271eb99cc95SLorenzo Bianconi .tx_complete_skb = mt7663u_tx_complete_skb, 2725416651cSLorenzo Bianconi .tx_status_data = mt7663u_tx_status_data, 273eb99cc95SLorenzo Bianconi .rx_skb = mt7615_queue_rx_skb, 274eb99cc95SLorenzo Bianconi .sta_ps = mt7615_sta_ps, 275eb99cc95SLorenzo Bianconi .sta_add = mt7615_mac_sta_add, 276eb99cc95SLorenzo Bianconi .sta_remove = mt7615_mac_sta_remove, 277eb99cc95SLorenzo Bianconi .update_survey = mt7615_update_channel, 278eb99cc95SLorenzo Bianconi }; 279eb99cc95SLorenzo Bianconi struct usb_device *udev = interface_to_usbdev(usb_intf); 280eb99cc95SLorenzo Bianconi struct ieee80211_ops *ops; 281eb99cc95SLorenzo Bianconi struct mt7615_dev *dev; 282eb99cc95SLorenzo Bianconi struct mt76_dev *mdev; 283eb99cc95SLorenzo Bianconi int ret; 284eb99cc95SLorenzo Bianconi 285eb99cc95SLorenzo Bianconi ops = devm_kmemdup(&usb_intf->dev, &mt7615_ops, sizeof(mt7615_ops), 286eb99cc95SLorenzo Bianconi GFP_KERNEL); 287eb99cc95SLorenzo Bianconi if (!ops) 288eb99cc95SLorenzo Bianconi return -ENOMEM; 289eb99cc95SLorenzo Bianconi 290eb99cc95SLorenzo Bianconi ops->stop = mt7663u_stop; 291eb99cc95SLorenzo Bianconi 292eb99cc95SLorenzo Bianconi mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops); 293eb99cc95SLorenzo Bianconi if (!mdev) 294eb99cc95SLorenzo Bianconi return -ENOMEM; 295eb99cc95SLorenzo Bianconi 296eb99cc95SLorenzo Bianconi dev = container_of(mdev, struct mt7615_dev, mt76); 297eb99cc95SLorenzo Bianconi udev = usb_get_dev(udev); 298eb99cc95SLorenzo Bianconi usb_reset_device(udev); 299eb99cc95SLorenzo Bianconi 300eb99cc95SLorenzo Bianconi usb_set_intfdata(usb_intf, dev); 301eb99cc95SLorenzo Bianconi 302eb99cc95SLorenzo Bianconi dev->reg_map = mt7663u_reg_map; 303eb99cc95SLorenzo Bianconi dev->ops = ops; 304eb99cc95SLorenzo Bianconi ret = mt76u_init(mdev, usb_intf, true); 305eb99cc95SLorenzo Bianconi if (ret < 0) 306eb99cc95SLorenzo Bianconi goto error; 307eb99cc95SLorenzo Bianconi 308eb99cc95SLorenzo Bianconi mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | 309eb99cc95SLorenzo Bianconi (mt76_rr(dev, MT_HW_REV) & 0xff); 310eb99cc95SLorenzo Bianconi dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); 311eb99cc95SLorenzo Bianconi 312eb99cc95SLorenzo Bianconi if (mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, 313eb99cc95SLorenzo Bianconi FW_STATE_PWR_ON << 1, 500)) { 314eb99cc95SLorenzo Bianconi dev_dbg(dev->mt76.dev, "Usb device already powered on\n"); 315eb99cc95SLorenzo Bianconi set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state); 316eb99cc95SLorenzo Bianconi goto alloc_queues; 317eb99cc95SLorenzo Bianconi } 318eb99cc95SLorenzo Bianconi 319eb99cc95SLorenzo Bianconi ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, 320eb99cc95SLorenzo Bianconi USB_DIR_OUT | USB_TYPE_VENDOR, 321eb99cc95SLorenzo Bianconi 0x0, 0x1, NULL, 0); 322eb99cc95SLorenzo Bianconi if (ret) 323eb99cc95SLorenzo Bianconi goto error; 324eb99cc95SLorenzo Bianconi 325eb99cc95SLorenzo Bianconi if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, 326eb99cc95SLorenzo Bianconi FW_STATE_PWR_ON << 1, 500)) { 327eb99cc95SLorenzo Bianconi dev_err(dev->mt76.dev, "Timeout for power on\n"); 328eb99cc95SLorenzo Bianconi return -EIO; 329eb99cc95SLorenzo Bianconi } 330eb99cc95SLorenzo Bianconi 331eb99cc95SLorenzo Bianconi alloc_queues: 332eb99cc95SLorenzo Bianconi ret = mt76u_alloc_mcu_queue(&dev->mt76); 333eb99cc95SLorenzo Bianconi if (ret) 334eb99cc95SLorenzo Bianconi goto error; 335eb99cc95SLorenzo Bianconi 336eb99cc95SLorenzo Bianconi ret = mt76u_alloc_queues(&dev->mt76); 337eb99cc95SLorenzo Bianconi if (ret) 338eb99cc95SLorenzo Bianconi goto error; 339eb99cc95SLorenzo Bianconi 340eb99cc95SLorenzo Bianconi ret = mt7663u_register_device(dev); 341eb99cc95SLorenzo Bianconi if (ret) 342eb99cc95SLorenzo Bianconi goto error_freeq; 343eb99cc95SLorenzo Bianconi 344eb99cc95SLorenzo Bianconi return 0; 345eb99cc95SLorenzo Bianconi 346eb99cc95SLorenzo Bianconi error_freeq: 347eb99cc95SLorenzo Bianconi mt76u_queues_deinit(&dev->mt76); 348eb99cc95SLorenzo Bianconi error: 349eb99cc95SLorenzo Bianconi mt76u_deinit(&dev->mt76); 350eb99cc95SLorenzo Bianconi usb_set_intfdata(usb_intf, NULL); 351eb99cc95SLorenzo Bianconi usb_put_dev(interface_to_usbdev(usb_intf)); 352eb99cc95SLorenzo Bianconi 353eb99cc95SLorenzo Bianconi ieee80211_free_hw(mdev->hw); 354eb99cc95SLorenzo Bianconi 355eb99cc95SLorenzo Bianconi return ret; 356eb99cc95SLorenzo Bianconi } 357eb99cc95SLorenzo Bianconi 358eb99cc95SLorenzo Bianconi static void mt7663u_disconnect(struct usb_interface *usb_intf) 359eb99cc95SLorenzo Bianconi { 360eb99cc95SLorenzo Bianconi struct mt7615_dev *dev = usb_get_intfdata(usb_intf); 361eb99cc95SLorenzo Bianconi 362eb99cc95SLorenzo Bianconi if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) 363eb99cc95SLorenzo Bianconi return; 364eb99cc95SLorenzo Bianconi 365eb99cc95SLorenzo Bianconi ieee80211_unregister_hw(dev->mt76.hw); 366eb99cc95SLorenzo Bianconi mt7663u_cleanup(dev); 367eb99cc95SLorenzo Bianconi 368eb99cc95SLorenzo Bianconi usb_set_intfdata(usb_intf, NULL); 369eb99cc95SLorenzo Bianconi usb_put_dev(interface_to_usbdev(usb_intf)); 370eb99cc95SLorenzo Bianconi 371eb99cc95SLorenzo Bianconi mt76u_deinit(&dev->mt76); 372eb99cc95SLorenzo Bianconi ieee80211_free_hw(dev->mt76.hw); 373eb99cc95SLorenzo Bianconi } 374eb99cc95SLorenzo Bianconi 375*d0846f08SSean Wang #ifdef CONFIG_PM 376*d0846f08SSean Wang static int mt7663u_suspend(struct usb_interface *intf, pm_message_t state) 377eb99cc95SLorenzo Bianconi { 378*d0846f08SSean Wang struct mt7615_dev *dev = usb_get_intfdata(intf); 379*d0846f08SSean Wang 380*d0846f08SSean Wang if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) && 381*d0846f08SSean Wang mt7615_firmware_offload(dev)) { 382*d0846f08SSean Wang int err; 383*d0846f08SSean Wang 384*d0846f08SSean Wang err = mt7615_mcu_set_hif_suspend(dev, true); 385*d0846f08SSean Wang if (err < 0) 386*d0846f08SSean Wang return err; 387*d0846f08SSean Wang } 388*d0846f08SSean Wang 389*d0846f08SSean Wang mt76u_stop_rx(&dev->mt76); 390*d0846f08SSean Wang 391*d0846f08SSean Wang mt76u_stop_tx(&dev->mt76); 392*d0846f08SSean Wang tasklet_kill(&dev->mt76.tx_tasklet); 393*d0846f08SSean Wang 394eb99cc95SLorenzo Bianconi return 0; 395eb99cc95SLorenzo Bianconi } 396eb99cc95SLorenzo Bianconi 397*d0846f08SSean Wang static int mt7663u_resume(struct usb_interface *intf) 398eb99cc95SLorenzo Bianconi { 399*d0846f08SSean Wang struct mt7615_dev *dev = usb_get_intfdata(intf); 400*d0846f08SSean Wang int err; 401*d0846f08SSean Wang 402*d0846f08SSean Wang err = mt76u_vendor_request(&dev->mt76, MT_VEND_FEATURE_SET, 403*d0846f08SSean Wang USB_DIR_OUT | USB_TYPE_VENDOR, 404*d0846f08SSean Wang 0x5, 0x0, NULL, 0); 405*d0846f08SSean Wang if (err) 406*d0846f08SSean Wang return err; 407*d0846f08SSean Wang 408*d0846f08SSean Wang err = mt76u_resume_rx(&dev->mt76); 409*d0846f08SSean Wang if (err < 0) 410*d0846f08SSean Wang return err; 411*d0846f08SSean Wang 412*d0846f08SSean Wang if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) && 413*d0846f08SSean Wang mt7615_firmware_offload(dev)) 414*d0846f08SSean Wang err = mt7615_mcu_set_hif_suspend(dev, false); 415*d0846f08SSean Wang 416*d0846f08SSean Wang return err; 417eb99cc95SLorenzo Bianconi } 418*d0846f08SSean Wang #endif /* CONFIG_PM */ 419eb99cc95SLorenzo Bianconi 420eb99cc95SLorenzo Bianconi MODULE_DEVICE_TABLE(usb, mt7615_device_table); 421f2dc8ea1SLorenzo Bianconi MODULE_FIRMWARE(MT7663_OFFLOAD_FIRMWARE_N9); 422f2dc8ea1SLorenzo Bianconi MODULE_FIRMWARE(MT7663_OFFLOAD_ROM_PATCH); 423eb99cc95SLorenzo Bianconi MODULE_FIRMWARE(MT7663_FIRMWARE_N9); 424eb99cc95SLorenzo Bianconi MODULE_FIRMWARE(MT7663_ROM_PATCH); 425eb99cc95SLorenzo Bianconi 426eb99cc95SLorenzo Bianconi static struct usb_driver mt7663u_driver = { 427eb99cc95SLorenzo Bianconi .name = KBUILD_MODNAME, 428eb99cc95SLorenzo Bianconi .id_table = mt7615_device_table, 429eb99cc95SLorenzo Bianconi .probe = mt7663u_probe, 430eb99cc95SLorenzo Bianconi .disconnect = mt7663u_disconnect, 431eb99cc95SLorenzo Bianconi #ifdef CONFIG_PM 432eb99cc95SLorenzo Bianconi .suspend = mt7663u_suspend, 433eb99cc95SLorenzo Bianconi .resume = mt7663u_resume, 434eb99cc95SLorenzo Bianconi .reset_resume = mt7663u_resume, 435eb99cc95SLorenzo Bianconi #endif /* CONFIG_PM */ 436eb99cc95SLorenzo Bianconi .soft_unbind = 1, 437eb99cc95SLorenzo Bianconi .disable_hub_initiated_lpm = 1, 438eb99cc95SLorenzo Bianconi }; 439eb99cc95SLorenzo Bianconi module_usb_driver(mt7663u_driver); 440eb99cc95SLorenzo Bianconi 441eb99cc95SLorenzo Bianconi MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); 442eb99cc95SLorenzo Bianconi MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); 443eb99cc95SLorenzo Bianconi MODULE_LICENSE("Dual BSD/GPL"); 444