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) 2015-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 #include "opt_wlan.h" 23 24 #include <sys/param.h> 25 #include <sys/lock.h> 26 #include <sys/mutex.h> 27 #include <sys/mbuf.h> 28 #include <sys/kernel.h> 29 #include <sys/socket.h> 30 #include <sys/systm.h> 31 #include <sys/malloc.h> 32 #include <sys/queue.h> 33 #include <sys/taskqueue.h> 34 #include <sys/bus.h> 35 #include <sys/endian.h> 36 #include <sys/linker.h> 37 38 #include <net/if.h> 39 #include <net/ethernet.h> 40 #include <net/if_media.h> 41 42 #include <net80211/ieee80211_var.h> 43 #include <net80211/ieee80211_radiotap.h> 44 45 #include <dev/rtwn/if_rtwnreg.h> 46 #include <dev/rtwn/if_rtwnvar.h> 47 #include <dev/rtwn/if_rtwn_debug.h> 48 49 #include <dev/rtwn/usb/rtwn_usb_var.h> 50 51 #include <dev/rtwn/rtl8192c/r92c_var.h> 52 53 #include <dev/rtwn/rtl8192c/usb/r92cu.h> 54 #include <dev/rtwn/rtl8192c/usb/r92cu_reg.h> 55 56 void 57 r92cu_init_bb(struct rtwn_softc *sc) 58 { 59 60 /* Enable BB and RF. */ 61 rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, 62 R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | 63 R92C_SYS_FUNC_EN_DIO_RF); 64 65 rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83); 66 67 rtwn_write_1(sc, R92C_RF_CTRL, 68 R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); 69 rtwn_write_1(sc, R92C_SYS_FUNC_EN, 70 R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | 71 R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); 72 73 rtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f); 74 rtwn_write_1(sc, 0x15, 0xe9); 75 rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); 76 77 r92c_init_bb_common(sc); 78 } 79 80 int 81 r92cu_power_on(struct rtwn_softc *sc) 82 { 83 #define RTWN_CHK(res) do { \ 84 if (res != 0) \ 85 return (EIO); \ 86 } while(0) 87 uint32_t reg; 88 int ntries; 89 90 /* Wait for autoload done bit. */ 91 for (ntries = 0; ntries < 5000; ntries++) { 92 if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN) 93 break; 94 rtwn_delay(sc, 10); 95 } 96 if (ntries == 5000) { 97 device_printf(sc->sc_dev, 98 "timeout waiting for chip autoload\n"); 99 return (ETIMEDOUT); 100 } 101 102 /* Unlock ISO/CLK/Power control register. */ 103 RTWN_CHK(rtwn_write_1(sc, R92C_RSV_CTRL, 0)); 104 105 /* Move SPS into PWM mode. */ 106 RTWN_CHK(rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b)); 107 108 /* just in case if power_off() was not properly executed. */ 109 rtwn_delay(sc, 100); 110 111 reg = rtwn_read_1(sc, R92C_LDOV12D_CTRL); 112 if (!(reg & R92C_LDOV12D_CTRL_LDV12_EN)) { 113 RTWN_CHK(rtwn_write_1(sc, R92C_LDOV12D_CTRL, 114 reg | R92C_LDOV12D_CTRL_LDV12_EN)); 115 116 rtwn_delay(sc, 100); 117 118 RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, 119 R92C_SYS_ISO_CTRL_MD2PP, 0)); 120 } 121 122 /* Auto enable WLAN. */ 123 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, 124 R92C_APS_FSMCO_APFM_ONMAC, 1)); 125 126 for (ntries = 0; ntries < 5000; ntries++) { 127 if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & 128 R92C_APS_FSMCO_APFM_ONMAC)) 129 break; 130 rtwn_delay(sc, 10); 131 } 132 if (ntries == 5000) { 133 device_printf(sc->sc_dev, 134 "timeout waiting for MAC auto ON\n"); 135 return (ETIMEDOUT); 136 } 137 138 /* Enable radio, GPIO and LED functions. */ 139 RTWN_CHK(rtwn_write_2(sc, R92C_APS_FSMCO, 140 R92C_APS_FSMCO_AFSM_HSUS | 141 R92C_APS_FSMCO_PDN_EN | 142 R92C_APS_FSMCO_PFM_ALDN)); 143 144 /* Release RF digital isolation. */ 145 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_SYS_ISO_CTRL, 146 R92C_SYS_ISO_CTRL_DIOR, 0, 1)); 147 148 /* Initialize MAC. */ 149 RTWN_CHK(rtwn_setbits_1(sc, R92C_APSD_CTRL, 150 R92C_APSD_CTRL_OFF, 0)); 151 for (ntries = 0; ntries < 1000; ntries++) { 152 if (!(rtwn_read_1(sc, R92C_APSD_CTRL) & 153 R92C_APSD_CTRL_OFF_STATUS)) 154 break; 155 rtwn_delay(sc, 50); 156 } 157 if (ntries == 1000) { 158 device_printf(sc->sc_dev, 159 "timeout waiting for MAC initialization\n"); 160 return (ETIMEDOUT); 161 } 162 163 /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ 164 RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, 165 R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | 166 R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | 167 R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | 168 ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | 169 R92C_CR_CALTMR_EN)); 170 171 RTWN_CHK(rtwn_write_1(sc, 0xfe10, 0x19)); 172 173 return (0); 174 #undef RTWN_CHK 175 } 176 177 void 178 r92cu_power_off(struct rtwn_softc *sc) 179 { 180 #ifndef RTWN_WITHOUT_UCODE 181 struct r92c_softc *rs = sc->sc_priv; 182 #endif 183 uint32_t reg; 184 int error; 185 186 /* Deinit C2H event handler. */ 187 #ifndef RTWN_WITHOUT_UCODE 188 callout_stop(&rs->rs_c2h_report); 189 rs->rs_c2h_paused = 0; 190 rs->rs_c2h_pending = 0; 191 rs->rs_c2h_timeout = hz; 192 #endif 193 194 /* Block all Tx queues. */ 195 error = rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); 196 if (error == ENXIO) /* hardware gone */ 197 return; 198 199 /* Disable RF */ 200 rtwn_rf_write(sc, 0, 0, 0); 201 202 rtwn_write_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF); 203 204 /* Reset BB state machine */ 205 rtwn_write_1(sc, R92C_SYS_FUNC_EN, 206 R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA | 207 R92C_SYS_FUNC_EN_BB_GLB_RST); 208 rtwn_write_1(sc, R92C_SYS_FUNC_EN, 209 R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA); 210 211 /* 212 * Reset digital sequence 213 */ 214 #ifndef RTWN_WITHOUT_UCODE 215 if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY) { 216 /* Reset MCU ready status */ 217 rtwn_write_1(sc, R92C_MCUFWDL, 0); 218 219 /* If firmware in ram code, do reset */ 220 r92c_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN); 221 } 222 #endif 223 224 /* Reset MAC and Enable 8051 */ 225 rtwn_write_1(sc, R92C_SYS_FUNC_EN + 1, 226 (R92C_SYS_FUNC_EN_CPUEN | 227 R92C_SYS_FUNC_EN_ELDR | 228 R92C_SYS_FUNC_EN_HWPDN) >> 8); 229 230 /* Reset MCU ready status */ 231 rtwn_write_1(sc, R92C_MCUFWDL, 0); 232 233 /* Disable MAC clock */ 234 rtwn_write_2(sc, R92C_SYS_CLKR, 235 R92C_SYS_CLKR_ANAD16V_EN | 236 R92C_SYS_CLKR_ANA8M | 237 R92C_SYS_CLKR_LOADER_EN | 238 R92C_SYS_CLKR_80M_SSC_DIS | 239 R92C_SYS_CLKR_SYS_EN | 240 R92C_SYS_CLKR_RING_EN | 241 0x4000); 242 243 /* Disable AFE PLL */ 244 rtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x80); 245 246 /* Gated AFE DIG_CLOCK */ 247 rtwn_write_2(sc, R92C_AFE_XTAL_CTRL, 0x880F); 248 249 /* Isolated digital to PON */ 250 rtwn_write_1(sc, R92C_SYS_ISO_CTRL, 251 R92C_SYS_ISO_CTRL_MD2PP | 252 R92C_SYS_ISO_CTRL_PA2PCIE | 253 R92C_SYS_ISO_CTRL_PD2CORE | 254 R92C_SYS_ISO_CTRL_IP2MAC | 255 R92C_SYS_ISO_CTRL_DIOP | 256 R92C_SYS_ISO_CTRL_DIOE); 257 258 /* 259 * Pull GPIO PIN to balance level and LED control 260 */ 261 /* 1. Disable GPIO[7:0] */ 262 rtwn_write_2(sc, R92C_GPIO_IOSEL, 0x0000); 263 264 reg = rtwn_read_4(sc, R92C_GPIO_PIN_CTRL) & ~0x0000ff00; 265 reg |= ((reg << 8) & 0x0000ff00) | 0x00ff0000; 266 rtwn_write_4(sc, R92C_GPIO_PIN_CTRL, reg); 267 268 /* Disable GPIO[10:8] */ 269 rtwn_write_1(sc, R92C_MAC_PINMUX_CFG, 0x00); 270 271 reg = rtwn_read_2(sc, R92C_GPIO_IO_SEL) & ~0x00f0; 272 reg |= (((reg & 0x000f) << 4) | 0x0780); 273 rtwn_write_2(sc, R92C_GPIO_IO_SEL, reg); 274 275 /* Disable LED0 & 1 */ 276 rtwn_write_2(sc, R92C_LEDCFG0, 0x8080); 277 278 /* 279 * Reset digital sequence 280 */ 281 /* Disable ELDR clock */ 282 rtwn_write_2(sc, R92C_SYS_CLKR, 283 R92C_SYS_CLKR_ANAD16V_EN | 284 R92C_SYS_CLKR_ANA8M | 285 R92C_SYS_CLKR_LOADER_EN | 286 R92C_SYS_CLKR_80M_SSC_DIS | 287 R92C_SYS_CLKR_SYS_EN | 288 R92C_SYS_CLKR_RING_EN | 289 0x4000); 290 291 /* Isolated ELDR to PON */ 292 rtwn_write_1(sc, R92C_SYS_ISO_CTRL + 1, 293 (R92C_SYS_ISO_CTRL_DIOR | 294 R92C_SYS_ISO_CTRL_PWC_EV12V) >> 8); 295 296 /* 297 * Disable analog sequence 298 */ 299 /* Disable A15 power */ 300 rtwn_write_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_OBUF); 301 /* Disable digital core power */ 302 rtwn_setbits_1(sc, R92C_LDOV12D_CTRL, 303 R92C_LDOV12D_CTRL_LDV12_EN, 0); 304 305 /* Enter PFM mode */ 306 rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); 307 308 /* Set USB suspend */ 309 rtwn_write_2(sc, R92C_APS_FSMCO, 310 R92C_APS_FSMCO_APDM_HOST | 311 R92C_APS_FSMCO_AFSM_HSUS | 312 R92C_APS_FSMCO_PFM_ALDN); 313 314 /* Lock ISO/CLK/Power control register. */ 315 rtwn_write_1(sc, R92C_RSV_CTRL, 0x0E); 316 } 317 318 void 319 r92cu_init_intr(struct rtwn_softc *sc) 320 { 321 rtwn_write_4(sc, R92C_HISR, 0xffffffff); 322 rtwn_write_4(sc, R92C_HIMR, 0xffffffff); 323 } 324 325 void 326 r92cu_init_tx_agg(struct rtwn_softc *sc) 327 { 328 struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); 329 uint32_t reg; 330 331 reg = rtwn_read_4(sc, R92C_TDECTRL); 332 reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, uc->tx_agg_desc_num); 333 rtwn_write_4(sc, R92C_TDECTRL, reg); 334 } 335 336 void 337 r92cu_init_rx_agg(struct rtwn_softc *sc) 338 { 339 340 /* Rx aggregation (DMA & USB). */ 341 rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, 342 R92C_TRXDMA_CTRL_RXDMA_AGG_EN); 343 rtwn_setbits_1(sc, R92C_USB_SPECIAL_OPTION, 0, 344 R92C_USB_SPECIAL_OPTION_AGG_EN); 345 346 /* XXX dehardcode */ 347 rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48); 348 rtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4); 349 rtwn_write_1(sc, R92C_USB_AGG_TH, 8); 350 rtwn_write_1(sc, R92C_USB_AGG_TO, 6); 351 } 352 353 void 354 r92cu_post_init(struct rtwn_softc *sc) 355 { 356 357 rtwn_write_4(sc, R92C_POWER_STATUS, 0x5); 358 359 /* Perform LO and IQ calibrations. */ 360 r92c_iq_calib(sc); 361 /* Perform LC calibration. */ 362 r92c_lc_calib(sc); 363 364 /* Fix USB interference issue. */ 365 rtwn_write_1(sc, 0xfe40, 0xe0); 366 rtwn_write_1(sc, 0xfe41, 0x8d); 367 rtwn_write_1(sc, 0xfe42, 0x80); 368 369 r92c_pa_bias_init(sc); 370 371 /* Fix for lower temperature. */ 372 rtwn_write_1(sc, 0x15, 0xe9); 373 374 #ifndef RTWN_WITHOUT_UCODE 375 if (sc->sc_flags & RTWN_FW_LOADED) { 376 struct r92c_softc *rs = sc->sc_priv; 377 378 if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) { 379 /* XXX firmware RA does not work yet */ 380 sc->sc_ratectl = RTWN_RATECTL_NET80211; 381 } else 382 sc->sc_ratectl = sc->sc_ratectl_sysctl; 383 384 /* Start C2H event handling. */ 385 callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout, 386 r92c_handle_c2h_report, sc); 387 } else 388 #endif 389 sc->sc_ratectl = RTWN_RATECTL_NONE; 390 } 391