162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC 262306a36Sopenharmony_ci/* Copyright (C) 2019 MediaTek Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Author: Roy Luo <royluo@google.com> 562306a36Sopenharmony_ci * Ryder Lee <ryder.lee@mediatek.com> 662306a36Sopenharmony_ci * Felix Fietkau <nbd@nbd.name> 762306a36Sopenharmony_ci * Lorenzo Bianconi <lorenzo@kernel.org> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/etherdevice.h> 1162306a36Sopenharmony_ci#include <linux/hwmon.h> 1262306a36Sopenharmony_ci#include <linux/hwmon-sysfs.h> 1362306a36Sopenharmony_ci#include "mt7615.h" 1462306a36Sopenharmony_ci#include "mac.h" 1562306a36Sopenharmony_ci#include "mcu.h" 1662306a36Sopenharmony_ci#include "eeprom.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic ssize_t mt7615_thermal_show_temp(struct device *dev, 1962306a36Sopenharmony_ci struct device_attribute *attr, 2062306a36Sopenharmony_ci char *buf) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci struct mt7615_dev *mdev = dev_get_drvdata(dev); 2362306a36Sopenharmony_ci int temperature; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci if (!mt7615_wait_for_mcu_init(mdev)) 2662306a36Sopenharmony_ci return 0; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci mt7615_mutex_acquire(mdev); 2962306a36Sopenharmony_ci temperature = mt7615_mcu_get_temperature(mdev); 3062306a36Sopenharmony_ci mt7615_mutex_release(mdev); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci if (temperature < 0) 3362306a36Sopenharmony_ci return temperature; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci /* display in millidegree celcius */ 3662306a36Sopenharmony_ci return sprintf(buf, "%u\n", temperature * 1000); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic SENSOR_DEVICE_ATTR(temp1_input, 0444, mt7615_thermal_show_temp, 4062306a36Sopenharmony_ci NULL, 0); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic struct attribute *mt7615_hwmon_attrs[] = { 4362306a36Sopenharmony_ci &sensor_dev_attr_temp1_input.dev_attr.attr, 4462306a36Sopenharmony_ci NULL, 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ciATTRIBUTE_GROUPS(mt7615_hwmon); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciint mt7615_thermal_init(struct mt7615_dev *dev) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci struct wiphy *wiphy = mt76_hw(dev)->wiphy; 5162306a36Sopenharmony_ci struct device *hwmon; 5262306a36Sopenharmony_ci const char *name; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (!IS_REACHABLE(CONFIG_HWMON)) 5562306a36Sopenharmony_ci return 0; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7615_%s", 5862306a36Sopenharmony_ci wiphy_name(wiphy)); 5962306a36Sopenharmony_ci hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev, 6062306a36Sopenharmony_ci mt7615_hwmon_groups); 6162306a36Sopenharmony_ci if (IS_ERR(hwmon)) 6262306a36Sopenharmony_ci return PTR_ERR(hwmon); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci return 0; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_thermal_init); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic void 6962306a36Sopenharmony_cimt7615_phy_init(struct mt7615_dev *dev) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci /* disable rf low power beacon mode */ 7262306a36Sopenharmony_ci mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(0), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); 7362306a36Sopenharmony_ci mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(1), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic void 7762306a36Sopenharmony_cimt7615_init_mac_chain(struct mt7615_dev *dev, int chain) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci u32 val; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci if (!chain) 8262306a36Sopenharmony_ci val = MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN; 8362306a36Sopenharmony_ci else 8462306a36Sopenharmony_ci val = MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* enable band 0/1 clk */ 8762306a36Sopenharmony_ci mt76_set(dev, MT_CFG_CCR, val); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci mt76_rmw(dev, MT_TMAC_TRCR(chain), 9062306a36Sopenharmony_ci MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL, 9162306a36Sopenharmony_ci FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) | 9262306a36Sopenharmony_ci FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0)); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_ACR(chain), 9562306a36Sopenharmony_ci MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | 9662306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) | 9762306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT)); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_ARUCR(chain), 10062306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | 10162306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | 10262306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | 10362306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | 10462306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | 10562306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | 10662306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | 10762306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_ARDCR(chain), 11062306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | 11162306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | 11262306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | 11362306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | 11462306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | 11562306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | 11662306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | 11762306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1)); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci mt76_clear(dev, MT_DMA_RCFR0(chain), MT_DMA_RCFR0_MCU_RX_TDLS); 12062306a36Sopenharmony_ci if (!mt7615_firmware_offload(dev)) { 12162306a36Sopenharmony_ci u32 mask, set; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci mask = MT_DMA_RCFR0_MCU_RX_MGMT | 12462306a36Sopenharmony_ci MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR | 12562306a36Sopenharmony_ci MT_DMA_RCFR0_MCU_RX_CTL_BAR | 12662306a36Sopenharmony_ci MT_DMA_RCFR0_MCU_RX_BYPASS | 12762306a36Sopenharmony_ci MT_DMA_RCFR0_RX_DROPPED_UCAST | 12862306a36Sopenharmony_ci MT_DMA_RCFR0_RX_DROPPED_MCAST; 12962306a36Sopenharmony_ci set = FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_UCAST, 2) | 13062306a36Sopenharmony_ci FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_MCAST, 2); 13162306a36Sopenharmony_ci mt76_rmw(dev, MT_DMA_RCFR0(chain), mask, set); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic void 13662306a36Sopenharmony_cimt7615_mac_init(struct mt7615_dev *dev) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci int i; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci mt7615_init_mac_chain(dev, 0); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci mt76_rmw_field(dev, MT_TMAC_CTCR0, 14362306a36Sopenharmony_ci MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); 14462306a36Sopenharmony_ci mt76_rmw_field(dev, MT_TMAC_CTCR0, 14562306a36Sopenharmony_ci MT_TMAC_CTCR0_INS_DDLMT_DENSITY, 0x3); 14662306a36Sopenharmony_ci mt76_rmw(dev, MT_TMAC_CTCR0, 14762306a36Sopenharmony_ci MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | 14862306a36Sopenharmony_ci MT_TMAC_CTCR0_INS_DDLMT_EN, 14962306a36Sopenharmony_ci MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | 15062306a36Sopenharmony_ci MT_TMAC_CTCR0_INS_DDLMT_EN); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0); 15362306a36Sopenharmony_ci mt7615_mac_set_scs(&dev->phy, true); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, 15662306a36Sopenharmony_ci MT_AGG_SCR_NLNAV_MID_PTEC_DIS); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci mt76_wr(dev, MT_AGG_ARCR, 15962306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | 16062306a36Sopenharmony_ci MT_AGG_ARCR_RATE_DOWN_RATIO_EN | 16162306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | 16262306a36Sopenharmony_ci FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4)); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci for (i = 0; i < MT7615_WTBL_SIZE; i++) 16562306a36Sopenharmony_ci mt7615_mac_wtbl_update(dev, i, 16662306a36Sopenharmony_ci MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_EN); 16962306a36Sopenharmony_ci mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci mt76_wr(dev, MT_DMA_DCR0, 17262306a36Sopenharmony_ci FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) | 17362306a36Sopenharmony_ci MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN | 17462306a36Sopenharmony_ci MT_DMA_DCR0_RX_HDR_TRANS_EN); 17562306a36Sopenharmony_ci /* disable TDLS filtering */ 17662306a36Sopenharmony_ci mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN); 17762306a36Sopenharmony_ci mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN); 17862306a36Sopenharmony_ci if (is_mt7663(&dev->mt76)) { 17962306a36Sopenharmony_ci mt76_wr(dev, MT_WF_AGG(0x160), 0x5c341c02); 18062306a36Sopenharmony_ci mt76_wr(dev, MT_WF_AGG(0x164), 0x70708040); 18162306a36Sopenharmony_ci } else { 18262306a36Sopenharmony_ci mt7615_init_mac_chain(dev, 1); 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci mt7615_mcu_set_rx_hdr_trans_blacklist(dev); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic void 18862306a36Sopenharmony_cimt7615_check_offload_capability(struct mt7615_dev *dev) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci struct ieee80211_hw *hw = mt76_hw(dev); 19162306a36Sopenharmony_ci struct wiphy *wiphy = hw->wiphy; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (mt7615_firmware_offload(dev)) { 19462306a36Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_PS); 19562306a36Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci wiphy->flags &= ~WIPHY_FLAG_4ADDR_STATION; 19862306a36Sopenharmony_ci wiphy->max_remain_on_channel_duration = 5000; 19962306a36Sopenharmony_ci wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | 20062306a36Sopenharmony_ci NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | 20162306a36Sopenharmony_ci WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | 20262306a36Sopenharmony_ci NL80211_FEATURE_P2P_GO_CTWIN | 20362306a36Sopenharmony_ci NL80211_FEATURE_P2P_GO_OPPPS; 20462306a36Sopenharmony_ci } else { 20562306a36Sopenharmony_ci dev->ops->hw_scan = NULL; 20662306a36Sopenharmony_ci dev->ops->cancel_hw_scan = NULL; 20762306a36Sopenharmony_ci dev->ops->sched_scan_start = NULL; 20862306a36Sopenharmony_ci dev->ops->sched_scan_stop = NULL; 20962306a36Sopenharmony_ci dev->ops->set_rekey_data = NULL; 21062306a36Sopenharmony_ci dev->ops->remain_on_channel = NULL; 21162306a36Sopenharmony_ci dev->ops->cancel_remain_on_channel = NULL; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci wiphy->max_sched_scan_plan_interval = 0; 21462306a36Sopenharmony_ci wiphy->max_sched_scan_ie_len = 0; 21562306a36Sopenharmony_ci wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; 21662306a36Sopenharmony_ci wiphy->max_sched_scan_ssids = 0; 21762306a36Sopenharmony_ci wiphy->max_match_sets = 0; 21862306a36Sopenharmony_ci wiphy->max_sched_scan_reqs = 0; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cibool mt7615_wait_for_mcu_init(struct mt7615_dev *dev) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci flush_work(&dev->mcu_work); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_wait_for_mcu_init); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic const struct ieee80211_iface_limit if_limits[] = { 23162306a36Sopenharmony_ci { 23262306a36Sopenharmony_ci .max = 1, 23362306a36Sopenharmony_ci .types = BIT(NL80211_IFTYPE_ADHOC) 23462306a36Sopenharmony_ci }, { 23562306a36Sopenharmony_ci .max = MT7615_MAX_INTERFACES, 23662306a36Sopenharmony_ci .types = BIT(NL80211_IFTYPE_AP) | 23762306a36Sopenharmony_ci#ifdef CONFIG_MAC80211_MESH 23862306a36Sopenharmony_ci BIT(NL80211_IFTYPE_MESH_POINT) | 23962306a36Sopenharmony_ci#endif 24062306a36Sopenharmony_ci BIT(NL80211_IFTYPE_P2P_CLIENT) | 24162306a36Sopenharmony_ci BIT(NL80211_IFTYPE_P2P_GO) | 24262306a36Sopenharmony_ci BIT(NL80211_IFTYPE_STATION) 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci}; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic const struct ieee80211_iface_combination if_comb_radar[] = { 24762306a36Sopenharmony_ci { 24862306a36Sopenharmony_ci .limits = if_limits, 24962306a36Sopenharmony_ci .n_limits = ARRAY_SIZE(if_limits), 25062306a36Sopenharmony_ci .max_interfaces = MT7615_MAX_INTERFACES, 25162306a36Sopenharmony_ci .num_different_channels = 1, 25262306a36Sopenharmony_ci .beacon_int_infra_match = true, 25362306a36Sopenharmony_ci .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | 25462306a36Sopenharmony_ci BIT(NL80211_CHAN_WIDTH_20) | 25562306a36Sopenharmony_ci BIT(NL80211_CHAN_WIDTH_40) | 25662306a36Sopenharmony_ci BIT(NL80211_CHAN_WIDTH_80) | 25762306a36Sopenharmony_ci BIT(NL80211_CHAN_WIDTH_160) | 25862306a36Sopenharmony_ci BIT(NL80211_CHAN_WIDTH_80P80), 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci}; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic const struct ieee80211_iface_combination if_comb[] = { 26362306a36Sopenharmony_ci { 26462306a36Sopenharmony_ci .limits = if_limits, 26562306a36Sopenharmony_ci .n_limits = ARRAY_SIZE(if_limits), 26662306a36Sopenharmony_ci .max_interfaces = MT7615_MAX_INTERFACES, 26762306a36Sopenharmony_ci .num_different_channels = 1, 26862306a36Sopenharmony_ci .beacon_int_infra_match = true, 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci}; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_civoid mt7615_init_txpower(struct mt7615_dev *dev, 27362306a36Sopenharmony_ci struct ieee80211_supported_band *sband) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains; 27662306a36Sopenharmony_ci int delta_idx, delta = mt76_tx_power_nss_delta(n_chains); 27762306a36Sopenharmony_ci u8 *eep = (u8 *)dev->mt76.eeprom.data; 27862306a36Sopenharmony_ci enum nl80211_band band = sband->band; 27962306a36Sopenharmony_ci struct mt76_power_limits limits; 28062306a36Sopenharmony_ci u8 rate_val; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci delta_idx = mt7615_eeprom_get_power_delta_index(dev, band); 28362306a36Sopenharmony_ci rate_val = eep[delta_idx]; 28462306a36Sopenharmony_ci if ((rate_val & ~MT_EE_RATE_POWER_MASK) == 28562306a36Sopenharmony_ci (MT_EE_RATE_POWER_EN | MT_EE_RATE_POWER_SIGN)) 28662306a36Sopenharmony_ci delta += rate_val & MT_EE_RATE_POWER_MASK; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (!is_mt7663(&dev->mt76) && mt7615_ext_pa_enabled(dev, band)) 28962306a36Sopenharmony_ci target_chains = 1; 29062306a36Sopenharmony_ci else 29162306a36Sopenharmony_ci target_chains = n_chains; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci for (i = 0; i < sband->n_channels; i++) { 29462306a36Sopenharmony_ci struct ieee80211_channel *chan = &sband->channels[i]; 29562306a36Sopenharmony_ci u8 target_power = 0; 29662306a36Sopenharmony_ci int j; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci for (j = 0; j < target_chains; j++) { 29962306a36Sopenharmony_ci int index; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci index = mt7615_eeprom_get_target_power_index(dev, chan, j); 30262306a36Sopenharmony_ci if (index < 0) 30362306a36Sopenharmony_ci continue; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci target_power = max(target_power, eep[index]); 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci target_power = mt76_get_rate_power_limits(&dev->mphy, chan, 30962306a36Sopenharmony_ci &limits, 31062306a36Sopenharmony_ci target_power); 31162306a36Sopenharmony_ci target_power += delta; 31262306a36Sopenharmony_ci target_power = DIV_ROUND_UP(target_power, 2); 31362306a36Sopenharmony_ci chan->max_power = min_t(int, chan->max_reg_power, 31462306a36Sopenharmony_ci target_power); 31562306a36Sopenharmony_ci chan->orig_mpwr = target_power; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_init_txpower); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_civoid mt7615_init_work(struct mt7615_dev *dev) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci mt7615_mcu_set_eeprom(dev); 32362306a36Sopenharmony_ci mt7615_mac_init(dev); 32462306a36Sopenharmony_ci mt7615_phy_init(dev); 32562306a36Sopenharmony_ci mt7615_mcu_del_wtbl_all(dev); 32662306a36Sopenharmony_ci mt7615_check_offload_capability(dev); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_init_work); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic void 33162306a36Sopenharmony_cimt7615_regd_notifier(struct wiphy *wiphy, 33262306a36Sopenharmony_ci struct regulatory_request *request) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 33562306a36Sopenharmony_ci struct mt7615_dev *dev = mt7615_hw_dev(hw); 33662306a36Sopenharmony_ci struct mt76_phy *mphy = hw->priv; 33762306a36Sopenharmony_ci struct mt7615_phy *phy = mphy->priv; 33862306a36Sopenharmony_ci struct cfg80211_chan_def *chandef = &mphy->chandef; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); 34162306a36Sopenharmony_ci dev->mt76.region = request->dfs_region; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci mt7615_init_txpower(dev, &mphy->sband_2g.sband); 34462306a36Sopenharmony_ci mt7615_init_txpower(dev, &mphy->sband_5g.sband); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci mt7615_mutex_acquire(dev); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if (chandef->chan->flags & IEEE80211_CHAN_RADAR) 34962306a36Sopenharmony_ci mt7615_dfs_init_radar_detector(phy); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (mt7615_firmware_offload(phy->dev)) { 35262306a36Sopenharmony_ci mt76_connac_mcu_set_channel_domain(mphy); 35362306a36Sopenharmony_ci mt76_connac_mcu_set_rate_txpower(mphy); 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci mt7615_mutex_release(dev); 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistatic void 36062306a36Sopenharmony_cimt7615_init_wiphy(struct ieee80211_hw *hw) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci struct mt7615_phy *phy = mt7615_hw_phy(hw); 36362306a36Sopenharmony_ci struct wiphy *wiphy = hw->wiphy; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci hw->queues = 4; 36662306a36Sopenharmony_ci hw->max_rates = 3; 36762306a36Sopenharmony_ci hw->max_report_rates = 7; 36862306a36Sopenharmony_ci hw->max_rate_tries = 11; 36962306a36Sopenharmony_ci hw->netdev_features = NETIF_F_RXCSUM; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci hw->radiotap_timestamp.units_pos = 37262306a36Sopenharmony_ci IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci phy->slottime = 9; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci hw->sta_data_size = sizeof(struct mt7615_sta); 37762306a36Sopenharmony_ci hw->vif_data_size = sizeof(struct mt7615_vif); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (is_mt7663(&phy->dev->mt76)) { 38062306a36Sopenharmony_ci wiphy->iface_combinations = if_comb; 38162306a36Sopenharmony_ci wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); 38262306a36Sopenharmony_ci } else { 38362306a36Sopenharmony_ci wiphy->iface_combinations = if_comb_radar; 38462306a36Sopenharmony_ci wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_radar); 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci wiphy->reg_notifier = mt7615_regd_notifier; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci wiphy->max_sched_scan_plan_interval = 38962306a36Sopenharmony_ci MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL; 39062306a36Sopenharmony_ci wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN; 39162306a36Sopenharmony_ci wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; 39262306a36Sopenharmony_ci wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; 39362306a36Sopenharmony_ci wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH; 39462306a36Sopenharmony_ci wiphy->max_sched_scan_reqs = 1; 39562306a36Sopenharmony_ci wiphy->max_scan_ssids = 4; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); 39862306a36Sopenharmony_ci wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); 39962306a36Sopenharmony_ci wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); 40062306a36Sopenharmony_ci if (!is_mt7622(&phy->dev->mt76)) 40162306a36Sopenharmony_ci wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); 40462306a36Sopenharmony_ci ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); 40562306a36Sopenharmony_ci ieee80211_hw_set(hw, WANT_MONITOR_VIF); 40662306a36Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); 40762306a36Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci if (is_mt7615(&phy->dev->mt76)) 41062306a36Sopenharmony_ci hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; 41162306a36Sopenharmony_ci else 41262306a36Sopenharmony_ci hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; 41562306a36Sopenharmony_ci phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; 41662306a36Sopenharmony_ci phy->mt76->sband_5g.sband.vht_cap.cap |= 41762306a36Sopenharmony_ci IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic void 42162306a36Sopenharmony_cimt7615_cap_dbdc_enable(struct mt7615_dev *dev) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci dev->mphy.sband_5g.sband.vht_cap.cap &= 42462306a36Sopenharmony_ci ~(IEEE80211_VHT_CAP_SHORT_GI_160 | 42562306a36Sopenharmony_ci IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); 42662306a36Sopenharmony_ci if (dev->chainmask == 0xf) 42762306a36Sopenharmony_ci dev->mphy.antenna_mask = dev->chainmask >> 2; 42862306a36Sopenharmony_ci else 42962306a36Sopenharmony_ci dev->mphy.antenna_mask = dev->chainmask >> 1; 43062306a36Sopenharmony_ci dev->mphy.chainmask = dev->mphy.antenna_mask; 43162306a36Sopenharmony_ci dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; 43262306a36Sopenharmony_ci dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; 43362306a36Sopenharmony_ci mt76_set_stream_caps(&dev->mphy, true); 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic void 43762306a36Sopenharmony_cimt7615_cap_dbdc_disable(struct mt7615_dev *dev) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci dev->mphy.sband_5g.sband.vht_cap.cap |= 44062306a36Sopenharmony_ci IEEE80211_VHT_CAP_SHORT_GI_160 | 44162306a36Sopenharmony_ci IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; 44262306a36Sopenharmony_ci dev->mphy.antenna_mask = dev->chainmask; 44362306a36Sopenharmony_ci dev->mphy.chainmask = dev->chainmask; 44462306a36Sopenharmony_ci dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask; 44562306a36Sopenharmony_ci dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask; 44662306a36Sopenharmony_ci mt76_set_stream_caps(&dev->mphy, true); 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ciu32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci u32 base, offset; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci if (is_mt7663(&dev->mt76)) { 45462306a36Sopenharmony_ci base = addr & MT7663_MCU_PCIE_REMAP_2_BASE; 45562306a36Sopenharmony_ci offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET; 45662306a36Sopenharmony_ci } else { 45762306a36Sopenharmony_ci base = addr & MT_MCU_PCIE_REMAP_2_BASE; 45862306a36Sopenharmony_ci offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci return MT_PCIE_REMAP_BASE_2 + offset; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_reg_map); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic void 46762306a36Sopenharmony_cimt7615_led_set_config(struct led_classdev *led_cdev, 46862306a36Sopenharmony_ci u8 delay_on, u8 delay_off) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci struct mt7615_dev *dev; 47162306a36Sopenharmony_ci struct mt76_phy *mphy; 47262306a36Sopenharmony_ci u32 val, addr; 47362306a36Sopenharmony_ci u8 index; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci mphy = container_of(led_cdev, struct mt76_phy, leds.cdev); 47662306a36Sopenharmony_ci dev = container_of(mphy->dev, struct mt7615_dev, mt76); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci if (!mt76_connac_pm_ref(mphy, &dev->pm)) 47962306a36Sopenharmony_ci return; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | 48262306a36Sopenharmony_ci FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | 48362306a36Sopenharmony_ci FIELD_PREP(MT_LED_STATUS_ON, delay_on); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci index = dev->dbdc_support ? mphy->band_idx : mphy->leds.pin; 48662306a36Sopenharmony_ci addr = mt7615_reg_map(dev, MT_LED_STATUS_0(index)); 48762306a36Sopenharmony_ci mt76_wr(dev, addr, val); 48862306a36Sopenharmony_ci addr = mt7615_reg_map(dev, MT_LED_STATUS_1(index)); 48962306a36Sopenharmony_ci mt76_wr(dev, addr, val); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci val = MT_LED_CTRL_REPLAY(index) | MT_LED_CTRL_KICK(index); 49262306a36Sopenharmony_ci if (dev->mphy.leds.al) 49362306a36Sopenharmony_ci val |= MT_LED_CTRL_POLARITY(index); 49462306a36Sopenharmony_ci if (mphy->band_idx) 49562306a36Sopenharmony_ci val |= MT_LED_CTRL_BAND(index); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci addr = mt7615_reg_map(dev, MT_LED_CTRL); 49862306a36Sopenharmony_ci mt76_wr(dev, addr, val); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci mt76_connac_pm_unref(mphy, &dev->pm); 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ciint mt7615_led_set_blink(struct led_classdev *led_cdev, 50462306a36Sopenharmony_ci unsigned long *delay_on, 50562306a36Sopenharmony_ci unsigned long *delay_off) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci u8 delta_on, delta_off; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci delta_off = max_t(u8, *delay_off / 10, 1); 51062306a36Sopenharmony_ci delta_on = max_t(u8, *delay_on / 10, 1); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci mt7615_led_set_config(led_cdev, delta_on, delta_off); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return 0; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_led_set_blink); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_civoid mt7615_led_set_brightness(struct led_classdev *led_cdev, 51962306a36Sopenharmony_ci enum led_brightness brightness) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci if (!brightness) 52262306a36Sopenharmony_ci mt7615_led_set_config(led_cdev, 0, 0xff); 52362306a36Sopenharmony_ci else 52462306a36Sopenharmony_ci mt7615_led_set_config(led_cdev, 0xff, 0); 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_led_set_brightness); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ciint mt7615_register_ext_phy(struct mt7615_dev *dev) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci struct mt7615_phy *phy = mt7615_ext_phy(dev); 53162306a36Sopenharmony_ci struct mt76_phy *mphy; 53262306a36Sopenharmony_ci int i, ret; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (!is_mt7615(&dev->mt76)) 53562306a36Sopenharmony_ci return -EOPNOTSUPP; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) 53862306a36Sopenharmony_ci return -EINVAL; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci if (phy) 54162306a36Sopenharmony_ci return 0; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci mt7615_cap_dbdc_enable(dev); 54462306a36Sopenharmony_ci mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops, MT_BAND1); 54562306a36Sopenharmony_ci if (!mphy) 54662306a36Sopenharmony_ci return -ENOMEM; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci phy = mphy->priv; 54962306a36Sopenharmony_ci phy->dev = dev; 55062306a36Sopenharmony_ci phy->mt76 = mphy; 55162306a36Sopenharmony_ci mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask; 55262306a36Sopenharmony_ci mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1; 55362306a36Sopenharmony_ci mt7615_init_wiphy(mphy->hw); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci INIT_DELAYED_WORK(&mphy->mac_work, mt7615_mac_work); 55662306a36Sopenharmony_ci INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work); 55762306a36Sopenharmony_ci skb_queue_head_init(&phy->scan_event_list); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci INIT_WORK(&phy->roc_work, mt7615_roc_work); 56062306a36Sopenharmony_ci timer_setup(&phy->roc_timer, mt7615_roc_timer, 0); 56162306a36Sopenharmony_ci init_waitqueue_head(&phy->roc_wait); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci mt7615_mac_set_scs(phy, true); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci /* 56662306a36Sopenharmony_ci * Make the secondary PHY MAC address local without overlapping with 56762306a36Sopenharmony_ci * the usual MAC address allocation scheme on multiple virtual interfaces 56862306a36Sopenharmony_ci */ 56962306a36Sopenharmony_ci memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 57062306a36Sopenharmony_ci ETH_ALEN); 57162306a36Sopenharmony_ci mphy->macaddr[0] |= 2; 57262306a36Sopenharmony_ci mphy->macaddr[0] ^= BIT(7); 57362306a36Sopenharmony_ci mt76_eeprom_override(mphy); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci /* second phy can only handle 5 GHz */ 57662306a36Sopenharmony_ci mphy->cap.has_5ghz = true; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* mt7615 second phy shares the same hw queues with the primary one */ 57962306a36Sopenharmony_ci for (i = 0; i <= MT_TXQ_PSD ; i++) 58062306a36Sopenharmony_ci mphy->q_tx[i] = dev->mphy.q_tx[i]; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /* init led callbacks */ 58362306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_MT76_LEDS)) { 58462306a36Sopenharmony_ci mphy->leds.cdev.brightness_set = mt7615_led_set_brightness; 58562306a36Sopenharmony_ci mphy->leds.cdev.blink_set = mt7615_led_set_blink; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci ret = mt76_register_phy(mphy, true, mt76_rates, 58962306a36Sopenharmony_ci ARRAY_SIZE(mt76_rates)); 59062306a36Sopenharmony_ci if (ret) 59162306a36Sopenharmony_ci ieee80211_free_hw(mphy->hw); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci return ret; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_register_ext_phy); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_civoid mt7615_unregister_ext_phy(struct mt7615_dev *dev) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci struct mt7615_phy *phy = mt7615_ext_phy(dev); 60062306a36Sopenharmony_ci struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1]; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci if (!phy) 60362306a36Sopenharmony_ci return; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci mt7615_cap_dbdc_disable(dev); 60662306a36Sopenharmony_ci mt76_unregister_phy(mphy); 60762306a36Sopenharmony_ci ieee80211_free_hw(mphy->hw); 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_unregister_ext_phy); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_civoid mt7615_init_device(struct mt7615_dev *dev) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci struct ieee80211_hw *hw = mt76_hw(dev); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci dev->phy.dev = dev; 61662306a36Sopenharmony_ci dev->phy.mt76 = &dev->mt76.phy; 61762306a36Sopenharmony_ci dev->mt76.phy.priv = &dev->phy; 61862306a36Sopenharmony_ci dev->mt76.tx_worker.fn = mt7615_tx_worker; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci INIT_DELAYED_WORK(&dev->pm.ps_work, mt7615_pm_power_save_work); 62162306a36Sopenharmony_ci INIT_WORK(&dev->pm.wake_work, mt7615_pm_wake_work); 62262306a36Sopenharmony_ci spin_lock_init(&dev->pm.wake.lock); 62362306a36Sopenharmony_ci mutex_init(&dev->pm.mutex); 62462306a36Sopenharmony_ci init_waitqueue_head(&dev->pm.wait); 62562306a36Sopenharmony_ci spin_lock_init(&dev->pm.txq_lock); 62662306a36Sopenharmony_ci INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7615_mac_work); 62762306a36Sopenharmony_ci INIT_DELAYED_WORK(&dev->phy.scan_work, mt7615_scan_work); 62862306a36Sopenharmony_ci INIT_DELAYED_WORK(&dev->coredump.work, mt7615_coredump_work); 62962306a36Sopenharmony_ci skb_queue_head_init(&dev->phy.scan_event_list); 63062306a36Sopenharmony_ci skb_queue_head_init(&dev->coredump.msg_list); 63162306a36Sopenharmony_ci init_waitqueue_head(&dev->reset_wait); 63262306a36Sopenharmony_ci init_waitqueue_head(&dev->phy.roc_wait); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci INIT_WORK(&dev->phy.roc_work, mt7615_roc_work); 63562306a36Sopenharmony_ci timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci mt7615_init_wiphy(hw); 63862306a36Sopenharmony_ci dev->pm.idle_timeout = MT7615_PM_TIMEOUT; 63962306a36Sopenharmony_ci dev->pm.stats.last_wake_event = jiffies; 64062306a36Sopenharmony_ci dev->pm.stats.last_doze_event = jiffies; 64162306a36Sopenharmony_ci mt7615_cap_dbdc_disable(dev); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci#ifdef CONFIG_NL80211_TESTMODE 64462306a36Sopenharmony_ci dev->mt76.test_ops = &mt7615_testmode_ops; 64562306a36Sopenharmony_ci#endif 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_init_device); 648