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