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