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