1*7453645fSAndriy Voskoboinyk /* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ 2*7453645fSAndriy Voskoboinyk 3*7453645fSAndriy Voskoboinyk /*- 4*7453645fSAndriy Voskoboinyk * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> 5*7453645fSAndriy Voskoboinyk * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org> 6*7453645fSAndriy Voskoboinyk * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org> 7*7453645fSAndriy Voskoboinyk * 8*7453645fSAndriy Voskoboinyk * Permission to use, copy, modify, and distribute this software for any 9*7453645fSAndriy Voskoboinyk * purpose with or without fee is hereby granted, provided that the above 10*7453645fSAndriy Voskoboinyk * copyright notice and this permission notice appear in all copies. 11*7453645fSAndriy Voskoboinyk * 12*7453645fSAndriy Voskoboinyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13*7453645fSAndriy Voskoboinyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14*7453645fSAndriy Voskoboinyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15*7453645fSAndriy Voskoboinyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16*7453645fSAndriy Voskoboinyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17*7453645fSAndriy Voskoboinyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18*7453645fSAndriy Voskoboinyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19*7453645fSAndriy Voskoboinyk */ 20*7453645fSAndriy Voskoboinyk 21*7453645fSAndriy Voskoboinyk #include <sys/cdefs.h> 22*7453645fSAndriy Voskoboinyk __FBSDID("$FreeBSD$"); 23*7453645fSAndriy Voskoboinyk 24*7453645fSAndriy Voskoboinyk #include "opt_wlan.h" 25*7453645fSAndriy Voskoboinyk 26*7453645fSAndriy Voskoboinyk #include <sys/param.h> 27*7453645fSAndriy Voskoboinyk #include <sys/lock.h> 28*7453645fSAndriy Voskoboinyk #include <sys/mutex.h> 29*7453645fSAndriy Voskoboinyk #include <sys/mbuf.h> 30*7453645fSAndriy Voskoboinyk #include <sys/kernel.h> 31*7453645fSAndriy Voskoboinyk #include <sys/socket.h> 32*7453645fSAndriy Voskoboinyk #include <sys/systm.h> 33*7453645fSAndriy Voskoboinyk #include <sys/malloc.h> 34*7453645fSAndriy Voskoboinyk #include <sys/queue.h> 35*7453645fSAndriy Voskoboinyk #include <sys/taskqueue.h> 36*7453645fSAndriy Voskoboinyk #include <sys/bus.h> 37*7453645fSAndriy Voskoboinyk #include <sys/endian.h> 38*7453645fSAndriy Voskoboinyk #include <sys/linker.h> 39*7453645fSAndriy Voskoboinyk 40*7453645fSAndriy Voskoboinyk #include <machine/bus.h> 41*7453645fSAndriy Voskoboinyk #include <machine/resource.h> 42*7453645fSAndriy Voskoboinyk #include <sys/rman.h> 43*7453645fSAndriy Voskoboinyk 44*7453645fSAndriy Voskoboinyk #include <net/if.h> 45*7453645fSAndriy Voskoboinyk #include <net/ethernet.h> 46*7453645fSAndriy Voskoboinyk #include <net/if_media.h> 47*7453645fSAndriy Voskoboinyk 48*7453645fSAndriy Voskoboinyk #include <net80211/ieee80211_var.h> 49*7453645fSAndriy Voskoboinyk #include <net80211/ieee80211_radiotap.h> 50*7453645fSAndriy Voskoboinyk 51*7453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnvar.h> 52*7453645fSAndriy Voskoboinyk 53*7453645fSAndriy Voskoboinyk #include <dev/rtwn/pci/rtwn_pci_var.h> 54*7453645fSAndriy Voskoboinyk 55*7453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/r92c_var.h> 56*7453645fSAndriy Voskoboinyk 57*7453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/pci/r92ce.h> 58*7453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/pci/r92ce_reg.h> 59*7453645fSAndriy Voskoboinyk 60*7453645fSAndriy Voskoboinyk 61*7453645fSAndriy Voskoboinyk void 62*7453645fSAndriy Voskoboinyk r92ce_init_intr(struct rtwn_softc *sc) 63*7453645fSAndriy Voskoboinyk { 64*7453645fSAndriy Voskoboinyk /* Disable interrupts. */ 65*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_HISR, 0x00000000); 66*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_HIMR, 0x00000000); 67*7453645fSAndriy Voskoboinyk } 68*7453645fSAndriy Voskoboinyk 69*7453645fSAndriy Voskoboinyk void 70*7453645fSAndriy Voskoboinyk r92ce_init_edca(struct rtwn_softc *sc) 71*7453645fSAndriy Voskoboinyk { 72*7453645fSAndriy Voskoboinyk /* SIFS */ 73*7453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_SPEC_SIFS, 0x1010); 74*7453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x1010); 75*7453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_SIFS_CCK, 0x1010); 76*7453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_SIFS_OFDM, 0x0e0e); 77*7453645fSAndriy Voskoboinyk /* TXOP */ 78*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b); 79*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f); 80*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4322); 81*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3222); 82*7453645fSAndriy Voskoboinyk } 83*7453645fSAndriy Voskoboinyk 84*7453645fSAndriy Voskoboinyk void 85*7453645fSAndriy Voskoboinyk r92ce_init_bb(struct rtwn_softc *sc) 86*7453645fSAndriy Voskoboinyk { 87*7453645fSAndriy Voskoboinyk 88*7453645fSAndriy Voskoboinyk /* Enable BB and RF. */ 89*7453645fSAndriy Voskoboinyk rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, 90*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | 91*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_DIO_RF); 92*7453645fSAndriy Voskoboinyk 93*7453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83); 94*7453645fSAndriy Voskoboinyk 95*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_RF_CTRL, 96*7453645fSAndriy Voskoboinyk R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); 97*7453645fSAndriy Voskoboinyk 98*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_SYS_FUNC_EN, 99*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_DIO_PCIE | R92C_SYS_FUNC_EN_PCIEA | 100*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_PPLL | R92C_SYS_FUNC_EN_BB_GLB_RST | 101*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_BBRSTB); 102*7453645fSAndriy Voskoboinyk 103*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); 104*7453645fSAndriy Voskoboinyk 105*7453645fSAndriy Voskoboinyk rtwn_setbits_4(sc, R92C_LEDCFG0, 0, 0x00800000); 106*7453645fSAndriy Voskoboinyk 107*7453645fSAndriy Voskoboinyk r92c_init_bb_common(sc); 108*7453645fSAndriy Voskoboinyk 109*7453645fSAndriy Voskoboinyk if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & 110*7453645fSAndriy Voskoboinyk R92C_HSSI_PARAM2_CCK_HIPWR) 111*7453645fSAndriy Voskoboinyk sc->sc_flags |= RTWN_FLAG_CCK_HIPWR; 112*7453645fSAndriy Voskoboinyk } 113*7453645fSAndriy Voskoboinyk 114*7453645fSAndriy Voskoboinyk int 115*7453645fSAndriy Voskoboinyk r92ce_power_on(struct rtwn_softc *sc) 116*7453645fSAndriy Voskoboinyk { 117*7453645fSAndriy Voskoboinyk struct r92c_softc *rs = sc->sc_priv; 118*7453645fSAndriy Voskoboinyk uint32_t reg; 119*7453645fSAndriy Voskoboinyk int ntries; 120*7453645fSAndriy Voskoboinyk 121*7453645fSAndriy Voskoboinyk /* Wait for autoload done bit. */ 122*7453645fSAndriy Voskoboinyk for (ntries = 0; ntries < 1000; ntries++) { 123*7453645fSAndriy Voskoboinyk if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN) 124*7453645fSAndriy Voskoboinyk break; 125*7453645fSAndriy Voskoboinyk DELAY(5); 126*7453645fSAndriy Voskoboinyk } 127*7453645fSAndriy Voskoboinyk if (ntries == 1000) { 128*7453645fSAndriy Voskoboinyk device_printf(sc->sc_dev, 129*7453645fSAndriy Voskoboinyk "timeout waiting for chip autoload\n"); 130*7453645fSAndriy Voskoboinyk return (ETIMEDOUT); 131*7453645fSAndriy Voskoboinyk } 132*7453645fSAndriy Voskoboinyk 133*7453645fSAndriy Voskoboinyk /* Unlock ISO/CLK/Power control register. */ 134*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_RSV_CTRL, 0); 135*7453645fSAndriy Voskoboinyk 136*7453645fSAndriy Voskoboinyk if (rs->board_type != R92C_BOARD_TYPE_DONGLE) { 137*7453645fSAndriy Voskoboinyk /* bt coex */ 138*7453645fSAndriy Voskoboinyk rtwn_setbits_4(sc, R92C_APS_FSMCO, 0, 139*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_SOP_ABG | 140*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_SOP_AMB | 141*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_XOP_BTCK); 142*7453645fSAndriy Voskoboinyk } 143*7453645fSAndriy Voskoboinyk 144*7453645fSAndriy Voskoboinyk /* Move SPS into PWM mode. */ 145*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b); 146*7453645fSAndriy Voskoboinyk 147*7453645fSAndriy Voskoboinyk /* Set low byte to 0x0f, leave others unchanged. */ 148*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0f); 149*7453645fSAndriy Voskoboinyk 150*7453645fSAndriy Voskoboinyk /* TODO: check if we need this for 8188CE */ 151*7453645fSAndriy Voskoboinyk if (rs->board_type != R92C_BOARD_TYPE_DONGLE) { 152*7453645fSAndriy Voskoboinyk /* bt coex */ 153*7453645fSAndriy Voskoboinyk /* XXX magic from linux */ 154*7453645fSAndriy Voskoboinyk rtwn_setbits_4(sc, R92C_AFE_XTAL_CTRL, 0x024800, 0); 155*7453645fSAndriy Voskoboinyk } 156*7453645fSAndriy Voskoboinyk 157*7453645fSAndriy Voskoboinyk rtwn_setbits_2(sc, R92C_SYS_ISO_CTRL, 0xff00, 158*7453645fSAndriy Voskoboinyk R92C_SYS_ISO_CTRL_PWC_EV12V | R92C_SYS_ISO_CTRL_DIOR); 159*7453645fSAndriy Voskoboinyk 160*7453645fSAndriy Voskoboinyk DELAY(200); 161*7453645fSAndriy Voskoboinyk 162*7453645fSAndriy Voskoboinyk /* TODO: linux does additional btcoex stuff here */ 163*7453645fSAndriy Voskoboinyk 164*7453645fSAndriy Voskoboinyk /* Auto enable WLAN. */ 165*7453645fSAndriy Voskoboinyk rtwn_setbits_2(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_ONMAC); 166*7453645fSAndriy Voskoboinyk for (ntries = 0; ntries < 1000; ntries++) { 167*7453645fSAndriy Voskoboinyk if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & 168*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_APFM_ONMAC)) 169*7453645fSAndriy Voskoboinyk break; 170*7453645fSAndriy Voskoboinyk DELAY(5); 171*7453645fSAndriy Voskoboinyk } 172*7453645fSAndriy Voskoboinyk if (ntries == 1000) { 173*7453645fSAndriy Voskoboinyk device_printf(sc->sc_dev, "timeout waiting for MAC auto ON\n"); 174*7453645fSAndriy Voskoboinyk return (ETIMEDOUT); 175*7453645fSAndriy Voskoboinyk } 176*7453645fSAndriy Voskoboinyk 177*7453645fSAndriy Voskoboinyk /* Enable radio, GPIO and LED functions. */ 178*7453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_APS_FSMCO, 179*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_AFSM_PCIE | 180*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_PDN_EN | 181*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_PFM_ALDN); 182*7453645fSAndriy Voskoboinyk /* Release RF digital isolation. */ 183*7453645fSAndriy Voskoboinyk rtwn_setbits_2(sc, R92C_SYS_ISO_CTRL, R92C_SYS_ISO_CTRL_DIOR, 0); 184*7453645fSAndriy Voskoboinyk 185*7453645fSAndriy Voskoboinyk if (rs->chip & R92C_CHIP_92C) 186*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x77); 187*7453645fSAndriy Voskoboinyk else 188*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x22); 189*7453645fSAndriy Voskoboinyk 190*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_INT_MIG, 0); 191*7453645fSAndriy Voskoboinyk 192*7453645fSAndriy Voskoboinyk if (rs->board_type != R92C_BOARD_TYPE_DONGLE) { 193*7453645fSAndriy Voskoboinyk /* bt coex */ 194*7453645fSAndriy Voskoboinyk /* XXX magic from linux */ 195*7453645fSAndriy Voskoboinyk rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0x02, 0); 196*7453645fSAndriy Voskoboinyk } 197*7453645fSAndriy Voskoboinyk 198*7453645fSAndriy Voskoboinyk rtwn_setbits_1(sc, R92C_GPIO_MUXCFG, R92C_GPIO_MUXCFG_RFKILL, 0); 199*7453645fSAndriy Voskoboinyk 200*7453645fSAndriy Voskoboinyk reg = rtwn_read_1(sc, R92C_GPIO_IO_SEL); 201*7453645fSAndriy Voskoboinyk if (!(reg & R92C_GPIO_IO_SEL_RFKILL)) { 202*7453645fSAndriy Voskoboinyk device_printf(sc->sc_dev, 203*7453645fSAndriy Voskoboinyk "radio is disabled by hardware switch\n"); 204*7453645fSAndriy Voskoboinyk /* XXX how driver will know when radio will be enabled? */ 205*7453645fSAndriy Voskoboinyk return (EPERM); 206*7453645fSAndriy Voskoboinyk } 207*7453645fSAndriy Voskoboinyk 208*7453645fSAndriy Voskoboinyk /* Initialize MAC. */ 209*7453645fSAndriy Voskoboinyk rtwn_setbits_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF, 0); 210*7453645fSAndriy Voskoboinyk for (ntries = 0; ntries < 200; ntries++) { 211*7453645fSAndriy Voskoboinyk if (!(rtwn_read_1(sc, R92C_APSD_CTRL) & 212*7453645fSAndriy Voskoboinyk R92C_APSD_CTRL_OFF_STATUS)) 213*7453645fSAndriy Voskoboinyk break; 214*7453645fSAndriy Voskoboinyk DELAY(500); 215*7453645fSAndriy Voskoboinyk } 216*7453645fSAndriy Voskoboinyk if (ntries == 200) { 217*7453645fSAndriy Voskoboinyk device_printf(sc->sc_dev, 218*7453645fSAndriy Voskoboinyk "timeout waiting for MAC initialization\n"); 219*7453645fSAndriy Voskoboinyk return (ETIMEDOUT); 220*7453645fSAndriy Voskoboinyk } 221*7453645fSAndriy Voskoboinyk 222*7453645fSAndriy Voskoboinyk /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ 223*7453645fSAndriy Voskoboinyk rtwn_setbits_2(sc, R92C_CR, 0, 224*7453645fSAndriy Voskoboinyk R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | 225*7453645fSAndriy Voskoboinyk R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | 226*7453645fSAndriy Voskoboinyk R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | 227*7453645fSAndriy Voskoboinyk ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0)); 228*7453645fSAndriy Voskoboinyk 229*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_MCUTST_1, 0x0); 230*7453645fSAndriy Voskoboinyk 231*7453645fSAndriy Voskoboinyk return (0); 232*7453645fSAndriy Voskoboinyk } 233*7453645fSAndriy Voskoboinyk 234*7453645fSAndriy Voskoboinyk void 235*7453645fSAndriy Voskoboinyk r92ce_power_off(struct rtwn_softc *sc) 236*7453645fSAndriy Voskoboinyk { 237*7453645fSAndriy Voskoboinyk #ifndef RTWN_WITHOUT_UCODE 238*7453645fSAndriy Voskoboinyk struct r92c_softc *rs = sc->sc_priv; 239*7453645fSAndriy Voskoboinyk 240*7453645fSAndriy Voskoboinyk /* Deinit C2H event handler. */ 241*7453645fSAndriy Voskoboinyk callout_stop(&rs->rs_c2h_report); 242*7453645fSAndriy Voskoboinyk rs->rs_c2h_paused = 0; 243*7453645fSAndriy Voskoboinyk rs->rs_c2h_pending = 0; 244*7453645fSAndriy Voskoboinyk rs->rs_c2h_timeout = hz; 245*7453645fSAndriy Voskoboinyk #endif 246*7453645fSAndriy Voskoboinyk 247*7453645fSAndriy Voskoboinyk /* Stop hardware. */ 248*7453645fSAndriy Voskoboinyk /* Disable interrupts. */ 249*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_HISR, 0); 250*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_HIMR, 0); 251*7453645fSAndriy Voskoboinyk 252*7453645fSAndriy Voskoboinyk /* Stop hardware. */ 253*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); 254*7453645fSAndriy Voskoboinyk 255*7453645fSAndriy Voskoboinyk /* Turn off RF. */ 256*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_RF_CTRL, 0); 257*7453645fSAndriy Voskoboinyk 258*7453645fSAndriy Voskoboinyk /* Reset BB state machine */ 259*7453645fSAndriy Voskoboinyk rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_BB_GLB_RST); 260*7453645fSAndriy Voskoboinyk rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0); 261*7453645fSAndriy Voskoboinyk 262*7453645fSAndriy Voskoboinyk /* Disable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ 263*7453645fSAndriy Voskoboinyk rtwn_setbits_2(sc, R92C_CR, 264*7453645fSAndriy Voskoboinyk R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | 265*7453645fSAndriy Voskoboinyk R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | 266*7453645fSAndriy Voskoboinyk R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | 267*7453645fSAndriy Voskoboinyk R92C_CR_ENSEC, 268*7453645fSAndriy Voskoboinyk 0); 269*7453645fSAndriy Voskoboinyk 270*7453645fSAndriy Voskoboinyk /* If firmware in ram code, do reset. */ 271*7453645fSAndriy Voskoboinyk #ifndef RTWN_WITHOUT_UCODE 272*7453645fSAndriy Voskoboinyk if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) 273*7453645fSAndriy Voskoboinyk r92ce_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN); 274*7453645fSAndriy Voskoboinyk #endif 275*7453645fSAndriy Voskoboinyk 276*7453645fSAndriy Voskoboinyk /* TODO: linux does additional btcoex stuff here */ 277*7453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0x80); /* linux magic number */ 278*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); /* ditto */ 279*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0e); /* different with btcoex */ 280*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_RSV_CTRL, 0x0e); 281*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_PDN_EN); 282*7453645fSAndriy Voskoboinyk } 283*7453645fSAndriy Voskoboinyk 284*7453645fSAndriy Voskoboinyk void 285*7453645fSAndriy Voskoboinyk r92ce_init_ampdu(struct rtwn_softc *sc) 286*7453645fSAndriy Voskoboinyk { 287*7453645fSAndriy Voskoboinyk 288*7453645fSAndriy Voskoboinyk /* Setup AMPDU aggregation. */ 289*7453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ 290*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); 291*7453645fSAndriy Voskoboinyk } 292*7453645fSAndriy Voskoboinyk 293*7453645fSAndriy Voskoboinyk void 294*7453645fSAndriy Voskoboinyk r92ce_post_init(struct rtwn_softc *sc) 295*7453645fSAndriy Voskoboinyk { 296*7453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_FWHW_TXQ_CTRL, 297*7453645fSAndriy Voskoboinyk 0x1f00 | R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW); 298*7453645fSAndriy Voskoboinyk 299*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff); 300*7453645fSAndriy Voskoboinyk 301*7453645fSAndriy Voskoboinyk /* Perform LO and IQ calibrations. */ 302*7453645fSAndriy Voskoboinyk r92ce_iq_calib(sc); 303*7453645fSAndriy Voskoboinyk /* Perform LC calibration. */ 304*7453645fSAndriy Voskoboinyk r92c_lc_calib(sc); 305*7453645fSAndriy Voskoboinyk 306*7453645fSAndriy Voskoboinyk r92c_pa_bias_init(sc); 307*7453645fSAndriy Voskoboinyk 308*7453645fSAndriy Voskoboinyk /* Fix for lower temperature. */ 309*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, 0x15, 0xe9); 310*7453645fSAndriy Voskoboinyk 311*7453645fSAndriy Voskoboinyk #ifndef RTWN_WITHOUT_UCODE 312*7453645fSAndriy Voskoboinyk if (sc->sc_flags & RTWN_FW_LOADED) { 313*7453645fSAndriy Voskoboinyk struct r92c_softc *rs = sc->sc_priv; 314*7453645fSAndriy Voskoboinyk 315*7453645fSAndriy Voskoboinyk if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) { 316*7453645fSAndriy Voskoboinyk /* XXX TODO: fix (see comment in r92cu_init.c) */ 317*7453645fSAndriy Voskoboinyk sc->sc_ratectl = RTWN_RATECTL_NET80211; 318*7453645fSAndriy Voskoboinyk } else 319*7453645fSAndriy Voskoboinyk sc->sc_ratectl = sc->sc_ratectl_sysctl; 320*7453645fSAndriy Voskoboinyk 321*7453645fSAndriy Voskoboinyk /* Start C2H event handling. */ 322*7453645fSAndriy Voskoboinyk callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout, 323*7453645fSAndriy Voskoboinyk r92c_handle_c2h_report, sc); 324*7453645fSAndriy Voskoboinyk } else 325*7453645fSAndriy Voskoboinyk #endif 326*7453645fSAndriy Voskoboinyk sc->sc_ratectl = RTWN_RATECTL_NONE; 327*7453645fSAndriy Voskoboinyk } 328