Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7915/init.c
48525 views
// SPDX-License-Identifier: ISC1/* 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;305306for (i = 0; i < sband->n_channels; i++) {307struct ieee80211_channel *chan = &sband->channels[i];308u32 target_power = 0;309int j;310311for (j = 0; j < n_chains; j++) {312u32 val;313314val = mt7915_eeprom_get_target_power(dev, chan, j);315target_power = max(target_power, val);316}317318target_power += pwr_delta;319target_power = mt76_get_rate_power_limits(phy->mt76, chan,320&limits,321target_power);322target_power += path_delta;323target_power = DIV_ROUND_UP(target_power, 2);324chan->max_power = min_t(int, chan->max_reg_power,325target_power);326chan->orig_mpwr = target_power;327}328}329330void mt7915_init_txpower(struct mt7915_phy *phy)331{332if (!phy)333return;334335if (phy->mt76->cap.has_2ghz)336__mt7915_init_txpower(phy, &phy->mt76->sband_2g.sband);337if (phy->mt76->cap.has_5ghz)338__mt7915_init_txpower(phy, &phy->mt76->sband_5g.sband);339if (phy->mt76->cap.has_6ghz)340__mt7915_init_txpower(phy, &phy->mt76->sband_6g.sband);341}342343static void344mt7915_regd_notifier(struct wiphy *wiphy,345struct regulatory_request *request)346{347struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);348struct mt7915_dev *dev = mt7915_hw_dev(hw);349struct mt76_phy *mphy = hw->priv;350struct mt7915_phy *phy = mphy->priv;351352memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));353dev->mt76.region = request->dfs_region;354355if (dev->mt76.region == NL80211_DFS_UNSET)356mt7915_mcu_rdd_background_enable(phy, NULL);357358mt7915_init_txpower(phy);359360mphy->dfs_state = MT_DFS_STATE_UNKNOWN;361mt7915_dfs_init_radar_detector(phy);362}363364static void365mt7915_init_wiphy(struct mt7915_phy *phy)366{367struct mt76_phy *mphy = phy->mt76;368struct ieee80211_hw *hw = mphy->hw;369struct mt76_dev *mdev = &phy->dev->mt76;370struct wiphy *wiphy = hw->wiphy;371struct mt7915_dev *dev = phy->dev;372373hw->queues = 4;374hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;375hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;376hw->netdev_features = NETIF_F_RXCSUM;377378if (mtk_wed_device_active(&mdev->mmio.wed))379hw->netdev_features |= NETIF_F_HW_TC;380381hw->radiotap_timestamp.units_pos =382IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;383384phy->slottime = 9;385386hw->sta_data_size = sizeof(struct mt7915_sta);387hw->vif_data_size = sizeof(struct mt7915_vif);388389wiphy->iface_combinations = if_comb;390wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);391wiphy->reg_notifier = mt7915_regd_notifier;392wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;393wiphy->mbssid_max_interfaces = 16;394395wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);396wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);397wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);398wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);399wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);400wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);401wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);402wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);403wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);404wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);405406if (!is_mt7915(&dev->mt76))407wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);408409if (mt7915_eeprom_has_background_radar(phy->dev) &&410#if defined(CONFIG_OF)411(!mdev->dev->of_node ||412!of_property_read_bool(mdev->dev->of_node,413"mediatek,disable-radar-background")))414#else4151)416#endif417wiphy_ext_feature_set(wiphy,418NL80211_EXT_FEATURE_RADAR_BACKGROUND);419420ieee80211_hw_set(hw, HAS_RATE_CONTROL);421ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);422ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);423ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);424ieee80211_hw_set(hw, WANT_MONITOR_VIF);425ieee80211_hw_set(hw, SUPPORTS_TX_FRAG);426427hw->max_tx_fragments = 4;428429if (phy->mt76->cap.has_2ghz) {430phy->mt76->sband_2g.sband.ht_cap.cap |=431IEEE80211_HT_CAP_LDPC_CODING |432IEEE80211_HT_CAP_MAX_AMSDU;433if (is_mt7915(&dev->mt76))434phy->mt76->sband_2g.sband.ht_cap.ampdu_density =435IEEE80211_HT_MPDU_DENSITY_4;436else437phy->mt76->sband_2g.sband.ht_cap.ampdu_density =438IEEE80211_HT_MPDU_DENSITY_2;439}440441if (phy->mt76->cap.has_5ghz) {442struct ieee80211_sta_vht_cap *vht_cap;443444vht_cap = &phy->mt76->sband_5g.sband.vht_cap;445phy->mt76->sband_5g.sband.ht_cap.cap |=446IEEE80211_HT_CAP_LDPC_CODING |447IEEE80211_HT_CAP_MAX_AMSDU;448449if (is_mt7915(&dev->mt76)) {450phy->mt76->sband_5g.sband.ht_cap.ampdu_density =451IEEE80211_HT_MPDU_DENSITY_4;452453vht_cap->cap |=454IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |455IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;456457if (!dev->dbdc_support)458vht_cap->cap |=459IEEE80211_VHT_CAP_SHORT_GI_160 |460FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);461} else {462phy->mt76->sband_5g.sband.ht_cap.ampdu_density =463IEEE80211_HT_MPDU_DENSITY_2;464465vht_cap->cap |=466IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |467IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;468469/* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */470vht_cap->cap |=471IEEE80211_VHT_CAP_SHORT_GI_160 |472IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;473}474475if (!is_mt7915(&dev->mt76) || !dev->dbdc_support)476ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);477}478479mt76_set_stream_caps(phy->mt76, true);480mt7915_set_stream_vht_txbf_caps(phy);481mt7915_set_stream_he_caps(phy);482mt7915_init_txpower(phy);483484wiphy->available_antennas_rx = phy->mt76->antenna_mask;485wiphy->available_antennas_tx = phy->mt76->antenna_mask;486487/* init led callbacks */488if (IS_ENABLED(CONFIG_MT76_LEDS)) {489mphy->leds.cdev.brightness_set = mt7915_led_set_brightness;490mphy->leds.cdev.blink_set = mt7915_led_set_blink;491}492}493494static void495mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)496{497u32 mask, set;498499mt76_rmw_field(dev, MT_TMAC_CTCR0(band),500MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);501mt76_set(dev, MT_TMAC_CTCR0(band),502MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |503MT_TMAC_CTCR0_INS_DDLMT_EN);504505mask = MT_MDP_RCFR0_MCU_RX_MGMT |506MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR |507MT_MDP_RCFR0_MCU_RX_CTL_BAR;508set = FIELD_PREP(MT_MDP_RCFR0_MCU_RX_MGMT, MT_MDP_TO_HIF) |509FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR, MT_MDP_TO_HIF) |510FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_BAR, MT_MDP_TO_HIF);511mt76_rmw(dev, MT_MDP_BNRCFR0(band), mask, set);512513mask = MT_MDP_RCFR1_MCU_RX_BYPASS |514MT_MDP_RCFR1_RX_DROPPED_UCAST |515MT_MDP_RCFR1_RX_DROPPED_MCAST;516set = FIELD_PREP(MT_MDP_RCFR1_MCU_RX_BYPASS, MT_MDP_TO_HIF) |517FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_UCAST, MT_MDP_TO_HIF) |518FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);519mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);520521mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 0x680);522523/* mt7915: disable rx rate report by default due to hw issues */524mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);525526/* clear estimated value of EIFS for Rx duration & OBSS time */527mt76_wr(dev, MT_WF_RMAC_RSVD0(band), MT_WF_RMAC_RSVD0_EIFS_CLR);528529/* clear backoff time for Rx duration */530mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME1(band),531MT_WF_RMAC_MIB_NONQOSD_BACKOFF);532mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME3(band),533MT_WF_RMAC_MIB_QOS01_BACKOFF);534mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME4(band),535MT_WF_RMAC_MIB_QOS23_BACKOFF);536537/* clear backoff time for Tx duration */538mt76_clear(dev, MT_WTBLOFF_TOP_ACR(band),539MT_WTBLOFF_TOP_ADM_BACKOFFTIME);540541/* exclude estimated backoff time for Tx duration on MT7915 */542if (is_mt7915(&dev->mt76))543mt76_set(dev, MT_AGG_ATCR0(band),544MT_AGG_ATCR_MAC_BFF_TIME_EN);545546/* clear backoff time and set software compensation for OBSS time */547mask = MT_WF_RMAC_MIB_OBSS_BACKOFF | MT_WF_RMAC_MIB_ED_OFFSET;548set = FIELD_PREP(MT_WF_RMAC_MIB_OBSS_BACKOFF, 0) |549FIELD_PREP(MT_WF_RMAC_MIB_ED_OFFSET, 4);550mt76_rmw(dev, MT_WF_RMAC_MIB_AIRTIME0(band), mask, set);551552/* filter out non-resp frames and get instanstaeous signal reporting */553mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;554set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |555FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);556mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);557558/* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than559* MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.560*/561if (mtk_wed_device_active(&dev->mt76.mmio.wed))562mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);563}564565static void566mt7915_init_led_mux(struct mt7915_dev *dev)567{568if (!IS_ENABLED(CONFIG_MT76_LEDS))569return;570571if (dev->dbdc_support) {572switch (mt76_chip(&dev->mt76)) {573case 0x7915:574mt76_rmw_field(dev, MT_LED_GPIO_MUX2,575GENMASK(11, 8), 4);576mt76_rmw_field(dev, MT_LED_GPIO_MUX3,577GENMASK(11, 8), 4);578break;579case 0x7986:580mt76_rmw_field(dev, MT_LED_GPIO_MUX0,581GENMASK(7, 4), 1);582mt76_rmw_field(dev, MT_LED_GPIO_MUX0,583GENMASK(11, 8), 1);584break;585case 0x7916:586mt76_rmw_field(dev, MT_LED_GPIO_MUX1,587GENMASK(27, 24), 3);588mt76_rmw_field(dev, MT_LED_GPIO_MUX1,589GENMASK(31, 28), 3);590break;591default:592break;593}594} else if (dev->mphy.leds.pin) {595switch (mt76_chip(&dev->mt76)) {596case 0x7915:597mt76_rmw_field(dev, MT_LED_GPIO_MUX3,598GENMASK(11, 8), 4);599break;600case 0x7986:601mt76_rmw_field(dev, MT_LED_GPIO_MUX0,602GENMASK(11, 8), 1);603break;604case 0x7916:605mt76_rmw_field(dev, MT_LED_GPIO_MUX1,606GENMASK(31, 28), 3);607break;608default:609break;610}611} else {612switch (mt76_chip(&dev->mt76)) {613case 0x7915:614mt76_rmw_field(dev, MT_LED_GPIO_MUX2,615GENMASK(11, 8), 4);616break;617case 0x7986:618mt76_rmw_field(dev, MT_LED_GPIO_MUX0,619GENMASK(7, 4), 1);620break;621case 0x7916:622mt76_rmw_field(dev, MT_LED_GPIO_MUX1,623GENMASK(27, 24), 3);624break;625default:626break;627}628}629}630631void mt7915_mac_init(struct mt7915_dev *dev)632{633int i;634u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;635636/* config pse qid6 wfdma port selection */637if (!is_mt7915(&dev->mt76) && dev->hif2)638mt76_rmw(dev, MT_WF_PP_TOP_RXQ_WFDMA_CF_5, 0,639MT_WF_PP_TOP_RXQ_QID6_WFDMA_HIF_SEL_MASK);640641mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, rx_len);642643if (!is_mt7915(&dev->mt76))644mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);645else646mt76_clear(dev, MT_PLE_HOST_RPT0, MT_PLE_HOST_RPT0_TX_LATENCY);647648/* enable hardware de-agg */649mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);650651for (i = 0; i < mt7915_wtbl_size(dev); i++)652mt7915_mac_wtbl_update(dev, i,653MT_WTBL_UPDATE_ADM_COUNT_CLEAR);654for (i = 0; i < 2; i++)655mt7915_mac_init_band(dev, i);656657mt7915_init_led_mux(dev);658}659660int mt7915_txbf_init(struct mt7915_dev *dev)661{662int ret;663664if (dev->dbdc_support) {665ret = mt7915_mcu_set_txbf(dev, MT_BF_MODULE_UPDATE);666if (ret)667return ret;668}669670/* trigger sounding packets */671ret = mt7915_mcu_set_txbf(dev, MT_BF_SOUNDING_ON);672if (ret)673return ret;674675/* enable eBF */676return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);677}678679static struct mt7915_phy *680mt7915_alloc_ext_phy(struct mt7915_dev *dev)681{682struct mt7915_phy *phy;683struct mt76_phy *mphy;684685if (!dev->dbdc_support)686return NULL;687688mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops, MT_BAND1);689if (!mphy)690return ERR_PTR(-ENOMEM);691692phy = mphy->priv;693phy->dev = dev;694phy->mt76 = mphy;695696/* Bind main phy to band0 and ext_phy to band1 for dbdc case */697phy->mt76->band_idx = 1;698699return phy;700}701702static int703mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)704{705struct mt76_phy *mphy = phy->mt76;706int ret;707708INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);709710mt7915_eeprom_parse_hw_cap(dev, phy);711712#if defined(__linux__)713memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2,714#elif defined(__FreeBSD__)715memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR2,716#endif717ETH_ALEN);718/* Make the secondary PHY MAC address local without overlapping with719* the usual MAC address allocation scheme on multiple virtual interfaces720*/721if (!is_valid_ether_addr(mphy->macaddr)) {722#if defined(__linux__)723memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,724#elif defined(__FreeBSD__)725memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,726#endif727ETH_ALEN);728mphy->macaddr[0] |= 2;729mphy->macaddr[0] ^= BIT(7);730}731mt76_eeprom_override(mphy);732733/* init wiphy according to mphy and phy */734mt7915_init_wiphy(phy);735736ret = mt76_register_phy(mphy, true, mt76_rates,737ARRAY_SIZE(mt76_rates));738if (ret)739return ret;740741ret = mt7915_thermal_init(phy);742if (ret)743goto unreg;744745#if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS)746mt7915_init_debugfs(phy);747#endif748749return 0;750751unreg:752mt76_unregister_phy(mphy);753return ret;754}755756static void mt7915_init_work(struct work_struct *work)757{758struct mt7915_dev *dev = container_of(work, struct mt7915_dev,759init_work);760761mt7915_mcu_set_eeprom(dev);762mt7915_mac_init(dev);763mt7915_txbf_init(dev);764}765766void mt7915_wfsys_reset(struct mt7915_dev *dev)767{768#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0)769#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16)770771if (is_mt7915(&dev->mt76)) {772u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON;773774mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM);775776/* change to software control */777val |= MT_TOP_PWR_SW_RST;778mt76_wr(dev, MT_TOP_PWR_CTRL, val);779780/* reset wfsys */781val &= ~MT_TOP_PWR_SW_RST;782mt76_wr(dev, MT_TOP_PWR_CTRL, val);783784/* release wfsys then mcu re-executes romcode */785val |= MT_TOP_PWR_SW_RST;786mt76_wr(dev, MT_TOP_PWR_CTRL, val);787788/* switch to hw control */789val &= ~MT_TOP_PWR_SW_RST;790val |= MT_TOP_PWR_HW_CTRL;791mt76_wr(dev, MT_TOP_PWR_CTRL, val);792793/* check whether mcu resets to default */794if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR,795MT_MCU_DUMMY_DEFAULT, MT_MCU_DUMMY_DEFAULT,7961000)) {797dev_err(dev->mt76.dev, "wifi subsystem reset failure\n");798return;799}800801/* wfsys reset won't clear host registers */802mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);803804msleep(100);805} else if (is_mt798x(&dev->mt76)) {806mt7986_wmac_disable(dev);807msleep(20);808809mt7986_wmac_enable(dev);810msleep(20);811} else {812mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);813msleep(20);814815mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);816msleep(20);817}818}819820static bool mt7915_band_config(struct mt7915_dev *dev)821{822bool ret = true;823824dev->phy.mt76->band_idx = 0;825826if (is_mt798x(&dev->mt76)) {827u32 sku = mt7915_check_adie(dev, true);828829/*830* for mt7986, dbdc support is determined by the number831* of adie chips and the main phy is bound to band1 when832* dbdc is disabled.833*/834if (sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE) {835dev->phy.mt76->band_idx = 1;836ret = false;837}838} else {839ret = is_mt7915(&dev->mt76) ?840!!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)) : true;841}842843return ret;844}845846static int847mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)848{849int ret, idx;850851mt76_wr(dev, MT_INT_MASK_CSR, 0);852mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);853854INIT_WORK(&dev->init_work, mt7915_init_work);855856ret = mt7915_dma_init(dev, phy2);857if (ret)858return ret;859860set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);861862ret = mt7915_mcu_init(dev);863if (ret)864return ret;865866ret = mt7915_eeprom_init(dev);867if (ret < 0)868return ret;869870if (dev->cal) {871ret = mt7915_mcu_apply_group_cal(dev);872if (ret)873return ret;874}875876/* Beacon and mgmt frames should occupy wcid 0 */877idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);878if (idx)879return -ENOSPC;880881dev->mt76.global_wcid.idx = idx;882dev->mt76.global_wcid.hw_key_idx = -1;883dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;884rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);885886return 0;887}888889void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)890{891int sts;892u32 *cap;893894if (!phy->mt76->cap.has_5ghz)895return;896897sts = hweight8(phy->mt76->chainmask);898cap = &phy->mt76->sband_5g.sband.vht_cap.cap;899900*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |901IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |902FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK,903sts - 1);904905*cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK |906IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |907IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);908909if (sts < 2)910return;911912*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |913IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE |914FIELD_PREP(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,915sts - 1);916}917918static void919mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,920struct ieee80211_sta_he_cap *he_cap, int vif)921{922struct mt7915_dev *dev = phy->dev;923struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;924int sts = hweight8(phy->mt76->chainmask);925u8 c, sts_160 = sts;926927/* Can do 1/2 of STS in 160Mhz mode for mt7915 */928if (is_mt7915(&dev->mt76)) {929if (!dev->dbdc_support)930sts_160 /= 2;931else932sts_160 = 0;933}934935#ifdef CONFIG_MAC80211_MESH936if (vif == NL80211_IFTYPE_MESH_POINT)937return;938#endif939940elem->phy_cap_info[3] &= ~IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;941elem->phy_cap_info[4] &= ~IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;942943c = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;944if (sts_160)945c |= IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;946elem->phy_cap_info[5] &= ~c;947948c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |949IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;950elem->phy_cap_info[6] &= ~c;951952elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;953954c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US;955if (!is_mt7915(&dev->mt76))956c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;957elem->phy_cap_info[2] |= c;958959c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |960IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;961if (sts_160)962c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;963elem->phy_cap_info[4] |= c;964965/* do not support NG16 due to spec D4.0 changes subcarrier idx */966c = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |967IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU;968969if (vif == NL80211_IFTYPE_STATION)970c |= IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;971972elem->phy_cap_info[6] |= c;973974if (sts < 2)975return;976977/* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */978elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3;979980if (vif != NL80211_IFTYPE_AP && vif != NL80211_IFTYPE_STATION)981return;982983elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;984985c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,986sts - 1);987if (sts_160)988c |= FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,989sts_160 - 1);990elem->phy_cap_info[5] |= c;991992if (vif != NL80211_IFTYPE_AP)993return;994995elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;996997c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |998IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;999elem->phy_cap_info[6] |= c;10001001if (!is_mt7915(&dev->mt76)) {1002c = IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |1003IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;1004elem->phy_cap_info[7] |= c;1005}1006}10071008static int1009mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,1010struct ieee80211_sband_iftype_data *data)1011{1012struct mt7915_dev *dev = phy->dev;1013int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);1014u16 mcs_map = 0;1015u16 mcs_map_160 = 0;1016u8 nss_160;10171018if (!is_mt7915(&dev->mt76))1019nss_160 = nss;1020else if (!dev->dbdc_support)1021/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */1022nss_160 = nss / 2;1023else1024/* Can't do 160MHz with mt7915 dbdc */1025nss_160 = 0;10261027for (i = 0; i < 8; i++) {1028if (i < nss)1029mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));1030else1031mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));10321033if (i < nss_160)1034mcs_map_160 |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));1035else1036mcs_map_160 |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));1037}10381039for (i = 0; i < NUM_NL80211_IFTYPES; i++) {1040struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;1041struct ieee80211_he_cap_elem *he_cap_elem =1042&he_cap->he_cap_elem;1043struct ieee80211_he_mcs_nss_supp *he_mcs =1044&he_cap->he_mcs_nss_supp;10451046switch (i) {1047case NL80211_IFTYPE_STATION:1048case NL80211_IFTYPE_AP:1049#ifdef CONFIG_MAC80211_MESH1050case NL80211_IFTYPE_MESH_POINT:1051#endif1052break;1053default:1054continue;1055}10561057data[idx].types_mask = BIT(i);1058he_cap->has_he = true;10591060he_cap_elem->mac_cap_info[0] =1061IEEE80211_HE_MAC_CAP0_HTC_HE;1062he_cap_elem->mac_cap_info[3] =1063IEEE80211_HE_MAC_CAP3_OMI_CONTROL |1064IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;1065he_cap_elem->mac_cap_info[4] =1066IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU;10671068if (band == NL80211_BAND_2GHZ)1069he_cap_elem->phy_cap_info[0] =1070IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;1071else if (nss_160)1072he_cap_elem->phy_cap_info[0] =1073IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |1074IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;1075else1076he_cap_elem->phy_cap_info[0] =1077IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;10781079he_cap_elem->phy_cap_info[1] =1080IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;1081he_cap_elem->phy_cap_info[2] =1082IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |1083IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;10841085switch (i) {1086case NL80211_IFTYPE_AP:1087he_cap_elem->mac_cap_info[0] |=1088IEEE80211_HE_MAC_CAP0_TWT_RES;1089he_cap_elem->mac_cap_info[2] |=1090IEEE80211_HE_MAC_CAP2_BSR;1091he_cap_elem->mac_cap_info[4] |=1092IEEE80211_HE_MAC_CAP4_BQR;1093he_cap_elem->mac_cap_info[5] |=1094IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;1095he_cap_elem->phy_cap_info[3] |=1096IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |1097IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;1098he_cap_elem->phy_cap_info[6] |=1099IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |1100IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;1101he_cap_elem->phy_cap_info[9] |=1102IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |1103IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;1104break;1105case NL80211_IFTYPE_STATION:1106he_cap_elem->mac_cap_info[1] |=1107IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;11081109if (band == NL80211_BAND_2GHZ)1110he_cap_elem->phy_cap_info[0] |=1111IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;1112else1113he_cap_elem->phy_cap_info[0] |=1114IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;11151116he_cap_elem->phy_cap_info[1] |=1117IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |1118IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US;1119he_cap_elem->phy_cap_info[3] |=1120IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |1121IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;1122he_cap_elem->phy_cap_info[6] |=1123IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |1124IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |1125IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;1126he_cap_elem->phy_cap_info[7] |=1127IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |1128IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;1129he_cap_elem->phy_cap_info[8] |=1130IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |1131IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;1132if (nss_160)1133he_cap_elem->phy_cap_info[8] |=1134IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |1135IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;1136he_cap_elem->phy_cap_info[9] |=1137IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |1138IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |1139IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |1140IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |1141IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |1142IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;1143break;1144}11451146memset(he_mcs, 0, sizeof(*he_mcs));1147he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);1148he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);1149he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map_160);1150he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map_160);11511152mt7915_set_stream_he_txbf_caps(phy, he_cap, i);11531154memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));1155if (he_cap_elem->phy_cap_info[6] &1156IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {1157mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band);1158} else {1159he_cap_elem->phy_cap_info[9] |=1160u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,1161IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);1162}11631164if (band == NL80211_BAND_6GHZ) {1165u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |1166IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;11671168cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,1169IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |1170u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,1171IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |1172u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,1173IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);11741175data[idx].he_6ghz_capa.capa = cpu_to_le16(cap);1176}11771178idx++;1179}11801181return idx;1182}11831184void mt7915_set_stream_he_caps(struct mt7915_phy *phy)1185{1186struct ieee80211_sband_iftype_data *data;1187struct ieee80211_supported_band *band;1188int n;11891190if (phy->mt76->cap.has_2ghz) {1191data = phy->iftype[NL80211_BAND_2GHZ];1192n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);11931194band = &phy->mt76->sband_2g.sband;1195_ieee80211_set_sband_iftype_data(band, data, n);1196}11971198if (phy->mt76->cap.has_5ghz) {1199data = phy->iftype[NL80211_BAND_5GHZ];1200n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);12011202band = &phy->mt76->sband_5g.sband;1203_ieee80211_set_sband_iftype_data(band, data, n);1204}12051206if (phy->mt76->cap.has_6ghz) {1207data = phy->iftype[NL80211_BAND_6GHZ];1208n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data);12091210band = &phy->mt76->sband_6g.sband;1211_ieee80211_set_sband_iftype_data(band, data, n);1212}1213}12141215static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)1216{1217struct mt7915_phy *phy = mt7915_ext_phy(dev);1218struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];12191220if (!phy)1221return;12221223#if defined(__linux__)1224mt7915_unregister_thermal(phy);1225#endif1226mt76_unregister_phy(mphy);1227ieee80211_free_hw(mphy->hw);1228}12291230static void mt7915_stop_hardware(struct mt7915_dev *dev)1231{1232mt7915_mcu_exit(dev);1233mt76_connac2_tx_token_put(&dev->mt76);1234mt7915_dma_cleanup(dev);1235tasklet_disable(&dev->mt76.irq_tasklet);12361237if (is_mt798x(&dev->mt76))1238mt7986_wmac_disable(dev);1239}12401241int mt7915_register_device(struct mt7915_dev *dev)1242{1243struct mt7915_phy *phy2;1244int ret;12451246dev->phy.dev = dev;1247dev->phy.mt76 = &dev->mt76.phy;1248dev->mt76.phy.priv = &dev->phy;1249INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);1250INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work);1251INIT_LIST_HEAD(&dev->sta_rc_list);1252INIT_LIST_HEAD(&dev->twt_list);12531254init_waitqueue_head(&dev->reset_wait);1255INIT_WORK(&dev->reset_work, mt7915_mac_reset_work);1256INIT_WORK(&dev->dump_work, mt7915_mac_dump_work);1257mutex_init(&dev->dump_mutex);12581259dev->dbdc_support = mt7915_band_config(dev);12601261phy2 = mt7915_alloc_ext_phy(dev);1262if (IS_ERR(phy2))1263return PTR_ERR(phy2);12641265ret = mt7915_init_hardware(dev, phy2);1266if (ret)1267goto free_phy2;12681269mt7915_init_wiphy(&dev->phy);12701271#ifdef CONFIG_NL80211_TESTMODE1272dev->mt76.test_ops = &mt7915_testmode_ops;1273#endif12741275ret = mt76_register_device(&dev->mt76, true, mt76_rates,1276ARRAY_SIZE(mt76_rates));1277if (ret)1278goto stop_hw;12791280ret = mt7915_thermal_init(&dev->phy);1281if (ret)1282goto unreg_dev;12831284if (phy2) {1285ret = mt7915_register_ext_phy(dev, phy2);1286if (ret)1287goto unreg_thermal;1288}12891290ieee80211_queue_work(mt76_hw(dev), &dev->init_work);12911292dev->recovery.hw_init_done = true;12931294#if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS)1295ret = mt7915_init_debugfs(&dev->phy);1296if (ret)1297goto unreg_thermal;1298#endif12991300ret = mt7915_coredump_register(dev);1301if (ret)1302goto unreg_thermal;13031304return 0;13051306unreg_thermal:1307#if defined(__linux__)1308mt7915_unregister_thermal(&dev->phy);1309#endif1310unreg_dev:1311mt76_unregister_device(&dev->mt76);1312stop_hw:1313mt7915_stop_hardware(dev);1314free_phy2:1315if (phy2)1316ieee80211_free_hw(phy2->mt76->hw);1317return ret;1318}13191320void mt7915_unregister_device(struct mt7915_dev *dev)1321{1322mt7915_unregister_ext_phy(dev);1323mt7915_coredump_unregister(dev);1324#if defined(__linux__)1325mt7915_unregister_thermal(&dev->phy);1326#endif1327mt76_unregister_device(&dev->mt76);1328mt7915_stop_hardware(dev);13291330mt76_free_device(&dev->mt76);1331}133213331334