1 /*- 2 * Copyright (c) 2016-2019 Andriy Voskoboinyk <avos@FreeBSD.org> 3 * 4 * Permission to use, copy, modify, and 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 <sys/cdefs.h> 18 #include "opt_wlan.h" 19 20 #include <sys/param.h> 21 #include <sys/lock.h> 22 #include <sys/mutex.h> 23 #include <sys/mbuf.h> 24 #include <sys/kernel.h> 25 #include <sys/socket.h> 26 #include <sys/systm.h> 27 #include <sys/malloc.h> 28 #include <sys/queue.h> 29 #include <sys/taskqueue.h> 30 #include <sys/bus.h> 31 #include <sys/endian.h> 32 #include <sys/linker.h> 33 34 #include <net/if.h> 35 #include <net/ethernet.h> 36 #include <net/if_media.h> 37 38 #include <net80211/ieee80211_var.h> 39 #include <net80211/ieee80211_radiotap.h> 40 41 #include <dev/rtwn/if_rtwnreg.h> 42 #include <dev/rtwn/if_rtwnvar.h> 43 #include <dev/rtwn/if_rtwn_debug.h> 44 45 #include <dev/rtwn/rtl8188e/r88e.h> 46 #include <dev/rtwn/rtl8188e/r88e_reg.h> 47 48 /* Registers to save and restore during IQ calibration. */ 49 struct r88e_iq_cal_reg_vals { 50 uint32_t adda[16]; 51 uint8_t txpause; 52 uint8_t bcn_ctrl[2]; 53 uint32_t gpio_muxcfg; 54 uint32_t cck0_afesetting; 55 uint32_t ofdm0_trxpathena; 56 uint32_t ofdm0_trmuxpar; 57 uint32_t fpga0_rfifacesw0; 58 uint32_t fpga0_rfifacesw1; 59 uint32_t fpga0_rfifaceoe0; 60 uint32_t fpga0_rfifaceoe1; 61 uint32_t config_ant0; 62 uint32_t config_ant1; 63 }; 64 65 static int 66 r88e_iq_calib_chain(struct rtwn_softc *sc, uint16_t tx[2], uint16_t rx[2]) 67 { 68 uint32_t status; 69 70 /* Set Rx IQ calibration mode table. */ 71 rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); 72 rtwn_rf_write(sc, 0, R88E_RF_WE_LUT, 0x800a0); 73 rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000); 74 rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xf); 75 rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf117b); 76 rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); 77 78 /* IQ calibration settings. */ 79 rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00); 80 rtwn_bb_write(sc, R92C_RX_IQK, 0x81004800); 81 82 /* IQ calibration settings for chain 0. */ 83 rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1c); 84 rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x30008c1c); 85 rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160804); 86 rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160000); 87 88 /* LO calibration settings. */ 89 rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911); 90 91 /* We're doing LO and IQ calibration in one shot. */ 92 rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000); 93 rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000); 94 95 /* Give LO and IQ calibrations the time to complete. */ 96 rtwn_delay(sc, 10000); 97 98 /* Read IQ calibration status. */ 99 status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0)); 100 if (status & (1 << 28)) 101 return (0); /* Tx failed. */ 102 103 /* Read Tx IQ calibration results. */ 104 tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(0)), 105 R92C_POWER_IQK_RESULT); 106 tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(0)), 107 R92C_POWER_IQK_RESULT); 108 if (tx[0] == 0x142 || tx[1] == 0x042) 109 return (0); /* Tx failed. */ 110 111 rtwn_bb_write(sc, R92C_TX_IQK, 0x80007c00 | (tx[0] << 16) | tx[1]); 112 113 /* Set Rx IQ calibration mode table. */ 114 rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); 115 rtwn_rf_write(sc, 0, R88E_RF_WE_LUT, 0x800a0); 116 rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000); 117 rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xf); 118 rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7ffa); 119 rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); 120 121 /* IQ calibration settings. */ 122 rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800); 123 124 /* IQ calibration settings for chain 0. */ 125 rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x30008c1c); 126 rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1c); 127 rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160c05); 128 rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160c05); 129 130 /* LO calibration settings. */ 131 rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911); 132 133 /* We're doing LO and IQ calibration in one shot. */ 134 rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000); 135 rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000); 136 137 /* Give LO and IQ calibrations the time to complete. */ 138 rtwn_delay(sc, 10000); 139 140 /* Read IQ calibration status. */ 141 status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0)); 142 if (status & (1 << 27)) 143 return (1); /* Rx failed. */ 144 145 /* Read Rx IQ calibration results. */ 146 rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(0)), 147 R92C_POWER_IQK_RESULT); 148 rx[1] = MS(status, R92C_POWER_IQK_RESULT); 149 if (rx[0] == 0x132 || rx[1] == 0x036) 150 return (1); /* Rx failed. */ 151 152 return (3); /* Both Tx and Rx succeeded. */ 153 } 154 155 static void 156 r88e_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2], 157 uint16_t rx[2], struct r88e_iq_cal_reg_vals *vals) 158 { 159 /* Registers to save and restore during IQ calibration. */ 160 static const uint16_t reg_adda[16] = { 161 0x85c, 0xe6c, 0xe70, 0xe74, 162 0xe78, 0xe7c, 0xe80, 0xe84, 163 0xe88, 0xe8c, 0xed0, 0xed4, 164 0xed8, 0xedc, 0xee0, 0xeec 165 }; 166 int i; 167 uint32_t hssi_param1; 168 169 if (n == 0) { 170 for (i = 0; i < nitems(reg_adda); i++) 171 vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]); 172 173 vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE); 174 vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0)); 175 vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1)); 176 vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG); 177 } 178 179 rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0); 180 for (i = 1; i < nitems(reg_adda); i++) 181 rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0); 182 183 hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0)); 184 if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { 185 rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), 186 hssi_param1 | R92C_HSSI_PARAM1_PI); 187 rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), 188 hssi_param1 | R92C_HSSI_PARAM1_PI); 189 } 190 191 if (n == 0) { 192 vals->cck0_afesetting = rtwn_bb_read(sc, R92C_CCK0_AFESETTING); 193 vals->ofdm0_trxpathena = 194 rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); 195 vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR); 196 vals->fpga0_rfifacesw0 = 197 rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0)); 198 vals->fpga0_rfifacesw1 = 199 rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1)); 200 vals->fpga0_rfifaceoe0 = 201 rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0)); 202 vals->fpga0_rfifaceoe1 = 203 rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(1)); 204 vals->config_ant0 = rtwn_bb_read(sc, R92C_CONFIG_ANT(0)); 205 vals->config_ant1 = rtwn_bb_read(sc, R92C_CONFIG_ANT(1)); 206 } 207 208 rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0, 0x0f000000); 209 rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600); 210 rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4); 211 rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000); 212 rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0, 0x04000400); 213 rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0x400, 0); 214 rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(1), 0x400, 0); 215 216 rtwn_write_1(sc, R92C_TXPAUSE, 217 R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH); 218 rtwn_write_1(sc, R92C_BCN_CTRL(0), 219 vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN); 220 rtwn_write_1(sc, R92C_BCN_CTRL(1), 221 vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN); 222 rtwn_write_1(sc, R92C_GPIO_MUXCFG, 223 vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT); 224 225 rtwn_bb_write(sc, R92C_CONFIG_ANT(0), 0x0f600000); 226 227 rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); 228 rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00); 229 rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800); 230 231 /* Run IQ calibration twice. */ 232 for (i = 0; i < 2; i++) { 233 int ret; 234 235 ret = r88e_iq_calib_chain(sc, tx, rx); 236 if (ret == 0) { 237 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Tx failed.\n", 238 __func__); 239 tx[0] = 0xff; 240 tx[1] = 0xff; 241 rx[0] = 0xff; 242 rx[1] = 0xff; 243 } else if (ret == 1) { 244 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Rx failed.\n", 245 __func__); 246 rx[0] = 0xff; 247 rx[1] = 0xff; 248 } else if (ret == 3) { 249 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Both Tx and Rx" 250 " succeeded.\n", __func__); 251 } 252 } 253 254 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, 255 "%s: results for run %d: tx[0] 0x%x, tx[1] 0x%x, rx[0] 0x%x, " 256 "rx[1] 0x%x\n", __func__, n, tx[0], tx[1], rx[0], rx[1]); 257 258 rtwn_bb_write(sc, R92C_CCK0_AFESETTING, vals->cck0_afesetting); 259 rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, vals->ofdm0_trxpathena); 260 rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0), vals->fpga0_rfifacesw0); 261 rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), vals->fpga0_rfifacesw1); 262 rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar); 263 rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0), vals->fpga0_rfifaceoe0); 264 rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1), vals->fpga0_rfifaceoe1); 265 rtwn_bb_write(sc, R92C_CONFIG_ANT(0), vals->config_ant0); 266 rtwn_bb_write(sc, R92C_CONFIG_ANT(1), vals->config_ant1); 267 268 rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); 269 rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3); 270 271 if (n != 0) { 272 if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { 273 rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1); 274 rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1); 275 } 276 277 for (i = 0; i < nitems(reg_adda); i++) 278 rtwn_bb_write(sc, reg_adda[i], vals->adda[i]); 279 280 rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause); 281 rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]); 282 rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]); 283 rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg); 284 } 285 } 286 287 #define RTWN_IQ_CAL_MAX_TOLERANCE 5 288 static int 289 r88e_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2], 290 uint16_t rx1[2], uint16_t tx2[2], uint16_t rx2[2]) 291 { 292 int i, tx_ok, rx_ok; 293 294 tx_ok = rx_ok = 0; 295 for (i = 0; i < 2; i++) { 296 if (tx1[i] == 0xff || tx2[i] == 0xff || 297 rx1[i] == 0xff || rx2[i] == 0xff) 298 continue; 299 300 tx_ok = (abs(tx1[i] - tx2[i]) <= RTWN_IQ_CAL_MAX_TOLERANCE); 301 rx_ok = (abs(rx1[i] - rx2[i]) <= RTWN_IQ_CAL_MAX_TOLERANCE); 302 } 303 304 return (tx_ok && rx_ok); 305 } 306 #undef RTWN_IQ_CAL_MAX_TOLERANCE 307 308 static void 309 r88e_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2], 310 uint16_t rx[2]) 311 { 312 uint32_t reg, val, x; 313 long y, tx_c; 314 315 if (tx[0] == 0xff || tx[1] == 0xff) 316 return; 317 318 reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0)); 319 val = ((reg >> 22) & 0x3ff); 320 x = tx[0]; 321 if (x & 0x00000200) 322 x |= 0xfffffc00; 323 reg = (((x * val) >> 8) & 0x3ff); 324 rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x3ff, reg); 325 rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000, 326 ((x * val) & 0x80) << 24); 327 328 y = tx[1]; 329 if (y & 0x00000200) 330 y |= 0xfffffc00; 331 tx_c = (y * val) >> 8; 332 rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(0), 0xf0000000, 333 (tx_c & 0x3c0) << 22); 334 rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x003f0000, 335 (tx_c & 0x3f) << 16); 336 rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000, 337 ((y * val) & 0x80) << 22); 338 339 if (rx[0] == 0xff || rx[1] == 0xff) 340 return; 341 342 rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0x3ff, 343 rx[0] & 0x3ff); 344 rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0xfc00, 345 (rx[1] & 0x3f) << 10); 346 rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000, 347 (rx[1] & 0x3c0) << 22); 348 } 349 350 #define RTWN_IQ_CAL_NRUN 3 351 void 352 r88e_iq_calib(struct rtwn_softc *sc) 353 { 354 struct r88e_iq_cal_reg_vals vals; 355 uint16_t tx[RTWN_IQ_CAL_NRUN][2], rx[RTWN_IQ_CAL_NRUN][2]; 356 int n, valid; 357 358 KASSERT(sc->ntxchains == 1, 359 ("%s: only 1T1R configuration is supported!\n", __func__)); 360 361 valid = 0; 362 for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) { 363 r88e_iq_calib_run(sc, n, tx[n], rx[n], &vals); 364 365 if (n == 0) 366 continue; 367 368 /* Valid results remain stable after consecutive runs. */ 369 valid = r88e_iq_calib_compare_results(sc, tx[n - 1], 370 rx[n - 1], tx[n], rx[n]); 371 if (valid) 372 break; 373 } 374 375 if (valid) 376 r88e_iq_calib_write_results(sc, tx[n], rx[n]); 377 } 378 #undef RTWN_IQ_CAL_NRUN 379 380 void 381 r88e_temp_measure(struct rtwn_softc *sc) 382 { 383 rtwn_rf_write(sc, 0, R88E_RF_T_METER, R88E_RF_T_METER_START); 384 } 385 386 uint8_t 387 r88e_temp_read(struct rtwn_softc *sc) 388 { 389 return (MS(rtwn_rf_read(sc, 0, R88E_RF_T_METER), 390 R88E_RF_T_METER_VAL)); 391 } 392