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 { }, 25 }; 26 27 static const struct pci_device_id mt7996_hif_device_table[] = { 28 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7991) }, 29 { }, 30 }; 31 32 static 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 #if defined(__linux__) 41 val = readl(hif->regs + MT_PCIE_RECOG_ID); 42 #elif defined(__FreeBSD__) 43 val = readl((u8 *)hif->regs + MT_PCIE_RECOG_ID); 44 #endif 45 val &= MT_PCIE_RECOG_ID_MASK; 46 if (val != idx) 47 continue; 48 49 get_device(hif->dev); 50 goto out; 51 } 52 hif = NULL; 53 54 out: 55 spin_unlock_bh(&hif_lock); 56 57 return hif; 58 } 59 60 static void mt7996_put_hif2(struct mt7996_hif *hif) 61 { 62 if (!hif) 63 return; 64 65 put_device(hif->dev); 66 } 67 68 static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev) 69 { 70 hif_idx++; 71 #if defined(__linux__) 72 if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL)) 73 #elif defined(__FreeBSD__) 74 if (!linuxkpi_pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL)) 75 #endif 76 return NULL; 77 78 writel(hif_idx | MT_PCIE_RECOG_ID_SEM, 79 #if defined(__linux__) 80 pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID); 81 #elif defined(__FreeBSD__) 82 (u8 *)(pcim_iomap_table(pdev)[0]) + MT_PCIE_RECOG_ID); 83 #endif 84 85 return mt7996_pci_get_hif2(hif_idx); 86 } 87 88 static int mt7996_pci_hif2_probe(struct pci_dev *pdev) 89 { 90 struct mt7996_hif *hif; 91 92 hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL); 93 if (!hif) 94 return -ENOMEM; 95 96 hif->dev = &pdev->dev; 97 hif->regs = pcim_iomap_table(pdev)[0]; 98 hif->irq = pdev->irq; 99 spin_lock_bh(&hif_lock); 100 list_add(&hif->list, &hif_list); 101 spin_unlock_bh(&hif_lock); 102 pci_set_drvdata(pdev, hif); 103 104 return 0; 105 } 106 107 static int mt7996_pci_probe(struct pci_dev *pdev, 108 const struct pci_device_id *id) 109 { 110 struct pci_dev *hif2_dev; 111 struct mt7996_dev *dev; 112 struct mt76_dev *mdev; 113 struct mt7996_hif *hif2; 114 int irq, ret; 115 116 ret = pcim_enable_device(pdev); 117 if (ret) 118 return ret; 119 120 ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); 121 if (ret) 122 return ret; 123 124 pci_set_master(pdev); 125 126 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 127 if (ret) 128 return ret; 129 130 mt76_pci_disable_aspm(pdev); 131 132 if (id->device == 0x7991) 133 return mt7996_pci_hif2_probe(pdev); 134 135 dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], 136 id->device); 137 if (IS_ERR(dev)) 138 return PTR_ERR(dev); 139 140 mdev = &dev->mt76; 141 mt7996_wfsys_reset(dev); 142 hif2 = mt7996_pci_init_hif2(pdev); 143 144 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 145 if (ret < 0) 146 goto free_device; 147 148 irq = pdev->irq; 149 ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler, 150 IRQF_SHARED, KBUILD_MODNAME, dev); 151 if (ret) 152 goto free_irq_vector; 153 154 mt76_wr(dev, MT_INT_MASK_CSR, 0); 155 /* master switch of PCIe tnterrupt enable */ 156 mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 157 158 if (hif2) { 159 hif2_dev = container_of(hif2->dev, struct pci_dev, dev); 160 dev->hif2 = hif2; 161 162 ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES); 163 if (ret < 0) 164 goto free_hif2; 165 166 dev->hif2->irq = hif2_dev->irq; 167 ret = devm_request_irq(mdev->dev, dev->hif2->irq, 168 mt7996_irq_handler, IRQF_SHARED, 169 KBUILD_MODNAME "-hif", dev); 170 if (ret) 171 goto free_hif2_irq_vector; 172 173 mt76_wr(dev, MT_INT1_MASK_CSR, 0); 174 /* master switch of PCIe tnterrupt enable */ 175 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); 176 } 177 178 ret = mt7996_register_device(dev); 179 if (ret) 180 goto free_hif2_irq; 181 182 return 0; 183 184 free_hif2_irq: 185 if (dev->hif2) 186 devm_free_irq(mdev->dev, dev->hif2->irq, dev); 187 free_hif2_irq_vector: 188 if (dev->hif2) 189 pci_free_irq_vectors(hif2_dev); 190 free_hif2: 191 if (dev->hif2) 192 put_device(dev->hif2->dev); 193 devm_free_irq(mdev->dev, irq, dev); 194 free_irq_vector: 195 pci_free_irq_vectors(pdev); 196 free_device: 197 mt76_free_device(&dev->mt76); 198 199 return ret; 200 } 201 202 static void mt7996_hif_remove(struct pci_dev *pdev) 203 { 204 struct mt7996_hif *hif = pci_get_drvdata(pdev); 205 206 list_del(&hif->list); 207 } 208 209 static void mt7996_pci_remove(struct pci_dev *pdev) 210 { 211 struct mt76_dev *mdev; 212 struct mt7996_dev *dev; 213 214 mdev = pci_get_drvdata(pdev); 215 dev = container_of(mdev, struct mt7996_dev, mt76); 216 mt7996_put_hif2(dev->hif2); 217 mt7996_unregister_device(dev); 218 } 219 220 struct pci_driver mt7996_hif_driver = { 221 .name = KBUILD_MODNAME "_hif", 222 .id_table = mt7996_hif_device_table, 223 .probe = mt7996_pci_probe, 224 .remove = mt7996_hif_remove, 225 }; 226 227 struct pci_driver mt7996_pci_driver = { 228 .name = KBUILD_MODNAME, 229 .id_table = mt7996_pci_device_table, 230 .probe = mt7996_pci_probe, 231 .remove = mt7996_pci_remove, 232 }; 233 234 MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table); 235 MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table); 236 MODULE_FIRMWARE(MT7996_FIRMWARE_WA); 237 MODULE_FIRMWARE(MT7996_FIRMWARE_WM); 238 MODULE_FIRMWARE(MT7996_FIRMWARE_DSP); 239 MODULE_FIRMWARE(MT7996_ROM_PATCH); 240 #if defined(__FreeBSD__) 241 MODULE_VERSION(mt7996_pci, 1); 242 MODULE_DEPEND(mt7996_pci, linuxkpi, 1, 1, 1); 243 MODULE_DEPEND(mt7996_pci, linuxkpi_wlan, 1, 1, 1); 244 MODULE_DEPEND(mt7996_pci, mt76_core, 1, 1, 1); 245 #endif 246