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