1134b2d0dSStanislaw Gruszka /* 2134b2d0dSStanislaw Gruszka * (c) Copyright 2002-2010, Ralink Technology, Inc. 3134b2d0dSStanislaw Gruszka * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> 4134b2d0dSStanislaw Gruszka * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> 5134b2d0dSStanislaw Gruszka * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> 6134b2d0dSStanislaw Gruszka * 7134b2d0dSStanislaw Gruszka * This program is free software; you can redistribute it and/or modify 8134b2d0dSStanislaw Gruszka * it under the terms of the GNU General Public License version 2 9134b2d0dSStanislaw Gruszka * as published by the Free Software Foundation 10134b2d0dSStanislaw Gruszka * 11134b2d0dSStanislaw Gruszka * This program is distributed in the hope that it will be useful, 12134b2d0dSStanislaw Gruszka * but WITHOUT ANY WARRANTY; without even the implied warranty of 13134b2d0dSStanislaw Gruszka * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14134b2d0dSStanislaw Gruszka * GNU General Public License for more details. 15134b2d0dSStanislaw Gruszka */ 16134b2d0dSStanislaw Gruszka 17134b2d0dSStanislaw Gruszka #include "mt76x0.h" 18134b2d0dSStanislaw Gruszka #include "eeprom.h" 19134b2d0dSStanislaw Gruszka #include "trace.h" 20134b2d0dSStanislaw Gruszka #include "mcu.h" 21134b2d0dSStanislaw Gruszka #include "usb.h" 22134b2d0dSStanislaw Gruszka 23134b2d0dSStanislaw Gruszka #include "initvals.h" 24134b2d0dSStanislaw Gruszka 25134b2d0dSStanislaw Gruszka static void 26134b2d0dSStanislaw Gruszka mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable) 27134b2d0dSStanislaw Gruszka { 28134b2d0dSStanislaw Gruszka int i; 29134b2d0dSStanislaw Gruszka 30134b2d0dSStanislaw Gruszka /* Note: we don't turn off WLAN_CLK because that makes the device 31134b2d0dSStanislaw Gruszka * not respond properly on the probe path. 32134b2d0dSStanislaw Gruszka * In case anyone (PSM?) wants to use this function we can 33134b2d0dSStanislaw Gruszka * bring the clock stuff back and fixup the probe path. 34134b2d0dSStanislaw Gruszka */ 35134b2d0dSStanislaw Gruszka 36134b2d0dSStanislaw Gruszka if (enable) 37134b2d0dSStanislaw Gruszka val |= (MT_WLAN_FUN_CTRL_WLAN_EN | 38134b2d0dSStanislaw Gruszka MT_WLAN_FUN_CTRL_WLAN_CLK_EN); 39134b2d0dSStanislaw Gruszka else 40134b2d0dSStanislaw Gruszka val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN); 41134b2d0dSStanislaw Gruszka 42134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_WLAN_FUN_CTRL, val); 43134b2d0dSStanislaw Gruszka udelay(20); 44134b2d0dSStanislaw Gruszka 45134b2d0dSStanislaw Gruszka if (!enable) 46134b2d0dSStanislaw Gruszka return; 47134b2d0dSStanislaw Gruszka 48134b2d0dSStanislaw Gruszka for (i = 200; i; i--) { 49134b2d0dSStanislaw Gruszka val = mt76_rr(dev, MT_CMB_CTRL); 50134b2d0dSStanislaw Gruszka 51134b2d0dSStanislaw Gruszka if (val & MT_CMB_CTRL_XTAL_RDY && val & MT_CMB_CTRL_PLL_LD) 52134b2d0dSStanislaw Gruszka break; 53134b2d0dSStanislaw Gruszka 54134b2d0dSStanislaw Gruszka udelay(20); 55134b2d0dSStanislaw Gruszka } 56134b2d0dSStanislaw Gruszka 57134b2d0dSStanislaw Gruszka /* Note: vendor driver tries to disable/enable wlan here and retry 58134b2d0dSStanislaw Gruszka * but the code which does it is so buggy it must have never 59134b2d0dSStanislaw Gruszka * triggered, so don't bother. 60134b2d0dSStanislaw Gruszka */ 61134b2d0dSStanislaw Gruszka if (!i) 62134b2d0dSStanislaw Gruszka dev_err(dev->mt76.dev, "Error: PLL and XTAL check failed!\n"); 63134b2d0dSStanislaw Gruszka } 64134b2d0dSStanislaw Gruszka 65369bbecdSStanislaw Gruszka void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset) 66134b2d0dSStanislaw Gruszka { 67134b2d0dSStanislaw Gruszka u32 val; 68134b2d0dSStanislaw Gruszka 69134b2d0dSStanislaw Gruszka mutex_lock(&dev->hw_atomic_mutex); 70134b2d0dSStanislaw Gruszka 71134b2d0dSStanislaw Gruszka val = mt76_rr(dev, MT_WLAN_FUN_CTRL); 72134b2d0dSStanislaw Gruszka 73134b2d0dSStanislaw Gruszka if (reset) { 74134b2d0dSStanislaw Gruszka val |= MT_WLAN_FUN_CTRL_GPIO_OUT_EN; 75134b2d0dSStanislaw Gruszka val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL; 76134b2d0dSStanislaw Gruszka 77134b2d0dSStanislaw Gruszka if (val & MT_WLAN_FUN_CTRL_WLAN_EN) { 78134b2d0dSStanislaw Gruszka val |= (MT_WLAN_FUN_CTRL_WLAN_RESET | 79134b2d0dSStanislaw Gruszka MT_WLAN_FUN_CTRL_WLAN_RESET_RF); 80134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_WLAN_FUN_CTRL, val); 81134b2d0dSStanislaw Gruszka udelay(20); 82134b2d0dSStanislaw Gruszka 83134b2d0dSStanislaw Gruszka val &= ~(MT_WLAN_FUN_CTRL_WLAN_RESET | 84134b2d0dSStanislaw Gruszka MT_WLAN_FUN_CTRL_WLAN_RESET_RF); 85134b2d0dSStanislaw Gruszka } 86134b2d0dSStanislaw Gruszka } 87134b2d0dSStanislaw Gruszka 88134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_WLAN_FUN_CTRL, val); 89134b2d0dSStanislaw Gruszka udelay(20); 90134b2d0dSStanislaw Gruszka 91134b2d0dSStanislaw Gruszka mt76x0_set_wlan_state(dev, val, enable); 92134b2d0dSStanislaw Gruszka 93134b2d0dSStanislaw Gruszka mutex_unlock(&dev->hw_atomic_mutex); 94134b2d0dSStanislaw Gruszka } 95134b2d0dSStanislaw Gruszka 96134b2d0dSStanislaw Gruszka static void mt76x0_reset_csr_bbp(struct mt76x0_dev *dev) 97134b2d0dSStanislaw Gruszka { 98134b2d0dSStanislaw Gruszka u32 val; 99134b2d0dSStanislaw Gruszka 100134b2d0dSStanislaw Gruszka val = mt76_rr(dev, MT_PBF_SYS_CTRL); 101134b2d0dSStanislaw Gruszka val &= ~0x2000; 102134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_PBF_SYS_CTRL, val); 103134b2d0dSStanislaw Gruszka 104134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR | 105134b2d0dSStanislaw Gruszka MT_MAC_SYS_CTRL_RESET_BBP); 106134b2d0dSStanislaw Gruszka 107134b2d0dSStanislaw Gruszka msleep(200); 108134b2d0dSStanislaw Gruszka } 109134b2d0dSStanislaw Gruszka 110134b2d0dSStanislaw Gruszka static void mt76x0_init_usb_dma(struct mt76x0_dev *dev) 111134b2d0dSStanislaw Gruszka { 112134b2d0dSStanislaw Gruszka u32 val; 113134b2d0dSStanislaw Gruszka 114134b2d0dSStanislaw Gruszka val = mt76_rr(dev, MT_USB_DMA_CFG); 115134b2d0dSStanislaw Gruszka 116134b2d0dSStanislaw Gruszka val |= FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, MT_USB_AGGR_TIMEOUT) | 117134b2d0dSStanislaw Gruszka FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_LMT, MT_USB_AGGR_SIZE_LIMIT) | 118134b2d0dSStanislaw Gruszka MT_USB_DMA_CFG_RX_BULK_EN | 119134b2d0dSStanislaw Gruszka MT_USB_DMA_CFG_TX_BULK_EN; 120134b2d0dSStanislaw Gruszka if (dev->in_max_packet == 512) 121134b2d0dSStanislaw Gruszka val |= MT_USB_DMA_CFG_RX_BULK_AGG_EN; 122134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_USB_DMA_CFG, val); 123134b2d0dSStanislaw Gruszka 124134b2d0dSStanislaw Gruszka val = mt76_rr(dev, MT_COM_REG0); 125134b2d0dSStanislaw Gruszka if (val & 1) 126134b2d0dSStanislaw Gruszka dev_dbg(dev->mt76.dev, "MCU not ready\n"); 127134b2d0dSStanislaw Gruszka 128134b2d0dSStanislaw Gruszka val = mt76_rr(dev, MT_USB_DMA_CFG); 129134b2d0dSStanislaw Gruszka 130134b2d0dSStanislaw Gruszka val |= MT_USB_DMA_CFG_RX_DROP_OR_PADDING; 131134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_USB_DMA_CFG, val); 132134b2d0dSStanislaw Gruszka val &= ~MT_USB_DMA_CFG_RX_DROP_OR_PADDING; 133134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_USB_DMA_CFG, val); 134134b2d0dSStanislaw Gruszka } 135134b2d0dSStanislaw Gruszka 136134b2d0dSStanislaw Gruszka #define RANDOM_WRITE(dev, tab) \ 137134b2d0dSStanislaw Gruszka mt76x0_write_reg_pairs(dev, MT_MCU_MEMMAP_WLAN, tab, ARRAY_SIZE(tab)); 138134b2d0dSStanislaw Gruszka 139134b2d0dSStanislaw Gruszka static int mt76x0_init_bbp(struct mt76x0_dev *dev) 140134b2d0dSStanislaw Gruszka { 141134b2d0dSStanislaw Gruszka int ret, i; 142134b2d0dSStanislaw Gruszka 143134b2d0dSStanislaw Gruszka ret = mt76x0_wait_bbp_ready(dev); 144134b2d0dSStanislaw Gruszka if (ret) 145134b2d0dSStanislaw Gruszka return ret; 146134b2d0dSStanislaw Gruszka 147134b2d0dSStanislaw Gruszka RANDOM_WRITE(dev, mt76x0_bbp_init_tab); 148134b2d0dSStanislaw Gruszka 149134b2d0dSStanislaw Gruszka for (i = 0; i < ARRAY_SIZE(mt76x0_bbp_switch_tab); i++) { 150134b2d0dSStanislaw Gruszka const struct mt76x0_bbp_switch_item *item = &mt76x0_bbp_switch_tab[i]; 151134b2d0dSStanislaw Gruszka const struct mt76_reg_pair *pair = &item->reg_pair; 152134b2d0dSStanislaw Gruszka 153134b2d0dSStanislaw Gruszka if (((RF_G_BAND | RF_BW_20) & item->bw_band) == (RF_G_BAND | RF_BW_20)) 154134b2d0dSStanislaw Gruszka mt76_wr(dev, pair->reg, pair->value); 155134b2d0dSStanislaw Gruszka } 156134b2d0dSStanislaw Gruszka 157134b2d0dSStanislaw Gruszka RANDOM_WRITE(dev, mt76x0_dcoc_tab); 158134b2d0dSStanislaw Gruszka 159134b2d0dSStanislaw Gruszka return 0; 160134b2d0dSStanislaw Gruszka } 161134b2d0dSStanislaw Gruszka 162134b2d0dSStanislaw Gruszka static void 163134b2d0dSStanislaw Gruszka mt76_init_beacon_offsets(struct mt76x0_dev *dev) 164134b2d0dSStanislaw Gruszka { 165134b2d0dSStanislaw Gruszka u16 base = MT_BEACON_BASE; 166134b2d0dSStanislaw Gruszka u32 regs[4] = {}; 167134b2d0dSStanislaw Gruszka int i; 168134b2d0dSStanislaw Gruszka 169134b2d0dSStanislaw Gruszka for (i = 0; i < 16; i++) { 170134b2d0dSStanislaw Gruszka u16 addr = dev->beacon_offsets[i]; 171134b2d0dSStanislaw Gruszka 172134b2d0dSStanislaw Gruszka regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4)); 173134b2d0dSStanislaw Gruszka } 174134b2d0dSStanislaw Gruszka 175134b2d0dSStanislaw Gruszka for (i = 0; i < 4; i++) 176134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]); 177134b2d0dSStanislaw Gruszka } 178134b2d0dSStanislaw Gruszka 179134b2d0dSStanislaw Gruszka static void mt76x0_init_mac_registers(struct mt76x0_dev *dev) 180134b2d0dSStanislaw Gruszka { 181134b2d0dSStanislaw Gruszka u32 reg; 182134b2d0dSStanislaw Gruszka 183134b2d0dSStanislaw Gruszka RANDOM_WRITE(dev, common_mac_reg_table); 184134b2d0dSStanislaw Gruszka 185134b2d0dSStanislaw Gruszka mt76_init_beacon_offsets(dev); 186134b2d0dSStanislaw Gruszka 187134b2d0dSStanislaw Gruszka /* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */ 188134b2d0dSStanislaw Gruszka RANDOM_WRITE(dev, mt76x0_mac_reg_table); 189134b2d0dSStanislaw Gruszka 190134b2d0dSStanislaw Gruszka /* Release BBP and MAC reset MAC_SYS_CTRL[1:0] = 0x0 */ 191134b2d0dSStanislaw Gruszka reg = mt76_rr(dev, MT_MAC_SYS_CTRL); 192134b2d0dSStanislaw Gruszka reg &= ~0x3; 193134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_MAC_SYS_CTRL, reg); 194134b2d0dSStanislaw Gruszka 195134b2d0dSStanislaw Gruszka if (is_mt7610e(dev)) { 196134b2d0dSStanislaw Gruszka /* Disable COEX_EN */ 197134b2d0dSStanislaw Gruszka reg = mt76_rr(dev, MT_COEXCFG0); 198134b2d0dSStanislaw Gruszka reg &= 0xFFFFFFFE; 199134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_COEXCFG0, reg); 200134b2d0dSStanislaw Gruszka } 201134b2d0dSStanislaw Gruszka 202134b2d0dSStanislaw Gruszka /* Set 0x141C[15:12]=0xF */ 203134b2d0dSStanislaw Gruszka reg = mt76_rr(dev, MT_EXT_CCA_CFG); 204134b2d0dSStanislaw Gruszka reg |= 0x0000F000; 205134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_EXT_CCA_CFG, reg); 206134b2d0dSStanislaw Gruszka 207134b2d0dSStanislaw Gruszka mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN); 208134b2d0dSStanislaw Gruszka 209134b2d0dSStanislaw Gruszka /* 210134b2d0dSStanislaw Gruszka TxRing 9 is for Mgmt frame. 211134b2d0dSStanislaw Gruszka TxRing 8 is for In-band command frame. 212134b2d0dSStanislaw Gruszka WMM_RG0_TXQMA: This register setting is for FCE to define the rule of TxRing 9. 213134b2d0dSStanislaw Gruszka WMM_RG1_TXQMA: This register setting is for FCE to define the rule of TxRing 8. 214134b2d0dSStanislaw Gruszka */ 215134b2d0dSStanislaw Gruszka reg = mt76_rr(dev, MT_WMM_CTRL); 216134b2d0dSStanislaw Gruszka reg &= ~0x000003FF; 217134b2d0dSStanislaw Gruszka reg |= 0x00000201; 218134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_WMM_CTRL, reg); 219134b2d0dSStanislaw Gruszka 220134b2d0dSStanislaw Gruszka /* TODO: Probably not needed */ 221134b2d0dSStanislaw Gruszka mt76_wr(dev, 0x7028, 0); 222134b2d0dSStanislaw Gruszka mt76_wr(dev, 0x7010, 0); 223134b2d0dSStanislaw Gruszka mt76_wr(dev, 0x7024, 0); 224134b2d0dSStanislaw Gruszka msleep(10); 225134b2d0dSStanislaw Gruszka } 226134b2d0dSStanislaw Gruszka 227134b2d0dSStanislaw Gruszka static int mt76x0_init_wcid_mem(struct mt76x0_dev *dev) 228134b2d0dSStanislaw Gruszka { 229134b2d0dSStanislaw Gruszka u32 *vals; 230134b2d0dSStanislaw Gruszka int i, ret; 231134b2d0dSStanislaw Gruszka 232134b2d0dSStanislaw Gruszka vals = kmalloc(sizeof(*vals) * N_WCIDS * 2, GFP_KERNEL); 233134b2d0dSStanislaw Gruszka if (!vals) 234134b2d0dSStanislaw Gruszka return -ENOMEM; 235134b2d0dSStanislaw Gruszka 236134b2d0dSStanislaw Gruszka for (i = 0; i < N_WCIDS; i++) { 237134b2d0dSStanislaw Gruszka vals[i * 2] = 0xffffffff; 238134b2d0dSStanislaw Gruszka vals[i * 2 + 1] = 0x00ffffff; 239134b2d0dSStanislaw Gruszka } 240134b2d0dSStanislaw Gruszka 241134b2d0dSStanislaw Gruszka ret = mt76x0_burst_write_regs(dev, MT_WCID_ADDR_BASE, 242134b2d0dSStanislaw Gruszka vals, N_WCIDS * 2); 243134b2d0dSStanislaw Gruszka kfree(vals); 244134b2d0dSStanislaw Gruszka 245134b2d0dSStanislaw Gruszka return ret; 246134b2d0dSStanislaw Gruszka } 247134b2d0dSStanislaw Gruszka 248134b2d0dSStanislaw Gruszka static int mt76x0_init_key_mem(struct mt76x0_dev *dev) 249134b2d0dSStanislaw Gruszka { 250134b2d0dSStanislaw Gruszka u32 vals[4] = {}; 251134b2d0dSStanislaw Gruszka 252134b2d0dSStanislaw Gruszka return mt76x0_burst_write_regs(dev, MT_SKEY_MODE_BASE_0, 253134b2d0dSStanislaw Gruszka vals, ARRAY_SIZE(vals)); 254134b2d0dSStanislaw Gruszka } 255134b2d0dSStanislaw Gruszka 256134b2d0dSStanislaw Gruszka static int mt76x0_init_wcid_attr_mem(struct mt76x0_dev *dev) 257134b2d0dSStanislaw Gruszka { 258134b2d0dSStanislaw Gruszka u32 *vals; 259134b2d0dSStanislaw Gruszka int i, ret; 260134b2d0dSStanislaw Gruszka 261134b2d0dSStanislaw Gruszka vals = kmalloc(sizeof(*vals) * N_WCIDS * 2, GFP_KERNEL); 262134b2d0dSStanislaw Gruszka if (!vals) 263134b2d0dSStanislaw Gruszka return -ENOMEM; 264134b2d0dSStanislaw Gruszka 265134b2d0dSStanislaw Gruszka for (i = 0; i < N_WCIDS * 2; i++) 266134b2d0dSStanislaw Gruszka vals[i] = 1; 267134b2d0dSStanislaw Gruszka 268134b2d0dSStanislaw Gruszka ret = mt76x0_burst_write_regs(dev, MT_WCID_ATTR_BASE, 269134b2d0dSStanislaw Gruszka vals, N_WCIDS * 2); 270134b2d0dSStanislaw Gruszka kfree(vals); 271134b2d0dSStanislaw Gruszka 272134b2d0dSStanislaw Gruszka return ret; 273134b2d0dSStanislaw Gruszka } 274134b2d0dSStanislaw Gruszka 275134b2d0dSStanislaw Gruszka static void mt76x0_reset_counters(struct mt76x0_dev *dev) 276134b2d0dSStanislaw Gruszka { 277134b2d0dSStanislaw Gruszka mt76_rr(dev, MT_RX_STA_CNT0); 278134b2d0dSStanislaw Gruszka mt76_rr(dev, MT_RX_STA_CNT1); 279134b2d0dSStanislaw Gruszka mt76_rr(dev, MT_RX_STA_CNT2); 280134b2d0dSStanislaw Gruszka mt76_rr(dev, MT_TX_STA_CNT0); 281134b2d0dSStanislaw Gruszka mt76_rr(dev, MT_TX_STA_CNT1); 282134b2d0dSStanislaw Gruszka mt76_rr(dev, MT_TX_STA_CNT2); 283134b2d0dSStanislaw Gruszka } 284134b2d0dSStanislaw Gruszka 285134b2d0dSStanislaw Gruszka int mt76x0_mac_start(struct mt76x0_dev *dev) 286134b2d0dSStanislaw Gruszka { 287134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); 288134b2d0dSStanislaw Gruszka 289134b2d0dSStanislaw Gruszka if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY | 290134b2d0dSStanislaw Gruszka MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000)) 291134b2d0dSStanislaw Gruszka return -ETIMEDOUT; 292134b2d0dSStanislaw Gruszka 293134b2d0dSStanislaw Gruszka dev->rxfilter = MT_RX_FILTR_CFG_CRC_ERR | 294134b2d0dSStanislaw Gruszka MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC | 295134b2d0dSStanislaw Gruszka MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP | 296134b2d0dSStanislaw Gruszka MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND | 297134b2d0dSStanislaw Gruszka MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS | 298134b2d0dSStanislaw Gruszka MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL | 299134b2d0dSStanislaw Gruszka MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV; 300134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter); 301134b2d0dSStanislaw Gruszka 302134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_MAC_SYS_CTRL, 303134b2d0dSStanislaw Gruszka MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); 304134b2d0dSStanislaw Gruszka 305134b2d0dSStanislaw Gruszka if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY | 306134b2d0dSStanislaw Gruszka MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50)) 307134b2d0dSStanislaw Gruszka return -ETIMEDOUT; 308134b2d0dSStanislaw Gruszka 309134b2d0dSStanislaw Gruszka return 0; 310134b2d0dSStanislaw Gruszka } 311134b2d0dSStanislaw Gruszka 312134b2d0dSStanislaw Gruszka static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev) 313134b2d0dSStanislaw Gruszka { 314134b2d0dSStanislaw Gruszka int i, ok; 315134b2d0dSStanislaw Gruszka 316134b2d0dSStanislaw Gruszka if (test_bit(MT76_REMOVED, &dev->mt76.state)) 317134b2d0dSStanislaw Gruszka return; 318134b2d0dSStanislaw Gruszka 319134b2d0dSStanislaw Gruszka mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN | 320134b2d0dSStanislaw Gruszka MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN | 321134b2d0dSStanislaw Gruszka MT_BEACON_TIME_CFG_BEACON_TX); 322134b2d0dSStanislaw Gruszka 323134b2d0dSStanislaw Gruszka if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000)) 324134b2d0dSStanislaw Gruszka dev_warn(dev->mt76.dev, "Warning: TX DMA did not stop!\n"); 325134b2d0dSStanislaw Gruszka 326134b2d0dSStanislaw Gruszka /* Page count on TxQ */ 327134b2d0dSStanislaw Gruszka i = 200; 328134b2d0dSStanislaw Gruszka while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) || 329134b2d0dSStanislaw Gruszka (mt76_rr(dev, 0x0a30) & 0x000000ff) || 330134b2d0dSStanislaw Gruszka (mt76_rr(dev, 0x0a34) & 0x00ff00ff))) 331134b2d0dSStanislaw Gruszka msleep(10); 332134b2d0dSStanislaw Gruszka 333134b2d0dSStanislaw Gruszka if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000)) 334134b2d0dSStanislaw Gruszka dev_warn(dev->mt76.dev, "Warning: MAC TX did not stop!\n"); 335134b2d0dSStanislaw Gruszka 336134b2d0dSStanislaw Gruszka mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX | 337134b2d0dSStanislaw Gruszka MT_MAC_SYS_CTRL_ENABLE_TX); 338134b2d0dSStanislaw Gruszka 339134b2d0dSStanislaw Gruszka /* Page count on RxQ */ 340134b2d0dSStanislaw Gruszka ok = 0; 341134b2d0dSStanislaw Gruszka i = 200; 342134b2d0dSStanislaw Gruszka while (i--) { 343134b2d0dSStanislaw Gruszka if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) && 344134b2d0dSStanislaw Gruszka !mt76_rr(dev, 0x0a30) && 345134b2d0dSStanislaw Gruszka !mt76_rr(dev, 0x0a34)) { 346134b2d0dSStanislaw Gruszka if (ok++ > 5) 347134b2d0dSStanislaw Gruszka break; 348134b2d0dSStanislaw Gruszka continue; 349134b2d0dSStanislaw Gruszka } 350134b2d0dSStanislaw Gruszka msleep(1); 351134b2d0dSStanislaw Gruszka } 352134b2d0dSStanislaw Gruszka 353134b2d0dSStanislaw Gruszka if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000)) 354134b2d0dSStanislaw Gruszka dev_warn(dev->mt76.dev, "Warning: MAC RX did not stop!\n"); 355134b2d0dSStanislaw Gruszka 356134b2d0dSStanislaw Gruszka if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000)) 357134b2d0dSStanislaw Gruszka dev_warn(dev->mt76.dev, "Warning: RX DMA did not stop!\n"); 358134b2d0dSStanislaw Gruszka } 359134b2d0dSStanislaw Gruszka 360134b2d0dSStanislaw Gruszka void mt76x0_mac_stop(struct mt76x0_dev *dev) 361134b2d0dSStanislaw Gruszka { 362134b2d0dSStanislaw Gruszka mt76x0_mac_stop_hw(dev); 363134b2d0dSStanislaw Gruszka flush_delayed_work(&dev->stat_work); 364134b2d0dSStanislaw Gruszka cancel_delayed_work_sync(&dev->stat_work); 365134b2d0dSStanislaw Gruszka } 366134b2d0dSStanislaw Gruszka 367134b2d0dSStanislaw Gruszka static void mt76x0_stop_hardware(struct mt76x0_dev *dev) 368134b2d0dSStanislaw Gruszka { 369134b2d0dSStanislaw Gruszka mt76x0_chip_onoff(dev, false, false); 370134b2d0dSStanislaw Gruszka } 371134b2d0dSStanislaw Gruszka 372134b2d0dSStanislaw Gruszka int mt76x0_init_hardware(struct mt76x0_dev *dev) 373134b2d0dSStanislaw Gruszka { 374134b2d0dSStanislaw Gruszka static const u16 beacon_offsets[16] = { 375134b2d0dSStanislaw Gruszka /* 512 byte per beacon */ 376134b2d0dSStanislaw Gruszka 0xc000, 0xc200, 0xc400, 0xc600, 377134b2d0dSStanislaw Gruszka 0xc800, 0xca00, 0xcc00, 0xce00, 378134b2d0dSStanislaw Gruszka 0xd000, 0xd200, 0xd400, 0xd600, 379134b2d0dSStanislaw Gruszka 0xd800, 0xda00, 0xdc00, 0xde00 380134b2d0dSStanislaw Gruszka }; 381134b2d0dSStanislaw Gruszka int ret; 382134b2d0dSStanislaw Gruszka 383134b2d0dSStanislaw Gruszka dev->beacon_offsets = beacon_offsets; 384134b2d0dSStanislaw Gruszka 385134b2d0dSStanislaw Gruszka mt76x0_chip_onoff(dev, true, true); 386134b2d0dSStanislaw Gruszka 3872735a6ddSStanislaw Gruszka if (!mt76x02_wait_for_mac(&dev->mt76)) { 3882735a6ddSStanislaw Gruszka ret = -ETIMEDOUT; 389134b2d0dSStanislaw Gruszka goto err; 3902735a6ddSStanislaw Gruszka } 3912735a6ddSStanislaw Gruszka 392134b2d0dSStanislaw Gruszka ret = mt76x0_mcu_init(dev); 393134b2d0dSStanislaw Gruszka if (ret) 394134b2d0dSStanislaw Gruszka goto err; 395134b2d0dSStanislaw Gruszka 396134b2d0dSStanislaw Gruszka if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG, 397134b2d0dSStanislaw Gruszka MT_WPDMA_GLO_CFG_TX_DMA_BUSY | 398134b2d0dSStanislaw Gruszka MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100)) { 399134b2d0dSStanislaw Gruszka ret = -EIO; 400134b2d0dSStanislaw Gruszka goto err; 401134b2d0dSStanislaw Gruszka } 402134b2d0dSStanislaw Gruszka 403134b2d0dSStanislaw Gruszka /* Wait for ASIC ready after FW load. */ 4042735a6ddSStanislaw Gruszka if (!mt76x02_wait_for_mac(&dev->mt76)) { 4052735a6ddSStanislaw Gruszka ret = -ETIMEDOUT; 406134b2d0dSStanislaw Gruszka goto err; 4072735a6ddSStanislaw Gruszka } 408134b2d0dSStanislaw Gruszka 409134b2d0dSStanislaw Gruszka mt76x0_reset_csr_bbp(dev); 410134b2d0dSStanislaw Gruszka mt76x0_init_usb_dma(dev); 411134b2d0dSStanislaw Gruszka 412134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_HEADER_TRANS_CTRL_REG, 0x0); 413134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_TSO_CTRL, 0x0); 414134b2d0dSStanislaw Gruszka 415134b2d0dSStanislaw Gruszka ret = mt76x0_mcu_cmd_init(dev); 416134b2d0dSStanislaw Gruszka if (ret) 417134b2d0dSStanislaw Gruszka goto err; 418134b2d0dSStanislaw Gruszka ret = mt76x0_dma_init(dev); 419134b2d0dSStanislaw Gruszka if (ret) 420134b2d0dSStanislaw Gruszka goto err_mcu; 421134b2d0dSStanislaw Gruszka 422134b2d0dSStanislaw Gruszka mt76x0_init_mac_registers(dev); 423134b2d0dSStanislaw Gruszka 424134b2d0dSStanislaw Gruszka if (!mt76_poll_msec(dev, MT_MAC_STATUS, 425134b2d0dSStanislaw Gruszka MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 1000)) { 426134b2d0dSStanislaw Gruszka ret = -EIO; 427134b2d0dSStanislaw Gruszka goto err_rx; 428134b2d0dSStanislaw Gruszka } 429134b2d0dSStanislaw Gruszka 430134b2d0dSStanislaw Gruszka ret = mt76x0_init_bbp(dev); 431134b2d0dSStanislaw Gruszka if (ret) 432134b2d0dSStanislaw Gruszka goto err_rx; 433134b2d0dSStanislaw Gruszka 434134b2d0dSStanislaw Gruszka ret = mt76x0_init_wcid_mem(dev); 435134b2d0dSStanislaw Gruszka if (ret) 436134b2d0dSStanislaw Gruszka goto err_rx; 437134b2d0dSStanislaw Gruszka ret = mt76x0_init_key_mem(dev); 438134b2d0dSStanislaw Gruszka if (ret) 439134b2d0dSStanislaw Gruszka goto err_rx; 440134b2d0dSStanislaw Gruszka ret = mt76x0_init_wcid_attr_mem(dev); 441134b2d0dSStanislaw Gruszka if (ret) 442134b2d0dSStanislaw Gruszka goto err_rx; 443134b2d0dSStanislaw Gruszka 444134b2d0dSStanislaw Gruszka mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | 445134b2d0dSStanislaw Gruszka MT_BEACON_TIME_CFG_SYNC_MODE | 446134b2d0dSStanislaw Gruszka MT_BEACON_TIME_CFG_TBTT_EN | 447134b2d0dSStanislaw Gruszka MT_BEACON_TIME_CFG_BEACON_TX)); 448134b2d0dSStanislaw Gruszka 449134b2d0dSStanislaw Gruszka mt76x0_reset_counters(dev); 450134b2d0dSStanislaw Gruszka 451134b2d0dSStanislaw Gruszka mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); 452134b2d0dSStanislaw Gruszka 453134b2d0dSStanislaw Gruszka mt76_wr(dev, MT_TXOP_CTRL_CFG, 454134b2d0dSStanislaw Gruszka FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) | 455134b2d0dSStanislaw Gruszka FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58)); 456134b2d0dSStanislaw Gruszka 457134b2d0dSStanislaw Gruszka ret = mt76x0_eeprom_init(dev); 458134b2d0dSStanislaw Gruszka if (ret) 459134b2d0dSStanislaw Gruszka goto err_rx; 460134b2d0dSStanislaw Gruszka 461134b2d0dSStanislaw Gruszka mt76x0_phy_init(dev); 462134b2d0dSStanislaw Gruszka return 0; 463134b2d0dSStanislaw Gruszka 464134b2d0dSStanislaw Gruszka err_rx: 465134b2d0dSStanislaw Gruszka mt76x0_dma_cleanup(dev); 466134b2d0dSStanislaw Gruszka err_mcu: 467134b2d0dSStanislaw Gruszka mt76x0_mcu_cmd_deinit(dev); 468134b2d0dSStanislaw Gruszka err: 469134b2d0dSStanislaw Gruszka mt76x0_chip_onoff(dev, false, false); 470134b2d0dSStanislaw Gruszka return ret; 471134b2d0dSStanislaw Gruszka } 472134b2d0dSStanislaw Gruszka 473134b2d0dSStanislaw Gruszka void mt76x0_cleanup(struct mt76x0_dev *dev) 474134b2d0dSStanislaw Gruszka { 475134b2d0dSStanislaw Gruszka if (!test_and_clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) 476134b2d0dSStanislaw Gruszka return; 477134b2d0dSStanislaw Gruszka 478134b2d0dSStanislaw Gruszka mt76x0_stop_hardware(dev); 479134b2d0dSStanislaw Gruszka mt76x0_dma_cleanup(dev); 480134b2d0dSStanislaw Gruszka mt76x0_mcu_cmd_deinit(dev); 481134b2d0dSStanislaw Gruszka } 482134b2d0dSStanislaw Gruszka 483134b2d0dSStanislaw Gruszka struct mt76x0_dev *mt76x0_alloc_device(struct device *pdev) 484134b2d0dSStanislaw Gruszka { 485134b2d0dSStanislaw Gruszka struct ieee80211_hw *hw; 486134b2d0dSStanislaw Gruszka struct mt76x0_dev *dev; 487134b2d0dSStanislaw Gruszka 488134b2d0dSStanislaw Gruszka hw = ieee80211_alloc_hw(sizeof(*dev), &mt76x0_ops); 489134b2d0dSStanislaw Gruszka if (!hw) 490134b2d0dSStanislaw Gruszka return NULL; 491134b2d0dSStanislaw Gruszka 492134b2d0dSStanislaw Gruszka dev = hw->priv; 493134b2d0dSStanislaw Gruszka dev->mt76.dev = pdev; 494134b2d0dSStanislaw Gruszka dev->mt76.hw = hw; 495134b2d0dSStanislaw Gruszka mutex_init(&dev->usb_ctrl_mtx); 496134b2d0dSStanislaw Gruszka mutex_init(&dev->reg_atomic_mutex); 497134b2d0dSStanislaw Gruszka mutex_init(&dev->hw_atomic_mutex); 498134b2d0dSStanislaw Gruszka mutex_init(&dev->mutex); 499134b2d0dSStanislaw Gruszka spin_lock_init(&dev->tx_lock); 500134b2d0dSStanislaw Gruszka spin_lock_init(&dev->rx_lock); 501134b2d0dSStanislaw Gruszka spin_lock_init(&dev->mt76.lock); 502134b2d0dSStanislaw Gruszka spin_lock_init(&dev->mac_lock); 503134b2d0dSStanislaw Gruszka spin_lock_init(&dev->con_mon_lock); 504134b2d0dSStanislaw Gruszka atomic_set(&dev->avg_ampdu_len, 1); 505134b2d0dSStanislaw Gruszka skb_queue_head_init(&dev->tx_skb_done); 506134b2d0dSStanislaw Gruszka 507134b2d0dSStanislaw Gruszka dev->stat_wq = alloc_workqueue("mt76x0", WQ_UNBOUND, 0); 508134b2d0dSStanislaw Gruszka if (!dev->stat_wq) { 509134b2d0dSStanislaw Gruszka ieee80211_free_hw(hw); 510134b2d0dSStanislaw Gruszka return NULL; 511134b2d0dSStanislaw Gruszka } 512134b2d0dSStanislaw Gruszka 513134b2d0dSStanislaw Gruszka return dev; 514134b2d0dSStanislaw Gruszka } 515134b2d0dSStanislaw Gruszka 516134b2d0dSStanislaw Gruszka #define CHAN2G(_idx, _freq) { \ 517134b2d0dSStanislaw Gruszka .band = NL80211_BAND_2GHZ, \ 518134b2d0dSStanislaw Gruszka .center_freq = (_freq), \ 519134b2d0dSStanislaw Gruszka .hw_value = (_idx), \ 520134b2d0dSStanislaw Gruszka .max_power = 30, \ 521134b2d0dSStanislaw Gruszka } 522134b2d0dSStanislaw Gruszka 523134b2d0dSStanislaw Gruszka static const struct ieee80211_channel mt76_channels_2ghz[] = { 524134b2d0dSStanislaw Gruszka CHAN2G(1, 2412), 525134b2d0dSStanislaw Gruszka CHAN2G(2, 2417), 526134b2d0dSStanislaw Gruszka CHAN2G(3, 2422), 527134b2d0dSStanislaw Gruszka CHAN2G(4, 2427), 528134b2d0dSStanislaw Gruszka CHAN2G(5, 2432), 529134b2d0dSStanislaw Gruszka CHAN2G(6, 2437), 530134b2d0dSStanislaw Gruszka CHAN2G(7, 2442), 531134b2d0dSStanislaw Gruszka CHAN2G(8, 2447), 532134b2d0dSStanislaw Gruszka CHAN2G(9, 2452), 533134b2d0dSStanislaw Gruszka CHAN2G(10, 2457), 534134b2d0dSStanislaw Gruszka CHAN2G(11, 2462), 535134b2d0dSStanislaw Gruszka CHAN2G(12, 2467), 536134b2d0dSStanislaw Gruszka CHAN2G(13, 2472), 537134b2d0dSStanislaw Gruszka CHAN2G(14, 2484), 538134b2d0dSStanislaw Gruszka }; 539134b2d0dSStanislaw Gruszka 540134b2d0dSStanislaw Gruszka #define CHAN5G(_idx, _freq) { \ 541134b2d0dSStanislaw Gruszka .band = NL80211_BAND_5GHZ, \ 542134b2d0dSStanislaw Gruszka .center_freq = (_freq), \ 543134b2d0dSStanislaw Gruszka .hw_value = (_idx), \ 544134b2d0dSStanislaw Gruszka .max_power = 30, \ 545134b2d0dSStanislaw Gruszka } 546134b2d0dSStanislaw Gruszka 547134b2d0dSStanislaw Gruszka static const struct ieee80211_channel mt76_channels_5ghz[] = { 548134b2d0dSStanislaw Gruszka CHAN5G(36, 5180), 549134b2d0dSStanislaw Gruszka CHAN5G(40, 5200), 550134b2d0dSStanislaw Gruszka CHAN5G(44, 5220), 551134b2d0dSStanislaw Gruszka CHAN5G(46, 5230), 552134b2d0dSStanislaw Gruszka CHAN5G(48, 5240), 553134b2d0dSStanislaw Gruszka CHAN5G(52, 5260), 554134b2d0dSStanislaw Gruszka CHAN5G(56, 5280), 555134b2d0dSStanislaw Gruszka CHAN5G(60, 5300), 556134b2d0dSStanislaw Gruszka CHAN5G(64, 5320), 557134b2d0dSStanislaw Gruszka 558134b2d0dSStanislaw Gruszka CHAN5G(100, 5500), 559134b2d0dSStanislaw Gruszka CHAN5G(104, 5520), 560134b2d0dSStanislaw Gruszka CHAN5G(108, 5540), 561134b2d0dSStanislaw Gruszka CHAN5G(112, 5560), 562134b2d0dSStanislaw Gruszka CHAN5G(116, 5580), 563134b2d0dSStanislaw Gruszka CHAN5G(120, 5600), 564134b2d0dSStanislaw Gruszka CHAN5G(124, 5620), 565134b2d0dSStanislaw Gruszka CHAN5G(128, 5640), 566134b2d0dSStanislaw Gruszka CHAN5G(132, 5660), 567134b2d0dSStanislaw Gruszka CHAN5G(136, 5680), 568134b2d0dSStanislaw Gruszka CHAN5G(140, 5700), 569134b2d0dSStanislaw Gruszka }; 570134b2d0dSStanislaw Gruszka 571134b2d0dSStanislaw Gruszka #define CCK_RATE(_idx, _rate) { \ 572134b2d0dSStanislaw Gruszka .bitrate = _rate, \ 573134b2d0dSStanislaw Gruszka .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ 574134b2d0dSStanislaw Gruszka .hw_value = (MT_PHY_TYPE_CCK << 8) | _idx, \ 575134b2d0dSStanislaw Gruszka .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + _idx), \ 576134b2d0dSStanislaw Gruszka } 577134b2d0dSStanislaw Gruszka 578134b2d0dSStanislaw Gruszka #define OFDM_RATE(_idx, _rate) { \ 579134b2d0dSStanislaw Gruszka .bitrate = _rate, \ 580134b2d0dSStanislaw Gruszka .hw_value = (MT_PHY_TYPE_OFDM << 8) | _idx, \ 581134b2d0dSStanislaw Gruszka .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | _idx, \ 582134b2d0dSStanislaw Gruszka } 583134b2d0dSStanislaw Gruszka 584134b2d0dSStanislaw Gruszka static struct ieee80211_rate mt76_rates[] = { 585134b2d0dSStanislaw Gruszka CCK_RATE(0, 10), 586134b2d0dSStanislaw Gruszka CCK_RATE(1, 20), 587134b2d0dSStanislaw Gruszka CCK_RATE(2, 55), 588134b2d0dSStanislaw Gruszka CCK_RATE(3, 110), 589134b2d0dSStanislaw Gruszka OFDM_RATE(0, 60), 590134b2d0dSStanislaw Gruszka OFDM_RATE(1, 90), 591134b2d0dSStanislaw Gruszka OFDM_RATE(2, 120), 592134b2d0dSStanislaw Gruszka OFDM_RATE(3, 180), 593134b2d0dSStanislaw Gruszka OFDM_RATE(4, 240), 594134b2d0dSStanislaw Gruszka OFDM_RATE(5, 360), 595134b2d0dSStanislaw Gruszka OFDM_RATE(6, 480), 596134b2d0dSStanislaw Gruszka OFDM_RATE(7, 540), 597134b2d0dSStanislaw Gruszka }; 598134b2d0dSStanislaw Gruszka 599134b2d0dSStanislaw Gruszka static int 600134b2d0dSStanislaw Gruszka mt76_init_sband(struct mt76x0_dev *dev, struct ieee80211_supported_band *sband, 601134b2d0dSStanislaw Gruszka const struct ieee80211_channel *chan, int n_chan, 602134b2d0dSStanislaw Gruszka struct ieee80211_rate *rates, int n_rates) 603134b2d0dSStanislaw Gruszka { 604134b2d0dSStanislaw Gruszka struct ieee80211_sta_ht_cap *ht_cap; 605134b2d0dSStanislaw Gruszka void *chanlist; 606134b2d0dSStanislaw Gruszka int size; 607134b2d0dSStanislaw Gruszka 608134b2d0dSStanislaw Gruszka size = n_chan * sizeof(*chan); 609134b2d0dSStanislaw Gruszka chanlist = devm_kmemdup(dev->mt76.dev, chan, size, GFP_KERNEL); 610134b2d0dSStanislaw Gruszka if (!chanlist) 611134b2d0dSStanislaw Gruszka return -ENOMEM; 612134b2d0dSStanislaw Gruszka 613134b2d0dSStanislaw Gruszka sband->channels = chanlist; 614134b2d0dSStanislaw Gruszka sband->n_channels = n_chan; 615134b2d0dSStanislaw Gruszka sband->bitrates = rates; 616134b2d0dSStanislaw Gruszka sband->n_bitrates = n_rates; 617134b2d0dSStanislaw Gruszka 618134b2d0dSStanislaw Gruszka ht_cap = &sband->ht_cap; 619134b2d0dSStanislaw Gruszka ht_cap->ht_supported = true; 620134b2d0dSStanislaw Gruszka ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 621134b2d0dSStanislaw Gruszka IEEE80211_HT_CAP_GRN_FLD | 622134b2d0dSStanislaw Gruszka IEEE80211_HT_CAP_SGI_20 | 623134b2d0dSStanislaw Gruszka IEEE80211_HT_CAP_SGI_40 | 624134b2d0dSStanislaw Gruszka (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 625134b2d0dSStanislaw Gruszka 626134b2d0dSStanislaw Gruszka ht_cap->mcs.rx_mask[0] = 0xff; 627134b2d0dSStanislaw Gruszka ht_cap->mcs.rx_mask[4] = 0x1; 628134b2d0dSStanislaw Gruszka ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 629134b2d0dSStanislaw Gruszka ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 630134b2d0dSStanislaw Gruszka ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_2; 631134b2d0dSStanislaw Gruszka 632134b2d0dSStanislaw Gruszka return 0; 633134b2d0dSStanislaw Gruszka } 634134b2d0dSStanislaw Gruszka 635134b2d0dSStanislaw Gruszka static int 636134b2d0dSStanislaw Gruszka mt76_init_sband_2g(struct mt76x0_dev *dev) 637134b2d0dSStanislaw Gruszka { 638134b2d0dSStanislaw Gruszka dev->mt76.hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->mt76.sband_2g.sband; 639134b2d0dSStanislaw Gruszka 640134b2d0dSStanislaw Gruszka WARN_ON(dev->ee->reg.start - 1 + dev->ee->reg.num > 641134b2d0dSStanislaw Gruszka ARRAY_SIZE(mt76_channels_2ghz)); 642134b2d0dSStanislaw Gruszka 643134b2d0dSStanislaw Gruszka 644134b2d0dSStanislaw Gruszka return mt76_init_sband(dev, &dev->mt76.sband_2g.sband, 645134b2d0dSStanislaw Gruszka mt76_channels_2ghz, ARRAY_SIZE(mt76_channels_2ghz), 646134b2d0dSStanislaw Gruszka mt76_rates, ARRAY_SIZE(mt76_rates)); 647134b2d0dSStanislaw Gruszka } 648134b2d0dSStanislaw Gruszka 649134b2d0dSStanislaw Gruszka static int 650134b2d0dSStanislaw Gruszka mt76_init_sband_5g(struct mt76x0_dev *dev) 651134b2d0dSStanislaw Gruszka { 652134b2d0dSStanislaw Gruszka dev->mt76.hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->mt76.sband_5g.sband; 653134b2d0dSStanislaw Gruszka 654134b2d0dSStanislaw Gruszka return mt76_init_sband(dev, &dev->mt76.sband_5g.sband, 655134b2d0dSStanislaw Gruszka mt76_channels_5ghz, ARRAY_SIZE(mt76_channels_5ghz), 656134b2d0dSStanislaw Gruszka mt76_rates + 4, ARRAY_SIZE(mt76_rates) - 4); 657134b2d0dSStanislaw Gruszka } 658134b2d0dSStanislaw Gruszka 659134b2d0dSStanislaw Gruszka 660134b2d0dSStanislaw Gruszka int mt76x0_register_device(struct mt76x0_dev *dev) 661134b2d0dSStanislaw Gruszka { 662134b2d0dSStanislaw Gruszka struct ieee80211_hw *hw = dev->mt76.hw; 663134b2d0dSStanislaw Gruszka struct wiphy *wiphy = hw->wiphy; 664134b2d0dSStanislaw Gruszka int ret; 665134b2d0dSStanislaw Gruszka 666134b2d0dSStanislaw Gruszka /* Reserve WCID 0 for mcast - thanks to this APs WCID will go to 667134b2d0dSStanislaw Gruszka * entry no. 1 like it does in the vendor driver. 668134b2d0dSStanislaw Gruszka */ 669134b2d0dSStanislaw Gruszka dev->wcid_mask[0] |= 1; 670134b2d0dSStanislaw Gruszka 671134b2d0dSStanislaw Gruszka /* init fake wcid for monitor interfaces */ 672134b2d0dSStanislaw Gruszka dev->mon_wcid = devm_kmalloc(dev->mt76.dev, sizeof(*dev->mon_wcid), 673134b2d0dSStanislaw Gruszka GFP_KERNEL); 674134b2d0dSStanislaw Gruszka if (!dev->mon_wcid) 675134b2d0dSStanislaw Gruszka return -ENOMEM; 676134b2d0dSStanislaw Gruszka dev->mon_wcid->idx = 0xff; 677134b2d0dSStanislaw Gruszka dev->mon_wcid->hw_key_idx = -1; 678134b2d0dSStanislaw Gruszka 679134b2d0dSStanislaw Gruszka SET_IEEE80211_DEV(hw, dev->mt76.dev); 680134b2d0dSStanislaw Gruszka 681134b2d0dSStanislaw Gruszka hw->queues = 4; 682134b2d0dSStanislaw Gruszka ieee80211_hw_set(hw, SIGNAL_DBM); 683134b2d0dSStanislaw Gruszka ieee80211_hw_set(hw, PS_NULLFUNC_STACK); 684134b2d0dSStanislaw Gruszka ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); 685134b2d0dSStanislaw Gruszka ieee80211_hw_set(hw, AMPDU_AGGREGATION); 686134b2d0dSStanislaw Gruszka ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); 687134b2d0dSStanislaw Gruszka hw->max_rates = 1; 688134b2d0dSStanislaw Gruszka hw->max_report_rates = 7; 689134b2d0dSStanislaw Gruszka hw->max_rate_tries = 1; 690134b2d0dSStanislaw Gruszka 691134b2d0dSStanislaw Gruszka hw->sta_data_size = sizeof(struct mt76_sta); 692134b2d0dSStanislaw Gruszka hw->vif_data_size = sizeof(struct mt76_vif); 693134b2d0dSStanislaw Gruszka 694134b2d0dSStanislaw Gruszka SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); 695134b2d0dSStanislaw Gruszka 696134b2d0dSStanislaw Gruszka wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; 697134b2d0dSStanislaw Gruszka wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 698134b2d0dSStanislaw Gruszka 699134b2d0dSStanislaw Gruszka if (dev->ee->has_2ghz) { 700134b2d0dSStanislaw Gruszka ret = mt76_init_sband_2g(dev); 701134b2d0dSStanislaw Gruszka if (ret) 702134b2d0dSStanislaw Gruszka return ret; 703134b2d0dSStanislaw Gruszka } 704134b2d0dSStanislaw Gruszka 705134b2d0dSStanislaw Gruszka if (dev->ee->has_5ghz) { 706134b2d0dSStanislaw Gruszka ret = mt76_init_sband_5g(dev); 707134b2d0dSStanislaw Gruszka if (ret) 708134b2d0dSStanislaw Gruszka return ret; 709134b2d0dSStanislaw Gruszka } 710134b2d0dSStanislaw Gruszka 711134b2d0dSStanislaw Gruszka dev->mt76.chandef.chan = &dev->mt76.sband_2g.sband.channels[0]; 712134b2d0dSStanislaw Gruszka 713134b2d0dSStanislaw Gruszka INIT_DELAYED_WORK(&dev->mac_work, mt76x0_mac_work); 714134b2d0dSStanislaw Gruszka INIT_DELAYED_WORK(&dev->stat_work, mt76x0_tx_stat); 715134b2d0dSStanislaw Gruszka 716134b2d0dSStanislaw Gruszka ret = ieee80211_register_hw(hw); 717134b2d0dSStanislaw Gruszka if (ret) 718134b2d0dSStanislaw Gruszka return ret; 719134b2d0dSStanislaw Gruszka 720134b2d0dSStanislaw Gruszka mt76x0_init_debugfs(dev); 721134b2d0dSStanislaw Gruszka 722134b2d0dSStanislaw Gruszka return 0; 723134b2d0dSStanislaw Gruszka } 724