GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / net / wireless / mediatek / mt76 / mt7915 / pci.c
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
15 static bool wed_enable = false;
16 module_param(wed_enable, bool, 0644);
17
18 static LIST_HEAD(hif_list);
19 static DEFINE_SPINLOCK(hif_lock);
20 static u32 hif_idx;
21
22 static const struct pci_device_id mt7915_pci_device_table[] = {
23         { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) },
24         { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7906) },
25         { },
26 };
27
28 static const struct pci_device_id mt7915_hif_device_table[] = {
29         { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) },
30         { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x790a) },
31         { },
32 };
33
34 static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx)
35 {
36         struct mt7915_hif *hif;
37         u32 val;
38
39         spin_lock_bh(&hif_lock);
40
41         list_for_each_entry(hif, &hif_list, list) {
42                 val = readl(hif->regs + MT_PCIE_RECOG_ID);
43                 val &= MT_PCIE_RECOG_ID_MASK;
44                 if (val != idx)
45                         continue;
46
47                 get_device(hif->dev);
48                 goto out;
49         }
50         hif = NULL;
51
52 out:
53         spin_unlock_bh(&hif_lock);
54
55         return hif;
56 }
57
58 static void mt7915_put_hif2(struct mt7915_hif *hif)
59 {
60         if (!hif)
61                 return;
62
63         put_device(hif->dev);
64 }
65
66 static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev)
67 {
68         hif_idx++;
69         if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL) &&
70             !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL))
71                 return NULL;
72
73         writel(hif_idx | MT_PCIE_RECOG_ID_SEM,
74                pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID);
75
76         return mt7915_pci_get_hif2(hif_idx);
77 }
78
79 static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
80 {
81         struct mt7915_hif *hif;
82
83         hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);
84         if (!hif)
85                 return -ENOMEM;
86
87         hif->dev = &pdev->dev;
88         hif->regs = pcim_iomap_table(pdev)[0];
89         hif->irq = pdev->irq;
90         spin_lock_bh(&hif_lock);
91         list_add(&hif->list, &hif_list);
92         spin_unlock_bh(&hif_lock);
93         pci_set_drvdata(pdev, hif);
94
95         return 0;
96 }
97
98 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
99 static int mt7915_wed_offload_enable(struct mtk_wed_device *wed)
100 {
101         struct mt7915_dev *dev;
102         int ret;
103
104         dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
105
106         spin_lock_bh(&dev->mt76.token_lock);
107         dev->mt76.token_size = wed->wlan.token_start;
108         spin_unlock_bh(&dev->mt76.token_lock);
109
110         ret = wait_event_timeout(dev->mt76.tx_wait,
111                                  !dev->mt76.wed_token_count, HZ);
112         if (!ret)
113                 return -EAGAIN;
114
115         return 0;
116 }
117
118 static void mt7915_wed_offload_disable(struct mtk_wed_device *wed)
119 {
120         struct mt7915_dev *dev;
121
122         dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
123
124         spin_lock_bh(&dev->mt76.token_lock);
125         dev->mt76.token_size = MT7915_TOKEN_SIZE;
126         spin_unlock_bh(&dev->mt76.token_lock);
127 }
128 #endif
129
130 static int
131 mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq)
132 {
133 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
134         struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
135         int ret;
136
137         if (!wed_enable)
138                 return 0;
139
140         wed->wlan.pci_dev = pdev;
141         wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) +
142                                MT_WFDMA_EXT_CSR_BASE;
143         wed->wlan.nbuf = 4096;
144         wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
145         wed->wlan.init_buf = mt7915_wed_init_buf;
146         wed->wlan.offload_enable = mt7915_wed_offload_enable;
147         wed->wlan.offload_disable = mt7915_wed_offload_disable;
148
149         if (mtk_wed_device_attach(wed) != 0)
150                 return 0;
151
152         *irq = wed->irq;
153         dev->mt76.dma_dev = wed->dev;
154
155         ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
156         if (ret)
157                 return ret;
158
159         return 1;
160 #else
161         return 0;
162 #endif
163 }
164
165 static int mt7915_pci_probe(struct pci_dev *pdev,
166                             const struct pci_device_id *id)
167 {
168         struct mt7915_hif *hif2 = NULL;
169         struct mt7915_dev *dev;
170         struct mt76_dev *mdev;
171         int irq;
172         int ret;
173
174         ret = pcim_enable_device(pdev);
175         if (ret)
176                 return ret;
177
178         ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
179         if (ret)
180                 return ret;
181
182         pci_set_master(pdev);
183
184         ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
185         if (ret)
186                 return ret;
187
188         mt76_pci_disable_aspm(pdev);
189
190         if (id->device == 0x7916 || id->device == 0x790a)
191                 return mt7915_pci_hif2_probe(pdev);
192
193         dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
194                                 id->device);
195         if (IS_ERR(dev))
196                 return PTR_ERR(dev);
197
198         mdev = &dev->mt76;
199         mt7915_wfsys_reset(dev);
200         hif2 = mt7915_pci_init_hif2(pdev);
201
202         ret = mt7915_pci_wed_init(dev, pdev, &irq);
203         if (ret < 0)
204                 goto free_wed_or_irq_vector;
205
206         if (!ret) {
207                 hif2 = mt7915_pci_init_hif2(pdev);
208
209                 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
210                 if (ret < 0)
211                         goto free_device;
212
213                 irq = pdev->irq;
214         }
215
216         ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
217                                IRQF_SHARED, KBUILD_MODNAME, dev);
218         if (ret)
219                 goto free_wed_or_irq_vector;
220
221         /* master switch of PCIe tnterrupt enable */
222         mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
223
224         if (hif2) {
225                 dev->hif2 = hif2;
226
227                 mt76_wr(dev, MT_INT1_MASK_CSR, 0);
228                 /* master switch of PCIe tnterrupt enable */
229                 if (is_mt7915(mdev))
230                         mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
231                 else
232                         mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff);
233
234                 ret = devm_request_irq(mdev->dev, dev->hif2->irq,
235                                        mt7915_irq_handler, IRQF_SHARED,
236                                        KBUILD_MODNAME "-hif", dev);
237                 if (ret)
238                         goto free_hif2;
239         }
240
241         ret = mt7915_register_device(dev);
242         if (ret)
243                 goto free_hif2_irq;
244
245         return 0;
246
247 free_hif2_irq:
248         if (dev->hif2)
249                 devm_free_irq(mdev->dev, dev->hif2->irq, dev);
250 free_hif2:
251         if (dev->hif2)
252                 put_device(dev->hif2->dev);
253         devm_free_irq(mdev->dev, irq, dev);
254 free_wed_or_irq_vector:
255         if (mtk_wed_device_active(&mdev->mmio.wed))
256                 mtk_wed_device_detach(&mdev->mmio.wed);
257         else
258                 pci_free_irq_vectors(pdev);
259 free_device:
260         mt76_free_device(&dev->mt76);
261
262         return ret;
263 }
264
265 static void mt7915_hif_remove(struct pci_dev *pdev)
266 {
267         struct mt7915_hif *hif = pci_get_drvdata(pdev);
268
269         list_del(&hif->list);
270 }
271
272 static void mt7915_pci_remove(struct pci_dev *pdev)
273 {
274         struct mt76_dev *mdev;
275         struct mt7915_dev *dev;
276
277         mdev = pci_get_drvdata(pdev);
278         dev = container_of(mdev, struct mt7915_dev, mt76);
279         mt7915_put_hif2(dev->hif2);
280         mt7915_unregister_device(dev);
281 }
282
283 struct pci_driver mt7915_hif_driver = {
284         .name           = KBUILD_MODNAME "_hif",
285         .id_table       = mt7915_hif_device_table,
286         .probe          = mt7915_pci_probe,
287         .remove         = mt7915_hif_remove,
288 };
289
290 struct pci_driver mt7915_pci_driver = {
291         .name           = KBUILD_MODNAME,
292         .id_table       = mt7915_pci_device_table,
293         .probe          = mt7915_pci_probe,
294         .remove         = mt7915_pci_remove,
295 };
296
297 MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table);
298 MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table);
299 /*(DEBLOBBED)*/