pci.c (6701B)
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 15static bool wed_enable = false; 16module_param(wed_enable, bool, 0644); 17 18static LIST_HEAD(hif_list); 19static DEFINE_SPINLOCK(hif_lock); 20static u32 hif_idx; 21 22static const struct pci_device_id mt7915_pci_device_table[] = { 23 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) }, 24 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7906) }, 25 { }, 26}; 27 28static const struct pci_device_id mt7915_hif_device_table[] = { 29 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) }, 30 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x790a) }, 31 { }, 32}; 33 34static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx) 35{ 36 struct mt7915_hif *hif; 37 u32 val; 38 39 spin_lock_bh(&hif_lock); 40 41 list_for_each_entry(hif, &hif_list, list) { 42 val = readl(hif->regs + MT_PCIE_RECOG_ID); 43 val &= MT_PCIE_RECOG_ID_MASK; 44 if (val != idx) 45 continue; 46 47 get_device(hif->dev); 48 goto out; 49 } 50 hif = NULL; 51 52out: 53 spin_unlock_bh(&hif_lock); 54 55 return hif; 56} 57 58static void mt7915_put_hif2(struct mt7915_hif *hif) 59{ 60 if (!hif) 61 return; 62 63 put_device(hif->dev); 64} 65 66static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev) 67{ 68 hif_idx++; 69 if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL) && 70 !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, 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 mt7915_pci_get_hif2(hif_idx); 77} 78 79static int mt7915_pci_hif2_probe(struct pci_dev *pdev) 80{ 81 struct mt7915_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 spin_lock_bh(&hif_lock); 91 list_add(&hif->list, &hif_list); 92 spin_unlock_bh(&hif_lock); 93 pci_set_drvdata(pdev, hif); 94 95 return 0; 96} 97 98#ifdef CONFIG_NET_MEDIATEK_SOC_WED 99static int mt7915_wed_offload_enable(struct mtk_wed_device *wed) 100{ 101 struct mt7915_dev *dev; 102 int ret; 103 104 dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); 105 106 spin_lock_bh(&dev->mt76.token_lock); 107 dev->mt76.token_size = wed->wlan.token_start; 108 spin_unlock_bh(&dev->mt76.token_lock); 109 110 ret = wait_event_timeout(dev->mt76.tx_wait, 111 !dev->mt76.wed_token_count, HZ); 112 if (!ret) 113 return -EAGAIN; 114 115 return 0; 116} 117 118static void mt7915_wed_offload_disable(struct mtk_wed_device *wed) 119{ 120 struct mt7915_dev *dev; 121 122 dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); 123 124 spin_lock_bh(&dev->mt76.token_lock); 125 dev->mt76.token_size = MT7915_TOKEN_SIZE; 126 spin_unlock_bh(&dev->mt76.token_lock); 127} 128#endif 129 130static int 131mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq) 132{ 133#ifdef CONFIG_NET_MEDIATEK_SOC_WED 134 struct mtk_wed_device *wed = &dev->mt76.mmio.wed; 135 int ret; 136 137 if (!wed_enable) 138 return 0; 139 140 wed->wlan.pci_dev = pdev; 141 wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) + 142 MT_WFDMA_EXT_CSR_BASE; 143 wed->wlan.nbuf = 4096; 144 wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf; 145 wed->wlan.init_buf = mt7915_wed_init_buf; 146 wed->wlan.offload_enable = mt7915_wed_offload_enable; 147 wed->wlan.offload_disable = mt7915_wed_offload_disable; 148 149 if (mtk_wed_device_attach(wed) != 0) 150 return 0; 151 152 *irq = wed->irq; 153 dev->mt76.dma_dev = wed->dev; 154 155 ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32)); 156 if (ret) 157 return ret; 158 159 return 1; 160#else 161 return 0; 162#endif 163} 164 165static int mt7915_pci_probe(struct pci_dev *pdev, 166 const struct pci_device_id *id) 167{ 168 struct mt7915_hif *hif2 = NULL; 169 struct mt7915_dev *dev; 170 struct mt76_dev *mdev; 171 int irq; 172 int ret; 173 174 ret = pcim_enable_device(pdev); 175 if (ret) 176 return ret; 177 178 ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); 179 if (ret) 180 return ret; 181 182 pci_set_master(pdev); 183 184 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 185 if (ret) 186 return ret; 187 188 mt76_pci_disable_aspm(pdev); 189 190 if (id->device == 0x7916 || id->device == 0x790a) 191 return mt7915_pci_hif2_probe(pdev); 192 193 dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], 194 id->device); 195 if (IS_ERR(dev)) 196 return PTR_ERR(dev); 197 198 mdev = &dev->mt76; 199 mt7915_wfsys_reset(dev); 200 hif2 = mt7915_pci_init_hif2(pdev); 201 202 ret = mt7915_pci_wed_init(dev, pdev, &irq); 203 if (ret < 0) 204 goto free_wed_or_irq_vector; 205 206 if (!ret) { 207 hif2 = mt7915_pci_init_hif2(pdev); 208 209 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 210 if (ret < 0) 211 goto free_device; 212 213 irq = pdev->irq; 214 } 215 216 ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler, 217 IRQF_SHARED, KBUILD_MODNAME, dev); 218 if (ret) 219 goto free_wed_or_irq_vector; 220 221 /* master switch of PCIe tnterrupt enable */ 222 mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 223 224 if (hif2) { 225 dev->hif2 = hif2; 226 227 mt76_wr(dev, MT_INT1_MASK_CSR, 0); 228 /* master switch of PCIe tnterrupt enable */ 229 if (is_mt7915(mdev)) 230 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); 231 else 232 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff); 233 234 ret = devm_request_irq(mdev->dev, dev->hif2->irq, 235 mt7915_irq_handler, IRQF_SHARED, 236 KBUILD_MODNAME "-hif", dev); 237 if (ret) 238 goto free_hif2; 239 } 240 241 ret = mt7915_register_device(dev); 242 if (ret) 243 goto free_hif2_irq; 244 245 return 0; 246 247free_hif2_irq: 248 if (dev->hif2) 249 devm_free_irq(mdev->dev, dev->hif2->irq, dev); 250free_hif2: 251 if (dev->hif2) 252 put_device(dev->hif2->dev); 253 devm_free_irq(mdev->dev, irq, dev); 254free_wed_or_irq_vector: 255 if (mtk_wed_device_active(&mdev->mmio.wed)) 256 mtk_wed_device_detach(&mdev->mmio.wed); 257 else 258 pci_free_irq_vectors(pdev); 259free_device: 260 mt76_free_device(&dev->mt76); 261 262 return ret; 263} 264 265static void mt7915_hif_remove(struct pci_dev *pdev) 266{ 267 struct mt7915_hif *hif = pci_get_drvdata(pdev); 268 269 list_del(&hif->list); 270} 271 272static void mt7915_pci_remove(struct pci_dev *pdev) 273{ 274 struct mt76_dev *mdev; 275 struct mt7915_dev *dev; 276 277 mdev = pci_get_drvdata(pdev); 278 dev = container_of(mdev, struct mt7915_dev, mt76); 279 mt7915_put_hif2(dev->hif2); 280 mt7915_unregister_device(dev); 281} 282 283struct pci_driver mt7915_hif_driver = { 284 .name = KBUILD_MODNAME "_hif", 285 .id_table = mt7915_hif_device_table, 286 .probe = mt7915_pci_probe, 287 .remove = mt7915_hif_remove, 288}; 289 290struct pci_driver mt7915_pci_driver = { 291 .name = KBUILD_MODNAME, 292 .id_table = mt7915_pci_device_table, 293 .probe = mt7915_pci_probe, 294 .remove = mt7915_pci_remove, 295}; 296 297MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table); 298MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table); 299MODULE_FIRMWARE(MT7915_FIRMWARE_WA); 300MODULE_FIRMWARE(MT7915_FIRMWARE_WM); 301MODULE_FIRMWARE(MT7915_ROM_PATCH); 302MODULE_FIRMWARE(MT7916_FIRMWARE_WA); 303MODULE_FIRMWARE(MT7916_FIRMWARE_WM); 304MODULE_FIRMWARE(MT7916_ROM_PATCH);