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