1 /* 2 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "mt76x2u.h" 18 #include "eeprom.h" 19 #include "../mt76x02_phy.h" 20 21 void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev) 22 { 23 struct ieee80211_channel *chan = dev->mt76.chandef.chan; 24 bool is_5ghz = chan->band == NL80211_BAND_5GHZ; 25 26 if (mt76x2_channel_silent(dev)) 27 return; 28 29 mt76x2u_mac_stop(dev); 30 31 if (is_5ghz) 32 mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 0, false); 33 34 mt76x02_mcu_calibrate(dev, MCU_CAL_TX_LOFT, is_5ghz, false); 35 mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz, false); 36 mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQC_FI, is_5ghz, false); 37 mt76x02_mcu_calibrate(dev, MCU_CAL_TEMP_SENSOR, 0, false); 38 39 mt76x2u_mac_resume(dev); 40 } 41 42 static void 43 mt76x2u_phy_update_channel_gain(struct mt76x02_dev *dev) 44 { 45 u8 channel = dev->mt76.chandef.chan->hw_value; 46 int freq, freq1; 47 u32 false_cca; 48 49 freq = dev->mt76.chandef.chan->center_freq; 50 freq1 = dev->mt76.chandef.center_freq1; 51 52 switch (dev->mt76.chandef.width) { 53 case NL80211_CHAN_WIDTH_80: { 54 int ch_group_index; 55 56 ch_group_index = (freq - freq1 + 30) / 20; 57 if (WARN_ON(ch_group_index < 0 || ch_group_index > 3)) 58 ch_group_index = 0; 59 channel += 6 - ch_group_index * 4; 60 break; 61 } 62 case NL80211_CHAN_WIDTH_40: 63 if (freq1 > freq) 64 channel += 2; 65 else 66 channel -= 2; 67 break; 68 default: 69 break; 70 } 71 72 dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); 73 false_cca = FIELD_GET(MT_RX_STAT_1_CCA_ERRORS, 74 mt76_rr(dev, MT_RX_STAT_1)); 75 76 mt76x2u_mcu_set_dynamic_vga(dev, channel, false, false, 77 dev->cal.avg_rssi_all, false_cca); 78 } 79 80 void mt76x2u_phy_calibrate(struct work_struct *work) 81 { 82 struct mt76x02_dev *dev; 83 84 dev = container_of(work, struct mt76x02_dev, cal_work.work); 85 mt76x2_phy_tssi_compensate(dev, false); 86 mt76x2u_phy_update_channel_gain(dev); 87 88 ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, 89 MT_CALIBRATE_INTERVAL); 90 } 91 92 int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, 93 struct cfg80211_chan_def *chandef) 94 { 95 u32 ext_cca_chan[4] = { 96 [0] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 0) | 97 FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 1) | 98 FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 2) | 99 FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 3) | 100 FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(0)), 101 [1] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 1) | 102 FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 0) | 103 FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 2) | 104 FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 3) | 105 FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(1)), 106 [2] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 2) | 107 FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 3) | 108 FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 1) | 109 FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | 110 FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(2)), 111 [3] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 3) | 112 FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 2) | 113 FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 1) | 114 FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | 115 FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(3)), 116 }; 117 bool scan = test_bit(MT76_SCANNING, &dev->mt76.state); 118 struct ieee80211_channel *chan = chandef->chan; 119 u8 channel = chan->hw_value, bw, bw_index; 120 int ch_group_index, freq, freq1, ret; 121 122 dev->cal.channel_cal_done = false; 123 freq = chandef->chan->center_freq; 124 freq1 = chandef->center_freq1; 125 126 switch (chandef->width) { 127 case NL80211_CHAN_WIDTH_40: 128 bw = 1; 129 if (freq1 > freq) { 130 bw_index = 1; 131 ch_group_index = 0; 132 } else { 133 bw_index = 3; 134 ch_group_index = 1; 135 } 136 channel += 2 - ch_group_index * 4; 137 break; 138 case NL80211_CHAN_WIDTH_80: 139 ch_group_index = (freq - freq1 + 30) / 20; 140 if (WARN_ON(ch_group_index < 0 || ch_group_index > 3)) 141 ch_group_index = 0; 142 bw = 2; 143 bw_index = ch_group_index; 144 channel += 6 - ch_group_index * 4; 145 break; 146 default: 147 bw = 0; 148 bw_index = 0; 149 ch_group_index = 0; 150 break; 151 } 152 153 mt76x2_read_rx_gain(dev); 154 mt76x2_phy_set_txpower_regs(dev, chan->band); 155 mt76x2_configure_tx_delay(dev, chan->band, bw); 156 mt76x2_phy_set_txpower(dev); 157 158 mt76x02_phy_set_band(dev, chan->band, ch_group_index & 1); 159 mt76x02_phy_set_bw(dev, chandef->width, ch_group_index); 160 161 mt76_rmw(dev, MT_EXT_CCA_CFG, 162 (MT_EXT_CCA_CFG_CCA0 | 163 MT_EXT_CCA_CFG_CCA1 | 164 MT_EXT_CCA_CFG_CCA2 | 165 MT_EXT_CCA_CFG_CCA3 | 166 MT_EXT_CCA_CFG_CCA_MASK), 167 ext_cca_chan[ch_group_index]); 168 169 ret = mt76x2_mcu_set_channel(dev, channel, bw, bw_index, scan); 170 if (ret) 171 return ret; 172 173 mt76x2_mcu_init_gain(dev, channel, dev->cal.rx.mcu_gain, true); 174 175 /* Enable LDPC Rx */ 176 if (mt76xx_rev(dev) >= MT76XX_REV_E3) 177 mt76_set(dev, MT_BBP(RXO, 13), BIT(10)); 178 179 if (!dev->cal.init_cal_done) { 180 u8 val = mt76x02_eeprom_get(dev, MT_EE_BT_RCAL_RESULT); 181 182 if (val != 0xff) 183 mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, false); 184 } 185 186 mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, channel, false); 187 188 /* Rx LPF calibration */ 189 if (!dev->cal.init_cal_done) 190 mt76x02_mcu_calibrate(dev, MCU_CAL_RC, 0, false); 191 dev->cal.init_cal_done = true; 192 193 mt76_wr(dev, MT_BBP(AGC, 61), 0xff64a4e2); 194 mt76_wr(dev, MT_BBP(AGC, 7), 0x08081010); 195 mt76_wr(dev, MT_BBP(AGC, 11), 0x00000404); 196 mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); 197 mt76_wr(dev, MT_TXOP_CTRL_CFG, 0X04101b3f); 198 199 mt76_set(dev, MT_BBP(TXO, 4), BIT(25)); 200 mt76_set(dev, MT_BBP(RXO, 13), BIT(8)); 201 202 if (scan) 203 return 0; 204 205 if (mt76x2_tssi_enabled(dev)) { 206 /* init default values for temp compensation */ 207 mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, 208 0x38); 209 mt76_rmw_field(dev, MT_TX_ALC_CFG_2, MT_TX_ALC_CFG_2_TEMP_COMP, 210 0x38); 211 212 /* init tssi calibration */ 213 if (!mt76x2_channel_silent(dev)) { 214 struct ieee80211_channel *chan; 215 u32 flag = 0; 216 217 chan = dev->mt76.chandef.chan; 218 if (chan->band == NL80211_BAND_5GHZ) 219 flag |= BIT(0); 220 if (mt76x02_ext_pa_enabled(dev, chan->band)) 221 flag |= BIT(8); 222 mt76x02_mcu_calibrate(dev, MCU_CAL_TSSI, flag, false); 223 dev->cal.tssi_cal_done = true; 224 } 225 } 226 227 ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, 228 MT_CALIBRATE_INTERVAL); 229 return 0; 230 } 231