Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7615/init.c
48525 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2019 MediaTek Inc.2*3* Author: Roy Luo <[email protected]>4* Ryder Lee <[email protected]>5* Felix Fietkau <[email protected]>6* Lorenzo Bianconi <[email protected]>7*/89#include <linux/etherdevice.h>10#include <linux/hwmon.h>11#include <linux/hwmon-sysfs.h>12#include "mt7615.h"13#include "mac.h"14#include "mcu.h"15#include "eeprom.h"1617#if defined(__linux__)18static ssize_t mt7615_thermal_show_temp(struct device *dev,19struct device_attribute *attr,20char *buf)21{22struct mt7615_dev *mdev = dev_get_drvdata(dev);23int temperature;2425if (!mt7615_wait_for_mcu_init(mdev))26return 0;2728mt7615_mutex_acquire(mdev);29temperature = mt7615_mcu_get_temperature(mdev);30mt7615_mutex_release(mdev);3132if (temperature < 0)33return temperature;3435/* display in millidegree celcius */36return sprintf(buf, "%u\n", temperature * 1000);37}3839static SENSOR_DEVICE_ATTR(temp1_input, 0444, mt7615_thermal_show_temp,40NULL, 0);4142static struct attribute *mt7615_hwmon_attrs[] = {43&sensor_dev_attr_temp1_input.dev_attr.attr,44NULL,45};46ATTRIBUTE_GROUPS(mt7615_hwmon);4748int mt7615_thermal_init(struct mt7615_dev *dev)49{50struct wiphy *wiphy = mt76_hw(dev)->wiphy;51struct device *hwmon;52const char *name;5354if (!IS_REACHABLE(CONFIG_HWMON))55return 0;5657name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7615_%s",58wiphy_name(wiphy));59if (!name)60return -ENOMEM;6162hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev,63mt7615_hwmon_groups);64return PTR_ERR_OR_ZERO(hwmon);65}66EXPORT_SYMBOL_GPL(mt7615_thermal_init);67#endif6869static void70mt7615_phy_init(struct mt7615_dev *dev)71{72/* disable rf low power beacon mode */73mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(0), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN);74mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(1), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN);75}7677static void78mt7615_init_mac_chain(struct mt7615_dev *dev, int chain)79{80u32 val;8182if (!chain)83val = MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN;84else85val = MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN;8687/* enable band 0/1 clk */88mt76_set(dev, MT_CFG_CCR, val);8990mt76_rmw(dev, MT_TMAC_TRCR(chain),91MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL,92FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) |93FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0));9495mt76_wr(dev, MT_AGG_ACR(chain),96MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE |97FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) |98FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT));99100mt76_wr(dev, MT_AGG_ARUCR(chain),101FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) |102FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) |103FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) |104FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) |105FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) |106FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) |107FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) |108FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1));109110mt76_wr(dev, MT_AGG_ARDCR(chain),111FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) |112FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) |113FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) |114FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) |115FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) |116FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) |117FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) |118FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1));119120mt76_clear(dev, MT_DMA_RCFR0(chain), MT_DMA_RCFR0_MCU_RX_TDLS);121if (!mt7615_firmware_offload(dev)) {122u32 mask, set;123124mask = MT_DMA_RCFR0_MCU_RX_MGMT |125MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR |126MT_DMA_RCFR0_MCU_RX_CTL_BAR |127MT_DMA_RCFR0_MCU_RX_BYPASS |128MT_DMA_RCFR0_RX_DROPPED_UCAST |129MT_DMA_RCFR0_RX_DROPPED_MCAST;130set = FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_UCAST, 2) |131FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_MCAST, 2);132mt76_rmw(dev, MT_DMA_RCFR0(chain), mask, set);133}134}135136static void137mt7615_mac_init(struct mt7615_dev *dev)138{139int i;140141mt7615_init_mac_chain(dev, 0);142143mt76_rmw_field(dev, MT_TMAC_CTCR0,144MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);145mt76_rmw_field(dev, MT_TMAC_CTCR0,146MT_TMAC_CTCR0_INS_DDLMT_DENSITY, 0x3);147mt76_rmw(dev, MT_TMAC_CTCR0,148MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |149MT_TMAC_CTCR0_INS_DDLMT_EN,150MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |151MT_TMAC_CTCR0_INS_DDLMT_EN);152153mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);154mt7615_mac_set_scs(&dev->phy, true);155156mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS,157MT_AGG_SCR_NLNAV_MID_PTEC_DIS);158159mt76_wr(dev, MT_AGG_ARCR,160FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) |161MT_AGG_ARCR_RATE_DOWN_RATIO_EN |162FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) |163FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4));164165for (i = 0; i < MT7615_WTBL_SIZE; i++)166mt7615_mac_wtbl_update(dev, i,167MT_WTBL_UPDATE_ADM_COUNT_CLEAR);168169mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_EN);170mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN);171172mt76_wr(dev, MT_DMA_DCR0,173FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) |174MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN |175MT_DMA_DCR0_RX_HDR_TRANS_EN);176/* disable TDLS filtering */177mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN);178mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN);179if (is_mt7663(&dev->mt76)) {180mt76_wr(dev, MT_WF_AGG(0x160), 0x5c341c02);181mt76_wr(dev, MT_WF_AGG(0x164), 0x70708040);182} else {183mt7615_init_mac_chain(dev, 1);184}185mt7615_mcu_set_rx_hdr_trans_blacklist(dev);186}187188static void189mt7615_check_offload_capability(struct mt7615_dev *dev)190{191struct ieee80211_hw *hw = mt76_hw(dev);192struct wiphy *wiphy = hw->wiphy;193194if (mt7615_firmware_offload(dev)) {195ieee80211_hw_set(hw, SUPPORTS_PS);196ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);197198wiphy->flags &= ~WIPHY_FLAG_4ADDR_STATION;199wiphy->max_remain_on_channel_duration = 5000;200wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |201NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |202WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |203NL80211_FEATURE_P2P_GO_CTWIN |204NL80211_FEATURE_P2P_GO_OPPPS;205} else {206dev->ops->hw_scan = NULL;207dev->ops->cancel_hw_scan = NULL;208dev->ops->sched_scan_start = NULL;209dev->ops->sched_scan_stop = NULL;210dev->ops->set_rekey_data = NULL;211dev->ops->remain_on_channel = NULL;212dev->ops->cancel_remain_on_channel = NULL;213214wiphy->max_sched_scan_plan_interval = 0;215wiphy->max_sched_scan_ie_len = 0;216wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;217wiphy->max_sched_scan_ssids = 0;218wiphy->max_match_sets = 0;219wiphy->max_sched_scan_reqs = 0;220}221}222223bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev)224{225flush_work(&dev->mcu_work);226227return test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);228}229EXPORT_SYMBOL_GPL(mt7615_wait_for_mcu_init);230231static const struct ieee80211_iface_limit if_limits[] = {232{233.max = 1,234.types = BIT(NL80211_IFTYPE_ADHOC)235}, {236.max = MT7615_MAX_INTERFACES,237.types = BIT(NL80211_IFTYPE_AP) |238#ifdef CONFIG_MAC80211_MESH239BIT(NL80211_IFTYPE_MESH_POINT) |240#endif241BIT(NL80211_IFTYPE_P2P_CLIENT) |242BIT(NL80211_IFTYPE_P2P_GO) |243BIT(NL80211_IFTYPE_STATION)244}245};246247static const struct ieee80211_iface_combination if_comb_radar[] = {248{249.limits = if_limits,250.n_limits = ARRAY_SIZE(if_limits),251.max_interfaces = MT7615_MAX_INTERFACES,252.num_different_channels = 1,253.beacon_int_infra_match = true,254.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |255BIT(NL80211_CHAN_WIDTH_20) |256BIT(NL80211_CHAN_WIDTH_40) |257BIT(NL80211_CHAN_WIDTH_80) |258BIT(NL80211_CHAN_WIDTH_160) |259BIT(NL80211_CHAN_WIDTH_80P80),260}261};262263static const struct ieee80211_iface_combination if_comb[] = {264{265.limits = if_limits,266.n_limits = ARRAY_SIZE(if_limits),267.max_interfaces = MT7615_MAX_INTERFACES,268.num_different_channels = 1,269.beacon_int_infra_match = true,270}271};272273void mt7615_init_txpower(struct mt7615_dev *dev,274struct ieee80211_supported_band *sband)275{276int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains;277int delta_idx, delta = mt76_tx_power_path_delta(n_chains);278u8 *eep = (u8 *)dev->mt76.eeprom.data;279enum nl80211_band band = sband->band;280struct mt76_power_limits limits;281u8 rate_val;282283delta_idx = mt7615_eeprom_get_power_delta_index(dev, band);284rate_val = eep[delta_idx];285if ((rate_val & ~MT_EE_RATE_POWER_MASK) ==286(MT_EE_RATE_POWER_EN | MT_EE_RATE_POWER_SIGN))287delta += rate_val & MT_EE_RATE_POWER_MASK;288289if (!is_mt7663(&dev->mt76) && mt7615_ext_pa_enabled(dev, band))290target_chains = 1;291else292target_chains = n_chains;293294for (i = 0; i < sband->n_channels; i++) {295struct ieee80211_channel *chan = &sband->channels[i];296u8 target_power = 0;297int j;298299for (j = 0; j < target_chains; j++) {300int index;301302index = mt7615_eeprom_get_target_power_index(dev, chan, j);303if (index < 0)304continue;305306target_power = max(target_power, eep[index]);307}308309target_power = mt76_get_rate_power_limits(&dev->mphy, chan,310&limits,311target_power);312target_power += delta;313target_power = DIV_ROUND_UP(target_power, 2);314chan->max_power = min_t(int, chan->max_reg_power,315target_power);316chan->orig_mpwr = target_power;317}318}319EXPORT_SYMBOL_GPL(mt7615_init_txpower);320321void mt7615_init_work(struct mt7615_dev *dev)322{323mt7615_mcu_set_eeprom(dev);324mt7615_mac_init(dev);325mt7615_phy_init(dev);326mt76_connac_mcu_del_wtbl_all(&dev->mt76);327mt7615_check_offload_capability(dev);328}329EXPORT_SYMBOL_GPL(mt7615_init_work);330331static void332mt7615_regd_notifier(struct wiphy *wiphy,333struct regulatory_request *request)334{335struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);336struct mt7615_dev *dev = mt7615_hw_dev(hw);337struct mt76_phy *mphy = hw->priv;338struct mt7615_phy *phy = mphy->priv;339struct cfg80211_chan_def *chandef = &mphy->chandef;340341memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));342dev->mt76.region = request->dfs_region;343344mt7615_init_txpower(dev, &mphy->sband_2g.sband);345mt7615_init_txpower(dev, &mphy->sband_5g.sband);346347mt7615_mutex_acquire(dev);348349if (chandef->chan->flags & IEEE80211_CHAN_RADAR)350mt7615_dfs_init_radar_detector(phy);351352if (mt7615_firmware_offload(phy->dev)) {353mt76_connac_mcu_set_channel_domain(mphy);354mt76_connac_mcu_set_rate_txpower(mphy);355}356357mt7615_mutex_release(dev);358}359360static void361mt7615_init_wiphy(struct ieee80211_hw *hw)362{363struct mt7615_phy *phy = mt7615_hw_phy(hw);364struct wiphy *wiphy = hw->wiphy;365366hw->queues = 4;367hw->max_rates = 3;368hw->max_report_rates = 7;369hw->max_rate_tries = 11;370hw->netdev_features = NETIF_F_RXCSUM;371372hw->radiotap_timestamp.units_pos =373IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;374375phy->slottime = 9;376377hw->sta_data_size = sizeof(struct mt7615_sta);378hw->vif_data_size = sizeof(struct mt7615_vif);379380if (is_mt7663(&phy->dev->mt76)) {381wiphy->iface_combinations = if_comb;382wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);383} else {384wiphy->iface_combinations = if_comb_radar;385wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_radar);386}387wiphy->reg_notifier = mt7615_regd_notifier;388389wiphy->max_sched_scan_plan_interval =390MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL;391wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN;392wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;393wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;394wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;395wiphy->max_sched_scan_reqs = 1;396wiphy->max_scan_ssids = 4;397398wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);399wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);400wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);401if (!is_mt7622(&phy->dev->mt76))402wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);403404ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);405ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);406ieee80211_hw_set(hw, WANT_MONITOR_VIF);407ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);408ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);409410if (is_mt7615(&phy->dev->mt76))411hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM;412else413hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM;414415phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;416phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;417phy->mt76->sband_5g.sband.vht_cap.cap |=418IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;419}420421static void422mt7615_cap_dbdc_enable(struct mt7615_dev *dev)423{424dev->mphy.sband_5g.sband.vht_cap.cap &=425~(IEEE80211_VHT_CAP_SHORT_GI_160 |426IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ);427if (dev->chainmask == 0xf)428dev->mphy.antenna_mask = dev->chainmask >> 2;429else430dev->mphy.antenna_mask = dev->chainmask >> 1;431dev->mphy.chainmask = dev->mphy.antenna_mask;432dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;433dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;434mt76_set_stream_caps(&dev->mphy, true);435}436437static void438mt7615_cap_dbdc_disable(struct mt7615_dev *dev)439{440dev->mphy.sband_5g.sband.vht_cap.cap |=441IEEE80211_VHT_CAP_SHORT_GI_160 |442IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;443dev->mphy.antenna_mask = dev->chainmask;444dev->mphy.chainmask = dev->chainmask;445dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask;446dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask;447mt76_set_stream_caps(&dev->mphy, true);448}449450u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr)451{452u32 base, offset;453454if (is_mt7663(&dev->mt76)) {455base = addr & MT7663_MCU_PCIE_REMAP_2_BASE;456offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET;457} else {458base = addr & MT_MCU_PCIE_REMAP_2_BASE;459offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET;460}461mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base);462463return MT_PCIE_REMAP_BASE_2 + offset;464}465EXPORT_SYMBOL_GPL(mt7615_reg_map);466467static void468mt7615_led_set_config(struct led_classdev *led_cdev,469u8 delay_on, u8 delay_off)470{471struct mt7615_dev *dev;472struct mt76_phy *mphy;473u32 val, addr;474u8 index;475476mphy = container_of(led_cdev, struct mt76_phy, leds.cdev);477dev = container_of(mphy->dev, struct mt7615_dev, mt76);478479if (!mt76_connac_pm_ref(mphy, &dev->pm))480return;481482val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) |483FIELD_PREP(MT_LED_STATUS_OFF, delay_off) |484FIELD_PREP(MT_LED_STATUS_ON, delay_on);485486index = dev->dbdc_support ? mphy->band_idx : mphy->leds.pin;487addr = mt7615_reg_map(dev, MT_LED_STATUS_0(index));488mt76_wr(dev, addr, val);489addr = mt7615_reg_map(dev, MT_LED_STATUS_1(index));490mt76_wr(dev, addr, val);491492val = MT_LED_CTRL_REPLAY(index) | MT_LED_CTRL_KICK(index);493if (dev->mphy.leds.al)494val |= MT_LED_CTRL_POLARITY(index);495if (mphy->band_idx)496val |= MT_LED_CTRL_BAND(index);497498addr = mt7615_reg_map(dev, MT_LED_CTRL);499mt76_wr(dev, addr, val);500501mt76_connac_pm_unref(mphy, &dev->pm);502}503504int mt7615_led_set_blink(struct led_classdev *led_cdev,505unsigned long *delay_on,506unsigned long *delay_off)507{508u8 delta_on, delta_off;509510delta_off = max_t(u8, *delay_off / 10, 1);511delta_on = max_t(u8, *delay_on / 10, 1);512513mt7615_led_set_config(led_cdev, delta_on, delta_off);514515return 0;516}517EXPORT_SYMBOL_GPL(mt7615_led_set_blink);518519void mt7615_led_set_brightness(struct led_classdev *led_cdev,520enum led_brightness brightness)521{522if (!brightness)523mt7615_led_set_config(led_cdev, 0, 0xff);524else525mt7615_led_set_config(led_cdev, 0xff, 0);526}527EXPORT_SYMBOL_GPL(mt7615_led_set_brightness);528529int mt7615_register_ext_phy(struct mt7615_dev *dev)530{531struct mt7615_phy *phy = mt7615_ext_phy(dev);532struct mt76_phy *mphy;533int i, ret;534535if (!is_mt7615(&dev->mt76))536return -EOPNOTSUPP;537538if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))539return -EINVAL;540541if (phy)542return 0;543544mt7615_cap_dbdc_enable(dev);545mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops, MT_BAND1);546if (!mphy)547return -ENOMEM;548549phy = mphy->priv;550phy->dev = dev;551phy->mt76 = mphy;552mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask;553mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1;554mt7615_init_wiphy(mphy->hw);555556INIT_DELAYED_WORK(&mphy->mac_work, mt7615_mac_work);557INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work);558skb_queue_head_init(&phy->scan_event_list);559560INIT_WORK(&phy->roc_work, mt7615_roc_work);561timer_setup(&phy->roc_timer, mt7615_roc_timer, 0);562init_waitqueue_head(&phy->roc_wait);563564mt7615_mac_set_scs(phy, true);565566/*567* Make the secondary PHY MAC address local without overlapping with568* the usual MAC address allocation scheme on multiple virtual interfaces569*/570#if defined(__linux__)571memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,572#elif defined(__FreeBSD__)573memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,574#endif575ETH_ALEN);576mphy->macaddr[0] |= 2;577mphy->macaddr[0] ^= BIT(7);578mt76_eeprom_override(mphy);579580/* second phy can only handle 5 GHz */581mphy->cap.has_5ghz = true;582583/* mt7615 second phy shares the same hw queues with the primary one */584for (i = 0; i <= MT_TXQ_PSD ; i++)585mphy->q_tx[i] = dev->mphy.q_tx[i];586587/* init led callbacks */588if (IS_ENABLED(CONFIG_MT76_LEDS)) {589mphy->leds.cdev.brightness_set = mt7615_led_set_brightness;590mphy->leds.cdev.blink_set = mt7615_led_set_blink;591}592593ret = mt76_register_phy(mphy, true, mt76_rates,594ARRAY_SIZE(mt76_rates));595if (ret)596ieee80211_free_hw(mphy->hw);597598return ret;599}600EXPORT_SYMBOL_GPL(mt7615_register_ext_phy);601602void mt7615_unregister_ext_phy(struct mt7615_dev *dev)603{604struct mt7615_phy *phy = mt7615_ext_phy(dev);605struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];606607if (!phy)608return;609610mt7615_cap_dbdc_disable(dev);611mt76_unregister_phy(mphy);612ieee80211_free_hw(mphy->hw);613}614EXPORT_SYMBOL_GPL(mt7615_unregister_ext_phy);615616void mt7615_init_device(struct mt7615_dev *dev)617{618struct ieee80211_hw *hw = mt76_hw(dev);619620dev->phy.dev = dev;621dev->phy.mt76 = &dev->mt76.phy;622dev->mt76.phy.priv = &dev->phy;623dev->mt76.tx_worker.fn = mt7615_tx_worker;624625INIT_DELAYED_WORK(&dev->pm.ps_work, mt7615_pm_power_save_work);626INIT_WORK(&dev->pm.wake_work, mt7615_pm_wake_work);627spin_lock_init(&dev->pm.wake.lock);628mutex_init(&dev->pm.mutex);629init_waitqueue_head(&dev->pm.wait);630spin_lock_init(&dev->pm.txq_lock);631INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7615_mac_work);632INIT_DELAYED_WORK(&dev->phy.scan_work, mt7615_scan_work);633INIT_DELAYED_WORK(&dev->coredump.work, mt7615_coredump_work);634skb_queue_head_init(&dev->phy.scan_event_list);635skb_queue_head_init(&dev->coredump.msg_list);636init_waitqueue_head(&dev->reset_wait);637init_waitqueue_head(&dev->phy.roc_wait);638639INIT_WORK(&dev->phy.roc_work, mt7615_roc_work);640timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0);641642mt7615_init_wiphy(hw);643dev->pm.idle_timeout = MT7615_PM_TIMEOUT;644dev->pm.stats.last_wake_event = jiffies;645dev->pm.stats.last_doze_event = jiffies;646mt7615_cap_dbdc_disable(dev);647648#ifdef CONFIG_NL80211_TESTMODE649dev->mt76.test_ops = &mt7615_testmode_ops;650#endif651}652EXPORT_SYMBOL_GPL(mt7615_init_device);653654655