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