16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2020 MediaTek Inc.
36c92544dSBjoern A. Zeeb *
46c92544dSBjoern A. Zeeb * Author: Lorenzo Bianconi <lorenzo@kernel.org>
56c92544dSBjoern A. Zeeb * Sean Wang <sean.wang@mediatek.com>
66c92544dSBjoern A. Zeeb */
76c92544dSBjoern A. Zeeb
86c92544dSBjoern A. Zeeb #include <linux/kernel.h>
96c92544dSBjoern A. Zeeb #include <linux/module.h>
106c92544dSBjoern A. Zeeb #include <linux/usb.h>
116c92544dSBjoern A. Zeeb
126c92544dSBjoern A. Zeeb #include "mt7615.h"
136c92544dSBjoern A. Zeeb #include "mac.h"
146c92544dSBjoern A. Zeeb #include "mcu.h"
156c92544dSBjoern A. Zeeb #include "regs.h"
166c92544dSBjoern A. Zeeb
176c92544dSBjoern A. Zeeb const u32 mt7663_usb_sdio_reg_map[] = {
186c92544dSBjoern A. Zeeb [MT_TOP_CFG_BASE] = 0x80020000,
196c92544dSBjoern A. Zeeb [MT_HW_BASE] = 0x80000000,
206c92544dSBjoern A. Zeeb [MT_DMA_SHDL_BASE] = 0x5000a000,
216c92544dSBjoern A. Zeeb [MT_HIF_BASE] = 0x50000000,
226c92544dSBjoern A. Zeeb [MT_CSR_BASE] = 0x40000000,
236c92544dSBjoern A. Zeeb [MT_EFUSE_ADDR_BASE] = 0x78011000,
246c92544dSBjoern A. Zeeb [MT_TOP_MISC_BASE] = 0x81020000,
256c92544dSBjoern A. Zeeb [MT_PLE_BASE] = 0x82060000,
266c92544dSBjoern A. Zeeb [MT_PSE_BASE] = 0x82068000,
276c92544dSBjoern A. Zeeb [MT_PP_BASE] = 0x8206c000,
286c92544dSBjoern A. Zeeb [MT_WTBL_BASE_ADDR] = 0x820e0000,
296c92544dSBjoern A. Zeeb [MT_CFG_BASE] = 0x820f0000,
306c92544dSBjoern A. Zeeb [MT_AGG_BASE] = 0x820f2000,
316c92544dSBjoern A. Zeeb [MT_ARB_BASE] = 0x820f3000,
326c92544dSBjoern A. Zeeb [MT_TMAC_BASE] = 0x820f4000,
336c92544dSBjoern A. Zeeb [MT_RMAC_BASE] = 0x820f5000,
346c92544dSBjoern A. Zeeb [MT_DMA_BASE] = 0x820f7000,
356c92544dSBjoern A. Zeeb [MT_PF_BASE] = 0x820f8000,
366c92544dSBjoern A. Zeeb [MT_WTBL_BASE_ON] = 0x820f9000,
376c92544dSBjoern A. Zeeb [MT_WTBL_BASE_OFF] = 0x820f9800,
386c92544dSBjoern A. Zeeb [MT_LPON_BASE] = 0x820fb000,
396c92544dSBjoern A. Zeeb [MT_MIB_BASE] = 0x820fd000,
406c92544dSBjoern A. Zeeb };
416c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7663_usb_sdio_reg_map);
426c92544dSBjoern A. Zeeb
436c92544dSBjoern A. Zeeb static void
mt7663_usb_sdio_write_txwi(struct mt7615_dev * dev,struct mt76_wcid * wcid,enum mt76_txq_id qid,struct ieee80211_sta * sta,struct ieee80211_key_conf * key,int pid,struct sk_buff * skb)446c92544dSBjoern A. Zeeb mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid,
456c92544dSBjoern A. Zeeb enum mt76_txq_id qid, struct ieee80211_sta *sta,
466c92544dSBjoern A. Zeeb struct ieee80211_key_conf *key, int pid,
476c92544dSBjoern A. Zeeb struct sk_buff *skb)
486c92544dSBjoern A. Zeeb {
496c92544dSBjoern A. Zeeb __le32 *txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE);
506c92544dSBjoern A. Zeeb
516c92544dSBjoern A. Zeeb memset(txwi, 0, MT_USB_TXD_SIZE);
526c92544dSBjoern A. Zeeb mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, qid, false);
536c92544dSBjoern A. Zeeb skb_push(skb, MT_USB_TXD_SIZE);
546c92544dSBjoern A. Zeeb }
556c92544dSBjoern A. Zeeb
mt7663_usb_sdio_set_rates(struct mt7615_dev * dev,struct mt7615_wtbl_rate_desc * wrd)566c92544dSBjoern A. Zeeb static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,
576c92544dSBjoern A. Zeeb struct mt7615_wtbl_rate_desc *wrd)
586c92544dSBjoern A. Zeeb {
596c92544dSBjoern A. Zeeb struct mt7615_rate_desc *rate = &wrd->rate;
606c92544dSBjoern A. Zeeb struct mt7615_sta *sta = wrd->sta;
616c92544dSBjoern A. Zeeb u32 w5, w27, addr, val;
626c92544dSBjoern A. Zeeb u16 idx;
636c92544dSBjoern A. Zeeb
646c92544dSBjoern A. Zeeb lockdep_assert_held(&dev->mt76.mutex);
656c92544dSBjoern A. Zeeb
666c92544dSBjoern A. Zeeb if (!sta)
676c92544dSBjoern A. Zeeb return -EINVAL;
686c92544dSBjoern A. Zeeb
696c92544dSBjoern A. Zeeb if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000))
706c92544dSBjoern A. Zeeb return -ETIMEDOUT;
716c92544dSBjoern A. Zeeb
726c92544dSBjoern A. Zeeb addr = mt7615_mac_wtbl_addr(dev, sta->wcid.idx);
736c92544dSBjoern A. Zeeb
746c92544dSBjoern A. Zeeb w27 = mt76_rr(dev, addr + 27 * 4);
756c92544dSBjoern A. Zeeb w27 &= ~MT_WTBL_W27_CC_BW_SEL;
766c92544dSBjoern A. Zeeb w27 |= FIELD_PREP(MT_WTBL_W27_CC_BW_SEL, rate->bw);
776c92544dSBjoern A. Zeeb
786c92544dSBjoern A. Zeeb w5 = mt76_rr(dev, addr + 5 * 4);
796c92544dSBjoern A. Zeeb w5 &= ~(MT_WTBL_W5_BW_CAP | MT_WTBL_W5_CHANGE_BW_RATE |
806c92544dSBjoern A. Zeeb MT_WTBL_W5_MPDU_OK_COUNT |
816c92544dSBjoern A. Zeeb MT_WTBL_W5_MPDU_FAIL_COUNT |
826c92544dSBjoern A. Zeeb MT_WTBL_W5_RATE_IDX);
836c92544dSBjoern A. Zeeb w5 |= FIELD_PREP(MT_WTBL_W5_BW_CAP, rate->bw) |
846c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_W5_CHANGE_BW_RATE,
856c92544dSBjoern A. Zeeb rate->bw_idx ? rate->bw_idx - 1 : 7);
866c92544dSBjoern A. Zeeb
876c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WTBL_RIUCR0, w5);
886c92544dSBjoern A. Zeeb
896c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WTBL_RIUCR1,
906c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR1_RATE0, rate->probe_val) |
916c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR1_RATE1, rate->val[0]) |
926c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, rate->val[1]));
936c92544dSBjoern A. Zeeb
946c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WTBL_RIUCR2,
956c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, rate->val[1] >> 8) |
966c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR2_RATE3, rate->val[1]) |
976c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR2_RATE4, rate->val[2]) |
986c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, rate->val[2]));
996c92544dSBjoern A. Zeeb
1006c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WTBL_RIUCR3,
1016c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, rate->val[2] >> 4) |
1026c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR3_RATE6, rate->val[3]) |
1036c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_RIUCR3_RATE7, rate->val[3]));
1046c92544dSBjoern A. Zeeb
1056c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WTBL_UPDATE,
1066c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, sta->wcid.idx) |
1076c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_RATE_UPDATE |
1086c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_TX_COUNT_CLEAR);
1096c92544dSBjoern A. Zeeb
1106c92544dSBjoern A. Zeeb mt76_wr(dev, addr + 27 * 4, w27);
1116c92544dSBjoern A. Zeeb
1126c92544dSBjoern A. Zeeb sta->rate_probe = sta->rateset[rate->rateset].probe_rate.idx != -1;
1136c92544dSBjoern A. Zeeb
1146c92544dSBjoern A. Zeeb idx = sta->vif->mt76.omac_idx;
1156c92544dSBjoern A. Zeeb idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
1166c92544dSBjoern A. Zeeb addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
1176c92544dSBjoern A. Zeeb
1186c92544dSBjoern A. Zeeb mt76_rmw(dev, addr, MT_LPON_TCR_MODE, MT_LPON_TCR_READ); /* TSF read */
1196c92544dSBjoern A. Zeeb val = mt76_rr(dev, MT_LPON_UTTR0);
1206c92544dSBjoern A. Zeeb sta->rate_set_tsf = (val & ~BIT(0)) | rate->rateset;
1216c92544dSBjoern A. Zeeb
1226c92544dSBjoern A. Zeeb if (!(sta->wcid.tx_info & MT_WCID_TX_INFO_SET))
1236c92544dSBjoern A. Zeeb mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
1246c92544dSBjoern A. Zeeb
1256c92544dSBjoern A. Zeeb sta->rate_count = 2 * MT7615_RATE_RETRY * sta->n_rates;
1266c92544dSBjoern A. Zeeb sta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
1276c92544dSBjoern A. Zeeb
1286c92544dSBjoern A. Zeeb return 0;
1296c92544dSBjoern A. Zeeb }
1306c92544dSBjoern A. Zeeb
mt7663_usb_sdio_rate_work(struct work_struct * work)1316c92544dSBjoern A. Zeeb static void mt7663_usb_sdio_rate_work(struct work_struct *work)
1326c92544dSBjoern A. Zeeb {
1336c92544dSBjoern A. Zeeb struct mt7615_wtbl_rate_desc *wrd, *wrd_next;
1346c92544dSBjoern A. Zeeb struct list_head wrd_list;
1356c92544dSBjoern A. Zeeb struct mt7615_dev *dev;
1366c92544dSBjoern A. Zeeb
1376c92544dSBjoern A. Zeeb dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev,
1386c92544dSBjoern A. Zeeb rate_work);
1396c92544dSBjoern A. Zeeb
1406c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&wrd_list);
1416c92544dSBjoern A. Zeeb spin_lock_bh(&dev->mt76.lock);
1426c92544dSBjoern A. Zeeb list_splice_init(&dev->wrd_head, &wrd_list);
1436c92544dSBjoern A. Zeeb spin_unlock_bh(&dev->mt76.lock);
1446c92544dSBjoern A. Zeeb
1456c92544dSBjoern A. Zeeb list_for_each_entry_safe(wrd, wrd_next, &wrd_list, node) {
1466c92544dSBjoern A. Zeeb list_del(&wrd->node);
1476c92544dSBjoern A. Zeeb
1486c92544dSBjoern A. Zeeb mt7615_mutex_acquire(dev);
1496c92544dSBjoern A. Zeeb mt7663_usb_sdio_set_rates(dev, wrd);
1506c92544dSBjoern A. Zeeb mt7615_mutex_release(dev);
1516c92544dSBjoern A. Zeeb
1526c92544dSBjoern A. Zeeb kfree(wrd);
1536c92544dSBjoern A. Zeeb }
1546c92544dSBjoern A. Zeeb }
1556c92544dSBjoern A. Zeeb
mt7663_usb_sdio_tx_status_data(struct mt76_dev * mdev,u8 * update)1566c92544dSBjoern A. Zeeb bool mt7663_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
1576c92544dSBjoern A. Zeeb {
1586c92544dSBjoern A. Zeeb struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1596c92544dSBjoern A. Zeeb
1606c92544dSBjoern A. Zeeb mt7615_mutex_acquire(dev);
1616c92544dSBjoern A. Zeeb mt7615_mac_sta_poll(dev);
1626c92544dSBjoern A. Zeeb mt7615_mutex_release(dev);
1636c92544dSBjoern A. Zeeb
1646c92544dSBjoern A. Zeeb return false;
1656c92544dSBjoern A. Zeeb }
1666c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_status_data);
1676c92544dSBjoern A. Zeeb
mt7663_usb_sdio_tx_complete_skb(struct mt76_dev * mdev,struct mt76_queue_entry * e)1686c92544dSBjoern A. Zeeb void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
1696c92544dSBjoern A. Zeeb struct mt76_queue_entry *e)
1706c92544dSBjoern A. Zeeb {
1716c92544dSBjoern A. Zeeb unsigned int headroom = MT_USB_TXD_SIZE;
1726c92544dSBjoern A. Zeeb
1736c92544dSBjoern A. Zeeb if (mt76_is_usb(mdev))
1746c92544dSBjoern A. Zeeb headroom += MT_USB_HDR_SIZE;
1756c92544dSBjoern A. Zeeb skb_pull(e->skb, headroom);
1766c92544dSBjoern A. Zeeb
1776c92544dSBjoern A. Zeeb mt76_tx_complete_skb(mdev, e->wcid, e->skb);
1786c92544dSBjoern A. Zeeb }
1796c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_complete_skb);
1806c92544dSBjoern A. Zeeb
mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev * mdev,void * txwi_ptr,enum mt76_txq_id qid,struct mt76_wcid * wcid,struct ieee80211_sta * sta,struct mt76_tx_info * tx_info)1816c92544dSBjoern A. Zeeb int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
1826c92544dSBjoern A. Zeeb enum mt76_txq_id qid, struct mt76_wcid *wcid,
1836c92544dSBjoern A. Zeeb struct ieee80211_sta *sta,
1846c92544dSBjoern A. Zeeb struct mt76_tx_info *tx_info)
1856c92544dSBjoern A. Zeeb {
1866c92544dSBjoern A. Zeeb struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1876c92544dSBjoern A. Zeeb struct sk_buff *skb = tx_info->skb;
1886c92544dSBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1896c92544dSBjoern A. Zeeb struct ieee80211_key_conf *key = info->control.hw_key;
1906c92544dSBjoern A. Zeeb struct mt7615_sta *msta;
1916c92544dSBjoern A. Zeeb int pad, err, pktid;
1926c92544dSBjoern A. Zeeb
1936c92544dSBjoern A. Zeeb msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
1946c92544dSBjoern A. Zeeb if (!wcid)
1956c92544dSBjoern A. Zeeb wcid = &dev->mt76.global_wcid;
1966c92544dSBjoern A. Zeeb
1976c92544dSBjoern A. Zeeb if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) &&
1986c92544dSBjoern A. Zeeb msta && !msta->rate_probe) {
1996c92544dSBjoern A. Zeeb /* request to configure sampling rate */
2006c92544dSBjoern A. Zeeb spin_lock_bh(&dev->mt76.lock);
2016c92544dSBjoern A. Zeeb mt7615_mac_set_rates(&dev->phy, msta, &info->control.rates[0],
2026c92544dSBjoern A. Zeeb msta->rates);
2036c92544dSBjoern A. Zeeb spin_unlock_bh(&dev->mt76.lock);
2046c92544dSBjoern A. Zeeb }
2056c92544dSBjoern A. Zeeb
2066c92544dSBjoern A. Zeeb pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
2076c92544dSBjoern A. Zeeb mt7663_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
2086c92544dSBjoern A. Zeeb if (mt76_is_usb(mdev)) {
2096c92544dSBjoern A. Zeeb u32 len = skb->len;
2106c92544dSBjoern A. Zeeb
2116c92544dSBjoern A. Zeeb put_unaligned_le32(len, skb_push(skb, sizeof(len)));
2126c92544dSBjoern A. Zeeb pad = round_up(skb->len, 4) + 4 - skb->len;
2136c92544dSBjoern A. Zeeb } else {
2146c92544dSBjoern A. Zeeb pad = round_up(skb->len, 4) - skb->len;
2156c92544dSBjoern A. Zeeb }
2166c92544dSBjoern A. Zeeb
2176c92544dSBjoern A. Zeeb err = mt76_skb_adjust_pad(skb, pad);
2186c92544dSBjoern A. Zeeb if (err)
2196c92544dSBjoern A. Zeeb /* Release pktid in case of error. */
2206c92544dSBjoern A. Zeeb idr_remove(&wcid->pktid, pktid);
2216c92544dSBjoern A. Zeeb
2226c92544dSBjoern A. Zeeb return err;
2236c92544dSBjoern A. Zeeb }
2246c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_prepare_skb);
2256c92544dSBjoern A. Zeeb
mt7663u_dma_sched_init(struct mt7615_dev * dev)2266c92544dSBjoern A. Zeeb static int mt7663u_dma_sched_init(struct mt7615_dev *dev)
2276c92544dSBjoern A. Zeeb {
2286c92544dSBjoern A. Zeeb int i;
2296c92544dSBjoern A. Zeeb
2306c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_DMA_SHDL(MT_DMASHDL_PKT_MAX_SIZE),
2316c92544dSBjoern A. Zeeb MT_DMASHDL_PKT_MAX_SIZE_PLE | MT_DMASHDL_PKT_MAX_SIZE_PSE,
2326c92544dSBjoern A. Zeeb FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PLE, 1) |
2336c92544dSBjoern A. Zeeb FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PSE, 8));
2346c92544dSBjoern A. Zeeb
2356c92544dSBjoern A. Zeeb /* disable refill group 5 - group 15 and raise group 2
2366c92544dSBjoern A. Zeeb * and 3 as high priority.
2376c92544dSBjoern A. Zeeb */
2386c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_REFILL), 0xffe00006);
2396c92544dSBjoern A. Zeeb mt76_clear(dev, MT_DMA_SHDL(MT_DMASHDL_PAGE), BIT(16));
2406c92544dSBjoern A. Zeeb
2416c92544dSBjoern A. Zeeb for (i = 0; i < 5; i++)
2426c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_GROUP_QUOTA(i)),
2436c92544dSBjoern A. Zeeb FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x3) |
2446c92544dSBjoern A. Zeeb FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x1ff));
2456c92544dSBjoern A. Zeeb
2466c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(0)), 0x42104210);
2476c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(1)), 0x42104210);
2486c92544dSBjoern A. Zeeb
2496c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(2)), 0x4444);
2506c92544dSBjoern A. Zeeb
2516c92544dSBjoern A. Zeeb /* group pririority from high to low:
2526c92544dSBjoern A. Zeeb * 15 (cmd groups) > 4 > 3 > 2 > 1 > 0.
2536c92544dSBjoern A. Zeeb */
2546c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET0), 0x6501234f);
2556c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET1), 0xedcba987);
2566c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_OPTIONAL), 0x7004801c);
2576c92544dSBjoern A. Zeeb
2586c92544dSBjoern A. Zeeb mt76_wr(dev, MT_UDMA_WLCFG_1,
2596c92544dSBjoern A. Zeeb FIELD_PREP(MT_WL_TX_TMOUT_LMT, 80000) |
2606c92544dSBjoern A. Zeeb FIELD_PREP(MT_WL_RX_AGG_PKT_LMT, 1));
2616c92544dSBjoern A. Zeeb
2626c92544dSBjoern A. Zeeb /* setup UDMA Rx Flush */
2636c92544dSBjoern A. Zeeb mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH);
2646c92544dSBjoern A. Zeeb /* hif reset */
2656c92544dSBjoern A. Zeeb mt76_set(dev, MT_HIF_RST, MT_HIF_LOGIC_RST_N);
2666c92544dSBjoern A. Zeeb
2676c92544dSBjoern A. Zeeb mt76_set(dev, MT_UDMA_WLCFG_0,
2686c92544dSBjoern A. Zeeb MT_WL_RX_AGG_EN | MT_WL_RX_EN | MT_WL_TX_EN |
2696c92544dSBjoern A. Zeeb MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN |
2706c92544dSBjoern A. Zeeb MT_WL_TX_TMOUT_FUNC_EN);
2716c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_UDMA_WLCFG_0, MT_WL_RX_AGG_LMT | MT_WL_RX_AGG_TO,
2726c92544dSBjoern A. Zeeb FIELD_PREP(MT_WL_RX_AGG_LMT, 32) |
2736c92544dSBjoern A. Zeeb FIELD_PREP(MT_WL_RX_AGG_TO, 100));
2746c92544dSBjoern A. Zeeb
2756c92544dSBjoern A. Zeeb return 0;
2766c92544dSBjoern A. Zeeb }
2776c92544dSBjoern A. Zeeb
mt7663_usb_sdio_init_hardware(struct mt7615_dev * dev)2786c92544dSBjoern A. Zeeb static int mt7663_usb_sdio_init_hardware(struct mt7615_dev *dev)
2796c92544dSBjoern A. Zeeb {
2806c92544dSBjoern A. Zeeb int ret, idx;
2816c92544dSBjoern A. Zeeb
2826c92544dSBjoern A. Zeeb ret = mt7615_eeprom_init(dev, MT_EFUSE_BASE);
2836c92544dSBjoern A. Zeeb if (ret < 0)
2846c92544dSBjoern A. Zeeb return ret;
2856c92544dSBjoern A. Zeeb
2866c92544dSBjoern A. Zeeb if (mt76_is_usb(&dev->mt76)) {
2876c92544dSBjoern A. Zeeb ret = mt7663u_dma_sched_init(dev);
2886c92544dSBjoern A. Zeeb if (ret)
2896c92544dSBjoern A. Zeeb return ret;
2906c92544dSBjoern A. Zeeb }
2916c92544dSBjoern A. Zeeb
2926c92544dSBjoern A. Zeeb set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
2936c92544dSBjoern A. Zeeb
2946c92544dSBjoern A. Zeeb /* Beacon and mgmt frames should occupy wcid 0 */
2956c92544dSBjoern A. Zeeb idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1);
2966c92544dSBjoern A. Zeeb if (idx)
2976c92544dSBjoern A. Zeeb return -ENOSPC;
2986c92544dSBjoern A. Zeeb
2996c92544dSBjoern A. Zeeb dev->mt76.global_wcid.idx = idx;
3006c92544dSBjoern A. Zeeb dev->mt76.global_wcid.hw_key_idx = -1;
3016c92544dSBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
3026c92544dSBjoern A. Zeeb
3036c92544dSBjoern A. Zeeb return 0;
3046c92544dSBjoern A. Zeeb }
3056c92544dSBjoern A. Zeeb
mt7663_usb_sdio_register_device(struct mt7615_dev * dev)3066c92544dSBjoern A. Zeeb int mt7663_usb_sdio_register_device(struct mt7615_dev *dev)
3076c92544dSBjoern A. Zeeb {
3086c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = mt76_hw(dev);
3096c92544dSBjoern A. Zeeb int err;
3106c92544dSBjoern A. Zeeb
3116c92544dSBjoern A. Zeeb INIT_WORK(&dev->rate_work, mt7663_usb_sdio_rate_work);
3126c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&dev->wrd_head);
3136c92544dSBjoern A. Zeeb mt7615_init_device(dev);
3146c92544dSBjoern A. Zeeb
3156c92544dSBjoern A. Zeeb err = mt7663_usb_sdio_init_hardware(dev);
3166c92544dSBjoern A. Zeeb if (err)
3176c92544dSBjoern A. Zeeb return err;
3186c92544dSBjoern A. Zeeb
3196c92544dSBjoern A. Zeeb hw->extra_tx_headroom += MT_USB_TXD_SIZE;
3206c92544dSBjoern A. Zeeb if (mt76_is_usb(&dev->mt76)) {
3216c92544dSBjoern A. Zeeb hw->extra_tx_headroom += MT_USB_HDR_SIZE;
3226c92544dSBjoern A. Zeeb /* check hw sg support in order to enable AMSDU */
3236c92544dSBjoern A. Zeeb if (dev->mt76.usb.sg_en)
3246c92544dSBjoern A. Zeeb hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM;
3256c92544dSBjoern A. Zeeb else
3266c92544dSBjoern A. Zeeb hw->max_tx_fragments = 1;
3276c92544dSBjoern A. Zeeb }
3286c92544dSBjoern A. Zeeb
3296c92544dSBjoern A. Zeeb err = mt76_register_device(&dev->mt76, true, mt76_rates,
3306c92544dSBjoern A. Zeeb ARRAY_SIZE(mt76_rates));
3316c92544dSBjoern A. Zeeb if (err < 0)
3326c92544dSBjoern A. Zeeb return err;
3336c92544dSBjoern A. Zeeb
3346c92544dSBjoern A. Zeeb if (!dev->mt76.usb.sg_en) {
3356c92544dSBjoern A. Zeeb struct ieee80211_sta_vht_cap *vht_cap;
3366c92544dSBjoern A. Zeeb
3376c92544dSBjoern A. Zeeb /* decrease max A-MSDU size if SG is not supported */
3386c92544dSBjoern A. Zeeb vht_cap = &dev->mphy.sband_5g.sband.vht_cap;
3396c92544dSBjoern A. Zeeb vht_cap->cap &= ~IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
3406c92544dSBjoern A. Zeeb }
3416c92544dSBjoern A. Zeeb
3426c92544dSBjoern A. Zeeb ieee80211_queue_work(hw, &dev->mcu_work);
3436c92544dSBjoern A. Zeeb mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband);
3446c92544dSBjoern A. Zeeb mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband);
3456c92544dSBjoern A. Zeeb
3466c92544dSBjoern A. Zeeb return mt7615_init_debugfs(dev);
3476c92544dSBjoern A. Zeeb }
3486c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7663_usb_sdio_register_device);
3496c92544dSBjoern A. Zeeb
3506c92544dSBjoern A. Zeeb MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
3516c92544dSBjoern A. Zeeb MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
3526c92544dSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
353