summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915/pci.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/pci.c249
1 files changed, 150 insertions, 99 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
index 7937c6965f59..f6b03211a879 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: ISC
+// SPDX-License-Identifier: BSD-3-Clause-Clear
/* Copyright (C) 2020 MediaTek Inc.
*
* Author: Ryder Lee <ryder.lee@mediatek.com>
@@ -12,87 +12,90 @@
#include "mac.h"
#include "../trace.h"
+static LIST_HEAD(hif_list);
+static DEFINE_SPINLOCK(hif_lock);
+static u32 hif_idx;
+
static const struct pci_device_id mt7915_pci_device_table[] = {
- { PCI_DEVICE(0x14c3, 0x7915) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7906) },
{ },
};
-static void
-mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
-{
- struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
-
- mt7915_irq_enable(dev, MT_INT_RX_DONE(q));
-}
+static const struct pci_device_id mt7915_hif_device_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x790a) },
+ { },
+};
-/* TODO: support 2/4/6/8 MSI-X vectors */
-static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
+static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx)
{
- struct mt7915_dev *dev = dev_instance;
- u32 intr;
+ struct mt7915_hif *hif;
+ u32 val;
- intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
- mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
+ spin_lock_bh(&hif_lock);
- if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
- return IRQ_NONE;
+ list_for_each_entry(hif, &hif_list, list) {
+ val = readl(hif->regs + MT_PCIE_RECOG_ID);
+ val &= MT_PCIE_RECOG_ID_MASK;
+ if (val != idx)
+ continue;
- trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
+ get_device(hif->dev);
+ hif->index = idx;
+ goto out;
+ }
+ hif = NULL;
- intr &= dev->mt76.mmio.irqmask;
+out:
+ spin_unlock_bh(&hif_lock);
- if (intr & MT_INT_TX_DONE_ALL) {
- mt7915_irq_disable(dev, MT_INT_TX_DONE_ALL);
- napi_schedule(&dev->mt76.tx_napi);
- }
+ return hif;
+}
- if (intr & MT_INT_RX_DONE_DATA) {
- mt7915_irq_disable(dev, MT_INT_RX_DONE_DATA);
- napi_schedule(&dev->mt76.napi[0]);
- }
+static void mt7915_put_hif2(struct mt7915_hif *hif)
+{
+ if (!hif)
+ return;
- if (intr & MT_INT_RX_DONE_WM) {
- mt7915_irq_disable(dev, MT_INT_RX_DONE_WM);
- napi_schedule(&dev->mt76.napi[1]);
- }
+ put_device(hif->dev);
+}
- if (intr & MT_INT_RX_DONE_WA) {
- mt7915_irq_disable(dev, MT_INT_RX_DONE_WA);
- napi_schedule(&dev->mt76.napi[2]);
- }
+static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev)
+{
+ struct pci_dev *tmp_pdev;
- if (intr & MT_INT_MCU_CMD) {
- u32 val = mt76_rr(dev, MT_MCU_CMD);
+ hif_idx++;
- mt76_wr(dev, MT_MCU_CMD, val);
- if (val & MT_MCU_CMD_ERROR_MASK) {
- dev->reset_state = val;
- ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
- wake_up(&dev->reset_wait);
- }
+ tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL);
+ if (!tmp_pdev) {
+ tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL);
+ if (!tmp_pdev)
+ return NULL;
}
+ pci_dev_put(tmp_pdev);
+
+ writel(hif_idx | MT_PCIE_RECOG_ID_SEM,
+ pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID);
- return IRQ_HANDLED;
+ return mt7915_pci_get_hif2(hif_idx);
}
-static int
-mt7915_alloc_device(struct pci_dev *pdev, struct mt7915_dev *dev)
+static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
{
-#define NUM_BANDS 2
- int i;
- s8 **sku;
+ struct mt7915_hif *hif;
- sku = devm_kzalloc(&pdev->dev, NUM_BANDS * sizeof(*sku), GFP_KERNEL);
- if (!sku)
+ hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);
+ if (!hif)
return -ENOMEM;
- for (i = 0; i < NUM_BANDS; i++) {
- sku[i] = devm_kzalloc(&pdev->dev, MT7915_SKU_TABLE_SIZE *
- sizeof(**sku), GFP_KERNEL);
- if (!sku[i])
- return -ENOMEM;
- }
- dev->rate_power = sku;
+ hif->dev = &pdev->dev;
+ hif->regs = pcim_iomap_table(pdev)[0];
+ hif->irq = pdev->irq;
+ spin_lock_bh(&hif_lock);
+ list_add(&hif->list, &hif_list);
+ spin_unlock_bh(&hif_lock);
+ pci_set_drvdata(pdev, hif);
return 0;
}
@@ -100,24 +103,10 @@ mt7915_alloc_device(struct pci_dev *pdev, struct mt7915_dev *dev)
static int mt7915_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
- static const struct mt76_driver_ops drv_ops = {
- /* txwi_size = txd size + txp size */
- .txwi_size = MT_TXD_SIZE + sizeof(struct mt7915_txp),
- .drv_flags = MT_DRV_TXWI_NO_FREE,
- .survey_flags = SURVEY_INFO_TIME_TX |
- SURVEY_INFO_TIME_RX |
- SURVEY_INFO_TIME_BSS_RX,
- .tx_prepare_skb = mt7915_tx_prepare_skb,
- .tx_complete_skb = mt7915_tx_complete_skb,
- .rx_skb = mt7915_queue_rx_skb,
- .rx_poll_complete = mt7915_rx_poll_complete,
- .sta_ps = mt7915_sta_ps,
- .sta_add = mt7915_mac_sta_add,
- .sta_remove = mt7915_mac_sta_remove,
- .update_survey = mt7915_update_channel,
- };
+ struct mt7915_hif *hif2 = NULL;
struct mt7915_dev *dev;
struct mt76_dev *mdev;
+ int irq;
int ret;
ret = pcim_enable_device(pdev);
@@ -130,51 +119,112 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev);
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
- mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7915_ops,
- &drv_ops);
- if (!mdev)
- return -ENOMEM;
+ mt76_pci_disable_aspm(pdev);
- dev = container_of(mdev, struct mt7915_dev, mt76);
- ret = mt7915_alloc_device(pdev, dev);
- if (ret)
- return ret;
+ if (id->device == 0x7916 || id->device == 0x790a)
+ return mt7915_pci_hif2_probe(pdev);
- mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
- mdev->rev = (mt7915_l1_rr(dev, MT_HW_CHIPID) << 16) |
- (mt7915_l1_rr(dev, MT_HW_REV) & 0xff);
- dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
+ dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
+ id->device);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
- /* master switch of PCIe tnterrupt enable */
- mt7915_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+ mdev = &dev->mt76;
+ mt7915_wfsys_reset(dev);
+ hif2 = mt7915_pci_init_hif2(pdev);
- ret = devm_request_irq(mdev->dev, pdev->irq, mt7915_irq_handler,
+ ret = mt7915_mmio_wed_init(dev, pdev, true, &irq);
+ if (ret < 0)
+ goto free_wed_or_irq_vector;
+
+ if (!ret) {
+ hif2 = mt7915_pci_init_hif2(pdev);
+
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+ if (ret < 0)
+ goto free_device;
+
+ irq = pdev->irq;
+ }
+
+ ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
- goto error;
+ goto free_wed_or_irq_vector;
+
+ /* master switch of PCIe tnterrupt enable */
+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+
+ if (hif2) {
+ dev->hif2 = hif2;
+
+ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+ /* master switch of PCIe tnterrupt enable */
+ if (is_mt7915(mdev))
+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
+ else
+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff);
+
+ ret = devm_request_irq(mdev->dev, dev->hif2->irq,
+ mt7915_irq_handler, IRQF_SHARED,
+ KBUILD_MODNAME "-hif", dev);
+ if (ret)
+ goto free_hif2;
+ }
ret = mt7915_register_device(dev);
if (ret)
- goto error;
+ goto free_hif2_irq;
return 0;
-error:
- ieee80211_free_hw(mt76_hw(dev));
+
+free_hif2_irq:
+ if (dev->hif2)
+ devm_free_irq(mdev->dev, dev->hif2->irq, dev);
+free_hif2:
+ if (dev->hif2)
+ put_device(dev->hif2->dev);
+ devm_free_irq(mdev->dev, irq, dev);
+free_wed_or_irq_vector:
+ if (mtk_wed_device_active(&mdev->mmio.wed))
+ mtk_wed_device_detach(&mdev->mmio.wed);
+ else
+ pci_free_irq_vectors(pdev);
+free_device:
+ mt76_free_device(&dev->mt76);
+
return ret;
}
+static void mt7915_hif_remove(struct pci_dev *pdev)
+{
+ struct mt7915_hif *hif = pci_get_drvdata(pdev);
+
+ list_del(&hif->list);
+}
+
static void mt7915_pci_remove(struct pci_dev *pdev)
{
- struct mt76_dev *mdev = pci_get_drvdata(pdev);
- struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+ struct mt76_dev *mdev;
+ struct mt7915_dev *dev;
+ mdev = pci_get_drvdata(pdev);
+ dev = container_of(mdev, struct mt7915_dev, mt76);
+ mt7915_put_hif2(dev->hif2);
mt7915_unregister_device(dev);
}
+struct pci_driver mt7915_hif_driver = {
+ .name = KBUILD_MODNAME "_hif",
+ .id_table = mt7915_hif_device_table,
+ .probe = mt7915_pci_probe,
+ .remove = mt7915_hif_remove,
+};
+
struct pci_driver mt7915_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7915_pci_device_table,
@@ -182,10 +232,11 @@ struct pci_driver mt7915_pci_driver = {
.remove = mt7915_pci_remove,
};
-module_pci_driver(mt7915_pci_driver);
-
MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table);
+MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table);
MODULE_FIRMWARE(MT7915_FIRMWARE_WA);
MODULE_FIRMWARE(MT7915_FIRMWARE_WM);
MODULE_FIRMWARE(MT7915_ROM_PATCH);
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_FIRMWARE(MT7916_FIRMWARE_WA);
+MODULE_FIRMWARE(MT7916_FIRMWARE_WM);
+MODULE_FIRMWARE(MT7916_ROM_PATCH);