16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2020 MediaTek Inc. */
36c92544dSBjoern A. Zeeb
46c92544dSBjoern A. Zeeb #include <linux/etherdevice.h>
56c92544dSBjoern A. Zeeb #include <linux/hwmon.h>
66c92544dSBjoern A. Zeeb #include <linux/hwmon-sysfs.h>
7cbb3ec25SBjoern A. Zeeb #include <linux/of.h>
86c92544dSBjoern A. Zeeb #include <linux/thermal.h>
96c92544dSBjoern A. Zeeb #if defined(__FreeBSD__)
106c92544dSBjoern A. Zeeb #include <linux/delay.h>
116c92544dSBjoern A. Zeeb #endif
126c92544dSBjoern A. Zeeb #include "mt7915.h"
136c92544dSBjoern A. Zeeb #include "mac.h"
146c92544dSBjoern A. Zeeb #include "mcu.h"
15cbb3ec25SBjoern A. Zeeb #include "coredump.h"
166c92544dSBjoern A. Zeeb #include "eeprom.h"
176c92544dSBjoern A. Zeeb
186c92544dSBjoern A. Zeeb static const struct ieee80211_iface_limit if_limits[] = {
196c92544dSBjoern A. Zeeb {
206c92544dSBjoern A. Zeeb .max = 1,
216c92544dSBjoern A. Zeeb .types = BIT(NL80211_IFTYPE_ADHOC)
226c92544dSBjoern A. Zeeb }, {
236c92544dSBjoern A. Zeeb .max = 16,
246c92544dSBjoern A. Zeeb .types = BIT(NL80211_IFTYPE_AP)
256c92544dSBjoern A. Zeeb #ifdef CONFIG_MAC80211_MESH
266c92544dSBjoern A. Zeeb | BIT(NL80211_IFTYPE_MESH_POINT)
276c92544dSBjoern A. Zeeb #endif
286c92544dSBjoern A. Zeeb }, {
296c92544dSBjoern A. Zeeb .max = MT7915_MAX_INTERFACES,
306c92544dSBjoern A. Zeeb .types = BIT(NL80211_IFTYPE_STATION)
316c92544dSBjoern A. Zeeb }
326c92544dSBjoern A. Zeeb };
336c92544dSBjoern A. Zeeb
346c92544dSBjoern A. Zeeb static const struct ieee80211_iface_combination if_comb[] = {
356c92544dSBjoern A. Zeeb {
366c92544dSBjoern A. Zeeb .limits = if_limits,
376c92544dSBjoern A. Zeeb .n_limits = ARRAY_SIZE(if_limits),
386c92544dSBjoern A. Zeeb .max_interfaces = MT7915_MAX_INTERFACES,
396c92544dSBjoern A. Zeeb .num_different_channels = 1,
406c92544dSBjoern A. Zeeb .beacon_int_infra_match = true,
416c92544dSBjoern A. Zeeb .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
426c92544dSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_20) |
436c92544dSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_40) |
446c92544dSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_80) |
45cbb3ec25SBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_160),
466c92544dSBjoern A. Zeeb }
476c92544dSBjoern A. Zeeb };
486c92544dSBjoern A. Zeeb
496c92544dSBjoern A. Zeeb #if defined(__linux__)
mt7915_thermal_temp_show(struct device * dev,struct device_attribute * attr,char * buf)506c92544dSBjoern A. Zeeb static ssize_t mt7915_thermal_temp_show(struct device *dev,
516c92544dSBjoern A. Zeeb struct device_attribute *attr,
526c92544dSBjoern A. Zeeb char *buf)
536c92544dSBjoern A. Zeeb {
546c92544dSBjoern A. Zeeb struct mt7915_phy *phy = dev_get_drvdata(dev);
556c92544dSBjoern A. Zeeb int i = to_sensor_dev_attr(attr)->index;
566c92544dSBjoern A. Zeeb int temperature;
576c92544dSBjoern A. Zeeb
586c92544dSBjoern A. Zeeb switch (i) {
596c92544dSBjoern A. Zeeb case 0:
60*8ba4d145SBjoern A. Zeeb mutex_lock(&phy->dev->mt76.mutex);
616c92544dSBjoern A. Zeeb temperature = mt7915_mcu_get_temperature(phy);
62*8ba4d145SBjoern A. Zeeb mutex_unlock(&phy->dev->mt76.mutex);
636c92544dSBjoern A. Zeeb if (temperature < 0)
646c92544dSBjoern A. Zeeb return temperature;
656c92544dSBjoern A. Zeeb /* display in millidegree celcius */
666c92544dSBjoern A. Zeeb return sprintf(buf, "%u\n", temperature * 1000);
676c92544dSBjoern A. Zeeb case 1:
686c92544dSBjoern A. Zeeb case 2:
696c92544dSBjoern A. Zeeb return sprintf(buf, "%u\n",
706c92544dSBjoern A. Zeeb phy->throttle_temp[i - 1] * 1000);
716c92544dSBjoern A. Zeeb case 3:
726c92544dSBjoern A. Zeeb return sprintf(buf, "%hhu\n", phy->throttle_state);
736c92544dSBjoern A. Zeeb default:
746c92544dSBjoern A. Zeeb return -EINVAL;
756c92544dSBjoern A. Zeeb }
766c92544dSBjoern A. Zeeb }
776c92544dSBjoern A. Zeeb
mt7915_thermal_temp_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)786c92544dSBjoern A. Zeeb static ssize_t mt7915_thermal_temp_store(struct device *dev,
796c92544dSBjoern A. Zeeb struct device_attribute *attr,
806c92544dSBjoern A. Zeeb const char *buf, size_t count)
816c92544dSBjoern A. Zeeb {
826c92544dSBjoern A. Zeeb struct mt7915_phy *phy = dev_get_drvdata(dev);
836c92544dSBjoern A. Zeeb int ret, i = to_sensor_dev_attr(attr)->index;
846c92544dSBjoern A. Zeeb long val;
856c92544dSBjoern A. Zeeb
866c92544dSBjoern A. Zeeb ret = kstrtol(buf, 10, &val);
876c92544dSBjoern A. Zeeb if (ret < 0)
886c92544dSBjoern A. Zeeb return ret;
896c92544dSBjoern A. Zeeb
906c92544dSBjoern A. Zeeb mutex_lock(&phy->dev->mt76.mutex);
91*8ba4d145SBjoern A. Zeeb val = DIV_ROUND_CLOSEST(clamp_val(val, 60 * 1000, 130 * 1000), 1000);
92cbb3ec25SBjoern A. Zeeb
93cbb3ec25SBjoern A. Zeeb if ((i - 1 == MT7915_CRIT_TEMP_IDX &&
94cbb3ec25SBjoern A. Zeeb val > phy->throttle_temp[MT7915_MAX_TEMP_IDX]) ||
95cbb3ec25SBjoern A. Zeeb (i - 1 == MT7915_MAX_TEMP_IDX &&
96cbb3ec25SBjoern A. Zeeb val < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) {
97cbb3ec25SBjoern A. Zeeb dev_err(phy->dev->mt76.dev,
98cbb3ec25SBjoern A. Zeeb "temp1_max shall be greater than temp1_crit.");
99cbb3ec25SBjoern A. Zeeb mutex_unlock(&phy->dev->mt76.mutex);
100cbb3ec25SBjoern A. Zeeb return -EINVAL;
101cbb3ec25SBjoern A. Zeeb }
102cbb3ec25SBjoern A. Zeeb
1036c92544dSBjoern A. Zeeb phy->throttle_temp[i - 1] = val;
104cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_thermal_protect(phy);
105*8ba4d145SBjoern A. Zeeb mutex_unlock(&phy->dev->mt76.mutex);
106cbb3ec25SBjoern A. Zeeb if (ret)
107cbb3ec25SBjoern A. Zeeb return ret;
108cbb3ec25SBjoern A. Zeeb
1096c92544dSBjoern A. Zeeb return count;
1106c92544dSBjoern A. Zeeb }
1116c92544dSBjoern A. Zeeb
1126c92544dSBjoern A. Zeeb static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7915_thermal_temp, 0);
1136c92544dSBjoern A. Zeeb static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7915_thermal_temp, 1);
1146c92544dSBjoern A. Zeeb static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7915_thermal_temp, 2);
1156c92544dSBjoern A. Zeeb static SENSOR_DEVICE_ATTR_RO(throttle1, mt7915_thermal_temp, 3);
1166c92544dSBjoern A. Zeeb
1176c92544dSBjoern A. Zeeb static struct attribute *mt7915_hwmon_attrs[] = {
1186c92544dSBjoern A. Zeeb &sensor_dev_attr_temp1_input.dev_attr.attr,
1196c92544dSBjoern A. Zeeb &sensor_dev_attr_temp1_crit.dev_attr.attr,
1206c92544dSBjoern A. Zeeb &sensor_dev_attr_temp1_max.dev_attr.attr,
1216c92544dSBjoern A. Zeeb &sensor_dev_attr_throttle1.dev_attr.attr,
1226c92544dSBjoern A. Zeeb NULL,
1236c92544dSBjoern A. Zeeb };
1246c92544dSBjoern A. Zeeb ATTRIBUTE_GROUPS(mt7915_hwmon);
1256c92544dSBjoern A. Zeeb
1266c92544dSBjoern A. Zeeb static int
mt7915_thermal_get_max_throttle_state(struct thermal_cooling_device * cdev,unsigned long * state)1276c92544dSBjoern A. Zeeb mt7915_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
1286c92544dSBjoern A. Zeeb unsigned long *state)
1296c92544dSBjoern A. Zeeb {
1306c92544dSBjoern A. Zeeb *state = MT7915_CDEV_THROTTLE_MAX;
1316c92544dSBjoern A. Zeeb
1326c92544dSBjoern A. Zeeb return 0;
1336c92544dSBjoern A. Zeeb }
1346c92544dSBjoern A. Zeeb
1356c92544dSBjoern A. Zeeb static int
mt7915_thermal_get_cur_throttle_state(struct thermal_cooling_device * cdev,unsigned long * state)1366c92544dSBjoern A. Zeeb mt7915_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
1376c92544dSBjoern A. Zeeb unsigned long *state)
1386c92544dSBjoern A. Zeeb {
1396c92544dSBjoern A. Zeeb struct mt7915_phy *phy = cdev->devdata;
1406c92544dSBjoern A. Zeeb
1416c92544dSBjoern A. Zeeb *state = phy->cdev_state;
1426c92544dSBjoern A. Zeeb
1436c92544dSBjoern A. Zeeb return 0;
1446c92544dSBjoern A. Zeeb }
1456c92544dSBjoern A. Zeeb
1466c92544dSBjoern A. Zeeb static int
mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device * cdev,unsigned long state)1476c92544dSBjoern A. Zeeb mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
1486c92544dSBjoern A. Zeeb unsigned long state)
1496c92544dSBjoern A. Zeeb {
1506c92544dSBjoern A. Zeeb struct mt7915_phy *phy = cdev->devdata;
1516c92544dSBjoern A. Zeeb u8 throttling = MT7915_THERMAL_THROTTLE_MAX - state;
1526c92544dSBjoern A. Zeeb int ret;
1536c92544dSBjoern A. Zeeb
154cbb3ec25SBjoern A. Zeeb if (state > MT7915_CDEV_THROTTLE_MAX) {
155cbb3ec25SBjoern A. Zeeb dev_err(phy->dev->mt76.dev,
156cbb3ec25SBjoern A. Zeeb "please specify a valid throttling state\n");
1576c92544dSBjoern A. Zeeb return -EINVAL;
158cbb3ec25SBjoern A. Zeeb }
1596c92544dSBjoern A. Zeeb
1606c92544dSBjoern A. Zeeb if (state == phy->cdev_state)
1616c92544dSBjoern A. Zeeb return 0;
1626c92544dSBjoern A. Zeeb
1636c92544dSBjoern A. Zeeb /*
1646c92544dSBjoern A. Zeeb * cooling_device convention: 0 = no cooling, more = more cooling
1656c92544dSBjoern A. Zeeb * mcu convention: 1 = max cooling, more = less cooling
1666c92544dSBjoern A. Zeeb */
167*8ba4d145SBjoern A. Zeeb mutex_lock(&phy->dev->mt76.mutex);
1686c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_thermal_throttling(phy, throttling);
169*8ba4d145SBjoern A. Zeeb mutex_unlock(&phy->dev->mt76.mutex);
1706c92544dSBjoern A. Zeeb if (ret)
1716c92544dSBjoern A. Zeeb return ret;
1726c92544dSBjoern A. Zeeb
1736c92544dSBjoern A. Zeeb phy->cdev_state = state;
1746c92544dSBjoern A. Zeeb
1756c92544dSBjoern A. Zeeb return 0;
1766c92544dSBjoern A. Zeeb }
1776c92544dSBjoern A. Zeeb
1786c92544dSBjoern A. Zeeb static const struct thermal_cooling_device_ops mt7915_thermal_ops = {
1796c92544dSBjoern A. Zeeb .get_max_state = mt7915_thermal_get_max_throttle_state,
1806c92544dSBjoern A. Zeeb .get_cur_state = mt7915_thermal_get_cur_throttle_state,
1816c92544dSBjoern A. Zeeb .set_cur_state = mt7915_thermal_set_cur_throttle_state,
1826c92544dSBjoern A. Zeeb };
1836c92544dSBjoern A. Zeeb
mt7915_unregister_thermal(struct mt7915_phy * phy)1846c92544dSBjoern A. Zeeb static void mt7915_unregister_thermal(struct mt7915_phy *phy)
1856c92544dSBjoern A. Zeeb {
1866c92544dSBjoern A. Zeeb struct wiphy *wiphy = phy->mt76->hw->wiphy;
1876c92544dSBjoern A. Zeeb
1886c92544dSBjoern A. Zeeb if (!phy->cdev)
1896c92544dSBjoern A. Zeeb return;
1906c92544dSBjoern A. Zeeb
1916c92544dSBjoern A. Zeeb sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
1926c92544dSBjoern A. Zeeb thermal_cooling_device_unregister(phy->cdev);
1936c92544dSBjoern A. Zeeb }
1946c92544dSBjoern A. Zeeb #endif
1956c92544dSBjoern A. Zeeb
mt7915_thermal_init(struct mt7915_phy * phy)1966c92544dSBjoern A. Zeeb static int mt7915_thermal_init(struct mt7915_phy *phy)
1976c92544dSBjoern A. Zeeb {
1986c92544dSBjoern A. Zeeb #if defined(__linux__)
1996c92544dSBjoern A. Zeeb struct wiphy *wiphy = phy->mt76->hw->wiphy;
2006c92544dSBjoern A. Zeeb struct thermal_cooling_device *cdev;
2016c92544dSBjoern A. Zeeb struct device *hwmon;
2026c92544dSBjoern A. Zeeb const char *name;
2036c92544dSBjoern A. Zeeb
2046c92544dSBjoern A. Zeeb name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7915_%s",
2056c92544dSBjoern A. Zeeb wiphy_name(wiphy));
206*8ba4d145SBjoern A. Zeeb if (!name)
207*8ba4d145SBjoern A. Zeeb return -ENOMEM;
2086c92544dSBjoern A. Zeeb
2096c92544dSBjoern A. Zeeb cdev = thermal_cooling_device_register(name, phy, &mt7915_thermal_ops);
2106c92544dSBjoern A. Zeeb if (!IS_ERR(cdev)) {
2116c92544dSBjoern A. Zeeb if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
2126c92544dSBjoern A. Zeeb "cooling_device") < 0)
2136c92544dSBjoern A. Zeeb thermal_cooling_device_unregister(cdev);
2146c92544dSBjoern A. Zeeb else
2156c92544dSBjoern A. Zeeb phy->cdev = cdev;
2166c92544dSBjoern A. Zeeb }
2176c92544dSBjoern A. Zeeb
218cbb3ec25SBjoern A. Zeeb /* initialize critical/maximum high temperature */
219cbb3ec25SBjoern A. Zeeb phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
220cbb3ec25SBjoern A. Zeeb phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
221cbb3ec25SBjoern A. Zeeb
2226c92544dSBjoern A. Zeeb if (!IS_REACHABLE(CONFIG_HWMON))
2236c92544dSBjoern A. Zeeb return 0;
2246c92544dSBjoern A. Zeeb
2256c92544dSBjoern A. Zeeb hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
2266c92544dSBjoern A. Zeeb mt7915_hwmon_groups);
227*8ba4d145SBjoern A. Zeeb return PTR_ERR_OR_ZERO(hwmon);
228*8ba4d145SBjoern A. Zeeb #elif defined(__FreeBSD__)
229cbb3ec25SBjoern A. Zeeb return 0;
230*8ba4d145SBjoern A. Zeeb #endif
2316c92544dSBjoern A. Zeeb }
2326c92544dSBjoern A. Zeeb
2336c92544dSBjoern A. Zeeb #if defined(CONFIG_MT76_LEDS)
mt7915_led_set_config(struct led_classdev * led_cdev,u8 delay_on,u8 delay_off)2346c92544dSBjoern A. Zeeb static void mt7915_led_set_config(struct led_classdev *led_cdev,
2356c92544dSBjoern A. Zeeb u8 delay_on, u8 delay_off)
2366c92544dSBjoern A. Zeeb {
2376c92544dSBjoern A. Zeeb struct mt7915_dev *dev;
238cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy;
2396c92544dSBjoern A. Zeeb u32 val;
2406c92544dSBjoern A. Zeeb
241cbb3ec25SBjoern A. Zeeb mphy = container_of(led_cdev, struct mt76_phy, leds.cdev);
242cbb3ec25SBjoern A. Zeeb dev = container_of(mphy->dev, struct mt7915_dev, mt76);
2436c92544dSBjoern A. Zeeb
244cbb3ec25SBjoern A. Zeeb /* set PWM mode */
245cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) |
246cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_LED_STATUS_OFF, delay_off) |
247cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_LED_STATUS_ON, delay_on);
248cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_LED_STATUS_0(mphy->band_idx), val);
249cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_LED_STATUS_1(mphy->band_idx), val);
2506c92544dSBjoern A. Zeeb
2516c92544dSBjoern A. Zeeb /* enable LED */
252cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_LED_EN(mphy->band_idx), 1);
2536c92544dSBjoern A. Zeeb
2546c92544dSBjoern A. Zeeb /* control LED */
255cbb3ec25SBjoern A. Zeeb val = MT_LED_CTRL_KICK;
256cbb3ec25SBjoern A. Zeeb if (dev->mphy.leds.al)
2576c92544dSBjoern A. Zeeb val |= MT_LED_CTRL_POLARITY;
258cbb3ec25SBjoern A. Zeeb if (mphy->band_idx)
259cbb3ec25SBjoern A. Zeeb val |= MT_LED_CTRL_BAND;
2606c92544dSBjoern A. Zeeb
261cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_LED_CTRL(mphy->band_idx), val);
262cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_LED_CTRL(mphy->band_idx), MT_LED_CTRL_KICK);
2636c92544dSBjoern A. Zeeb }
2646c92544dSBjoern A. Zeeb #endif
2656c92544dSBjoern A. Zeeb
mt7915_led_set_blink(struct led_classdev * led_cdev,unsigned long * delay_on,unsigned long * delay_off)2666c92544dSBjoern A. Zeeb static int mt7915_led_set_blink(struct led_classdev *led_cdev,
2676c92544dSBjoern A. Zeeb unsigned long *delay_on,
2686c92544dSBjoern A. Zeeb unsigned long *delay_off)
2696c92544dSBjoern A. Zeeb {
2706c92544dSBjoern A. Zeeb #if defined(CONFIG_MT76_LEDS)
2716c92544dSBjoern A. Zeeb u16 delta_on = 0, delta_off = 0;
2726c92544dSBjoern A. Zeeb
2736c92544dSBjoern A. Zeeb #define HW_TICK 10
2746c92544dSBjoern A. Zeeb #define TO_HW_TICK(_t) (((_t) > HW_TICK) ? ((_t) / HW_TICK) : HW_TICK)
2756c92544dSBjoern A. Zeeb
2766c92544dSBjoern A. Zeeb if (*delay_on)
2776c92544dSBjoern A. Zeeb delta_on = TO_HW_TICK(*delay_on);
2786c92544dSBjoern A. Zeeb if (*delay_off)
2796c92544dSBjoern A. Zeeb delta_off = TO_HW_TICK(*delay_off);
2806c92544dSBjoern A. Zeeb
2816c92544dSBjoern A. Zeeb mt7915_led_set_config(led_cdev, delta_on, delta_off);
2826c92544dSBjoern A. Zeeb #endif
2836c92544dSBjoern A. Zeeb
2846c92544dSBjoern A. Zeeb return 0;
2856c92544dSBjoern A. Zeeb }
2866c92544dSBjoern A. Zeeb
mt7915_led_set_brightness(struct led_classdev * led_cdev,enum led_brightness brightness)2876c92544dSBjoern A. Zeeb static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
2886c92544dSBjoern A. Zeeb enum led_brightness brightness)
2896c92544dSBjoern A. Zeeb {
2906c92544dSBjoern A. Zeeb #if defined(CONFIG_MT76_LEDS)
2916c92544dSBjoern A. Zeeb if (!brightness)
2926c92544dSBjoern A. Zeeb mt7915_led_set_config(led_cdev, 0, 0xff);
2936c92544dSBjoern A. Zeeb else
2946c92544dSBjoern A. Zeeb mt7915_led_set_config(led_cdev, 0xff, 0);
2956c92544dSBjoern A. Zeeb #endif
2966c92544dSBjoern A. Zeeb }
2976c92544dSBjoern A. Zeeb
__mt7915_init_txpower(struct mt7915_phy * phy,struct ieee80211_supported_band * sband)298*8ba4d145SBjoern A. Zeeb static void __mt7915_init_txpower(struct mt7915_phy *phy,
2996c92544dSBjoern A. Zeeb struct ieee80211_supported_band *sband)
3006c92544dSBjoern A. Zeeb {
301*8ba4d145SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
302*8ba4d145SBjoern A. Zeeb int i, n_chains = hweight16(phy->mt76->chainmask);
3036c92544dSBjoern A. Zeeb int nss_delta = mt76_tx_power_nss_delta(n_chains);
3046c92544dSBjoern A. Zeeb int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band);
3056c92544dSBjoern A. Zeeb struct mt76_power_limits limits;
3066c92544dSBjoern A. Zeeb
3076c92544dSBjoern A. Zeeb for (i = 0; i < sband->n_channels; i++) {
3086c92544dSBjoern A. Zeeb struct ieee80211_channel *chan = &sband->channels[i];
3096c92544dSBjoern A. Zeeb u32 target_power = 0;
3106c92544dSBjoern A. Zeeb int j;
3116c92544dSBjoern A. Zeeb
3126c92544dSBjoern A. Zeeb for (j = 0; j < n_chains; j++) {
3136c92544dSBjoern A. Zeeb u32 val;
3146c92544dSBjoern A. Zeeb
3156c92544dSBjoern A. Zeeb val = mt7915_eeprom_get_target_power(dev, chan, j);
3166c92544dSBjoern A. Zeeb target_power = max(target_power, val);
3176c92544dSBjoern A. Zeeb }
3186c92544dSBjoern A. Zeeb
3196c92544dSBjoern A. Zeeb target_power += pwr_delta;
320*8ba4d145SBjoern A. Zeeb target_power = mt76_get_rate_power_limits(phy->mt76, chan,
3216c92544dSBjoern A. Zeeb &limits,
3226c92544dSBjoern A. Zeeb target_power);
3236c92544dSBjoern A. Zeeb target_power += nss_delta;
3246c92544dSBjoern A. Zeeb target_power = DIV_ROUND_UP(target_power, 2);
3256c92544dSBjoern A. Zeeb chan->max_power = min_t(int, chan->max_reg_power,
3266c92544dSBjoern A. Zeeb target_power);
3276c92544dSBjoern A. Zeeb chan->orig_mpwr = target_power;
3286c92544dSBjoern A. Zeeb }
3296c92544dSBjoern A. Zeeb }
3306c92544dSBjoern A. Zeeb
mt7915_init_txpower(struct mt7915_phy * phy)331*8ba4d145SBjoern A. Zeeb void mt7915_init_txpower(struct mt7915_phy *phy)
332*8ba4d145SBjoern A. Zeeb {
333*8ba4d145SBjoern A. Zeeb if (!phy)
334*8ba4d145SBjoern A. Zeeb return;
335*8ba4d145SBjoern A. Zeeb
336*8ba4d145SBjoern A. Zeeb if (phy->mt76->cap.has_2ghz)
337*8ba4d145SBjoern A. Zeeb __mt7915_init_txpower(phy, &phy->mt76->sband_2g.sband);
338*8ba4d145SBjoern A. Zeeb if (phy->mt76->cap.has_5ghz)
339*8ba4d145SBjoern A. Zeeb __mt7915_init_txpower(phy, &phy->mt76->sband_5g.sband);
340*8ba4d145SBjoern A. Zeeb if (phy->mt76->cap.has_6ghz)
341*8ba4d145SBjoern A. Zeeb __mt7915_init_txpower(phy, &phy->mt76->sband_6g.sband);
342*8ba4d145SBjoern A. Zeeb }
343*8ba4d145SBjoern A. Zeeb
3446c92544dSBjoern A. Zeeb static void
mt7915_regd_notifier(struct wiphy * wiphy,struct regulatory_request * request)3456c92544dSBjoern A. Zeeb mt7915_regd_notifier(struct wiphy *wiphy,
3466c92544dSBjoern A. Zeeb struct regulatory_request *request)
3476c92544dSBjoern A. Zeeb {
3486c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
3496c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
3506c92544dSBjoern A. Zeeb struct mt76_phy *mphy = hw->priv;
3516c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mphy->priv;
3526c92544dSBjoern A. Zeeb
3536c92544dSBjoern A. Zeeb memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
3546c92544dSBjoern A. Zeeb dev->mt76.region = request->dfs_region;
3556c92544dSBjoern A. Zeeb
3566c92544dSBjoern A. Zeeb if (dev->mt76.region == NL80211_DFS_UNSET)
3576c92544dSBjoern A. Zeeb mt7915_mcu_rdd_background_enable(phy, NULL);
3586c92544dSBjoern A. Zeeb
359*8ba4d145SBjoern A. Zeeb mt7915_init_txpower(phy);
3606c92544dSBjoern A. Zeeb
3616c92544dSBjoern A. Zeeb mphy->dfs_state = MT_DFS_STATE_UNKNOWN;
3626c92544dSBjoern A. Zeeb mt7915_dfs_init_radar_detector(phy);
3636c92544dSBjoern A. Zeeb }
3646c92544dSBjoern A. Zeeb
3656c92544dSBjoern A. Zeeb static void
mt7915_init_wiphy(struct mt7915_phy * phy)366cbb3ec25SBjoern A. Zeeb mt7915_init_wiphy(struct mt7915_phy *phy)
3676c92544dSBjoern A. Zeeb {
368cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy = phy->mt76;
369cbb3ec25SBjoern A. Zeeb struct ieee80211_hw *hw = mphy->hw;
3706c92544dSBjoern A. Zeeb struct mt76_dev *mdev = &phy->dev->mt76;
3716c92544dSBjoern A. Zeeb struct wiphy *wiphy = hw->wiphy;
3726c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3736c92544dSBjoern A. Zeeb
3746c92544dSBjoern A. Zeeb hw->queues = 4;
3756c92544dSBjoern A. Zeeb hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
3766c92544dSBjoern A. Zeeb hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
3776c92544dSBjoern A. Zeeb hw->netdev_features = NETIF_F_RXCSUM;
3786c92544dSBjoern A. Zeeb
379*8ba4d145SBjoern A. Zeeb if (mtk_wed_device_active(&mdev->mmio.wed))
380*8ba4d145SBjoern A. Zeeb hw->netdev_features |= NETIF_F_HW_TC;
381*8ba4d145SBjoern A. Zeeb
3826c92544dSBjoern A. Zeeb hw->radiotap_timestamp.units_pos =
3836c92544dSBjoern A. Zeeb IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
3846c92544dSBjoern A. Zeeb
3856c92544dSBjoern A. Zeeb phy->slottime = 9;
3866c92544dSBjoern A. Zeeb
3876c92544dSBjoern A. Zeeb hw->sta_data_size = sizeof(struct mt7915_sta);
3886c92544dSBjoern A. Zeeb hw->vif_data_size = sizeof(struct mt7915_vif);
3896c92544dSBjoern A. Zeeb
3906c92544dSBjoern A. Zeeb wiphy->iface_combinations = if_comb;
3916c92544dSBjoern A. Zeeb wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
3926c92544dSBjoern A. Zeeb wiphy->reg_notifier = mt7915_regd_notifier;
3936c92544dSBjoern A. Zeeb wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
3946c92544dSBjoern A. Zeeb wiphy->mbssid_max_interfaces = 16;
3956c92544dSBjoern A. Zeeb
3966c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
3976c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
3986c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
3996c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
4006c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
4016c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
4026c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
4036c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
404cbb3ec25SBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
405cbb3ec25SBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
406cbb3ec25SBjoern A. Zeeb
407cbb3ec25SBjoern A. Zeeb if (!is_mt7915(&dev->mt76))
408cbb3ec25SBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
4096c92544dSBjoern A. Zeeb
4106c92544dSBjoern A. Zeeb #if defined(CONFIG_OF)
4116c92544dSBjoern A. Zeeb if (!mdev->dev->of_node ||
4126c92544dSBjoern A. Zeeb !of_property_read_bool(mdev->dev->of_node,
4136c92544dSBjoern A. Zeeb "mediatek,disable-radar-background"))
4146c92544dSBjoern A. Zeeb #endif
4156c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy,
4166c92544dSBjoern A. Zeeb NL80211_EXT_FEATURE_RADAR_BACKGROUND);
4176c92544dSBjoern A. Zeeb
4186c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, HAS_RATE_CONTROL);
4196c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
4206c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
4216c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
4226c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, WANT_MONITOR_VIF);
423*8ba4d145SBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_TX_FRAG);
4246c92544dSBjoern A. Zeeb
4256c92544dSBjoern A. Zeeb hw->max_tx_fragments = 4;
4266c92544dSBjoern A. Zeeb
4276c92544dSBjoern A. Zeeb if (phy->mt76->cap.has_2ghz) {
4286c92544dSBjoern A. Zeeb phy->mt76->sband_2g.sband.ht_cap.cap |=
4296c92544dSBjoern A. Zeeb IEEE80211_HT_CAP_LDPC_CODING |
4306c92544dSBjoern A. Zeeb IEEE80211_HT_CAP_MAX_AMSDU;
431*8ba4d145SBjoern A. Zeeb if (is_mt7915(&dev->mt76))
4326c92544dSBjoern A. Zeeb phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
4336c92544dSBjoern A. Zeeb IEEE80211_HT_MPDU_DENSITY_4;
434*8ba4d145SBjoern A. Zeeb else
435*8ba4d145SBjoern A. Zeeb phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
436*8ba4d145SBjoern A. Zeeb IEEE80211_HT_MPDU_DENSITY_2;
4376c92544dSBjoern A. Zeeb }
4386c92544dSBjoern A. Zeeb
4396c92544dSBjoern A. Zeeb if (phy->mt76->cap.has_5ghz) {
440cbb3ec25SBjoern A. Zeeb struct ieee80211_sta_vht_cap *vht_cap;
441cbb3ec25SBjoern A. Zeeb
442cbb3ec25SBjoern A. Zeeb vht_cap = &phy->mt76->sband_5g.sband.vht_cap;
4436c92544dSBjoern A. Zeeb phy->mt76->sband_5g.sband.ht_cap.cap |=
4446c92544dSBjoern A. Zeeb IEEE80211_HT_CAP_LDPC_CODING |
4456c92544dSBjoern A. Zeeb IEEE80211_HT_CAP_MAX_AMSDU;
446*8ba4d145SBjoern A. Zeeb
447*8ba4d145SBjoern A. Zeeb if (is_mt7915(&dev->mt76)) {
4486c92544dSBjoern A. Zeeb phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
4496c92544dSBjoern A. Zeeb IEEE80211_HT_MPDU_DENSITY_4;
4506c92544dSBjoern A. Zeeb
451cbb3ec25SBjoern A. Zeeb vht_cap->cap |=
4526c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
4536c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
4546c92544dSBjoern A. Zeeb
4556c92544dSBjoern A. Zeeb if (!dev->dbdc_support)
456cbb3ec25SBjoern A. Zeeb vht_cap->cap |=
4576c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_SHORT_GI_160 |
458cbb3ec25SBjoern A. Zeeb FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
4596c92544dSBjoern A. Zeeb } else {
460*8ba4d145SBjoern A. Zeeb phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
461*8ba4d145SBjoern A. Zeeb IEEE80211_HT_MPDU_DENSITY_2;
462*8ba4d145SBjoern A. Zeeb
463cbb3ec25SBjoern A. Zeeb vht_cap->cap |=
4646c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
4656c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
4666c92544dSBjoern A. Zeeb
4676c92544dSBjoern A. Zeeb /* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */
468cbb3ec25SBjoern A. Zeeb vht_cap->cap |=
4696c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_SHORT_GI_160 |
4706c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
4716c92544dSBjoern A. Zeeb }
472cbb3ec25SBjoern A. Zeeb
473cbb3ec25SBjoern A. Zeeb if (!is_mt7915(&dev->mt76) || !dev->dbdc_support)
474cbb3ec25SBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
4756c92544dSBjoern A. Zeeb }
4766c92544dSBjoern A. Zeeb
4776c92544dSBjoern A. Zeeb mt76_set_stream_caps(phy->mt76, true);
4786c92544dSBjoern A. Zeeb mt7915_set_stream_vht_txbf_caps(phy);
4796c92544dSBjoern A. Zeeb mt7915_set_stream_he_caps(phy);
480*8ba4d145SBjoern A. Zeeb mt7915_init_txpower(phy);
4816c92544dSBjoern A. Zeeb
4826c92544dSBjoern A. Zeeb wiphy->available_antennas_rx = phy->mt76->antenna_mask;
4836c92544dSBjoern A. Zeeb wiphy->available_antennas_tx = phy->mt76->antenna_mask;
484cbb3ec25SBjoern A. Zeeb
485cbb3ec25SBjoern A. Zeeb /* init led callbacks */
486cbb3ec25SBjoern A. Zeeb if (IS_ENABLED(CONFIG_MT76_LEDS)) {
487cbb3ec25SBjoern A. Zeeb mphy->leds.cdev.brightness_set = mt7915_led_set_brightness;
488cbb3ec25SBjoern A. Zeeb mphy->leds.cdev.blink_set = mt7915_led_set_blink;
489cbb3ec25SBjoern A. Zeeb }
4906c92544dSBjoern A. Zeeb }
4916c92544dSBjoern A. Zeeb
4926c92544dSBjoern A. Zeeb static void
mt7915_mac_init_band(struct mt7915_dev * dev,u8 band)4936c92544dSBjoern A. Zeeb mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
4946c92544dSBjoern A. Zeeb {
4956c92544dSBjoern A. Zeeb u32 mask, set;
4966c92544dSBjoern A. Zeeb
4976c92544dSBjoern A. Zeeb mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
4986c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
4996c92544dSBjoern A. Zeeb mt76_set(dev, MT_TMAC_CTCR0(band),
5006c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
5016c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_EN);
5026c92544dSBjoern A. Zeeb
5036c92544dSBjoern A. Zeeb mask = MT_MDP_RCFR0_MCU_RX_MGMT |
5046c92544dSBjoern A. Zeeb MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR |
5056c92544dSBjoern A. Zeeb MT_MDP_RCFR0_MCU_RX_CTL_BAR;
5066c92544dSBjoern A. Zeeb set = FIELD_PREP(MT_MDP_RCFR0_MCU_RX_MGMT, MT_MDP_TO_HIF) |
5076c92544dSBjoern A. Zeeb FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR, MT_MDP_TO_HIF) |
5086c92544dSBjoern A. Zeeb FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_BAR, MT_MDP_TO_HIF);
5096c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_MDP_BNRCFR0(band), mask, set);
5106c92544dSBjoern A. Zeeb
5116c92544dSBjoern A. Zeeb mask = MT_MDP_RCFR1_MCU_RX_BYPASS |
5126c92544dSBjoern A. Zeeb MT_MDP_RCFR1_RX_DROPPED_UCAST |
5136c92544dSBjoern A. Zeeb MT_MDP_RCFR1_RX_DROPPED_MCAST;
5146c92544dSBjoern A. Zeeb set = FIELD_PREP(MT_MDP_RCFR1_MCU_RX_BYPASS, MT_MDP_TO_HIF) |
5156c92544dSBjoern A. Zeeb FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_UCAST, MT_MDP_TO_HIF) |
5166c92544dSBjoern A. Zeeb FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);
5176c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);
5186c92544dSBjoern A. Zeeb
5196c92544dSBjoern A. Zeeb mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 0x680);
5206c92544dSBjoern A. Zeeb
5216c92544dSBjoern A. Zeeb /* mt7915: disable rx rate report by default due to hw issues */
5226c92544dSBjoern A. Zeeb mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
523cbb3ec25SBjoern A. Zeeb
524cbb3ec25SBjoern A. Zeeb /* clear estimated value of EIFS for Rx duration & OBSS time */
525cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_RMAC_RSVD0(band), MT_WF_RMAC_RSVD0_EIFS_CLR);
526cbb3ec25SBjoern A. Zeeb
527cbb3ec25SBjoern A. Zeeb /* clear backoff time for Rx duration */
528cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME1(band),
529cbb3ec25SBjoern A. Zeeb MT_WF_RMAC_MIB_NONQOSD_BACKOFF);
530cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME3(band),
531cbb3ec25SBjoern A. Zeeb MT_WF_RMAC_MIB_QOS01_BACKOFF);
532cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_WF_RMAC_MIB_AIRTIME4(band),
533cbb3ec25SBjoern A. Zeeb MT_WF_RMAC_MIB_QOS23_BACKOFF);
534cbb3ec25SBjoern A. Zeeb
535*8ba4d145SBjoern A. Zeeb /* clear backoff time for Tx duration */
536*8ba4d145SBjoern A. Zeeb mt76_clear(dev, MT_WTBLOFF_TOP_ACR(band),
537*8ba4d145SBjoern A. Zeeb MT_WTBLOFF_TOP_ADM_BACKOFFTIME);
538*8ba4d145SBjoern A. Zeeb
539*8ba4d145SBjoern A. Zeeb /* exclude estimated backoff time for Tx duration on MT7915 */
540*8ba4d145SBjoern A. Zeeb if (is_mt7915(&dev->mt76))
541*8ba4d145SBjoern A. Zeeb mt76_set(dev, MT_AGG_ATCR0(band),
542*8ba4d145SBjoern A. Zeeb MT_AGG_ATCR_MAC_BFF_TIME_EN);
543*8ba4d145SBjoern A. Zeeb
544cbb3ec25SBjoern A. Zeeb /* clear backoff time and set software compensation for OBSS time */
545cbb3ec25SBjoern A. Zeeb mask = MT_WF_RMAC_MIB_OBSS_BACKOFF | MT_WF_RMAC_MIB_ED_OFFSET;
546cbb3ec25SBjoern A. Zeeb set = FIELD_PREP(MT_WF_RMAC_MIB_OBSS_BACKOFF, 0) |
547cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_WF_RMAC_MIB_ED_OFFSET, 4);
548cbb3ec25SBjoern A. Zeeb mt76_rmw(dev, MT_WF_RMAC_MIB_AIRTIME0(band), mask, set);
549cbb3ec25SBjoern A. Zeeb
550cbb3ec25SBjoern A. Zeeb /* filter out non-resp frames and get instanstaeous signal reporting */
551cbb3ec25SBjoern A. Zeeb mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;
552cbb3ec25SBjoern A. Zeeb set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
553cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
554cbb3ec25SBjoern A. Zeeb mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
555cbb3ec25SBjoern A. Zeeb
556cbb3ec25SBjoern A. Zeeb /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than
557cbb3ec25SBjoern A. Zeeb * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.
558cbb3ec25SBjoern A. Zeeb */
559cbb3ec25SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed))
560cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);
5616c92544dSBjoern A. Zeeb }
5626c92544dSBjoern A. Zeeb
563cbb3ec25SBjoern A. Zeeb static void
mt7915_init_led_mux(struct mt7915_dev * dev)564cbb3ec25SBjoern A. Zeeb mt7915_init_led_mux(struct mt7915_dev *dev)
565cbb3ec25SBjoern A. Zeeb {
566cbb3ec25SBjoern A. Zeeb if (!IS_ENABLED(CONFIG_MT76_LEDS))
567cbb3ec25SBjoern A. Zeeb return;
568cbb3ec25SBjoern A. Zeeb
569cbb3ec25SBjoern A. Zeeb if (dev->dbdc_support) {
570cbb3ec25SBjoern A. Zeeb switch (mt76_chip(&dev->mt76)) {
571cbb3ec25SBjoern A. Zeeb case 0x7915:
572cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX2,
573cbb3ec25SBjoern A. Zeeb GENMASK(11, 8), 4);
574cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX3,
575cbb3ec25SBjoern A. Zeeb GENMASK(11, 8), 4);
576cbb3ec25SBjoern A. Zeeb break;
577cbb3ec25SBjoern A. Zeeb case 0x7986:
578cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX0,
579cbb3ec25SBjoern A. Zeeb GENMASK(7, 4), 1);
580cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX0,
581cbb3ec25SBjoern A. Zeeb GENMASK(11, 8), 1);
582cbb3ec25SBjoern A. Zeeb break;
583cbb3ec25SBjoern A. Zeeb case 0x7916:
584cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX1,
585cbb3ec25SBjoern A. Zeeb GENMASK(27, 24), 3);
586cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX1,
587cbb3ec25SBjoern A. Zeeb GENMASK(31, 28), 3);
588cbb3ec25SBjoern A. Zeeb break;
589cbb3ec25SBjoern A. Zeeb default:
590cbb3ec25SBjoern A. Zeeb break;
591cbb3ec25SBjoern A. Zeeb }
592cbb3ec25SBjoern A. Zeeb } else if (dev->mphy.leds.pin) {
593cbb3ec25SBjoern A. Zeeb switch (mt76_chip(&dev->mt76)) {
594cbb3ec25SBjoern A. Zeeb case 0x7915:
595cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX3,
596cbb3ec25SBjoern A. Zeeb GENMASK(11, 8), 4);
597cbb3ec25SBjoern A. Zeeb break;
598cbb3ec25SBjoern A. Zeeb case 0x7986:
599cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX0,
600cbb3ec25SBjoern A. Zeeb GENMASK(11, 8), 1);
601cbb3ec25SBjoern A. Zeeb break;
602cbb3ec25SBjoern A. Zeeb case 0x7916:
603cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX1,
604cbb3ec25SBjoern A. Zeeb GENMASK(31, 28), 3);
605cbb3ec25SBjoern A. Zeeb break;
606cbb3ec25SBjoern A. Zeeb default:
607cbb3ec25SBjoern A. Zeeb break;
608cbb3ec25SBjoern A. Zeeb }
609cbb3ec25SBjoern A. Zeeb } else {
610cbb3ec25SBjoern A. Zeeb switch (mt76_chip(&dev->mt76)) {
611cbb3ec25SBjoern A. Zeeb case 0x7915:
612cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX2,
613cbb3ec25SBjoern A. Zeeb GENMASK(11, 8), 4);
614cbb3ec25SBjoern A. Zeeb break;
615cbb3ec25SBjoern A. Zeeb case 0x7986:
616cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX0,
617cbb3ec25SBjoern A. Zeeb GENMASK(7, 4), 1);
618cbb3ec25SBjoern A. Zeeb break;
619cbb3ec25SBjoern A. Zeeb case 0x7916:
620cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_LED_GPIO_MUX1,
621cbb3ec25SBjoern A. Zeeb GENMASK(27, 24), 3);
622cbb3ec25SBjoern A. Zeeb break;
623cbb3ec25SBjoern A. Zeeb default:
624cbb3ec25SBjoern A. Zeeb break;
625cbb3ec25SBjoern A. Zeeb }
626cbb3ec25SBjoern A. Zeeb }
627cbb3ec25SBjoern A. Zeeb }
628cbb3ec25SBjoern A. Zeeb
mt7915_mac_init(struct mt7915_dev * dev)629cbb3ec25SBjoern A. Zeeb void mt7915_mac_init(struct mt7915_dev *dev)
6306c92544dSBjoern A. Zeeb {
6316c92544dSBjoern A. Zeeb int i;
6326c92544dSBjoern A. Zeeb u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;
6336c92544dSBjoern A. Zeeb
6346c92544dSBjoern A. Zeeb /* config pse qid6 wfdma port selection */
6356c92544dSBjoern A. Zeeb if (!is_mt7915(&dev->mt76) && dev->hif2)
6366c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_WF_PP_TOP_RXQ_WFDMA_CF_5, 0,
6376c92544dSBjoern A. Zeeb MT_WF_PP_TOP_RXQ_QID6_WFDMA_HIF_SEL_MASK);
6386c92544dSBjoern A. Zeeb
6396c92544dSBjoern A. Zeeb mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, rx_len);
6406c92544dSBjoern A. Zeeb
6416c92544dSBjoern A. Zeeb if (!is_mt7915(&dev->mt76))
6426c92544dSBjoern A. Zeeb mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
643cbb3ec25SBjoern A. Zeeb else
644cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_PLE_HOST_RPT0, MT_PLE_HOST_RPT0_TX_LATENCY);
6456c92544dSBjoern A. Zeeb
6466c92544dSBjoern A. Zeeb /* enable hardware de-agg */
6476c92544dSBjoern A. Zeeb mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
6486c92544dSBjoern A. Zeeb
6496c92544dSBjoern A. Zeeb for (i = 0; i < mt7915_wtbl_size(dev); i++)
6506c92544dSBjoern A. Zeeb mt7915_mac_wtbl_update(dev, i,
6516c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
6526c92544dSBjoern A. Zeeb for (i = 0; i < 2; i++)
6536c92544dSBjoern A. Zeeb mt7915_mac_init_band(dev, i);
6546c92544dSBjoern A. Zeeb
655cbb3ec25SBjoern A. Zeeb mt7915_init_led_mux(dev);
6566c92544dSBjoern A. Zeeb }
6576c92544dSBjoern A. Zeeb
mt7915_txbf_init(struct mt7915_dev * dev)658cbb3ec25SBjoern A. Zeeb int mt7915_txbf_init(struct mt7915_dev *dev)
6596c92544dSBjoern A. Zeeb {
6606c92544dSBjoern A. Zeeb int ret;
6616c92544dSBjoern A. Zeeb
6626c92544dSBjoern A. Zeeb if (dev->dbdc_support) {
6636c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_txbf(dev, MT_BF_MODULE_UPDATE);
6646c92544dSBjoern A. Zeeb if (ret)
6656c92544dSBjoern A. Zeeb return ret;
6666c92544dSBjoern A. Zeeb }
6676c92544dSBjoern A. Zeeb
6686c92544dSBjoern A. Zeeb /* trigger sounding packets */
6696c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_txbf(dev, MT_BF_SOUNDING_ON);
6706c92544dSBjoern A. Zeeb if (ret)
6716c92544dSBjoern A. Zeeb return ret;
6726c92544dSBjoern A. Zeeb
6736c92544dSBjoern A. Zeeb /* enable eBF */
6746c92544dSBjoern A. Zeeb return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);
6756c92544dSBjoern A. Zeeb }
6766c92544dSBjoern A. Zeeb
6776c92544dSBjoern A. Zeeb static struct mt7915_phy *
mt7915_alloc_ext_phy(struct mt7915_dev * dev)6786c92544dSBjoern A. Zeeb mt7915_alloc_ext_phy(struct mt7915_dev *dev)
6796c92544dSBjoern A. Zeeb {
6806c92544dSBjoern A. Zeeb struct mt7915_phy *phy;
6816c92544dSBjoern A. Zeeb struct mt76_phy *mphy;
6826c92544dSBjoern A. Zeeb
6836c92544dSBjoern A. Zeeb if (!dev->dbdc_support)
6846c92544dSBjoern A. Zeeb return NULL;
6856c92544dSBjoern A. Zeeb
6866c92544dSBjoern A. Zeeb mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops, MT_BAND1);
6876c92544dSBjoern A. Zeeb if (!mphy)
6886c92544dSBjoern A. Zeeb return ERR_PTR(-ENOMEM);
6896c92544dSBjoern A. Zeeb
6906c92544dSBjoern A. Zeeb phy = mphy->priv;
6916c92544dSBjoern A. Zeeb phy->dev = dev;
6926c92544dSBjoern A. Zeeb phy->mt76 = mphy;
6936c92544dSBjoern A. Zeeb
6946c92544dSBjoern A. Zeeb /* Bind main phy to band0 and ext_phy to band1 for dbdc case */
695cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx = 1;
6966c92544dSBjoern A. Zeeb
6976c92544dSBjoern A. Zeeb return phy;
6986c92544dSBjoern A. Zeeb }
6996c92544dSBjoern A. Zeeb
7006c92544dSBjoern A. Zeeb static int
mt7915_register_ext_phy(struct mt7915_dev * dev,struct mt7915_phy * phy)7016c92544dSBjoern A. Zeeb mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)
7026c92544dSBjoern A. Zeeb {
7036c92544dSBjoern A. Zeeb struct mt76_phy *mphy = phy->mt76;
7046c92544dSBjoern A. Zeeb int ret;
7056c92544dSBjoern A. Zeeb
7066c92544dSBjoern A. Zeeb INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);
7076c92544dSBjoern A. Zeeb
7086c92544dSBjoern A. Zeeb mt7915_eeprom_parse_hw_cap(dev, phy);
7096c92544dSBjoern A. Zeeb
7106c92544dSBjoern A. Zeeb #if defined(__linux__)
7116c92544dSBjoern A. Zeeb memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR2,
7126c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__)
7136c92544dSBjoern A. Zeeb memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR2,
7146c92544dSBjoern A. Zeeb #endif
7156c92544dSBjoern A. Zeeb ETH_ALEN);
7166c92544dSBjoern A. Zeeb /* Make the secondary PHY MAC address local without overlapping with
7176c92544dSBjoern A. Zeeb * the usual MAC address allocation scheme on multiple virtual interfaces
7186c92544dSBjoern A. Zeeb */
7196c92544dSBjoern A. Zeeb if (!is_valid_ether_addr(mphy->macaddr)) {
7206c92544dSBjoern A. Zeeb #if defined(__linux__)
7216c92544dSBjoern A. Zeeb memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
7226c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__)
7236c92544dSBjoern A. Zeeb memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
7246c92544dSBjoern A. Zeeb #endif
7256c92544dSBjoern A. Zeeb ETH_ALEN);
7266c92544dSBjoern A. Zeeb mphy->macaddr[0] |= 2;
7276c92544dSBjoern A. Zeeb mphy->macaddr[0] ^= BIT(7);
7286c92544dSBjoern A. Zeeb }
7296c92544dSBjoern A. Zeeb mt76_eeprom_override(mphy);
7306c92544dSBjoern A. Zeeb
7316c92544dSBjoern A. Zeeb /* init wiphy according to mphy and phy */
732cbb3ec25SBjoern A. Zeeb mt7915_init_wiphy(phy);
7336c92544dSBjoern A. Zeeb
7346c92544dSBjoern A. Zeeb ret = mt76_register_phy(mphy, true, mt76_rates,
7356c92544dSBjoern A. Zeeb ARRAY_SIZE(mt76_rates));
7366c92544dSBjoern A. Zeeb if (ret)
7376c92544dSBjoern A. Zeeb return ret;
7386c92544dSBjoern A. Zeeb
7396c92544dSBjoern A. Zeeb ret = mt7915_thermal_init(phy);
7406c92544dSBjoern A. Zeeb if (ret)
7416c92544dSBjoern A. Zeeb goto unreg;
7426c92544dSBjoern A. Zeeb
7436c92544dSBjoern A. Zeeb #if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS)
7446c92544dSBjoern A. Zeeb mt7915_init_debugfs(phy);
7456c92544dSBjoern A. Zeeb #endif
7466c92544dSBjoern A. Zeeb
7476c92544dSBjoern A. Zeeb return 0;
7486c92544dSBjoern A. Zeeb
7496c92544dSBjoern A. Zeeb unreg:
7506c92544dSBjoern A. Zeeb mt76_unregister_phy(mphy);
7516c92544dSBjoern A. Zeeb return ret;
7526c92544dSBjoern A. Zeeb }
7536c92544dSBjoern A. Zeeb
mt7915_init_work(struct work_struct * work)7546c92544dSBjoern A. Zeeb static void mt7915_init_work(struct work_struct *work)
7556c92544dSBjoern A. Zeeb {
7566c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(work, struct mt7915_dev,
7576c92544dSBjoern A. Zeeb init_work);
7586c92544dSBjoern A. Zeeb
7596c92544dSBjoern A. Zeeb mt7915_mcu_set_eeprom(dev);
7606c92544dSBjoern A. Zeeb mt7915_mac_init(dev);
7616c92544dSBjoern A. Zeeb mt7915_txbf_init(dev);
7626c92544dSBjoern A. Zeeb }
7636c92544dSBjoern A. Zeeb
mt7915_wfsys_reset(struct mt7915_dev * dev)7646c92544dSBjoern A. Zeeb void mt7915_wfsys_reset(struct mt7915_dev *dev)
7656c92544dSBjoern A. Zeeb {
7666c92544dSBjoern A. Zeeb #define MT_MCU_DUMMY_RANDOM GENMASK(15, 0)
7676c92544dSBjoern A. Zeeb #define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16)
7686c92544dSBjoern A. Zeeb
7696c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76)) {
7706c92544dSBjoern A. Zeeb u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON;
7716c92544dSBjoern A. Zeeb
7726c92544dSBjoern A. Zeeb mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM);
7736c92544dSBjoern A. Zeeb
7746c92544dSBjoern A. Zeeb /* change to software control */
7756c92544dSBjoern A. Zeeb val |= MT_TOP_PWR_SW_RST;
7766c92544dSBjoern A. Zeeb mt76_wr(dev, MT_TOP_PWR_CTRL, val);
7776c92544dSBjoern A. Zeeb
7786c92544dSBjoern A. Zeeb /* reset wfsys */
7796c92544dSBjoern A. Zeeb val &= ~MT_TOP_PWR_SW_RST;
7806c92544dSBjoern A. Zeeb mt76_wr(dev, MT_TOP_PWR_CTRL, val);
7816c92544dSBjoern A. Zeeb
7826c92544dSBjoern A. Zeeb /* release wfsys then mcu re-executes romcode */
7836c92544dSBjoern A. Zeeb val |= MT_TOP_PWR_SW_RST;
7846c92544dSBjoern A. Zeeb mt76_wr(dev, MT_TOP_PWR_CTRL, val);
7856c92544dSBjoern A. Zeeb
7866c92544dSBjoern A. Zeeb /* switch to hw control */
7876c92544dSBjoern A. Zeeb val &= ~MT_TOP_PWR_SW_RST;
7886c92544dSBjoern A. Zeeb val |= MT_TOP_PWR_HW_CTRL;
7896c92544dSBjoern A. Zeeb mt76_wr(dev, MT_TOP_PWR_CTRL, val);
7906c92544dSBjoern A. Zeeb
7916c92544dSBjoern A. Zeeb /* check whether mcu resets to default */
7926c92544dSBjoern A. Zeeb if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR,
7936c92544dSBjoern A. Zeeb MT_MCU_DUMMY_DEFAULT, MT_MCU_DUMMY_DEFAULT,
7946c92544dSBjoern A. Zeeb 1000)) {
7956c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "wifi subsystem reset failure\n");
7966c92544dSBjoern A. Zeeb return;
7976c92544dSBjoern A. Zeeb }
7986c92544dSBjoern A. Zeeb
7996c92544dSBjoern A. Zeeb /* wfsys reset won't clear host registers */
8006c92544dSBjoern A. Zeeb mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);
8016c92544dSBjoern A. Zeeb
8026c92544dSBjoern A. Zeeb msleep(100);
803cbb3ec25SBjoern A. Zeeb } else if (is_mt798x(&dev->mt76)) {
8046c92544dSBjoern A. Zeeb mt7986_wmac_disable(dev);
8056c92544dSBjoern A. Zeeb msleep(20);
8066c92544dSBjoern A. Zeeb
8076c92544dSBjoern A. Zeeb mt7986_wmac_enable(dev);
8086c92544dSBjoern A. Zeeb msleep(20);
8096c92544dSBjoern A. Zeeb } else {
8106c92544dSBjoern A. Zeeb mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
8116c92544dSBjoern A. Zeeb msleep(20);
8126c92544dSBjoern A. Zeeb
8136c92544dSBjoern A. Zeeb mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);
8146c92544dSBjoern A. Zeeb msleep(20);
8156c92544dSBjoern A. Zeeb }
8166c92544dSBjoern A. Zeeb }
8176c92544dSBjoern A. Zeeb
mt7915_band_config(struct mt7915_dev * dev)8186c92544dSBjoern A. Zeeb static bool mt7915_band_config(struct mt7915_dev *dev)
8196c92544dSBjoern A. Zeeb {
8206c92544dSBjoern A. Zeeb bool ret = true;
8216c92544dSBjoern A. Zeeb
822cbb3ec25SBjoern A. Zeeb dev->phy.mt76->band_idx = 0;
8236c92544dSBjoern A. Zeeb
824cbb3ec25SBjoern A. Zeeb if (is_mt798x(&dev->mt76)) {
8256c92544dSBjoern A. Zeeb u32 sku = mt7915_check_adie(dev, true);
8266c92544dSBjoern A. Zeeb
8276c92544dSBjoern A. Zeeb /*
8286c92544dSBjoern A. Zeeb * for mt7986, dbdc support is determined by the number
8296c92544dSBjoern A. Zeeb * of adie chips and the main phy is bound to band1 when
8306c92544dSBjoern A. Zeeb * dbdc is disabled.
8316c92544dSBjoern A. Zeeb */
8326c92544dSBjoern A. Zeeb if (sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE) {
833cbb3ec25SBjoern A. Zeeb dev->phy.mt76->band_idx = 1;
8346c92544dSBjoern A. Zeeb ret = false;
8356c92544dSBjoern A. Zeeb }
8366c92544dSBjoern A. Zeeb } else {
8376c92544dSBjoern A. Zeeb ret = is_mt7915(&dev->mt76) ?
8386c92544dSBjoern A. Zeeb !!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)) : true;
8396c92544dSBjoern A. Zeeb }
8406c92544dSBjoern A. Zeeb
8416c92544dSBjoern A. Zeeb return ret;
8426c92544dSBjoern A. Zeeb }
8436c92544dSBjoern A. Zeeb
8446c92544dSBjoern A. Zeeb static int
mt7915_init_hardware(struct mt7915_dev * dev,struct mt7915_phy * phy2)8456c92544dSBjoern A. Zeeb mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)
8466c92544dSBjoern A. Zeeb {
8476c92544dSBjoern A. Zeeb int ret, idx;
8486c92544dSBjoern A. Zeeb
8496c92544dSBjoern A. Zeeb mt76_wr(dev, MT_INT_MASK_CSR, 0);
8506c92544dSBjoern A. Zeeb mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
8516c92544dSBjoern A. Zeeb
8526c92544dSBjoern A. Zeeb INIT_WORK(&dev->init_work, mt7915_init_work);
8536c92544dSBjoern A. Zeeb
8546c92544dSBjoern A. Zeeb ret = mt7915_dma_init(dev, phy2);
8556c92544dSBjoern A. Zeeb if (ret)
8566c92544dSBjoern A. Zeeb return ret;
8576c92544dSBjoern A. Zeeb
8586c92544dSBjoern A. Zeeb set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
8596c92544dSBjoern A. Zeeb
8606c92544dSBjoern A. Zeeb ret = mt7915_mcu_init(dev);
8616c92544dSBjoern A. Zeeb if (ret)
8626c92544dSBjoern A. Zeeb return ret;
8636c92544dSBjoern A. Zeeb
8646c92544dSBjoern A. Zeeb ret = mt7915_eeprom_init(dev);
8656c92544dSBjoern A. Zeeb if (ret < 0)
8666c92544dSBjoern A. Zeeb return ret;
8676c92544dSBjoern A. Zeeb
868*8ba4d145SBjoern A. Zeeb if (dev->cal) {
8696c92544dSBjoern A. Zeeb ret = mt7915_mcu_apply_group_cal(dev);
8706c92544dSBjoern A. Zeeb if (ret)
8716c92544dSBjoern A. Zeeb return ret;
8726c92544dSBjoern A. Zeeb }
8736c92544dSBjoern A. Zeeb
8746c92544dSBjoern A. Zeeb /* Beacon and mgmt frames should occupy wcid 0 */
8756c92544dSBjoern A. Zeeb idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
8766c92544dSBjoern A. Zeeb if (idx)
8776c92544dSBjoern A. Zeeb return -ENOSPC;
8786c92544dSBjoern A. Zeeb
8796c92544dSBjoern A. Zeeb dev->mt76.global_wcid.idx = idx;
8806c92544dSBjoern A. Zeeb dev->mt76.global_wcid.hw_key_idx = -1;
8816c92544dSBjoern A. Zeeb dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;
8826c92544dSBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
8836c92544dSBjoern A. Zeeb
8846c92544dSBjoern A. Zeeb return 0;
8856c92544dSBjoern A. Zeeb }
8866c92544dSBjoern A. Zeeb
mt7915_set_stream_vht_txbf_caps(struct mt7915_phy * phy)8876c92544dSBjoern A. Zeeb void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)
8886c92544dSBjoern A. Zeeb {
889cbb3ec25SBjoern A. Zeeb int sts;
8906c92544dSBjoern A. Zeeb u32 *cap;
8916c92544dSBjoern A. Zeeb
8926c92544dSBjoern A. Zeeb if (!phy->mt76->cap.has_5ghz)
8936c92544dSBjoern A. Zeeb return;
8946c92544dSBjoern A. Zeeb
895cbb3ec25SBjoern A. Zeeb sts = hweight8(phy->mt76->chainmask);
8966c92544dSBjoern A. Zeeb cap = &phy->mt76->sband_5g.sband.vht_cap.cap;
8976c92544dSBjoern A. Zeeb
8986c92544dSBjoern A. Zeeb *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
8996c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
900cbb3ec25SBjoern A. Zeeb FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK,
901cbb3ec25SBjoern A. Zeeb sts - 1);
9026c92544dSBjoern A. Zeeb
9036c92544dSBjoern A. Zeeb *cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK |
9046c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
9056c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
9066c92544dSBjoern A. Zeeb
907cbb3ec25SBjoern A. Zeeb if (sts < 2)
9086c92544dSBjoern A. Zeeb return;
9096c92544dSBjoern A. Zeeb
9106c92544dSBjoern A. Zeeb *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
9116c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE |
9126c92544dSBjoern A. Zeeb FIELD_PREP(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,
913cbb3ec25SBjoern A. Zeeb sts - 1);
9146c92544dSBjoern A. Zeeb }
9156c92544dSBjoern A. Zeeb
9166c92544dSBjoern A. Zeeb static void
mt7915_set_stream_he_txbf_caps(struct mt7915_phy * phy,struct ieee80211_sta_he_cap * he_cap,int vif)917cbb3ec25SBjoern A. Zeeb mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
918cbb3ec25SBjoern A. Zeeb struct ieee80211_sta_he_cap *he_cap, int vif)
9196c92544dSBjoern A. Zeeb {
920cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
9216c92544dSBjoern A. Zeeb struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
922cbb3ec25SBjoern A. Zeeb int sts = hweight8(phy->mt76->chainmask);
923cbb3ec25SBjoern A. Zeeb u8 c, sts_160 = sts;
9246c92544dSBjoern A. Zeeb
925cbb3ec25SBjoern A. Zeeb /* Can do 1/2 of STS in 160Mhz mode for mt7915 */
926cbb3ec25SBjoern A. Zeeb if (is_mt7915(&dev->mt76)) {
927cbb3ec25SBjoern A. Zeeb if (!dev->dbdc_support)
928cbb3ec25SBjoern A. Zeeb sts_160 /= 2;
9296c92544dSBjoern A. Zeeb else
930cbb3ec25SBjoern A. Zeeb sts_160 = 0;
931cbb3ec25SBjoern A. Zeeb }
9326c92544dSBjoern A. Zeeb
9336c92544dSBjoern A. Zeeb #ifdef CONFIG_MAC80211_MESH
9346c92544dSBjoern A. Zeeb if (vif == NL80211_IFTYPE_MESH_POINT)
9356c92544dSBjoern A. Zeeb return;
9366c92544dSBjoern A. Zeeb #endif
9376c92544dSBjoern A. Zeeb
9386c92544dSBjoern A. Zeeb elem->phy_cap_info[3] &= ~IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
9396c92544dSBjoern A. Zeeb elem->phy_cap_info[4] &= ~IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
9406c92544dSBjoern A. Zeeb
941cbb3ec25SBjoern A. Zeeb c = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
942cbb3ec25SBjoern A. Zeeb if (sts_160)
943cbb3ec25SBjoern A. Zeeb c |= IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
9446c92544dSBjoern A. Zeeb elem->phy_cap_info[5] &= ~c;
9456c92544dSBjoern A. Zeeb
9466c92544dSBjoern A. Zeeb c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
9476c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;
9486c92544dSBjoern A. Zeeb elem->phy_cap_info[6] &= ~c;
9496c92544dSBjoern A. Zeeb
9506c92544dSBjoern A. Zeeb elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
9516c92544dSBjoern A. Zeeb
9526c92544dSBjoern A. Zeeb c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US;
9536c92544dSBjoern A. Zeeb if (!is_mt7915(&dev->mt76))
9546c92544dSBjoern A. Zeeb c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
9556c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
9566c92544dSBjoern A. Zeeb elem->phy_cap_info[2] |= c;
9576c92544dSBjoern A. Zeeb
9586c92544dSBjoern A. Zeeb c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
959cbb3ec25SBjoern A. Zeeb IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;
960cbb3ec25SBjoern A. Zeeb if (sts_160)
961cbb3ec25SBjoern A. Zeeb c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
9626c92544dSBjoern A. Zeeb elem->phy_cap_info[4] |= c;
9636c92544dSBjoern A. Zeeb
9646c92544dSBjoern A. Zeeb /* do not support NG16 due to spec D4.0 changes subcarrier idx */
9656c92544dSBjoern A. Zeeb c = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
9666c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU;
9676c92544dSBjoern A. Zeeb
9686c92544dSBjoern A. Zeeb if (vif == NL80211_IFTYPE_STATION)
9696c92544dSBjoern A. Zeeb c |= IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
9706c92544dSBjoern A. Zeeb
9716c92544dSBjoern A. Zeeb elem->phy_cap_info[6] |= c;
9726c92544dSBjoern A. Zeeb
973cbb3ec25SBjoern A. Zeeb if (sts < 2)
9746c92544dSBjoern A. Zeeb return;
9756c92544dSBjoern A. Zeeb
9766c92544dSBjoern A. Zeeb /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
977cbb3ec25SBjoern A. Zeeb elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3;
9786c92544dSBjoern A. Zeeb
979*8ba4d145SBjoern A. Zeeb if (vif != NL80211_IFTYPE_AP && vif != NL80211_IFTYPE_STATION)
9806c92544dSBjoern A. Zeeb return;
9816c92544dSBjoern A. Zeeb
9826c92544dSBjoern A. Zeeb elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
9836c92544dSBjoern A. Zeeb
9846c92544dSBjoern A. Zeeb c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
985cbb3ec25SBjoern A. Zeeb sts - 1);
986cbb3ec25SBjoern A. Zeeb if (sts_160)
987cbb3ec25SBjoern A. Zeeb c |= FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,
988cbb3ec25SBjoern A. Zeeb sts_160 - 1);
9896c92544dSBjoern A. Zeeb elem->phy_cap_info[5] |= c;
9906c92544dSBjoern A. Zeeb
991*8ba4d145SBjoern A. Zeeb if (vif != NL80211_IFTYPE_AP)
992*8ba4d145SBjoern A. Zeeb return;
993*8ba4d145SBjoern A. Zeeb
994*8ba4d145SBjoern A. Zeeb elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
995*8ba4d145SBjoern A. Zeeb
9966c92544dSBjoern A. Zeeb c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
9976c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;
9986c92544dSBjoern A. Zeeb elem->phy_cap_info[6] |= c;
9996c92544dSBjoern A. Zeeb
10006c92544dSBjoern A. Zeeb if (!is_mt7915(&dev->mt76)) {
10016c92544dSBjoern A. Zeeb c = IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
10026c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
10036c92544dSBjoern A. Zeeb elem->phy_cap_info[7] |= c;
10046c92544dSBjoern A. Zeeb }
10056c92544dSBjoern A. Zeeb }
10066c92544dSBjoern A. Zeeb
10076c92544dSBjoern A. Zeeb static int
mt7915_init_he_caps(struct mt7915_phy * phy,enum nl80211_band band,struct ieee80211_sband_iftype_data * data)10086c92544dSBjoern A. Zeeb mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
10096c92544dSBjoern A. Zeeb struct ieee80211_sband_iftype_data *data)
10106c92544dSBjoern A. Zeeb {
10116c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
1012cbb3ec25SBjoern A. Zeeb int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);
10136c92544dSBjoern A. Zeeb u16 mcs_map = 0;
10146c92544dSBjoern A. Zeeb u16 mcs_map_160 = 0;
10156c92544dSBjoern A. Zeeb u8 nss_160;
10166c92544dSBjoern A. Zeeb
1017cbb3ec25SBjoern A. Zeeb if (!is_mt7915(&dev->mt76))
1018cbb3ec25SBjoern A. Zeeb nss_160 = nss;
1019cbb3ec25SBjoern A. Zeeb else if (!dev->dbdc_support)
10206c92544dSBjoern A. Zeeb /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
10216c92544dSBjoern A. Zeeb nss_160 = nss / 2;
10226c92544dSBjoern A. Zeeb else
1023cbb3ec25SBjoern A. Zeeb /* Can't do 160MHz with mt7915 dbdc */
1024cbb3ec25SBjoern A. Zeeb nss_160 = 0;
10256c92544dSBjoern A. Zeeb
10266c92544dSBjoern A. Zeeb for (i = 0; i < 8; i++) {
10276c92544dSBjoern A. Zeeb if (i < nss)
10286c92544dSBjoern A. Zeeb mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
10296c92544dSBjoern A. Zeeb else
10306c92544dSBjoern A. Zeeb mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
10316c92544dSBjoern A. Zeeb
10326c92544dSBjoern A. Zeeb if (i < nss_160)
10336c92544dSBjoern A. Zeeb mcs_map_160 |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
10346c92544dSBjoern A. Zeeb else
10356c92544dSBjoern A. Zeeb mcs_map_160 |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
10366c92544dSBjoern A. Zeeb }
10376c92544dSBjoern A. Zeeb
10386c92544dSBjoern A. Zeeb for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
10396c92544dSBjoern A. Zeeb struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
10406c92544dSBjoern A. Zeeb struct ieee80211_he_cap_elem *he_cap_elem =
10416c92544dSBjoern A. Zeeb &he_cap->he_cap_elem;
10426c92544dSBjoern A. Zeeb struct ieee80211_he_mcs_nss_supp *he_mcs =
10436c92544dSBjoern A. Zeeb &he_cap->he_mcs_nss_supp;
10446c92544dSBjoern A. Zeeb
10456c92544dSBjoern A. Zeeb switch (i) {
10466c92544dSBjoern A. Zeeb case NL80211_IFTYPE_STATION:
10476c92544dSBjoern A. Zeeb case NL80211_IFTYPE_AP:
10486c92544dSBjoern A. Zeeb #ifdef CONFIG_MAC80211_MESH
10496c92544dSBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
10506c92544dSBjoern A. Zeeb #endif
10516c92544dSBjoern A. Zeeb break;
10526c92544dSBjoern A. Zeeb default:
10536c92544dSBjoern A. Zeeb continue;
10546c92544dSBjoern A. Zeeb }
10556c92544dSBjoern A. Zeeb
10566c92544dSBjoern A. Zeeb data[idx].types_mask = BIT(i);
10576c92544dSBjoern A. Zeeb he_cap->has_he = true;
10586c92544dSBjoern A. Zeeb
10596c92544dSBjoern A. Zeeb he_cap_elem->mac_cap_info[0] =
10606c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP0_HTC_HE;
10616c92544dSBjoern A. Zeeb he_cap_elem->mac_cap_info[3] =
10626c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
10636c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;
10646c92544dSBjoern A. Zeeb he_cap_elem->mac_cap_info[4] =
10656c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU;
10666c92544dSBjoern A. Zeeb
10676c92544dSBjoern A. Zeeb if (band == NL80211_BAND_2GHZ)
10686c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[0] =
10696c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
1070cbb3ec25SBjoern A. Zeeb else if (nss_160)
10716c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[0] =
10726c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
1073cbb3ec25SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
1074cbb3ec25SBjoern A. Zeeb else
1075cbb3ec25SBjoern A. Zeeb he_cap_elem->phy_cap_info[0] =
1076cbb3ec25SBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
10776c92544dSBjoern A. Zeeb
10786c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[1] =
10796c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
10806c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[2] =
10816c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
10826c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
10836c92544dSBjoern A. Zeeb
10846c92544dSBjoern A. Zeeb switch (i) {
10856c92544dSBjoern A. Zeeb case NL80211_IFTYPE_AP:
10866c92544dSBjoern A. Zeeb he_cap_elem->mac_cap_info[0] |=
10876c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP0_TWT_RES;
10886c92544dSBjoern A. Zeeb he_cap_elem->mac_cap_info[2] |=
10896c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP2_BSR;
10906c92544dSBjoern A. Zeeb he_cap_elem->mac_cap_info[4] |=
10916c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP4_BQR;
10926c92544dSBjoern A. Zeeb he_cap_elem->mac_cap_info[5] |=
10936c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;
10946c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[3] |=
10956c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
10966c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
10976c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[6] |=
10986c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
10996c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
11006c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[9] |=
11016c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
11026c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
11036c92544dSBjoern A. Zeeb break;
11046c92544dSBjoern A. Zeeb case NL80211_IFTYPE_STATION:
11056c92544dSBjoern A. Zeeb he_cap_elem->mac_cap_info[1] |=
11066c92544dSBjoern A. Zeeb IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
11076c92544dSBjoern A. Zeeb
11086c92544dSBjoern A. Zeeb if (band == NL80211_BAND_2GHZ)
11096c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[0] |=
11106c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;
11116c92544dSBjoern A. Zeeb else
11126c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[0] |=
11136c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;
11146c92544dSBjoern A. Zeeb
11156c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[1] |=
11166c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
11176c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US;
11186c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[3] |=
11196c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
11206c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
11216c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[6] |=
11226c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
11236c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
11246c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
11256c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[7] |=
11266c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
11276c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
11286c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[8] |=
11296c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
11306c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;
1131cbb3ec25SBjoern A. Zeeb if (nss_160)
1132cbb3ec25SBjoern A. Zeeb he_cap_elem->phy_cap_info[8] |=
1133cbb3ec25SBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
1134cbb3ec25SBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU;
11356c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[9] |=
11366c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
11376c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
11386c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
11396c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
11406c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
11416c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
11426c92544dSBjoern A. Zeeb break;
11436c92544dSBjoern A. Zeeb }
11446c92544dSBjoern A. Zeeb
1145cbb3ec25SBjoern A. Zeeb memset(he_mcs, 0, sizeof(*he_mcs));
11466c92544dSBjoern A. Zeeb he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
11476c92544dSBjoern A. Zeeb he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
11486c92544dSBjoern A. Zeeb he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map_160);
11496c92544dSBjoern A. Zeeb he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map_160);
11506c92544dSBjoern A. Zeeb
1151cbb3ec25SBjoern A. Zeeb mt7915_set_stream_he_txbf_caps(phy, he_cap, i);
11526c92544dSBjoern A. Zeeb
11536c92544dSBjoern A. Zeeb memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
11546c92544dSBjoern A. Zeeb if (he_cap_elem->phy_cap_info[6] &
11556c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
1156*8ba4d145SBjoern A. Zeeb mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss, band);
11576c92544dSBjoern A. Zeeb } else {
11586c92544dSBjoern A. Zeeb he_cap_elem->phy_cap_info[9] |=
11596c92544dSBjoern A. Zeeb u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
11606c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
11616c92544dSBjoern A. Zeeb }
11626c92544dSBjoern A. Zeeb
11636c92544dSBjoern A. Zeeb if (band == NL80211_BAND_6GHZ) {
11646c92544dSBjoern A. Zeeb u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
11656c92544dSBjoern A. Zeeb IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
11666c92544dSBjoern A. Zeeb
11676c92544dSBjoern A. Zeeb cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
11686c92544dSBjoern A. Zeeb IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
11696c92544dSBjoern A. Zeeb u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
11706c92544dSBjoern A. Zeeb IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
11716c92544dSBjoern A. Zeeb u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
11726c92544dSBjoern A. Zeeb IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
11736c92544dSBjoern A. Zeeb
11746c92544dSBjoern A. Zeeb data[idx].he_6ghz_capa.capa = cpu_to_le16(cap);
11756c92544dSBjoern A. Zeeb }
11766c92544dSBjoern A. Zeeb
11776c92544dSBjoern A. Zeeb idx++;
11786c92544dSBjoern A. Zeeb }
11796c92544dSBjoern A. Zeeb
11806c92544dSBjoern A. Zeeb return idx;
11816c92544dSBjoern A. Zeeb }
11826c92544dSBjoern A. Zeeb
mt7915_set_stream_he_caps(struct mt7915_phy * phy)11836c92544dSBjoern A. Zeeb void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
11846c92544dSBjoern A. Zeeb {
11856c92544dSBjoern A. Zeeb struct ieee80211_sband_iftype_data *data;
11866c92544dSBjoern A. Zeeb struct ieee80211_supported_band *band;
11876c92544dSBjoern A. Zeeb int n;
11886c92544dSBjoern A. Zeeb
11896c92544dSBjoern A. Zeeb if (phy->mt76->cap.has_2ghz) {
11906c92544dSBjoern A. Zeeb data = phy->iftype[NL80211_BAND_2GHZ];
11916c92544dSBjoern A. Zeeb n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);
11926c92544dSBjoern A. Zeeb
11936c92544dSBjoern A. Zeeb band = &phy->mt76->sband_2g.sband;
1194*8ba4d145SBjoern A. Zeeb _ieee80211_set_sband_iftype_data(band, data, n);
11956c92544dSBjoern A. Zeeb }
11966c92544dSBjoern A. Zeeb
11976c92544dSBjoern A. Zeeb if (phy->mt76->cap.has_5ghz) {
11986c92544dSBjoern A. Zeeb data = phy->iftype[NL80211_BAND_5GHZ];
11996c92544dSBjoern A. Zeeb n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);
12006c92544dSBjoern A. Zeeb
12016c92544dSBjoern A. Zeeb band = &phy->mt76->sband_5g.sband;
1202*8ba4d145SBjoern A. Zeeb _ieee80211_set_sband_iftype_data(band, data, n);
12036c92544dSBjoern A. Zeeb }
12046c92544dSBjoern A. Zeeb
12056c92544dSBjoern A. Zeeb if (phy->mt76->cap.has_6ghz) {
12066c92544dSBjoern A. Zeeb data = phy->iftype[NL80211_BAND_6GHZ];
12076c92544dSBjoern A. Zeeb n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data);
12086c92544dSBjoern A. Zeeb
12096c92544dSBjoern A. Zeeb band = &phy->mt76->sband_6g.sband;
1210*8ba4d145SBjoern A. Zeeb _ieee80211_set_sband_iftype_data(band, data, n);
12116c92544dSBjoern A. Zeeb }
12126c92544dSBjoern A. Zeeb }
12136c92544dSBjoern A. Zeeb
mt7915_unregister_ext_phy(struct mt7915_dev * dev)12146c92544dSBjoern A. Zeeb static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
12156c92544dSBjoern A. Zeeb {
12166c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_ext_phy(dev);
12176c92544dSBjoern A. Zeeb struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];
12186c92544dSBjoern A. Zeeb
12196c92544dSBjoern A. Zeeb if (!phy)
12206c92544dSBjoern A. Zeeb return;
12216c92544dSBjoern A. Zeeb
12226c92544dSBjoern A. Zeeb #if defined(__linux__)
12236c92544dSBjoern A. Zeeb mt7915_unregister_thermal(phy);
12246c92544dSBjoern A. Zeeb #endif
12256c92544dSBjoern A. Zeeb mt76_unregister_phy(mphy);
12266c92544dSBjoern A. Zeeb ieee80211_free_hw(mphy->hw);
12276c92544dSBjoern A. Zeeb }
12286c92544dSBjoern A. Zeeb
mt7915_stop_hardware(struct mt7915_dev * dev)12296c92544dSBjoern A. Zeeb static void mt7915_stop_hardware(struct mt7915_dev *dev)
12306c92544dSBjoern A. Zeeb {
12316c92544dSBjoern A. Zeeb mt7915_mcu_exit(dev);
1232cbb3ec25SBjoern A. Zeeb mt76_connac2_tx_token_put(&dev->mt76);
12336c92544dSBjoern A. Zeeb mt7915_dma_cleanup(dev);
1234cbb3ec25SBjoern A. Zeeb tasklet_disable(&dev->mt76.irq_tasklet);
12356c92544dSBjoern A. Zeeb
1236cbb3ec25SBjoern A. Zeeb if (is_mt798x(&dev->mt76))
12376c92544dSBjoern A. Zeeb mt7986_wmac_disable(dev);
12386c92544dSBjoern A. Zeeb }
12396c92544dSBjoern A. Zeeb
mt7915_register_device(struct mt7915_dev * dev)12406c92544dSBjoern A. Zeeb int mt7915_register_device(struct mt7915_dev *dev)
12416c92544dSBjoern A. Zeeb {
12426c92544dSBjoern A. Zeeb struct mt7915_phy *phy2;
12436c92544dSBjoern A. Zeeb int ret;
12446c92544dSBjoern A. Zeeb
12456c92544dSBjoern A. Zeeb dev->phy.dev = dev;
12466c92544dSBjoern A. Zeeb dev->phy.mt76 = &dev->mt76.phy;
12476c92544dSBjoern A. Zeeb dev->mt76.phy.priv = &dev->phy;
12486c92544dSBjoern A. Zeeb INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);
12496c92544dSBjoern A. Zeeb INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work);
12506c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&dev->sta_rc_list);
12516c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&dev->twt_list);
12526c92544dSBjoern A. Zeeb
12536c92544dSBjoern A. Zeeb init_waitqueue_head(&dev->reset_wait);
12546c92544dSBjoern A. Zeeb INIT_WORK(&dev->reset_work, mt7915_mac_reset_work);
1255cbb3ec25SBjoern A. Zeeb INIT_WORK(&dev->dump_work, mt7915_mac_dump_work);
1256cbb3ec25SBjoern A. Zeeb mutex_init(&dev->dump_mutex);
12576c92544dSBjoern A. Zeeb
12586c92544dSBjoern A. Zeeb dev->dbdc_support = mt7915_band_config(dev);
12596c92544dSBjoern A. Zeeb
12606c92544dSBjoern A. Zeeb phy2 = mt7915_alloc_ext_phy(dev);
12616c92544dSBjoern A. Zeeb if (IS_ERR(phy2))
12626c92544dSBjoern A. Zeeb return PTR_ERR(phy2);
12636c92544dSBjoern A. Zeeb
12646c92544dSBjoern A. Zeeb ret = mt7915_init_hardware(dev, phy2);
12656c92544dSBjoern A. Zeeb if (ret)
12666c92544dSBjoern A. Zeeb goto free_phy2;
12676c92544dSBjoern A. Zeeb
1268cbb3ec25SBjoern A. Zeeb mt7915_init_wiphy(&dev->phy);
12696c92544dSBjoern A. Zeeb
12706c92544dSBjoern A. Zeeb #ifdef CONFIG_NL80211_TESTMODE
12716c92544dSBjoern A. Zeeb dev->mt76.test_ops = &mt7915_testmode_ops;
12726c92544dSBjoern A. Zeeb #endif
12736c92544dSBjoern A. Zeeb
12746c92544dSBjoern A. Zeeb ret = mt76_register_device(&dev->mt76, true, mt76_rates,
12756c92544dSBjoern A. Zeeb ARRAY_SIZE(mt76_rates));
12766c92544dSBjoern A. Zeeb if (ret)
12776c92544dSBjoern A. Zeeb goto stop_hw;
12786c92544dSBjoern A. Zeeb
12796c92544dSBjoern A. Zeeb ret = mt7915_thermal_init(&dev->phy);
12806c92544dSBjoern A. Zeeb if (ret)
12816c92544dSBjoern A. Zeeb goto unreg_dev;
12826c92544dSBjoern A. Zeeb
12836c92544dSBjoern A. Zeeb if (phy2) {
12846c92544dSBjoern A. Zeeb ret = mt7915_register_ext_phy(dev, phy2);
12856c92544dSBjoern A. Zeeb if (ret)
12866c92544dSBjoern A. Zeeb goto unreg_thermal;
12876c92544dSBjoern A. Zeeb }
12886c92544dSBjoern A. Zeeb
1289*8ba4d145SBjoern A. Zeeb ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
1290*8ba4d145SBjoern A. Zeeb
1291cbb3ec25SBjoern A. Zeeb dev->recovery.hw_init_done = true;
1292cbb3ec25SBjoern A. Zeeb
12936c92544dSBjoern A. Zeeb #if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS)
1294cbb3ec25SBjoern A. Zeeb ret = mt7915_init_debugfs(&dev->phy);
1295cbb3ec25SBjoern A. Zeeb if (ret)
1296cbb3ec25SBjoern A. Zeeb goto unreg_thermal;
12976c92544dSBjoern A. Zeeb #endif
12986c92544dSBjoern A. Zeeb
1299cbb3ec25SBjoern A. Zeeb ret = mt7915_coredump_register(dev);
1300cbb3ec25SBjoern A. Zeeb if (ret)
1301cbb3ec25SBjoern A. Zeeb goto unreg_thermal;
1302cbb3ec25SBjoern A. Zeeb
13036c92544dSBjoern A. Zeeb return 0;
13046c92544dSBjoern A. Zeeb
13056c92544dSBjoern A. Zeeb unreg_thermal:
13066c92544dSBjoern A. Zeeb #if defined(__linux__)
13076c92544dSBjoern A. Zeeb mt7915_unregister_thermal(&dev->phy);
13086c92544dSBjoern A. Zeeb #endif
13096c92544dSBjoern A. Zeeb unreg_dev:
13106c92544dSBjoern A. Zeeb mt76_unregister_device(&dev->mt76);
13116c92544dSBjoern A. Zeeb stop_hw:
13126c92544dSBjoern A. Zeeb mt7915_stop_hardware(dev);
13136c92544dSBjoern A. Zeeb free_phy2:
13146c92544dSBjoern A. Zeeb if (phy2)
13156c92544dSBjoern A. Zeeb ieee80211_free_hw(phy2->mt76->hw);
13166c92544dSBjoern A. Zeeb return ret;
13176c92544dSBjoern A. Zeeb }
13186c92544dSBjoern A. Zeeb
mt7915_unregister_device(struct mt7915_dev * dev)13196c92544dSBjoern A. Zeeb void mt7915_unregister_device(struct mt7915_dev *dev)
13206c92544dSBjoern A. Zeeb {
13216c92544dSBjoern A. Zeeb mt7915_unregister_ext_phy(dev);
1322cbb3ec25SBjoern A. Zeeb mt7915_coredump_unregister(dev);
13236c92544dSBjoern A. Zeeb #if defined(__linux__)
13246c92544dSBjoern A. Zeeb mt7915_unregister_thermal(&dev->phy);
13256c92544dSBjoern A. Zeeb #endif
13266c92544dSBjoern A. Zeeb mt76_unregister_device(&dev->mt76);
13276c92544dSBjoern A. Zeeb mt7915_stop_hardware(dev);
13286c92544dSBjoern A. Zeeb
13296c92544dSBjoern A. Zeeb mt76_free_device(&dev->mt76);
13306c92544dSBjoern A. Zeeb }
1331