18c2ecf20Sopenharmony_ci#include <linux/kernel.h>
28c2ecf20Sopenharmony_ci#include <linux/module.h>
38c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
48c2ecf20Sopenharmony_ci#include <linux/pci.h>
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include "mt7615.h"
78c2ecf20Sopenharmony_ci#include "regs.h"
88c2ecf20Sopenharmony_ci#include "mac.h"
98c2ecf20Sopenharmony_ci#include "../trace.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ciconst u32 mt7615e_reg_map[] = {
128c2ecf20Sopenharmony_ci	[MT_TOP_CFG_BASE]	= 0x01000,
138c2ecf20Sopenharmony_ci	[MT_HW_BASE]		= 0x01000,
148c2ecf20Sopenharmony_ci	[MT_PCIE_REMAP_2]	= 0x02504,
158c2ecf20Sopenharmony_ci	[MT_ARB_BASE]		= 0x20c00,
168c2ecf20Sopenharmony_ci	[MT_HIF_BASE]		= 0x04000,
178c2ecf20Sopenharmony_ci	[MT_CSR_BASE]		= 0x07000,
188c2ecf20Sopenharmony_ci	[MT_PLE_BASE]		= 0x08000,
198c2ecf20Sopenharmony_ci	[MT_PSE_BASE]		= 0x0c000,
208c2ecf20Sopenharmony_ci	[MT_CFG_BASE]		= 0x20200,
218c2ecf20Sopenharmony_ci	[MT_AGG_BASE]		= 0x20a00,
228c2ecf20Sopenharmony_ci	[MT_TMAC_BASE]		= 0x21000,
238c2ecf20Sopenharmony_ci	[MT_RMAC_BASE]		= 0x21200,
248c2ecf20Sopenharmony_ci	[MT_DMA_BASE]		= 0x21800,
258c2ecf20Sopenharmony_ci	[MT_PF_BASE]		= 0x22000,
268c2ecf20Sopenharmony_ci	[MT_WTBL_BASE_ON]	= 0x23000,
278c2ecf20Sopenharmony_ci	[MT_WTBL_BASE_OFF]	= 0x23400,
288c2ecf20Sopenharmony_ci	[MT_LPON_BASE]		= 0x24200,
298c2ecf20Sopenharmony_ci	[MT_MIB_BASE]		= 0x24800,
308c2ecf20Sopenharmony_ci	[MT_WTBL_BASE_ADDR]	= 0x30000,
318c2ecf20Sopenharmony_ci	[MT_PCIE_REMAP_BASE2]	= 0x80000,
328c2ecf20Sopenharmony_ci	[MT_TOP_MISC_BASE]	= 0xc0000,
338c2ecf20Sopenharmony_ci	[MT_EFUSE_ADDR_BASE]	= 0x81070000,
348c2ecf20Sopenharmony_ci};
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ciconst u32 mt7663e_reg_map[] = {
378c2ecf20Sopenharmony_ci	[MT_TOP_CFG_BASE]	= 0x01000,
388c2ecf20Sopenharmony_ci	[MT_HW_BASE]		= 0x02000,
398c2ecf20Sopenharmony_ci	[MT_DMA_SHDL_BASE]	= 0x06000,
408c2ecf20Sopenharmony_ci	[MT_PCIE_REMAP_2]	= 0x0700c,
418c2ecf20Sopenharmony_ci	[MT_ARB_BASE]		= 0x20c00,
428c2ecf20Sopenharmony_ci	[MT_HIF_BASE]		= 0x04000,
438c2ecf20Sopenharmony_ci	[MT_CSR_BASE]		= 0x07000,
448c2ecf20Sopenharmony_ci	[MT_PLE_BASE]		= 0x08000,
458c2ecf20Sopenharmony_ci	[MT_PSE_BASE]		= 0x0c000,
468c2ecf20Sopenharmony_ci	[MT_PP_BASE]            = 0x0e000,
478c2ecf20Sopenharmony_ci	[MT_CFG_BASE]		= 0x20000,
488c2ecf20Sopenharmony_ci	[MT_AGG_BASE]		= 0x22000,
498c2ecf20Sopenharmony_ci	[MT_TMAC_BASE]		= 0x24000,
508c2ecf20Sopenharmony_ci	[MT_RMAC_BASE]		= 0x25000,
518c2ecf20Sopenharmony_ci	[MT_DMA_BASE]		= 0x27000,
528c2ecf20Sopenharmony_ci	[MT_PF_BASE]		= 0x28000,
538c2ecf20Sopenharmony_ci	[MT_WTBL_BASE_ON]	= 0x29000,
548c2ecf20Sopenharmony_ci	[MT_WTBL_BASE_OFF]	= 0x29800,
558c2ecf20Sopenharmony_ci	[MT_LPON_BASE]		= 0x2b000,
568c2ecf20Sopenharmony_ci	[MT_MIB_BASE]		= 0x2d000,
578c2ecf20Sopenharmony_ci	[MT_WTBL_BASE_ADDR]	= 0x30000,
588c2ecf20Sopenharmony_ci	[MT_PCIE_REMAP_BASE2]	= 0x90000,
598c2ecf20Sopenharmony_ci	[MT_TOP_MISC_BASE]	= 0xc0000,
608c2ecf20Sopenharmony_ci	[MT_EFUSE_ADDR_BASE]	= 0x78011000,
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ciu32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	u32 base, offset;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	if (is_mt7663(&dev->mt76)) {
688c2ecf20Sopenharmony_ci		base = addr & MT7663_MCU_PCIE_REMAP_2_BASE;
698c2ecf20Sopenharmony_ci		offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET;
708c2ecf20Sopenharmony_ci	} else {
718c2ecf20Sopenharmony_ci		base = addr & MT_MCU_PCIE_REMAP_2_BASE;
728c2ecf20Sopenharmony_ci		offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET;
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci	mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	return MT_PCIE_REMAP_BASE_2 + offset;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistatic void
808c2ecf20Sopenharmony_cimt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	mt7615_irq_enable(dev, MT_INT_RX_DONE(q));
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	struct mt7615_dev *dev = dev_instance;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	mt76_wr(dev, MT_INT_MASK_CSR, 0);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
948c2ecf20Sopenharmony_ci		return IRQ_NONE;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	tasklet_schedule(&dev->irq_tasklet);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistatic void mt7615_irq_tasklet(unsigned long data)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	struct mt7615_dev *dev = (struct mt7615_dev *)data;
1048c2ecf20Sopenharmony_ci	u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	mt76_wr(dev, MT_INT_MASK_CSR, 0);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
1098c2ecf20Sopenharmony_ci	intr &= dev->mt76.mmio.irqmask;
1108c2ecf20Sopenharmony_ci	mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	mask |= intr & MT_INT_RX_DONE_ALL;
1158c2ecf20Sopenharmony_ci	if (intr & tx_mcu_mask)
1168c2ecf20Sopenharmony_ci		mask |= tx_mcu_mask;
1178c2ecf20Sopenharmony_ci	mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	if (intr & tx_mcu_mask)
1208c2ecf20Sopenharmony_ci		napi_schedule(&dev->mt76.tx_napi);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	if (intr & MT_INT_RX_DONE(0))
1238c2ecf20Sopenharmony_ci		napi_schedule(&dev->mt76.napi[0]);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	if (intr & MT_INT_RX_DONE(1))
1268c2ecf20Sopenharmony_ci		napi_schedule(&dev->mt76.napi[1]);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	if (intr & MT_INT_MCU_CMD) {
1298c2ecf20Sopenharmony_ci		u32 val = mt76_rr(dev, MT_MCU_CMD);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci		if (val & MT_MCU_CMD_ERROR_MASK) {
1328c2ecf20Sopenharmony_ci			dev->reset_state = val;
1338c2ecf20Sopenharmony_ci			ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
1348c2ecf20Sopenharmony_ci			wake_up(&dev->reset_wait);
1358c2ecf20Sopenharmony_ci		}
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic u32 __mt7615_reg_addr(struct mt7615_dev *dev, u32 addr)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	if (addr < 0x100000)
1428c2ecf20Sopenharmony_ci		return addr;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	return mt7615_reg_map(dev, addr);
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic u32 mt7615_rr(struct mt76_dev *mdev, u32 offset)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1508c2ecf20Sopenharmony_ci	u32 addr = __mt7615_reg_addr(dev, offset);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	return dev->bus_ops->rr(mdev, addr);
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistatic void mt7615_wr(struct mt76_dev *mdev, u32 offset, u32 val)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1588c2ecf20Sopenharmony_ci	u32 addr = __mt7615_reg_addr(dev, offset);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	dev->bus_ops->wr(mdev, addr, val);
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic u32 mt7615_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1668c2ecf20Sopenharmony_ci	u32 addr = __mt7615_reg_addr(dev, offset);
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	return dev->bus_ops->rmw(mdev, addr, mask, val);
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ciint mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
1728c2ecf20Sopenharmony_ci		      int irq, const u32 *map)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	static const struct mt76_driver_ops drv_ops = {
1758c2ecf20Sopenharmony_ci		/* txwi_size = txd size + txp size */
1768c2ecf20Sopenharmony_ci		.txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common),
1778c2ecf20Sopenharmony_ci		.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
1788c2ecf20Sopenharmony_ci		.survey_flags = SURVEY_INFO_TIME_TX |
1798c2ecf20Sopenharmony_ci				SURVEY_INFO_TIME_RX |
1808c2ecf20Sopenharmony_ci				SURVEY_INFO_TIME_BSS_RX,
1818c2ecf20Sopenharmony_ci		.tx_prepare_skb = mt7615_tx_prepare_skb,
1828c2ecf20Sopenharmony_ci		.tx_complete_skb = mt7615_tx_complete_skb,
1838c2ecf20Sopenharmony_ci		.rx_skb = mt7615_queue_rx_skb,
1848c2ecf20Sopenharmony_ci		.rx_poll_complete = mt7615_rx_poll_complete,
1858c2ecf20Sopenharmony_ci		.sta_ps = mt7615_sta_ps,
1868c2ecf20Sopenharmony_ci		.sta_add = mt7615_mac_sta_add,
1878c2ecf20Sopenharmony_ci		.sta_remove = mt7615_mac_sta_remove,
1888c2ecf20Sopenharmony_ci		.update_survey = mt7615_update_channel,
1898c2ecf20Sopenharmony_ci	};
1908c2ecf20Sopenharmony_ci	struct mt76_bus_ops *bus_ops;
1918c2ecf20Sopenharmony_ci	struct ieee80211_ops *ops;
1928c2ecf20Sopenharmony_ci	struct mt7615_dev *dev;
1938c2ecf20Sopenharmony_ci	struct mt76_dev *mdev;
1948c2ecf20Sopenharmony_ci	int ret;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	ops = devm_kmemdup(pdev, &mt7615_ops, sizeof(mt7615_ops), GFP_KERNEL);
1978c2ecf20Sopenharmony_ci	if (!ops)
1988c2ecf20Sopenharmony_ci		return -ENOMEM;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	mdev = mt76_alloc_device(pdev, sizeof(*dev), ops, &drv_ops);
2018c2ecf20Sopenharmony_ci	if (!mdev)
2028c2ecf20Sopenharmony_ci		return -ENOMEM;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	dev = container_of(mdev, struct mt7615_dev, mt76);
2058c2ecf20Sopenharmony_ci	mt76_mmio_init(&dev->mt76, mem_base);
2068c2ecf20Sopenharmony_ci	tasklet_init(&dev->irq_tasklet, mt7615_irq_tasklet, (unsigned long)dev);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	dev->reg_map = map;
2098c2ecf20Sopenharmony_ci	dev->ops = ops;
2108c2ecf20Sopenharmony_ci	mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
2118c2ecf20Sopenharmony_ci		    (mt76_rr(dev, MT_HW_REV) & 0xff);
2128c2ecf20Sopenharmony_ci	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	dev->bus_ops = dev->mt76.bus;
2158c2ecf20Sopenharmony_ci	bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
2168c2ecf20Sopenharmony_ci			       GFP_KERNEL);
2178c2ecf20Sopenharmony_ci	if (!bus_ops) {
2188c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2198c2ecf20Sopenharmony_ci		goto error;
2208c2ecf20Sopenharmony_ci	}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	bus_ops->rr = mt7615_rr;
2238c2ecf20Sopenharmony_ci	bus_ops->wr = mt7615_wr;
2248c2ecf20Sopenharmony_ci	bus_ops->rmw = mt7615_rmw;
2258c2ecf20Sopenharmony_ci	dev->mt76.bus = bus_ops;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	mt76_wr(dev, MT_INT_MASK_CSR, 0);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler,
2308c2ecf20Sopenharmony_ci			       IRQF_SHARED, KBUILD_MODNAME, dev);
2318c2ecf20Sopenharmony_ci	if (ret)
2328c2ecf20Sopenharmony_ci		goto error;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	if (is_mt7663(mdev))
2358c2ecf20Sopenharmony_ci		mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	ret = mt7615_register_device(dev);
2388c2ecf20Sopenharmony_ci	if (ret)
2398c2ecf20Sopenharmony_ci		goto error;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	return 0;
2428c2ecf20Sopenharmony_cierror:
2438c2ecf20Sopenharmony_ci	mt76_free_device(&dev->mt76);
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	return ret;
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cistatic int __init mt7615_init(void)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	int ret;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	ret = pci_register_driver(&mt7615_pci_driver);
2538c2ecf20Sopenharmony_ci	if (ret)
2548c2ecf20Sopenharmony_ci		return ret;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_MT7622_WMAC)) {
2578c2ecf20Sopenharmony_ci		ret = platform_driver_register(&mt7622_wmac_driver);
2588c2ecf20Sopenharmony_ci		if (ret)
2598c2ecf20Sopenharmony_ci			pci_unregister_driver(&mt7615_pci_driver);
2608c2ecf20Sopenharmony_ci	}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	return ret;
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic void __exit mt7615_exit(void)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_MT7622_WMAC))
2688c2ecf20Sopenharmony_ci		platform_driver_unregister(&mt7622_wmac_driver);
2698c2ecf20Sopenharmony_ci	pci_unregister_driver(&mt7615_pci_driver);
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cimodule_init(mt7615_init);
2738c2ecf20Sopenharmony_cimodule_exit(mt7615_exit);
2748c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
275