xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/mediatek/mt76/mt7915/init.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: ISC
2*4882a593Smuzhiyun /* Copyright (C) 2020 MediaTek Inc. */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/etherdevice.h>
5*4882a593Smuzhiyun #include "mt7915.h"
6*4882a593Smuzhiyun #include "mac.h"
7*4882a593Smuzhiyun #include "eeprom.h"
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun static void
mt7915_mac_init_band(struct mt7915_dev * dev,u8 band)10*4882a593Smuzhiyun mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
11*4882a593Smuzhiyun {
12*4882a593Smuzhiyun 	u32 mask, set;
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun 	mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
15*4882a593Smuzhiyun 		       MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
16*4882a593Smuzhiyun 	mt76_set(dev, MT_TMAC_CTCR0(band),
17*4882a593Smuzhiyun 		 MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
18*4882a593Smuzhiyun 		 MT_TMAC_CTCR0_INS_DDLMT_EN);
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 	mask = MT_MDP_RCFR0_MCU_RX_MGMT |
21*4882a593Smuzhiyun 	       MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR |
22*4882a593Smuzhiyun 	       MT_MDP_RCFR0_MCU_RX_CTL_BAR;
23*4882a593Smuzhiyun 	set = FIELD_PREP(MT_MDP_RCFR0_MCU_RX_MGMT, MT_MDP_TO_HIF) |
24*4882a593Smuzhiyun 	      FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR, MT_MDP_TO_HIF) |
25*4882a593Smuzhiyun 	      FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_BAR, MT_MDP_TO_HIF);
26*4882a593Smuzhiyun 	mt76_rmw(dev, MT_MDP_BNRCFR0(band), mask, set);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	mask = MT_MDP_RCFR1_MCU_RX_BYPASS |
29*4882a593Smuzhiyun 	       MT_MDP_RCFR1_RX_DROPPED_UCAST |
30*4882a593Smuzhiyun 	       MT_MDP_RCFR1_RX_DROPPED_MCAST;
31*4882a593Smuzhiyun 	set = FIELD_PREP(MT_MDP_RCFR1_MCU_RX_BYPASS, MT_MDP_TO_HIF) |
32*4882a593Smuzhiyun 	      FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_UCAST, MT_MDP_TO_HIF) |
33*4882a593Smuzhiyun 	      FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);
34*4882a593Smuzhiyun 	mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
37*4882a593Smuzhiyun 	mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun 
mt7915_mac_init(struct mt7915_dev * dev)40*4882a593Smuzhiyun static void mt7915_mac_init(struct mt7915_dev *dev)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	int i;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	mt76_rmw_field(dev, MT_DMA_DCR0, MT_DMA_DCR0_MAX_RX_LEN, 1536);
45*4882a593Smuzhiyun 	mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
46*4882a593Smuzhiyun 	/* enable rx rate report */
47*4882a593Smuzhiyun 	mt76_set(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN);
48*4882a593Smuzhiyun 	/* disable hardware de-agg */
49*4882a593Smuzhiyun 	mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	for (i = 0; i < MT7915_WTBL_SIZE; i++)
52*4882a593Smuzhiyun 		mt7915_mac_wtbl_update(dev, i,
53*4882a593Smuzhiyun 				       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	mt7915_mac_init_band(dev, 0);
56*4882a593Smuzhiyun 	mt7915_mac_init_band(dev, 1);
57*4882a593Smuzhiyun 	mt7915_mcu_set_rts_thresh(&dev->phy, 0x92b);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
mt7915_txbf_init(struct mt7915_dev * dev)60*4882a593Smuzhiyun static int mt7915_txbf_init(struct mt7915_dev *dev)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	int ret;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	/*
65*4882a593Smuzhiyun 	 * TODO: DBDC & check whether iBF phase calibration data has
66*4882a593Smuzhiyun 	 * been stored in eeprom offset 0x651~0x7b8, then write down
67*4882a593Smuzhiyun 	 * 0x1111 into 0x651 and 0x651 to trigger iBF.
68*4882a593Smuzhiyun 	 */
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	/* trigger sounding packets */
71*4882a593Smuzhiyun 	ret = mt7915_mcu_set_txbf_sounding(dev);
72*4882a593Smuzhiyun 	if (ret)
73*4882a593Smuzhiyun 		return ret;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	/* enable iBF & eBF */
76*4882a593Smuzhiyun 	return mt7915_mcu_set_txbf_type(dev);
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun static void
mt7915_init_txpower_band(struct mt7915_dev * dev,struct ieee80211_supported_band * sband)80*4882a593Smuzhiyun mt7915_init_txpower_band(struct mt7915_dev *dev,
81*4882a593Smuzhiyun 			 struct ieee80211_supported_band *sband)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	int i, n_chains = hweight8(dev->mphy.antenna_mask);
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	for (i = 0; i < sband->n_channels; i++) {
86*4882a593Smuzhiyun 		struct ieee80211_channel *chan = &sband->channels[i];
87*4882a593Smuzhiyun 		u32 target_power = 0;
88*4882a593Smuzhiyun 		int j;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 		for (j = 0; j < n_chains; j++) {
91*4882a593Smuzhiyun 			u32 val;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 			val = mt7915_eeprom_get_target_power(dev, chan, j);
94*4882a593Smuzhiyun 			target_power = max(target_power, val);
95*4882a593Smuzhiyun 		}
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 		chan->max_power = min_t(int, chan->max_reg_power,
98*4882a593Smuzhiyun 					target_power / 2);
99*4882a593Smuzhiyun 		chan->orig_mpwr = target_power / 2;
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
mt7915_init_txpower(struct mt7915_dev * dev)103*4882a593Smuzhiyun static void mt7915_init_txpower(struct mt7915_dev *dev)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	mt7915_init_txpower_band(dev, &dev->mphy.sband_2g.sband);
106*4882a593Smuzhiyun 	mt7915_init_txpower_band(dev, &dev->mphy.sband_5g.sband);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	mt7915_eeprom_init_sku(dev);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
mt7915_init_work(struct work_struct * work)111*4882a593Smuzhiyun static void mt7915_init_work(struct work_struct *work)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	struct mt7915_dev *dev = container_of(work, struct mt7915_dev,
114*4882a593Smuzhiyun 				 init_work);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	mt7915_mcu_set_eeprom(dev);
117*4882a593Smuzhiyun 	mt7915_mac_init(dev);
118*4882a593Smuzhiyun 	mt7915_init_txpower(dev);
119*4882a593Smuzhiyun 	mt7915_txbf_init(dev);
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
mt7915_init_hardware(struct mt7915_dev * dev)122*4882a593Smuzhiyun static int mt7915_init_hardware(struct mt7915_dev *dev)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	int ret, idx;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	INIT_WORK(&dev->init_work, mt7915_init_work);
129*4882a593Smuzhiyun 	spin_lock_init(&dev->token_lock);
130*4882a593Smuzhiyun 	idr_init(&dev->token);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	ret = mt7915_dma_init(dev);
133*4882a593Smuzhiyun 	if (ret)
134*4882a593Smuzhiyun 		return ret;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	/*
139*4882a593Smuzhiyun 	 * force firmware operation mode into normal state,
140*4882a593Smuzhiyun 	 * which should be set before firmware download stage.
141*4882a593Smuzhiyun 	 */
142*4882a593Smuzhiyun 	mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	ret = mt7915_mcu_init(dev);
145*4882a593Smuzhiyun 	if (ret)
146*4882a593Smuzhiyun 		return ret;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	ret = mt7915_eeprom_init(dev);
149*4882a593Smuzhiyun 	if (ret < 0)
150*4882a593Smuzhiyun 		return ret;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	/* Beacon and mgmt frames should occupy wcid 0 */
153*4882a593Smuzhiyun 	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA - 1);
154*4882a593Smuzhiyun 	if (idx)
155*4882a593Smuzhiyun 		return -ENOSPC;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	dev->mt76.global_wcid.idx = idx;
158*4882a593Smuzhiyun 	dev->mt76.global_wcid.hw_key_idx = -1;
159*4882a593Smuzhiyun 	dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;
160*4882a593Smuzhiyun 	rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	return 0;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun #define CCK_RATE(_idx, _rate) {						\
166*4882a593Smuzhiyun 	.bitrate = _rate,						\
167*4882a593Smuzhiyun 	.flags = IEEE80211_RATE_SHORT_PREAMBLE,				\
168*4882a593Smuzhiyun 	.hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),			\
169*4882a593Smuzhiyun 	.hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)),	\
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun #define OFDM_RATE(_idx, _rate) {					\
173*4882a593Smuzhiyun 	.bitrate = _rate,						\
174*4882a593Smuzhiyun 	.hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),			\
175*4882a593Smuzhiyun 	.hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),		\
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun static struct ieee80211_rate mt7915_rates[] = {
179*4882a593Smuzhiyun 	CCK_RATE(0, 10),
180*4882a593Smuzhiyun 	CCK_RATE(1, 20),
181*4882a593Smuzhiyun 	CCK_RATE(2, 55),
182*4882a593Smuzhiyun 	CCK_RATE(3, 110),
183*4882a593Smuzhiyun 	OFDM_RATE(11, 60),
184*4882a593Smuzhiyun 	OFDM_RATE(15, 90),
185*4882a593Smuzhiyun 	OFDM_RATE(10, 120),
186*4882a593Smuzhiyun 	OFDM_RATE(14, 180),
187*4882a593Smuzhiyun 	OFDM_RATE(9,  240),
188*4882a593Smuzhiyun 	OFDM_RATE(13, 360),
189*4882a593Smuzhiyun 	OFDM_RATE(8,  480),
190*4882a593Smuzhiyun 	OFDM_RATE(12, 540),
191*4882a593Smuzhiyun };
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun static const struct ieee80211_iface_limit if_limits[] = {
194*4882a593Smuzhiyun 	{
195*4882a593Smuzhiyun 		.max = 1,
196*4882a593Smuzhiyun 		.types = BIT(NL80211_IFTYPE_ADHOC)
197*4882a593Smuzhiyun 	}, {
198*4882a593Smuzhiyun 		.max = MT7915_MAX_INTERFACES,
199*4882a593Smuzhiyun 		.types = BIT(NL80211_IFTYPE_AP) |
200*4882a593Smuzhiyun #ifdef CONFIG_MAC80211_MESH
201*4882a593Smuzhiyun 			 BIT(NL80211_IFTYPE_MESH_POINT) |
202*4882a593Smuzhiyun #endif
203*4882a593Smuzhiyun 			 BIT(NL80211_IFTYPE_STATION)
204*4882a593Smuzhiyun 	}
205*4882a593Smuzhiyun };
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun static const struct ieee80211_iface_combination if_comb[] = {
208*4882a593Smuzhiyun 	{
209*4882a593Smuzhiyun 		.limits = if_limits,
210*4882a593Smuzhiyun 		.n_limits = ARRAY_SIZE(if_limits),
211*4882a593Smuzhiyun 		.max_interfaces = 4,
212*4882a593Smuzhiyun 		.num_different_channels = 1,
213*4882a593Smuzhiyun 		.beacon_int_infra_match = true,
214*4882a593Smuzhiyun 		.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
215*4882a593Smuzhiyun 				       BIT(NL80211_CHAN_WIDTH_20) |
216*4882a593Smuzhiyun 				       BIT(NL80211_CHAN_WIDTH_40) |
217*4882a593Smuzhiyun 				       BIT(NL80211_CHAN_WIDTH_80) |
218*4882a593Smuzhiyun 				       BIT(NL80211_CHAN_WIDTH_160) |
219*4882a593Smuzhiyun 				       BIT(NL80211_CHAN_WIDTH_80P80),
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun };
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun static void
mt7915_regd_notifier(struct wiphy * wiphy,struct regulatory_request * request)224*4882a593Smuzhiyun mt7915_regd_notifier(struct wiphy *wiphy,
225*4882a593Smuzhiyun 		     struct regulatory_request *request)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
228*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
229*4882a593Smuzhiyun 	struct mt76_phy *mphy = hw->priv;
230*4882a593Smuzhiyun 	struct mt7915_phy *phy = mphy->priv;
231*4882a593Smuzhiyun 	struct cfg80211_chan_def *chandef = &mphy->chandef;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	dev->mt76.region = request->dfs_region;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR))
236*4882a593Smuzhiyun 		return;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	mt7915_dfs_init_radar_detector(phy);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun static void
mt7915_init_wiphy(struct ieee80211_hw * hw)242*4882a593Smuzhiyun mt7915_init_wiphy(struct ieee80211_hw *hw)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
245*4882a593Smuzhiyun 	struct wiphy *wiphy = hw->wiphy;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	hw->queues = 4;
248*4882a593Smuzhiyun 	hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
249*4882a593Smuzhiyun 	hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	phy->slottime = 9;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	hw->sta_data_size = sizeof(struct mt7915_sta);
254*4882a593Smuzhiyun 	hw->vif_data_size = sizeof(struct mt7915_vif);
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	wiphy->iface_combinations = if_comb;
257*4882a593Smuzhiyun 	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
258*4882a593Smuzhiyun 	wiphy->reg_notifier = mt7915_regd_notifier;
259*4882a593Smuzhiyun 	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	hw->max_tx_fragments = 4;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
mt7915_set_stream_vht_txbf_caps(struct mt7915_phy * phy)268*4882a593Smuzhiyun void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	int nss = hweight8(phy->chainmask);
271*4882a593Smuzhiyun 	u32 *cap = &phy->mt76->sband_5g.sband.vht_cap.cap;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
274*4882a593Smuzhiyun 		IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
275*4882a593Smuzhiyun 		(3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	*cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK |
278*4882a593Smuzhiyun 		  IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
279*4882a593Smuzhiyun 		  IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	if (nss < 2)
282*4882a593Smuzhiyun 		return;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
285*4882a593Smuzhiyun 		IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE |
286*4882a593Smuzhiyun 		FIELD_PREP(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,
287*4882a593Smuzhiyun 			   nss - 1);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun static void
mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap * he_cap,int vif,int nss)291*4882a593Smuzhiyun mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
292*4882a593Smuzhiyun 			       int vif, int nss)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun 	struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
295*4882a593Smuzhiyun 	struct ieee80211_he_mcs_nss_supp *mcs = &he_cap->he_mcs_nss_supp;
296*4882a593Smuzhiyun 	u8 c;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun #ifdef CONFIG_MAC80211_MESH
299*4882a593Smuzhiyun 	if (vif == NL80211_IFTYPE_MESH_POINT)
300*4882a593Smuzhiyun 		return;
301*4882a593Smuzhiyun #endif
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	elem->phy_cap_info[3] &= ~IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
304*4882a593Smuzhiyun 	elem->phy_cap_info[4] &= ~IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	c = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK |
307*4882a593Smuzhiyun 	    IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
308*4882a593Smuzhiyun 	elem->phy_cap_info[5] &= ~c;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB |
311*4882a593Smuzhiyun 	    IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB;
312*4882a593Smuzhiyun 	elem->phy_cap_info[6] &= ~c;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
317*4882a593Smuzhiyun 	    IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
318*4882a593Smuzhiyun 	    IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
319*4882a593Smuzhiyun 	elem->phy_cap_info[2] |= c;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
322*4882a593Smuzhiyun 	    IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 |
323*4882a593Smuzhiyun 	    IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
324*4882a593Smuzhiyun 	elem->phy_cap_info[4] |= c;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* do not support NG16 due to spec D4.0 changes subcarrier idx */
327*4882a593Smuzhiyun 	c = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
328*4882a593Smuzhiyun 	    IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	if (vif == NL80211_IFTYPE_STATION)
331*4882a593Smuzhiyun 		c |= IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	elem->phy_cap_info[6] |= c;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	if (nss < 2)
336*4882a593Smuzhiyun 		return;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	/* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
339*4882a593Smuzhiyun 	elem->phy_cap_info[7] |= min_t(int, nss - 1, 2) << 3;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	if (vif != NL80211_IFTYPE_AP)
342*4882a593Smuzhiyun 		return;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
345*4882a593Smuzhiyun 	elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	/* num_snd_dim */
348*4882a593Smuzhiyun 	c = (nss - 1) | (max_t(int, mcs->tx_mcs_160, 1) << 3);
349*4882a593Smuzhiyun 	elem->phy_cap_info[5] |= c;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB |
352*4882a593Smuzhiyun 	    IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB;
353*4882a593Smuzhiyun 	elem->phy_cap_info[6] |= c;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun static void
mt7915_gen_ppe_thresh(u8 * he_ppet)357*4882a593Smuzhiyun mt7915_gen_ppe_thresh(u8 *he_ppet)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	int ru, nss, max_nss = 1, max_ru = 3;
360*4882a593Smuzhiyun 	u8 bit = 7, ru_bit_mask = 0x7;
361*4882a593Smuzhiyun 	u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	he_ppet[0] = max_nss & IEEE80211_PPE_THRES_NSS_MASK;
364*4882a593Smuzhiyun 	he_ppet[0] |= (ru_bit_mask <<
365*4882a593Smuzhiyun 		       IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS) &
366*4882a593Smuzhiyun 			IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	for (nss = 0; nss <= max_nss; nss++) {
369*4882a593Smuzhiyun 		for (ru = 0; ru < max_ru; ru++) {
370*4882a593Smuzhiyun 			u8 val;
371*4882a593Smuzhiyun 			int i;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 			if (!(ru_bit_mask & BIT(ru)))
374*4882a593Smuzhiyun 				continue;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 			val = (ppet16_ppet8_ru3_ru0[nss] >> (ru * 6)) &
377*4882a593Smuzhiyun 			       0x3f;
378*4882a593Smuzhiyun 			val = ((val >> 3) & 0x7) | ((val & 0x7) << 3);
379*4882a593Smuzhiyun 			for (i = 5; i >= 0; i--) {
380*4882a593Smuzhiyun 				he_ppet[bit / 8] |=
381*4882a593Smuzhiyun 					((val >> i) & 0x1) << ((bit % 8));
382*4882a593Smuzhiyun 				bit++;
383*4882a593Smuzhiyun 			}
384*4882a593Smuzhiyun 		}
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun static int
mt7915_init_he_caps(struct mt7915_phy * phy,enum nl80211_band band,struct ieee80211_sband_iftype_data * data)389*4882a593Smuzhiyun mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
390*4882a593Smuzhiyun 		    struct ieee80211_sband_iftype_data *data)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	int i, idx = 0;
393*4882a593Smuzhiyun 	int nss = hweight8(phy->chainmask);
394*4882a593Smuzhiyun 	u16 mcs_map = 0;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
397*4882a593Smuzhiyun 		if (i < nss)
398*4882a593Smuzhiyun 			mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
399*4882a593Smuzhiyun 		else
400*4882a593Smuzhiyun 			mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
401*4882a593Smuzhiyun 	}
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
404*4882a593Smuzhiyun 		struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
405*4882a593Smuzhiyun 		struct ieee80211_he_cap_elem *he_cap_elem =
406*4882a593Smuzhiyun 				&he_cap->he_cap_elem;
407*4882a593Smuzhiyun 		struct ieee80211_he_mcs_nss_supp *he_mcs =
408*4882a593Smuzhiyun 				&he_cap->he_mcs_nss_supp;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 		switch (i) {
411*4882a593Smuzhiyun 		case NL80211_IFTYPE_STATION:
412*4882a593Smuzhiyun 		case NL80211_IFTYPE_AP:
413*4882a593Smuzhiyun #ifdef CONFIG_MAC80211_MESH
414*4882a593Smuzhiyun 		case NL80211_IFTYPE_MESH_POINT:
415*4882a593Smuzhiyun #endif
416*4882a593Smuzhiyun 			break;
417*4882a593Smuzhiyun 		default:
418*4882a593Smuzhiyun 			continue;
419*4882a593Smuzhiyun 		}
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 		data[idx].types_mask = BIT(i);
422*4882a593Smuzhiyun 		he_cap->has_he = true;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 		he_cap_elem->mac_cap_info[0] =
425*4882a593Smuzhiyun 			IEEE80211_HE_MAC_CAP0_HTC_HE;
426*4882a593Smuzhiyun 		he_cap_elem->mac_cap_info[3] =
427*4882a593Smuzhiyun 			IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
428*4882a593Smuzhiyun 			IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_RESERVED;
429*4882a593Smuzhiyun 		he_cap_elem->mac_cap_info[4] =
430*4882a593Smuzhiyun 			IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 		if (band == NL80211_BAND_2GHZ)
433*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[0] =
434*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
435*4882a593Smuzhiyun 		else if (band == NL80211_BAND_5GHZ)
436*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[0] =
437*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
438*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
439*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 		he_cap_elem->phy_cap_info[1] =
442*4882a593Smuzhiyun 			IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
443*4882a593Smuzhiyun 		he_cap_elem->phy_cap_info[2] =
444*4882a593Smuzhiyun 			IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
445*4882a593Smuzhiyun 			IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 		switch (i) {
448*4882a593Smuzhiyun 		case NL80211_IFTYPE_AP:
449*4882a593Smuzhiyun 			he_cap_elem->mac_cap_info[0] |=
450*4882a593Smuzhiyun 				IEEE80211_HE_MAC_CAP0_TWT_RES;
451*4882a593Smuzhiyun 			he_cap_elem->mac_cap_info[2] |=
452*4882a593Smuzhiyun 				IEEE80211_HE_MAC_CAP2_BSR;
453*4882a593Smuzhiyun 			he_cap_elem->mac_cap_info[4] |=
454*4882a593Smuzhiyun 				IEEE80211_HE_MAC_CAP4_BQR;
455*4882a593Smuzhiyun 			he_cap_elem->mac_cap_info[5] |=
456*4882a593Smuzhiyun 				IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;
457*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[3] |=
458*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
459*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
460*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[6] |=
461*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
462*4882a593Smuzhiyun 			break;
463*4882a593Smuzhiyun 		case NL80211_IFTYPE_STATION:
464*4882a593Smuzhiyun 			he_cap_elem->mac_cap_info[0] |=
465*4882a593Smuzhiyun 				IEEE80211_HE_MAC_CAP0_TWT_REQ;
466*4882a593Smuzhiyun 			he_cap_elem->mac_cap_info[1] |=
467*4882a593Smuzhiyun 				IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 			if (band == NL80211_BAND_2GHZ)
470*4882a593Smuzhiyun 				he_cap_elem->phy_cap_info[0] |=
471*4882a593Smuzhiyun 					IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;
472*4882a593Smuzhiyun 			else if (band == NL80211_BAND_5GHZ)
473*4882a593Smuzhiyun 				he_cap_elem->phy_cap_info[0] |=
474*4882a593Smuzhiyun 					IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[1] |=
477*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
478*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US;
479*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[3] |=
480*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
481*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
482*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[6] |=
483*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
484*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
485*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
486*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[7] |=
487*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR |
488*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
489*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[8] |=
490*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
491*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
492*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
493*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;
494*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[9] |=
495*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
496*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
497*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
498*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
499*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
500*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
501*4882a593Smuzhiyun 			break;
502*4882a593Smuzhiyun 		}
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 		he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
505*4882a593Smuzhiyun 		he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
506*4882a593Smuzhiyun 		he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map);
507*4882a593Smuzhiyun 		he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map);
508*4882a593Smuzhiyun 		he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map);
509*4882a593Smuzhiyun 		he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map);
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 		mt7915_set_stream_he_txbf_caps(he_cap, i, nss);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 		memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
514*4882a593Smuzhiyun 		if (he_cap_elem->phy_cap_info[6] &
515*4882a593Smuzhiyun 		    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
516*4882a593Smuzhiyun 			mt7915_gen_ppe_thresh(he_cap->ppe_thres);
517*4882a593Smuzhiyun 		} else {
518*4882a593Smuzhiyun 			he_cap_elem->phy_cap_info[9] |=
519*4882a593Smuzhiyun 				IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US;
520*4882a593Smuzhiyun 		}
521*4882a593Smuzhiyun 		idx++;
522*4882a593Smuzhiyun 	}
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	return idx;
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun 
mt7915_set_stream_he_caps(struct mt7915_phy * phy)527*4882a593Smuzhiyun void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	struct ieee80211_sband_iftype_data *data;
530*4882a593Smuzhiyun 	struct ieee80211_supported_band *band;
531*4882a593Smuzhiyun 	struct mt76_dev *mdev = &phy->dev->mt76;
532*4882a593Smuzhiyun 	int n;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	if (mdev->cap.has_2ghz) {
535*4882a593Smuzhiyun 		data = phy->iftype[NL80211_BAND_2GHZ];
536*4882a593Smuzhiyun 		n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 		band = &phy->mt76->sband_2g.sband;
539*4882a593Smuzhiyun 		band->iftype_data = data;
540*4882a593Smuzhiyun 		band->n_iftype_data = n;
541*4882a593Smuzhiyun 	}
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	if (mdev->cap.has_5ghz) {
544*4882a593Smuzhiyun 		data = phy->iftype[NL80211_BAND_5GHZ];
545*4882a593Smuzhiyun 		n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 		band = &phy->mt76->sband_5g.sband;
548*4882a593Smuzhiyun 		band->iftype_data = data;
549*4882a593Smuzhiyun 		band->n_iftype_data = n;
550*4882a593Smuzhiyun 	}
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun static void
mt7915_cap_dbdc_enable(struct mt7915_dev * dev)554*4882a593Smuzhiyun mt7915_cap_dbdc_enable(struct mt7915_dev *dev)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun 	dev->mphy.sband_5g.sband.vht_cap.cap &=
557*4882a593Smuzhiyun 			~(IEEE80211_VHT_CAP_SHORT_GI_160 |
558*4882a593Smuzhiyun 			  IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	if (dev->chainmask == 0xf)
561*4882a593Smuzhiyun 		dev->mphy.antenna_mask = dev->chainmask >> 2;
562*4882a593Smuzhiyun 	else
563*4882a593Smuzhiyun 		dev->mphy.antenna_mask = dev->chainmask >> 1;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	dev->phy.chainmask = dev->mphy.antenna_mask;
566*4882a593Smuzhiyun 	dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask;
567*4882a593Smuzhiyun 	dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask;
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	mt76_set_stream_caps(&dev->mphy, true);
570*4882a593Smuzhiyun 	mt7915_set_stream_vht_txbf_caps(&dev->phy);
571*4882a593Smuzhiyun 	mt7915_set_stream_he_caps(&dev->phy);
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun static void
mt7915_cap_dbdc_disable(struct mt7915_dev * dev)575*4882a593Smuzhiyun mt7915_cap_dbdc_disable(struct mt7915_dev *dev)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun 	dev->mphy.sband_5g.sband.vht_cap.cap |=
578*4882a593Smuzhiyun 			IEEE80211_VHT_CAP_SHORT_GI_160 |
579*4882a593Smuzhiyun 			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	dev->mphy.antenna_mask = dev->chainmask;
582*4882a593Smuzhiyun 	dev->phy.chainmask = dev->chainmask;
583*4882a593Smuzhiyun 	dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask;
584*4882a593Smuzhiyun 	dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask;
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 	mt76_set_stream_caps(&dev->mphy, true);
587*4882a593Smuzhiyun 	mt7915_set_stream_vht_txbf_caps(&dev->phy);
588*4882a593Smuzhiyun 	mt7915_set_stream_he_caps(&dev->phy);
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun 
mt7915_register_ext_phy(struct mt7915_dev * dev)591*4882a593Smuzhiyun int mt7915_register_ext_phy(struct mt7915_dev *dev)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_ext_phy(dev);
594*4882a593Smuzhiyun 	struct mt76_phy *mphy;
595*4882a593Smuzhiyun 	int ret;
596*4882a593Smuzhiyun 	bool bound;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	/* TODO: enble DBDC */
599*4882a593Smuzhiyun 	bound = mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5);
600*4882a593Smuzhiyun 	if (!bound)
601*4882a593Smuzhiyun 		return -EINVAL;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))
604*4882a593Smuzhiyun 		return -EINVAL;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	if (phy)
607*4882a593Smuzhiyun 		return 0;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	mt7915_cap_dbdc_enable(dev);
610*4882a593Smuzhiyun 	mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
611*4882a593Smuzhiyun 	if (!mphy)
612*4882a593Smuzhiyun 		return -ENOMEM;
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	phy = mphy->priv;
615*4882a593Smuzhiyun 	phy->dev = dev;
616*4882a593Smuzhiyun 	phy->mt76 = mphy;
617*4882a593Smuzhiyun 	phy->chainmask = dev->chainmask & ~dev->phy.chainmask;
618*4882a593Smuzhiyun 	mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1;
619*4882a593Smuzhiyun 	mt7915_init_wiphy(mphy->hw);
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	INIT_LIST_HEAD(&phy->stats_list);
622*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work);
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	/*
625*4882a593Smuzhiyun 	 * Make the secondary PHY MAC address local without overlapping with
626*4882a593Smuzhiyun 	 * the usual MAC address allocation scheme on multiple virtual interfaces
627*4882a593Smuzhiyun 	 */
628*4882a593Smuzhiyun 	mphy->hw->wiphy->perm_addr[0] |= 2;
629*4882a593Smuzhiyun 	mphy->hw->wiphy->perm_addr[0] ^= BIT(7);
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	/* The second interface does not get any packets unless it has a vif */
632*4882a593Smuzhiyun 	ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	ret = mt76_register_phy(mphy);
635*4882a593Smuzhiyun 	if (ret)
636*4882a593Smuzhiyun 		ieee80211_free_hw(mphy->hw);
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	return ret;
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun 
mt7915_unregister_ext_phy(struct mt7915_dev * dev)641*4882a593Smuzhiyun void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
642*4882a593Smuzhiyun {
643*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_ext_phy(dev);
644*4882a593Smuzhiyun 	struct mt76_phy *mphy = dev->mt76.phy2;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	if (!phy)
647*4882a593Smuzhiyun 		return;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	mt7915_cap_dbdc_disable(dev);
650*4882a593Smuzhiyun 	mt76_unregister_phy(mphy);
651*4882a593Smuzhiyun 	ieee80211_free_hw(mphy->hw);
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun 
mt7915_register_device(struct mt7915_dev * dev)654*4882a593Smuzhiyun int mt7915_register_device(struct mt7915_dev *dev)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun 	struct ieee80211_hw *hw = mt76_hw(dev);
657*4882a593Smuzhiyun 	int ret;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	dev->phy.dev = dev;
660*4882a593Smuzhiyun 	dev->phy.mt76 = &dev->mt76.phy;
661*4882a593Smuzhiyun 	dev->mt76.phy.priv = &dev->phy;
662*4882a593Smuzhiyun 	INIT_LIST_HEAD(&dev->phy.stats_list);
663*4882a593Smuzhiyun 	INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);
664*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&dev->phy.mac_work, mt7915_mac_work);
665*4882a593Smuzhiyun 	INIT_LIST_HEAD(&dev->sta_rc_list);
666*4882a593Smuzhiyun 	INIT_LIST_HEAD(&dev->sta_poll_list);
667*4882a593Smuzhiyun 	spin_lock_init(&dev->sta_poll_lock);
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	init_waitqueue_head(&dev->reset_wait);
670*4882a593Smuzhiyun 	INIT_WORK(&dev->reset_work, mt7915_mac_reset_work);
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	ret = mt7915_init_hardware(dev);
673*4882a593Smuzhiyun 	if (ret)
674*4882a593Smuzhiyun 		return ret;
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	mt7915_init_wiphy(hw);
677*4882a593Smuzhiyun 	dev->mphy.sband_2g.sband.ht_cap.cap |=
678*4882a593Smuzhiyun 			IEEE80211_HT_CAP_LDPC_CODING |
679*4882a593Smuzhiyun 			IEEE80211_HT_CAP_MAX_AMSDU;
680*4882a593Smuzhiyun 	dev->mphy.sband_5g.sband.ht_cap.cap |=
681*4882a593Smuzhiyun 			IEEE80211_HT_CAP_LDPC_CODING |
682*4882a593Smuzhiyun 			IEEE80211_HT_CAP_MAX_AMSDU;
683*4882a593Smuzhiyun 	dev->mphy.sband_5g.sband.vht_cap.cap |=
684*4882a593Smuzhiyun 			IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
685*4882a593Smuzhiyun 			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
686*4882a593Smuzhiyun 	mt7915_cap_dbdc_disable(dev);
687*4882a593Smuzhiyun 	dev->phy.dfs_state = -1;
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 	ret = mt76_register_device(&dev->mt76, true, mt7915_rates,
690*4882a593Smuzhiyun 				   ARRAY_SIZE(mt7915_rates));
691*4882a593Smuzhiyun 	if (ret)
692*4882a593Smuzhiyun 		return ret;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	return mt7915_init_debugfs(dev);
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun 
mt7915_unregister_device(struct mt7915_dev * dev)699*4882a593Smuzhiyun void mt7915_unregister_device(struct mt7915_dev *dev)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun 	struct mt76_txwi_cache *txwi;
702*4882a593Smuzhiyun 	int id;
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	mt7915_unregister_ext_phy(dev);
705*4882a593Smuzhiyun 	mt76_unregister_device(&dev->mt76);
706*4882a593Smuzhiyun 	mt7915_mcu_exit(dev);
707*4882a593Smuzhiyun 	mt7915_dma_cleanup(dev);
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	spin_lock_bh(&dev->token_lock);
710*4882a593Smuzhiyun 	idr_for_each_entry(&dev->token, txwi, id) {
711*4882a593Smuzhiyun 		mt7915_txp_skb_unmap(&dev->mt76, txwi);
712*4882a593Smuzhiyun 		if (txwi->skb) {
713*4882a593Smuzhiyun 			struct ieee80211_hw *hw;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 			hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb);
716*4882a593Smuzhiyun 			ieee80211_free_txskb(hw, txwi->skb);
717*4882a593Smuzhiyun 		}
718*4882a593Smuzhiyun 		mt76_put_txwi(&dev->mt76, txwi);
719*4882a593Smuzhiyun 	}
720*4882a593Smuzhiyun 	spin_unlock_bh(&dev->token_lock);
721*4882a593Smuzhiyun 	idr_destroy(&dev->token);
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	mt76_free_device(&dev->mt76);
724*4882a593Smuzhiyun }
725