developer | b11a539 | 2022-03-31 00:34:47 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: ISC |
| 2 | /* Copyright (C) 2020 MediaTek Inc. */ |
| 3 | |
| 4 | #include <linux/kernel.h> |
| 5 | #include <linux/module.h> |
| 6 | #include <linux/platform_device.h> |
| 7 | #include <linux/pci.h> |
| 8 | |
| 9 | #include "mt7615.h" |
| 10 | #include "regs.h" |
| 11 | #include "mac.h" |
| 12 | #include "../trace.h" |
| 13 | |
| 14 | const u32 mt7615e_reg_map[] = { |
| 15 | [MT_TOP_CFG_BASE] = 0x01000, |
| 16 | [MT_HW_BASE] = 0x01000, |
| 17 | [MT_PCIE_REMAP_2] = 0x02504, |
| 18 | [MT_ARB_BASE] = 0x20c00, |
| 19 | [MT_HIF_BASE] = 0x04000, |
| 20 | [MT_CSR_BASE] = 0x07000, |
| 21 | [MT_PLE_BASE] = 0x08000, |
| 22 | [MT_PSE_BASE] = 0x0c000, |
| 23 | [MT_CFG_BASE] = 0x20200, |
| 24 | [MT_AGG_BASE] = 0x20a00, |
| 25 | [MT_TMAC_BASE] = 0x21000, |
| 26 | [MT_RMAC_BASE] = 0x21200, |
| 27 | [MT_DMA_BASE] = 0x21800, |
| 28 | [MT_PF_BASE] = 0x22000, |
| 29 | [MT_WTBL_BASE_ON] = 0x23000, |
| 30 | [MT_WTBL_BASE_OFF] = 0x23400, |
| 31 | [MT_LPON_BASE] = 0x24200, |
| 32 | [MT_MIB_BASE] = 0x24800, |
| 33 | [MT_WTBL_BASE_ADDR] = 0x30000, |
| 34 | [MT_PCIE_REMAP_BASE2] = 0x80000, |
| 35 | [MT_TOP_MISC_BASE] = 0xc0000, |
| 36 | [MT_EFUSE_ADDR_BASE] = 0x81070000, |
| 37 | }; |
| 38 | |
| 39 | const u32 mt7663e_reg_map[] = { |
| 40 | [MT_TOP_CFG_BASE] = 0x01000, |
| 41 | [MT_HW_BASE] = 0x02000, |
| 42 | [MT_DMA_SHDL_BASE] = 0x06000, |
| 43 | [MT_PCIE_REMAP_2] = 0x0700c, |
| 44 | [MT_ARB_BASE] = 0x20c00, |
| 45 | [MT_HIF_BASE] = 0x04000, |
| 46 | [MT_CSR_BASE] = 0x07000, |
| 47 | [MT_PLE_BASE] = 0x08000, |
| 48 | [MT_PSE_BASE] = 0x0c000, |
| 49 | [MT_PP_BASE] = 0x0e000, |
| 50 | [MT_CFG_BASE] = 0x20000, |
| 51 | [MT_AGG_BASE] = 0x22000, |
| 52 | [MT_TMAC_BASE] = 0x24000, |
| 53 | [MT_RMAC_BASE] = 0x25000, |
| 54 | [MT_DMA_BASE] = 0x27000, |
| 55 | [MT_PF_BASE] = 0x28000, |
| 56 | [MT_WTBL_BASE_ON] = 0x29000, |
| 57 | [MT_WTBL_BASE_OFF] = 0x29800, |
| 58 | [MT_LPON_BASE] = 0x2b000, |
| 59 | [MT_MIB_BASE] = 0x2d000, |
| 60 | [MT_WTBL_BASE_ADDR] = 0x30000, |
| 61 | [MT_PCIE_REMAP_BASE2] = 0x90000, |
| 62 | [MT_TOP_MISC_BASE] = 0xc0000, |
| 63 | [MT_EFUSE_ADDR_BASE] = 0x78011000, |
| 64 | }; |
| 65 | |
| 66 | u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) |
| 67 | { |
| 68 | u32 base, offset; |
| 69 | |
| 70 | if (is_mt7663(&dev->mt76)) { |
| 71 | base = addr & MT7663_MCU_PCIE_REMAP_2_BASE; |
| 72 | offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET; |
| 73 | } else { |
| 74 | base = addr & MT_MCU_PCIE_REMAP_2_BASE; |
| 75 | offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; |
| 76 | } |
| 77 | mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); |
| 78 | |
| 79 | return MT_PCIE_REMAP_BASE_2 + offset; |
| 80 | } |
| 81 | |
| 82 | static void |
| 83 | mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) |
| 84 | { |
| 85 | struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); |
| 86 | |
| 87 | mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); |
| 88 | } |
| 89 | |
| 90 | static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) |
| 91 | { |
| 92 | struct mt7615_dev *dev = dev_instance; |
| 93 | |
| 94 | mt76_wr(dev, MT_INT_MASK_CSR, 0); |
| 95 | |
| 96 | if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) |
| 97 | return IRQ_NONE; |
| 98 | |
| 99 | tasklet_schedule(&dev->irq_tasklet); |
| 100 | |
| 101 | return IRQ_HANDLED; |
| 102 | } |
| 103 | |
| 104 | static void mt7615_irq_tasklet(struct tasklet_struct *t) |
| 105 | { |
| 106 | struct mt7615_dev *dev = from_tasklet(dev, t, irq_tasklet); |
| 107 | u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev); |
| 108 | u32 mcu_int; |
| 109 | |
| 110 | mt76_wr(dev, MT_INT_MASK_CSR, 0); |
| 111 | |
| 112 | intr = mt76_rr(dev, MT_INT_SOURCE_CSR); |
| 113 | intr &= dev->mt76.mmio.irqmask; |
| 114 | mt76_wr(dev, MT_INT_SOURCE_CSR, intr); |
| 115 | |
| 116 | trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); |
| 117 | |
| 118 | mask |= intr & MT_INT_RX_DONE_ALL; |
| 119 | if (intr & tx_mcu_mask) |
| 120 | mask |= tx_mcu_mask; |
| 121 | mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); |
| 122 | |
| 123 | if (intr & tx_mcu_mask) |
| 124 | napi_schedule(&dev->mt76.tx_napi); |
| 125 | |
| 126 | if (intr & MT_INT_RX_DONE(0)) |
| 127 | napi_schedule(&dev->mt76.napi[0]); |
| 128 | |
| 129 | if (intr & MT_INT_RX_DONE(1)) |
| 130 | napi_schedule(&dev->mt76.napi[1]); |
| 131 | |
| 132 | if (!(intr & (MT_INT_MCU_CMD | MT7663_INT_MCU_CMD))) |
| 133 | return; |
| 134 | |
| 135 | if (is_mt7663(&dev->mt76)) { |
| 136 | mcu_int = mt76_rr(dev, MT_MCU2HOST_INT_STATUS); |
| 137 | mcu_int &= MT7663_MCU_CMD_ERROR_MASK; |
| 138 | mt76_wr(dev, MT_MCU2HOST_INT_STATUS, mcu_int); |
| 139 | } else { |
| 140 | mcu_int = mt76_rr(dev, MT_MCU_CMD); |
| 141 | mcu_int &= MT_MCU_CMD_ERROR_MASK; |
| 142 | } |
| 143 | |
| 144 | if (!mcu_int) |
| 145 | return; |
| 146 | |
| 147 | dev->reset_state = mcu_int; |
| 148 | ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); |
| 149 | wake_up(&dev->reset_wait); |
| 150 | } |
| 151 | |
| 152 | static u32 __mt7615_reg_addr(struct mt7615_dev *dev, u32 addr) |
| 153 | { |
| 154 | if (addr < 0x100000) |
| 155 | return addr; |
| 156 | |
| 157 | return mt7615_reg_map(dev, addr); |
| 158 | } |
| 159 | |
| 160 | static u32 mt7615_rr(struct mt76_dev *mdev, u32 offset) |
| 161 | { |
| 162 | struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); |
| 163 | u32 addr = __mt7615_reg_addr(dev, offset); |
| 164 | |
| 165 | return dev->bus_ops->rr(mdev, addr); |
| 166 | } |
| 167 | |
| 168 | static void mt7615_wr(struct mt76_dev *mdev, u32 offset, u32 val) |
| 169 | { |
| 170 | struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); |
| 171 | u32 addr = __mt7615_reg_addr(dev, offset); |
| 172 | |
| 173 | dev->bus_ops->wr(mdev, addr, val); |
| 174 | } |
| 175 | |
| 176 | static u32 mt7615_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) |
| 177 | { |
| 178 | struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); |
| 179 | u32 addr = __mt7615_reg_addr(dev, offset); |
| 180 | |
| 181 | return dev->bus_ops->rmw(mdev, addr, mask, val); |
| 182 | } |
| 183 | |
| 184 | int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, |
| 185 | int irq, const u32 *map) |
| 186 | { |
| 187 | static const struct mt76_driver_ops drv_ops = { |
| 188 | /* txwi_size = txd size + txp size */ |
| 189 | .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common), |
| 190 | .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ, |
| 191 | .survey_flags = SURVEY_INFO_TIME_TX | |
| 192 | SURVEY_INFO_TIME_RX | |
| 193 | SURVEY_INFO_TIME_BSS_RX, |
| 194 | .token_size = MT7615_TOKEN_SIZE, |
| 195 | .tx_prepare_skb = mt7615_tx_prepare_skb, |
| 196 | .tx_complete_skb = mt7615_tx_complete_skb, |
| 197 | .rx_check = mt7615_rx_check, |
| 198 | .rx_skb = mt7615_queue_rx_skb, |
| 199 | .rx_poll_complete = mt7615_rx_poll_complete, |
| 200 | .sta_ps = mt7615_sta_ps, |
| 201 | .sta_add = mt7615_mac_sta_add, |
| 202 | .sta_remove = mt7615_mac_sta_remove, |
| 203 | .update_survey = mt7615_update_channel, |
| 204 | }; |
| 205 | struct mt76_bus_ops *bus_ops; |
| 206 | struct ieee80211_ops *ops; |
| 207 | struct mt7615_dev *dev; |
| 208 | struct mt76_dev *mdev; |
| 209 | int ret; |
| 210 | |
| 211 | ops = devm_kmemdup(pdev, &mt7615_ops, sizeof(mt7615_ops), GFP_KERNEL); |
| 212 | if (!ops) |
| 213 | return -ENOMEM; |
| 214 | |
| 215 | mdev = mt76_alloc_device(pdev, sizeof(*dev), ops, &drv_ops); |
| 216 | if (!mdev) |
| 217 | return -ENOMEM; |
| 218 | |
| 219 | dev = container_of(mdev, struct mt7615_dev, mt76); |
| 220 | mt76_mmio_init(&dev->mt76, mem_base); |
| 221 | tasklet_setup(&dev->irq_tasklet, mt7615_irq_tasklet); |
| 222 | |
| 223 | dev->reg_map = map; |
| 224 | dev->ops = ops; |
| 225 | mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | |
| 226 | (mt76_rr(dev, MT_HW_REV) & 0xff); |
| 227 | dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); |
| 228 | |
| 229 | dev->bus_ops = dev->mt76.bus; |
| 230 | bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), |
| 231 | GFP_KERNEL); |
| 232 | if (!bus_ops) { |
| 233 | ret = -ENOMEM; |
| 234 | goto err_free_dev; |
| 235 | } |
| 236 | |
| 237 | bus_ops->rr = mt7615_rr; |
| 238 | bus_ops->wr = mt7615_wr; |
| 239 | bus_ops->rmw = mt7615_rmw; |
| 240 | dev->mt76.bus = bus_ops; |
| 241 | |
| 242 | mt76_wr(dev, MT_INT_MASK_CSR, 0); |
| 243 | |
| 244 | ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler, |
| 245 | IRQF_SHARED, KBUILD_MODNAME, dev); |
| 246 | if (ret) |
| 247 | goto err_free_dev; |
| 248 | |
| 249 | if (is_mt7663(mdev)) |
| 250 | mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1); |
| 251 | |
| 252 | ret = mt7615_register_device(dev); |
| 253 | if (ret) |
| 254 | goto err_free_irq; |
| 255 | |
| 256 | return 0; |
| 257 | |
| 258 | err_free_irq: |
| 259 | devm_free_irq(pdev, irq, dev); |
| 260 | err_free_dev: |
| 261 | mt76_free_device(&dev->mt76); |
| 262 | |
| 263 | return ret; |
| 264 | } |
| 265 | |
| 266 | static int __init mt7615_init(void) |
| 267 | { |
| 268 | int ret; |
| 269 | |
| 270 | ret = pci_register_driver(&mt7615_pci_driver); |
| 271 | if (ret) |
| 272 | return ret; |
| 273 | |
| 274 | if (IS_ENABLED(CONFIG_MT7622_WMAC)) { |
| 275 | ret = platform_driver_register(&mt7622_wmac_driver); |
| 276 | if (ret) |
| 277 | pci_unregister_driver(&mt7615_pci_driver); |
| 278 | } |
| 279 | |
| 280 | return ret; |
| 281 | } |
| 282 | |
| 283 | static void __exit mt7615_exit(void) |
| 284 | { |
| 285 | if (IS_ENABLED(CONFIG_MT7622_WMAC)) |
| 286 | platform_driver_unregister(&mt7622_wmac_driver); |
| 287 | pci_unregister_driver(&mt7615_pci_driver); |
| 288 | } |
| 289 | |
| 290 | module_init(mt7615_init); |
| 291 | module_exit(mt7615_exit); |
| 292 | MODULE_LICENSE("Dual BSD/GPL"); |