File Index
Files and directories
Sign in
FILE

pci.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/mediatek/mt76/mt7996/pci.c C
  1// SPDX-License-Identifier: BSD-3-Clause-Clear
  2/*
  3 * Copyright (C) 2022 MediaTek Inc.
  4 */
  5
  6#include <linux/kernel.h>
  7#include <linux/module.h>
  8#include <linux/pci.h>
  9
 10#include "mt7996.h"
 11#include "mac.h"
 12#include "../trace.h"
 13
 14static LIST_HEAD(hif_list);
 15static DEFINE_SPINLOCK(hif_lock);
 16static u32 hif_idx;
 17
 18static const struct pci_device_id mt7996_pci_device_table[] = {
 19	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID) },
 20	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID) },
 21	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID) },
 22	{ },
 23};
 24
 25static const struct pci_device_id mt7996_hif_device_table[] = {
 26	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2) },
 27	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2) },
 28	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2) },
 29	{ },
 30};
 31
 32static struct mt7996_hif *mt7996_pci_get_hif2(u32 idx)
 33{
 34	struct mt7996_hif *hif;
 35	u32 val;
 36
 37	spin_lock_bh(&hif_lock);
 38
 39	list_for_each_entry(hif, &hif_list, list) {
 40		val = readl(hif->regs + MT_PCIE_RECOG_ID);
 41		val &= MT_PCIE_RECOG_ID_MASK;
 42		if (val != idx)
 43			continue;
 44
 45		get_device(hif->dev);
 46		goto out;
 47	}
 48	hif = NULL;
 49
 50out:
 51	spin_unlock_bh(&hif_lock);
 52
 53	return hif;
 54}
 55
 56static void mt7996_put_hif2(struct mt7996_hif *hif)
 57{
 58	if (!hif)
 59		return;
 60
 61	put_device(hif->dev);
 62}
 63
 64static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev)
 65{
 66	hif_idx++;
 67
 68	if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2, NULL) &&
 69	    !pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2, NULL) &&
 70	    !pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2, 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 mt7996_pci_get_hif2(hif_idx);
 77}
 78
 79static int mt7996_pci_hif2_probe(struct pci_dev *pdev)
 80{
 81	struct mt7996_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	pcie_bandwidth_available(pdev, NULL, &hif->speed, &hif->width);
 91	spin_lock_bh(&hif_lock);
 92	list_add(&hif->list, &hif_list);
 93	spin_unlock_bh(&hif_lock);
 94	pci_set_drvdata(pdev, hif);
 95
 96	return 0;
 97}
 98
 99static int mt7996_pci_probe(struct pci_dev *pdev,
100			    const struct pci_device_id *id)
101{
102	struct pci_dev *hif2_dev;
103	struct mt7996_hif *hif2;
104	struct mt7996_dev *dev;
105	int irq, hif2_irq, ret;
106	struct mt76_dev *mdev;
107
108	ret = pcim_enable_device(pdev);
109	if (ret)
110		return ret;
111
112	ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
113	if (ret)
114		return ret;
115
116	pci_set_master(pdev);
117
118	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
119	if (ret)
120		return ret;
121
122	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
123	if (ret)
124		return ret;
125
126	mt76_pci_disable_aspm(pdev);
127
128	if (id->device == MT7996_DEVICE_ID_2 ||
129	    id->device == MT7992_DEVICE_ID_2 ||
130	    id->device == MT7990_DEVICE_ID_2)
131		return mt7996_pci_hif2_probe(pdev);
132
133	dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
134				id->device);
135	if (IS_ERR(dev))
136		return PTR_ERR(dev);
137
138	mdev = &dev->mt76;
139	mt7996_wfsys_reset(dev);
140	hif2 = mt7996_pci_init_hif2(pdev);
141	dev->hif2 = hif2;
142
143	mt76_npu_init(mdev, pci_resource_start(pdev, 0),
144		      pdev->bus && pci_domain_nr(pdev->bus) ? 3 : 2);
145
146	ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
147	if (ret < 0)
148		goto free_wed_or_irq_vector;
149
150	if (!ret) {
151		ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
152		if (ret < 0)
153			goto free_device;
154
155		irq = pdev->irq;
156	}
157
158	ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
159			       IRQF_SHARED, KBUILD_MODNAME, dev);
160	if (ret)
161		goto free_wed_or_irq_vector;
162
163	mt76_wr(dev, MT_INT_MASK_CSR, 0);
164	/* master switch of PCIe interrupt enable */
165	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
166
167	if (hif2) {
168		hif2_dev = container_of(hif2->dev, struct pci_dev, dev);
169
170		ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &hif2_irq);
171		if (ret < 0)
172			goto free_hif2_wed_irq_vector;
173
174		if (!ret) {
175			ret = pci_alloc_irq_vectors(hif2_dev, 1, 1,
176						    PCI_IRQ_ALL_TYPES);
177			if (ret < 0)
178				goto free_hif2;
179
180			dev->hif2->irq = hif2_dev->irq;
181			hif2_irq = dev->hif2->irq;
182		}
183
184		ret = devm_request_irq(mdev->dev, hif2_irq, mt7996_irq_handler,
185				       IRQF_SHARED, KBUILD_MODNAME "-hif",
186				       dev);
187		if (ret)
188			goto free_hif2_wed_irq_vector;
189
190		mt76_wr(dev, MT_INT1_MASK_CSR, 0);
191		/* master switch of PCIe tnterrupt enable */
192		mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
193	}
194
195	ret = mt7996_register_device(dev);
196	if (ret)
197		goto free_hif2_irq;
198
199	return 0;
200
201free_hif2_irq:
202	if (dev->hif2)
203		devm_free_irq(mdev->dev, hif2_irq, dev);
204free_hif2_wed_irq_vector:
205	if (dev->hif2) {
206		if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
207			mtk_wed_device_detach(&dev->mt76.mmio.wed_hif2);
208		else
209			pci_free_irq_vectors(hif2_dev);
210	}
211free_hif2:
212	if (dev->hif2)
213		put_device(dev->hif2->dev);
214	devm_free_irq(mdev->dev, irq, dev);
215free_wed_or_irq_vector:
216	if (mtk_wed_device_active(&dev->mt76.mmio.wed))
217		mtk_wed_device_detach(&dev->mt76.mmio.wed);
218	else
219		pci_free_irq_vectors(pdev);
220free_device:
221	mt76_free_device(&dev->mt76);
222
223	return ret;
224}
225
226static void mt7996_hif_remove(struct pci_dev *pdev)
227{
228	struct mt7996_hif *hif = pci_get_drvdata(pdev);
229
230	list_del(&hif->list);
231}
232
233static void mt7996_pci_remove(struct pci_dev *pdev)
234{
235	struct mt76_dev *mdev;
236	struct mt7996_dev *dev;
237
238	mdev = pci_get_drvdata(pdev);
239	dev = container_of(mdev, struct mt7996_dev, mt76);
240	mt7996_put_hif2(dev->hif2);
241	mt7996_unregister_device(dev);
242}
243
244struct pci_driver mt7996_hif_driver = {
245	.name		= KBUILD_MODNAME "_hif",
246	.id_table	= mt7996_hif_device_table,
247	.probe		= mt7996_pci_probe,
248	.remove		= mt7996_hif_remove,
249};
250
251struct pci_driver mt7996_pci_driver = {
252	.name		= KBUILD_MODNAME,
253	.id_table	= mt7996_pci_device_table,
254	.probe		= mt7996_pci_probe,
255	.remove		= mt7996_pci_remove,
256};
257
258MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);
259MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);
260MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
261MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
262MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
263MODULE_FIRMWARE(MT7996_ROM_PATCH);
264MODULE_FIRMWARE(MT7992_FIRMWARE_WA);
265MODULE_FIRMWARE(MT7992_FIRMWARE_WM);
266MODULE_FIRMWARE(MT7992_FIRMWARE_DSP);
267MODULE_FIRMWARE(MT7992_ROM_PATCH);
268MODULE_FIRMWARE(MT7990_FIRMWARE_WM);
269MODULE_FIRMWARE(MT7990_ROM_PATCH);
~/ Read-only file preview.