xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7615/init.c (revision 8ba4d145d351db26e07695b8e90697398c5dfec2)
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 
1877285868SBjoern A. Zeeb #if defined(__linux__)
mt7615_thermal_show_temp(struct device * dev,struct device_attribute * attr,char * buf)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 
mt7615_thermal_init(struct mt7615_dev * dev)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));
60*8ba4d145SBjoern A. Zeeb 	if (!name)
61*8ba4d145SBjoern A. Zeeb 		return -ENOMEM;
62*8ba4d145SBjoern A. Zeeb 
636c92544dSBjoern A. Zeeb 	hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev,
646c92544dSBjoern A. Zeeb 						       mt7615_hwmon_groups);
65*8ba4d145SBjoern A. Zeeb 	return PTR_ERR_OR_ZERO(hwmon);
666c92544dSBjoern A. Zeeb }
676c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_thermal_init);
6877285868SBjoern A. Zeeb #endif
696c92544dSBjoern A. Zeeb 
706c92544dSBjoern A. Zeeb static void
mt7615_phy_init(struct mt7615_dev * dev)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
mt7615_init_mac_chain(struct mt7615_dev * dev,int chain)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
mt7615_mac_init(struct mt7615_dev * dev)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
mt7615_check_offload_capability(struct mt7615_dev * dev)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 
mt7615_wait_for_mcu_init(struct mt7615_dev * dev)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 
mt7615_init_txpower(struct mt7615_dev * dev,struct ieee80211_supported_band * sband)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 
mt7615_init_work(struct mt7615_dev * dev)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);
327*8ba4d145SBjoern A. Zeeb 	mt76_connac_mcu_del_wtbl_all(&dev->mt76);
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
mt7615_regd_notifier(struct wiphy * wiphy,struct regulatory_request * request)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
mt7615_init_wiphy(struct ieee80211_hw * hw)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
mt7615_cap_dbdc_enable(struct mt7615_dev * dev)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
mt7615_cap_dbdc_disable(struct mt7615_dev * dev)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 
mt7615_reg_map(struct mt7615_dev * dev,u32 addr)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
mt7615_led_set_config(struct led_classdev * led_cdev,u8 delay_on,u8 delay_off)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 
mt7615_led_set_blink(struct led_classdev * led_cdev,unsigned long * delay_on,unsigned long * delay_off)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 
mt7615_led_set_brightness(struct led_classdev * led_cdev,enum led_brightness brightness)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 
mt7615_register_ext_phy(struct mt7615_dev * dev)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 	 */
57177285868SBjoern A. Zeeb #if defined(__linux__)
5726c92544dSBjoern A. Zeeb 	memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
57377285868SBjoern A. Zeeb #elif defined(__FreeBSD__)
57477285868SBjoern A. Zeeb 	memcpy(mphy->macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
57577285868SBjoern 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 
mt7615_unregister_ext_phy(struct mt7615_dev * dev)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 
mt7615_init_device(struct mt7615_dev * dev)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