xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7615/pci.c (revision cbb3ec25236ba72f91cbdf23f8b78b9d1af0cedf)
16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2019 MediaTek Inc.
36c92544dSBjoern A. Zeeb  *
46c92544dSBjoern A. Zeeb  * Author: Ryder Lee <ryder.lee@mediatek.com>
56c92544dSBjoern A. Zeeb  *         Felix Fietkau <nbd@nbd.name>
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/pci.h>
116c92544dSBjoern A. Zeeb 
126c92544dSBjoern A. Zeeb #include "mt7615.h"
136c92544dSBjoern A. Zeeb #include "mcu.h"
146c92544dSBjoern A. Zeeb 
156c92544dSBjoern A. Zeeb static const struct pci_device_id mt7615_pci_device_table[] = {
166c92544dSBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7615) },
176c92544dSBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7663) },
186c92544dSBjoern A. Zeeb 	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7611) },
196c92544dSBjoern A. Zeeb 	{ },
206c92544dSBjoern A. Zeeb };
216c92544dSBjoern A. Zeeb 
mt7615_pci_probe(struct pci_dev * pdev,const struct pci_device_id * id)226c92544dSBjoern A. Zeeb static int mt7615_pci_probe(struct pci_dev *pdev,
236c92544dSBjoern A. Zeeb 			    const struct pci_device_id *id)
246c92544dSBjoern A. Zeeb {
256c92544dSBjoern A. Zeeb 	const u32 *map;
266c92544dSBjoern A. Zeeb 	int ret;
276c92544dSBjoern A. Zeeb 
286c92544dSBjoern A. Zeeb 	ret = pcim_enable_device(pdev);
296c92544dSBjoern A. Zeeb 	if (ret)
306c92544dSBjoern A. Zeeb 		return ret;
316c92544dSBjoern A. Zeeb 
326c92544dSBjoern A. Zeeb 	ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
336c92544dSBjoern A. Zeeb 	if (ret)
346c92544dSBjoern A. Zeeb 		return ret;
356c92544dSBjoern A. Zeeb 
366c92544dSBjoern A. Zeeb 	pci_set_master(pdev);
376c92544dSBjoern A. Zeeb 
386c92544dSBjoern A. Zeeb 	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
396c92544dSBjoern A. Zeeb 	if (ret < 0)
406c92544dSBjoern A. Zeeb 		return ret;
416c92544dSBjoern A. Zeeb 
426c92544dSBjoern A. Zeeb 	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
436c92544dSBjoern A. Zeeb 	if (ret)
446c92544dSBjoern A. Zeeb 		goto error;
456c92544dSBjoern A. Zeeb 
466c92544dSBjoern A. Zeeb 	mt76_pci_disable_aspm(pdev);
476c92544dSBjoern A. Zeeb 
486c92544dSBjoern A. Zeeb 	map = id->device == 0x7663 ? mt7663e_reg_map : mt7615e_reg_map;
496c92544dSBjoern A. Zeeb 	ret = mt7615_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
506c92544dSBjoern A. Zeeb 				pdev->irq, map);
516c92544dSBjoern A. Zeeb 	if (ret)
526c92544dSBjoern A. Zeeb 		goto error;
536c92544dSBjoern A. Zeeb 
546c92544dSBjoern A. Zeeb 	return 0;
556c92544dSBjoern A. Zeeb error:
566c92544dSBjoern A. Zeeb 	pci_free_irq_vectors(pdev);
576c92544dSBjoern A. Zeeb 
586c92544dSBjoern A. Zeeb 	return ret;
596c92544dSBjoern A. Zeeb }
606c92544dSBjoern A. Zeeb 
mt7615_pci_remove(struct pci_dev * pdev)616c92544dSBjoern A. Zeeb static void mt7615_pci_remove(struct pci_dev *pdev)
626c92544dSBjoern A. Zeeb {
636c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
646c92544dSBjoern A. Zeeb 	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
656c92544dSBjoern A. Zeeb 
666c92544dSBjoern A. Zeeb 	mt7615_unregister_device(dev);
676c92544dSBjoern A. Zeeb 	devm_free_irq(&pdev->dev, pdev->irq, dev);
686c92544dSBjoern A. Zeeb 	pci_free_irq_vectors(pdev);
696c92544dSBjoern A. Zeeb }
706c92544dSBjoern A. Zeeb 
716c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
mt7615_pci_suspend(struct pci_dev * pdev,pm_message_t state)726c92544dSBjoern A. Zeeb static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
736c92544dSBjoern A. Zeeb {
746c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
756c92544dSBjoern A. Zeeb 	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
766c92544dSBjoern A. Zeeb 	bool hif_suspend;
776c92544dSBjoern A. Zeeb 	int i, err;
786c92544dSBjoern A. Zeeb 
796c92544dSBjoern A. Zeeb 	err = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
806c92544dSBjoern A. Zeeb 	if (err < 0)
816c92544dSBjoern A. Zeeb 		return err;
826c92544dSBjoern A. Zeeb 
836c92544dSBjoern A. Zeeb 	hif_suspend = !test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
846c92544dSBjoern A. Zeeb 		      mt7615_firmware_offload(dev);
856c92544dSBjoern A. Zeeb 	if (hif_suspend) {
866c92544dSBjoern A. Zeeb 		err = mt76_connac_mcu_set_hif_suspend(mdev, true);
876c92544dSBjoern A. Zeeb 		if (err)
886c92544dSBjoern A. Zeeb 			return err;
896c92544dSBjoern A. Zeeb 	}
906c92544dSBjoern A. Zeeb 
916c92544dSBjoern A. Zeeb 	napi_disable(&mdev->tx_napi);
926c92544dSBjoern A. Zeeb 	mt76_worker_disable(&mdev->tx_worker);
936c92544dSBjoern A. Zeeb 
946c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
956c92544dSBjoern A. Zeeb 		napi_disable(&mdev->napi[i]);
966c92544dSBjoern A. Zeeb 	}
97*cbb3ec25SBjoern A. Zeeb 	tasklet_kill(&mdev->irq_tasklet);
986c92544dSBjoern A. Zeeb 
996c92544dSBjoern A. Zeeb 	mt7615_dma_reset(dev);
1006c92544dSBjoern A. Zeeb 
1016c92544dSBjoern A. Zeeb 	err = mt7615_wait_pdma_busy(dev);
1026c92544dSBjoern A. Zeeb 	if (err)
1036c92544dSBjoern A. Zeeb 		goto restore;
1046c92544dSBjoern A. Zeeb 
1056c92544dSBjoern A. Zeeb 	if (is_mt7663(mdev)) {
1066c92544dSBjoern A. Zeeb 		mt76_set(dev, MT_PDMA_SLP_PROT, MT_PDMA_AXI_SLPPROT_ENABLE);
1076c92544dSBjoern A. Zeeb 		if (!mt76_poll_msec(dev, MT_PDMA_SLP_PROT,
1086c92544dSBjoern A. Zeeb 				    MT_PDMA_AXI_SLPPROT_RDY,
1096c92544dSBjoern A. Zeeb 				    MT_PDMA_AXI_SLPPROT_RDY, 1000)) {
1106c92544dSBjoern A. Zeeb 			dev_err(mdev->dev, "PDMA sleep protection failed\n");
1116c92544dSBjoern A. Zeeb 			err = -EIO;
1126c92544dSBjoern A. Zeeb 			goto restore;
1136c92544dSBjoern A. Zeeb 		}
1146c92544dSBjoern A. Zeeb 	}
1156c92544dSBjoern A. Zeeb 
1166c92544dSBjoern A. Zeeb 	pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
1176c92544dSBjoern A. Zeeb 	pci_save_state(pdev);
1186c92544dSBjoern A. Zeeb 	err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
1196c92544dSBjoern A. Zeeb 	if (err)
1206c92544dSBjoern A. Zeeb 		goto restore;
1216c92544dSBjoern A. Zeeb 
1226c92544dSBjoern A. Zeeb 	err = mt7615_mcu_set_fw_ctrl(dev);
1236c92544dSBjoern A. Zeeb 	if (err)
1246c92544dSBjoern A. Zeeb 		goto restore;
1256c92544dSBjoern A. Zeeb 
1266c92544dSBjoern A. Zeeb 	return 0;
1276c92544dSBjoern A. Zeeb 
1286c92544dSBjoern A. Zeeb restore:
1296c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
1306c92544dSBjoern A. Zeeb 		napi_enable(&mdev->napi[i]);
1316c92544dSBjoern A. Zeeb 	}
1326c92544dSBjoern A. Zeeb 	napi_enable(&mdev->tx_napi);
1336c92544dSBjoern A. Zeeb 	if (hif_suspend)
1346c92544dSBjoern A. Zeeb 		mt76_connac_mcu_set_hif_suspend(mdev, false);
1356c92544dSBjoern A. Zeeb 
1366c92544dSBjoern A. Zeeb 	return err;
1376c92544dSBjoern A. Zeeb }
1386c92544dSBjoern A. Zeeb 
mt7615_pci_resume(struct pci_dev * pdev)1396c92544dSBjoern A. Zeeb static int mt7615_pci_resume(struct pci_dev *pdev)
1406c92544dSBjoern A. Zeeb {
1416c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = pci_get_drvdata(pdev);
1426c92544dSBjoern A. Zeeb 	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1436c92544dSBjoern A. Zeeb 	bool pdma_reset;
1446c92544dSBjoern A. Zeeb 	int i, err;
1456c92544dSBjoern A. Zeeb 
1466c92544dSBjoern A. Zeeb 	err = mt7615_mcu_set_drv_ctrl(dev);
1476c92544dSBjoern A. Zeeb 	if (err < 0)
1486c92544dSBjoern A. Zeeb 		return err;
1496c92544dSBjoern A. Zeeb 
1506c92544dSBjoern A. Zeeb 	err = pci_set_power_state(pdev, PCI_D0);
1516c92544dSBjoern A. Zeeb 	if (err)
1526c92544dSBjoern A. Zeeb 		return err;
1536c92544dSBjoern A. Zeeb 
1546c92544dSBjoern A. Zeeb 	pci_restore_state(pdev);
1556c92544dSBjoern A. Zeeb 
1566c92544dSBjoern A. Zeeb 	if (is_mt7663(&dev->mt76)) {
1576c92544dSBjoern A. Zeeb 		mt76_clear(dev, MT_PDMA_SLP_PROT, MT_PDMA_AXI_SLPPROT_ENABLE);
1586c92544dSBjoern A. Zeeb 		mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1);
1596c92544dSBjoern A. Zeeb 	}
1606c92544dSBjoern A. Zeeb 
1616c92544dSBjoern A. Zeeb 	pdma_reset = !mt76_rr(dev, MT_WPDMA_TX_RING0_CTRL0) &&
1626c92544dSBjoern A. Zeeb 		     !mt76_rr(dev, MT_WPDMA_TX_RING0_CTRL1);
1636c92544dSBjoern A. Zeeb 	if (pdma_reset)
1646c92544dSBjoern A. Zeeb 		dev_err(mdev->dev, "PDMA engine must be reinitialized\n");
1656c92544dSBjoern A. Zeeb 
1666c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->tx_worker);
1676c92544dSBjoern A. Zeeb 	local_bh_disable();
1686c92544dSBjoern A. Zeeb 	mt76_for_each_q_rx(mdev, i) {
1696c92544dSBjoern A. Zeeb 		napi_enable(&mdev->napi[i]);
1706c92544dSBjoern A. Zeeb 		napi_schedule(&mdev->napi[i]);
1716c92544dSBjoern A. Zeeb 	}
1726c92544dSBjoern A. Zeeb 	napi_enable(&mdev->tx_napi);
1736c92544dSBjoern A. Zeeb 	napi_schedule(&mdev->tx_napi);
1746c92544dSBjoern A. Zeeb 	local_bh_enable();
1756c92544dSBjoern A. Zeeb 
1766c92544dSBjoern A. Zeeb 	if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
1776c92544dSBjoern A. Zeeb 	    mt7615_firmware_offload(dev))
1786c92544dSBjoern A. Zeeb 		err = mt76_connac_mcu_set_hif_suspend(mdev, false);
1796c92544dSBjoern A. Zeeb 
1806c92544dSBjoern A. Zeeb 	return err;
1816c92544dSBjoern A. Zeeb }
1826c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
1836c92544dSBjoern A. Zeeb 
1846c92544dSBjoern A. Zeeb struct pci_driver mt7615_pci_driver = {
1856c92544dSBjoern A. Zeeb 	.name		= KBUILD_MODNAME,
1866c92544dSBjoern A. Zeeb 	.id_table	= mt7615_pci_device_table,
1876c92544dSBjoern A. Zeeb 	.probe		= mt7615_pci_probe,
1886c92544dSBjoern A. Zeeb 	.remove		= mt7615_pci_remove,
1896c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
1906c92544dSBjoern A. Zeeb 	.suspend	= mt7615_pci_suspend,
1916c92544dSBjoern A. Zeeb 	.resume		= mt7615_pci_resume,
1926c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
1936c92544dSBjoern A. Zeeb };
1946c92544dSBjoern A. Zeeb 
1956c92544dSBjoern A. Zeeb MODULE_DEVICE_TABLE(pci, mt7615_pci_device_table);
1966c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7615_FIRMWARE_CR4);
1976c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7615_FIRMWARE_N9);
1986c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7615_ROM_PATCH);
1996c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7663_OFFLOAD_FIRMWARE_N9);
2006c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7663_OFFLOAD_ROM_PATCH);
2016c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7663_FIRMWARE_N9);
2026c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7663_ROM_PATCH);
203