16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC 26c92544dSBjoern A. Zeeb /* Copyright (C) 2019 MediaTek Inc. 36c92544dSBjoern A. Zeeb * 46c92544dSBjoern A. Zeeb * Author: Roy Luo <royluo@google.com> 56c92544dSBjoern A. Zeeb * Ryder Lee <ryder.lee@mediatek.com> 66c92544dSBjoern A. Zeeb * Felix Fietkau <nbd@nbd.name> 76c92544dSBjoern A. Zeeb * Lorenzo Bianconi <lorenzo@kernel.org> 86c92544dSBjoern A. Zeeb */ 96c92544dSBjoern A. Zeeb 106c92544dSBjoern A. Zeeb #include <linux/etherdevice.h> 116c92544dSBjoern A. Zeeb #include <linux/hwmon.h> 126c92544dSBjoern A. Zeeb #include <linux/hwmon-sysfs.h> 136c92544dSBjoern A. Zeeb #include "mt7615.h" 146c92544dSBjoern A. Zeeb #include "mac.h" 156c92544dSBjoern A. Zeeb #include "mcu.h" 166c92544dSBjoern A. Zeeb #include "eeprom.h" 176c92544dSBjoern A. Zeeb 18*77285868SBjoern A. Zeeb #if defined(__linux__) 196c92544dSBjoern A. Zeeb static ssize_t mt7615_thermal_show_temp(struct device *dev, 206c92544dSBjoern A. Zeeb struct device_attribute *attr, 216c92544dSBjoern A. Zeeb char *buf) 226c92544dSBjoern A. Zeeb { 236c92544dSBjoern A. Zeeb struct mt7615_dev *mdev = dev_get_drvdata(dev); 246c92544dSBjoern A. Zeeb int temperature; 256c92544dSBjoern A. Zeeb 266c92544dSBjoern A. Zeeb if (!mt7615_wait_for_mcu_init(mdev)) 276c92544dSBjoern A. Zeeb return 0; 286c92544dSBjoern A. Zeeb 296c92544dSBjoern A. Zeeb mt7615_mutex_acquire(mdev); 306c92544dSBjoern A. Zeeb temperature = mt7615_mcu_get_temperature(mdev); 316c92544dSBjoern A. Zeeb mt7615_mutex_release(mdev); 326c92544dSBjoern A. Zeeb 336c92544dSBjoern A. Zeeb if (temperature < 0) 346c92544dSBjoern A. Zeeb return temperature; 356c92544dSBjoern A. Zeeb 366c92544dSBjoern A. Zeeb /* display in millidegree celcius */ 376c92544dSBjoern A. Zeeb return sprintf(buf, "%u\n", temperature * 1000); 386c92544dSBjoern A. Zeeb } 396c92544dSBjoern A. Zeeb 406c92544dSBjoern A. Zeeb static SENSOR_DEVICE_ATTR(temp1_input, 0444, mt7615_thermal_show_temp, 416c92544dSBjoern A. Zeeb NULL, 0); 426c92544dSBjoern A. Zeeb 436c92544dSBjoern A. Zeeb static struct attribute *mt7615_hwmon_attrs[] = { 446c92544dSBjoern A. Zeeb &sensor_dev_attr_temp1_input.dev_attr.attr, 456c92544dSBjoern A. Zeeb NULL, 466c92544dSBjoern A. Zeeb }; 476c92544dSBjoern A. Zeeb ATTRIBUTE_GROUPS(mt7615_hwmon); 486c92544dSBjoern A. Zeeb 496c92544dSBjoern A. Zeeb int mt7615_thermal_init(struct mt7615_dev *dev) 506c92544dSBjoern A. Zeeb { 516c92544dSBjoern A. Zeeb struct wiphy *wiphy = mt76_hw(dev)->wiphy; 526c92544dSBjoern A. Zeeb struct device *hwmon; 536c92544dSBjoern A. Zeeb const char *name; 546c92544dSBjoern A. Zeeb 556c92544dSBjoern A. Zeeb if (!IS_REACHABLE(CONFIG_HWMON)) 566c92544dSBjoern A. Zeeb return 0; 576c92544dSBjoern A. Zeeb 586c92544dSBjoern A. Zeeb name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7615_%s", 596c92544dSBjoern A. Zeeb wiphy_name(wiphy)); 606c92544dSBjoern A. Zeeb hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev, 616c92544dSBjoern A. Zeeb mt7615_hwmon_groups); 626c92544dSBjoern A. Zeeb if (IS_ERR(hwmon)) 636c92544dSBjoern A. Zeeb return PTR_ERR(hwmon); 646c92544dSBjoern A. Zeeb 656c92544dSBjoern A. Zeeb return 0; 666c92544dSBjoern A. Zeeb } 676c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_thermal_init); 68*77285868SBjoern A. Zeeb #endif 696c92544dSBjoern A. Zeeb 706c92544dSBjoern A. Zeeb static void 716c92544dSBjoern A. Zeeb mt7615_phy_init(struct mt7615_dev *dev) 726c92544dSBjoern A. Zeeb { 736c92544dSBjoern A. Zeeb /* disable rf low power beacon mode */ 746c92544dSBjoern A. Zeeb mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(0), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); 756c92544dSBjoern A. Zeeb mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(1), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); 766c92544dSBjoern A. Zeeb } 776c92544dSBjoern A. Zeeb 786c92544dSBjoern A. Zeeb static void 796c92544dSBjoern A. Zeeb mt7615_init_mac_chain(struct mt7615_dev *dev, int chain) 806c92544dSBjoern A. Zeeb { 816c92544dSBjoern A. Zeeb u32 val; 826c92544dSBjoern A. Zeeb 836c92544dSBjoern A. Zeeb if (!chain) 846c92544dSBjoern A. Zeeb val = MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN; 856c92544dSBjoern A. Zeeb else 866c92544dSBjoern A. Zeeb val = MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN; 876c92544dSBjoern A. Zeeb 886c92544dSBjoern A. Zeeb /* enable band 0/1 clk */ 896c92544dSBjoern A. Zeeb mt76_set(dev, MT_CFG_CCR, val); 906c92544dSBjoern A. Zeeb 916c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_TMAC_TRCR(chain), 926c92544dSBjoern A. Zeeb MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL, 936c92544dSBjoern A. Zeeb FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) | 946c92544dSBjoern A. Zeeb FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0)); 956c92544dSBjoern A. Zeeb 966c92544dSBjoern A. Zeeb mt76_wr(dev, MT_AGG_ACR(chain), 976c92544dSBjoern A. Zeeb MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | 986c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) | 996c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT)); 1006c92544dSBjoern A. Zeeb 1016c92544dSBjoern A. Zeeb mt76_wr(dev, MT_AGG_ARUCR(chain), 1026c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | 1036c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | 1046c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | 1056c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | 1066c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | 1076c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | 1086c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | 1096c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); 1106c92544dSBjoern A. Zeeb 1116c92544dSBjoern A. Zeeb mt76_wr(dev, MT_AGG_ARDCR(chain), 1126c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | 1136c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | 1146c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | 1156c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | 1166c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | 1176c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | 1186c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | 1196c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1)); 1206c92544dSBjoern A. Zeeb 1216c92544dSBjoern A. Zeeb mt76_clear(dev, MT_DMA_RCFR0(chain), MT_DMA_RCFR0_MCU_RX_TDLS); 1226c92544dSBjoern A. Zeeb if (!mt7615_firmware_offload(dev)) { 1236c92544dSBjoern A. Zeeb u32 mask, set; 1246c92544dSBjoern A. Zeeb 1256c92544dSBjoern A. Zeeb mask = MT_DMA_RCFR0_MCU_RX_MGMT | 1266c92544dSBjoern A. Zeeb MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR | 1276c92544dSBjoern A. Zeeb MT_DMA_RCFR0_MCU_RX_CTL_BAR | 1286c92544dSBjoern A. Zeeb MT_DMA_RCFR0_MCU_RX_BYPASS | 1296c92544dSBjoern A. Zeeb MT_DMA_RCFR0_RX_DROPPED_UCAST | 1306c92544dSBjoern A. Zeeb MT_DMA_RCFR0_RX_DROPPED_MCAST; 1316c92544dSBjoern A. Zeeb set = FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_UCAST, 2) | 1326c92544dSBjoern A. Zeeb FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_MCAST, 2); 1336c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_DMA_RCFR0(chain), mask, set); 1346c92544dSBjoern A. Zeeb } 1356c92544dSBjoern A. Zeeb } 1366c92544dSBjoern A. Zeeb 1376c92544dSBjoern A. Zeeb static void 1386c92544dSBjoern A. Zeeb mt7615_mac_init(struct mt7615_dev *dev) 1396c92544dSBjoern A. Zeeb { 1406c92544dSBjoern A. Zeeb int i; 1416c92544dSBjoern A. Zeeb 1426c92544dSBjoern A. Zeeb mt7615_init_mac_chain(dev, 0); 1436c92544dSBjoern A. Zeeb 1446c92544dSBjoern A. Zeeb mt76_rmw_field(dev, MT_TMAC_CTCR0, 1456c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); 1466c92544dSBjoern A. Zeeb mt76_rmw_field(dev, MT_TMAC_CTCR0, 1476c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_DENSITY, 0x3); 1486c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_TMAC_CTCR0, 1496c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | 1506c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_EN, 1516c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | 1526c92544dSBjoern A. Zeeb MT_TMAC_CTCR0_INS_DDLMT_EN); 1536c92544dSBjoern A. Zeeb 1546c92544dSBjoern A. Zeeb mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0); 1556c92544dSBjoern A. Zeeb mt7615_mac_set_scs(&dev->phy, true); 1566c92544dSBjoern A. Zeeb 1576c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, 1586c92544dSBjoern A. Zeeb MT_AGG_SCR_NLNAV_MID_PTEC_DIS); 1596c92544dSBjoern A. Zeeb 1606c92544dSBjoern A. Zeeb mt76_wr(dev, MT_AGG_ARCR, 1616c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | 1626c92544dSBjoern A. Zeeb MT_AGG_ARCR_RATE_DOWN_RATIO_EN | 1636c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | 1646c92544dSBjoern A. Zeeb FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4)); 1656c92544dSBjoern A. Zeeb 1666c92544dSBjoern A. Zeeb for (i = 0; i < MT7615_WTBL_SIZE; i++) 1676c92544dSBjoern A. Zeeb mt7615_mac_wtbl_update(dev, i, 1686c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 1696c92544dSBjoern A. Zeeb 1706c92544dSBjoern A. Zeeb mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_EN); 1716c92544dSBjoern A. Zeeb mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN); 1726c92544dSBjoern A. Zeeb 1736c92544dSBjoern A. Zeeb mt76_wr(dev, MT_DMA_DCR0, 1746c92544dSBjoern A. Zeeb FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) | 1756c92544dSBjoern A. Zeeb MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN | 1766c92544dSBjoern A. Zeeb MT_DMA_DCR0_RX_HDR_TRANS_EN); 1776c92544dSBjoern A. Zeeb /* disable TDLS filtering */ 1786c92544dSBjoern A. Zeeb mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN); 1796c92544dSBjoern A. Zeeb mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN); 1806c92544dSBjoern A. Zeeb if (is_mt7663(&dev->mt76)) { 1816c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WF_AGG(0x160), 0x5c341c02); 1826c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WF_AGG(0x164), 0x70708040); 1836c92544dSBjoern A. Zeeb } else { 1846c92544dSBjoern A. Zeeb mt7615_init_mac_chain(dev, 1); 1856c92544dSBjoern A. Zeeb } 1866c92544dSBjoern A. Zeeb mt7615_mcu_set_rx_hdr_trans_blacklist(dev); 1876c92544dSBjoern A. Zeeb } 1886c92544dSBjoern A. Zeeb 1896c92544dSBjoern A. Zeeb static void 1906c92544dSBjoern A. Zeeb mt7615_check_offload_capability(struct mt7615_dev *dev) 1916c92544dSBjoern A. Zeeb { 1926c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = mt76_hw(dev); 1936c92544dSBjoern A. Zeeb struct wiphy *wiphy = hw->wiphy; 1946c92544dSBjoern A. Zeeb 1956c92544dSBjoern A. Zeeb if (mt7615_firmware_offload(dev)) { 1966c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_PS); 1976c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); 1986c92544dSBjoern A. Zeeb 1996c92544dSBjoern A. Zeeb wiphy->flags &= ~WIPHY_FLAG_4ADDR_STATION; 2006c92544dSBjoern A. Zeeb wiphy->max_remain_on_channel_duration = 5000; 2016c92544dSBjoern A. Zeeb wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | 2026c92544dSBjoern A. Zeeb NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | 2036c92544dSBjoern A. Zeeb WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | 2046c92544dSBjoern A. Zeeb NL80211_FEATURE_P2P_GO_CTWIN | 2056c92544dSBjoern A. Zeeb NL80211_FEATURE_P2P_GO_OPPPS; 2066c92544dSBjoern A. Zeeb } else { 2076c92544dSBjoern A. Zeeb dev->ops->hw_scan = NULL; 2086c92544dSBjoern A. Zeeb dev->ops->cancel_hw_scan = NULL; 2096c92544dSBjoern A. Zeeb dev->ops->sched_scan_start = NULL; 2106c92544dSBjoern A. Zeeb dev->ops->sched_scan_stop = NULL; 2116c92544dSBjoern A. Zeeb dev->ops->set_rekey_data = NULL; 2126c92544dSBjoern A. Zeeb dev->ops->remain_on_channel = NULL; 2136c92544dSBjoern A. Zeeb dev->ops->cancel_remain_on_channel = NULL; 2146c92544dSBjoern A. Zeeb 2156c92544dSBjoern A. Zeeb wiphy->max_sched_scan_plan_interval = 0; 2166c92544dSBjoern A. Zeeb wiphy->max_sched_scan_ie_len = 0; 2176c92544dSBjoern A. Zeeb wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; 2186c92544dSBjoern A. Zeeb wiphy->max_sched_scan_ssids = 0; 2196c92544dSBjoern A. Zeeb wiphy->max_match_sets = 0; 2206c92544dSBjoern A. Zeeb wiphy->max_sched_scan_reqs = 0; 2216c92544dSBjoern A. Zeeb } 2226c92544dSBjoern A. Zeeb } 2236c92544dSBjoern A. Zeeb 2246c92544dSBjoern A. Zeeb bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev) 2256c92544dSBjoern A. Zeeb { 2266c92544dSBjoern A. Zeeb flush_work(&dev->mcu_work); 2276c92544dSBjoern A. Zeeb 2286c92544dSBjoern A. Zeeb return test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 2296c92544dSBjoern A. Zeeb } 2306c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_wait_for_mcu_init); 2316c92544dSBjoern A. Zeeb 2326c92544dSBjoern A. Zeeb static const struct ieee80211_iface_limit if_limits[] = { 2336c92544dSBjoern A. Zeeb { 2346c92544dSBjoern A. Zeeb .max = 1, 2356c92544dSBjoern A. Zeeb .types = BIT(NL80211_IFTYPE_ADHOC) 2366c92544dSBjoern A. Zeeb }, { 2376c92544dSBjoern A. Zeeb .max = MT7615_MAX_INTERFACES, 2386c92544dSBjoern A. Zeeb .types = BIT(NL80211_IFTYPE_AP) | 2396c92544dSBjoern A. Zeeb #ifdef CONFIG_MAC80211_MESH 2406c92544dSBjoern A. Zeeb BIT(NL80211_IFTYPE_MESH_POINT) | 2416c92544dSBjoern A. Zeeb #endif 2426c92544dSBjoern A. Zeeb BIT(NL80211_IFTYPE_P2P_CLIENT) | 2436c92544dSBjoern A. Zeeb BIT(NL80211_IFTYPE_P2P_GO) | 2446c92544dSBjoern A. Zeeb BIT(NL80211_IFTYPE_STATION) 2456c92544dSBjoern A. Zeeb } 2466c92544dSBjoern A. Zeeb }; 2476c92544dSBjoern A. Zeeb 2486c92544dSBjoern A. Zeeb static const struct ieee80211_iface_combination if_comb_radar[] = { 2496c92544dSBjoern A. Zeeb { 2506c92544dSBjoern A. Zeeb .limits = if_limits, 2516c92544dSBjoern A. Zeeb .n_limits = ARRAY_SIZE(if_limits), 2526c92544dSBjoern A. Zeeb .max_interfaces = MT7615_MAX_INTERFACES, 2536c92544dSBjoern A. Zeeb .num_different_channels = 1, 2546c92544dSBjoern A. Zeeb .beacon_int_infra_match = true, 2556c92544dSBjoern A. Zeeb .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | 2566c92544dSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_20) | 2576c92544dSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_40) | 2586c92544dSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_80) | 2596c92544dSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_160) | 2606c92544dSBjoern A. Zeeb BIT(NL80211_CHAN_WIDTH_80P80), 2616c92544dSBjoern A. Zeeb } 2626c92544dSBjoern A. Zeeb }; 2636c92544dSBjoern A. Zeeb 2646c92544dSBjoern A. Zeeb static const struct ieee80211_iface_combination if_comb[] = { 2656c92544dSBjoern A. Zeeb { 2666c92544dSBjoern A. Zeeb .limits = if_limits, 2676c92544dSBjoern A. Zeeb .n_limits = ARRAY_SIZE(if_limits), 2686c92544dSBjoern A. Zeeb .max_interfaces = MT7615_MAX_INTERFACES, 2696c92544dSBjoern A. Zeeb .num_different_channels = 1, 2706c92544dSBjoern A. Zeeb .beacon_int_infra_match = true, 2716c92544dSBjoern A. Zeeb } 2726c92544dSBjoern A. Zeeb }; 2736c92544dSBjoern A. Zeeb 2746c92544dSBjoern A. Zeeb void mt7615_init_txpower(struct mt7615_dev *dev, 2756c92544dSBjoern A. Zeeb struct ieee80211_supported_band *sband) 2766c92544dSBjoern A. Zeeb { 2776c92544dSBjoern A. Zeeb int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains; 2786c92544dSBjoern A. Zeeb int delta_idx, delta = mt76_tx_power_nss_delta(n_chains); 2796c92544dSBjoern A. Zeeb u8 *eep = (u8 *)dev->mt76.eeprom.data; 2806c92544dSBjoern A. Zeeb enum nl80211_band band = sband->band; 2816c92544dSBjoern A. Zeeb struct mt76_power_limits limits; 2826c92544dSBjoern A. Zeeb u8 rate_val; 2836c92544dSBjoern A. Zeeb 2846c92544dSBjoern A. Zeeb delta_idx = mt7615_eeprom_get_power_delta_index(dev, band); 2856c92544dSBjoern A. Zeeb rate_val = eep[delta_idx]; 2866c92544dSBjoern A. Zeeb if ((rate_val & ~MT_EE_RATE_POWER_MASK) == 2876c92544dSBjoern A. Zeeb (MT_EE_RATE_POWER_EN | MT_EE_RATE_POWER_SIGN)) 2886c92544dSBjoern A. Zeeb delta += rate_val & MT_EE_RATE_POWER_MASK; 2896c92544dSBjoern A. Zeeb 2906c92544dSBjoern A. Zeeb if (!is_mt7663(&dev->mt76) && mt7615_ext_pa_enabled(dev, band)) 2916c92544dSBjoern A. Zeeb target_chains = 1; 2926c92544dSBjoern A. Zeeb else 2936c92544dSBjoern A. Zeeb target_chains = n_chains; 2946c92544dSBjoern A. Zeeb 2956c92544dSBjoern A. Zeeb for (i = 0; i < sband->n_channels; i++) { 2966c92544dSBjoern A. Zeeb struct ieee80211_channel *chan = &sband->channels[i]; 2976c92544dSBjoern A. Zeeb u8 target_power = 0; 2986c92544dSBjoern A. Zeeb int j; 2996c92544dSBjoern A. Zeeb 3006c92544dSBjoern A. Zeeb for (j = 0; j < target_chains; j++) { 3016c92544dSBjoern A. Zeeb int index; 3026c92544dSBjoern A. Zeeb 3036c92544dSBjoern A. Zeeb index = mt7615_eeprom_get_target_power_index(dev, chan, j); 3046c92544dSBjoern A. Zeeb if (index < 0) 3056c92544dSBjoern A. Zeeb continue; 3066c92544dSBjoern A. Zeeb 3076c92544dSBjoern A. Zeeb target_power = max(target_power, eep[index]); 3086c92544dSBjoern A. Zeeb } 3096c92544dSBjoern A. Zeeb 3106c92544dSBjoern A. Zeeb target_power = mt76_get_rate_power_limits(&dev->mphy, chan, 3116c92544dSBjoern A. Zeeb &limits, 3126c92544dSBjoern A. Zeeb target_power); 3136c92544dSBjoern A. Zeeb target_power += delta; 3146c92544dSBjoern A. Zeeb target_power = DIV_ROUND_UP(target_power, 2); 3156c92544dSBjoern A. Zeeb chan->max_power = min_t(int, chan->max_reg_power, 3166c92544dSBjoern A. Zeeb target_power); 3176c92544dSBjoern A. Zeeb chan->orig_mpwr = target_power; 3186c92544dSBjoern A. Zeeb } 3196c92544dSBjoern A. Zeeb } 3206c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_init_txpower); 3216c92544dSBjoern A. Zeeb 3226c92544dSBjoern A. Zeeb void mt7615_init_work(struct mt7615_dev *dev) 3236c92544dSBjoern A. Zeeb { 3246c92544dSBjoern A. Zeeb mt7615_mcu_set_eeprom(dev); 3256c92544dSBjoern A. Zeeb mt7615_mac_init(dev); 3266c92544dSBjoern A. Zeeb mt7615_phy_init(dev); 3276c92544dSBjoern A. Zeeb mt7615_mcu_del_wtbl_all(dev); 3286c92544dSBjoern A. Zeeb mt7615_check_offload_capability(dev); 3296c92544dSBjoern A. Zeeb } 3306c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_init_work); 3316c92544dSBjoern A. Zeeb 3326c92544dSBjoern A. Zeeb static void 3336c92544dSBjoern A. Zeeb mt7615_regd_notifier(struct wiphy *wiphy, 3346c92544dSBjoern A. Zeeb struct regulatory_request *request) 3356c92544dSBjoern A. Zeeb { 3366c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 3376c92544dSBjoern A. Zeeb struct mt7615_dev *dev = mt7615_hw_dev(hw); 3386c92544dSBjoern A. Zeeb struct mt76_phy *mphy = hw->priv; 3396c92544dSBjoern A. Zeeb struct mt7615_phy *phy = mphy->priv; 3406c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &mphy->chandef; 3416c92544dSBjoern A. Zeeb 3426c92544dSBjoern A. Zeeb memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); 3436c92544dSBjoern A. Zeeb dev->mt76.region = request->dfs_region; 3446c92544dSBjoern A. Zeeb 3456c92544dSBjoern A. Zeeb mt7615_init_txpower(dev, &mphy->sband_2g.sband); 3466c92544dSBjoern A. Zeeb mt7615_init_txpower(dev, &mphy->sband_5g.sband); 3476c92544dSBjoern A. Zeeb 3486c92544dSBjoern A. Zeeb mt7615_mutex_acquire(dev); 3496c92544dSBjoern A. Zeeb 3506c92544dSBjoern A. Zeeb if (chandef->chan->flags & IEEE80211_CHAN_RADAR) 3516c92544dSBjoern A. Zeeb mt7615_dfs_init_radar_detector(phy); 3526c92544dSBjoern A. Zeeb 3536c92544dSBjoern A. Zeeb if (mt7615_firmware_offload(phy->dev)) { 3546c92544dSBjoern A. Zeeb mt76_connac_mcu_set_channel_domain(mphy); 3556c92544dSBjoern A. Zeeb mt76_connac_mcu_set_rate_txpower(mphy); 3566c92544dSBjoern A. Zeeb } 3576c92544dSBjoern A. Zeeb 3586c92544dSBjoern A. Zeeb mt7615_mutex_release(dev); 3596c92544dSBjoern A. Zeeb } 3606c92544dSBjoern A. Zeeb 3616c92544dSBjoern A. Zeeb static void 3626c92544dSBjoern A. Zeeb mt7615_init_wiphy(struct ieee80211_hw *hw) 3636c92544dSBjoern A. Zeeb { 3646c92544dSBjoern A. Zeeb struct mt7615_phy *phy = mt7615_hw_phy(hw); 3656c92544dSBjoern A. Zeeb struct wiphy *wiphy = hw->wiphy; 3666c92544dSBjoern A. Zeeb 3676c92544dSBjoern A. Zeeb hw->queues = 4; 3686c92544dSBjoern A. Zeeb hw->max_rates = 3; 3696c92544dSBjoern A. Zeeb hw->max_report_rates = 7; 3706c92544dSBjoern A. Zeeb hw->max_rate_tries = 11; 3716c92544dSBjoern A. Zeeb hw->netdev_features = NETIF_F_RXCSUM; 3726c92544dSBjoern A. Zeeb 3736c92544dSBjoern A. Zeeb hw->radiotap_timestamp.units_pos = 3746c92544dSBjoern A. Zeeb IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; 3756c92544dSBjoern A. Zeeb 3766c92544dSBjoern A. Zeeb phy->slottime = 9; 3776c92544dSBjoern A. Zeeb 3786c92544dSBjoern A. Zeeb hw->sta_data_size = sizeof(struct mt7615_sta); 3796c92544dSBjoern A. Zeeb hw->vif_data_size = sizeof(struct mt7615_vif); 3806c92544dSBjoern A. Zeeb 3816c92544dSBjoern A. Zeeb if (is_mt7663(&phy->dev->mt76)) { 3826c92544dSBjoern A. Zeeb wiphy->iface_combinations = if_comb; 3836c92544dSBjoern A. Zeeb wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); 3846c92544dSBjoern A. Zeeb } else { 3856c92544dSBjoern A. Zeeb wiphy->iface_combinations = if_comb_radar; 3866c92544dSBjoern A. Zeeb wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_radar); 3876c92544dSBjoern A. Zeeb } 3886c92544dSBjoern A. Zeeb wiphy->reg_notifier = mt7615_regd_notifier; 3896c92544dSBjoern A. Zeeb 3906c92544dSBjoern A. Zeeb wiphy->max_sched_scan_plan_interval = 3916c92544dSBjoern A. Zeeb MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL; 3926c92544dSBjoern A. Zeeb wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN; 3936c92544dSBjoern A. Zeeb wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; 3946c92544dSBjoern A. Zeeb wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; 3956c92544dSBjoern A. Zeeb wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH; 3966c92544dSBjoern A. Zeeb wiphy->max_sched_scan_reqs = 1; 3976c92544dSBjoern A. Zeeb wiphy->max_scan_ssids = 4; 3986c92544dSBjoern A. Zeeb 3996c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); 4006c92544dSBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); 401cbb3ec25SBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); 402cbb3ec25SBjoern A. Zeeb if (!is_mt7622(&phy->dev->mt76)) 403cbb3ec25SBjoern A. Zeeb wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); 4046c92544dSBjoern A. Zeeb 4056c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); 4066c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); 4076c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, WANT_MONITOR_VIF); 4086c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); 4096c92544dSBjoern A. Zeeb ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); 4106c92544dSBjoern A. Zeeb 4116c92544dSBjoern A. Zeeb if (is_mt7615(&phy->dev->mt76)) 4126c92544dSBjoern A. Zeeb hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; 4136c92544dSBjoern A. Zeeb else 4146c92544dSBjoern A. Zeeb hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM; 4156c92544dSBjoern A. Zeeb 4166c92544dSBjoern A. Zeeb phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; 4176c92544dSBjoern A. Zeeb phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; 4186c92544dSBjoern A. Zeeb phy->mt76->sband_5g.sband.vht_cap.cap |= 4196c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; 4206c92544dSBjoern A. Zeeb } 4216c92544dSBjoern A. Zeeb 4226c92544dSBjoern A. Zeeb static void 4236c92544dSBjoern A. Zeeb mt7615_cap_dbdc_enable(struct mt7615_dev *dev) 4246c92544dSBjoern A. Zeeb { 4256c92544dSBjoern A. Zeeb dev->mphy.sband_5g.sband.vht_cap.cap &= 4266c92544dSBjoern A. Zeeb ~(IEEE80211_VHT_CAP_SHORT_GI_160 | 4276c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); 4286c92544dSBjoern A. Zeeb if (dev->chainmask == 0xf) 4296c92544dSBjoern A. Zeeb dev->mphy.antenna_mask = dev->chainmask >> 2; 4306c92544dSBjoern A. Zeeb else 4316c92544dSBjoern A. Zeeb dev->mphy.antenna_mask = dev->chainmask >> 1; 4326c92544dSBjoern A. Zeeb dev->mphy.chainmask = dev->mphy.antenna_mask; 4336c92544dSBjoern A. Zeeb dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; 4346c92544dSBjoern A. Zeeb dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; 4356c92544dSBjoern A. Zeeb mt76_set_stream_caps(&dev->mphy, true); 4366c92544dSBjoern A. Zeeb } 4376c92544dSBjoern A. Zeeb 4386c92544dSBjoern A. Zeeb static void 4396c92544dSBjoern A. Zeeb mt7615_cap_dbdc_disable(struct mt7615_dev *dev) 4406c92544dSBjoern A. Zeeb { 4416c92544dSBjoern A. Zeeb dev->mphy.sband_5g.sband.vht_cap.cap |= 4426c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_SHORT_GI_160 | 4436c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; 4446c92544dSBjoern A. Zeeb dev->mphy.antenna_mask = dev->chainmask; 4456c92544dSBjoern A. Zeeb dev->mphy.chainmask = dev->chainmask; 4466c92544dSBjoern A. Zeeb dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask; 4476c92544dSBjoern A. Zeeb dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask; 4486c92544dSBjoern A. Zeeb mt76_set_stream_caps(&dev->mphy, true); 4496c92544dSBjoern A. Zeeb } 4506c92544dSBjoern A. Zeeb 451cbb3ec25SBjoern A. Zeeb u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) 452cbb3ec25SBjoern A. Zeeb { 453cbb3ec25SBjoern A. Zeeb u32 base, offset; 454cbb3ec25SBjoern A. Zeeb 455cbb3ec25SBjoern A. Zeeb if (is_mt7663(&dev->mt76)) { 456cbb3ec25SBjoern A. Zeeb base = addr & MT7663_MCU_PCIE_REMAP_2_BASE; 457cbb3ec25SBjoern A. Zeeb offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET; 458cbb3ec25SBjoern A. Zeeb } else { 459cbb3ec25SBjoern A. Zeeb base = addr & MT_MCU_PCIE_REMAP_2_BASE; 460cbb3ec25SBjoern A. Zeeb offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; 461cbb3ec25SBjoern A. Zeeb } 462cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); 463cbb3ec25SBjoern A. Zeeb 464cbb3ec25SBjoern A. Zeeb return MT_PCIE_REMAP_BASE_2 + offset; 465cbb3ec25SBjoern A. Zeeb } 466cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_reg_map); 467cbb3ec25SBjoern A. Zeeb 468cbb3ec25SBjoern A. Zeeb static void 469cbb3ec25SBjoern A. Zeeb mt7615_led_set_config(struct led_classdev *led_cdev, 470cbb3ec25SBjoern A. Zeeb u8 delay_on, u8 delay_off) 471cbb3ec25SBjoern A. Zeeb { 472cbb3ec25SBjoern A. Zeeb struct mt7615_dev *dev; 473cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy; 474cbb3ec25SBjoern A. Zeeb u32 val, addr; 475cbb3ec25SBjoern A. Zeeb u8 index; 476cbb3ec25SBjoern A. Zeeb 477cbb3ec25SBjoern A. Zeeb mphy = container_of(led_cdev, struct mt76_phy, leds.cdev); 478cbb3ec25SBjoern A. Zeeb dev = container_of(mphy->dev, struct mt7615_dev, mt76); 479cbb3ec25SBjoern A. Zeeb 480cbb3ec25SBjoern A. Zeeb if (!mt76_connac_pm_ref(mphy, &dev->pm)) 481cbb3ec25SBjoern A. Zeeb return; 482cbb3ec25SBjoern A. Zeeb 483cbb3ec25SBjoern A. Zeeb val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | 484cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | 485cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_LED_STATUS_ON, delay_on); 486cbb3ec25SBjoern A. Zeeb 487cbb3ec25SBjoern A. Zeeb index = dev->dbdc_support ? mphy->band_idx : mphy->leds.pin; 488cbb3ec25SBjoern A. Zeeb addr = mt7615_reg_map(dev, MT_LED_STATUS_0(index)); 489cbb3ec25SBjoern A. Zeeb mt76_wr(dev, addr, val); 490cbb3ec25SBjoern A. Zeeb addr = mt7615_reg_map(dev, MT_LED_STATUS_1(index)); 491cbb3ec25SBjoern A. Zeeb mt76_wr(dev, addr, val); 492cbb3ec25SBjoern A. Zeeb 493cbb3ec25SBjoern A. Zeeb val = MT_LED_CTRL_REPLAY(index) | MT_LED_CTRL_KICK(index); 494cbb3ec25SBjoern A. Zeeb if (dev->mphy.leds.al) 495cbb3ec25SBjoern A. Zeeb val |= MT_LED_CTRL_POLARITY(index); 496cbb3ec25SBjoern A. Zeeb if (mphy->band_idx) 497cbb3ec25SBjoern A. Zeeb val |= MT_LED_CTRL_BAND(index); 498cbb3ec25SBjoern A. Zeeb 499cbb3ec25SBjoern A. Zeeb addr = mt7615_reg_map(dev, MT_LED_CTRL); 500cbb3ec25SBjoern A. Zeeb mt76_wr(dev, addr, val); 501cbb3ec25SBjoern A. Zeeb 502cbb3ec25SBjoern A. Zeeb mt76_connac_pm_unref(mphy, &dev->pm); 503cbb3ec25SBjoern A. Zeeb } 504cbb3ec25SBjoern A. Zeeb 505cbb3ec25SBjoern A. Zeeb int mt7615_led_set_blink(struct led_classdev *led_cdev, 506cbb3ec25SBjoern A. Zeeb unsigned long *delay_on, 507cbb3ec25SBjoern A. Zeeb unsigned long *delay_off) 508cbb3ec25SBjoern A. Zeeb { 509cbb3ec25SBjoern A. Zeeb u8 delta_on, delta_off; 510cbb3ec25SBjoern A. Zeeb 511cbb3ec25SBjoern A. Zeeb delta_off = max_t(u8, *delay_off / 10, 1); 512cbb3ec25SBjoern A. Zeeb delta_on = max_t(u8, *delay_on / 10, 1); 513cbb3ec25SBjoern A. Zeeb 514cbb3ec25SBjoern A. Zeeb mt7615_led_set_config(led_cdev, delta_on, delta_off); 515cbb3ec25SBjoern A. Zeeb 516cbb3ec25SBjoern A. Zeeb return 0; 517cbb3ec25SBjoern A. Zeeb } 518cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_led_set_blink); 519cbb3ec25SBjoern A. Zeeb 520cbb3ec25SBjoern A. Zeeb void mt7615_led_set_brightness(struct led_classdev *led_cdev, 521cbb3ec25SBjoern A. Zeeb enum led_brightness brightness) 522cbb3ec25SBjoern A. Zeeb { 523cbb3ec25SBjoern A. Zeeb if (!brightness) 524cbb3ec25SBjoern A. Zeeb mt7615_led_set_config(led_cdev, 0, 0xff); 525cbb3ec25SBjoern A. Zeeb else 526cbb3ec25SBjoern A. Zeeb mt7615_led_set_config(led_cdev, 0xff, 0); 527cbb3ec25SBjoern A. Zeeb } 528cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_led_set_brightness); 529cbb3ec25SBjoern A. Zeeb 5306c92544dSBjoern A. Zeeb int mt7615_register_ext_phy(struct mt7615_dev *dev) 5316c92544dSBjoern A. Zeeb { 5326c92544dSBjoern A. Zeeb struct mt7615_phy *phy = mt7615_ext_phy(dev); 5336c92544dSBjoern A. Zeeb struct mt76_phy *mphy; 5346c92544dSBjoern A. Zeeb int i, ret; 5356c92544dSBjoern A. Zeeb 5366c92544dSBjoern A. Zeeb if (!is_mt7615(&dev->mt76)) 5376c92544dSBjoern A. Zeeb return -EOPNOTSUPP; 5386c92544dSBjoern A. Zeeb 5396c92544dSBjoern A. Zeeb if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) 5406c92544dSBjoern A. Zeeb return -EINVAL; 5416c92544dSBjoern A. Zeeb 5426c92544dSBjoern A. Zeeb if (phy) 5436c92544dSBjoern A. Zeeb return 0; 5446c92544dSBjoern A. Zeeb 5456c92544dSBjoern A. Zeeb mt7615_cap_dbdc_enable(dev); 5466c92544dSBjoern A. Zeeb mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops, MT_BAND1); 5476c92544dSBjoern A. Zeeb if (!mphy) 5486c92544dSBjoern A. Zeeb return -ENOMEM; 5496c92544dSBjoern A. Zeeb 5506c92544dSBjoern A. Zeeb phy = mphy->priv; 5516c92544dSBjoern A. Zeeb phy->dev = dev; 5526c92544dSBjoern A. Zeeb phy->mt76 = mphy; 5536c92544dSBjoern A. Zeeb mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask; 5546c92544dSBjoern A. Zeeb mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1; 5556c92544dSBjoern A. Zeeb mt7615_init_wiphy(mphy->hw); 5566c92544dSBjoern A. Zeeb 5576c92544dSBjoern A. Zeeb INIT_DELAYED_WORK(&mphy->mac_work, mt7615_mac_work); 5586c92544dSBjoern A. Zeeb INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work); 5596c92544dSBjoern A. Zeeb skb_queue_head_init(&phy->scan_event_list); 5606c92544dSBjoern A. Zeeb 5616c92544dSBjoern A. Zeeb INIT_WORK(&phy->roc_work, mt7615_roc_work); 5626c92544dSBjoern A. Zeeb timer_setup(&phy->roc_timer, mt7615_roc_timer, 0); 5636c92544dSBjoern A. Zeeb init_waitqueue_head(&phy->roc_wait); 5646c92544dSBjoern A. Zeeb 5656c92544dSBjoern A. Zeeb mt7615_mac_set_scs(phy, true); 5666c92544dSBjoern A. Zeeb 5676c92544dSBjoern A. Zeeb /* 5686c92544dSBjoern A. Zeeb * Make the secondary PHY MAC address local without overlapping with 5696c92544dSBjoern A. Zeeb * the usual MAC address allocation scheme on multiple virtual interfaces 5706c92544dSBjoern A. Zeeb */ 571*77285868SBjoern A. Zeeb #if defined(__linux__) 5726c92544dSBjoern A. Zeeb memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 573*77285868SBjoern A. Zeeb #elif defined(__FreeBSD__) 574*77285868SBjoern A. Zeeb memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 575*77285868SBjoern A. Zeeb #endif 5766c92544dSBjoern A. Zeeb ETH_ALEN); 5776c92544dSBjoern A. Zeeb mphy->macaddr[0] |= 2; 5786c92544dSBjoern A. Zeeb mphy->macaddr[0] ^= BIT(7); 5796c92544dSBjoern A. Zeeb mt76_eeprom_override(mphy); 5806c92544dSBjoern A. Zeeb 5816c92544dSBjoern A. Zeeb /* second phy can only handle 5 GHz */ 5826c92544dSBjoern A. Zeeb mphy->cap.has_5ghz = true; 5836c92544dSBjoern A. Zeeb 5846c92544dSBjoern A. Zeeb /* mt7615 second phy shares the same hw queues with the primary one */ 5856c92544dSBjoern A. Zeeb for (i = 0; i <= MT_TXQ_PSD ; i++) 5866c92544dSBjoern A. Zeeb mphy->q_tx[i] = dev->mphy.q_tx[i]; 5876c92544dSBjoern A. Zeeb 588cbb3ec25SBjoern A. Zeeb /* init led callbacks */ 589cbb3ec25SBjoern A. Zeeb if (IS_ENABLED(CONFIG_MT76_LEDS)) { 590cbb3ec25SBjoern A. Zeeb mphy->leds.cdev.brightness_set = mt7615_led_set_brightness; 591cbb3ec25SBjoern A. Zeeb mphy->leds.cdev.blink_set = mt7615_led_set_blink; 592cbb3ec25SBjoern A. Zeeb } 593cbb3ec25SBjoern A. Zeeb 5946c92544dSBjoern A. Zeeb ret = mt76_register_phy(mphy, true, mt76_rates, 5956c92544dSBjoern A. Zeeb ARRAY_SIZE(mt76_rates)); 5966c92544dSBjoern A. Zeeb if (ret) 5976c92544dSBjoern A. Zeeb ieee80211_free_hw(mphy->hw); 5986c92544dSBjoern A. Zeeb 5996c92544dSBjoern A. Zeeb return ret; 6006c92544dSBjoern A. Zeeb } 6016c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_register_ext_phy); 6026c92544dSBjoern A. Zeeb 6036c92544dSBjoern A. Zeeb void mt7615_unregister_ext_phy(struct mt7615_dev *dev) 6046c92544dSBjoern A. Zeeb { 6056c92544dSBjoern A. Zeeb struct mt7615_phy *phy = mt7615_ext_phy(dev); 6066c92544dSBjoern A. Zeeb struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1]; 6076c92544dSBjoern A. Zeeb 6086c92544dSBjoern A. Zeeb if (!phy) 6096c92544dSBjoern A. Zeeb return; 6106c92544dSBjoern A. Zeeb 6116c92544dSBjoern A. Zeeb mt7615_cap_dbdc_disable(dev); 6126c92544dSBjoern A. Zeeb mt76_unregister_phy(mphy); 6136c92544dSBjoern A. Zeeb ieee80211_free_hw(mphy->hw); 6146c92544dSBjoern A. Zeeb } 6156c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_unregister_ext_phy); 6166c92544dSBjoern A. Zeeb 6176c92544dSBjoern A. Zeeb void mt7615_init_device(struct mt7615_dev *dev) 6186c92544dSBjoern A. Zeeb { 6196c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = mt76_hw(dev); 6206c92544dSBjoern A. Zeeb 6216c92544dSBjoern A. Zeeb dev->phy.dev = dev; 6226c92544dSBjoern A. Zeeb dev->phy.mt76 = &dev->mt76.phy; 6236c92544dSBjoern A. Zeeb dev->mt76.phy.priv = &dev->phy; 6246c92544dSBjoern A. Zeeb dev->mt76.tx_worker.fn = mt7615_tx_worker; 6256c92544dSBjoern A. Zeeb 6266c92544dSBjoern A. Zeeb INIT_DELAYED_WORK(&dev->pm.ps_work, mt7615_pm_power_save_work); 6276c92544dSBjoern A. Zeeb INIT_WORK(&dev->pm.wake_work, mt7615_pm_wake_work); 6286c92544dSBjoern A. Zeeb spin_lock_init(&dev->pm.wake.lock); 6296c92544dSBjoern A. Zeeb mutex_init(&dev->pm.mutex); 6306c92544dSBjoern A. Zeeb init_waitqueue_head(&dev->pm.wait); 6316c92544dSBjoern A. Zeeb spin_lock_init(&dev->pm.txq_lock); 6326c92544dSBjoern A. Zeeb INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7615_mac_work); 6336c92544dSBjoern A. Zeeb INIT_DELAYED_WORK(&dev->phy.scan_work, mt7615_scan_work); 6346c92544dSBjoern A. Zeeb INIT_DELAYED_WORK(&dev->coredump.work, mt7615_coredump_work); 6356c92544dSBjoern A. Zeeb skb_queue_head_init(&dev->phy.scan_event_list); 6366c92544dSBjoern A. Zeeb skb_queue_head_init(&dev->coredump.msg_list); 6376c92544dSBjoern A. Zeeb init_waitqueue_head(&dev->reset_wait); 6386c92544dSBjoern A. Zeeb init_waitqueue_head(&dev->phy.roc_wait); 6396c92544dSBjoern A. Zeeb 6406c92544dSBjoern A. Zeeb INIT_WORK(&dev->phy.roc_work, mt7615_roc_work); 6416c92544dSBjoern A. Zeeb timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0); 6426c92544dSBjoern A. Zeeb 6436c92544dSBjoern A. Zeeb mt7615_init_wiphy(hw); 6446c92544dSBjoern A. Zeeb dev->pm.idle_timeout = MT7615_PM_TIMEOUT; 6456c92544dSBjoern A. Zeeb dev->pm.stats.last_wake_event = jiffies; 6466c92544dSBjoern A. Zeeb dev->pm.stats.last_doze_event = jiffies; 6476c92544dSBjoern A. Zeeb mt7615_cap_dbdc_disable(dev); 6486c92544dSBjoern A. Zeeb 6496c92544dSBjoern A. Zeeb #ifdef CONFIG_NL80211_TESTMODE 6506c92544dSBjoern A. Zeeb dev->mt76.test_ops = &mt7615_testmode_ops; 6516c92544dSBjoern A. Zeeb #endif 6526c92544dSBjoern A. Zeeb } 6536c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_init_device); 654