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