1*4882a593Smuzhiyun // SPDX-License-Identifier: ISC
2*4882a593Smuzhiyun /* Copyright (C) 2020 MediaTek Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Author: Ryder Lee <ryder.lee@mediatek.com>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/kernel.h>
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/pci.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include "mt7915.h"
12*4882a593Smuzhiyun #include "mac.h"
13*4882a593Smuzhiyun #include "../trace.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun static const struct pci_device_id mt7915_pci_device_table[] = {
16*4882a593Smuzhiyun { PCI_DEVICE(0x14c3, 0x7915) },
17*4882a593Smuzhiyun { },
18*4882a593Smuzhiyun };
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun static void
mt7915_rx_poll_complete(struct mt76_dev * mdev,enum mt76_rxq_id q)21*4882a593Smuzhiyun mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun mt7915_irq_enable(dev, MT_INT_RX_DONE(q));
26*4882a593Smuzhiyun }
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /* TODO: support 2/4/6/8 MSI-X vectors */
mt7915_irq_handler(int irq,void * dev_instance)29*4882a593Smuzhiyun static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun struct mt7915_dev *dev = dev_instance;
32*4882a593Smuzhiyun u32 intr, mask;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
35*4882a593Smuzhiyun intr &= dev->mt76.mmio.irqmask;
36*4882a593Smuzhiyun mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
39*4882a593Smuzhiyun return IRQ_NONE;
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun mask = intr & MT_INT_RX_DONE_ALL;
44*4882a593Smuzhiyun if (intr & MT_INT_TX_DONE_MCU)
45*4882a593Smuzhiyun mask |= MT_INT_TX_DONE_MCU;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun mt7915_irq_disable(dev, mask);
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun if (intr & MT_INT_TX_DONE_MCU)
50*4882a593Smuzhiyun napi_schedule(&dev->mt76.tx_napi);
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun if (intr & MT_INT_RX_DONE_DATA)
53*4882a593Smuzhiyun napi_schedule(&dev->mt76.napi[0]);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun if (intr & MT_INT_RX_DONE_WM)
56*4882a593Smuzhiyun napi_schedule(&dev->mt76.napi[1]);
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun if (intr & MT_INT_RX_DONE_WA)
59*4882a593Smuzhiyun napi_schedule(&dev->mt76.napi[2]);
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun if (intr & MT_INT_MCU_CMD) {
62*4882a593Smuzhiyun u32 val = mt76_rr(dev, MT_MCU_CMD);
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun mt76_wr(dev, MT_MCU_CMD, val);
65*4882a593Smuzhiyun if (val & MT_MCU_CMD_ERROR_MASK) {
66*4882a593Smuzhiyun dev->reset_state = val;
67*4882a593Smuzhiyun ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
68*4882a593Smuzhiyun wake_up(&dev->reset_wait);
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun return IRQ_HANDLED;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun static int
mt7915_alloc_device(struct pci_dev * pdev,struct mt7915_dev * dev)76*4882a593Smuzhiyun mt7915_alloc_device(struct pci_dev *pdev, struct mt7915_dev *dev)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun #define NUM_BANDS 2
79*4882a593Smuzhiyun int i;
80*4882a593Smuzhiyun s8 **sku;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun sku = devm_kzalloc(&pdev->dev, NUM_BANDS * sizeof(*sku), GFP_KERNEL);
83*4882a593Smuzhiyun if (!sku)
84*4882a593Smuzhiyun return -ENOMEM;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun for (i = 0; i < NUM_BANDS; i++) {
87*4882a593Smuzhiyun sku[i] = devm_kzalloc(&pdev->dev, MT7915_SKU_TABLE_SIZE *
88*4882a593Smuzhiyun sizeof(**sku), GFP_KERNEL);
89*4882a593Smuzhiyun if (!sku[i])
90*4882a593Smuzhiyun return -ENOMEM;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun dev->rate_power = sku;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
mt7915_pci_probe(struct pci_dev * pdev,const struct pci_device_id * id)97*4882a593Smuzhiyun static int mt7915_pci_probe(struct pci_dev *pdev,
98*4882a593Smuzhiyun const struct pci_device_id *id)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun static const struct mt76_driver_ops drv_ops = {
101*4882a593Smuzhiyun /* txwi_size = txd size + txp size */
102*4882a593Smuzhiyun .txwi_size = MT_TXD_SIZE + sizeof(struct mt7915_txp),
103*4882a593Smuzhiyun .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
104*4882a593Smuzhiyun MT_DRV_AMSDU_OFFLOAD,
105*4882a593Smuzhiyun .survey_flags = SURVEY_INFO_TIME_TX |
106*4882a593Smuzhiyun SURVEY_INFO_TIME_RX |
107*4882a593Smuzhiyun SURVEY_INFO_TIME_BSS_RX,
108*4882a593Smuzhiyun .tx_prepare_skb = mt7915_tx_prepare_skb,
109*4882a593Smuzhiyun .tx_complete_skb = mt7915_tx_complete_skb,
110*4882a593Smuzhiyun .rx_skb = mt7915_queue_rx_skb,
111*4882a593Smuzhiyun .rx_poll_complete = mt7915_rx_poll_complete,
112*4882a593Smuzhiyun .sta_ps = mt7915_sta_ps,
113*4882a593Smuzhiyun .sta_add = mt7915_mac_sta_add,
114*4882a593Smuzhiyun .sta_remove = mt7915_mac_sta_remove,
115*4882a593Smuzhiyun .update_survey = mt7915_update_channel,
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun struct mt7915_dev *dev;
118*4882a593Smuzhiyun struct mt76_dev *mdev;
119*4882a593Smuzhiyun int ret;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun ret = pcim_enable_device(pdev);
122*4882a593Smuzhiyun if (ret)
123*4882a593Smuzhiyun return ret;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
126*4882a593Smuzhiyun if (ret)
127*4882a593Smuzhiyun return ret;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun pci_set_master(pdev);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
132*4882a593Smuzhiyun if (ret)
133*4882a593Smuzhiyun return ret;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7915_ops,
136*4882a593Smuzhiyun &drv_ops);
137*4882a593Smuzhiyun if (!mdev)
138*4882a593Smuzhiyun return -ENOMEM;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun dev = container_of(mdev, struct mt7915_dev, mt76);
141*4882a593Smuzhiyun ret = mt7915_alloc_device(pdev, dev);
142*4882a593Smuzhiyun if (ret)
143*4882a593Smuzhiyun goto error;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
146*4882a593Smuzhiyun mdev->rev = (mt7915_l1_rr(dev, MT_HW_CHIPID) << 16) |
147*4882a593Smuzhiyun (mt7915_l1_rr(dev, MT_HW_REV) & 0xff);
148*4882a593Smuzhiyun dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun mt76_wr(dev, MT_INT_MASK_CSR, 0);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* master switch of PCIe tnterrupt enable */
153*4882a593Smuzhiyun mt7915_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun ret = devm_request_irq(mdev->dev, pdev->irq, mt7915_irq_handler,
156*4882a593Smuzhiyun IRQF_SHARED, KBUILD_MODNAME, dev);
157*4882a593Smuzhiyun if (ret)
158*4882a593Smuzhiyun goto error;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun ret = mt7915_register_device(dev);
161*4882a593Smuzhiyun if (ret)
162*4882a593Smuzhiyun goto error;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun return 0;
165*4882a593Smuzhiyun error:
166*4882a593Smuzhiyun mt76_free_device(&dev->mt76);
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun return ret;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
mt7915_pci_remove(struct pci_dev * pdev)171*4882a593Smuzhiyun static void mt7915_pci_remove(struct pci_dev *pdev)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun struct mt76_dev *mdev = pci_get_drvdata(pdev);
174*4882a593Smuzhiyun struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun mt7915_unregister_device(dev);
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun struct pci_driver mt7915_pci_driver = {
180*4882a593Smuzhiyun .name = KBUILD_MODNAME,
181*4882a593Smuzhiyun .id_table = mt7915_pci_device_table,
182*4882a593Smuzhiyun .probe = mt7915_pci_probe,
183*4882a593Smuzhiyun .remove = mt7915_pci_remove,
184*4882a593Smuzhiyun };
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun module_pci_driver(mt7915_pci_driver);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table);
189*4882a593Smuzhiyun MODULE_FIRMWARE(MT7915_FIRMWARE_WA);
190*4882a593Smuzhiyun MODULE_FIRMWARE(MT7915_FIRMWARE_WM);
191*4882a593Smuzhiyun MODULE_FIRMWARE(MT7915_ROM_PATCH);
192*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
193