linux/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
<<
>>
Prefs
   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 LIST_HEAD(hif_list);
  16static DEFINE_SPINLOCK(hif_lock);
  17static u32 hif_idx;
  18
  19static const struct pci_device_id mt7915_pci_device_table[] = {
  20        { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) },
  21        { },
  22};
  23
  24static const struct pci_device_id mt7915_hif_device_table[] = {
  25        { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) },
  26        { },
  27};
  28
  29void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, bool write_reg,
  30                                  u32 clear, u32 set)
  31{
  32        struct mt76_dev *mdev = &dev->mt76;
  33        unsigned long flags;
  34
  35        spin_lock_irqsave(&mdev->mmio.irq_lock, flags);
  36
  37        mdev->mmio.irqmask &= ~clear;
  38        mdev->mmio.irqmask |= set;
  39
  40        if (write_reg) {
  41                mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
  42                mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
  43        }
  44
  45        spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags);
  46}
  47
  48static struct mt7915_hif *
  49mt7915_pci_get_hif2(struct mt7915_dev *dev)
  50{
  51        struct mt7915_hif *hif;
  52        u32 val;
  53
  54        spin_lock_bh(&hif_lock);
  55
  56        list_for_each_entry(hif, &hif_list, list) {
  57                val = readl(hif->regs + MT_PCIE_RECOG_ID);
  58                val &= MT_PCIE_RECOG_ID_MASK;
  59                if (val != dev->hif_idx)
  60                        continue;
  61
  62                get_device(hif->dev);
  63                goto out;
  64        }
  65        hif = NULL;
  66
  67out:
  68        spin_unlock_bh(&hif_lock);
  69
  70        return hif;
  71}
  72
  73static void mt7915_put_hif2(struct mt7915_hif *hif)
  74{
  75        if (!hif)
  76                return;
  77
  78        put_device(hif->dev);
  79}
  80
  81static void
  82mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
  83{
  84        struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
  85        static const u32 rx_irq_mask[] = {
  86                [MT_RXQ_MAIN] = MT_INT_RX_DONE_DATA0,
  87                [MT_RXQ_EXT] = MT_INT_RX_DONE_DATA1,
  88                [MT_RXQ_MCU] = MT_INT_RX_DONE_WM,
  89                [MT_RXQ_MCU_WA] = MT_INT_RX_DONE_WA,
  90                [MT_RXQ_EXT_WA] = MT_INT_RX_DONE_WA_EXT,
  91        };
  92
  93        mt7915_irq_enable(dev, rx_irq_mask[q]);
  94}
  95
  96/* TODO: support 2/4/6/8 MSI-X vectors */
  97static void mt7915_irq_tasklet(struct tasklet_struct *t)
  98{
  99        struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet);
 100        u32 intr, intr1, mask;
 101
 102        mt76_wr(dev, MT_INT_MASK_CSR, 0);
 103        if (dev->hif2)
 104                mt76_wr(dev, MT_INT1_MASK_CSR, 0);
 105
 106        intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
 107        intr &= dev->mt76.mmio.irqmask;
 108        mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
 109
 110        if (dev->hif2) {
 111                intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
 112                intr1 &= dev->mt76.mmio.irqmask;
 113                mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
 114
 115                intr |= intr1;
 116        }
 117
 118        trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
 119
 120        mask = intr & MT_INT_RX_DONE_ALL;
 121        if (intr & MT_INT_TX_DONE_MCU)
 122                mask |= MT_INT_TX_DONE_MCU;
 123
 124        mt7915_irq_disable(dev, mask);
 125
 126        if (intr & MT_INT_TX_DONE_MCU)
 127                napi_schedule(&dev->mt76.tx_napi);
 128
 129        if (intr & MT_INT_RX_DONE_DATA0)
 130                napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]);
 131
 132        if (intr & MT_INT_RX_DONE_DATA1)
 133                napi_schedule(&dev->mt76.napi[MT_RXQ_EXT]);
 134
 135        if (intr & MT_INT_RX_DONE_WM)
 136                napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]);
 137
 138        if (intr & MT_INT_RX_DONE_WA)
 139                napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]);
 140
 141        if (intr & MT_INT_RX_DONE_WA_EXT)
 142                napi_schedule(&dev->mt76.napi[MT_RXQ_EXT_WA]);
 143
 144        if (intr & MT_INT_MCU_CMD) {
 145                u32 val = mt76_rr(dev, MT_MCU_CMD);
 146
 147                mt76_wr(dev, MT_MCU_CMD, val);
 148                if (val & MT_MCU_CMD_ERROR_MASK) {
 149                        dev->reset_state = val;
 150                        ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
 151                        wake_up(&dev->reset_wait);
 152                }
 153        }
 154}
 155
 156static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
 157{
 158        struct mt7915_dev *dev = dev_instance;
 159
 160        mt76_wr(dev, MT_INT_MASK_CSR, 0);
 161        if (dev->hif2)
 162                mt76_wr(dev, MT_INT1_MASK_CSR, 0);
 163
 164        if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
 165                return IRQ_NONE;
 166
 167        tasklet_schedule(&dev->irq_tasklet);
 168
 169        return IRQ_HANDLED;
 170}
 171
 172static void mt7915_pci_init_hif2(struct mt7915_dev *dev)
 173{
 174        struct mt7915_hif *hif;
 175
 176        dev->hif_idx = ++hif_idx;
 177        if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL))
 178                return;
 179
 180        mt76_wr(dev, MT_PCIE_RECOG_ID, dev->hif_idx | MT_PCIE_RECOG_ID_SEM);
 181
 182        hif = mt7915_pci_get_hif2(dev);
 183        if (!hif)
 184                return;
 185
 186        dev->hif2 = hif;
 187
 188        mt76_wr(dev, MT_INT1_MASK_CSR, 0);
 189
 190        if (devm_request_irq(dev->mt76.dev, hif->irq, mt7915_irq_handler,
 191                             IRQF_SHARED, KBUILD_MODNAME "-hif", dev)) {
 192                mt7915_put_hif2(hif);
 193                hif = NULL;
 194        }
 195
 196        /* master switch of PCIe tnterrupt enable */
 197        mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
 198}
 199
 200static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
 201{
 202        struct mt7915_hif *hif;
 203
 204        hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);
 205        if (!hif)
 206                return -ENOMEM;
 207
 208        hif->dev = &pdev->dev;
 209        hif->regs = pcim_iomap_table(pdev)[0];
 210        hif->irq = pdev->irq;
 211        spin_lock_bh(&hif_lock);
 212        list_add(&hif->list, &hif_list);
 213        spin_unlock_bh(&hif_lock);
 214        pci_set_drvdata(pdev, hif);
 215
 216        return 0;
 217}
 218
 219static int mt7915_pci_probe(struct pci_dev *pdev,
 220                            const struct pci_device_id *id)
 221{
 222        static const struct mt76_driver_ops drv_ops = {
 223                /* txwi_size = txd size + txp size */
 224                .txwi_size = MT_TXD_SIZE + sizeof(struct mt7915_txp),
 225                .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
 226                             MT_DRV_AMSDU_OFFLOAD,
 227                .survey_flags = SURVEY_INFO_TIME_TX |
 228                                SURVEY_INFO_TIME_RX |
 229                                SURVEY_INFO_TIME_BSS_RX,
 230                .token_size = MT7915_TOKEN_SIZE,
 231                .tx_prepare_skb = mt7915_tx_prepare_skb,
 232                .tx_complete_skb = mt7915_tx_complete_skb,
 233                .rx_skb = mt7915_queue_rx_skb,
 234                .rx_poll_complete = mt7915_rx_poll_complete,
 235                .sta_ps = mt7915_sta_ps,
 236                .sta_add = mt7915_mac_sta_add,
 237                .sta_remove = mt7915_mac_sta_remove,
 238                .update_survey = mt7915_update_channel,
 239        };
 240        struct mt7915_dev *dev;
 241        struct mt76_dev *mdev;
 242        int ret;
 243
 244        ret = pcim_enable_device(pdev);
 245        if (ret)
 246                return ret;
 247
 248        ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
 249        if (ret)
 250                return ret;
 251
 252        pci_set_master(pdev);
 253
 254        ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 255        if (ret)
 256                return ret;
 257
 258        mt76_pci_disable_aspm(pdev);
 259
 260        if (id->device == 0x7916)
 261                return mt7915_pci_hif2_probe(pdev);
 262
 263        mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7915_ops,
 264                                 &drv_ops);
 265        if (!mdev)
 266                return -ENOMEM;
 267
 268        dev = container_of(mdev, struct mt7915_dev, mt76);
 269
 270        ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
 271        if (ret < 0)
 272                goto free;
 273
 274        ret = mt7915_mmio_init(mdev, pcim_iomap_table(pdev)[0], pdev->irq);
 275        if (ret)
 276                goto error;
 277
 278        tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet);
 279
 280        mt76_wr(dev, MT_INT_MASK_CSR, 0);
 281
 282        /* master switch of PCIe tnterrupt enable */
 283        mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
 284
 285        ret = devm_request_irq(mdev->dev, pdev->irq, mt7915_irq_handler,
 286                               IRQF_SHARED, KBUILD_MODNAME, dev);
 287        if (ret)
 288                goto error;
 289
 290        mt7915_pci_init_hif2(dev);
 291
 292        ret = mt7915_register_device(dev);
 293        if (ret)
 294                goto free_irq;
 295
 296        return 0;
 297free_irq:
 298        devm_free_irq(mdev->dev, pdev->irq, dev);
 299error:
 300        pci_free_irq_vectors(pdev);
 301free:
 302        mt76_free_device(&dev->mt76);
 303
 304        return ret;
 305}
 306
 307static void mt7915_hif_remove(struct pci_dev *pdev)
 308{
 309        struct mt7915_hif *hif = pci_get_drvdata(pdev);
 310
 311        list_del(&hif->list);
 312}
 313
 314static void mt7915_pci_remove(struct pci_dev *pdev)
 315{
 316        struct mt76_dev *mdev;
 317        struct mt7915_dev *dev;
 318
 319        mdev = pci_get_drvdata(pdev);
 320        dev = container_of(mdev, struct mt7915_dev, mt76);
 321        mt7915_put_hif2(dev->hif2);
 322        mt7915_unregister_device(dev);
 323}
 324
 325static struct pci_driver mt7915_hif_driver = {
 326        .name           = KBUILD_MODNAME "_hif",
 327        .id_table       = mt7915_hif_device_table,
 328        .probe          = mt7915_pci_probe,
 329        .remove         = mt7915_hif_remove,
 330};
 331
 332static struct pci_driver mt7915_pci_driver = {
 333        .name           = KBUILD_MODNAME,
 334        .id_table       = mt7915_pci_device_table,
 335        .probe          = mt7915_pci_probe,
 336        .remove         = mt7915_pci_remove,
 337};
 338
 339static int __init mt7915_init(void)
 340{
 341        int ret;
 342
 343        ret = pci_register_driver(&mt7915_hif_driver);
 344        if (ret)
 345                return ret;
 346
 347        ret = pci_register_driver(&mt7915_pci_driver);
 348        if (ret)
 349                pci_unregister_driver(&mt7915_hif_driver);
 350
 351        return ret;
 352}
 353
 354static void __exit mt7915_exit(void)
 355{
 356    pci_unregister_driver(&mt7915_pci_driver);
 357    pci_unregister_driver(&mt7915_hif_driver);
 358}
 359
 360module_init(mt7915_init);
 361module_exit(mt7915_exit);
 362
 363MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table);
 364MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table);
 365MODULE_FIRMWARE(MT7915_FIRMWARE_WA);
 366MODULE_FIRMWARE(MT7915_FIRMWARE_WM);
 367MODULE_FIRMWARE(MT7915_ROM_PATCH);
 368MODULE_LICENSE("Dual BSD/GPL");
 369