1*7453645fSAndriy Voskoboinyk /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ 2*7453645fSAndriy Voskoboinyk 3*7453645fSAndriy Voskoboinyk /*- 4*7453645fSAndriy Voskoboinyk * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> 5*7453645fSAndriy Voskoboinyk * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> 6*7453645fSAndriy Voskoboinyk * Copyright (c) 2015-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 <net/if.h> 41*7453645fSAndriy Voskoboinyk #include <net/ethernet.h> 42*7453645fSAndriy Voskoboinyk #include <net/if_media.h> 43*7453645fSAndriy Voskoboinyk 44*7453645fSAndriy Voskoboinyk #include <net80211/ieee80211_var.h> 45*7453645fSAndriy Voskoboinyk #include <net80211/ieee80211_radiotap.h> 46*7453645fSAndriy Voskoboinyk 47*7453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnreg.h> 48*7453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnvar.h> 49*7453645fSAndriy Voskoboinyk 50*7453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwn_debug.h> 51*7453645fSAndriy Voskoboinyk 52*7453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/r92c.h> 53*7453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/r92c_var.h> 54*7453645fSAndriy Voskoboinyk 55*7453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8188e/r88e.h> 56*7453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8188e/r88e_reg.h> 57*7453645fSAndriy Voskoboinyk 58*7453645fSAndriy Voskoboinyk 59*7453645fSAndriy Voskoboinyk static void 60*7453645fSAndriy Voskoboinyk r88e_crystalcap_write(struct rtwn_softc *sc) 61*7453645fSAndriy Voskoboinyk { 62*7453645fSAndriy Voskoboinyk struct r92c_softc *rs = sc->sc_priv; 63*7453645fSAndriy Voskoboinyk uint32_t reg; 64*7453645fSAndriy Voskoboinyk uint8_t val; 65*7453645fSAndriy Voskoboinyk 66*7453645fSAndriy Voskoboinyk val = rs->crystalcap & 0x3f; 67*7453645fSAndriy Voskoboinyk reg = rtwn_bb_read(sc, R92C_AFE_XTAL_CTRL); 68*7453645fSAndriy Voskoboinyk rtwn_bb_write(sc, R92C_AFE_XTAL_CTRL, 69*7453645fSAndriy Voskoboinyk RW(reg, R92C_AFE_XTAL_CTRL_ADDR, val | val << 6)); 70*7453645fSAndriy Voskoboinyk } 71*7453645fSAndriy Voskoboinyk 72*7453645fSAndriy Voskoboinyk void 73*7453645fSAndriy Voskoboinyk r88e_init_bb(struct rtwn_softc *sc) 74*7453645fSAndriy Voskoboinyk { 75*7453645fSAndriy Voskoboinyk 76*7453645fSAndriy Voskoboinyk /* Enable BB and RF. */ 77*7453645fSAndriy Voskoboinyk rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, 78*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | 79*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_DIO_RF); 80*7453645fSAndriy Voskoboinyk 81*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_RF_CTRL, 82*7453645fSAndriy Voskoboinyk R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); 83*7453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_SYS_FUNC_EN, 84*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | 85*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); 86*7453645fSAndriy Voskoboinyk 87*7453645fSAndriy Voskoboinyk r92c_init_bb_common(sc); 88*7453645fSAndriy Voskoboinyk 89*7453645fSAndriy Voskoboinyk rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422); 90*7453645fSAndriy Voskoboinyk rtwn_delay(sc, 1); 91*7453645fSAndriy Voskoboinyk rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420); 92*7453645fSAndriy Voskoboinyk rtwn_delay(sc, 1); 93*7453645fSAndriy Voskoboinyk 94*7453645fSAndriy Voskoboinyk r88e_crystalcap_write(sc); 95*7453645fSAndriy Voskoboinyk } 96*7453645fSAndriy Voskoboinyk 97*7453645fSAndriy Voskoboinyk int 98*7453645fSAndriy Voskoboinyk r88e_power_on(struct rtwn_softc *sc) 99*7453645fSAndriy Voskoboinyk { 100*7453645fSAndriy Voskoboinyk #define RTWN_CHK(res) do { \ 101*7453645fSAndriy Voskoboinyk if (res != 0) \ 102*7453645fSAndriy Voskoboinyk return (EIO); \ 103*7453645fSAndriy Voskoboinyk } while(0) 104*7453645fSAndriy Voskoboinyk int ntries; 105*7453645fSAndriy Voskoboinyk 106*7453645fSAndriy Voskoboinyk /* Wait for power ready bit. */ 107*7453645fSAndriy Voskoboinyk for (ntries = 0; ntries < 5000; ntries++) { 108*7453645fSAndriy Voskoboinyk if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) 109*7453645fSAndriy Voskoboinyk break; 110*7453645fSAndriy Voskoboinyk rtwn_delay(sc, 10); 111*7453645fSAndriy Voskoboinyk } 112*7453645fSAndriy Voskoboinyk if (ntries == 5000) { 113*7453645fSAndriy Voskoboinyk device_printf(sc->sc_dev, 114*7453645fSAndriy Voskoboinyk "timeout waiting for chip power up\n"); 115*7453645fSAndriy Voskoboinyk return (ETIMEDOUT); 116*7453645fSAndriy Voskoboinyk } 117*7453645fSAndriy Voskoboinyk 118*7453645fSAndriy Voskoboinyk /* Reset BB. */ 119*7453645fSAndriy Voskoboinyk RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, 120*7453645fSAndriy Voskoboinyk R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0)); 121*7453645fSAndriy Voskoboinyk 122*7453645fSAndriy Voskoboinyk RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80)); 123*7453645fSAndriy Voskoboinyk 124*7453645fSAndriy Voskoboinyk /* Disable HWPDN. */ 125*7453645fSAndriy Voskoboinyk RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 126*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_APDM_HPDN, 0, 1)); 127*7453645fSAndriy Voskoboinyk 128*7453645fSAndriy Voskoboinyk /* Disable WL suspend. */ 129*7453645fSAndriy Voskoboinyk RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 130*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); 131*7453645fSAndriy Voskoboinyk 132*7453645fSAndriy Voskoboinyk RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 133*7453645fSAndriy Voskoboinyk 0, R92C_APS_FSMCO_APFM_ONMAC, 1)); 134*7453645fSAndriy Voskoboinyk for (ntries = 0; ntries < 5000; ntries++) { 135*7453645fSAndriy Voskoboinyk if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & 136*7453645fSAndriy Voskoboinyk R92C_APS_FSMCO_APFM_ONMAC)) 137*7453645fSAndriy Voskoboinyk break; 138*7453645fSAndriy Voskoboinyk rtwn_delay(sc, 10); 139*7453645fSAndriy Voskoboinyk } 140*7453645fSAndriy Voskoboinyk if (ntries == 5000) 141*7453645fSAndriy Voskoboinyk return (ETIMEDOUT); 142*7453645fSAndriy Voskoboinyk 143*7453645fSAndriy Voskoboinyk /* Enable LDO normal mode. */ 144*7453645fSAndriy Voskoboinyk RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL, 145*7453645fSAndriy Voskoboinyk R92C_LPLDO_CTRL_SLEEP, 0)); 146*7453645fSAndriy Voskoboinyk 147*7453645fSAndriy Voskoboinyk /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ 148*7453645fSAndriy Voskoboinyk RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0)); 149*7453645fSAndriy Voskoboinyk RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, 150*7453645fSAndriy Voskoboinyk R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | 151*7453645fSAndriy Voskoboinyk R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | 152*7453645fSAndriy Voskoboinyk R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | 153*7453645fSAndriy Voskoboinyk ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | 154*7453645fSAndriy Voskoboinyk R92C_CR_CALTMR_EN)); 155*7453645fSAndriy Voskoboinyk 156*7453645fSAndriy Voskoboinyk return (0); 157*7453645fSAndriy Voskoboinyk #undef RTWN_CHK 158*7453645fSAndriy Voskoboinyk } 159