brintos

brintos / linux-shallow public Read only

0
0
Text · 5.1 KiB · 3913289 Raw
242 lines · c
1// SPDX-License-Identifier: ISC2/* 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	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7906) },22	{ },23};24 25static const struct pci_device_id mt7915_hif_device_table[] = {26	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) },27	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x790a) },28	{ },29};30 31static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx)32{33	struct mt7915_hif *hif;34	u32 val;35 36	spin_lock_bh(&hif_lock);37 38	list_for_each_entry(hif, &hif_list, list) {39		val = readl(hif->regs + MT_PCIE_RECOG_ID);40		val &= MT_PCIE_RECOG_ID_MASK;41		if (val != idx)42			continue;43 44		get_device(hif->dev);45		goto out;46	}47	hif = NULL;48 49out:50	spin_unlock_bh(&hif_lock);51 52	return hif;53}54 55static void mt7915_put_hif2(struct mt7915_hif *hif)56{57	if (!hif)58		return;59 60	put_device(hif->dev);61}62 63static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev)64{65	struct pci_dev *tmp_pdev;66 67	hif_idx++;68 69	tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL);70	if (!tmp_pdev) {71		tmp_pdev = pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL);72		if (!tmp_pdev)73			return NULL;74	}75	pci_dev_put(tmp_pdev);76 77	writel(hif_idx | MT_PCIE_RECOG_ID_SEM,78	       pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID);79 80	return mt7915_pci_get_hif2(hif_idx);81}82 83static int mt7915_pci_hif2_probe(struct pci_dev *pdev)84{85	struct mt7915_hif *hif;86 87	hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);88	if (!hif)89		return -ENOMEM;90 91	hif->dev = &pdev->dev;92	hif->regs = pcim_iomap_table(pdev)[0];93	hif->irq = pdev->irq;94	spin_lock_bh(&hif_lock);95	list_add(&hif->list, &hif_list);96	spin_unlock_bh(&hif_lock);97	pci_set_drvdata(pdev, hif);98 99	return 0;100}101 102static int mt7915_pci_probe(struct pci_dev *pdev,103			    const struct pci_device_id *id)104{105	struct mt7915_hif *hif2 = NULL;106	struct mt7915_dev *dev;107	struct mt76_dev *mdev;108	int irq;109	int ret;110 111	ret = pcim_enable_device(pdev);112	if (ret)113		return ret;114 115	ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));116	if (ret)117		return ret;118 119	pci_set_master(pdev);120 121	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));122	if (ret)123		return ret;124 125	mt76_pci_disable_aspm(pdev);126 127	if (id->device == 0x7916 || id->device == 0x790a)128		return mt7915_pci_hif2_probe(pdev);129 130	dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],131				id->device);132	if (IS_ERR(dev))133		return PTR_ERR(dev);134 135	mdev = &dev->mt76;136	mt7915_wfsys_reset(dev);137	hif2 = mt7915_pci_init_hif2(pdev);138 139	ret = mt7915_mmio_wed_init(dev, pdev, true, &irq);140	if (ret < 0)141		goto free_wed_or_irq_vector;142 143	if (!ret) {144		hif2 = mt7915_pci_init_hif2(pdev);145 146		ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);147		if (ret < 0)148			goto free_device;149 150		irq = pdev->irq;151	}152 153	ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,154			       IRQF_SHARED, KBUILD_MODNAME, dev);155	if (ret)156		goto free_wed_or_irq_vector;157 158	/* master switch of PCIe tnterrupt enable */159	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);160 161	if (hif2) {162		dev->hif2 = hif2;163 164		mt76_wr(dev, MT_INT1_MASK_CSR, 0);165		/* master switch of PCIe tnterrupt enable */166		if (is_mt7915(mdev))167			mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);168		else169			mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff);170 171		ret = devm_request_irq(mdev->dev, dev->hif2->irq,172				       mt7915_irq_handler, IRQF_SHARED,173				       KBUILD_MODNAME "-hif", dev);174		if (ret)175			goto free_hif2;176	}177 178	ret = mt7915_register_device(dev);179	if (ret)180		goto free_hif2_irq;181 182	return 0;183 184free_hif2_irq:185	if (dev->hif2)186		devm_free_irq(mdev->dev, dev->hif2->irq, dev);187free_hif2:188	if (dev->hif2)189		put_device(dev->hif2->dev);190	devm_free_irq(mdev->dev, irq, dev);191free_wed_or_irq_vector:192	if (mtk_wed_device_active(&mdev->mmio.wed))193		mtk_wed_device_detach(&mdev->mmio.wed);194	else195		pci_free_irq_vectors(pdev);196free_device:197	mt76_free_device(&dev->mt76);198 199	return ret;200}201 202static void mt7915_hif_remove(struct pci_dev *pdev)203{204	struct mt7915_hif *hif = pci_get_drvdata(pdev);205 206	list_del(&hif->list);207}208 209static void mt7915_pci_remove(struct pci_dev *pdev)210{211	struct mt76_dev *mdev;212	struct mt7915_dev *dev;213 214	mdev = pci_get_drvdata(pdev);215	dev = container_of(mdev, struct mt7915_dev, mt76);216	mt7915_put_hif2(dev->hif2);217	mt7915_unregister_device(dev);218}219 220struct pci_driver mt7915_hif_driver = {221	.name		= KBUILD_MODNAME "_hif",222	.id_table	= mt7915_hif_device_table,223	.probe		= mt7915_pci_probe,224	.remove		= mt7915_hif_remove,225};226 227struct pci_driver mt7915_pci_driver = {228	.name		= KBUILD_MODNAME,229	.id_table	= mt7915_pci_device_table,230	.probe		= mt7915_pci_probe,231	.remove		= mt7915_pci_remove,232};233 234MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table);235MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table);236MODULE_FIRMWARE(MT7915_FIRMWARE_WA);237MODULE_FIRMWARE(MT7915_FIRMWARE_WM);238MODULE_FIRMWARE(MT7915_ROM_PATCH);239MODULE_FIRMWARE(MT7916_FIRMWARE_WA);240MODULE_FIRMWARE(MT7916_FIRMWARE_WM);241MODULE_FIRMWARE(MT7916_ROM_PATCH);242