xref: /freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
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