Commit | Line | Data |
---|---|---|
0e3d6777 | 1 | // SPDX-License-Identifier: ISC |
7bc04215 FF |
2 | /* |
3 | * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> | |
7bc04215 FF |
4 | */ |
5 | ||
6 | #include <linux/delay.h> | |
7 | #include "mt76x2.h" | |
1613c621 LB |
8 | #include "mcu.h" |
9 | #include "eeprom.h" | |
50b9e8d5 | 10 | #include "../mt76x02_phy.h" |
7bc04215 | 11 | |
7bc04215 | 12 | static bool |
e40803f2 | 13 | mt76x2_phy_tssi_init_cal(struct mt76x02_dev *dev) |
7bc04215 FF |
14 | { |
15 | struct ieee80211_channel *chan = dev->mt76.chandef.chan; | |
16 | u32 flag = 0; | |
17 | ||
4afeb396 | 18 | if (!mt76x2_tssi_enabled(dev)) |
7bc04215 FF |
19 | return false; |
20 | ||
21 | if (mt76x2_channel_silent(dev)) | |
22 | return false; | |
23 | ||
2cb16109 | 24 | if (chan->band == NL80211_BAND_5GHZ) |
7bc04215 FF |
25 | flag |= BIT(0); |
26 | ||
26a9daa6 | 27 | if (mt76x02_ext_pa_enabled(dev, chan->band)) |
7bc04215 FF |
28 | flag |= BIT(8); |
29 | ||
4ece1e0a | 30 | mt76x02_mcu_calibrate(dev, MCU_CAL_TSSI, flag); |
7bc04215 FF |
31 | dev->cal.tssi_cal_done = true; |
32 | return true; | |
33 | } | |
34 | ||
35 | static void | |
e40803f2 | 36 | mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) |
7bc04215 FF |
37 | { |
38 | struct ieee80211_channel *chan = dev->mt76.chandef.chan; | |
39 | bool is_5ghz = chan->band == NL80211_BAND_5GHZ; | |
40 | ||
41 | if (dev->cal.channel_cal_done) | |
42 | return; | |
43 | ||
44 | if (mt76x2_channel_silent(dev)) | |
45 | return; | |
46 | ||
47 | if (!dev->cal.tssi_cal_done) | |
48 | mt76x2_phy_tssi_init_cal(dev); | |
49 | ||
50 | if (!mac_stopped) | |
51 | mt76x2_mac_stop(dev, false); | |
52 | ||
53 | if (is_5ghz) | |
4ece1e0a | 54 | mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 0); |
7bc04215 | 55 | |
4ece1e0a SG |
56 | mt76x02_mcu_calibrate(dev, MCU_CAL_TX_LOFT, is_5ghz); |
57 | mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz); | |
58 | mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQC_FI, is_5ghz); | |
59 | mt76x02_mcu_calibrate(dev, MCU_CAL_TEMP_SENSOR, 0); | |
60 | mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0); | |
7bc04215 FF |
61 | |
62 | if (!mac_stopped) | |
63 | mt76x2_mac_resume(dev); | |
64 | ||
65 | mt76x2_apply_gain_adj(dev); | |
a78f1547 | 66 | mt76x02_edcca_init(dev); |
7bc04215 FF |
67 | |
68 | dev->cal.channel_cal_done = true; | |
69 | } | |
70 | ||
e40803f2 | 71 | void mt76x2_phy_set_antenna(struct mt76x02_dev *dev) |
7bc04215 FF |
72 | { |
73 | u32 val; | |
74 | ||
75 | val = mt76_rr(dev, MT_BBP(AGC, 0)); | |
5ebdc3e0 LB |
76 | val &= ~(BIT(4) | BIT(1)); |
77 | switch (dev->mt76.antenna_mask) { | |
78 | case 1: | |
79 | /* disable mac DAC control */ | |
80 | mt76_clear(dev, MT_BBP(IBI, 9), BIT(11)); | |
81 | mt76_clear(dev, MT_BBP(TXBE, 5), 3); | |
82 | mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0x3); | |
83 | mt76_rmw_field(dev, MT_BBP(CORE, 32), GENMASK(21, 20), 2); | |
84 | /* disable DAC 1 */ | |
85 | mt76_rmw_field(dev, MT_BBP(CORE, 33), GENMASK(12, 9), 4); | |
7bc04215 | 86 | |
5ebdc3e0 LB |
87 | val &= ~(BIT(3) | BIT(0)); |
88 | break; | |
89 | case 2: | |
90 | /* disable mac DAC control */ | |
91 | mt76_clear(dev, MT_BBP(IBI, 9), BIT(11)); | |
92 | mt76_rmw_field(dev, MT_BBP(TXBE, 5), 3, 1); | |
93 | mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0xc); | |
94 | mt76_rmw_field(dev, MT_BBP(CORE, 32), GENMASK(21, 20), 1); | |
95 | /* disable DAC 0 */ | |
96 | mt76_rmw_field(dev, MT_BBP(CORE, 33), GENMASK(12, 9), 1); | |
97 | ||
98 | val &= ~BIT(3); | |
99 | val |= BIT(0); | |
100 | break; | |
101 | case 3: | |
102 | default: | |
103 | /* enable mac DAC control */ | |
104 | mt76_set(dev, MT_BBP(IBI, 9), BIT(11)); | |
105 | mt76_set(dev, MT_BBP(TXBE, 5), 3); | |
106 | mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0xf); | |
107 | mt76_clear(dev, MT_BBP(CORE, 32), GENMASK(21, 20)); | |
108 | mt76_clear(dev, MT_BBP(CORE, 33), GENMASK(12, 9)); | |
7bc04215 | 109 | |
5ebdc3e0 LB |
110 | val &= ~BIT(0); |
111 | val |= BIT(3); | |
112 | break; | |
113 | } | |
7bc04215 FF |
114 | mt76_wr(dev, MT_BBP(AGC, 0), val); |
115 | } | |
116 | ||
e40803f2 | 117 | int mt76x2_phy_set_channel(struct mt76x02_dev *dev, |
7bc04215 FF |
118 | struct cfg80211_chan_def *chandef) |
119 | { | |
120 | struct ieee80211_channel *chan = chandef->chan; | |
121 | bool scan = test_bit(MT76_SCANNING, &dev->mt76.state); | |
122 | enum nl80211_band band = chan->band; | |
123 | u8 channel; | |
124 | ||
125 | u32 ext_cca_chan[4] = { | |
126 | [0] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 0) | | |
127 | FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 1) | | |
128 | FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 2) | | |
129 | FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 3) | | |
130 | FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(0)), | |
131 | [1] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 1) | | |
132 | FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 0) | | |
133 | FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 2) | | |
134 | FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 3) | | |
135 | FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(1)), | |
136 | [2] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 2) | | |
137 | FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 3) | | |
138 | FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 1) | | |
139 | FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | | |
140 | FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(2)), | |
141 | [3] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 3) | | |
142 | FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 2) | | |
143 | FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 1) | | |
144 | FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | | |
145 | FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(3)), | |
146 | }; | |
147 | int ch_group_index; | |
148 | u8 bw, bw_index; | |
149 | int freq, freq1; | |
150 | int ret; | |
7bc04215 FF |
151 | |
152 | dev->cal.channel_cal_done = false; | |
153 | freq = chandef->chan->center_freq; | |
154 | freq1 = chandef->center_freq1; | |
155 | channel = chan->hw_value; | |
156 | ||
157 | switch (chandef->width) { | |
158 | case NL80211_CHAN_WIDTH_40: | |
159 | bw = 1; | |
160 | if (freq1 > freq) { | |
161 | bw_index = 1; | |
162 | ch_group_index = 0; | |
163 | } else { | |
164 | bw_index = 3; | |
165 | ch_group_index = 1; | |
166 | } | |
167 | channel += 2 - ch_group_index * 4; | |
168 | break; | |
169 | case NL80211_CHAN_WIDTH_80: | |
170 | ch_group_index = (freq - freq1 + 30) / 20; | |
171 | if (WARN_ON(ch_group_index < 0 || ch_group_index > 3)) | |
172 | ch_group_index = 0; | |
173 | bw = 2; | |
174 | bw_index = ch_group_index; | |
175 | channel += 6 - ch_group_index * 4; | |
176 | break; | |
177 | default: | |
178 | bw = 0; | |
179 | bw_index = 0; | |
180 | ch_group_index = 0; | |
181 | break; | |
182 | } | |
183 | ||
184 | mt76x2_read_rx_gain(dev); | |
185 | mt76x2_phy_set_txpower_regs(dev, band); | |
186 | mt76x2_configure_tx_delay(dev, band, bw); | |
187 | mt76x2_phy_set_txpower(dev); | |
188 | ||
370c6415 | 189 | mt76x02_phy_set_band(dev, chan->band, ch_group_index & 1); |
032c08f4 | 190 | mt76x02_phy_set_bw(dev, chandef->width, ch_group_index); |
7bc04215 FF |
191 | |
192 | mt76_rmw(dev, MT_EXT_CCA_CFG, | |
193 | (MT_EXT_CCA_CFG_CCA0 | | |
194 | MT_EXT_CCA_CFG_CCA1 | | |
195 | MT_EXT_CCA_CFG_CCA2 | | |
196 | MT_EXT_CCA_CFG_CCA3 | | |
197 | MT_EXT_CCA_CFG_CCA_MASK), | |
198 | ext_cca_chan[ch_group_index]); | |
199 | ||
7bc04215 FF |
200 | ret = mt76x2_mcu_set_channel(dev, channel, bw, bw_index, scan); |
201 | if (ret) | |
202 | return ret; | |
203 | ||
204 | mt76x2_mcu_init_gain(dev, channel, dev->cal.rx.mcu_gain, true); | |
205 | ||
5ebdc3e0 LB |
206 | mt76x2_phy_set_antenna(dev); |
207 | ||
7bc04215 FF |
208 | /* Enable LDPC Rx */ |
209 | if (mt76xx_rev(dev) >= MT76XX_REV_E3) | |
210 | mt76_set(dev, MT_BBP(RXO, 13), BIT(10)); | |
211 | ||
212 | if (!dev->cal.init_cal_done) { | |
26a9daa6 | 213 | u8 val = mt76x02_eeprom_get(dev, MT_EE_BT_RCAL_RESULT); |
7bc04215 FF |
214 | |
215 | if (val != 0xff) | |
4ece1e0a | 216 | mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0); |
7bc04215 FF |
217 | } |
218 | ||
4ece1e0a | 219 | mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, channel); |
7bc04215 FF |
220 | |
221 | /* Rx LPF calibration */ | |
222 | if (!dev->cal.init_cal_done) | |
4ece1e0a | 223 | mt76x02_mcu_calibrate(dev, MCU_CAL_RC, 0); |
7bc04215 FF |
224 | |
225 | dev->cal.init_cal_done = true; | |
226 | ||
227 | mt76_wr(dev, MT_BBP(AGC, 61), 0xFF64A4E2); | |
228 | mt76_wr(dev, MT_BBP(AGC, 7), 0x08081010); | |
229 | mt76_wr(dev, MT_BBP(AGC, 11), 0x00000404); | |
230 | mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); | |
231 | mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F); | |
232 | ||
4606a26c | 233 | if (scan) |
7bc04215 FF |
234 | return 0; |
235 | ||
7bc04215 | 236 | mt76x2_phy_channel_calibrate(dev, true); |
e48797e9 | 237 | mt76x02_init_agc_gain(dev); |
7bc04215 | 238 | |
b9e5d4fe | 239 | /* init default values for temp compensation */ |
4afeb396 | 240 | if (mt76x2_tssi_enabled(dev)) { |
b9e5d4fe LB |
241 | mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, |
242 | 0x38); | |
243 | mt76_rmw_field(dev, MT_TX_ALC_CFG_2, MT_TX_ALC_CFG_2_TEMP_COMP, | |
244 | 0x38); | |
245 | } | |
246 | ||
7bc04215 FF |
247 | ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, |
248 | MT_CALIBRATE_INTERVAL); | |
249 | ||
250 | return 0; | |
251 | } | |
252 | ||
7bc04215 | 253 | static void |
e40803f2 | 254 | mt76x2_phy_temp_compensate(struct mt76x02_dev *dev) |
7bc04215 FF |
255 | { |
256 | struct mt76x2_temp_comp t; | |
257 | int temp, db_diff; | |
258 | ||
259 | if (mt76x2_get_temp_comp(dev, &t)) | |
260 | return; | |
261 | ||
262 | temp = mt76_get_field(dev, MT_TEMP_SENSOR, MT_TEMP_SENSOR_VAL); | |
263 | temp -= t.temp_25_ref; | |
264 | temp = (temp * 1789) / 1000 + 25; | |
265 | dev->cal.temp = temp; | |
266 | ||
267 | if (temp > 25) | |
268 | db_diff = (temp - 25) / t.high_slope; | |
269 | else | |
270 | db_diff = (25 - temp) / t.low_slope; | |
271 | ||
272 | db_diff = min(db_diff, t.upper_bound); | |
273 | db_diff = max(db_diff, t.lower_bound); | |
274 | ||
275 | mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, | |
276 | db_diff * 2); | |
277 | mt76_rmw_field(dev, MT_TX_ALC_CFG_2, MT_TX_ALC_CFG_2_TEMP_COMP, | |
278 | db_diff * 2); | |
279 | } | |
280 | ||
281 | void mt76x2_phy_calibrate(struct work_struct *work) | |
282 | { | |
e40803f2 | 283 | struct mt76x02_dev *dev; |
7bc04215 | 284 | |
e40803f2 | 285 | dev = container_of(work, struct mt76x02_dev, cal_work.work); |
8aac454d LB |
286 | |
287 | mutex_lock(&dev->mt76.mutex); | |
288 | ||
7bc04215 | 289 | mt76x2_phy_channel_calibrate(dev, false); |
4ece1e0a | 290 | mt76x2_phy_tssi_compensate(dev); |
7bc04215 FF |
291 | mt76x2_phy_temp_compensate(dev); |
292 | mt76x2_phy_update_channel_gain(dev); | |
8aac454d LB |
293 | |
294 | mutex_unlock(&dev->mt76.mutex); | |
295 | ||
7bc04215 FF |
296 | ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, |
297 | MT_CALIBRATE_INTERVAL); | |
298 | } | |
299 | ||
e40803f2 | 300 | int mt76x2_phy_start(struct mt76x02_dev *dev) |
7bc04215 FF |
301 | { |
302 | int ret; | |
303 | ||
c6950536 | 304 | ret = mt76x02_mcu_set_radio_state(dev, true); |
7bc04215 FF |
305 | if (ret) |
306 | return ret; | |
307 | ||
308 | mt76x2_mcu_load_cr(dev, MT_RF_BBP_CR, 0, 0); | |
309 | ||
310 | return ret; | |
311 | } |