Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7915/init.c
105687 views
// SPDX-License-Identifier: BSD-3-Clause-Clear1/* Copyright (C) 2020 MediaTek Inc. */23#include <linux/etherdevice.h>4#include <linux/hwmon.h>5#include <linux/hwmon-sysfs.h>6#include <linux/of.h>7#include <linux/thermal.h>8#if defined(__FreeBSD__)9#include <linux/delay.h>10#endif11#include "mt7915.h"12#include "mac.h"13#include "mcu.h"14#include "coredump.h"15#include "eeprom.h"1617static const struct ieee80211_iface_limit if_limits[] = {18{19.max = 1,20.types = BIT(NL80211_IFTYPE_ADHOC)21}, {22.max = 16,23.types = BIT(NL80211_IFTYPE_AP)24#ifdef CONFIG_MAC80211_MESH25| BIT(NL80211_IFTYPE_MESH_POINT)26#endif27}, {28.max = MT7915_MAX_INTERFACES,29.types = BIT(NL80211_IFTYPE_STATION)30}31};3233static const struct ieee80211_iface_combination if_comb[] = {34{35.limits = if_limits,36.n_limits = ARRAY_SIZE(if_limits),37.max_interfaces = MT7915_MAX_INTERFACES,38.num_different_channels = 1,39.beacon_int_infra_match = true,40.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |41BIT(NL80211_CHAN_WIDTH_20) |42BIT(NL80211_CHAN_WIDTH_40) |43BIT(NL80211_CHAN_WIDTH_80) |44BIT(NL80211_CHAN_WIDTH_160),45}46};4748#if defined(__linux__)49static ssize_t mt7915_thermal_temp_show(struct device *dev,50struct device_attribute *attr,51char *buf)52{53struct mt7915_phy *phy = dev_get_drvdata(dev);54int i = to_sensor_dev_attr(attr)->index;55int temperature;5657switch (i) {58case 0:59mutex_lock(&phy->dev->mt76.mutex);60temperature = mt7915_mcu_get_temperature(phy);61mutex_unlock(&phy->dev->mt76.mutex);62if (temperature < 0)63return temperature;64/* display in millidegree celcius */65return sprintf(buf, "%u\n", temperature * 1000);66case 1:67case 2:68return sprintf(buf, "%u\n",69phy->throttle_temp[i - 1] * 1000);70case 3:71return sprintf(buf, "%hhu\n", phy->throttle_state);72default:73return -EINVAL;74}75}7677static ssize_t mt7915_thermal_temp_store(struct device *dev,78struct device_attribute *attr,79const char *buf, size_t count)80{81struct mt7915_phy *phy = dev_get_drvdata(dev);82int ret, i = to_sensor_dev_attr(attr)->index;83long val;8485ret = kstrtol(buf, 10, &val);86if (ret < 0)87return ret;8889mutex_lock(&phy->dev->mt76.mutex);90val = DIV_ROUND_CLOSEST(clamp_val(val, 60 * 1000, 130 * 1000), 1000);9192if ((i - 1 == MT7915_CRIT_TEMP_IDX &&93val > phy->throttle_temp[MT7915_MAX_TEMP_IDX]) ||94(i - 1 == MT7915_MAX_TEMP_IDX &&95val < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) {96dev_err(phy->dev->mt76.dev,97"temp1_max shall be greater than temp1_crit.");98mutex_unlock(&phy->dev->mt76.mutex);99return -EINVAL;100}101102phy->throttle_temp[i - 1] = val;103ret = mt7915_mcu_set_thermal_protect(phy);104mutex_unlock(&phy->dev->mt76.mutex);105if (ret)106return ret;107108return count;109}110111static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7915_thermal_temp, 0);112static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7915_thermal_temp, 1);113static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7915_thermal_temp, 2);114static SENSOR_DEVICE_ATTR_RO(throttle1, mt7915_thermal_temp, 3);115116static struct attribute *mt7915_hwmon_attrs[] = {117&sensor_dev_attr_temp1_input.dev_attr.attr,118&sensor_dev_attr_temp1_crit.dev_attr.attr,119&sensor_dev_attr_temp1_max.dev_attr.attr,120&sensor_dev_attr_throttle1.dev_attr.attr,121NULL,122};123ATTRIBUTE_GROUPS(mt7915_hwmon);124125static int126mt7915_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,127unsigned long *state)128{129*state = MT7915_CDEV_THROTTLE_MAX;130131return 0;132}133134static int135mt7915_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,136unsigned long *state)137{138struct mt7915_phy *phy = cdev->devdata;139140*state = phy->cdev_state;141142return 0;143}144145static int146mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,147unsigned long state)148{149struct mt7915_phy *phy = cdev->devdata;150u8 throttling = MT7915_THERMAL_THROTTLE_MAX - state;151int ret;152153if (state > MT7915_CDEV_THROTTLE_MAX) {154dev_err(phy->dev->mt76.dev,155"please specify a valid throttling state\n");156return -EINVAL;157}158159if (state == phy->cdev_state)160return 0;161162/*163* cooling_device convention: 0 = no cooling, more = more cooling164* mcu convention: 1 = max cooling, more = less cooling165*/166mutex_lock(&phy->dev->mt76.mutex);167ret = mt7915_mcu_set_thermal_throttling(phy, throttling);168mutex_unlock(&phy->dev->mt76.mutex);169if (ret)170return ret;171172phy->cdev_state = state;173174return 0;175}176177static const struct thermal_cooling_device_ops mt7915_thermal_ops = {178.get_max_state = mt7915_thermal_get_max_throttle_state,179.get_cur_state = mt7915_thermal_get_cur_throttle_state,180.set_cur_state = mt7915_thermal_set_cur_throttle_state,181};182183static void mt7915_unregister_thermal(struct mt7915_phy *phy)184{185struct wiphy *wiphy = phy->mt76->hw->wiphy;186187if (!phy->cdev)188return;189190sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");191thermal_cooling_device_unregister(phy->cdev);192}193#endif194195static int mt7915_thermal_init(struct mt7915_phy *phy)196{197#if defined(__linux__)198struct wiphy *wiphy = phy->mt76->hw->wiphy;199struct thermal_cooling_device *cdev;200struct device *hwmon;201const char *name;202203name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7915_%s",204wiphy_name(wiphy));205if (!name)206return -ENOMEM;207208cdev = thermal_cooling_device_register(name, phy, &mt7915_thermal_ops);209if (!IS_ERR(cdev)) {210if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,211"cooling_device") < 0)212thermal_cooling_device_unregister(cdev);213else214phy->cdev = cdev;215}216217/* initialize critical/maximum high temperature */218phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;219phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;220221if (!IS_REACHABLE(CONFIG_HWMON))222return 0;223224hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,225mt7915_hwmon_groups);226return PTR_ERR_OR_ZERO(hwmon);227#elif defined(__FreeBSD__)228return 0;229#endif230}231232#if defined(CONFIG_MT76_LEDS)233static void mt7915_led_set_config(struct led_classdev *led_cdev,234u8 delay_on, u8 delay_off)235{236struct mt7915_dev *dev;237struct mt76_phy *mphy;238u32 val;239240mphy = container_of(led_cdev, struct mt76_phy, leds.cdev);241dev = container_of(mphy->dev, struct mt7915_dev, mt76);242243/* set PWM mode */244val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) |245FIELD_PREP(MT_LED_STATUS_OFF, delay_off) |246FIELD_PREP(MT_LED_STATUS_ON, delay_on);247mt76_wr(dev, MT_LED_STATUS_0(mphy->band_idx), val);248mt76_wr(dev, MT_LED_STATUS_1(mphy->band_idx), val);249250/* enable LED */251mt76_wr(dev, MT_LED_EN(mphy->band_idx), 1);252253/* control LED */254val = MT_LED_CTRL_KICK;255if (dev->mphy.leds.al)256val |= MT_LED_CTRL_POLARITY;257if (mphy->band_idx)258val |= MT_LED_CTRL_BAND;259260mt76_wr(dev, MT_LED_CTRL(mphy->band_idx), val);261mt76_clear(dev, MT_LED_CTRL(mphy->band_idx), MT_LED_CTRL_KICK);262}263#endif264265static int mt7915_led_set_blink(struct led_classdev *led_cdev,266unsigned long *delay_on,267unsigned long *delay_off)268{269#if defined(CONFIG_MT76_LEDS)270u16 delta_on = 0, delta_off = 0;271272#define HW_TICK 10273#define TO_HW_TICK(_t) (((_t) > HW_TICK) ? ((_t) / HW_TICK) : HW_TICK)274275if (*delay_on)276delta_on = TO_HW_TICK(*delay_on);277if (*delay_off)278delta_off = TO_HW_TICK(*delay_off);279280mt7915_led_set_config(led_cdev, delta_on, delta_off);281#endif282283return 0;284}285286static void mt7915_led_set_brightness(struct led_classdev *led_cdev,287enum led_brightness brightness)288{289#if defined(CONFIG_MT76_LEDS)290if (!brightness)291mt7915_led_set_config(led_cdev, 0, 0xff);292else293mt7915_led_set_config(led_cdev, 0xff, 0);294#endif295}296297static void __mt7915_init_txpower(struct mt7915_phy *phy,298struct ieee80211_supported_band *sband)299{300struct mt7915_dev *dev = phy->dev;301int i, n_chains = hweight16(phy->mt76->chainmask);302int path_delta = mt76_tx_power_path_delta(n_chains);303int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band);304struct mt76_power_limits limits;305306phy->sku_limit_en = true;307phy->sku_path_en = true;308for (i = 0; i < sband->n_channels; i++) {309struct ieee80211_channel *chan = &sband->channels[i];310u32 target_power = 0;311int j;312313for (j = 0; j < n_chains; j++) {314u32 val;315316val = mt7915_eeprom_get_target_power(dev, chan, j);317target_power = max(target_power, val);318}319320target_power += pwr_delta;321target_power = mt76_get_rate_power_limits(phy->mt76, chan,322&limits,323target_power);324325/* MT7915N can not enable Backoff table without setting value in dts */326if (!limits.path.ofdm[0])327phy->sku_path_en = false;328329target_power += path_delta;330target_power = DIV_ROUND_UP(target_power, 2);331chan->max_power = min_t(int, chan->max_reg_power,332target_power);333chan->orig_mpwr = target_power;334}335}336337void mt7915_init_txpower(struct mt7915_phy *phy)338{339if (!phy)340return;341342if (phy->mt76->cap.has_2ghz)343__mt7915_init_txpower(phy, &phy->mt76->sband_2g.sband);344if (phy->mt76->cap.has_5ghz)345__mt7915_init_txpower(phy, &phy->mt76->sband_5g.sband);346if (phy->mt76->cap.has_6ghz)347__mt7915_init_txpower(phy, &phy->mt76->sband_6g.sband);348}349350static void351mt7915_regd_notifier(struct wiphy *wiphy,352struct regulatory_request *request)353{354struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);355struct mt7915_dev *dev = mt7915_hw_dev(hw);356struct mt76_phy *mphy = hw->priv;357struct mt7915_phy *phy = mphy->priv;358359memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));360dev->mt76.region = request->dfs_region;361362if (dev->mt76.region == NL80211_DFS_UNSET)363mt7915_mcu_rdd_background_enable(phy, NULL);364365mt7915_init_txpower(phy);366367mphy->dfs_state = MT_DFS_STATE_UNKNOWN;368mt7915_dfs_init_radar_detector(phy);369}370371static void372mt7915_init_wiphy(struct mt7915_phy *phy)373{374struct mt76_phy *mphy = phy->mt76;375struct ieee80211_hw *hw = mphy->hw;376struct mt76_dev *mdev = &phy->dev->mt76;377struct wiphy *wiphy = hw->wiphy;378struct mt7915_dev *dev = phy->dev;379380hw->queues = 4;381hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;382hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;383hw->netdev_features = NETIF_F_RXCSUM;384385if (mtk_wed_device_active(&mdev->mmio.wed))386hw->netdev_features |= NETIF_F_HW_TC;387388hw->radiotap_timestamp.units_pos =389IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;390391phy->slottime = 9;392393hw->sta_data_size = sizeof(struct mt7915_sta);394hw->vif_data_size = sizeof(struct mt7915_vif);395396wiphy->iface_combinations = if_comb;397wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);398wiphy->reg_notifier = mt7915_regd_notifier;399wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;400wiphy->mbssid_max_interfaces = 16;401402wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);403wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);404wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);405wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);406wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);407wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);408wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);409wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);410wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);411wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);412413if (!is_mt7915(&dev->mt76))414wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);415416if (mt7915_eeprom_has_background_radar(phy->dev) &&417#if defined(CONFIG_OF)418(!mdev->dev->of_node ||419!of_property_read_bool(mdev->dev->of_node,420"mediatek,disable-radar-background")))421#else4221)423#endif424wiphy_ext_feature_set(wiphy,425NL80211_EXT_FEATURE_RADAR_BACKGROUND);426427ieee80211_hw_set(hw, HAS_RATE_CONTROL);428ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);429ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);430ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);431ieee80211_hw_set(hw, WANT_MONITOR_VIF);432ieee80211_hw_set(hw, SUPPORTS_TX_FRAG);433434hw->max_tx_fragments = 4;435436if (phy->mt76->cap.has_2ghz) {437phy->mt76->sband_2g.sband.ht_cap.cap |=438IEEE80211_HT_CAP_LDPC_CODING |439IEEE80211_HT_CAP_MAX_AMSDU;440if (is_mt7915(&dev->mt76))441phy->mt76->sband_2g.sband.ht_cap.ampdu_density =442IEEE80211_HT_MPDU_DENSITY_4;443else444phy->mt76->sband_2g.sband.ht_cap.ampdu_density =445IEEE80211_HT_MPDU_DENSITY_2;446}447448if (phy->mt76->cap.has_5ghz) {449struct ieee80211_sta_vht_cap *vht_cap;450451vht_cap = &phy->mt76->sband_5g.sband.vht_cap;452phy->mt76->sband_5g.sband.ht_cap.cap |=453IEEE80211_HT_CAP_LDPC_CODING |454IEEE80211_HT_CAP_MAX_AMSDU;455456if (is_mt7915(&dev->mt76)) {457phy->mt76->sband_5g.sband.ht_cap.ampdu_density =458IEEE80211_HT_MPDU_DENSITY_4;459460vht_cap->cap |=461IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |462IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;463464if (!dev->dbdc_support)465vht_cap->cap |=466IEEE80211_VHT_CAP_SHORT_GI_160 |467FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);468} else {469phy->mt76->sband_5g.sband.ht_cap.ampdu_density =470IEEE80211_HT_MPDU_DENSITY_2;471472vht_cap->cap |=473IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |474IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;475476/* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */477vht_cap->cap |=478IEEE80211_VHT_CAP_SHORT_GI_160 |479IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;480}481482if (!is_mt7915(&dev->mt76) || !dev->dbdc_support)483ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);484}485486mt76_set_stream_caps(phy->mt76, true);487mt7915_set_stream_vht_txbf_caps(phy);488mt7915_set_stream_he_caps(phy);489mt7915_init_txpower(phy);490491wiphy->available_antennas_rx = phy->mt76->antenna_mask;492wiphy->available_antennas_tx = phy->mt76->antenna_mask;493494/* init led callbacks */495if (IS_ENABLED(CONFIG_MT76_LEDS)) {496mphy->leds.cdev.brightness_set = mt7915_led_set_brightness;497mphy->leds.cdev.blink_set = mt7915_led_set_blink;498}499}500501static void502mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)503{504u32 mask, set;505506mt76_rmw_field(dev, MT_TMAC_CTCR0(band),507MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);508mt76_set(dev, MT_TMAC_CTCR0(band),509MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |510MT_TMAC_CTCR0_INS_DDLMT_EN);511512mask = MT_MDP_RCFR0_MCU_RX_MGMT |513MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR |514MT_MDP_RCFR0_MCU_RX_CTL_BAR;515set = FIELD_PREP(MT_MDP_RCFR0_MCU_RX_MGMT, MT_MDP_TO_HIF) |516FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR, MT_MDP_TO_HIF) |517FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_BAR, MT_MDP_TO_HIF);518mt76_rmw(dev, MT_MDP_BNRCFR0(band), mask, set);519520mask = MT_MDP_RCFR1_MCU_RX_BYPASS |521MT_MDP_RCFR1_RX_DROPPED_UCAST |522MT_MDP_RCFR1_RX_DROPPED_MCAST;523set = FIELD_PREP(MT_MDP_RCFR1_MCU_RX_BYPASS, MT_MDP_TO_HIF) |524FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_UCAST, MT_MDP_TO_HIF) |525FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);526mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);527528mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 0x680);529530/* mt7915: disable rx rate report by default due to hw issues */531mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);532533/* clear estimated value of EIFS for Rx duration & OBSS time */534mt76_wr(dev, MT_WF_RMAC_RSVD0(band), MT_WF_RMAC_RSVD0_EIFS_CLR);535536/* clear backoff time for Rx duration */537mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME1(band),538MT_WF_RMAC_MIB_NONQOSD_BACKOFF);539mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME3(band),540MT_WF_RMAC_MIB_QOS01_BACKOFF);541mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME4(band),542MT_WF_RMAC_MIB_QOS23_BACKOFF);543544/* clear backoff time for Tx duration */545mt76_clear(dev, MT_WTBLOFF_TOP_ACR(band),546MT_WTBLOFF_TOP_ADM_BACKOFFTIME);547548/* exclude estimated backoff time for Tx duration on MT7915 */549if (is_mt7915(&dev->mt76))550mt76_set(dev, MT_AGG_ATCR0(band),551MT_AGG_ATCR_MAC_BFF_TIME_EN);552553/* clear backoff time and set software compensation for OBSS time */554mask = MT_WF_RMAC_MIB_OBSS_BACKOFF | MT_WF_RMAC_MIB_ED_OFFSET;555set = FIELD_PREP(MT_WF_RMAC_MIB_OBSS_BACKOFF, 0) |556FIELD_PREP(MT_WF_RMAC_MIB_ED_OFFSET, 4);557mt76_rmw(dev, MT_WF_RMAC_MIB_AIRTIME0(band), mask, set);558559/* filter out non-resp frames and get instanstaeous signal reporting */560mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;561set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |562FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);563mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);564565/* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than566* MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.567*/568if (mtk_wed_device_active(&dev->mt76.mmio.wed))569mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);570}571572static void573mt7915_init_led_mux(struct mt7915_dev *dev)574{575if (!IS_ENABLED(CONFIG_MT76_LEDS))576return;577578if (dev->dbdc_support) {579switch (mt76_chip(&dev->mt76)) {580case 0x7915:581mt76_rmw_field(dev, MT_LED_GPIO_MUX2,582GENMASK(11, 8), 4);583mt76_rmw_field(dev, MT_LED_GPIO_MUX3,584GENMASK(11, 8), 4);585break;586case 0x7986:587mt76_rmw_field(dev, MT_LED_GPIO_MUX0,588GENMASK(7, 4), 1);589mt76_rmw_field(dev, MT_LED_GPIO_MUX0,590GENMASK(11, 8), 1);591break;592case 0x7916:593mt76_rmw_field(dev, MT_LED_GPIO_MUX1,594GENMASK(27, 24), 3);595mt76_rmw_field(dev, MT_LED_GPIO_MUX1,596GENMASK(31, 28), 3);597break;598default:599break;600}601} else if (dev->mphy.leds.pin) {602switch (mt76_chip(&dev->mt76)) {603case 0x7915:604mt76_rmw_field(dev, MT_LED_GPIO_MUX3,605GENMASK(11, 8), 4);606break;607case 0x7986:608mt76_rmw_field(dev, MT_LED_GPIO_MUX0,609GENMASK(11, 8), 1);610break;611case 0x7916:612mt76_rmw_field(dev, MT_LED_GPIO_MUX1,613GENMASK(31, 28), 3);614break;615default:616break;617}618} else {619switch (mt76_chip(&dev->mt76)) {620case 0x7915:621mt76_rmw_field(dev, MT_LED_GPIO_MUX2,622GENMASK(11, 8), 4);623break;624case 0x7986:625mt76_rmw_field(dev, MT_LED_GPIO_MUX0,626GENMASK(7, 4), 1);627break;628case 0x7916:629mt76_rmw_field(dev, MT_LED_GPIO_MUX1,630GENMASK(27, 24), 3);631break;632default:633break;634}635}636}637638void mt7915_mac_init(struct mt7915_dev *dev)639{640int i;641u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;642643/* config pse qid6 wfdma port selection */644if (!is_mt7915(&dev->mt76) && dev->hif2)645mt76_rmw(dev, MT_WF_PP_TOP_RXQ_WFDMA_CF_5, 0,646MT_WF_PP_TOP_RXQ_QID6_WFDMA_HIF_SEL_MASK);647648mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, rx_len);649650if (!is_mt7915(&dev->mt76))651mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);652else653mt76_clear(dev, MT_PLE_HOST_RPT0, MT_PLE_HOST_RPT0_TX_LATENCY);654655/* enable hardware de-agg */656mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);657658for (i = 0; i < mt7915_wtbl_size(dev); i++)659mt7915_mac_wtbl_update(dev, i,660MT_WTBL_UPDATE_ADM_COUNT_CLEAR);661for (i = 0; i < 2; i++)662mt7915_mac_init_band(dev, i);663664mt7915_init_led_mux(dev);665}666667int mt7915_txbf_init(struct mt7915_dev *dev)668{669int ret;670671if (dev->dbdc_support) {672ret = mt7915_mcu_set_txbf(dev, MT_BF_MODULE_UPDATE);673if (ret)674return ret;675}676677/* trigger sounding packets */678ret = mt7915_mcu_set_txbf(dev, MT_BF_SOUNDING_ON);679if (ret)680return ret;681682/* enable eBF */683return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);684}685686static struct mt7915_phy *687mt7915_alloc_ext_phy(struct mt7915_dev *dev)688{689struct mt7915_phy *phy;690struct mt76_phy *mphy;691692if (!dev->dbdc_support)693return NULL;694695mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops, MT_BAND1);696if (!mphy)697return ERR_PTR(-ENOMEM);698699phy = mphy->priv;700phy->dev = dev;701phy->mt76 = mphy;702703/* Bind main phy to band0 and ext_phy to band1 for dbdc case */704phy->mt76->band_idx = 1;705706return phy;707}708709static int710mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)711{712struct mt76_phy *mphy = phy->mt76;713int ret;714715INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);716717mt7915_eeprom_parse_hw_cap(dev, phy);718719#if defined(__linux__)720memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2,721#elif defined(__FreeBSD__)722memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR2,723#endif724ETH_ALEN);725/* Make the secondary PHY MAC address local without overlapping with726* the usual MAC address allocation scheme on multiple virtual interfaces727*/728if (!is_valid_ether_addr(mphy->macaddr)) {729#if defined(__linux__)730memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,731#elif defined(__FreeBSD__)732memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,733#endif734ETH_ALEN);735mphy->macaddr[0] |= 2;736mphy->macaddr[0] ^= BIT(7);737}738ret = mt76_eeprom_override(mphy);739if (ret)740return ret;741742/* init wiphy according to mphy and phy */743mt7915_init_wiphy(phy);744745ret = mt76_register_phy(mphy, true, mt76_rates,746ARRAY_SIZE(mt76_rates));747if (ret)748return ret;749750ret = mt7915_thermal_init(phy);751if (ret)752goto unreg;753754#if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS)755mt7915_init_debugfs(phy);756#endif757758return 0;759760unreg:761mt76_unregister_phy(mphy);762return ret;763}764765static void mt7915_init_work(struct work_struct *work)766{767struct mt7915_dev *dev = container_of(work, struct mt7915_dev,768init_work);769770mt7915_mcu_set_eeprom(dev);771mt7915_mac_init(dev);772mt7915_txbf_init(dev);773}774775void mt7915_wfsys_reset(struct mt7915_dev *dev)776{777#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0)778#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16)779780if (is_mt7915(&dev->mt76)) {781u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON;782783mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM);784785/* change to software control */786val |= MT_TOP_PWR_SW_RST;787mt76_wr(dev, MT_TOP_PWR_CTRL, val);788789/* reset wfsys */790val &= ~MT_TOP_PWR_SW_RST;791mt76_wr(dev, MT_TOP_PWR_CTRL, val);792793/* release wfsys then mcu re-executes romcode */794val |= MT_TOP_PWR_SW_RST;795mt76_wr(dev, MT_TOP_PWR_CTRL, val);796797/* switch to hw control */798val &= ~MT_TOP_PWR_SW_RST;799val |= MT_TOP_PWR_HW_CTRL;800mt76_wr(dev, MT_TOP_PWR_CTRL, val);801802/* check whether mcu resets to default */803if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR,804MT_MCU_DUMMY_DEFAULT, MT_MCU_DUMMY_DEFAULT,8051000)) {806dev_err(dev->mt76.dev, "wifi subsystem reset failure\n");807return;808}809810/* wfsys reset won't clear host registers */811mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);812813msleep(100);814} else if (is_mt798x(&dev->mt76)) {815mt7986_wmac_disable(dev);816msleep(20);817818mt7986_wmac_enable(dev);819msleep(20);820} else {821mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);822msleep(20);823824mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);825msleep(20);826}827}828829static bool mt7915_band_config(struct mt7915_dev *dev)830{831bool ret = true;832833dev->phy.mt76->band_idx = 0;834835if (is_mt798x(&dev->mt76)) {836u32 sku = mt7915_check_adie(dev, true);837838/*839* for mt7986, dbdc support is determined by the number840* of adie chips and the main phy is bound to band1 when841* dbdc is disabled.842*/843if (sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE) {844dev->phy.mt76->band_idx = 1;845ret = false;846}847} else {848ret = is_mt7915(&dev->mt76) ?849!!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)) : true;850}851852return ret;853}854855static int856mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)857{858int ret, idx;859860mt76_wr(dev, MT_INT_MASK_CSR, 0);861mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);862863INIT_WORK(&dev->init_work, mt7915_init_work);864865ret = mt7915_dma_init(dev, phy2);866if (ret)867return ret;868869set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);870871ret = mt7915_mcu_init(dev);872if (ret)873return ret;874875ret = mt7915_eeprom_init(dev);876if (ret < 0)877return ret;878879if (dev->cal) {880ret = mt7915_mcu_apply_group_cal(dev);881if (ret)882return ret;883}884885/* Beacon and mgmt frames should occupy wcid 0 */886idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);887if (idx)888return -ENOSPC;889890dev->mt76.global_wcid.idx = idx;891dev->mt76.global_wcid.hw_key_idx = -1;892dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;893rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);894895return 0;896}897898void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)899{900int sts;901u32 *cap;902903if (!phy->mt76->cap.has_5ghz)904return;905906sts = hweight8(phy->mt76->chainmask);907cap = &phy->mt76->sband_5g.sband.vht_cap.cap;908909*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |910IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |911FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK,912sts - 1);913914*cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK |915IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |916IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);917918if (sts < 2)919return;920921*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |922IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE |923FIELD_PREP(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,924sts - 1);925}926927static void928mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,929struct ieee80211_sta_he_cap *he_cap, int vif)930{931struct mt7915_dev *dev = phy->dev;932struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;933int sts = hweight8(phy->mt76->chainmask);934u8 c, sts_160 = sts;935936/* Can do 1/2 of STS in 160Mhz mode for mt7915 */937if (is_mt7915(&dev->mt76)) {938if (!dev->dbdc_support)939sts_160 /= 2;940else941sts_160 = 0;942}943944#ifdef CONFIG_MAC80211_MESH945if (vif == NL80211_IFTYPE_MESH_POINT)946return;947#endif948949elem->phy_cap_info[3] &= ~IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;950elem->phy_cap_info[4] &= ~IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;951952c = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;953if (sts_160)954c |= IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;955elem->phy_cap_info[5] &= ~c;956957c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |958IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;959elem->phy_cap_info[6] &= ~c;960961elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;962963c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US;964if (!is_mt7915(&dev->mt76))965c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;966elem->phy_cap_info[2] |= c;967968c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |969IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;970if (sts_160)971c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;972elem->phy_cap_info[4] |= c;973974/* do not support NG16 due to spec D4.0 changes subcarrier idx */975c = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |976IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU;977978if (vif == NL80211_IFTYPE_STATION)979c |= IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;980981elem->phy_cap_info[6] |= c;982983if (sts < 2)984return;985986/* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */987elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3;988989if (vif != NL80211_IFTYPE_AP && vif != NL80211_IFTYPE_STATION)990return;991992elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;993994c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,995sts - 1);996if (sts_160)997c |= FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,998sts_160 - 1);999elem->phy_cap_info[5] |= c;10001001if (vif != NL80211_IFTYPE_AP)1002return;10031004elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;10051006c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |1007IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;1008elem->phy_cap_info[6] |= c;10091010if (!is_mt7915(&dev->mt76)) {1011c = IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |1012IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;1013elem->phy_cap_info[7] |= c;1014}1015}10161017static int1018mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,1019struct ieee80211_sband_iftype_data *data)1020{1021struct mt7915_dev *dev = phy->dev;1022int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);1023u16 mcs_map = 0;1024u16 mcs_map_160 = 0;1025u8 nss_160;10261027if (!is_mt7915(&dev->mt76))1028nss_160 = nss;1029else if (!dev->dbdc_support)1030/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */1031nss_160 = nss / 2;1032else1033/* Can't do 160MHz with mt7915 dbdc */1034nss_160 = 0;10351036for (i = 0; i < 8; i++) {1037if (i < nss)1038mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));1039else1040mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));10411042if (i < nss_160)1043mcs_map_160 |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));1044else1045mcs_map_160 |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));1046}10471048for (i = 0; i < NUM_NL80211_IFTYPES; i++) {1049struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;1050struct ieee80211_he_cap_elem *he_cap_elem =1051&he_cap->he_cap_elem;1052struct ieee80211_he_mcs_nss_supp *he_mcs =1053&he_cap->he_mcs_nss_supp;10541055switch (i) {1056case NL80211_IFTYPE_STATION:1057case NL80211_IFTYPE_AP:1058#ifdef CONFIG_MAC80211_MESH1059case NL80211_IFTYPE_MESH_POINT:1060#endif1061break;1062default:1063continue;1064}10651066data[idx].types_mask = BIT(i);1067he_cap->has_he = true;10681069he_cap_elem->mac_cap_info[0] =1070IEEE80211_HE_MAC_CAP0_HTC_HE;1071he_cap_elem->mac_cap_info[3] =1072IEEE80211_HE_MAC_CAP3_OMI_CONTROL |1073IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;1074he_cap_elem->mac_cap_info[4] =1075IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU;10761077if (band == NL80211_BAND_2GHZ)1078he_cap_elem->phy_cap_info[0] =1079IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;1080else if (nss_160)1081he_cap_elem->phy_cap_info[0] =1082IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |1083IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;1084else1085he_cap_elem->phy_cap_info[0] =1086IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;10871088he_cap_elem->phy_cap_info[1] =1089IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;1090he_cap_elem->phy_cap_info[2] =1091IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |1092IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;10931094switch (i) {1095case NL80211_IFTYPE_AP:1096he_cap_elem->mac_cap_info[0] |=1097IEEE80211_HE_MAC_CAP0_TWT_RES;1098he_cap_elem->mac_cap_info[2] |=1099IEEE80211_HE_MAC_CAP2_BSR;1100he_cap_elem->mac_cap_info[4] |=1101IEEE80211_HE_MAC_CAP4_BQR;1102he_cap_elem->mac_cap_info[5] |=1103IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;1104he_cap_elem->phy_cap_info[3] |=1105IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |1106IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;1107he_cap_elem->phy_cap_info[6] |=1108IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |1109IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;1110he_cap_elem->phy_cap_info[9] |=1111IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |1112IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;1113break;1114case NL80211_IFTYPE_STATION:1115he_cap_elem->mac_cap_info[1] |=1116IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;11171118if (band == NL80211_BAND_2GHZ)1119he_cap_elem->phy_cap_info[0] |=1120IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;1121else1122he_cap_elem->phy_cap_info[0] |=1123IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;11241125he_cap_elem->phy_cap_info[1] |=1126IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |1127IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US;1128he_cap_elem->phy_cap_info[3] |=1129IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |1130IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;1131he_cap_elem->phy_cap_info[6] |=1132IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |1133IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |1134IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;1135he_cap_elem->phy_cap_info[7] |=1136IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |1137IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;1138he_cap_elem->phy_cap_info[8] |=1139IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |1140IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;1141if (nss_160)1142he_cap_elem->phy_cap_info[8] |=1143IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |1144IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;1145he_cap_elem->phy_cap_info[9] |=1146IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |1147IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |1148IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |1149IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |1150IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |1151IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;1152break;1153}11541155memset(he_mcs, 0, sizeof(*he_mcs));1156he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);1157he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);1158he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map_160);1159he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map_160);11601161mt7915_set_stream_he_txbf_caps(phy, he_cap, i);11621163memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));1164if (he_cap_elem->phy_cap_info[6] &1165IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {1166mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band);1167} else {1168he_cap_elem->phy_cap_info[9] |=1169u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,1170IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);1171}11721173if (band == NL80211_BAND_6GHZ) {1174u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |1175IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;11761177cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,1178IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |1179u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,1180IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |1181u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,1182IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);11831184data[idx].he_6ghz_capa.capa = cpu_to_le16(cap);1185}11861187idx++;1188}11891190return idx;1191}11921193void mt7915_set_stream_he_caps(struct mt7915_phy *phy)1194{1195struct ieee80211_sband_iftype_data *data;1196struct ieee80211_supported_band *band;1197int n;11981199if (phy->mt76->cap.has_2ghz) {1200data = phy->iftype[NL80211_BAND_2GHZ];1201n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);12021203band = &phy->mt76->sband_2g.sband;1204_ieee80211_set_sband_iftype_data(band, data, n);1205}12061207if (phy->mt76->cap.has_5ghz) {1208data = phy->iftype[NL80211_BAND_5GHZ];1209n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);12101211band = &phy->mt76->sband_5g.sband;1212_ieee80211_set_sband_iftype_data(band, data, n);1213}12141215if (phy->mt76->cap.has_6ghz) {1216data = phy->iftype[NL80211_BAND_6GHZ];1217n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data);12181219band = &phy->mt76->sband_6g.sband;1220_ieee80211_set_sband_iftype_data(band, data, n);1221}1222}12231224static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)1225{1226struct mt7915_phy *phy = mt7915_ext_phy(dev);1227struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];12281229if (!phy)1230return;12311232#if defined(__linux__)1233mt7915_unregister_thermal(phy);1234#endif1235mt76_unregister_phy(mphy);1236ieee80211_free_hw(mphy->hw);1237}12381239static void mt7915_stop_hardware(struct mt7915_dev *dev)1240{1241mt7915_mcu_exit(dev);1242mt76_connac2_tx_token_put(&dev->mt76);1243mt7915_dma_cleanup(dev);1244tasklet_disable(&dev->mt76.irq_tasklet);12451246if (is_mt798x(&dev->mt76))1247mt7986_wmac_disable(dev);1248}12491250int mt7915_register_device(struct mt7915_dev *dev)1251{1252struct mt7915_phy *phy2;1253int ret;12541255dev->phy.dev = dev;1256dev->phy.mt76 = &dev->mt76.phy;1257dev->mt76.phy.priv = &dev->phy;1258INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);1259INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work);1260INIT_LIST_HEAD(&dev->sta_rc_list);1261INIT_LIST_HEAD(&dev->twt_list);12621263init_waitqueue_head(&dev->reset_wait);1264INIT_WORK(&dev->reset_work, mt7915_mac_reset_work);1265INIT_WORK(&dev->dump_work, mt7915_mac_dump_work);1266mutex_init(&dev->dump_mutex);12671268dev->dbdc_support = mt7915_band_config(dev);12691270phy2 = mt7915_alloc_ext_phy(dev);1271if (IS_ERR(phy2))1272return PTR_ERR(phy2);12731274ret = mt7915_init_hardware(dev, phy2);1275if (ret)1276goto free_phy2;12771278mt7915_init_wiphy(&dev->phy);12791280#ifdef CONFIG_NL80211_TESTMODE1281dev->mt76.test_ops = &mt7915_testmode_ops;1282#endif12831284ret = mt76_register_device(&dev->mt76, true, mt76_rates,1285ARRAY_SIZE(mt76_rates));1286if (ret)1287goto stop_hw;12881289ret = mt7915_thermal_init(&dev->phy);1290if (ret)1291goto unreg_dev;12921293if (phy2) {1294ret = mt7915_register_ext_phy(dev, phy2);1295if (ret)1296goto unreg_thermal;1297}12981299ieee80211_queue_work(mt76_hw(dev), &dev->init_work);13001301dev->recovery.hw_init_done = true;13021303#if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS)1304ret = mt7915_init_debugfs(&dev->phy);1305if (ret)1306goto unreg_thermal;1307#endif13081309ret = mt7915_coredump_register(dev);1310if (ret)1311goto unreg_thermal;13121313return 0;13141315unreg_thermal:1316#if defined(__linux__)1317mt7915_unregister_thermal(&dev->phy);1318#endif1319unreg_dev:1320mt76_unregister_device(&dev->mt76);1321stop_hw:1322mt7915_stop_hardware(dev);1323free_phy2:1324if (phy2)1325ieee80211_free_hw(phy2->mt76->hw);1326return ret;1327}13281329void mt7915_unregister_device(struct mt7915_dev *dev)1330{1331mt7915_unregister_ext_phy(dev);1332mt7915_coredump_unregister(dev);1333#if defined(__linux__)1334mt7915_unregister_thermal(&dev->phy);1335#endif1336mt76_unregister_device(&dev->mt76);1337mt7915_stop_hardware(dev);13381339mt76_free_device(&dev->mt76);1340}134113421343