1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2020 MediaTek Inc. 3 * 4 * Author: Ryder Lee <ryder.lee@mediatek.com> 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/pci.h> 10 11 #include "mt7915.h" 12 #include "mac.h" 13 #include "../trace.h" 14 15 static LIST_HEAD(hif_list); 16 static DEFINE_SPINLOCK(hif_lock); 17 static u32 hif_idx; 18 19 static const struct pci_device_id mt7915_pci_device_table[] = { 20 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) }, 21 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7906) }, 22 { }, 23 }; 24 25 static const struct pci_device_id mt7915_hif_device_table[] = { 26 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) }, 27 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x790a) }, 28 { }, 29 }; 30 31 static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx) 32 { 33 struct mt7915_hif *hif; 34 u32 val; 35 36 spin_lock_bh(&hif_lock); 37 38 list_for_each_entry(hif, &hif_list, list) { 39 val = readl(hif->regs + MT_PCIE_RECOG_ID); 40 val &= MT_PCIE_RECOG_ID_MASK; 41 if (val != idx) 42 continue; 43 44 get_device(hif->dev); 45 hif->index = idx; 46 goto out; 47 } 48 hif = NULL; 49 50 out: 51 spin_unlock_bh(&hif_lock); 52 53 return hif; 54 } 55 56 static void mt7915_put_hif2(struct mt7915_hif *hif) 57 { 58 if (!hif) 59 return; 60 61 put_device(hif->dev); 62 } 63 64 static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev) 65 { 66 struct pci_dev *tmp_pdev; 67 68 hif_idx++; 69 70 tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL); 71 if (!tmp_pdev) { 72 tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL); 73 if (!tmp_pdev) 74 return NULL; 75 } 76 pci_dev_put(tmp_pdev); 77 78 writel(hif_idx | MT_PCIE_RECOG_ID_SEM, 79 pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID); 80 81 return mt7915_pci_get_hif2(hif_idx); 82 } 83 84 static int mt7915_pci_hif2_probe(struct pci_dev *pdev) 85 { 86 struct mt7915_hif *hif; 87 88 hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL); 89 if (!hif) 90 return -ENOMEM; 91 92 hif->dev = &pdev->dev; 93 hif->regs = pcim_iomap_table(pdev)[0]; 94 hif->irq = pdev->irq; 95 spin_lock_bh(&hif_lock); 96 list_add(&hif->list, &hif_list); 97 spin_unlock_bh(&hif_lock); 98 pci_set_drvdata(pdev, hif); 99 100 return 0; 101 } 102 103 static int mt7915_pci_probe(struct pci_dev *pdev, 104 const struct pci_device_id *id) 105 { 106 struct mt7915_hif *hif2 = NULL; 107 struct mt7915_dev *dev; 108 struct mt76_dev *mdev; 109 int irq; 110 int ret; 111 112 ret = pcim_enable_device(pdev); 113 if (ret) 114 return ret; 115 116 ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); 117 if (ret) 118 return ret; 119 120 pci_set_master(pdev); 121 122 ret = dma_set_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 == 0x7916 || id->device == 0x790a) 129 return mt7915_pci_hif2_probe(pdev); 130 131 dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], 132 id->device); 133 if (IS_ERR(dev)) 134 return PTR_ERR(dev); 135 136 mdev = &dev->mt76; 137 mt7915_wfsys_reset(dev); 138 hif2 = mt7915_pci_init_hif2(pdev); 139 140 ret = mt7915_mmio_wed_init(dev, pdev, true, &irq); 141 if (ret < 0) 142 goto free_wed_or_irq_vector; 143 144 if (!ret) { 145 hif2 = mt7915_pci_init_hif2(pdev); 146 147 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 148 if (ret < 0) 149 goto free_device; 150 151 irq = pdev->irq; 152 } 153 154 ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler, 155 IRQF_SHARED, KBUILD_MODNAME, dev); 156 if (ret) 157 goto free_wed_or_irq_vector; 158 159 /* master switch of PCIe tnterrupt enable */ 160 mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 161 162 if (hif2) { 163 dev->hif2 = hif2; 164 165 mt76_wr(dev, MT_INT1_MASK_CSR, 0); 166 /* master switch of PCIe tnterrupt enable */ 167 if (is_mt7915(mdev)) 168 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); 169 else 170 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff); 171 172 ret = devm_request_irq(mdev->dev, dev->hif2->irq, 173 mt7915_irq_handler, IRQF_SHARED, 174 KBUILD_MODNAME "-hif", dev); 175 if (ret) 176 goto free_hif2; 177 } 178 179 ret = mt7915_register_device(dev); 180 if (ret) 181 goto free_hif2_irq; 182 183 return 0; 184 185 free_hif2_irq: 186 if (dev->hif2) 187 devm_free_irq(mdev->dev, dev->hif2->irq, dev); 188 free_hif2: 189 if (dev->hif2) 190 put_device(dev->hif2->dev); 191 devm_free_irq(mdev->dev, irq, dev); 192 free_wed_or_irq_vector: 193 if (mtk_wed_device_active(&mdev->mmio.wed)) 194 mtk_wed_device_detach(&mdev->mmio.wed); 195 else 196 pci_free_irq_vectors(pdev); 197 free_device: 198 mt76_free_device(&dev->mt76); 199 200 return ret; 201 } 202 203 static void mt7915_hif_remove(struct pci_dev *pdev) 204 { 205 struct mt7915_hif *hif = pci_get_drvdata(pdev); 206 207 list_del(&hif->list); 208 } 209 210 static void mt7915_pci_remove(struct pci_dev *pdev) 211 { 212 struct mt76_dev *mdev; 213 struct mt7915_dev *dev; 214 215 mdev = pci_get_drvdata(pdev); 216 dev = container_of(mdev, struct mt7915_dev, mt76); 217 mt7915_put_hif2(dev->hif2); 218 mt7915_unregister_device(dev); 219 } 220 221 struct pci_driver mt7915_hif_driver = { 222 .name = KBUILD_MODNAME "_hif", 223 .id_table = mt7915_hif_device_table, 224 .probe = mt7915_pci_probe, 225 .remove = mt7915_hif_remove, 226 }; 227 228 struct pci_driver mt7915_pci_driver = { 229 .name = KBUILD_MODNAME, 230 .id_table = mt7915_pci_device_table, 231 .probe = mt7915_pci_probe, 232 .remove = mt7915_pci_remove, 233 }; 234 235 MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table); 236 MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table); 237 MODULE_FIRMWARE(MT7915_FIRMWARE_WA); 238 MODULE_FIRMWARE(MT7915_FIRMWARE_WM); 239 MODULE_FIRMWARE(MT7915_ROM_PATCH); 240 MODULE_FIRMWARE(MT7916_FIRMWARE_WA); 241 MODULE_FIRMWARE(MT7916_FIRMWARE_WM); 242 MODULE_FIRMWARE(MT7916_ROM_PATCH); 243