The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/rtwn/rtl8192c/r92c_calib.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
    5  * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
    6  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
    7  *
    8  * Permission to use, copy, modify, and distribute this software for any
    9  * purpose with or without fee is hereby granted, provided that the above
   10  * copyright notice and this permission notice appear in all copies.
   11  *
   12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   19  */
   20 
   21 #include <sys/cdefs.h>
   22 __FBSDID("$FreeBSD$");
   23 
   24 #include "opt_wlan.h"
   25 
   26 #include <sys/param.h>
   27 #include <sys/lock.h>
   28 #include <sys/mutex.h>
   29 #include <sys/mbuf.h>
   30 #include <sys/kernel.h>
   31 #include <sys/socket.h>
   32 #include <sys/systm.h>
   33 #include <sys/malloc.h>
   34 #include <sys/queue.h>
   35 #include <sys/taskqueue.h>
   36 #include <sys/bus.h>
   37 #include <sys/endian.h>
   38 #include <sys/linker.h>
   39 
   40 #include <net/if.h>
   41 #include <net/ethernet.h>
   42 #include <net/if_media.h>
   43 
   44 #include <net80211/ieee80211_var.h>
   45 #include <net80211/ieee80211_radiotap.h>
   46 
   47 #include <dev/rtwn/if_rtwnreg.h>
   48 #include <dev/rtwn/if_rtwnvar.h>
   49 #include <dev/rtwn/if_rtwn_debug.h>
   50 
   51 #include <dev/rtwn/rtl8192c/r92c.h>
   52 #include <dev/rtwn/rtl8192c/r92c_reg.h>
   53 
   54 /* Registers to save and restore during IQ calibration. */
   55 struct r92c_iq_cal_reg_vals {
   56         uint32_t        adda[16];
   57         uint8_t         txpause;
   58         uint8_t         bcn_ctrl[2];
   59         uint32_t        gpio_muxcfg;
   60         uint32_t        cck0_afesetting;
   61         uint32_t        ofdm0_trxpathena;
   62         uint32_t        ofdm0_trmuxpar;
   63         uint32_t        fpga0_rfifacesw0;
   64         uint32_t        fpga0_rfifacesw1;
   65         uint32_t        fpga0_rfifaceoe0;
   66         uint32_t        fpga0_rfifaceoe1;
   67         uint32_t        config_ant0;
   68         uint32_t        config_ant1;
   69 };
   70 
   71 /* XXX TODO: merge */
   72 static int
   73 r92c_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
   74     uint16_t rx[2])
   75 {
   76         uint32_t status;
   77 
   78         if (chain == 0) {       /* IQ calibration for chain 0. */
   79                 /* IQ calibration settings for chain 0. */
   80                 rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1f);
   81                 rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1f);
   82                 rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82140102);
   83 
   84                 if (sc->ntxchains > 1) {
   85                         rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160202);
   86                         /* IQ calibration settings for chain 1. */
   87                         rtwn_bb_write(sc, R92C_TX_IQK_TONE(1), 0x10008c22);
   88                         rtwn_bb_write(sc, R92C_RX_IQK_TONE(1), 0x10008c22);
   89                         rtwn_bb_write(sc, R92C_TX_IQK_PI(1), 0x82140102);
   90                         rtwn_bb_write(sc, R92C_RX_IQK_PI(1), 0x28160202);
   91                 } else
   92                         rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160502);
   93 
   94                 /* LO calibration settings. */
   95                 rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x001028d1);
   96                 /* We're doing LO and IQ calibration in one shot. */
   97                 rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
   98                 rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
   99 
  100         } else {                /* IQ calibration for chain 1. */
  101                 /* We're doing LO and IQ calibration in one shot. */
  102                 rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 2);
  103                 rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 0);
  104         }
  105 
  106         /* Give LO and IQ calibrations the time to complete. */
  107         rtwn_delay(sc, 10000);
  108 
  109         /* Read IQ calibration status. */
  110         status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
  111 
  112         if (status & (1 << (28 + chain * 3)))
  113                 return (0);     /* Tx failed. */
  114         /* Read Tx IQ calibration results. */
  115         tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(chain)),
  116             R92C_POWER_IQK_RESULT);
  117         tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(chain)),
  118             R92C_POWER_IQK_RESULT);
  119         if (tx[0] == 0x142 || tx[1] == 0x042)
  120                 return (0);     /* Tx failed. */
  121 
  122         if (status & (1 << (27 + chain * 3)))
  123                 return (1);     /* Rx failed. */
  124         /* Read Rx IQ calibration results. */
  125         rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(chain)),
  126             R92C_POWER_IQK_RESULT);
  127         rx[1] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(chain)),
  128             R92C_POWER_IQK_RESULT);
  129         if (rx[0] == 0x132 || rx[1] == 0x036)
  130                 return (1);     /* Rx failed. */
  131 
  132         return (3);     /* Both Tx and Rx succeeded. */
  133 }
  134 
  135 static void
  136 r92c_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
  137     uint16_t rx[2][2], struct r92c_iq_cal_reg_vals *vals)
  138 {
  139         /* Registers to save and restore during IQ calibration. */
  140         static const uint16_t reg_adda[16] = {
  141                 0x85c, 0xe6c, 0xe70, 0xe74,
  142                 0xe78, 0xe7c, 0xe80, 0xe84,
  143                 0xe88, 0xe8c, 0xed0, 0xed4,
  144                 0xed8, 0xedc, 0xee0, 0xeec
  145         };
  146         int i, chain;
  147         uint32_t hssi_param1;
  148 
  149         if (n == 0) {
  150                 for (i = 0; i < nitems(reg_adda); i++)
  151                         vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]);
  152 
  153                 vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE);
  154                 vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0));
  155                 vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1));
  156                 vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG);
  157         }
  158 
  159         if (sc->ntxchains == 1) {
  160                 rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0);
  161                 for (i = 1; i < nitems(reg_adda); i++)
  162                         rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0);
  163         } else {
  164                 for (i = 0; i < nitems(reg_adda); i++)
  165                         rtwn_bb_write(sc, reg_adda[i], 0x04db25a4);
  166         }
  167 
  168         hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
  169         if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
  170                 rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
  171                     hssi_param1 | R92C_HSSI_PARAM1_PI);
  172                 rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
  173                     hssi_param1 | R92C_HSSI_PARAM1_PI);
  174         }
  175 
  176         if (n == 0) {
  177                 vals->cck0_afesetting = rtwn_bb_read(sc, R92C_CCK0_AFESETTING);
  178                 vals->ofdm0_trxpathena =
  179                     rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
  180                 vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR);
  181                 vals->fpga0_rfifacesw0 =
  182                     rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0));
  183                 vals->fpga0_rfifacesw1 =
  184                     rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1));
  185                 vals->fpga0_rfifaceoe0 =
  186                     rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0));
  187                 vals->fpga0_rfifaceoe1 =
  188                     rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(1));
  189                 vals->config_ant0 = rtwn_bb_read(sc, R92C_CONFIG_ANT(0));
  190                 vals->config_ant1 = rtwn_bb_read(sc, R92C_CONFIG_ANT(1));
  191         }
  192 
  193         rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0, 0x0f000000);
  194         rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
  195         rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
  196         rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
  197         rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0, 0x04000400);
  198         rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0x400, 0);
  199         rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(1), 0x400, 0);
  200 
  201         if (sc->ntxchains > 1) {
  202                 rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
  203                 rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000);
  204         }
  205 
  206         rtwn_write_1(sc, R92C_TXPAUSE,
  207             R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH);
  208         rtwn_write_1(sc, R92C_BCN_CTRL(0),
  209             vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN);
  210         rtwn_write_1(sc, R92C_BCN_CTRL(1),
  211             vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN);
  212         rtwn_write_1(sc, R92C_GPIO_MUXCFG,
  213             vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT);
  214 
  215         rtwn_bb_write(sc, R92C_CONFIG_ANT(0), 0x00080000);
  216         if (sc->ntxchains > 1)
  217                 rtwn_bb_write(sc, R92C_CONFIG_ANT(1), 0x00080000);
  218 
  219         rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
  220         rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
  221         rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
  222 
  223         for (chain = 0; chain < sc->ntxchains; chain++) {
  224                 if (chain > 0) {
  225                         /* Put chain 0 on standby. */
  226                         rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
  227                         rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
  228                         rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
  229 
  230                         /* Enable chain 1. */
  231                         for (i = 0; i < nitems(reg_adda); i++)
  232                                 rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4);
  233                 }
  234 
  235                 /* Run IQ calibration twice. */
  236                 for (i = 0; i < 2; i++) {
  237                         int ret;
  238 
  239                         ret = r92c_iq_calib_chain(sc, chain,
  240                             tx[chain], rx[chain]);
  241                         if (ret == 0) {
  242                                 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
  243                                     "%s: chain %d: Tx failed.\n",
  244                                     __func__, chain);
  245                                 tx[chain][0] = 0xff;
  246                                 tx[chain][1] = 0xff;
  247                                 rx[chain][0] = 0xff;
  248                                 rx[chain][1] = 0xff;
  249                         } else if (ret == 1) {
  250                                 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
  251                                     "%s: chain %d: Rx failed.\n",
  252                                     __func__, chain);
  253                                 rx[chain][0] = 0xff;
  254                                 rx[chain][1] = 0xff;
  255                         } else if (ret == 3) {
  256                                 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
  257                                     "%s: chain %d: Both Tx and Rx "
  258                                     "succeeded.\n", __func__, chain);
  259                         }
  260                 }
  261 
  262                 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
  263                     "%s: results for run %d chain %d: tx[0] 0x%x, "
  264                     "tx[1] 0x%x, rx[0] 0x%x, rx[1] 0x%x\n", __func__, n, chain,
  265                     tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]);
  266         }
  267 
  268         rtwn_bb_write(sc, R92C_CCK0_AFESETTING, vals->cck0_afesetting);
  269         rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, vals->ofdm0_trxpathena);
  270         rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0), vals->fpga0_rfifacesw0);
  271         rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), vals->fpga0_rfifacesw1);
  272         rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar);
  273         rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0), vals->fpga0_rfifaceoe0);
  274         rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1), vals->fpga0_rfifaceoe1);
  275         rtwn_bb_write(sc, R92C_CONFIG_ANT(0), vals->config_ant0);
  276         rtwn_bb_write(sc, R92C_CONFIG_ANT(1), vals->config_ant1);
  277 
  278         rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
  279         rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
  280         if (sc->ntxchains > 1)
  281                 rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
  282 
  283         if (n != 0) {
  284                 if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
  285                         rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1);
  286                         rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1);
  287                 }
  288 
  289                 for (i = 0; i < nitems(reg_adda); i++)
  290                         rtwn_bb_write(sc, reg_adda[i], vals->adda[i]);
  291 
  292                 rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause);
  293                 rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]);
  294                 rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]);
  295                 rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg);
  296 
  297                 rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x01008c00);
  298                 rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x01008c00);
  299         }
  300 }
  301 
  302 #define RTWN_IQ_CAL_MAX_TOLERANCE 5
  303 static int
  304 r92c_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2][2],
  305     uint16_t rx1[2][2], uint16_t tx2[2][2], uint16_t rx2[2][2])
  306 {
  307         int chain, i, tx_ok[2], rx_ok[2];
  308 
  309         tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0;
  310         for (chain = 0; chain < sc->ntxchains; chain++) {
  311                 for (i = 0; i < 2; i++) {
  312                         if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff ||
  313                             rx1[chain][i] == 0xff || rx2[chain][i] == 0xff)
  314                                 continue;
  315 
  316                         tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <=
  317                             RTWN_IQ_CAL_MAX_TOLERANCE);
  318 
  319                         rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <=
  320                             RTWN_IQ_CAL_MAX_TOLERANCE);
  321                 }
  322         }
  323 
  324         if (sc->ntxchains > 1)
  325                 return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]);
  326         else
  327                 return (tx_ok[0] && rx_ok[0]);
  328 }
  329 #undef RTWN_IQ_CAL_MAX_TOLERANCE
  330 
  331 static void
  332 r92c_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2],
  333     uint16_t rx[2], int chain)
  334 {
  335         uint32_t reg, val, x;
  336         long y, tx_c;
  337 
  338         if (tx[0] == 0xff || tx[1] == 0xff)
  339                 return;
  340 
  341         reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain));
  342         val = ((reg >> 22) & 0x3ff);
  343         x = tx[0];
  344         if (x & 0x00000200)
  345                 x |= 0xfffffc00;
  346         reg = (((x * val) >> 8) & 0x3ff);
  347         rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x3ff, reg);
  348         rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000,
  349             ((x * val) & 0x80) << 24);
  350 
  351         y = tx[1];
  352         if (y & 0x00000200)
  353                 y |= 0xfffffc00;
  354         tx_c = (y * val) >> 8;
  355         rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(chain), 0xf0000000,
  356             (tx_c & 0x3c0) << 22);
  357         rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x003f0000,
  358             (tx_c & 0x3f) << 16);
  359         rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000,
  360             ((y * val) & 0x80) << 22);
  361 
  362         if (rx[0] == 0xff || rx[1] == 0xff)
  363                 return;
  364 
  365         rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0x3ff,
  366             rx[0] & 0x3ff);
  367         rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0xfc00,
  368             (rx[1] & 0x3f) << 10);
  369 
  370         if (chain == 0) {
  371                 rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000,
  372                     (rx[1] & 0x3c0) << 22);
  373         } else {
  374                 rtwn_bb_setbits(sc, R92C_OFDM0_AGCRSSITABLE, 0xf000,
  375                     (rx[1] & 0x3c0) << 6);
  376         }
  377 }
  378 
  379 #define RTWN_IQ_CAL_NRUN        3
  380 void
  381 r92c_iq_calib(struct rtwn_softc *sc)
  382 {
  383         struct r92c_iq_cal_reg_vals vals;
  384         uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2];
  385         int n, valid;
  386 
  387         valid = 0;
  388         for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) {
  389                 r92c_iq_calib_run(sc, n, tx[n], rx[n], &vals);
  390 
  391                 if (n == 0)
  392                         continue;
  393 
  394                 /* Valid results remain stable after consecutive runs. */
  395                 valid = r92c_iq_calib_compare_results(sc, tx[n - 1],
  396                     rx[n - 1], tx[n], rx[n]);
  397                 if (valid)
  398                         break;
  399         }
  400 
  401         if (valid) {
  402                 r92c_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0);
  403                 if (sc->ntxchains > 1)
  404                         r92c_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1);
  405         }
  406 }
  407 #undef RTWN_IQ_CAL_NRUN
  408 
  409 void
  410 r92c_lc_calib(struct rtwn_softc *sc)
  411 {
  412         uint32_t rf_ac[2];
  413         uint8_t txmode;
  414         int i;
  415 
  416         txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3);
  417         if ((txmode & 0x70) != 0) {
  418                 /* Disable all continuous Tx. */
  419                 rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70);
  420 
  421                 /* Set RF mode to standby mode. */
  422                 for (i = 0; i < sc->nrxchains; i++) {
  423                         rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC);
  424                         rtwn_rf_write(sc, i, R92C_RF_AC,
  425                             RW(rf_ac[i], R92C_RF_AC_MODE,
  426                                 R92C_RF_AC_MODE_STANDBY));
  427                 }
  428         } else {
  429                 /* Block all Tx queues. */
  430                 rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
  431         }
  432         /* Start calibration. */
  433         rtwn_rf_setbits(sc, 0, R92C_RF_CHNLBW, 0, R92C_RF_CHNLBW_LCSTART);
  434 
  435         /* Give calibration the time to complete. */
  436         rtwn_delay(sc, 100000); /* 100ms */
  437 
  438         /* Restore configuration. */
  439         if ((txmode & 0x70) != 0) {
  440                 /* Restore Tx mode. */
  441                 rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode);
  442                 /* Restore RF mode. */
  443                 for (i = 0; i < sc->nrxchains; i++)
  444                         rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]);
  445         } else {
  446                 /* Unblock all Tx queues. */
  447                 rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
  448         }
  449 }
  450 
  451 void
  452 r92c_temp_measure(struct rtwn_softc *sc)
  453 {
  454         rtwn_rf_write(sc, 0, R92C_RF_T_METER, R92C_RF_T_METER_START);
  455 }
  456 
  457 uint8_t
  458 r92c_temp_read(struct rtwn_softc *sc)
  459 {
  460         return (MS(rtwn_rf_read(sc, 0, R92C_RF_T_METER),
  461             R92C_RF_T_METER_VAL));
  462 }

Cache object: e51d4479e84f32be45a2013959dc3d64


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.