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 goto out; 46 } 47 hif = NULL; 48 49 out: 50 spin_unlock_bh(&hif_lock); 51 52 return hif; 53 } 54 55 static void mt7915_put_hif2(struct mt7915_hif *hif) 56 { 57 if (!hif) 58 return; 59 60 put_device(hif->dev); 61 } 62 63 static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev) 64 { 65 struct pci_dev *tmp_pdev; 66 67 hif_idx++; 68 69 tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL); 70 if (!tmp_pdev) { 71 tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL); 72 if (!tmp_pdev) 73 return NULL; 74 } 75 pci_dev_put(tmp_pdev); 76 77 writel(hif_idx | MT_PCIE_RECOG_ID_SEM, 78 pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID); 79 80 return mt7915_pci_get_hif2(hif_idx); 81 } 82 83 static int mt7915_pci_hif2_probe(struct pci_dev *pdev) 84 { 85 struct mt7915_hif *hif; 86 87 hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL); 88 if (!hif) 89 return -ENOMEM; 90 91 hif->dev = &pdev->dev; 92 hif->regs = pcim_iomap_table(pdev)[0]; 93 hif->irq = pdev->irq; 94 spin_lock_bh(&hif_lock); 95 list_add(&hif->list, &hif_list); 96 spin_unlock_bh(&hif_lock); 97 pci_set_drvdata(pdev, hif); 98 99 return 0; 100 } 101 102 static int mt7915_pci_probe(struct pci_dev *pdev, 103 const struct pci_device_id *id) 104 { 105 struct mt7915_hif *hif2 = NULL; 106 struct mt7915_dev *dev; 107 struct mt76_dev *mdev; 108 int irq; 109 int ret; 110 111 ret = pcim_enable_device(pdev); 112 if (ret) 113 return ret; 114 115 ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); 116 if (ret) 117 return ret; 118 119 pci_set_master(pdev); 120 121 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 122 if (ret) 123 return ret; 124 125 mt76_pci_disable_aspm(pdev); 126 127 if (id->device == 0x7916 || id->device == 0x790a) 128 return mt7915_pci_hif2_probe(pdev); 129 130 dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], 131 id->device); 132 if (IS_ERR(dev)) 133 return PTR_ERR(dev); 134 135 mdev = &dev->mt76; 136 mt7915_wfsys_reset(dev); 137 hif2 = mt7915_pci_init_hif2(pdev); 138 139 ret = mt7915_mmio_wed_init(dev, pdev, true, &irq); 140 if (ret < 0) 141 goto free_wed_or_irq_vector; 142 143 if (!ret) { 144 hif2 = mt7915_pci_init_hif2(pdev); 145 146 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 147 if (ret < 0) 148 goto free_device; 149 150 irq = pdev->irq; 151 } 152 153 ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler, 154 IRQF_SHARED, KBUILD_MODNAME, dev); 155 if (ret) 156 goto free_wed_or_irq_vector; 157 158 /* master switch of PCIe tnterrupt enable */ 159 mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 160 161 if (hif2) { 162 dev->hif2 = hif2; 163 164 mt76_wr(dev, MT_INT1_MASK_CSR, 0); 165 /* master switch of PCIe tnterrupt enable */ 166 if (is_mt7915(mdev)) 167 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); 168 else 169 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff); 170 171 ret = devm_request_irq(mdev->dev, dev->hif2->irq, 172 mt7915_irq_handler, IRQF_SHARED, 173 KBUILD_MODNAME "-hif", dev); 174 if (ret) 175 goto free_hif2; 176 } 177 178 ret = mt7915_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: 188 if (dev->hif2) 189 put_device(dev->hif2->dev); 190 devm_free_irq(mdev->dev, irq, dev); 191 free_wed_or_irq_vector: 192 if (mtk_wed_device_active(&mdev->mmio.wed)) 193 mtk_wed_device_detach(&mdev->mmio.wed); 194 else 195 pci_free_irq_vectors(pdev); 196 free_device: 197 mt76_free_device(&dev->mt76); 198 199 return ret; 200 } 201 202 static void mt7915_hif_remove(struct pci_dev *pdev) 203 { 204 struct mt7915_hif *hif = pci_get_drvdata(pdev); 205 206 list_del(&hif->list); 207 } 208 209 static void mt7915_pci_remove(struct pci_dev *pdev) 210 { 211 struct mt76_dev *mdev; 212 struct mt7915_dev *dev; 213 214 mdev = pci_get_drvdata(pdev); 215 dev = container_of(mdev, struct mt7915_dev, mt76); 216 mt7915_put_hif2(dev->hif2); 217 mt7915_unregister_device(dev); 218 } 219 220 struct pci_driver mt7915_hif_driver = { 221 .name = KBUILD_MODNAME "_hif", 222 .id_table = mt7915_hif_device_table, 223 .probe = mt7915_pci_probe, 224 .remove = mt7915_hif_remove, 225 }; 226 227 struct pci_driver mt7915_pci_driver = { 228 .name = KBUILD_MODNAME, 229 .id_table = mt7915_pci_device_table, 230 .probe = mt7915_pci_probe, 231 .remove = mt7915_pci_remove, 232 }; 233 234 MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table); 235 MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table); 236 MODULE_FIRMWARE(MT7915_FIRMWARE_WA); 237 MODULE_FIRMWARE(MT7915_FIRMWARE_WM); 238 MODULE_FIRMWARE(MT7915_ROM_PATCH); 239 MODULE_FIRMWARE(MT7916_FIRMWARE_WA); 240 MODULE_FIRMWARE(MT7916_FIRMWARE_WM); 241 MODULE_FIRMWARE(MT7916_ROM_PATCH); 242