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/rtl8821a/r21a_init.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 /*-
    2  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "opt_wlan.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/lock.h>
   34 #include <sys/mutex.h>
   35 #include <sys/mbuf.h>
   36 #include <sys/kernel.h>
   37 #include <sys/socket.h>
   38 #include <sys/systm.h>
   39 #include <sys/malloc.h>
   40 #include <sys/queue.h>
   41 #include <sys/taskqueue.h>
   42 #include <sys/bus.h>
   43 #include <sys/endian.h>
   44 #include <sys/linker.h>
   45 
   46 #include <net/if.h>
   47 #include <net/ethernet.h>
   48 #include <net/if_media.h>
   49 
   50 #include <net80211/ieee80211_var.h>
   51 #include <net80211/ieee80211_radiotap.h>
   52 
   53 #include <dev/rtwn/if_rtwnreg.h>
   54 #include <dev/rtwn/if_rtwnvar.h>
   55 
   56 #include <dev/rtwn/if_rtwn_debug.h>
   57 
   58 #include <dev/rtwn/rtl8812a/r12a_var.h>
   59 
   60 #include <dev/rtwn/rtl8821a/r21a.h>
   61 #include <dev/rtwn/rtl8821a/r21a_priv.h>
   62 #include <dev/rtwn/rtl8821a/r21a_reg.h>
   63 
   64 int
   65 r21a_power_on(struct rtwn_softc *sc)
   66 {
   67 #define RTWN_CHK(res) do {      \
   68         if (res != 0)           \
   69                 return (EIO);   \
   70 } while(0)
   71         int ntries;
   72 
   73         /* Clear suspend and power down bits.*/
   74         RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
   75             R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_APDM_HPDN, 0, 1));
   76 
   77         /* Disable GPIO9 as EXT WAKEUP. */
   78         RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0x01, 0));
   79 
   80         /* Enable WL suspend. */
   81         RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
   82             R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
   83 
   84         /* Enable LDOA12 MACRO block for all interfaces. */
   85         RTWN_CHK(rtwn_setbits_1(sc, R92C_LDOA15_CTRL, 0, R92C_LDOA15_CTRL_EN));
   86 
   87         /* Disable BT_GPS_SEL pins. */
   88         RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0x10, 0));
   89 
   90         /* 1 ms delay. */
   91         rtwn_delay(sc, 1000);
   92 
   93         /* Release analog Ips to digital isolation. */
   94         RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL,
   95             R92C_SYS_ISO_CTRL_IP2MAC, 0));
   96 
   97         /* Disable SW LPS and WL suspend. */
   98         RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
   99             R92C_APS_FSMCO_APFM_RSM |
  100             R92C_APS_FSMCO_AFSM_HSUS |
  101             R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
  102 
  103         /* Wait for power ready bit. */
  104         for (ntries = 0; ntries < 5000; ntries++) {
  105                 if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
  106                         break;
  107                 rtwn_delay(sc, 10);
  108         }
  109         if (ntries == 5000) {
  110                 device_printf(sc->sc_dev,
  111                     "timeout waiting for chip power up\n");
  112                 return (ETIMEDOUT);
  113         }
  114 
  115         /* Release WLON reset. */
  116         RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
  117             R92C_APS_FSMCO_RDY_MACON, 2));
  118 
  119         /* Disable HWPDN. */
  120         RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
  121             R92C_APS_FSMCO_APDM_HPDN, 0, 1));
  122 
  123         /* Disable WL suspend. */
  124         RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
  125             R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
  126 
  127         RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
  128             R92C_APS_FSMCO_APFM_ONMAC, 1));
  129         for (ntries = 0; ntries < 5000; ntries++) {
  130                 if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
  131                     R92C_APS_FSMCO_APFM_ONMAC))
  132                         break;
  133                 rtwn_delay(sc, 10);
  134         }
  135         if (ntries == 5000)
  136                 return (ETIMEDOUT);
  137 
  138         /* Switch DPDT_SEL_P output from WL BB. */
  139         RTWN_CHK(rtwn_setbits_1(sc, R92C_LEDCFG3, 0, 0x01));
  140 
  141         /* switch for PAPE_G/PAPE_A from WL BB; switch LNAON from WL BB. */
  142         RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0, 0x30));
  143 
  144         RTWN_CHK(rtwn_setbits_1(sc, 0x025, 0x40, 0));
  145 
  146         /* Enable falling edge triggering interrupt. */
  147         RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0, 0x02));
  148 
  149         /* Enable GPIO9 interrupt mode. */
  150         RTWN_CHK(rtwn_setbits_1(sc, 0x063, 0, 0x02));
  151 
  152         /* Enable GPIO9 input mode. */
  153         RTWN_CHK(rtwn_setbits_1(sc, 0x062, 0x02, 0));
  154 
  155         /* Enable HSISR GPIO interrupt. */
  156         RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR, 0, 0x01));
  157 
  158         /* Enable HSISR GPIO9 interrupt. */
  159         RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR + 2, 0, 0x02));
  160 
  161         /* XTAL trim. */
  162         RTWN_CHK(rtwn_setbits_1(sc, R92C_APE_PLL_CTRL_EXT + 2, 0xFF, 0x82));
  163 
  164         RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_MISC, 0, 0x40));
  165 
  166         /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
  167         RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0x0000));
  168         RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
  169             R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
  170             R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
  171             R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
  172             ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
  173             R92C_CR_CALTMR_EN));
  174 
  175         if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN)
  176                 RTWN_CHK(rtwn_setbits_1(sc, R92C_LDO_SWR_CTRL, 0, 0x40));
  177 
  178         return (0);
  179 #undef RTWN_CHK
  180 }
  181 
  182 void
  183 r21a_power_off(struct rtwn_softc *sc)
  184 {
  185         struct r12a_softc *rs = sc->sc_priv;
  186         int error, ntries;
  187 
  188         /* Stop Rx. */
  189         error = rtwn_write_1(sc, R92C_CR, 0);
  190         if (error == ENXIO)     /* hardware gone */
  191                 return;
  192 
  193         /* Move card to Low Power state. */
  194         /* Block all Tx queues. */
  195         rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
  196 
  197         for (ntries = 0; ntries < 10; ntries++) {
  198                 /* Should be zero if no packet is transmitting. */
  199                 if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
  200                         break;
  201 
  202                 rtwn_delay(sc, 5000);
  203         }
  204         if (ntries == 10) {
  205                 device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
  206                     __func__);
  207                 return;
  208         }
  209 
  210         /* CCK and OFDM are disabled, and clock are gated. */
  211         rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0);
  212 
  213         rtwn_delay(sc, 1);
  214 
  215         /* Reset whole BB. */
  216         rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0);
  217 
  218         /* Reset MAC TRX. */
  219         rtwn_write_1(sc, R92C_CR,
  220             R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN);
  221 
  222         /* check if removed later. (?) */
  223         rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1);
  224 
  225         /* Respond TxOK to scheduler */
  226         rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK);
  227 
  228         /* If firmware in ram code, do reset. */
  229 #ifndef RTWN_WITHOUT_UCODE
  230         if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL)
  231                 r21a_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
  232 #endif
  233 
  234         /* Reset MCU. */
  235         rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN,
  236             0, 1);
  237         rtwn_write_1(sc, R92C_MCUFWDL, 0);
  238 
  239         /* Move card to Disabled state. */
  240         /* Turn off RF. */
  241         rtwn_write_1(sc, R92C_RF_CTRL, 0);
  242 
  243         rtwn_setbits_1(sc, R92C_LEDCFG3, 0x01, 0);
  244 
  245         /* Enable rising edge triggering interrupt. */
  246         rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0x02, 0);
  247 
  248         /* Release WLON reset. */
  249         rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
  250             R92C_APS_FSMCO_RDY_MACON, 2);
  251 
  252         /* Turn off MAC by HW state machine */
  253         rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_OFF,
  254             1);
  255         for (ntries = 0; ntries < 10; ntries++) {
  256                 /* Wait until it will be disabled. */
  257                 if ((rtwn_read_2(sc, R92C_APS_FSMCO) &
  258                     R92C_APS_FSMCO_APFM_OFF) == 0)
  259                         break;
  260 
  261                 rtwn_delay(sc, 5000);
  262         }
  263         if (ntries == 10) {
  264                 device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
  265                     __func__);
  266                 return;
  267         }
  268 
  269         /* Analog Ips to digital isolation. */
  270         rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, 0, R92C_SYS_ISO_CTRL_IP2MAC);
  271 
  272         /* Disable LDOA12 MACRO block. */
  273         rtwn_setbits_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_EN, 0);
  274 
  275         /* Enable WL suspend. */
  276         rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE,
  277             R92C_APS_FSMCO_AFSM_HSUS, 1);
  278 
  279         /* Enable GPIO9 as EXT WAKEUP. */
  280         rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0, 0x01);
  281 
  282         rs->rs_flags &= ~(R12A_IQK_RUNNING | R12A_RADAR_ENABLED);
  283 }
  284 
  285 int
  286 r21a_check_condition(struct rtwn_softc *sc, const uint8_t cond[])
  287 {
  288         struct r12a_softc *rs = sc->sc_priv;
  289         uint8_t mask;
  290         int i;
  291 
  292         RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
  293             "%s: condition byte 0: %02X; ext 5ghz pa/lna %d/%d\n",
  294             __func__, cond[0], rs->ext_pa_5g, rs->ext_lna_5g);
  295 
  296         if (cond[0] == 0)
  297                 return (1);
  298 
  299         mask = 0;
  300         if (rs->ext_pa_5g)
  301                 mask |= R21A_COND_EXT_PA_5G;
  302         if (rs->ext_lna_5g)
  303                 mask |= R21A_COND_EXT_LNA_5G;
  304         if (rs->bt_coex)
  305                 mask |= R21A_COND_BT;
  306         if (!rs->ext_pa_2g && !rs->ext_lna_2g &&
  307             !rs->ext_pa_5g && !rs->ext_lna_5g && !rs->bt_coex)
  308                 mask = R21A_COND_BOARD_DEF;
  309 
  310         if (mask == 0)
  311                 return (0);
  312 
  313         for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++)
  314                 if (cond[i] == mask)
  315                         return (1);
  316 
  317         return (0);
  318 }
  319 
  320 void
  321 r21a_crystalcap_write(struct rtwn_softc *sc)
  322 {
  323         struct r12a_softc *rs = sc->sc_priv;
  324         uint32_t reg;
  325         uint8_t val;
  326 
  327         val = rs->crystalcap & 0x3f;
  328         reg = rtwn_bb_read(sc, R92C_MAC_PHY_CTRL);
  329         reg = RW(reg, R21A_MAC_PHY_CRYSTALCAP, val | (val << 6));
  330         rtwn_bb_write(sc, R92C_MAC_PHY_CTRL, reg);
  331 }
  332 
  333 int
  334 r21a_init_bcnq1_boundary(struct rtwn_softc *sc)
  335 {
  336 #define RTWN_CHK(res) do {      \
  337         if (res != 0)           \
  338                 return (EIO);   \
  339 } while(0)
  340         RTWN_CHK(rtwn_write_1(sc, R88E_TXPKTBUF_BCNQ1_BDNY,
  341             R21A_BCNQ0_BOUNDARY));
  342         RTWN_CHK(rtwn_write_1(sc, R21A_DWBCN1_CTRL + 1,
  343             R21A_BCNQ0_BOUNDARY));
  344         RTWN_CHK(rtwn_setbits_1_shift(sc, R21A_DWBCN1_CTRL, 0,
  345             R21A_DWBCN1_CTRL_SEL_EN, 2));
  346 
  347         return (0);
  348 #undef RTWN_CHK
  349 }
  350 
  351 void
  352 r21a_init_ampdu_fwhw(struct rtwn_softc *sc)
  353 {
  354         rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL,
  355             R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
  356         rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x03087777);
  357 }

Cache object: 36667f698f8f08a973ce8bc91666e2b3


[ 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.