xref: /freebsd/sys/dev/rtwn/rtl8821a/r21a_init.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
17453645fSAndriy Voskoboinyk /*-
27453645fSAndriy Voskoboinyk  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
37453645fSAndriy Voskoboinyk  * All rights reserved.
47453645fSAndriy Voskoboinyk  *
57453645fSAndriy Voskoboinyk  * Redistribution and use in source and binary forms, with or without
67453645fSAndriy Voskoboinyk  * modification, are permitted provided that the following conditions
77453645fSAndriy Voskoboinyk  * are met:
87453645fSAndriy Voskoboinyk  * 1. Redistributions of source code must retain the above copyright
97453645fSAndriy Voskoboinyk  *    notice, this list of conditions and the following disclaimer.
107453645fSAndriy Voskoboinyk  * 2. Redistributions in binary form must reproduce the above copyright
117453645fSAndriy Voskoboinyk  *    notice, this list of conditions and the following disclaimer in the
127453645fSAndriy Voskoboinyk  *    documentation and/or other materials provided with the distribution.
137453645fSAndriy Voskoboinyk  *
147453645fSAndriy Voskoboinyk  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
157453645fSAndriy Voskoboinyk  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
167453645fSAndriy Voskoboinyk  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
177453645fSAndriy Voskoboinyk  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
187453645fSAndriy Voskoboinyk  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
197453645fSAndriy Voskoboinyk  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
207453645fSAndriy Voskoboinyk  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
217453645fSAndriy Voskoboinyk  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
227453645fSAndriy Voskoboinyk  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
237453645fSAndriy Voskoboinyk  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
247453645fSAndriy Voskoboinyk  * SUCH DAMAGE.
257453645fSAndriy Voskoboinyk  */
267453645fSAndriy Voskoboinyk 
277453645fSAndriy Voskoboinyk #include <sys/cdefs.h>
287453645fSAndriy Voskoboinyk #include "opt_wlan.h"
297453645fSAndriy Voskoboinyk 
307453645fSAndriy Voskoboinyk #include <sys/param.h>
317453645fSAndriy Voskoboinyk #include <sys/lock.h>
327453645fSAndriy Voskoboinyk #include <sys/mutex.h>
337453645fSAndriy Voskoboinyk #include <sys/mbuf.h>
347453645fSAndriy Voskoboinyk #include <sys/kernel.h>
357453645fSAndriy Voskoboinyk #include <sys/socket.h>
367453645fSAndriy Voskoboinyk #include <sys/systm.h>
377453645fSAndriy Voskoboinyk #include <sys/malloc.h>
387453645fSAndriy Voskoboinyk #include <sys/queue.h>
397453645fSAndriy Voskoboinyk #include <sys/taskqueue.h>
407453645fSAndriy Voskoboinyk #include <sys/bus.h>
417453645fSAndriy Voskoboinyk #include <sys/endian.h>
427453645fSAndriy Voskoboinyk #include <sys/linker.h>
437453645fSAndriy Voskoboinyk 
447453645fSAndriy Voskoboinyk #include <net/if.h>
457453645fSAndriy Voskoboinyk #include <net/ethernet.h>
467453645fSAndriy Voskoboinyk #include <net/if_media.h>
477453645fSAndriy Voskoboinyk 
487453645fSAndriy Voskoboinyk #include <net80211/ieee80211_var.h>
497453645fSAndriy Voskoboinyk #include <net80211/ieee80211_radiotap.h>
507453645fSAndriy Voskoboinyk 
517453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnreg.h>
527453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnvar.h>
537453645fSAndriy Voskoboinyk 
547453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwn_debug.h>
557453645fSAndriy Voskoboinyk 
567453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8812a/r12a_var.h>
577453645fSAndriy Voskoboinyk 
587453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8821a/r21a.h>
597453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8821a/r21a_priv.h>
607453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8821a/r21a_reg.h>
617453645fSAndriy Voskoboinyk 
627453645fSAndriy Voskoboinyk int
r21a_power_on(struct rtwn_softc * sc)637453645fSAndriy Voskoboinyk r21a_power_on(struct rtwn_softc *sc)
647453645fSAndriy Voskoboinyk {
657453645fSAndriy Voskoboinyk #define RTWN_CHK(res) do {	\
667453645fSAndriy Voskoboinyk 	if (res != 0)		\
677453645fSAndriy Voskoboinyk 		return (EIO);	\
687453645fSAndriy Voskoboinyk } while(0)
697453645fSAndriy Voskoboinyk 	int ntries;
707453645fSAndriy Voskoboinyk 
717453645fSAndriy Voskoboinyk 	/* Clear suspend and power down bits.*/
727453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
737453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_APDM_HPDN, 0, 1));
747453645fSAndriy Voskoboinyk 
757453645fSAndriy Voskoboinyk 	/* Disable GPIO9 as EXT WAKEUP. */
767453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0x01, 0));
777453645fSAndriy Voskoboinyk 
787453645fSAndriy Voskoboinyk 	/* Enable WL suspend. */
797453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
807453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
817453645fSAndriy Voskoboinyk 
827453645fSAndriy Voskoboinyk 	/* Enable LDOA12 MACRO block for all interfaces. */
837453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_LDOA15_CTRL, 0, R92C_LDOA15_CTRL_EN));
847453645fSAndriy Voskoboinyk 
857453645fSAndriy Voskoboinyk 	/* Disable BT_GPS_SEL pins. */
867453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0x10, 0));
877453645fSAndriy Voskoboinyk 
887453645fSAndriy Voskoboinyk 	/* 1 ms delay. */
897453645fSAndriy Voskoboinyk 	rtwn_delay(sc, 1000);
907453645fSAndriy Voskoboinyk 
917453645fSAndriy Voskoboinyk 	/* Release analog Ips to digital isolation. */
927453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL,
937453645fSAndriy Voskoboinyk 	    R92C_SYS_ISO_CTRL_IP2MAC, 0));
947453645fSAndriy Voskoboinyk 
957453645fSAndriy Voskoboinyk 	/* Disable SW LPS and WL suspend. */
967453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
977453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_APFM_RSM |
987453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_AFSM_HSUS |
997453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
1007453645fSAndriy Voskoboinyk 
1017453645fSAndriy Voskoboinyk 	/* Wait for power ready bit. */
1027453645fSAndriy Voskoboinyk 	for (ntries = 0; ntries < 5000; ntries++) {
1037453645fSAndriy Voskoboinyk 		if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
1047453645fSAndriy Voskoboinyk 			break;
1057453645fSAndriy Voskoboinyk 		rtwn_delay(sc, 10);
1067453645fSAndriy Voskoboinyk 	}
1077453645fSAndriy Voskoboinyk 	if (ntries == 5000) {
1087453645fSAndriy Voskoboinyk 		device_printf(sc->sc_dev,
1097453645fSAndriy Voskoboinyk 		    "timeout waiting for chip power up\n");
1107453645fSAndriy Voskoboinyk 		return (ETIMEDOUT);
1117453645fSAndriy Voskoboinyk 	}
1127453645fSAndriy Voskoboinyk 
1137453645fSAndriy Voskoboinyk 	/* Release WLON reset. */
1147453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
1157453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_RDY_MACON, 2));
1167453645fSAndriy Voskoboinyk 
1177453645fSAndriy Voskoboinyk 	/* Disable HWPDN. */
1187453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
1197453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_APDM_HPDN, 0, 1));
1207453645fSAndriy Voskoboinyk 
1217453645fSAndriy Voskoboinyk 	/* Disable WL suspend. */
1227453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
1237453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
1247453645fSAndriy Voskoboinyk 
1257453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
1267453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_APFM_ONMAC, 1));
1277453645fSAndriy Voskoboinyk 	for (ntries = 0; ntries < 5000; ntries++) {
1287453645fSAndriy Voskoboinyk 		if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
1297453645fSAndriy Voskoboinyk 		    R92C_APS_FSMCO_APFM_ONMAC))
1307453645fSAndriy Voskoboinyk 			break;
1317453645fSAndriy Voskoboinyk 		rtwn_delay(sc, 10);
1327453645fSAndriy Voskoboinyk 	}
1337453645fSAndriy Voskoboinyk 	if (ntries == 5000)
1347453645fSAndriy Voskoboinyk 		return (ETIMEDOUT);
1357453645fSAndriy Voskoboinyk 
1367453645fSAndriy Voskoboinyk 	/* Switch DPDT_SEL_P output from WL BB. */
1377453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_LEDCFG3, 0, 0x01));
1387453645fSAndriy Voskoboinyk 
1397453645fSAndriy Voskoboinyk 	/* switch for PAPE_G/PAPE_A from WL BB; switch LNAON from WL BB. */
1407453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0, 0x30));
1417453645fSAndriy Voskoboinyk 
1427453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, 0x025, 0x40, 0));
1437453645fSAndriy Voskoboinyk 
1447453645fSAndriy Voskoboinyk 	/* Enable falling edge triggering interrupt. */
1457453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0, 0x02));
1467453645fSAndriy Voskoboinyk 
1477453645fSAndriy Voskoboinyk 	/* Enable GPIO9 interrupt mode. */
1487453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, 0x063, 0, 0x02));
1497453645fSAndriy Voskoboinyk 
1507453645fSAndriy Voskoboinyk 	/* Enable GPIO9 input mode. */
1517453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, 0x062, 0x02, 0));
1527453645fSAndriy Voskoboinyk 
1537453645fSAndriy Voskoboinyk 	/* Enable HSISR GPIO interrupt. */
1547453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR, 0, 0x01));
1557453645fSAndriy Voskoboinyk 
1567453645fSAndriy Voskoboinyk 	/* Enable HSISR GPIO9 interrupt. */
1577453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR + 2, 0, 0x02));
1587453645fSAndriy Voskoboinyk 
1597453645fSAndriy Voskoboinyk 	/* XTAL trim. */
1607453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_APE_PLL_CTRL_EXT + 2, 0xFF, 0x82));
1617453645fSAndriy Voskoboinyk 
1627453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_MISC, 0, 0x40));
1637453645fSAndriy Voskoboinyk 
1647453645fSAndriy Voskoboinyk 	/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
1657453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0x0000));
1667453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
1677453645fSAndriy Voskoboinyk 	    R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
1687453645fSAndriy Voskoboinyk 	    R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
1697453645fSAndriy Voskoboinyk 	    R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
1707453645fSAndriy Voskoboinyk 	    ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
1717453645fSAndriy Voskoboinyk 	    R92C_CR_CALTMR_EN));
1727453645fSAndriy Voskoboinyk 
1737453645fSAndriy Voskoboinyk 	if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN)
174*60b9567dSKevin Lo 		RTWN_CHK(rtwn_setbits_1(sc, R92C_LDO_SWR_CTRL, 0, 0x40));
1757453645fSAndriy Voskoboinyk 
1767453645fSAndriy Voskoboinyk 	return (0);
1777453645fSAndriy Voskoboinyk #undef RTWN_CHK
1787453645fSAndriy Voskoboinyk }
1797453645fSAndriy Voskoboinyk 
1807453645fSAndriy Voskoboinyk void
r21a_power_off(struct rtwn_softc * sc)1817453645fSAndriy Voskoboinyk r21a_power_off(struct rtwn_softc *sc)
1827453645fSAndriy Voskoboinyk {
1837453645fSAndriy Voskoboinyk 	struct r12a_softc *rs = sc->sc_priv;
1847453645fSAndriy Voskoboinyk 	int error, ntries;
1857453645fSAndriy Voskoboinyk 
1867453645fSAndriy Voskoboinyk 	/* Stop Rx. */
1877453645fSAndriy Voskoboinyk 	error = rtwn_write_1(sc, R92C_CR, 0);
1887453645fSAndriy Voskoboinyk 	if (error == ENXIO)	/* hardware gone */
1897453645fSAndriy Voskoboinyk 		return;
1907453645fSAndriy Voskoboinyk 
1917453645fSAndriy Voskoboinyk 	/* Move card to Low Power state. */
1927453645fSAndriy Voskoboinyk 	/* Block all Tx queues. */
1937453645fSAndriy Voskoboinyk 	rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
1947453645fSAndriy Voskoboinyk 
1957453645fSAndriy Voskoboinyk 	for (ntries = 0; ntries < 10; ntries++) {
1967453645fSAndriy Voskoboinyk 		/* Should be zero if no packet is transmitting. */
1977453645fSAndriy Voskoboinyk 		if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
1987453645fSAndriy Voskoboinyk 			break;
1997453645fSAndriy Voskoboinyk 
2007453645fSAndriy Voskoboinyk 		rtwn_delay(sc, 5000);
2017453645fSAndriy Voskoboinyk 	}
2027453645fSAndriy Voskoboinyk 	if (ntries == 10) {
2037453645fSAndriy Voskoboinyk 		device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
2047453645fSAndriy Voskoboinyk 		    __func__);
2057453645fSAndriy Voskoboinyk 		return;
2067453645fSAndriy Voskoboinyk 	}
2077453645fSAndriy Voskoboinyk 
2087453645fSAndriy Voskoboinyk 	/* CCK and OFDM are disabled, and clock are gated. */
2097453645fSAndriy Voskoboinyk 	rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0);
2107453645fSAndriy Voskoboinyk 
2117453645fSAndriy Voskoboinyk 	rtwn_delay(sc, 1);
2127453645fSAndriy Voskoboinyk 
2137453645fSAndriy Voskoboinyk 	/* Reset whole BB. */
2147453645fSAndriy Voskoboinyk 	rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0);
2157453645fSAndriy Voskoboinyk 
2167453645fSAndriy Voskoboinyk 	/* Reset MAC TRX. */
2177453645fSAndriy Voskoboinyk 	rtwn_write_1(sc, R92C_CR,
2187453645fSAndriy Voskoboinyk 	    R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN);
2197453645fSAndriy Voskoboinyk 
2207453645fSAndriy Voskoboinyk 	/* check if removed later. (?) */
2217453645fSAndriy Voskoboinyk 	rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1);
2227453645fSAndriy Voskoboinyk 
2237453645fSAndriy Voskoboinyk 	/* Respond TxOK to scheduler */
2247453645fSAndriy Voskoboinyk 	rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK);
2257453645fSAndriy Voskoboinyk 
2267453645fSAndriy Voskoboinyk 	/* If firmware in ram code, do reset. */
2277453645fSAndriy Voskoboinyk #ifndef RTWN_WITHOUT_UCODE
2287453645fSAndriy Voskoboinyk 	if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL)
2297453645fSAndriy Voskoboinyk 		r21a_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
2307453645fSAndriy Voskoboinyk #endif
2317453645fSAndriy Voskoboinyk 
2327453645fSAndriy Voskoboinyk 	/* Reset MCU. */
2337453645fSAndriy Voskoboinyk 	rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN,
2347453645fSAndriy Voskoboinyk 	    0, 1);
2357453645fSAndriy Voskoboinyk 	rtwn_write_1(sc, R92C_MCUFWDL, 0);
2367453645fSAndriy Voskoboinyk 
2377453645fSAndriy Voskoboinyk 	/* Move card to Disabled state. */
2387453645fSAndriy Voskoboinyk 	/* Turn off RF. */
2397453645fSAndriy Voskoboinyk 	rtwn_write_1(sc, R92C_RF_CTRL, 0);
2407453645fSAndriy Voskoboinyk 
2417453645fSAndriy Voskoboinyk 	rtwn_setbits_1(sc, R92C_LEDCFG3, 0x01, 0);
2427453645fSAndriy Voskoboinyk 
2437453645fSAndriy Voskoboinyk 	/* Enable rising edge triggering interrupt. */
2447453645fSAndriy Voskoboinyk 	rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0x02, 0);
2457453645fSAndriy Voskoboinyk 
2467453645fSAndriy Voskoboinyk 	/* Release WLON reset. */
2477453645fSAndriy Voskoboinyk 	rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
2487453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_RDY_MACON, 2);
2497453645fSAndriy Voskoboinyk 
2507453645fSAndriy Voskoboinyk 	/* Turn off MAC by HW state machine */
2517453645fSAndriy Voskoboinyk 	rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_OFF,
2527453645fSAndriy Voskoboinyk 	    1);
2537453645fSAndriy Voskoboinyk 	for (ntries = 0; ntries < 10; ntries++) {
2547453645fSAndriy Voskoboinyk 		/* Wait until it will be disabled. */
2557453645fSAndriy Voskoboinyk 		if ((rtwn_read_2(sc, R92C_APS_FSMCO) &
2567453645fSAndriy Voskoboinyk 		    R92C_APS_FSMCO_APFM_OFF) == 0)
2577453645fSAndriy Voskoboinyk 			break;
2587453645fSAndriy Voskoboinyk 
2597453645fSAndriy Voskoboinyk 		rtwn_delay(sc, 5000);
2607453645fSAndriy Voskoboinyk 	}
2617453645fSAndriy Voskoboinyk 	if (ntries == 10) {
2627453645fSAndriy Voskoboinyk 		device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
2637453645fSAndriy Voskoboinyk 		    __func__);
2647453645fSAndriy Voskoboinyk 		return;
2657453645fSAndriy Voskoboinyk 	}
2667453645fSAndriy Voskoboinyk 
2677453645fSAndriy Voskoboinyk 	/* Analog Ips to digital isolation. */
2687453645fSAndriy Voskoboinyk 	rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, 0, R92C_SYS_ISO_CTRL_IP2MAC);
2697453645fSAndriy Voskoboinyk 
2707453645fSAndriy Voskoboinyk 	/* Disable LDOA12 MACRO block. */
2717453645fSAndriy Voskoboinyk 	rtwn_setbits_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_EN, 0);
2727453645fSAndriy Voskoboinyk 
2737453645fSAndriy Voskoboinyk 	/* Enable WL suspend. */
2747453645fSAndriy Voskoboinyk 	rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE,
2757453645fSAndriy Voskoboinyk 	    R92C_APS_FSMCO_AFSM_HSUS, 1);
2767453645fSAndriy Voskoboinyk 
2777453645fSAndriy Voskoboinyk 	/* Enable GPIO9 as EXT WAKEUP. */
2787453645fSAndriy Voskoboinyk 	rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0, 0x01);
2797453645fSAndriy Voskoboinyk 
280b8ad00b0SAndriy Voskoboinyk 	rs->rs_flags &= ~(R12A_IQK_RUNNING | R12A_RADAR_ENABLED);
2817453645fSAndriy Voskoboinyk }
2827453645fSAndriy Voskoboinyk 
2837453645fSAndriy Voskoboinyk int
r21a_check_condition(struct rtwn_softc * sc,const uint8_t cond[])2847453645fSAndriy Voskoboinyk r21a_check_condition(struct rtwn_softc *sc, const uint8_t cond[])
2857453645fSAndriy Voskoboinyk {
2867453645fSAndriy Voskoboinyk 	struct r12a_softc *rs = sc->sc_priv;
2877453645fSAndriy Voskoboinyk 	uint8_t mask;
2887453645fSAndriy Voskoboinyk 	int i;
2897453645fSAndriy Voskoboinyk 
2907453645fSAndriy Voskoboinyk 	RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
2917453645fSAndriy Voskoboinyk 	    "%s: condition byte 0: %02X; ext 5ghz pa/lna %d/%d\n",
2927453645fSAndriy Voskoboinyk 	    __func__, cond[0], rs->ext_pa_5g, rs->ext_lna_5g);
2937453645fSAndriy Voskoboinyk 
2947453645fSAndriy Voskoboinyk 	if (cond[0] == 0)
2957453645fSAndriy Voskoboinyk 		return (1);
2967453645fSAndriy Voskoboinyk 
2977453645fSAndriy Voskoboinyk 	mask = 0;
2987453645fSAndriy Voskoboinyk 	if (rs->ext_pa_5g)
2997453645fSAndriy Voskoboinyk 		mask |= R21A_COND_EXT_PA_5G;
3007453645fSAndriy Voskoboinyk 	if (rs->ext_lna_5g)
3017453645fSAndriy Voskoboinyk 		mask |= R21A_COND_EXT_LNA_5G;
3027453645fSAndriy Voskoboinyk 	if (rs->bt_coex)
3037453645fSAndriy Voskoboinyk 		mask |= R21A_COND_BT;
3047453645fSAndriy Voskoboinyk 	if (!rs->ext_pa_2g && !rs->ext_lna_2g &&
3057453645fSAndriy Voskoboinyk 	    !rs->ext_pa_5g && !rs->ext_lna_5g && !rs->bt_coex)
3067453645fSAndriy Voskoboinyk 		mask = R21A_COND_BOARD_DEF;
3077453645fSAndriy Voskoboinyk 
3087453645fSAndriy Voskoboinyk 	if (mask == 0)
3097453645fSAndriy Voskoboinyk 		return (0);
3107453645fSAndriy Voskoboinyk 
3117453645fSAndriy Voskoboinyk 	for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++)
3127453645fSAndriy Voskoboinyk 		if (cond[i] == mask)
3137453645fSAndriy Voskoboinyk 			return (1);
3147453645fSAndriy Voskoboinyk 
3157453645fSAndriy Voskoboinyk 	return (0);
3167453645fSAndriy Voskoboinyk }
3177453645fSAndriy Voskoboinyk 
3187453645fSAndriy Voskoboinyk void
r21a_crystalcap_write(struct rtwn_softc * sc)3197453645fSAndriy Voskoboinyk r21a_crystalcap_write(struct rtwn_softc *sc)
3207453645fSAndriy Voskoboinyk {
3217453645fSAndriy Voskoboinyk 	struct r12a_softc *rs = sc->sc_priv;
3227453645fSAndriy Voskoboinyk 	uint32_t reg;
3237453645fSAndriy Voskoboinyk 	uint8_t val;
3247453645fSAndriy Voskoboinyk 
3257453645fSAndriy Voskoboinyk 	val = rs->crystalcap & 0x3f;
3267453645fSAndriy Voskoboinyk 	reg = rtwn_bb_read(sc, R92C_MAC_PHY_CTRL);
3277453645fSAndriy Voskoboinyk 	reg = RW(reg, R21A_MAC_PHY_CRYSTALCAP, val | (val << 6));
3287453645fSAndriy Voskoboinyk 	rtwn_bb_write(sc, R92C_MAC_PHY_CTRL, reg);
3297453645fSAndriy Voskoboinyk }
3307453645fSAndriy Voskoboinyk 
3317453645fSAndriy Voskoboinyk int
r21a_init_bcnq1_boundary(struct rtwn_softc * sc)3327453645fSAndriy Voskoboinyk r21a_init_bcnq1_boundary(struct rtwn_softc *sc)
3337453645fSAndriy Voskoboinyk {
3347453645fSAndriy Voskoboinyk #define RTWN_CHK(res) do {	\
3357453645fSAndriy Voskoboinyk 	if (res != 0)		\
3367453645fSAndriy Voskoboinyk 		return (EIO);	\
3377453645fSAndriy Voskoboinyk } while(0)
3387453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_write_1(sc, R88E_TXPKTBUF_BCNQ1_BDNY,
3397453645fSAndriy Voskoboinyk 	    R21A_BCNQ0_BOUNDARY));
3407453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_write_1(sc, R21A_DWBCN1_CTRL + 1,
3417453645fSAndriy Voskoboinyk 	    R21A_BCNQ0_BOUNDARY));
3427453645fSAndriy Voskoboinyk 	RTWN_CHK(rtwn_setbits_1_shift(sc, R21A_DWBCN1_CTRL, 0,
3437453645fSAndriy Voskoboinyk 	    R21A_DWBCN1_CTRL_SEL_EN, 2));
3447453645fSAndriy Voskoboinyk 
3457453645fSAndriy Voskoboinyk 	return (0);
3467453645fSAndriy Voskoboinyk #undef RTWN_CHK
3477453645fSAndriy Voskoboinyk }
3487453645fSAndriy Voskoboinyk 
3497453645fSAndriy Voskoboinyk void
r21a_init_ampdu_fwhw(struct rtwn_softc * sc)3507453645fSAndriy Voskoboinyk r21a_init_ampdu_fwhw(struct rtwn_softc *sc)
3517453645fSAndriy Voskoboinyk {
3527453645fSAndriy Voskoboinyk 	rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL,
3537453645fSAndriy Voskoboinyk 	    R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
3547453645fSAndriy Voskoboinyk 	rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x03087777);
3557453645fSAndriy Voskoboinyk }
356