259 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (C) 2022 MediaTek Inc.4 */5 6#include <linux/kernel.h>7#include <linux/module.h>8#include <linux/pci.h>9 10#include "mt7996.h"11#include "mac.h"12#include "../trace.h"13 14static LIST_HEAD(hif_list);15static DEFINE_SPINLOCK(hif_lock);16static u32 hif_idx;17 18static const struct pci_device_id mt7996_pci_device_table[] = {19 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7990) },20 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7992) },21 { },22};23 24static const struct pci_device_id mt7996_hif_device_table[] = {25 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7991) },26 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x799a) },27 { },28};29 30static struct mt7996_hif *mt7996_pci_get_hif2(u32 idx)31{32 struct mt7996_hif *hif;33 u32 val;34 35 spin_lock_bh(&hif_lock);36 37 list_for_each_entry(hif, &hif_list, list) {38 val = readl(hif->regs + MT_PCIE_RECOG_ID);39 val &= MT_PCIE_RECOG_ID_MASK;40 if (val != idx)41 continue;42 43 get_device(hif->dev);44 goto out;45 }46 hif = NULL;47 48out:49 spin_unlock_bh(&hif_lock);50 51 return hif;52}53 54static void mt7996_put_hif2(struct mt7996_hif *hif)55{56 if (!hif)57 return;58 59 put_device(hif->dev);60}61 62static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev)63{64 hif_idx++;65 66 if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL) &&67 !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x799a, NULL))68 return NULL;69 70 writel(hif_idx | MT_PCIE_RECOG_ID_SEM,71 pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID);72 73 return mt7996_pci_get_hif2(hif_idx);74}75 76static int mt7996_pci_hif2_probe(struct pci_dev *pdev)77{78 struct mt7996_hif *hif;79 80 hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);81 if (!hif)82 return -ENOMEM;83 84 hif->dev = &pdev->dev;85 hif->regs = pcim_iomap_table(pdev)[0];86 hif->irq = pdev->irq;87 spin_lock_bh(&hif_lock);88 list_add(&hif->list, &hif_list);89 spin_unlock_bh(&hif_lock);90 pci_set_drvdata(pdev, hif);91 92 return 0;93}94 95static int mt7996_pci_probe(struct pci_dev *pdev,96 const struct pci_device_id *id)97{98 struct pci_dev *hif2_dev;99 struct mt7996_hif *hif2;100 struct mt7996_dev *dev;101 int irq, hif2_irq, ret;102 struct mt76_dev *mdev;103 104 ret = pcim_enable_device(pdev);105 if (ret)106 return ret;107 108 ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));109 if (ret)110 return ret;111 112 pci_set_master(pdev);113 114 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));115 if (ret)116 return ret;117 118 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));119 if (ret)120 return ret;121 122 mt76_pci_disable_aspm(pdev);123 124 if (id->device == 0x7991 || id->device == 0x799a)125 return mt7996_pci_hif2_probe(pdev);126 127 dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],128 id->device);129 if (IS_ERR(dev))130 return PTR_ERR(dev);131 132 mdev = &dev->mt76;133 mt7996_wfsys_reset(dev);134 hif2 = mt7996_pci_init_hif2(pdev);135 136 ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);137 if (ret < 0)138 goto free_wed_or_irq_vector;139 140 if (!ret) {141 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);142 if (ret < 0)143 goto free_device;144 145 irq = pdev->irq;146 }147 148 ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,149 IRQF_SHARED, KBUILD_MODNAME, dev);150 if (ret)151 goto free_wed_or_irq_vector;152 153 mt76_wr(dev, MT_INT_MASK_CSR, 0);154 /* master switch of PCIe tnterrupt enable */155 mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);156 157 if (hif2) {158 hif2_dev = container_of(hif2->dev, struct pci_dev, dev);159 dev->hif2 = hif2;160 161 ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &hif2_irq);162 if (ret < 0)163 goto free_hif2_wed_irq_vector;164 165 if (!ret) {166 ret = pci_alloc_irq_vectors(hif2_dev, 1, 1,167 PCI_IRQ_ALL_TYPES);168 if (ret < 0)169 goto free_hif2;170 171 dev->hif2->irq = hif2_dev->irq;172 hif2_irq = dev->hif2->irq;173 }174 175 ret = devm_request_irq(mdev->dev, hif2_irq, mt7996_irq_handler,176 IRQF_SHARED, KBUILD_MODNAME "-hif",177 dev);178 if (ret)179 goto free_hif2_wed_irq_vector;180 181 mt76_wr(dev, MT_INT1_MASK_CSR, 0);182 /* master switch of PCIe tnterrupt enable */183 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);184 }185 186 ret = mt7996_register_device(dev);187 if (ret)188 goto free_hif2_irq;189 190 return 0;191 192free_hif2_irq:193 if (dev->hif2)194 devm_free_irq(mdev->dev, hif2_irq, dev);195free_hif2_wed_irq_vector:196 if (dev->hif2) {197 if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))198 mtk_wed_device_detach(&dev->mt76.mmio.wed_hif2);199 else200 pci_free_irq_vectors(hif2_dev);201 }202free_hif2:203 if (dev->hif2)204 put_device(dev->hif2->dev);205 devm_free_irq(mdev->dev, irq, dev);206free_wed_or_irq_vector:207 if (mtk_wed_device_active(&dev->mt76.mmio.wed))208 mtk_wed_device_detach(&dev->mt76.mmio.wed);209 else210 pci_free_irq_vectors(pdev);211free_device:212 mt76_free_device(&dev->mt76);213 214 return ret;215}216 217static void mt7996_hif_remove(struct pci_dev *pdev)218{219 struct mt7996_hif *hif = pci_get_drvdata(pdev);220 221 list_del(&hif->list);222}223 224static void mt7996_pci_remove(struct pci_dev *pdev)225{226 struct mt76_dev *mdev;227 struct mt7996_dev *dev;228 229 mdev = pci_get_drvdata(pdev);230 dev = container_of(mdev, struct mt7996_dev, mt76);231 mt7996_put_hif2(dev->hif2);232 mt7996_unregister_device(dev);233}234 235struct pci_driver mt7996_hif_driver = {236 .name = KBUILD_MODNAME "_hif",237 .id_table = mt7996_hif_device_table,238 .probe = mt7996_pci_probe,239 .remove = mt7996_hif_remove,240};241 242struct pci_driver mt7996_pci_driver = {243 .name = KBUILD_MODNAME,244 .id_table = mt7996_pci_device_table,245 .probe = mt7996_pci_probe,246 .remove = mt7996_pci_remove,247};248 249MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);250MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);251MODULE_FIRMWARE(MT7996_FIRMWARE_WA);252MODULE_FIRMWARE(MT7996_FIRMWARE_WM);253MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);254MODULE_FIRMWARE(MT7996_ROM_PATCH);255MODULE_FIRMWARE(MT7992_FIRMWARE_WA);256MODULE_FIRMWARE(MT7992_FIRMWARE_WM);257MODULE_FIRMWARE(MT7992_FIRMWARE_DSP);258MODULE_FIRMWARE(MT7992_ROM_PATCH);259