xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7615/mmio.c (revision 8ba4d145d351db26e07695b8e90697398c5dfec2)
16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2020 MediaTek Inc. */
36c92544dSBjoern A. Zeeb 
46c92544dSBjoern A. Zeeb #include <linux/kernel.h>
56c92544dSBjoern A. Zeeb #include <linux/module.h>
66c92544dSBjoern A. Zeeb #include <linux/platform_device.h>
76c92544dSBjoern A. Zeeb #include <linux/pci.h>
86c92544dSBjoern A. Zeeb 
96c92544dSBjoern A. Zeeb #include "mt7615.h"
106c92544dSBjoern A. Zeeb #include "regs.h"
116c92544dSBjoern A. Zeeb #include "mac.h"
126c92544dSBjoern A. Zeeb #include "../trace.h"
136c92544dSBjoern A. Zeeb 
146c92544dSBjoern A. Zeeb const u32 mt7615e_reg_map[] = {
156c92544dSBjoern A. Zeeb 	[MT_TOP_CFG_BASE]	= 0x01000,
166c92544dSBjoern A. Zeeb 	[MT_HW_BASE]		= 0x01000,
176c92544dSBjoern A. Zeeb 	[MT_PCIE_REMAP_2]	= 0x02504,
186c92544dSBjoern A. Zeeb 	[MT_ARB_BASE]		= 0x20c00,
196c92544dSBjoern A. Zeeb 	[MT_HIF_BASE]		= 0x04000,
206c92544dSBjoern A. Zeeb 	[MT_CSR_BASE]		= 0x07000,
216c92544dSBjoern A. Zeeb 	[MT_PLE_BASE]		= 0x08000,
226c92544dSBjoern A. Zeeb 	[MT_PSE_BASE]		= 0x0c000,
236c92544dSBjoern A. Zeeb 	[MT_CFG_BASE]		= 0x20200,
246c92544dSBjoern A. Zeeb 	[MT_AGG_BASE]		= 0x20a00,
256c92544dSBjoern A. Zeeb 	[MT_TMAC_BASE]		= 0x21000,
266c92544dSBjoern A. Zeeb 	[MT_RMAC_BASE]		= 0x21200,
276c92544dSBjoern A. Zeeb 	[MT_DMA_BASE]		= 0x21800,
286c92544dSBjoern A. Zeeb 	[MT_PF_BASE]		= 0x22000,
296c92544dSBjoern A. Zeeb 	[MT_WTBL_BASE_ON]	= 0x23000,
306c92544dSBjoern A. Zeeb 	[MT_WTBL_BASE_OFF]	= 0x23400,
316c92544dSBjoern A. Zeeb 	[MT_LPON_BASE]		= 0x24200,
326c92544dSBjoern A. Zeeb 	[MT_MIB_BASE]		= 0x24800,
336c92544dSBjoern A. Zeeb 	[MT_WTBL_BASE_ADDR]	= 0x30000,
346c92544dSBjoern A. Zeeb 	[MT_PCIE_REMAP_BASE2]	= 0x80000,
356c92544dSBjoern A. Zeeb 	[MT_TOP_MISC_BASE]	= 0xc0000,
366c92544dSBjoern A. Zeeb 	[MT_EFUSE_ADDR_BASE]	= 0x81070000,
376c92544dSBjoern A. Zeeb };
386c92544dSBjoern A. Zeeb 
396c92544dSBjoern A. Zeeb const u32 mt7663e_reg_map[] = {
406c92544dSBjoern A. Zeeb 	[MT_TOP_CFG_BASE]	= 0x01000,
416c92544dSBjoern A. Zeeb 	[MT_HW_BASE]		= 0x02000,
426c92544dSBjoern A. Zeeb 	[MT_DMA_SHDL_BASE]	= 0x06000,
436c92544dSBjoern A. Zeeb 	[MT_PCIE_REMAP_2]	= 0x0700c,
446c92544dSBjoern A. Zeeb 	[MT_ARB_BASE]		= 0x20c00,
456c92544dSBjoern A. Zeeb 	[MT_HIF_BASE]		= 0x04000,
466c92544dSBjoern A. Zeeb 	[MT_CSR_BASE]		= 0x07000,
476c92544dSBjoern A. Zeeb 	[MT_PLE_BASE]		= 0x08000,
486c92544dSBjoern A. Zeeb 	[MT_PSE_BASE]		= 0x0c000,
496c92544dSBjoern A. Zeeb 	[MT_PP_BASE]            = 0x0e000,
506c92544dSBjoern A. Zeeb 	[MT_CFG_BASE]		= 0x20000,
516c92544dSBjoern A. Zeeb 	[MT_AGG_BASE]		= 0x22000,
526c92544dSBjoern A. Zeeb 	[MT_TMAC_BASE]		= 0x24000,
536c92544dSBjoern A. Zeeb 	[MT_RMAC_BASE]		= 0x25000,
546c92544dSBjoern A. Zeeb 	[MT_DMA_BASE]		= 0x27000,
556c92544dSBjoern A. Zeeb 	[MT_PF_BASE]		= 0x28000,
566c92544dSBjoern A. Zeeb 	[MT_WTBL_BASE_ON]	= 0x29000,
576c92544dSBjoern A. Zeeb 	[MT_WTBL_BASE_OFF]	= 0x29800,
586c92544dSBjoern A. Zeeb 	[MT_LPON_BASE]		= 0x2b000,
596c92544dSBjoern A. Zeeb 	[MT_MIB_BASE]		= 0x2d000,
606c92544dSBjoern A. Zeeb 	[MT_WTBL_BASE_ADDR]	= 0x30000,
616c92544dSBjoern A. Zeeb 	[MT_PCIE_REMAP_BASE2]	= 0x90000,
626c92544dSBjoern A. Zeeb 	[MT_TOP_MISC_BASE]	= 0xc0000,
636c92544dSBjoern A. Zeeb 	[MT_EFUSE_ADDR_BASE]	= 0x78011000,
646c92544dSBjoern A. Zeeb };
656c92544dSBjoern A. Zeeb 
666c92544dSBjoern A. Zeeb static void
mt7615_rx_poll_complete(struct mt76_dev * mdev,enum mt76_rxq_id q)676c92544dSBjoern A. Zeeb mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
686c92544dSBjoern A. Zeeb {
69cbb3ec25SBjoern A. Zeeb 	mt76_connac_irq_enable(mdev, MT_INT_RX_DONE(q));
706c92544dSBjoern A. Zeeb }
716c92544dSBjoern A. Zeeb 
mt7615_irq_handler(int irq,void * dev_instance)726c92544dSBjoern A. Zeeb static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
736c92544dSBjoern A. Zeeb {
746c92544dSBjoern A. Zeeb 	struct mt7615_dev *dev = dev_instance;
756c92544dSBjoern A. Zeeb 
766c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_INT_MASK_CSR, 0);
776c92544dSBjoern A. Zeeb 
786c92544dSBjoern A. Zeeb 	if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
796c92544dSBjoern A. Zeeb 		return IRQ_NONE;
806c92544dSBjoern A. Zeeb 
81cbb3ec25SBjoern A. Zeeb 	tasklet_schedule(&dev->mt76.irq_tasklet);
826c92544dSBjoern A. Zeeb 
836c92544dSBjoern A. Zeeb 	return IRQ_HANDLED;
846c92544dSBjoern A. Zeeb }
856c92544dSBjoern A. Zeeb 
mt7615_irq_tasklet(struct tasklet_struct * t)866c92544dSBjoern A. Zeeb static void mt7615_irq_tasklet(struct tasklet_struct *t)
876c92544dSBjoern A. Zeeb {
88cbb3ec25SBjoern A. Zeeb 	struct mt7615_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
896c92544dSBjoern A. Zeeb 	u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev);
906c92544dSBjoern A. Zeeb 	u32 mcu_int;
916c92544dSBjoern A. Zeeb 
926c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_INT_MASK_CSR, 0);
936c92544dSBjoern A. Zeeb 
946c92544dSBjoern A. Zeeb 	intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
956c92544dSBjoern A. Zeeb 	intr &= dev->mt76.mmio.irqmask;
966c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
976c92544dSBjoern A. Zeeb 
986c92544dSBjoern A. Zeeb 	trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
996c92544dSBjoern A. Zeeb 
1006c92544dSBjoern A. Zeeb 	mask |= intr & MT_INT_RX_DONE_ALL;
1016c92544dSBjoern A. Zeeb 	if (intr & tx_mcu_mask)
1026c92544dSBjoern A. Zeeb 		mask |= tx_mcu_mask;
1036c92544dSBjoern A. Zeeb 	mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
1046c92544dSBjoern A. Zeeb 
1056c92544dSBjoern A. Zeeb 	if (intr & tx_mcu_mask)
1066c92544dSBjoern A. Zeeb 		napi_schedule(&dev->mt76.tx_napi);
1076c92544dSBjoern A. Zeeb 
1086c92544dSBjoern A. Zeeb 	if (intr & MT_INT_RX_DONE(0))
1096c92544dSBjoern A. Zeeb 		napi_schedule(&dev->mt76.napi[0]);
1106c92544dSBjoern A. Zeeb 
1116c92544dSBjoern A. Zeeb 	if (intr & MT_INT_RX_DONE(1))
1126c92544dSBjoern A. Zeeb 		napi_schedule(&dev->mt76.napi[1]);
1136c92544dSBjoern A. Zeeb 
1146c92544dSBjoern A. Zeeb 	if (!(intr & (MT_INT_MCU_CMD | MT7663_INT_MCU_CMD)))
1156c92544dSBjoern A. Zeeb 		return;
1166c92544dSBjoern A. Zeeb 
1176c92544dSBjoern A. Zeeb 	if (is_mt7663(&dev->mt76)) {
1186c92544dSBjoern A. Zeeb 		mcu_int = mt76_rr(dev, MT_MCU2HOST_INT_STATUS);
1196c92544dSBjoern A. Zeeb 		mcu_int &= MT7663_MCU_CMD_ERROR_MASK;
1206c92544dSBjoern A. Zeeb 		mt76_wr(dev, MT_MCU2HOST_INT_STATUS, mcu_int);
1216c92544dSBjoern A. Zeeb 	} else {
1226c92544dSBjoern A. Zeeb 		mcu_int = mt76_rr(dev, MT_MCU_CMD);
1236c92544dSBjoern A. Zeeb 		mcu_int &= MT_MCU_CMD_ERROR_MASK;
1246c92544dSBjoern A. Zeeb 	}
1256c92544dSBjoern A. Zeeb 
1266c92544dSBjoern A. Zeeb 	if (!mcu_int)
1276c92544dSBjoern A. Zeeb 		return;
1286c92544dSBjoern A. Zeeb 
1296c92544dSBjoern A. Zeeb 	dev->reset_state = mcu_int;
1306c92544dSBjoern A. Zeeb 	queue_work(dev->mt76.wq, &dev->reset_work);
1316c92544dSBjoern A. Zeeb 	wake_up(&dev->reset_wait);
1326c92544dSBjoern A. Zeeb }
1336c92544dSBjoern A. Zeeb 
__mt7615_reg_addr(struct mt7615_dev * dev,u32 addr)1346c92544dSBjoern A. Zeeb static u32 __mt7615_reg_addr(struct mt7615_dev *dev, u32 addr)
1356c92544dSBjoern A. Zeeb {
1366c92544dSBjoern A. Zeeb 	if (addr < 0x100000)
1376c92544dSBjoern A. Zeeb 		return addr;
1386c92544dSBjoern A. Zeeb 
1396c92544dSBjoern A. Zeeb 	return mt7615_reg_map(dev, addr);
1406c92544dSBjoern A. Zeeb }
1416c92544dSBjoern A. Zeeb 
mt7615_rr(struct mt76_dev * mdev,u32 offset)1426c92544dSBjoern A. Zeeb static u32 mt7615_rr(struct mt76_dev *mdev, u32 offset)
1436c92544dSBjoern A. Zeeb {
1446c92544dSBjoern A. Zeeb 	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1456c92544dSBjoern A. Zeeb 	u32 addr = __mt7615_reg_addr(dev, offset);
1466c92544dSBjoern A. Zeeb 
1476c92544dSBjoern A. Zeeb 	return dev->bus_ops->rr(mdev, addr);
1486c92544dSBjoern A. Zeeb }
1496c92544dSBjoern A. Zeeb 
mt7615_wr(struct mt76_dev * mdev,u32 offset,u32 val)1506c92544dSBjoern A. Zeeb static void mt7615_wr(struct mt76_dev *mdev, u32 offset, u32 val)
1516c92544dSBjoern A. Zeeb {
1526c92544dSBjoern A. Zeeb 	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1536c92544dSBjoern A. Zeeb 	u32 addr = __mt7615_reg_addr(dev, offset);
1546c92544dSBjoern A. Zeeb 
1556c92544dSBjoern A. Zeeb 	dev->bus_ops->wr(mdev, addr, val);
1566c92544dSBjoern A. Zeeb }
1576c92544dSBjoern A. Zeeb 
mt7615_rmw(struct mt76_dev * mdev,u32 offset,u32 mask,u32 val)1586c92544dSBjoern A. Zeeb static u32 mt7615_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
1596c92544dSBjoern A. Zeeb {
1606c92544dSBjoern A. Zeeb 	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1616c92544dSBjoern A. Zeeb 	u32 addr = __mt7615_reg_addr(dev, offset);
1626c92544dSBjoern A. Zeeb 
1636c92544dSBjoern A. Zeeb 	return dev->bus_ops->rmw(mdev, addr, mask, val);
1646c92544dSBjoern A. Zeeb }
1656c92544dSBjoern A. Zeeb 
mt7615_mmio_probe(struct device * pdev,void __iomem * mem_base,int irq,const u32 * map)1666c92544dSBjoern A. Zeeb int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
1676c92544dSBjoern A. Zeeb 		      int irq, const u32 *map)
1686c92544dSBjoern A. Zeeb {
1696c92544dSBjoern A. Zeeb 	static const struct mt76_driver_ops drv_ops = {
1706c92544dSBjoern A. Zeeb 		/* txwi_size = txd size + txp size */
1716c92544dSBjoern A. Zeeb 		.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_txp_common),
1726c92544dSBjoern A. Zeeb 		.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
1736c92544dSBjoern A. Zeeb 		.survey_flags = SURVEY_INFO_TIME_TX |
1746c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_RX |
1756c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_BSS_RX,
1766c92544dSBjoern A. Zeeb 		.token_size = MT7615_TOKEN_SIZE,
1776c92544dSBjoern A. Zeeb 		.tx_prepare_skb = mt7615_tx_prepare_skb,
1786c92544dSBjoern A. Zeeb 		.tx_complete_skb = mt76_connac_tx_complete_skb,
1796c92544dSBjoern A. Zeeb 		.rx_check = mt7615_rx_check,
1806c92544dSBjoern A. Zeeb 		.rx_skb = mt7615_queue_rx_skb,
1816c92544dSBjoern A. Zeeb 		.rx_poll_complete = mt7615_rx_poll_complete,
1826c92544dSBjoern A. Zeeb 		.sta_add = mt7615_mac_sta_add,
1836c92544dSBjoern A. Zeeb 		.sta_remove = mt7615_mac_sta_remove,
1846c92544dSBjoern A. Zeeb 		.update_survey = mt7615_update_channel,
185*8ba4d145SBjoern A. Zeeb 		.set_channel = mt7615_set_channel,
1866c92544dSBjoern A. Zeeb 	};
1876c92544dSBjoern A. Zeeb 	struct mt76_bus_ops *bus_ops;
1886c92544dSBjoern A. Zeeb 	struct ieee80211_ops *ops;
1896c92544dSBjoern A. Zeeb 	struct mt7615_dev *dev;
1906c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev;
1916c92544dSBjoern A. Zeeb 	int ret;
1926c92544dSBjoern A. Zeeb 
1936c92544dSBjoern A. Zeeb 	ops = devm_kmemdup(pdev, &mt7615_ops, sizeof(mt7615_ops), GFP_KERNEL);
1946c92544dSBjoern A. Zeeb 	if (!ops)
1956c92544dSBjoern A. Zeeb 		return -ENOMEM;
1966c92544dSBjoern A. Zeeb 
1976c92544dSBjoern A. Zeeb 	mdev = mt76_alloc_device(pdev, sizeof(*dev), ops, &drv_ops);
1986c92544dSBjoern A. Zeeb 	if (!mdev)
1996c92544dSBjoern A. Zeeb 		return -ENOMEM;
2006c92544dSBjoern A. Zeeb 
2016c92544dSBjoern A. Zeeb 	dev = container_of(mdev, struct mt7615_dev, mt76);
2026c92544dSBjoern A. Zeeb 	mt76_mmio_init(&dev->mt76, mem_base);
203cbb3ec25SBjoern A. Zeeb 	tasklet_setup(&mdev->irq_tasklet, mt7615_irq_tasklet);
2046c92544dSBjoern A. Zeeb 
2056c92544dSBjoern A. Zeeb 	dev->reg_map = map;
2066c92544dSBjoern A. Zeeb 	dev->ops = ops;
2076c92544dSBjoern A. Zeeb 	mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
2086c92544dSBjoern A. Zeeb 		    (mt76_rr(dev, MT_HW_REV) & 0xff);
2096c92544dSBjoern A. Zeeb 	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
2106c92544dSBjoern A. Zeeb 
2116c92544dSBjoern A. Zeeb 	dev->bus_ops = dev->mt76.bus;
2126c92544dSBjoern A. Zeeb 	bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
2136c92544dSBjoern A. Zeeb 			       GFP_KERNEL);
2146c92544dSBjoern A. Zeeb 	if (!bus_ops) {
2156c92544dSBjoern A. Zeeb 		ret = -ENOMEM;
2166c92544dSBjoern A. Zeeb 		goto err_free_dev;
2176c92544dSBjoern A. Zeeb 	}
2186c92544dSBjoern A. Zeeb 
2196c92544dSBjoern A. Zeeb 	bus_ops->rr = mt7615_rr;
2206c92544dSBjoern A. Zeeb 	bus_ops->wr = mt7615_wr;
2216c92544dSBjoern A. Zeeb 	bus_ops->rmw = mt7615_rmw;
2226c92544dSBjoern A. Zeeb 	dev->mt76.bus = bus_ops;
2236c92544dSBjoern A. Zeeb 
2246c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_INT_MASK_CSR, 0);
2256c92544dSBjoern A. Zeeb 
2266c92544dSBjoern A. Zeeb 	ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler,
2276c92544dSBjoern A. Zeeb 			       IRQF_SHARED, KBUILD_MODNAME, dev);
2286c92544dSBjoern A. Zeeb 	if (ret)
2296c92544dSBjoern A. Zeeb 		goto err_free_dev;
2306c92544dSBjoern A. Zeeb 
2316c92544dSBjoern A. Zeeb 	if (is_mt7663(mdev))
2326c92544dSBjoern A. Zeeb 		mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1);
2336c92544dSBjoern A. Zeeb 
2346c92544dSBjoern A. Zeeb 	ret = mt7615_register_device(dev);
2356c92544dSBjoern A. Zeeb 	if (ret)
2366c92544dSBjoern A. Zeeb 		goto err_free_irq;
2376c92544dSBjoern A. Zeeb 
2386c92544dSBjoern A. Zeeb 	return 0;
2396c92544dSBjoern A. Zeeb 
2406c92544dSBjoern A. Zeeb err_free_irq:
2416c92544dSBjoern A. Zeeb 	devm_free_irq(pdev, irq, dev);
2426c92544dSBjoern A. Zeeb err_free_dev:
2436c92544dSBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
2446c92544dSBjoern A. Zeeb 
2456c92544dSBjoern A. Zeeb 	return ret;
2466c92544dSBjoern A. Zeeb }
2476c92544dSBjoern A. Zeeb 
mt7615_init(void)2486c92544dSBjoern A. Zeeb static int __init mt7615_init(void)
2496c92544dSBjoern A. Zeeb {
2506c92544dSBjoern A. Zeeb 	int ret;
2516c92544dSBjoern A. Zeeb 
2526c92544dSBjoern A. Zeeb 	ret = pci_register_driver(&mt7615_pci_driver);
2536c92544dSBjoern A. Zeeb 	if (ret)
2546c92544dSBjoern A. Zeeb 		return ret;
2556c92544dSBjoern A. Zeeb 
2566c92544dSBjoern A. Zeeb 	if (IS_ENABLED(CONFIG_MT7622_WMAC)) {
2576c92544dSBjoern A. Zeeb 		ret = platform_driver_register(&mt7622_wmac_driver);
2586c92544dSBjoern A. Zeeb 		if (ret)
2596c92544dSBjoern A. Zeeb 			pci_unregister_driver(&mt7615_pci_driver);
2606c92544dSBjoern A. Zeeb 	}
2616c92544dSBjoern A. Zeeb 
2626c92544dSBjoern A. Zeeb 	return ret;
2636c92544dSBjoern A. Zeeb }
2646c92544dSBjoern A. Zeeb 
mt7615_exit(void)2656c92544dSBjoern A. Zeeb static void __exit mt7615_exit(void)
2666c92544dSBjoern A. Zeeb {
2676c92544dSBjoern A. Zeeb 	if (IS_ENABLED(CONFIG_MT7622_WMAC))
2686c92544dSBjoern A. Zeeb 		platform_driver_unregister(&mt7622_wmac_driver);
2696c92544dSBjoern A. Zeeb 	pci_unregister_driver(&mt7615_pci_driver);
2706c92544dSBjoern A. Zeeb }
2716c92544dSBjoern A. Zeeb 
2726c92544dSBjoern A. Zeeb module_init(mt7615_init);
2736c92544dSBjoern A. Zeeb module_exit(mt7615_exit);
274*8ba4d145SBjoern A. Zeeb MODULE_DESCRIPTION("MediaTek MT7615E MMIO helpers");
2756c92544dSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
276