xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7921/pci.c (revision 8ba4d145d351db26e07695b8e90697398c5dfec2)
16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2020 MediaTek Inc.
36c92544dSBjoern A. Zeeb  *
46c92544dSBjoern A. Zeeb  */
56c92544dSBjoern A. Zeeb 
66c92544dSBjoern A. Zeeb #if defined(__FreeBSD__)
76c92544dSBjoern A. Zeeb #define	LINUXKPI_PARAM_PREFIX	mt7921_pci_
86c92544dSBjoern A. Zeeb #endif
96c92544dSBjoern A. Zeeb 
106c92544dSBjoern A. Zeeb #include <linux/kernel.h>
116c92544dSBjoern A. Zeeb #include <linux/module.h>
126c92544dSBjoern A. Zeeb #include <linux/pci.h>
13*8ba4d145SBjoern A. Zeeb #include <linux/of.h>
146c92544dSBjoern A. Zeeb 
156c92544dSBjoern A. Zeeb #include "mt7921.h"
16cbb3ec25SBjoern A. Zeeb #include "../mt76_connac2_mac.h"
17cbb3ec25SBjoern A. Zeeb #include "../dma.h"
186c92544dSBjoern A. Zeeb #include "mcu.h"
196c92544dSBjoern A. Zeeb 
206c92544dSBjoern A. Zeeb static const struct pci_device_id mt7921_pci_device_table[] = {
21cbb3ec25SBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961),
22cbb3ec25SBjoern A. Zeeb 		.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
23cbb3ec25SBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7922),
24cbb3ec25SBjoern A. Zeeb 		.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
25*8ba4d145SBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_ITTIM, 0x7922),
26*8ba4d145SBjoern A. Zeeb 		.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
27cbb3ec25SBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608),
28cbb3ec25SBjoern A. Zeeb 		.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
29cbb3ec25SBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616),
30cbb3ec25SBjoern A. Zeeb 		.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
31*8ba4d145SBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7920),
32*8ba4d145SBjoern A. Zeeb 		.driver_data = (kernel_ulong_t)MT7920_FIRMWARE_WM },
336c92544dSBjoern A. Zeeb 	{ },
346c92544dSBjoern A. Zeeb };
356c92544dSBjoern A. Zeeb 
366c92544dSBjoern A. Zeeb static bool mt7921_disable_aspm;
376c92544dSBjoern A. Zeeb module_param_named(disable_aspm, mt7921_disable_aspm, bool, 0644);
386c92544dSBjoern A. Zeeb MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support");
396c92544dSBjoern A. Zeeb 
mt7921e_init_reset(struct mt792x_dev * dev)40cbb3ec25SBjoern A. Zeeb static int mt7921e_init_reset(struct mt792x_dev *dev)
416c92544dSBjoern A. Zeeb {
42cbb3ec25SBjoern A. Zeeb 	return mt792x_wpdma_reset(dev, true);
436c92544dSBjoern A. Zeeb }
446c92544dSBjoern A. Zeeb 
mt7921e_unregister_device(struct mt792x_dev * dev)45cbb3ec25SBjoern A. Zeeb static void mt7921e_unregister_device(struct mt792x_dev *dev)
466c92544dSBjoern A. Zeeb {
476c92544dSBjoern A. Zeeb 	int i;
486c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
49*8ba4d145SBjoern A. Zeeb 	struct ieee80211_hw *hw = mt76_hw(dev);
50*8ba4d145SBjoern A. Zeeb 
51*8ba4d145SBjoern A. Zeeb 	if (dev->phy.chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN)
52*8ba4d145SBjoern A. Zeeb 		wiphy_rfkill_stop_polling(hw->wiphy);
536c92544dSBjoern A. Zeeb 
546c92544dSBjoern A. Zeeb 	cancel_work_sync(&dev->init_work);
556c92544dSBjoern A. Zeeb 	mt76_unregister_device(&dev->mt76);
566c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(&dev->mt76, i)
576c92544dSBjoern A. Zeeb 		napi_disable(&dev->mt76.napi[i]);
586c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&pm->ps_work);
596c92544dSBjoern A. Zeeb 	cancel_work_sync(&pm->wake_work);
60cbb3ec25SBjoern A. Zeeb 	cancel_work_sync(&dev->reset_work);
616c92544dSBjoern A. Zeeb 
62cbb3ec25SBjoern A. Zeeb 	mt76_connac2_tx_token_put(&dev->mt76);
63cbb3ec25SBjoern A. Zeeb 	__mt792x_mcu_drv_pmctrl(dev);
64cbb3ec25SBjoern A. Zeeb 	mt792x_dma_cleanup(dev);
65cbb3ec25SBjoern A. Zeeb 	mt792x_wfsys_reset(dev);
666c92544dSBjoern A. Zeeb 	skb_queue_purge(&dev->mt76.mcu.res_q);
676c92544dSBjoern A. Zeeb 
68cbb3ec25SBjoern A. Zeeb 	tasklet_disable(&dev->mt76.irq_tasklet);
696c92544dSBjoern A. Zeeb }
706c92544dSBjoern A. Zeeb 
__mt7921_reg_addr(struct mt792x_dev * dev,u32 addr)71cbb3ec25SBjoern A. Zeeb static u32 __mt7921_reg_addr(struct mt792x_dev *dev, u32 addr)
726c92544dSBjoern A. Zeeb {
736c92544dSBjoern A. Zeeb 	static const struct mt76_connac_reg_map fixed_map[] = {
746c92544dSBjoern A. Zeeb 		{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
756c92544dSBjoern A. Zeeb 		{ 0x820ed000, 0x24800, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
766c92544dSBjoern A. Zeeb 		{ 0x820e4000, 0x21000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
776c92544dSBjoern A. Zeeb 		{ 0x820e7000, 0x21e00, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
786c92544dSBjoern A. Zeeb 		{ 0x820eb000, 0x24200, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
796c92544dSBjoern A. Zeeb 		{ 0x820e2000, 0x20800, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
806c92544dSBjoern A. Zeeb 		{ 0x820e3000, 0x20c00, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
816c92544dSBjoern A. Zeeb 		{ 0x820e5000, 0x21400, 0x00800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
826c92544dSBjoern A. Zeeb 		{ 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
836c92544dSBjoern A. Zeeb 		{ 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure register) */
846c92544dSBjoern A. Zeeb 		{ 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
856c92544dSBjoern A. Zeeb 		{ 0x54000000, 0x02000, 0x01000 }, /* WFDMA PCIE0 MCU DMA0 */
866c92544dSBjoern A. Zeeb 		{ 0x55000000, 0x03000, 0x01000 }, /* WFDMA PCIE0 MCU DMA1 */
876c92544dSBjoern A. Zeeb 		{ 0x58000000, 0x06000, 0x01000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
886c92544dSBjoern A. Zeeb 		{ 0x59000000, 0x07000, 0x01000 }, /* WFDMA PCIE1 MCU DMA1 */
896c92544dSBjoern A. Zeeb 		{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
906c92544dSBjoern A. Zeeb 		{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
916c92544dSBjoern A. Zeeb 		{ 0x7c060000, 0xe0000, 0x10000 }, /* CONN_INFRA, conn_host_csr_top */
926c92544dSBjoern A. Zeeb 		{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
936c92544dSBjoern A. Zeeb 		{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
946c92544dSBjoern A. Zeeb 		{ 0x820c0000, 0x08000, 0x04000 }, /* WF_UMAC_TOP (PLE) */
956c92544dSBjoern A. Zeeb 		{ 0x820c8000, 0x0c000, 0x02000 }, /* WF_UMAC_TOP (PSE) */
966c92544dSBjoern A. Zeeb 		{ 0x820cc000, 0x0e000, 0x01000 }, /* WF_UMAC_TOP (PP) */
976c92544dSBjoern A. Zeeb 		{ 0x820cd000, 0x0f000, 0x01000 }, /* WF_MDP_TOP */
986c92544dSBjoern A. Zeeb 		{ 0x74030000, 0x10000, 0x10000 }, /* PCIE_MAC_IREG */
996c92544dSBjoern A. Zeeb 		{ 0x820ce000, 0x21c00, 0x00200 }, /* WF_LMAC_TOP (WF_SEC) */
1006c92544dSBjoern A. Zeeb 		{ 0x820cf000, 0x22000, 0x01000 }, /* WF_LMAC_TOP (WF_PF) */
1016c92544dSBjoern A. Zeeb 		{ 0x820e0000, 0x20000, 0x00400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
1026c92544dSBjoern A. Zeeb 		{ 0x820e1000, 0x20400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
1036c92544dSBjoern A. Zeeb 		{ 0x820e9000, 0x23400, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
1046c92544dSBjoern A. Zeeb 		{ 0x820ea000, 0x24000, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
1056c92544dSBjoern A. Zeeb 		{ 0x820ec000, 0x24600, 0x00200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
1066c92544dSBjoern A. Zeeb 		{ 0x820f0000, 0xa0000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
1076c92544dSBjoern A. Zeeb 		{ 0x820f1000, 0xa0600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
1086c92544dSBjoern A. Zeeb 		{ 0x820f2000, 0xa0800, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
1096c92544dSBjoern A. Zeeb 		{ 0x820f3000, 0xa0c00, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
1106c92544dSBjoern A. Zeeb 		{ 0x820f4000, 0xa1000, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
1116c92544dSBjoern A. Zeeb 		{ 0x820f5000, 0xa1400, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
1126c92544dSBjoern A. Zeeb 		{ 0x820f7000, 0xa1e00, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
1136c92544dSBjoern A. Zeeb 		{ 0x820f9000, 0xa3400, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
1146c92544dSBjoern A. Zeeb 		{ 0x820fa000, 0xa4000, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
1156c92544dSBjoern A. Zeeb 		{ 0x820fb000, 0xa4200, 0x00400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
1166c92544dSBjoern A. Zeeb 		{ 0x820fc000, 0xa4600, 0x00200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
1176c92544dSBjoern A. Zeeb 		{ 0x820fd000, 0xa4800, 0x00800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
1186c92544dSBjoern A. Zeeb 	};
1196c92544dSBjoern A. Zeeb 	int i;
1206c92544dSBjoern A. Zeeb 
1216c92544dSBjoern A. Zeeb 	if (addr < 0x100000)
1226c92544dSBjoern A. Zeeb 		return addr;
1236c92544dSBjoern A. Zeeb 
1246c92544dSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
1256c92544dSBjoern A. Zeeb 		u32 ofs;
1266c92544dSBjoern A. Zeeb 
1276c92544dSBjoern A. Zeeb 		if (addr < fixed_map[i].phys)
1286c92544dSBjoern A. Zeeb 			continue;
1296c92544dSBjoern A. Zeeb 
1306c92544dSBjoern A. Zeeb 		ofs = addr - fixed_map[i].phys;
1316c92544dSBjoern A. Zeeb 		if (ofs > fixed_map[i].size)
1326c92544dSBjoern A. Zeeb 			continue;
1336c92544dSBjoern A. Zeeb 
1346c92544dSBjoern A. Zeeb 		return fixed_map[i].maps + ofs;
1356c92544dSBjoern A. Zeeb 	}
1366c92544dSBjoern A. Zeeb 
1376c92544dSBjoern A. Zeeb 	if ((addr >= 0x18000000 && addr < 0x18c00000) ||
1386c92544dSBjoern A. Zeeb 	    (addr >= 0x70000000 && addr < 0x78000000) ||
1396c92544dSBjoern A. Zeeb 	    (addr >= 0x7c000000 && addr < 0x7c400000))
1406c92544dSBjoern A. Zeeb 		return mt7921_reg_map_l1(dev, addr);
1416c92544dSBjoern A. Zeeb 
1426c92544dSBjoern A. Zeeb 	dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
1436c92544dSBjoern A. Zeeb 		addr);
1446c92544dSBjoern A. Zeeb 
1456c92544dSBjoern A. Zeeb 	return 0;
1466c92544dSBjoern A. Zeeb }
1476c92544dSBjoern A. Zeeb 
mt7921_rr(struct mt76_dev * mdev,u32 offset)1486c92544dSBjoern A. Zeeb static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
1496c92544dSBjoern A. Zeeb {
150cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1516c92544dSBjoern A. Zeeb 	u32 addr = __mt7921_reg_addr(dev, offset);
1526c92544dSBjoern A. Zeeb 
1536c92544dSBjoern A. Zeeb 	return dev->bus_ops->rr(mdev, addr);
1546c92544dSBjoern A. Zeeb }
1556c92544dSBjoern A. Zeeb 
mt7921_wr(struct mt76_dev * mdev,u32 offset,u32 val)1566c92544dSBjoern A. Zeeb static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
1576c92544dSBjoern A. Zeeb {
158cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1596c92544dSBjoern A. Zeeb 	u32 addr = __mt7921_reg_addr(dev, offset);
1606c92544dSBjoern A. Zeeb 
1616c92544dSBjoern A. Zeeb 	dev->bus_ops->wr(mdev, addr, val);
1626c92544dSBjoern A. Zeeb }
1636c92544dSBjoern A. Zeeb 
mt7921_rmw(struct mt76_dev * mdev,u32 offset,u32 mask,u32 val)1646c92544dSBjoern A. Zeeb static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
1656c92544dSBjoern A. Zeeb {
166cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
1676c92544dSBjoern A. Zeeb 	u32 addr = __mt7921_reg_addr(dev, offset);
1686c92544dSBjoern A. Zeeb 
1696c92544dSBjoern A. Zeeb 	return dev->bus_ops->rmw(mdev, addr, mask, val);
1706c92544dSBjoern A. Zeeb }
1716c92544dSBjoern A. Zeeb 
mt7921_dma_init(struct mt792x_dev * dev)172cbb3ec25SBjoern A. Zeeb static int mt7921_dma_init(struct mt792x_dev *dev)
173cbb3ec25SBjoern A. Zeeb {
174cbb3ec25SBjoern A. Zeeb 	int ret;
175cbb3ec25SBjoern A. Zeeb 
176cbb3ec25SBjoern A. Zeeb 	mt76_dma_attach(&dev->mt76);
177cbb3ec25SBjoern A. Zeeb 
178cbb3ec25SBjoern A. Zeeb 	ret = mt792x_dma_disable(dev, true);
179cbb3ec25SBjoern A. Zeeb 	if (ret)
180cbb3ec25SBjoern A. Zeeb 		return ret;
181cbb3ec25SBjoern A. Zeeb 
182cbb3ec25SBjoern A. Zeeb 	/* init tx queue */
183cbb3ec25SBjoern A. Zeeb 	ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
184cbb3ec25SBjoern A. Zeeb 					 MT7921_TX_RING_SIZE,
185*8ba4d145SBjoern A. Zeeb 					 MT_TX_RING_BASE, NULL, 0);
186cbb3ec25SBjoern A. Zeeb 	if (ret)
187cbb3ec25SBjoern A. Zeeb 		return ret;
188cbb3ec25SBjoern A. Zeeb 
189cbb3ec25SBjoern A. Zeeb 	mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
190cbb3ec25SBjoern A. Zeeb 
191cbb3ec25SBjoern A. Zeeb 	/* command to WM */
192cbb3ec25SBjoern A. Zeeb 	ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM,
193cbb3ec25SBjoern A. Zeeb 				  MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
194cbb3ec25SBjoern A. Zeeb 	if (ret)
195cbb3ec25SBjoern A. Zeeb 		return ret;
196cbb3ec25SBjoern A. Zeeb 
197cbb3ec25SBjoern A. Zeeb 	/* firmware download */
198cbb3ec25SBjoern A. Zeeb 	ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7921_TXQ_FWDL,
199cbb3ec25SBjoern A. Zeeb 				  MT7921_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
200cbb3ec25SBjoern A. Zeeb 	if (ret)
201cbb3ec25SBjoern A. Zeeb 		return ret;
202cbb3ec25SBjoern A. Zeeb 
203cbb3ec25SBjoern A. Zeeb 	/* event from WM before firmware download */
204cbb3ec25SBjoern A. Zeeb 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
205cbb3ec25SBjoern A. Zeeb 			       MT7921_RXQ_MCU_WM,
206cbb3ec25SBjoern A. Zeeb 			       MT7921_RX_MCU_RING_SIZE,
207cbb3ec25SBjoern A. Zeeb 			       MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
208cbb3ec25SBjoern A. Zeeb 	if (ret)
209cbb3ec25SBjoern A. Zeeb 		return ret;
210cbb3ec25SBjoern A. Zeeb 
211cbb3ec25SBjoern A. Zeeb 	/* Change mcu queue after firmware download */
212cbb3ec25SBjoern A. Zeeb 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
213cbb3ec25SBjoern A. Zeeb 			       MT7921_RXQ_MCU_WM,
214*8ba4d145SBjoern A. Zeeb 			       MT7921_RX_MCU_WA_RING_SIZE,
215cbb3ec25SBjoern A. Zeeb 			       MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
216cbb3ec25SBjoern A. Zeeb 	if (ret)
217cbb3ec25SBjoern A. Zeeb 		return ret;
218cbb3ec25SBjoern A. Zeeb 
219cbb3ec25SBjoern A. Zeeb 	/* rx data */
220cbb3ec25SBjoern A. Zeeb 	ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
221cbb3ec25SBjoern A. Zeeb 			       MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE,
222cbb3ec25SBjoern A. Zeeb 			       MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
223cbb3ec25SBjoern A. Zeeb 	if (ret)
224cbb3ec25SBjoern A. Zeeb 		return ret;
225cbb3ec25SBjoern A. Zeeb 
226cbb3ec25SBjoern A. Zeeb 	ret = mt76_init_queues(dev, mt792x_poll_rx);
227cbb3ec25SBjoern A. Zeeb 	if (ret < 0)
228cbb3ec25SBjoern A. Zeeb 		return ret;
229cbb3ec25SBjoern A. Zeeb 
230*8ba4d145SBjoern A. Zeeb 	netif_napi_add_tx(dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
231cbb3ec25SBjoern A. Zeeb 			  mt792x_poll_tx);
232cbb3ec25SBjoern A. Zeeb 	napi_enable(&dev->mt76.tx_napi);
233cbb3ec25SBjoern A. Zeeb 
234cbb3ec25SBjoern A. Zeeb 	return mt792x_dma_enable(dev);
235cbb3ec25SBjoern A. Zeeb }
236cbb3ec25SBjoern A. Zeeb 
mt7921_pci_probe(struct pci_dev * pdev,const struct pci_device_id * id)2376c92544dSBjoern A. Zeeb static int mt7921_pci_probe(struct pci_dev *pdev,
2386c92544dSBjoern A. Zeeb 			    const struct pci_device_id *id)
2396c92544dSBjoern A. Zeeb {
2406c92544dSBjoern A. Zeeb 	static const struct mt76_driver_ops drv_ops = {
2416c92544dSBjoern A. Zeeb 		/* txwi_size = txd size + txp size */
2426c92544dSBjoern A. Zeeb 		.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp),
243cbb3ec25SBjoern A. Zeeb 		.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
244cbb3ec25SBjoern A. Zeeb 			     MT_DRV_AMSDU_OFFLOAD,
2456c92544dSBjoern A. Zeeb 		.survey_flags = SURVEY_INFO_TIME_TX |
2466c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_RX |
2476c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_BSS_RX,
2486c92544dSBjoern A. Zeeb 		.token_size = MT7921_TOKEN_SIZE,
2496c92544dSBjoern A. Zeeb 		.tx_prepare_skb = mt7921e_tx_prepare_skb,
2506c92544dSBjoern A. Zeeb 		.tx_complete_skb = mt76_connac_tx_complete_skb,
2516c92544dSBjoern A. Zeeb 		.rx_check = mt7921_rx_check,
2526c92544dSBjoern A. Zeeb 		.rx_skb = mt7921_queue_rx_skb,
253cbb3ec25SBjoern A. Zeeb 		.rx_poll_complete = mt792x_rx_poll_complete,
2546c92544dSBjoern A. Zeeb 		.sta_add = mt7921_mac_sta_add,
255*8ba4d145SBjoern A. Zeeb 		.sta_event = mt7921_mac_sta_event,
2566c92544dSBjoern A. Zeeb 		.sta_remove = mt7921_mac_sta_remove,
257cbb3ec25SBjoern A. Zeeb 		.update_survey = mt792x_update_channel,
258*8ba4d145SBjoern A. Zeeb 		.set_channel = mt7921_set_channel,
2596c92544dSBjoern A. Zeeb 	};
260cbb3ec25SBjoern A. Zeeb 	static const struct mt792x_hif_ops mt7921_pcie_ops = {
2616c92544dSBjoern A. Zeeb 		.init_reset = mt7921e_init_reset,
2626c92544dSBjoern A. Zeeb 		.reset = mt7921e_mac_reset,
2636c92544dSBjoern A. Zeeb 		.mcu_init = mt7921e_mcu_init,
264cbb3ec25SBjoern A. Zeeb 		.drv_own = mt792xe_mcu_drv_pmctrl,
265cbb3ec25SBjoern A. Zeeb 		.fw_own = mt792xe_mcu_fw_pmctrl,
2666c92544dSBjoern A. Zeeb 	};
267cbb3ec25SBjoern A. Zeeb 	static const struct mt792x_irq_map irq_map = {
268cbb3ec25SBjoern A. Zeeb 		.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
269cbb3ec25SBjoern A. Zeeb 		.tx = {
270cbb3ec25SBjoern A. Zeeb 			.all_complete_mask = MT_INT_TX_DONE_ALL,
271cbb3ec25SBjoern A. Zeeb 			.mcu_complete_mask = MT_INT_TX_DONE_MCU,
272cbb3ec25SBjoern A. Zeeb 		},
273cbb3ec25SBjoern A. Zeeb 		.rx = {
274cbb3ec25SBjoern A. Zeeb 			.data_complete_mask = MT_INT_RX_DONE_DATA,
275cbb3ec25SBjoern A. Zeeb 			.wm_complete_mask = MT_INT_RX_DONE_WM,
276cbb3ec25SBjoern A. Zeeb 			.wm2_complete_mask = MT_INT_RX_DONE_WM2,
277cbb3ec25SBjoern A. Zeeb 		},
278cbb3ec25SBjoern A. Zeeb 	};
279cbb3ec25SBjoern A. Zeeb 	struct ieee80211_ops *ops;
2806c92544dSBjoern A. Zeeb 	struct mt76_bus_ops *bus_ops;
281cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev;
2826c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev;
283*8ba4d145SBjoern A. Zeeb 	u16 cmd, chipid;
284cbb3ec25SBjoern A. Zeeb 	u8 features;
2856c92544dSBjoern A. Zeeb 	int ret;
2866c92544dSBjoern A. Zeeb 
2876c92544dSBjoern A. Zeeb 	ret = pcim_enable_device(pdev);
2886c92544dSBjoern A. Zeeb 	if (ret)
2896c92544dSBjoern A. Zeeb 		return ret;
2906c92544dSBjoern A. Zeeb 
2916c92544dSBjoern A. Zeeb 	ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
2926c92544dSBjoern A. Zeeb 	if (ret)
2936c92544dSBjoern A. Zeeb 		return ret;
2946c92544dSBjoern A. Zeeb 
295cbb3ec25SBjoern A. Zeeb 	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
296cbb3ec25SBjoern A. Zeeb 	if (!(cmd & PCI_COMMAND_MEMORY)) {
297cbb3ec25SBjoern A. Zeeb 		cmd |= PCI_COMMAND_MEMORY;
298cbb3ec25SBjoern A. Zeeb 		pci_write_config_word(pdev, PCI_COMMAND, cmd);
299cbb3ec25SBjoern A. Zeeb 	}
3006c92544dSBjoern A. Zeeb 	pci_set_master(pdev);
3016c92544dSBjoern A. Zeeb 
3026c92544dSBjoern A. Zeeb 	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
3036c92544dSBjoern A. Zeeb 	if (ret < 0)
3046c92544dSBjoern A. Zeeb 		return ret;
3056c92544dSBjoern A. Zeeb 
3066c92544dSBjoern A. Zeeb 	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
3076c92544dSBjoern A. Zeeb 	if (ret)
3086c92544dSBjoern A. Zeeb 		goto err_free_pci_vec;
3096c92544dSBjoern A. Zeeb 
3106c92544dSBjoern A. Zeeb 	if (mt7921_disable_aspm)
3116c92544dSBjoern A. Zeeb 		mt76_pci_disable_aspm(pdev);
3126c92544dSBjoern A. Zeeb 
313cbb3ec25SBjoern A. Zeeb 	ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7921_ops,
314cbb3ec25SBjoern A. Zeeb 				      (void *)id->driver_data, &features);
315cbb3ec25SBjoern A. Zeeb 	if (!ops) {
316cbb3ec25SBjoern A. Zeeb 		ret = -ENOMEM;
317cbb3ec25SBjoern A. Zeeb 		goto err_free_pci_vec;
318cbb3ec25SBjoern A. Zeeb 	}
319cbb3ec25SBjoern A. Zeeb 
320cbb3ec25SBjoern A. Zeeb 	mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
3216c92544dSBjoern A. Zeeb 	if (!mdev) {
3226c92544dSBjoern A. Zeeb 		ret = -ENOMEM;
3236c92544dSBjoern A. Zeeb 		goto err_free_pci_vec;
3246c92544dSBjoern A. Zeeb 	}
3256c92544dSBjoern A. Zeeb 
3266c92544dSBjoern A. Zeeb 	pci_set_drvdata(pdev, mdev);
3276c92544dSBjoern A. Zeeb 
328cbb3ec25SBjoern A. Zeeb 	dev = container_of(mdev, struct mt792x_dev, mt76);
329cbb3ec25SBjoern A. Zeeb 	dev->fw_features = features;
3306c92544dSBjoern A. Zeeb 	dev->hif_ops = &mt7921_pcie_ops;
331cbb3ec25SBjoern A. Zeeb 	dev->irq_map = &irq_map;
3326c92544dSBjoern A. Zeeb 	mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
333cbb3ec25SBjoern A. Zeeb 	tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
3346c92544dSBjoern A. Zeeb 
3356c92544dSBjoern A. Zeeb 	dev->phy.dev = dev;
3366c92544dSBjoern A. Zeeb 	dev->phy.mt76 = &dev->mt76.phy;
3376c92544dSBjoern A. Zeeb 	dev->mt76.phy.priv = &dev->phy;
3386c92544dSBjoern A. Zeeb 	dev->bus_ops = dev->mt76.bus;
3396c92544dSBjoern A. Zeeb 	bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
3406c92544dSBjoern A. Zeeb 			       GFP_KERNEL);
3416c92544dSBjoern A. Zeeb 	if (!bus_ops) {
3426c92544dSBjoern A. Zeeb 		ret = -ENOMEM;
3436c92544dSBjoern A. Zeeb 		goto err_free_dev;
3446c92544dSBjoern A. Zeeb 	}
3456c92544dSBjoern A. Zeeb 
3466c92544dSBjoern A. Zeeb 	bus_ops->rr = mt7921_rr;
3476c92544dSBjoern A. Zeeb 	bus_ops->wr = mt7921_wr;
3486c92544dSBjoern A. Zeeb 	bus_ops->rmw = mt7921_rmw;
3496c92544dSBjoern A. Zeeb 	dev->mt76.bus = bus_ops;
3506c92544dSBjoern A. Zeeb 
351*8ba4d145SBjoern A. Zeeb 	if (!mt7921_disable_aspm && mt76_pci_aspm_supported(pdev))
352*8ba4d145SBjoern A. Zeeb 		dev->aspm_supported = true;
353*8ba4d145SBjoern A. Zeeb 
354cbb3ec25SBjoern A. Zeeb 	ret = mt792xe_mcu_fw_pmctrl(dev);
355cbb3ec25SBjoern A. Zeeb 	if (ret)
356cbb3ec25SBjoern A. Zeeb 		goto err_free_dev;
357cbb3ec25SBjoern A. Zeeb 
358cbb3ec25SBjoern A. Zeeb 	ret = __mt792xe_mcu_drv_pmctrl(dev);
3596c92544dSBjoern A. Zeeb 	if (ret)
3606c92544dSBjoern A. Zeeb 		goto err_free_dev;
3616c92544dSBjoern A. Zeeb 
362*8ba4d145SBjoern A. Zeeb 	chipid = mt7921_l1_rr(dev, MT_HW_CHIPID);
363*8ba4d145SBjoern A. Zeeb 	if (chipid == 0x7961 && (mt7921_l1_rr(dev, MT_HW_BOUND) & BIT(7)))
364*8ba4d145SBjoern A. Zeeb 		chipid = 0x7920;
365*8ba4d145SBjoern A. Zeeb 	mdev->rev = (chipid << 16) |
3666c92544dSBjoern A. Zeeb 		    (mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
3676c92544dSBjoern A. Zeeb 	dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
3686c92544dSBjoern A. Zeeb 
369cbb3ec25SBjoern A. Zeeb 	ret = mt792x_wfsys_reset(dev);
370cbb3ec25SBjoern A. Zeeb 	if (ret)
371cbb3ec25SBjoern A. Zeeb 		goto err_free_dev;
372cbb3ec25SBjoern A. Zeeb 
373cbb3ec25SBjoern A. Zeeb 	mt76_wr(dev, irq_map.host_irq_enable, 0);
3746c92544dSBjoern A. Zeeb 
3756c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
3766c92544dSBjoern A. Zeeb 
377cbb3ec25SBjoern A. Zeeb 	ret = devm_request_irq(mdev->dev, pdev->irq, mt792x_irq_handler,
3786c92544dSBjoern A. Zeeb 			       IRQF_SHARED, KBUILD_MODNAME, dev);
3796c92544dSBjoern A. Zeeb 	if (ret)
3806c92544dSBjoern A. Zeeb 		goto err_free_dev;
3816c92544dSBjoern A. Zeeb 
3826c92544dSBjoern A. Zeeb 	ret = mt7921_dma_init(dev);
3836c92544dSBjoern A. Zeeb 	if (ret)
3846c92544dSBjoern A. Zeeb 		goto err_free_irq;
3856c92544dSBjoern A. Zeeb 
3866c92544dSBjoern A. Zeeb 	ret = mt7921_register_device(dev);
3876c92544dSBjoern A. Zeeb 	if (ret)
3886c92544dSBjoern A. Zeeb 		goto err_free_irq;
3896c92544dSBjoern A. Zeeb 
390*8ba4d145SBjoern A. Zeeb #if defined(CONFIG_OF)
391*8ba4d145SBjoern A. Zeeb 	if (of_property_read_bool(dev->mt76.dev->of_node, "wakeup-source"))
392*8ba4d145SBjoern A. Zeeb 		device_init_wakeup(dev->mt76.dev, true);
393*8ba4d145SBjoern A. Zeeb #endif
394*8ba4d145SBjoern A. Zeeb 
3956c92544dSBjoern A. Zeeb 	return 0;
3966c92544dSBjoern A. Zeeb 
3976c92544dSBjoern A. Zeeb err_free_irq:
3986c92544dSBjoern A. Zeeb 	devm_free_irq(&pdev->dev, pdev->irq, dev);
3996c92544dSBjoern A. Zeeb err_free_dev:
4006c92544dSBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
4016c92544dSBjoern A. Zeeb err_free_pci_vec:
4026c92544dSBjoern A. Zeeb 	pci_free_irq_vectors(pdev);
4036c92544dSBjoern A. Zeeb 
4046c92544dSBjoern A. Zeeb 	return ret;
4056c92544dSBjoern A. Zeeb }
4066c92544dSBjoern A. Zeeb 
mt7921_pci_remove(struct pci_dev * pdev)4076c92544dSBjoern A. Zeeb static void mt7921_pci_remove(struct pci_dev *pdev)
4086c92544dSBjoern A. Zeeb {
4096c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
410cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
4116c92544dSBjoern A. Zeeb 
412*8ba4d145SBjoern A. Zeeb #if defined(CONFIG_OF)
413*8ba4d145SBjoern A. Zeeb 	if (of_property_read_bool(dev->mt76.dev->of_node, "wakeup-source"))
414*8ba4d145SBjoern A. Zeeb 		device_init_wakeup(dev->mt76.dev, false);
415*8ba4d145SBjoern A. Zeeb #endif
416*8ba4d145SBjoern A. Zeeb 
4176c92544dSBjoern A. Zeeb 	mt7921e_unregister_device(dev);
418*8ba4d145SBjoern A. Zeeb 	set_bit(MT76_REMOVED, &mdev->phy.state);
4196c92544dSBjoern A. Zeeb 	devm_free_irq(&pdev->dev, pdev->irq, dev);
4206c92544dSBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
4216c92544dSBjoern A. Zeeb 	pci_free_irq_vectors(pdev);
4226c92544dSBjoern A. Zeeb }
4236c92544dSBjoern A. Zeeb 
4246c92544dSBjoern A. Zeeb #if !defined(__FreeBSD__) || defined(CONFIG_PM_SLEEP)
mt7921_pci_suspend(struct device * device)4256c92544dSBjoern A. Zeeb static int mt7921_pci_suspend(struct device *device)
4266c92544dSBjoern A. Zeeb {
4276c92544dSBjoern A. Zeeb 	struct pci_dev *pdev = to_pci_dev(device);
4286c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
429cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
4306c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
4316c92544dSBjoern A. Zeeb 	int i, err;
4326c92544dSBjoern A. Zeeb 
4336c92544dSBjoern A. Zeeb 	pm->suspended = true;
4346c92544dSBjoern A. Zeeb 	flush_work(&dev->reset_work);
4356c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&pm->ps_work);
4366c92544dSBjoern A. Zeeb 	cancel_work_sync(&pm->wake_work);
4376c92544dSBjoern A. Zeeb 
438*8ba4d145SBjoern A. Zeeb 	mt7921_roc_abort_sync(dev);
439*8ba4d145SBjoern A. Zeeb 
440cbb3ec25SBjoern A. Zeeb 	err = mt792x_mcu_drv_pmctrl(dev);
4416c92544dSBjoern A. Zeeb 	if (err < 0)
4426c92544dSBjoern A. Zeeb 		goto restore_suspend;
4436c92544dSBjoern A. Zeeb 
444*8ba4d145SBjoern A. Zeeb 	wait_event_timeout(dev->wait,
445*8ba4d145SBjoern A. Zeeb 			   !dev->regd_in_progress, 5 * HZ);
446*8ba4d145SBjoern A. Zeeb 
447*8ba4d145SBjoern A. Zeeb 	err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_OFF_LED);
448*8ba4d145SBjoern A. Zeeb 	if (err < 0)
449*8ba4d145SBjoern A. Zeeb 		goto restore_suspend;
450*8ba4d145SBjoern A. Zeeb 
451*8ba4d145SBjoern A. Zeeb 	err = mt76_connac_mcu_set_hif_suspend(mdev, true, true);
4526c92544dSBjoern A. Zeeb 	if (err)
4536c92544dSBjoern A. Zeeb 		goto restore_suspend;
4546c92544dSBjoern A. Zeeb 
4556c92544dSBjoern A. Zeeb 	/* always enable deep sleep during suspend to reduce
4566c92544dSBjoern A. Zeeb 	 * power consumption
4576c92544dSBjoern A. Zeeb 	 */
4586c92544dSBjoern A. Zeeb 	mt76_connac_mcu_set_deep_sleep(&dev->mt76, true);
4596c92544dSBjoern A. Zeeb 
4606c92544dSBjoern A. Zeeb 	napi_disable(&mdev->tx_napi);
4616c92544dSBjoern A. Zeeb 	mt76_worker_disable(&mdev->tx_worker);
4626c92544dSBjoern A. Zeeb 
4636c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
4646c92544dSBjoern A. Zeeb 		napi_disable(&mdev->napi[i]);
4656c92544dSBjoern A. Zeeb 	}
4666c92544dSBjoern A. Zeeb 
4676c92544dSBjoern A. Zeeb 	/* wait until dma is idle  */
4686c92544dSBjoern A. Zeeb 	mt76_poll(dev, MT_WFDMA0_GLO_CFG,
4696c92544dSBjoern A. Zeeb 		  MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
4706c92544dSBjoern A. Zeeb 		  MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000);
4716c92544dSBjoern A. Zeeb 
4726c92544dSBjoern A. Zeeb 	/* put dma disabled */
4736c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_WFDMA0_GLO_CFG,
4746c92544dSBjoern A. Zeeb 		   MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
4756c92544dSBjoern A. Zeeb 
4766c92544dSBjoern A. Zeeb 	/* disable interrupt */
477cbb3ec25SBjoern A. Zeeb 	mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
4786c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
4796c92544dSBjoern A. Zeeb 	synchronize_irq(pdev->irq);
480cbb3ec25SBjoern A. Zeeb 	tasklet_kill(&mdev->irq_tasklet);
4816c92544dSBjoern A. Zeeb 
482cbb3ec25SBjoern A. Zeeb 	err = mt792x_mcu_fw_pmctrl(dev);
4836c92544dSBjoern A. Zeeb 	if (err)
4846c92544dSBjoern A. Zeeb 		goto restore_napi;
4856c92544dSBjoern A. Zeeb 
4866c92544dSBjoern A. Zeeb 	return 0;
4876c92544dSBjoern A. Zeeb 
4886c92544dSBjoern A. Zeeb restore_napi:
4896c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
4906c92544dSBjoern A. Zeeb 		napi_enable(&mdev->napi[i]);
4916c92544dSBjoern A. Zeeb 	}
4926c92544dSBjoern A. Zeeb 	napi_enable(&mdev->tx_napi);
4936c92544dSBjoern A. Zeeb 
4946c92544dSBjoern A. Zeeb 	if (!pm->ds_enable)
4956c92544dSBjoern A. Zeeb 		mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
4966c92544dSBjoern A. Zeeb 
497*8ba4d145SBjoern A. Zeeb 	mt76_connac_mcu_set_hif_suspend(mdev, false, true);
4986c92544dSBjoern A. Zeeb 
4996c92544dSBjoern A. Zeeb restore_suspend:
5006c92544dSBjoern A. Zeeb 	pm->suspended = false;
5016c92544dSBjoern A. Zeeb 
5026c92544dSBjoern A. Zeeb 	if (err < 0)
503cbb3ec25SBjoern A. Zeeb 		mt792x_reset(&dev->mt76);
5046c92544dSBjoern A. Zeeb 
5056c92544dSBjoern A. Zeeb 	return err;
5066c92544dSBjoern A. Zeeb }
5076c92544dSBjoern A. Zeeb 
mt7921_pci_resume(struct device * device)5086c92544dSBjoern A. Zeeb static int mt7921_pci_resume(struct device *device)
5096c92544dSBjoern A. Zeeb {
5106c92544dSBjoern A. Zeeb 	struct pci_dev *pdev = to_pci_dev(device);
5116c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
512cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
5136c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
5146c92544dSBjoern A. Zeeb 	int i, err;
5156c92544dSBjoern A. Zeeb 
516cbb3ec25SBjoern A. Zeeb 	err = mt792x_mcu_drv_pmctrl(dev);
5176c92544dSBjoern A. Zeeb 	if (err < 0)
5186c92544dSBjoern A. Zeeb 		goto failed;
5196c92544dSBjoern A. Zeeb 
520cbb3ec25SBjoern A. Zeeb 	mt792x_wpdma_reinit_cond(dev);
5216c92544dSBjoern A. Zeeb 
5226c92544dSBjoern A. Zeeb 	/* enable interrupt */
5236c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
524cbb3ec25SBjoern A. Zeeb 	mt76_connac_irq_enable(&dev->mt76,
525cbb3ec25SBjoern A. Zeeb 			       dev->irq_map->tx.all_complete_mask |
526cbb3ec25SBjoern A. Zeeb 			       MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
5276c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
5286c92544dSBjoern A. Zeeb 
5296c92544dSBjoern A. Zeeb 	/* put dma enabled */
5306c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_WFDMA0_GLO_CFG,
5316c92544dSBjoern A. Zeeb 		 MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
5326c92544dSBjoern A. Zeeb 
5336c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->tx_worker);
5346c92544dSBjoern A. Zeeb 
5356c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
5366c92544dSBjoern A. Zeeb 		napi_enable(&mdev->napi[i]);
5376c92544dSBjoern A. Zeeb 	}
5386c92544dSBjoern A. Zeeb 	napi_enable(&mdev->tx_napi);
539*8ba4d145SBjoern A. Zeeb 
540*8ba4d145SBjoern A. Zeeb 	local_bh_disable();
541*8ba4d145SBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
542*8ba4d145SBjoern A. Zeeb 		napi_schedule(&mdev->napi[i]);
543*8ba4d145SBjoern A. Zeeb 	}
5446c92544dSBjoern A. Zeeb 	napi_schedule(&mdev->tx_napi);
5456c92544dSBjoern A. Zeeb 	local_bh_enable();
5466c92544dSBjoern A. Zeeb 
5476c92544dSBjoern A. Zeeb 	/* restore previous ds setting */
5486c92544dSBjoern A. Zeeb 	if (!pm->ds_enable)
5496c92544dSBjoern A. Zeeb 		mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
5506c92544dSBjoern A. Zeeb 
551*8ba4d145SBjoern A. Zeeb 	err = mt76_connac_mcu_set_hif_suspend(mdev, false, true);
552*8ba4d145SBjoern A. Zeeb 	if (err < 0)
553*8ba4d145SBjoern A. Zeeb 		goto failed;
554*8ba4d145SBjoern A. Zeeb 
555*8ba4d145SBjoern A. Zeeb 	mt7921_regd_update(dev);
556*8ba4d145SBjoern A. Zeeb 	err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_ON_LED);
5576c92544dSBjoern A. Zeeb failed:
5586c92544dSBjoern A. Zeeb 	pm->suspended = false;
5596c92544dSBjoern A. Zeeb 
5606c92544dSBjoern A. Zeeb 	if (err < 0)
561cbb3ec25SBjoern A. Zeeb 		mt792x_reset(&dev->mt76);
5626c92544dSBjoern A. Zeeb 
5636c92544dSBjoern A. Zeeb 	return err;
5646c92544dSBjoern A. Zeeb }
5656c92544dSBjoern A. Zeeb #endif
5666c92544dSBjoern A. Zeeb 
mt7921_pci_shutdown(struct pci_dev * pdev)567cbb3ec25SBjoern A. Zeeb static void mt7921_pci_shutdown(struct pci_dev *pdev)
568cbb3ec25SBjoern A. Zeeb {
569cbb3ec25SBjoern A. Zeeb 	mt7921_pci_remove(pdev);
570cbb3ec25SBjoern A. Zeeb }
571cbb3ec25SBjoern A. Zeeb 
5726c92544dSBjoern A. Zeeb static DEFINE_SIMPLE_DEV_PM_OPS(mt7921_pm_ops, mt7921_pci_suspend, mt7921_pci_resume);
5736c92544dSBjoern A. Zeeb 
5746c92544dSBjoern A. Zeeb static struct pci_driver mt7921_pci_driver = {
5756c92544dSBjoern A. Zeeb 	.name		= KBUILD_MODNAME,
5766c92544dSBjoern A. Zeeb 	.id_table	= mt7921_pci_device_table,
5776c92544dSBjoern A. Zeeb 	.probe		= mt7921_pci_probe,
5786c92544dSBjoern A. Zeeb 	.remove		= mt7921_pci_remove,
579cbb3ec25SBjoern A. Zeeb 	.shutdown	= mt7921_pci_shutdown,
5806c92544dSBjoern A. Zeeb 	.driver.pm	= pm_sleep_ptr(&mt7921_pm_ops),
5816c92544dSBjoern A. Zeeb };
5826c92544dSBjoern A. Zeeb 
5836c92544dSBjoern A. Zeeb module_pci_driver(mt7921_pci_driver);
5846c92544dSBjoern A. Zeeb 
5856c92544dSBjoern A. Zeeb MODULE_DEVICE_TABLE(pci, mt7921_pci_device_table);
586*8ba4d145SBjoern A. Zeeb MODULE_FIRMWARE(MT7920_FIRMWARE_WM);
587*8ba4d145SBjoern A. Zeeb MODULE_FIRMWARE(MT7920_ROM_PATCH);
5886c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
5896c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7921_ROM_PATCH);
5906c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7922_FIRMWARE_WM);
5916c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7922_ROM_PATCH);
5926c92544dSBjoern A. Zeeb MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
5936c92544dSBjoern A. Zeeb MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
594*8ba4d145SBjoern A. Zeeb MODULE_DESCRIPTION("MediaTek MT7921E (PCIe) wireless driver");
5956c92544dSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
5966c92544dSBjoern A. Zeeb #if defined(__FreeBSD__)
5976c92544dSBjoern A. Zeeb MODULE_VERSION(mt7921_pci, 1);
5986c92544dSBjoern A. Zeeb MODULE_DEPEND(mt7921_pci, linuxkpi, 1, 1, 1);
5996c92544dSBjoern A. Zeeb MODULE_DEPEND(mt7921_pci, linuxkpi_wlan, 1, 1, 1);
6006c92544dSBjoern A. Zeeb MODULE_DEPEND(mt7921_pci, mt76_core, 1, 1, 1);
6016c92544dSBjoern A. Zeeb #endif
602