1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2020 MediaTek Inc. 3 * 4 * Author: Ryder Lee <ryder.lee@mediatek.com> 5 */ 6 7 #if defined(__FreeBSD__) 8 #define LINUXKPI_PARAM_PREFIX mt7915_pci_ 9 #endif 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/pci.h> 14 15 #include "mt7915.h" 16 #include "mac.h" 17 #include "../trace.h" 18 19 static bool wed_enable = false; 20 module_param(wed_enable, bool, 0644); 21 #if defined(__FreeBSD__) 22 MODULE_PARM_DESC(wed_enable, "WED enabled"); 23 #endif 24 25 #if defined(__linux__) 26 static LIST_HEAD(hif_list); 27 #elif defined(__FreeBSD__) 28 static LINUX_LIST_HEAD(hif_list); 29 #endif 30 static DEFINE_SPINLOCK(hif_lock); 31 static u32 hif_idx; 32 33 static const struct pci_device_id mt7915_pci_device_table[] = { 34 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) }, 35 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7906) }, 36 { }, 37 }; 38 39 static const struct pci_device_id mt7915_hif_device_table[] = { 40 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) }, 41 { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x790a) }, 42 { }, 43 }; 44 45 static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx) 46 { 47 struct mt7915_hif *hif; 48 u32 val; 49 50 spin_lock_bh(&hif_lock); 51 52 list_for_each_entry(hif, &hif_list, list) { 53 #if defined(__linux__) 54 val = readl(hif->regs + MT_PCIE_RECOG_ID); 55 #elif defined(__FreeBSD__) 56 val = readl((u8 *)hif->regs + MT_PCIE_RECOG_ID); 57 #endif 58 val &= MT_PCIE_RECOG_ID_MASK; 59 if (val != idx) 60 continue; 61 62 get_device(hif->dev); 63 goto out; 64 } 65 hif = NULL; 66 67 out: 68 spin_unlock_bh(&hif_lock); 69 70 return hif; 71 } 72 73 static void mt7915_put_hif2(struct mt7915_hif *hif) 74 { 75 if (!hif) 76 return; 77 78 put_device(hif->dev); 79 } 80 81 static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev) 82 { 83 hif_idx++; 84 #if defined(__linux__) 85 if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL) && 86 !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL)) 87 #elif defined(__FreeBSD__) 88 if (!linuxkpi_pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL) && 89 !linuxkpi_pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL)) 90 #endif 91 return NULL; 92 93 writel(hif_idx | MT_PCIE_RECOG_ID_SEM, 94 #if defined(__linux__) 95 pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID); 96 #elif defined(__FreeBSD__) 97 (u8 *)(pcim_iomap_table(pdev)[0]) + MT_PCIE_RECOG_ID); 98 #endif 99 100 return mt7915_pci_get_hif2(hif_idx); 101 } 102 103 static int mt7915_pci_hif2_probe(struct pci_dev *pdev) 104 { 105 struct mt7915_hif *hif; 106 107 hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL); 108 if (!hif) 109 return -ENOMEM; 110 111 hif->dev = &pdev->dev; 112 hif->regs = pcim_iomap_table(pdev)[0]; 113 hif->irq = pdev->irq; 114 spin_lock_bh(&hif_lock); 115 list_add(&hif->list, &hif_list); 116 spin_unlock_bh(&hif_lock); 117 pci_set_drvdata(pdev, hif); 118 119 return 0; 120 } 121 122 #ifdef CONFIG_NET_MEDIATEK_SOC_WED 123 static int mt7915_wed_offload_enable(struct mtk_wed_device *wed) 124 { 125 struct mt7915_dev *dev; 126 struct mt7915_phy *phy; 127 int ret; 128 129 dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); 130 131 spin_lock_bh(&dev->mt76.token_lock); 132 dev->mt76.token_size = wed->wlan.token_start; 133 spin_unlock_bh(&dev->mt76.token_lock); 134 135 ret = wait_event_timeout(dev->mt76.tx_wait, 136 !dev->mt76.wed_token_count, HZ); 137 if (!ret) 138 return -EAGAIN; 139 140 phy = &dev->phy; 141 mt76_set(dev, MT_AGG_ACR4(phy->band_idx), MT_AGG_ACR_PPDU_TXS2H); 142 143 phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; 144 if (phy) 145 mt76_set(dev, MT_AGG_ACR4(phy->band_idx), 146 MT_AGG_ACR_PPDU_TXS2H); 147 148 return 0; 149 } 150 151 static void mt7915_wed_offload_disable(struct mtk_wed_device *wed) 152 { 153 struct mt7915_dev *dev; 154 struct mt7915_phy *phy; 155 156 dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); 157 158 spin_lock_bh(&dev->mt76.token_lock); 159 dev->mt76.token_size = MT7915_TOKEN_SIZE; 160 spin_unlock_bh(&dev->mt76.token_lock); 161 162 /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than 163 * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set. 164 */ 165 phy = &dev->phy; 166 mt76_clear(dev, MT_AGG_ACR4(phy->band_idx), MT_AGG_ACR_PPDU_TXS2H); 167 168 phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; 169 if (phy) 170 mt76_clear(dev, MT_AGG_ACR4(phy->band_idx), 171 MT_AGG_ACR_PPDU_TXS2H); 172 } 173 #endif 174 175 static int 176 mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq) 177 { 178 #ifdef CONFIG_NET_MEDIATEK_SOC_WED 179 struct mtk_wed_device *wed = &dev->mt76.mmio.wed; 180 int ret; 181 182 if (!wed_enable) 183 return 0; 184 185 wed->wlan.pci_dev = pdev; 186 wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) + 187 MT_WFDMA_EXT_CSR_BASE; 188 wed->wlan.nbuf = 4096; 189 wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf; 190 wed->wlan.init_buf = mt7915_wed_init_buf; 191 wed->wlan.offload_enable = mt7915_wed_offload_enable; 192 wed->wlan.offload_disable = mt7915_wed_offload_disable; 193 194 if (mtk_wed_device_attach(wed) != 0) 195 return 0; 196 197 *irq = wed->irq; 198 dev->mt76.dma_dev = wed->dev; 199 200 ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32)); 201 if (ret) 202 return ret; 203 204 return 1; 205 #else 206 return 0; 207 #endif 208 } 209 210 static int mt7915_pci_probe(struct pci_dev *pdev, 211 const struct pci_device_id *id) 212 { 213 struct mt7915_hif *hif2 = NULL; 214 struct mt7915_dev *dev; 215 struct mt76_dev *mdev; 216 int irq; 217 int ret; 218 219 ret = pcim_enable_device(pdev); 220 if (ret) 221 return ret; 222 223 ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); 224 if (ret) 225 return ret; 226 227 pci_set_master(pdev); 228 229 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 230 if (ret) 231 return ret; 232 233 mt76_pci_disable_aspm(pdev); 234 235 if (id->device == 0x7916 || id->device == 0x790a) 236 return mt7915_pci_hif2_probe(pdev); 237 238 dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], 239 id->device); 240 if (IS_ERR(dev)) 241 return PTR_ERR(dev); 242 243 mdev = &dev->mt76; 244 mt7915_wfsys_reset(dev); 245 hif2 = mt7915_pci_init_hif2(pdev); 246 247 ret = mt7915_pci_wed_init(dev, pdev, &irq); 248 if (ret < 0) 249 goto free_wed_or_irq_vector; 250 251 if (!ret) { 252 hif2 = mt7915_pci_init_hif2(pdev); 253 254 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 255 if (ret < 0) 256 goto free_device; 257 258 irq = pdev->irq; 259 } 260 261 ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler, 262 IRQF_SHARED, KBUILD_MODNAME, dev); 263 if (ret) 264 goto free_wed_or_irq_vector; 265 266 /* master switch of PCIe tnterrupt enable */ 267 mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 268 269 if (hif2) { 270 dev->hif2 = hif2; 271 272 mt76_wr(dev, MT_INT1_MASK_CSR, 0); 273 /* master switch of PCIe tnterrupt enable */ 274 if (is_mt7915(mdev)) 275 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); 276 else 277 mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff); 278 279 ret = devm_request_irq(mdev->dev, dev->hif2->irq, 280 mt7915_irq_handler, IRQF_SHARED, 281 KBUILD_MODNAME "-hif", dev); 282 if (ret) 283 goto free_hif2; 284 } 285 286 ret = mt7915_register_device(dev); 287 if (ret) 288 goto free_hif2_irq; 289 290 return 0; 291 292 free_hif2_irq: 293 if (dev->hif2) 294 devm_free_irq(mdev->dev, dev->hif2->irq, dev); 295 free_hif2: 296 if (dev->hif2) 297 put_device(dev->hif2->dev); 298 devm_free_irq(mdev->dev, irq, dev); 299 free_wed_or_irq_vector: 300 if (mtk_wed_device_active(&mdev->mmio.wed)) 301 mtk_wed_device_detach(&mdev->mmio.wed); 302 else 303 pci_free_irq_vectors(pdev); 304 free_device: 305 mt76_free_device(&dev->mt76); 306 307 return ret; 308 } 309 310 static void mt7915_hif_remove(struct pci_dev *pdev) 311 { 312 struct mt7915_hif *hif = pci_get_drvdata(pdev); 313 314 list_del(&hif->list); 315 } 316 317 static void mt7915_pci_remove(struct pci_dev *pdev) 318 { 319 struct mt76_dev *mdev; 320 struct mt7915_dev *dev; 321 322 mdev = pci_get_drvdata(pdev); 323 dev = container_of(mdev, struct mt7915_dev, mt76); 324 mt7915_put_hif2(dev->hif2); 325 mt7915_unregister_device(dev); 326 } 327 328 struct pci_driver mt7915_hif_driver = { 329 .name = KBUILD_MODNAME "_hif", 330 .id_table = mt7915_hif_device_table, 331 .probe = mt7915_pci_probe, 332 .remove = mt7915_hif_remove, 333 }; 334 335 struct pci_driver mt7915_pci_driver = { 336 .name = KBUILD_MODNAME, 337 .id_table = mt7915_pci_device_table, 338 .probe = mt7915_pci_probe, 339 .remove = mt7915_pci_remove, 340 }; 341 342 MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table); 343 MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table); 344 MODULE_FIRMWARE(MT7915_FIRMWARE_WA); 345 MODULE_FIRMWARE(MT7915_FIRMWARE_WM); 346 MODULE_FIRMWARE(MT7915_ROM_PATCH); 347 MODULE_FIRMWARE(MT7916_FIRMWARE_WA); 348 MODULE_FIRMWARE(MT7916_FIRMWARE_WM); 349 MODULE_FIRMWARE(MT7916_ROM_PATCH); 350 #if defined(__FreeBSD__) 351 MODULE_VERSION(mt7915_pci, 1); 352 MODULE_DEPEND(mt7915_pci, linuxkpi, 1, 1, 1); 353 MODULE_DEPEND(mt7915_pci, linuxkpi_wlan, 1, 1, 1); 354 MODULE_DEPEND(mt7915_pci, mt76_core, 1, 1, 1); 355 #endif 356