17453645fSAndriy Voskoboinyk /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
27453645fSAndriy Voskoboinyk
37453645fSAndriy Voskoboinyk /*-
47453645fSAndriy Voskoboinyk * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
57453645fSAndriy Voskoboinyk * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
67453645fSAndriy Voskoboinyk * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
77453645fSAndriy Voskoboinyk *
87453645fSAndriy Voskoboinyk * Permission to use, copy, modify, and distribute this software for any
97453645fSAndriy Voskoboinyk * purpose with or without fee is hereby granted, provided that the above
107453645fSAndriy Voskoboinyk * copyright notice and this permission notice appear in all copies.
117453645fSAndriy Voskoboinyk *
127453645fSAndriy Voskoboinyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
137453645fSAndriy Voskoboinyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
147453645fSAndriy Voskoboinyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
157453645fSAndriy Voskoboinyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
167453645fSAndriy Voskoboinyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
177453645fSAndriy Voskoboinyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
187453645fSAndriy Voskoboinyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
197453645fSAndriy Voskoboinyk */
207453645fSAndriy Voskoboinyk
217453645fSAndriy Voskoboinyk #include <sys/cdefs.h>
227453645fSAndriy Voskoboinyk #include "opt_wlan.h"
237453645fSAndriy Voskoboinyk
247453645fSAndriy Voskoboinyk #include <sys/param.h>
257453645fSAndriy Voskoboinyk #include <sys/lock.h>
267453645fSAndriy Voskoboinyk #include <sys/mutex.h>
277453645fSAndriy Voskoboinyk #include <sys/mbuf.h>
287453645fSAndriy Voskoboinyk #include <sys/kernel.h>
297453645fSAndriy Voskoboinyk #include <sys/socket.h>
307453645fSAndriy Voskoboinyk #include <sys/systm.h>
317453645fSAndriy Voskoboinyk #include <sys/malloc.h>
327453645fSAndriy Voskoboinyk #include <sys/queue.h>
337453645fSAndriy Voskoboinyk #include <sys/taskqueue.h>
347453645fSAndriy Voskoboinyk #include <sys/bus.h>
357453645fSAndriy Voskoboinyk #include <sys/endian.h>
367453645fSAndriy Voskoboinyk #include <sys/linker.h>
377453645fSAndriy Voskoboinyk
387453645fSAndriy Voskoboinyk #include <net/if.h>
397453645fSAndriy Voskoboinyk #include <net/ethernet.h>
407453645fSAndriy Voskoboinyk #include <net/if_media.h>
417453645fSAndriy Voskoboinyk
427453645fSAndriy Voskoboinyk #include <net80211/ieee80211_var.h>
437453645fSAndriy Voskoboinyk #include <net80211/ieee80211_radiotap.h>
447453645fSAndriy Voskoboinyk
457453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnreg.h>
467453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnvar.h>
477453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwn_debug.h>
487453645fSAndriy Voskoboinyk
497453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/r92c.h>
507453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/r92c_priv.h>
517453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/r92c_reg.h>
527453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/r92c_var.h>
537453645fSAndriy Voskoboinyk
547453645fSAndriy Voskoboinyk int
r92c_check_condition(struct rtwn_softc * sc,const uint8_t cond[])557453645fSAndriy Voskoboinyk r92c_check_condition(struct rtwn_softc *sc, const uint8_t cond[])
567453645fSAndriy Voskoboinyk {
577453645fSAndriy Voskoboinyk struct r92c_softc *rs = sc->sc_priv;
587453645fSAndriy Voskoboinyk uint8_t mask;
597453645fSAndriy Voskoboinyk int i;
607453645fSAndriy Voskoboinyk
617453645fSAndriy Voskoboinyk if (cond[0] == 0)
627453645fSAndriy Voskoboinyk return (1);
637453645fSAndriy Voskoboinyk
647453645fSAndriy Voskoboinyk RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
657453645fSAndriy Voskoboinyk "%s: condition byte 0: %02X; chip %02X, board %02X\n",
667453645fSAndriy Voskoboinyk __func__, cond[0], rs->chip, rs->board_type);
677453645fSAndriy Voskoboinyk
687453645fSAndriy Voskoboinyk if (!(rs->chip & R92C_CHIP_92C)) {
697453645fSAndriy Voskoboinyk if (rs->board_type == R92C_BOARD_TYPE_HIGHPA)
707453645fSAndriy Voskoboinyk mask = R92C_COND_RTL8188RU;
717453645fSAndriy Voskoboinyk else if (rs->board_type == R92C_BOARD_TYPE_MINICARD)
727453645fSAndriy Voskoboinyk mask = R92C_COND_RTL8188CE;
737453645fSAndriy Voskoboinyk else
747453645fSAndriy Voskoboinyk mask = R92C_COND_RTL8188CU;
757453645fSAndriy Voskoboinyk } else {
767453645fSAndriy Voskoboinyk if (rs->board_type == R92C_BOARD_TYPE_MINICARD)
777453645fSAndriy Voskoboinyk mask = R92C_COND_RTL8192CE;
787453645fSAndriy Voskoboinyk else
797453645fSAndriy Voskoboinyk mask = R92C_COND_RTL8192CU;
807453645fSAndriy Voskoboinyk }
817453645fSAndriy Voskoboinyk
827453645fSAndriy Voskoboinyk for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++)
837453645fSAndriy Voskoboinyk if ((cond[i] & mask) == mask)
847453645fSAndriy Voskoboinyk return (1);
857453645fSAndriy Voskoboinyk
867453645fSAndriy Voskoboinyk return (0);
877453645fSAndriy Voskoboinyk }
887453645fSAndriy Voskoboinyk
897453645fSAndriy Voskoboinyk int
r92c_llt_init(struct rtwn_softc * sc)9060b9567dSKevin Lo r92c_llt_init(struct rtwn_softc *sc)
9160b9567dSKevin Lo {
9260b9567dSKevin Lo int i, error;
9360b9567dSKevin Lo
9460b9567dSKevin Lo /* Reserve pages [0; page_count]. */
9560b9567dSKevin Lo for (i = 0; i < sc->page_count; i++) {
9660b9567dSKevin Lo if ((error = r92c_llt_write(sc, i, i + 1)) != 0)
9760b9567dSKevin Lo return (error);
9860b9567dSKevin Lo }
9960b9567dSKevin Lo /* NB: 0xff indicates end-of-list. */
10060b9567dSKevin Lo if ((error = r92c_llt_write(sc, i, 0xff)) != 0)
10160b9567dSKevin Lo return (error);
10260b9567dSKevin Lo /*
10360b9567dSKevin Lo * Use pages [page_count + 1; pktbuf_count - 1]
10460b9567dSKevin Lo * as ring buffer.
10560b9567dSKevin Lo */
10660b9567dSKevin Lo for (++i; i < sc->pktbuf_count - 1; i++) {
10760b9567dSKevin Lo if ((error = r92c_llt_write(sc, i, i + 1)) != 0)
10860b9567dSKevin Lo return (error);
10960b9567dSKevin Lo }
11060b9567dSKevin Lo /* Make the last page point to the beginning of the ring buffer. */
11160b9567dSKevin Lo error = r92c_llt_write(sc, i, sc->page_count + 1);
11260b9567dSKevin Lo return (error);
11360b9567dSKevin Lo }
11460b9567dSKevin Lo
11560b9567dSKevin Lo int
r92c_set_page_size(struct rtwn_softc * sc)1167453645fSAndriy Voskoboinyk r92c_set_page_size(struct rtwn_softc *sc)
1177453645fSAndriy Voskoboinyk {
1187453645fSAndriy Voskoboinyk return (rtwn_write_1(sc, R92C_PBP, SM(R92C_PBP_PSRX, R92C_PBP_128) |
1197453645fSAndriy Voskoboinyk SM(R92C_PBP_PSTX, R92C_PBP_128)) == 0);
1207453645fSAndriy Voskoboinyk }
1217453645fSAndriy Voskoboinyk
1227453645fSAndriy Voskoboinyk void
r92c_init_bb_common(struct rtwn_softc * sc)1237453645fSAndriy Voskoboinyk r92c_init_bb_common(struct rtwn_softc *sc)
1247453645fSAndriy Voskoboinyk {
1257453645fSAndriy Voskoboinyk struct r92c_softc *rs = sc->sc_priv;
1267453645fSAndriy Voskoboinyk int i, j;
1277453645fSAndriy Voskoboinyk
1287453645fSAndriy Voskoboinyk /* Write BB initialization values. */
1297453645fSAndriy Voskoboinyk for (i = 0; i < sc->bb_size; i++) {
1307453645fSAndriy Voskoboinyk const struct rtwn_bb_prog *bb_prog = &sc->bb_prog[i];
1317453645fSAndriy Voskoboinyk
1327453645fSAndriy Voskoboinyk while (!rtwn_check_condition(sc, bb_prog->cond)) {
1337453645fSAndriy Voskoboinyk KASSERT(bb_prog->next != NULL,
1347453645fSAndriy Voskoboinyk ("%s: wrong condition value (i %d)\n",
1357453645fSAndriy Voskoboinyk __func__, i));
1367453645fSAndriy Voskoboinyk bb_prog = bb_prog->next;
1377453645fSAndriy Voskoboinyk }
1387453645fSAndriy Voskoboinyk
1397453645fSAndriy Voskoboinyk for (j = 0; j < bb_prog->count; j++) {
1407453645fSAndriy Voskoboinyk RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
1417453645fSAndriy Voskoboinyk "BB: reg 0x%03x, val 0x%08x\n",
1427453645fSAndriy Voskoboinyk bb_prog->reg[j], bb_prog->val[j]);
1437453645fSAndriy Voskoboinyk
1447453645fSAndriy Voskoboinyk rtwn_bb_write(sc, bb_prog->reg[j], bb_prog->val[j]);
1457453645fSAndriy Voskoboinyk rtwn_delay(sc, 1);
1467453645fSAndriy Voskoboinyk }
1477453645fSAndriy Voskoboinyk }
1487453645fSAndriy Voskoboinyk
1497453645fSAndriy Voskoboinyk if (rs->chip & R92C_CHIP_92C_1T2R) {
1507453645fSAndriy Voskoboinyk /* 8192C 1T only configuration. */
1517453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_FPGA0_TXINFO, 0x03, 0x02);
1527453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_FPGA1_TXINFO, 0x300033, 0x200022);
1537453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0xff000000,
1547453645fSAndriy Voskoboinyk 0x45000000);
1557453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_OFDM0_TRXPATHENA, 0xff, 0x23);
1567453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_OFDM0_AGCPARAM1, 0x30, 0x10);
1577453645fSAndriy Voskoboinyk
1587453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, 0xe74, 0x0c000000, 0x08000000);
1597453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, 0xe78, 0x0c000000, 0x08000000);
1607453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, 0xe7c, 0x0c000000, 0x08000000);
1617453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, 0xe80, 0x0c000000, 0x08000000);
1627453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, 0xe88, 0x0c000000, 0x08000000);
1637453645fSAndriy Voskoboinyk }
1647453645fSAndriy Voskoboinyk
1657453645fSAndriy Voskoboinyk /* Write AGC values. */
1667453645fSAndriy Voskoboinyk for (i = 0; i < sc->agc_size; i++) {
1677453645fSAndriy Voskoboinyk const struct rtwn_agc_prog *agc_prog = &sc->agc_prog[i];
1687453645fSAndriy Voskoboinyk
1697453645fSAndriy Voskoboinyk while (!rtwn_check_condition(sc, agc_prog->cond)) {
1707453645fSAndriy Voskoboinyk KASSERT(agc_prog->next != NULL,
1717453645fSAndriy Voskoboinyk ("%s: wrong condition value (2) (i %d)\n",
1727453645fSAndriy Voskoboinyk __func__, i));
1737453645fSAndriy Voskoboinyk agc_prog = agc_prog->next;
1747453645fSAndriy Voskoboinyk }
1757453645fSAndriy Voskoboinyk
1767453645fSAndriy Voskoboinyk for (j = 0; j < agc_prog->count; j++) {
1777453645fSAndriy Voskoboinyk RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
1787453645fSAndriy Voskoboinyk "AGC: val 0x%08x\n", agc_prog->val[j]);
1797453645fSAndriy Voskoboinyk
1807453645fSAndriy Voskoboinyk rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE,
1817453645fSAndriy Voskoboinyk agc_prog->val[j]);
1827453645fSAndriy Voskoboinyk rtwn_delay(sc, 1);
1837453645fSAndriy Voskoboinyk }
1847453645fSAndriy Voskoboinyk }
185d01f7b29SKevin Lo
186d01f7b29SKevin Lo if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & R92C_HSSI_PARAM2_CCK_HIPWR)
187d01f7b29SKevin Lo sc->sc_flags |= RTWN_FLAG_CCK_HIPWR;
1887453645fSAndriy Voskoboinyk }
1897453645fSAndriy Voskoboinyk
1907453645fSAndriy Voskoboinyk int
r92c_init_rf_chain(struct rtwn_softc * sc,const struct rtwn_rf_prog * rf_prog,int chain)1917453645fSAndriy Voskoboinyk r92c_init_rf_chain(struct rtwn_softc *sc,
1927453645fSAndriy Voskoboinyk const struct rtwn_rf_prog *rf_prog, int chain)
1937453645fSAndriy Voskoboinyk {
1947453645fSAndriy Voskoboinyk int i, j;
1957453645fSAndriy Voskoboinyk
1967453645fSAndriy Voskoboinyk RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: chain %d\n",
1977453645fSAndriy Voskoboinyk __func__, chain);
1987453645fSAndriy Voskoboinyk
1997453645fSAndriy Voskoboinyk for (i = 0; rf_prog[i].reg != NULL; i++) {
2007453645fSAndriy Voskoboinyk const struct rtwn_rf_prog *prog = &rf_prog[i];
2017453645fSAndriy Voskoboinyk
2027453645fSAndriy Voskoboinyk while (!rtwn_check_condition(sc, prog->cond)) {
2037453645fSAndriy Voskoboinyk KASSERT(prog->next != NULL,
2047453645fSAndriy Voskoboinyk ("%s: wrong condition value (i %d)\n",
2057453645fSAndriy Voskoboinyk __func__, i));
2067453645fSAndriy Voskoboinyk prog = prog->next;
2077453645fSAndriy Voskoboinyk }
2087453645fSAndriy Voskoboinyk
2097453645fSAndriy Voskoboinyk for (j = 0; j < prog->count; j++) {
2107453645fSAndriy Voskoboinyk RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
2117453645fSAndriy Voskoboinyk "RF: reg 0x%02x, val 0x%05x\n",
2127453645fSAndriy Voskoboinyk prog->reg[j], prog->val[j]);
2137453645fSAndriy Voskoboinyk
2147453645fSAndriy Voskoboinyk /*
2157453645fSAndriy Voskoboinyk * These are fake RF registers offsets that
2167453645fSAndriy Voskoboinyk * indicate a delay is required.
2177453645fSAndriy Voskoboinyk */
2187453645fSAndriy Voskoboinyk /* NB: we are using 'value' to store required delay. */
2197453645fSAndriy Voskoboinyk if (prog->reg[j] > 0xf8) {
2207453645fSAndriy Voskoboinyk rtwn_delay(sc, prog->val[j]);
2217453645fSAndriy Voskoboinyk continue;
2227453645fSAndriy Voskoboinyk }
2237453645fSAndriy Voskoboinyk
2247453645fSAndriy Voskoboinyk rtwn_rf_write(sc, chain, prog->reg[j], prog->val[j]);
2257453645fSAndriy Voskoboinyk rtwn_delay(sc, 1);
2267453645fSAndriy Voskoboinyk }
2277453645fSAndriy Voskoboinyk }
2287453645fSAndriy Voskoboinyk
2297453645fSAndriy Voskoboinyk return (i);
2307453645fSAndriy Voskoboinyk }
2317453645fSAndriy Voskoboinyk
2327453645fSAndriy Voskoboinyk void
r92c_init_rf(struct rtwn_softc * sc)23312bc2341SKevin Lo r92c_init_rf(struct rtwn_softc *sc)
2347453645fSAndriy Voskoboinyk {
2357453645fSAndriy Voskoboinyk struct r92c_softc *rs = sc->sc_priv;
2367453645fSAndriy Voskoboinyk uint32_t reg, type;
2377453645fSAndriy Voskoboinyk int i, chain, idx, off;
2387453645fSAndriy Voskoboinyk
2397453645fSAndriy Voskoboinyk for (chain = 0, i = 0; chain < sc->nrxchains; chain++, i++) {
2407453645fSAndriy Voskoboinyk /* Save RF_ENV control type. */
2417453645fSAndriy Voskoboinyk idx = chain / 2;
2427453645fSAndriy Voskoboinyk off = (chain % 2) * 16;
2437453645fSAndriy Voskoboinyk reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx));
2447453645fSAndriy Voskoboinyk type = (reg >> off) & 0x10;
2457453645fSAndriy Voskoboinyk
2467453645fSAndriy Voskoboinyk /* Set RF_ENV enable. */
2477453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain),
2487453645fSAndriy Voskoboinyk 0, 0x100000);
2497453645fSAndriy Voskoboinyk rtwn_delay(sc, 1);
2507453645fSAndriy Voskoboinyk /* Set RF_ENV output high. */
2517453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain),
2527453645fSAndriy Voskoboinyk 0, 0x10);
2537453645fSAndriy Voskoboinyk rtwn_delay(sc, 1);
2547453645fSAndriy Voskoboinyk /* Set address and data lengths of RF registers. */
2557453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain),
2567453645fSAndriy Voskoboinyk R92C_HSSI_PARAM2_ADDR_LENGTH, 0);
2577453645fSAndriy Voskoboinyk rtwn_delay(sc, 1);
2587453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain),
2597453645fSAndriy Voskoboinyk R92C_HSSI_PARAM2_DATA_LENGTH, 0);
2607453645fSAndriy Voskoboinyk rtwn_delay(sc, 1);
2617453645fSAndriy Voskoboinyk
2627453645fSAndriy Voskoboinyk /* Write RF initialization values for this chain. */
2637453645fSAndriy Voskoboinyk i += r92c_init_rf_chain(sc, &sc->rf_prog[i], chain);
2647453645fSAndriy Voskoboinyk
2657453645fSAndriy Voskoboinyk /* Restore RF_ENV control type. */
2667453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(idx),
2677453645fSAndriy Voskoboinyk 0x10 << off, type << off);
2687453645fSAndriy Voskoboinyk
2697453645fSAndriy Voskoboinyk /* Cache RF register CHNLBW. */
2707453645fSAndriy Voskoboinyk rs->rf_chnlbw[chain] = rtwn_rf_read(sc, chain,
2717453645fSAndriy Voskoboinyk R92C_RF_CHNLBW);
2727453645fSAndriy Voskoboinyk }
2737453645fSAndriy Voskoboinyk
2747453645fSAndriy Voskoboinyk if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) ==
2757453645fSAndriy Voskoboinyk R92C_CHIP_UMC_A_CUT) {
2767453645fSAndriy Voskoboinyk rtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255);
2777453645fSAndriy Voskoboinyk rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00);
2787453645fSAndriy Voskoboinyk }
2797453645fSAndriy Voskoboinyk
2807453645fSAndriy Voskoboinyk /* Turn CCK and OFDM blocks on. */
2817453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_CCK_EN);
2827453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_OFDM_EN);
2837453645fSAndriy Voskoboinyk }
2847453645fSAndriy Voskoboinyk
2857453645fSAndriy Voskoboinyk void
r92c_init_edca(struct rtwn_softc * sc)2867453645fSAndriy Voskoboinyk r92c_init_edca(struct rtwn_softc *sc)
2877453645fSAndriy Voskoboinyk {
2887453645fSAndriy Voskoboinyk /* SIFS */
2897453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a);
2907453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a);
2917453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_SIFS_CCK, 0x100a);
2927453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a);
2937453645fSAndriy Voskoboinyk /* TXOP */
2947453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b);
2957453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f);
2967453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005ea324);
2977453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002fa226);
2987453645fSAndriy Voskoboinyk }
2997453645fSAndriy Voskoboinyk
3007453645fSAndriy Voskoboinyk void
r92c_init_ampdu(struct rtwn_softc * sc)3017453645fSAndriy Voskoboinyk r92c_init_ampdu(struct rtwn_softc *sc)
3027453645fSAndriy Voskoboinyk {
3037453645fSAndriy Voskoboinyk
3047453645fSAndriy Voskoboinyk /* Setup AMPDU aggregation. */
3057453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
3067453645fSAndriy Voskoboinyk rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
3077453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0708);
3087453645fSAndriy Voskoboinyk }
3097453645fSAndriy Voskoboinyk
3107453645fSAndriy Voskoboinyk void
r92c_init_antsel(struct rtwn_softc * sc)3117453645fSAndriy Voskoboinyk r92c_init_antsel(struct rtwn_softc *sc)
3127453645fSAndriy Voskoboinyk {
3137453645fSAndriy Voskoboinyk uint32_t reg;
3147453645fSAndriy Voskoboinyk
3157453645fSAndriy Voskoboinyk if (sc->ntxchains != 1 || sc->nrxchains != 1)
3167453645fSAndriy Voskoboinyk return;
3177453645fSAndriy Voskoboinyk
3187453645fSAndriy Voskoboinyk rtwn_setbits_1(sc, R92C_LEDCFG2, 0, 0x80);
3197453645fSAndriy Voskoboinyk rtwn_bb_setbits(sc, R92C_FPGA0_RFPARAM(0), 0, 0x2000);
3207453645fSAndriy Voskoboinyk reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0));
3217453645fSAndriy Voskoboinyk sc->sc_ant = MS(reg, R92C_FPGA0_RFIFACEOE0_ANT); /* XXX */
322*d225ba4aSAndriy Voskoboinyk rtwn_setbits_1(sc, R92C_LEDCFG2, 0x80, 0);
3237453645fSAndriy Voskoboinyk }
3247453645fSAndriy Voskoboinyk
3257453645fSAndriy Voskoboinyk void
r92c_pa_bias_init(struct rtwn_softc * sc)3267453645fSAndriy Voskoboinyk r92c_pa_bias_init(struct rtwn_softc *sc)
3277453645fSAndriy Voskoboinyk {
3287453645fSAndriy Voskoboinyk struct r92c_softc *rs = sc->sc_priv;
3297453645fSAndriy Voskoboinyk int i;
3307453645fSAndriy Voskoboinyk
3317453645fSAndriy Voskoboinyk for (i = 0; i < sc->nrxchains; i++) {
3327453645fSAndriy Voskoboinyk if (rs->pa_setting & (1 << i))
3337453645fSAndriy Voskoboinyk continue;
3347453645fSAndriy Voskoboinyk r92c_rf_write(sc, i, R92C_RF_IPA, 0x0f406);
3357453645fSAndriy Voskoboinyk r92c_rf_write(sc, i, R92C_RF_IPA, 0x4f406);
3367453645fSAndriy Voskoboinyk r92c_rf_write(sc, i, R92C_RF_IPA, 0x8f406);
3377453645fSAndriy Voskoboinyk r92c_rf_write(sc, i, R92C_RF_IPA, 0xcf406);
3387453645fSAndriy Voskoboinyk }
3397453645fSAndriy Voskoboinyk if (!(rs->pa_setting & 0x10))
3407453645fSAndriy Voskoboinyk rtwn_setbits_1(sc, 0x16, 0xf0, 0x90);
3417453645fSAndriy Voskoboinyk }
342