162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/etherdevice.h> 462306a36Sopenharmony_ci#include "mt7603.h" 562306a36Sopenharmony_ci#include "mac.h" 662306a36Sopenharmony_ci#include "eeprom.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_ciconst struct mt76_driver_ops mt7603_drv_ops = { 962306a36Sopenharmony_ci .txwi_size = MT_TXD_SIZE, 1062306a36Sopenharmony_ci .drv_flags = MT_DRV_SW_RX_AIRTIME, 1162306a36Sopenharmony_ci .survey_flags = SURVEY_INFO_TIME_TX, 1262306a36Sopenharmony_ci .tx_prepare_skb = mt7603_tx_prepare_skb, 1362306a36Sopenharmony_ci .tx_complete_skb = mt7603_tx_complete_skb, 1462306a36Sopenharmony_ci .rx_skb = mt7603_queue_rx_skb, 1562306a36Sopenharmony_ci .rx_poll_complete = mt7603_rx_poll_complete, 1662306a36Sopenharmony_ci .sta_ps = mt7603_sta_ps, 1762306a36Sopenharmony_ci .sta_add = mt7603_sta_add, 1862306a36Sopenharmony_ci .sta_assoc = mt7603_sta_assoc, 1962306a36Sopenharmony_ci .sta_remove = mt7603_sta_remove, 2062306a36Sopenharmony_ci .update_survey = mt7603_update_channel, 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic void 2462306a36Sopenharmony_cimt7603_set_tmac_template(struct mt7603_dev *dev) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci u32 desc[5] = { 2762306a36Sopenharmony_ci [1] = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 0xf), 2862306a36Sopenharmony_ci [3] = MT_TXD5_SW_POWER_MGMT 2962306a36Sopenharmony_ci }; 3062306a36Sopenharmony_ci u32 addr; 3162306a36Sopenharmony_ci int i; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR); 3462306a36Sopenharmony_ci addr += MT_CLIENT_TMAC_INFO_TEMPLATE; 3562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(desc); i++) 3662306a36Sopenharmony_ci mt76_wr(dev, addr + 4 * i, desc[i]); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic void 4062306a36Sopenharmony_cimt7603_dma_sched_init(struct mt7603_dev *dev) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci int page_size = 128; 4362306a36Sopenharmony_ci int page_count; 4462306a36Sopenharmony_ci int max_len = 1792; 4562306a36Sopenharmony_ci int max_amsdu_pages = 4096 / page_size; 4662306a36Sopenharmony_ci int max_mcu_len = 4096; 4762306a36Sopenharmony_ci int max_beacon_len = 512 * 4 + max_len; 4862306a36Sopenharmony_ci int max_mcast_pages = 4 * max_len / page_size; 4962306a36Sopenharmony_ci int reserved_count = 0; 5062306a36Sopenharmony_ci int beacon_pages; 5162306a36Sopenharmony_ci int mcu_pages; 5262306a36Sopenharmony_ci int i; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci page_count = mt76_get_field(dev, MT_PSE_FC_P0, 5562306a36Sopenharmony_ci MT_PSE_FC_P0_MAX_QUOTA); 5662306a36Sopenharmony_ci beacon_pages = 4 * (max_beacon_len / page_size); 5762306a36Sopenharmony_ci mcu_pages = max_mcu_len / page_size; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci mt76_wr(dev, MT_PSE_FRP, 6062306a36Sopenharmony_ci FIELD_PREP(MT_PSE_FRP_P0, 7) | 6162306a36Sopenharmony_ci FIELD_PREP(MT_PSE_FRP_P1, 6) | 6262306a36Sopenharmony_ci FIELD_PREP(MT_PSE_FRP_P2_RQ2, 4)); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci mt76_wr(dev, MT_HIGH_PRIORITY_1, 0x55555553); 6562306a36Sopenharmony_ci mt76_wr(dev, MT_HIGH_PRIORITY_2, 0x78555555); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci mt76_wr(dev, MT_QUEUE_PRIORITY_1, 0x2b1a096e); 6862306a36Sopenharmony_ci mt76_wr(dev, MT_QUEUE_PRIORITY_2, 0x785f4d3c); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci mt76_wr(dev, MT_PRIORITY_MASK, 0xffffffff); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci mt76_wr(dev, MT_SCH_1, page_count | (2 << 28)); 7362306a36Sopenharmony_ci mt76_wr(dev, MT_SCH_2, max_amsdu_pages); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci for (i = 0; i <= 4; i++) 7662306a36Sopenharmony_ci mt76_wr(dev, MT_PAGE_COUNT(i), max_amsdu_pages); 7762306a36Sopenharmony_ci reserved_count += 5 * max_amsdu_pages; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci mt76_wr(dev, MT_PAGE_COUNT(5), mcu_pages); 8062306a36Sopenharmony_ci reserved_count += mcu_pages; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci mt76_wr(dev, MT_PAGE_COUNT(7), beacon_pages); 8362306a36Sopenharmony_ci reserved_count += beacon_pages; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci mt76_wr(dev, MT_PAGE_COUNT(8), max_mcast_pages); 8662306a36Sopenharmony_ci reserved_count += max_mcast_pages; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if (is_mt7603(dev)) 8962306a36Sopenharmony_ci reserved_count = 0; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci mt76_wr(dev, MT_RSV_MAX_THRESH, page_count - reserved_count); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (is_mt7603(dev) && mt76xx_rev(dev) >= MT7603_REV_E2) { 9462306a36Sopenharmony_ci mt76_wr(dev, MT_GROUP_THRESH(0), 9562306a36Sopenharmony_ci page_count - beacon_pages - mcu_pages); 9662306a36Sopenharmony_ci mt76_wr(dev, MT_GROUP_THRESH(1), beacon_pages); 9762306a36Sopenharmony_ci mt76_wr(dev, MT_BMAP_0, 0x0080ff5f); 9862306a36Sopenharmony_ci mt76_wr(dev, MT_GROUP_THRESH(2), mcu_pages); 9962306a36Sopenharmony_ci mt76_wr(dev, MT_BMAP_1, 0x00000020); 10062306a36Sopenharmony_ci } else { 10162306a36Sopenharmony_ci mt76_wr(dev, MT_GROUP_THRESH(0), page_count); 10262306a36Sopenharmony_ci mt76_wr(dev, MT_BMAP_0, 0xffff); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci mt76_wr(dev, MT_SCH_4, 0); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci for (i = 0; i <= 15; i++) 10862306a36Sopenharmony_ci mt76_wr(dev, MT_TXTIME_THRESH(i), 0xfffff); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci mt76_set(dev, MT_SCH_4, BIT(6)); 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic void 11462306a36Sopenharmony_cimt7603_phy_init(struct mt7603_dev *dev) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci int rx_chains = dev->mphy.antenna_mask; 11762306a36Sopenharmony_ci int tx_chains = hweight8(rx_chains) - 1; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci mt76_rmw(dev, MT_WF_RMAC_RMCR, 12062306a36Sopenharmony_ci (MT_WF_RMAC_RMCR_SMPS_MODE | 12162306a36Sopenharmony_ci MT_WF_RMAC_RMCR_RX_STREAMS), 12262306a36Sopenharmony_ci (FIELD_PREP(MT_WF_RMAC_RMCR_SMPS_MODE, 3) | 12362306a36Sopenharmony_ci FIELD_PREP(MT_WF_RMAC_RMCR_RX_STREAMS, rx_chains))); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci mt76_rmw_field(dev, MT_TMAC_TCR, MT_TMAC_TCR_TX_STREAMS, 12662306a36Sopenharmony_ci tx_chains); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci dev->agc0 = mt76_rr(dev, MT_AGC(0)); 12962306a36Sopenharmony_ci dev->agc3 = mt76_rr(dev, MT_AGC(3)); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic void 13362306a36Sopenharmony_cimt7603_mac_init(struct mt7603_dev *dev) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci u8 bc_addr[ETH_ALEN]; 13662306a36Sopenharmony_ci u32 addr; 13762306a36Sopenharmony_ci int i; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_0, 14062306a36Sopenharmony_ci (MT_AGG_SIZE_LIMIT(0) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | 14162306a36Sopenharmony_ci (MT_AGG_SIZE_LIMIT(1) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | 14262306a36Sopenharmony_ci (MT_AGG_SIZE_LIMIT(2) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | 14362306a36Sopenharmony_ci (MT_AGG_SIZE_LIMIT(3) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT)); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_1, 14662306a36Sopenharmony_ci (MT_AGG_SIZE_LIMIT(4) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | 14762306a36Sopenharmony_ci (MT_AGG_SIZE_LIMIT(5) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | 14862306a36Sopenharmony_ci (MT_AGG_SIZE_LIMIT(6) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | 14962306a36Sopenharmony_ci (MT_AGG_SIZE_LIMIT(7) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT)); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_LIMIT, 15262306a36Sopenharmony_ci FIELD_PREP(MT_AGG_LIMIT_AC(0), 24) | 15362306a36Sopenharmony_ci FIELD_PREP(MT_AGG_LIMIT_AC(1), 24) | 15462306a36Sopenharmony_ci FIELD_PREP(MT_AGG_LIMIT_AC(2), 24) | 15562306a36Sopenharmony_ci FIELD_PREP(MT_AGG_LIMIT_AC(3), 24)); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_LIMIT_1, 15862306a36Sopenharmony_ci FIELD_PREP(MT_AGG_LIMIT_AC(0), 24) | 15962306a36Sopenharmony_ci FIELD_PREP(MT_AGG_LIMIT_AC(1), 24) | 16062306a36Sopenharmony_ci FIELD_PREP(MT_AGG_LIMIT_AC(2), 24) | 16162306a36Sopenharmony_ci FIELD_PREP(MT_AGG_LIMIT_AC(3), 24)); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_CONTROL, 16462306a36Sopenharmony_ci FIELD_PREP(MT_AGG_CONTROL_BAR_RATE, 0x4b) | 16562306a36Sopenharmony_ci FIELD_PREP(MT_AGG_CONTROL_CFEND_RATE, 0x69) | 16662306a36Sopenharmony_ci MT_AGG_CONTROL_NO_BA_AR_RULE); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_RETRY_CONTROL, 16962306a36Sopenharmony_ci FIELD_PREP(MT_AGG_RETRY_CONTROL_BAR_LIMIT, 1) | 17062306a36Sopenharmony_ci FIELD_PREP(MT_AGG_RETRY_CONTROL_RTS_LIMIT, 15)); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci mt76_wr(dev, MT_DMA_DCR0, MT_DMA_DCR0_RX_VEC_DROP | 17362306a36Sopenharmony_ci FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 4096)); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci mt76_rmw(dev, MT_DMA_VCFR0, BIT(0), BIT(13)); 17662306a36Sopenharmony_ci mt76_rmw(dev, MT_DMA_TMCFR0, BIT(0) | BIT(1), BIT(13)); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci mt76_clear(dev, MT_WF_RMAC_TMR_PA, BIT(31)); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci mt76_set(dev, MT_WF_RMACDR, MT_WF_RMACDR_MAXLEN_20BIT); 18162306a36Sopenharmony_ci mt76_rmw(dev, MT_WF_RMAC_MAXMINLEN, 0xffffff, 0x19000); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci mt76_wr(dev, MT_WF_RFCR1, 0); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci mt76_set(dev, MT_TMAC_TCR, MT_TMAC_TCR_RX_RIFS_MODE); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci mt7603_set_tmac_template(dev); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* Enable RX group to HIF */ 19062306a36Sopenharmony_ci addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR); 19162306a36Sopenharmony_ci mt76_set(dev, addr + MT_CLIENT_RXINF, MT_CLIENT_RXINF_RXSH_GROUPS); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* Enable RX group to MCU */ 19462306a36Sopenharmony_ci mt76_set(dev, MT_DMA_DCR1, GENMASK(13, 11)); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci mt76_rmw_field(dev, MT_AGG_PCR_RTS, MT_AGG_PCR_RTS_PKT_THR, 3); 19762306a36Sopenharmony_ci mt76_set(dev, MT_TMAC_PCR, MT_TMAC_PCR_SPE_EN); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci /* include preamble detection in CCA trigger signal */ 20062306a36Sopenharmony_ci mt76_rmw_field(dev, MT_TXREQ, MT_TXREQ_CCA_SRC_SEL, 2); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci mt76_wr(dev, MT_RXREQ, 4); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* Configure all rx packets to HIF */ 20562306a36Sopenharmony_ci mt76_wr(dev, MT_DMA_RCFR0, 0xc0000000); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* Configure MCU txs selection with aggregation */ 20862306a36Sopenharmony_ci mt76_wr(dev, MT_DMA_TCFR0, 20962306a36Sopenharmony_ci FIELD_PREP(MT_DMA_TCFR_TXS_AGGR_TIMEOUT, 1) | /* 32 us */ 21062306a36Sopenharmony_ci MT_DMA_TCFR_TXS_AGGR_COUNT); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* Configure HIF txs selection with aggregation */ 21362306a36Sopenharmony_ci mt76_wr(dev, MT_DMA_TCFR1, 21462306a36Sopenharmony_ci FIELD_PREP(MT_DMA_TCFR_TXS_AGGR_TIMEOUT, 1) | /* 32 us */ 21562306a36Sopenharmony_ci MT_DMA_TCFR_TXS_AGGR_COUNT | /* Maximum count */ 21662306a36Sopenharmony_ci MT_DMA_TCFR_TXS_BIT_MAP); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci mt76_wr(dev, MT_MCU_PCIE_REMAP_1, MT_PSE_WTBL_2_PHYS_ADDR); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci for (i = 0; i < MT7603_WTBL_SIZE; i++) 22162306a36Sopenharmony_ci mt7603_wtbl_clear(dev, i); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci eth_broadcast_addr(bc_addr); 22462306a36Sopenharmony_ci mt7603_wtbl_init(dev, MT7603_WTBL_RESERVED, -1, bc_addr); 22562306a36Sopenharmony_ci dev->global_sta.wcid.idx = MT7603_WTBL_RESERVED; 22662306a36Sopenharmony_ci rcu_assign_pointer(dev->mt76.wcid[MT7603_WTBL_RESERVED], 22762306a36Sopenharmony_ci &dev->global_sta.wcid); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci mt76_rmw_field(dev, MT_LPON_BTEIR, MT_LPON_BTEIR_MBSS_MODE, 2); 23062306a36Sopenharmony_ci mt76_rmw_field(dev, MT_WF_RMACDR, MT_WF_RMACDR_MBSSID_MASK, 2); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_ARUCR, 23362306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | 23462306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | 23562306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | 23662306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | 23762306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | 23862306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | 23962306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | 24062306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_ARDCR, 24362306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7603_RATE_RETRY - 1) | 24462306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7603_RATE_RETRY - 1) | 24562306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7603_RATE_RETRY - 1) | 24662306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7603_RATE_RETRY - 1) | 24762306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7603_RATE_RETRY - 1) | 24862306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7603_RATE_RETRY - 1) | 24962306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7603_RATE_RETRY - 1) | 25062306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7603_RATE_RETRY - 1)); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_ARCR, 25362306a36Sopenharmony_ci (FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | 25462306a36Sopenharmony_ci MT_AGG_ARCR_RATE_DOWN_RATIO_EN | 25562306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | 25662306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4))); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci mt76_set(dev, MT_WTBL_RMVTCR, MT_WTBL_RMVTCR_RX_MV_MODE); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci mt76_clear(dev, MT_SEC_SCR, MT_SEC_SCR_MASK_ORDER); 26162306a36Sopenharmony_ci mt76_clear(dev, MT_SEC_SCR, BIT(18)); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* Set secondary beacon time offsets */ 26462306a36Sopenharmony_ci for (i = 0; i <= 4; i++) 26562306a36Sopenharmony_ci mt76_rmw_field(dev, MT_LPON_SBTOR(i), MT_LPON_SBTOR_TIME_OFFSET, 26662306a36Sopenharmony_ci (i + 1) * (20 + 4096)); 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic int 27062306a36Sopenharmony_cimt7603_init_hardware(struct mt7603_dev *dev) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci int i, ret; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci ret = mt7603_eeprom_init(dev); 27762306a36Sopenharmony_ci if (ret < 0) 27862306a36Sopenharmony_ci return ret; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci ret = mt7603_dma_init(dev); 28162306a36Sopenharmony_ci if (ret) 28262306a36Sopenharmony_ci return ret; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci mt76_wr(dev, MT_WPDMA_GLO_CFG, 0x52000850); 28562306a36Sopenharmony_ci mt7603_mac_dma_start(dev); 28662306a36Sopenharmony_ci dev->rxfilter = mt76_rr(dev, MT_WF_RFCR); 28762306a36Sopenharmony_ci set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci for (i = 0; i < MT7603_WTBL_SIZE; i++) { 29062306a36Sopenharmony_ci mt76_wr(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY | MT_PSE_RTA_WRITE | 29162306a36Sopenharmony_ci FIELD_PREP(MT_PSE_RTA_TAG_ID, i)); 29262306a36Sopenharmony_ci mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000); 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci ret = mt7603_mcu_init(dev); 29662306a36Sopenharmony_ci if (ret) 29762306a36Sopenharmony_ci return ret; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci mt7603_dma_sched_init(dev); 30062306a36Sopenharmony_ci mt7603_mcu_set_eeprom(dev); 30162306a36Sopenharmony_ci mt7603_phy_init(dev); 30262306a36Sopenharmony_ci mt7603_mac_init(dev); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci return 0; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic const struct ieee80211_iface_limit if_limits[] = { 30862306a36Sopenharmony_ci { 30962306a36Sopenharmony_ci .max = 1, 31062306a36Sopenharmony_ci .types = BIT(NL80211_IFTYPE_ADHOC) 31162306a36Sopenharmony_ci }, { 31262306a36Sopenharmony_ci .max = MT7603_MAX_INTERFACES, 31362306a36Sopenharmony_ci .types = BIT(NL80211_IFTYPE_STATION) | 31462306a36Sopenharmony_ci#ifdef CONFIG_MAC80211_MESH 31562306a36Sopenharmony_ci BIT(NL80211_IFTYPE_MESH_POINT) | 31662306a36Sopenharmony_ci#endif 31762306a36Sopenharmony_ci BIT(NL80211_IFTYPE_P2P_CLIENT) | 31862306a36Sopenharmony_ci BIT(NL80211_IFTYPE_P2P_GO) | 31962306a36Sopenharmony_ci BIT(NL80211_IFTYPE_AP) 32062306a36Sopenharmony_ci }, 32162306a36Sopenharmony_ci}; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic const struct ieee80211_iface_combination if_comb[] = { 32462306a36Sopenharmony_ci { 32562306a36Sopenharmony_ci .limits = if_limits, 32662306a36Sopenharmony_ci .n_limits = ARRAY_SIZE(if_limits), 32762306a36Sopenharmony_ci .max_interfaces = 4, 32862306a36Sopenharmony_ci .num_different_channels = 1, 32962306a36Sopenharmony_ci .beacon_int_infra_match = true, 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci}; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic void mt7603_led_set_config(struct mt76_phy *mphy, u8 delay_on, 33462306a36Sopenharmony_ci u8 delay_off) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci struct mt7603_dev *dev = container_of(mphy->dev, struct mt7603_dev, 33762306a36Sopenharmony_ci mt76); 33862306a36Sopenharmony_ci u32 val, addr; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | 34162306a36Sopenharmony_ci FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | 34262306a36Sopenharmony_ci FIELD_PREP(MT_LED_STATUS_ON, delay_on); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci addr = mt7603_reg_map(dev, MT_LED_STATUS_0(mphy->leds.pin)); 34562306a36Sopenharmony_ci mt76_wr(dev, addr, val); 34662306a36Sopenharmony_ci addr = mt7603_reg_map(dev, MT_LED_STATUS_1(mphy->leds.pin)); 34762306a36Sopenharmony_ci mt76_wr(dev, addr, val); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci val = MT_LED_CTRL_REPLAY(mphy->leds.pin) | 35062306a36Sopenharmony_ci MT_LED_CTRL_KICK(mphy->leds.pin); 35162306a36Sopenharmony_ci if (mphy->leds.al) 35262306a36Sopenharmony_ci val |= MT_LED_CTRL_POLARITY(mphy->leds.pin); 35362306a36Sopenharmony_ci addr = mt7603_reg_map(dev, MT_LED_CTRL); 35462306a36Sopenharmony_ci mt76_wr(dev, addr, val); 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic int mt7603_led_set_blink(struct led_classdev *led_cdev, 35862306a36Sopenharmony_ci unsigned long *delay_on, 35962306a36Sopenharmony_ci unsigned long *delay_off) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci struct mt76_phy *mphy = container_of(led_cdev, struct mt76_phy, 36262306a36Sopenharmony_ci leds.cdev); 36362306a36Sopenharmony_ci u8 delta_on, delta_off; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci delta_off = max_t(u8, *delay_off / 10, 1); 36662306a36Sopenharmony_ci delta_on = max_t(u8, *delay_on / 10, 1); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci mt7603_led_set_config(mphy, delta_on, delta_off); 36962306a36Sopenharmony_ci return 0; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic void mt7603_led_set_brightness(struct led_classdev *led_cdev, 37362306a36Sopenharmony_ci enum led_brightness brightness) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci struct mt76_phy *mphy = container_of(led_cdev, struct mt76_phy, 37662306a36Sopenharmony_ci leds.cdev); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if (!brightness) 37962306a36Sopenharmony_ci mt7603_led_set_config(mphy, 0, 0xff); 38062306a36Sopenharmony_ci else 38162306a36Sopenharmony_ci mt7603_led_set_config(mphy, 0xff, 0); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic u32 __mt7603_reg_addr(struct mt7603_dev *dev, u32 addr) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci if (addr < 0x100000) 38762306a36Sopenharmony_ci return addr; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci return mt7603_reg_map(dev, addr); 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic u32 mt7603_rr(struct mt76_dev *mdev, u32 offset) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 39562306a36Sopenharmony_ci u32 addr = __mt7603_reg_addr(dev, offset); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci return dev->bus_ops->rr(mdev, addr); 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic void mt7603_wr(struct mt76_dev *mdev, u32 offset, u32 val) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 40362306a36Sopenharmony_ci u32 addr = __mt7603_reg_addr(dev, offset); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci dev->bus_ops->wr(mdev, addr, val); 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic u32 mt7603_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 41162306a36Sopenharmony_ci u32 addr = __mt7603_reg_addr(dev, offset); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci return dev->bus_ops->rmw(mdev, addr, mask, val); 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_cistatic void 41762306a36Sopenharmony_cimt7603_regd_notifier(struct wiphy *wiphy, 41862306a36Sopenharmony_ci struct regulatory_request *request) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 42162306a36Sopenharmony_ci struct mt7603_dev *dev = hw->priv; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci dev->mt76.region = request->dfs_region; 42462306a36Sopenharmony_ci dev->ed_monitor = dev->ed_monitor_enabled && 42562306a36Sopenharmony_ci dev->mt76.region == NL80211_DFS_ETSI; 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic int 42962306a36Sopenharmony_cimt7603_txpower_signed(int val) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci bool sign = val & BIT(6); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci if (!(val & BIT(7))) 43462306a36Sopenharmony_ci return 0; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci val &= GENMASK(5, 0); 43762306a36Sopenharmony_ci if (!sign) 43862306a36Sopenharmony_ci val = -val; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci return val; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic void 44462306a36Sopenharmony_cimt7603_init_txpower(struct mt7603_dev *dev, 44562306a36Sopenharmony_ci struct ieee80211_supported_band *sband) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct ieee80211_channel *chan; 44862306a36Sopenharmony_ci u8 *eeprom = (u8 *)dev->mt76.eeprom.data; 44962306a36Sopenharmony_ci int target_power = eeprom[MT_EE_TX_POWER_0_START_2G + 2] & ~BIT(7); 45062306a36Sopenharmony_ci u8 *rate_power = &eeprom[MT_EE_TX_POWER_CCK]; 45162306a36Sopenharmony_ci bool ext_pa = eeprom[MT_EE_NIC_CONF_0 + 1] & BIT(1); 45262306a36Sopenharmony_ci int max_offset, cur_offset; 45362306a36Sopenharmony_ci int i; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (ext_pa && is_mt7603(dev)) 45662306a36Sopenharmony_ci target_power = eeprom[MT_EE_TX_POWER_TSSI_OFF] & ~BIT(7); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci if (target_power & BIT(6)) 45962306a36Sopenharmony_ci target_power = -(target_power & GENMASK(5, 0)); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci max_offset = 0; 46262306a36Sopenharmony_ci for (i = 0; i < 14; i++) { 46362306a36Sopenharmony_ci cur_offset = mt7603_txpower_signed(rate_power[i]); 46462306a36Sopenharmony_ci max_offset = max(max_offset, cur_offset); 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci target_power += max_offset; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci dev->tx_power_limit = target_power; 47062306a36Sopenharmony_ci dev->mphy.txpower_cur = target_power; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci target_power = DIV_ROUND_UP(target_power, 2); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* add 3 dBm for 2SS devices (combined output) */ 47562306a36Sopenharmony_ci if (dev->mphy.antenna_mask & BIT(1)) 47662306a36Sopenharmony_ci target_power += 3; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci for (i = 0; i < sband->n_channels; i++) { 47962306a36Sopenharmony_ci chan = &sband->channels[i]; 48062306a36Sopenharmony_ci chan->max_power = min_t(int, chan->max_reg_power, target_power); 48162306a36Sopenharmony_ci chan->orig_mpwr = target_power; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ciint mt7603_register_device(struct mt7603_dev *dev) 48662306a36Sopenharmony_ci{ 48762306a36Sopenharmony_ci struct mt76_bus_ops *bus_ops; 48862306a36Sopenharmony_ci struct ieee80211_hw *hw = mt76_hw(dev); 48962306a36Sopenharmony_ci struct wiphy *wiphy = hw->wiphy; 49062306a36Sopenharmony_ci int ret; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci dev->bus_ops = dev->mt76.bus; 49362306a36Sopenharmony_ci bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), 49462306a36Sopenharmony_ci GFP_KERNEL); 49562306a36Sopenharmony_ci if (!bus_ops) 49662306a36Sopenharmony_ci return -ENOMEM; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci bus_ops->rr = mt7603_rr; 49962306a36Sopenharmony_ci bus_ops->wr = mt7603_wr; 50062306a36Sopenharmony_ci bus_ops->rmw = mt7603_rmw; 50162306a36Sopenharmony_ci dev->mt76.bus = bus_ops; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci spin_lock_init(&dev->ps_lock); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7603_mac_work); 50662306a36Sopenharmony_ci tasklet_setup(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci dev->slottime = 9; 50962306a36Sopenharmony_ci dev->sensitivity_limit = 28; 51062306a36Sopenharmony_ci dev->dynamic_sensitivity = true; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci ret = mt7603_init_hardware(dev); 51362306a36Sopenharmony_ci if (ret) 51462306a36Sopenharmony_ci return ret; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci hw->queues = 4; 51762306a36Sopenharmony_ci hw->max_rates = 3; 51862306a36Sopenharmony_ci hw->max_report_rates = 7; 51962306a36Sopenharmony_ci hw->max_rate_tries = 11; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci hw->radiotap_timestamp.units_pos = 52262306a36Sopenharmony_ci IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci hw->sta_data_size = sizeof(struct mt7603_sta); 52562306a36Sopenharmony_ci hw->vif_data_size = sizeof(struct mt7603_vif); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci wiphy->iface_combinations = if_comb; 52862306a36Sopenharmony_ci wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); 53162306a36Sopenharmony_ci ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); 53262306a36Sopenharmony_ci ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci /* init led callbacks */ 53562306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_MT76_LEDS)) { 53662306a36Sopenharmony_ci dev->mphy.leds.cdev.brightness_set = mt7603_led_set_brightness; 53762306a36Sopenharmony_ci dev->mphy.leds.cdev.blink_set = mt7603_led_set_blink; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci wiphy->reg_notifier = mt7603_regd_notifier; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci ret = mt76_register_device(&dev->mt76, true, mt76_rates, 54362306a36Sopenharmony_ci ARRAY_SIZE(mt76_rates)); 54462306a36Sopenharmony_ci if (ret) 54562306a36Sopenharmony_ci return ret; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci mt7603_init_debugfs(dev); 54862306a36Sopenharmony_ci mt7603_init_txpower(dev, &dev->mphy.sband_2g.sband); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci return 0; 55162306a36Sopenharmony_ci} 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_civoid mt7603_unregister_device(struct mt7603_dev *dev) 55462306a36Sopenharmony_ci{ 55562306a36Sopenharmony_ci tasklet_disable(&dev->mt76.pre_tbtt_tasklet); 55662306a36Sopenharmony_ci mt76_unregister_device(&dev->mt76); 55762306a36Sopenharmony_ci mt7603_mcu_exit(dev); 55862306a36Sopenharmony_ci mt7603_dma_cleanup(dev); 55962306a36Sopenharmony_ci mt76_free_device(&dev->mt76); 56062306a36Sopenharmony_ci} 561