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