xref: /freebsd/sys/dev/rtwn/rtl8821a/r21a_init.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1 /*-
2  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 #include "opt_wlan.h"
29 
30 #include <sys/param.h>
31 #include <sys/lock.h>
32 #include <sys/mutex.h>
33 #include <sys/mbuf.h>
34 #include <sys/kernel.h>
35 #include <sys/socket.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/queue.h>
39 #include <sys/taskqueue.h>
40 #include <sys/bus.h>
41 #include <sys/endian.h>
42 #include <sys/linker.h>
43 
44 #include <net/if.h>
45 #include <net/ethernet.h>
46 #include <net/if_media.h>
47 
48 #include <net80211/ieee80211_var.h>
49 #include <net80211/ieee80211_radiotap.h>
50 
51 #include <dev/rtwn/if_rtwnreg.h>
52 #include <dev/rtwn/if_rtwnvar.h>
53 
54 #include <dev/rtwn/if_rtwn_debug.h>
55 
56 #include <dev/rtwn/rtl8812a/r12a_var.h>
57 
58 #include <dev/rtwn/rtl8821a/r21a.h>
59 #include <dev/rtwn/rtl8821a/r21a_priv.h>
60 #include <dev/rtwn/rtl8821a/r21a_reg.h>
61 
62 int
r21a_power_on(struct rtwn_softc * sc)63 r21a_power_on(struct rtwn_softc *sc)
64 {
65 #define RTWN_CHK(res) do {	\
66 	if (res != 0)		\
67 		return (EIO);	\
68 } while(0)
69 	int ntries;
70 
71 	/* Clear suspend and power down bits.*/
72 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
73 	    R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_APDM_HPDN, 0, 1));
74 
75 	/* Disable GPIO9 as EXT WAKEUP. */
76 	RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0x01, 0));
77 
78 	/* Enable WL suspend. */
79 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
80 	    R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
81 
82 	/* Enable LDOA12 MACRO block for all interfaces. */
83 	RTWN_CHK(rtwn_setbits_1(sc, R92C_LDOA15_CTRL, 0, R92C_LDOA15_CTRL_EN));
84 
85 	/* Disable BT_GPS_SEL pins. */
86 	RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0x10, 0));
87 
88 	/* 1 ms delay. */
89 	rtwn_delay(sc, 1000);
90 
91 	/* Release analog Ips to digital isolation. */
92 	RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL,
93 	    R92C_SYS_ISO_CTRL_IP2MAC, 0));
94 
95 	/* Disable SW LPS and WL suspend. */
96 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
97 	    R92C_APS_FSMCO_APFM_RSM |
98 	    R92C_APS_FSMCO_AFSM_HSUS |
99 	    R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
100 
101 	/* Wait for power ready bit. */
102 	for (ntries = 0; ntries < 5000; ntries++) {
103 		if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
104 			break;
105 		rtwn_delay(sc, 10);
106 	}
107 	if (ntries == 5000) {
108 		device_printf(sc->sc_dev,
109 		    "timeout waiting for chip power up\n");
110 		return (ETIMEDOUT);
111 	}
112 
113 	/* Release WLON reset. */
114 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
115 	    R92C_APS_FSMCO_RDY_MACON, 2));
116 
117 	/* Disable HWPDN. */
118 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
119 	    R92C_APS_FSMCO_APDM_HPDN, 0, 1));
120 
121 	/* Disable WL suspend. */
122 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
123 	    R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
124 
125 	RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
126 	    R92C_APS_FSMCO_APFM_ONMAC, 1));
127 	for (ntries = 0; ntries < 5000; ntries++) {
128 		if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
129 		    R92C_APS_FSMCO_APFM_ONMAC))
130 			break;
131 		rtwn_delay(sc, 10);
132 	}
133 	if (ntries == 5000)
134 		return (ETIMEDOUT);
135 
136 	/* Switch DPDT_SEL_P output from WL BB. */
137 	RTWN_CHK(rtwn_setbits_1(sc, R92C_LEDCFG3, 0, 0x01));
138 
139 	/* switch for PAPE_G/PAPE_A from WL BB; switch LNAON from WL BB. */
140 	RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0, 0x30));
141 
142 	RTWN_CHK(rtwn_setbits_1(sc, 0x025, 0x40, 0));
143 
144 	/* Enable falling edge triggering interrupt. */
145 	RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0, 0x02));
146 
147 	/* Enable GPIO9 interrupt mode. */
148 	RTWN_CHK(rtwn_setbits_1(sc, 0x063, 0, 0x02));
149 
150 	/* Enable GPIO9 input mode. */
151 	RTWN_CHK(rtwn_setbits_1(sc, 0x062, 0x02, 0));
152 
153 	/* Enable HSISR GPIO interrupt. */
154 	RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR, 0, 0x01));
155 
156 	/* Enable HSISR GPIO9 interrupt. */
157 	RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR + 2, 0, 0x02));
158 
159 	/* XTAL trim. */
160 	RTWN_CHK(rtwn_setbits_1(sc, R92C_APE_PLL_CTRL_EXT + 2, 0xFF, 0x82));
161 
162 	RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_MISC, 0, 0x40));
163 
164 	/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
165 	RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0x0000));
166 	RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
167 	    R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
168 	    R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
169 	    R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
170 	    ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
171 	    R92C_CR_CALTMR_EN));
172 
173 	if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN)
174 		RTWN_CHK(rtwn_setbits_1(sc, R92C_LDO_SWR_CTRL, 0, 0x40));
175 
176 	return (0);
177 #undef RTWN_CHK
178 }
179 
180 void
r21a_power_off(struct rtwn_softc * sc)181 r21a_power_off(struct rtwn_softc *sc)
182 {
183 	struct r12a_softc *rs = sc->sc_priv;
184 	int error, ntries;
185 
186 	/* Stop Rx. */
187 	error = rtwn_write_1(sc, R92C_CR, 0);
188 	if (error == ENXIO)	/* hardware gone */
189 		return;
190 
191 	/* Move card to Low Power state. */
192 	/* Block all Tx queues. */
193 	rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
194 
195 	for (ntries = 0; ntries < 10; ntries++) {
196 		/* Should be zero if no packet is transmitting. */
197 		if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
198 			break;
199 
200 		rtwn_delay(sc, 5000);
201 	}
202 	if (ntries == 10) {
203 		device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
204 		    __func__);
205 		return;
206 	}
207 
208 	/* CCK and OFDM are disabled, and clock are gated. */
209 	rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0);
210 
211 	rtwn_delay(sc, 1);
212 
213 	/* Reset whole BB. */
214 	rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0);
215 
216 	/* Reset MAC TRX. */
217 	rtwn_write_1(sc, R92C_CR,
218 	    R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN);
219 
220 	/* check if removed later. (?) */
221 	rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1);
222 
223 	/* Respond TxOK to scheduler */
224 	rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK);
225 
226 	/* If firmware in ram code, do reset. */
227 #ifndef RTWN_WITHOUT_UCODE
228 	if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL)
229 		r21a_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
230 #endif
231 
232 	/* Reset MCU. */
233 	rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN,
234 	    0, 1);
235 	rtwn_write_1(sc, R92C_MCUFWDL, 0);
236 
237 	/* Move card to Disabled state. */
238 	/* Turn off RF. */
239 	rtwn_write_1(sc, R92C_RF_CTRL, 0);
240 
241 	rtwn_setbits_1(sc, R92C_LEDCFG3, 0x01, 0);
242 
243 	/* Enable rising edge triggering interrupt. */
244 	rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0x02, 0);
245 
246 	/* Release WLON reset. */
247 	rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
248 	    R92C_APS_FSMCO_RDY_MACON, 2);
249 
250 	/* Turn off MAC by HW state machine */
251 	rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_OFF,
252 	    1);
253 	for (ntries = 0; ntries < 10; ntries++) {
254 		/* Wait until it will be disabled. */
255 		if ((rtwn_read_2(sc, R92C_APS_FSMCO) &
256 		    R92C_APS_FSMCO_APFM_OFF) == 0)
257 			break;
258 
259 		rtwn_delay(sc, 5000);
260 	}
261 	if (ntries == 10) {
262 		device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
263 		    __func__);
264 		return;
265 	}
266 
267 	/* Analog Ips to digital isolation. */
268 	rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, 0, R92C_SYS_ISO_CTRL_IP2MAC);
269 
270 	/* Disable LDOA12 MACRO block. */
271 	rtwn_setbits_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_EN, 0);
272 
273 	/* Enable WL suspend. */
274 	rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE,
275 	    R92C_APS_FSMCO_AFSM_HSUS, 1);
276 
277 	/* Enable GPIO9 as EXT WAKEUP. */
278 	rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0, 0x01);
279 
280 	rs->rs_flags &= ~(R12A_IQK_RUNNING | R12A_RADAR_ENABLED);
281 }
282 
283 int
r21a_check_condition(struct rtwn_softc * sc,const uint8_t cond[])284 r21a_check_condition(struct rtwn_softc *sc, const uint8_t cond[])
285 {
286 	struct r12a_softc *rs = sc->sc_priv;
287 	uint8_t mask;
288 	int i;
289 
290 	RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
291 	    "%s: condition byte 0: %02X; ext 5ghz pa/lna %d/%d\n",
292 	    __func__, cond[0], rs->ext_pa_5g, rs->ext_lna_5g);
293 
294 	if (cond[0] == 0)
295 		return (1);
296 
297 	mask = 0;
298 	if (rs->ext_pa_5g)
299 		mask |= R21A_COND_EXT_PA_5G;
300 	if (rs->ext_lna_5g)
301 		mask |= R21A_COND_EXT_LNA_5G;
302 	if (rs->bt_coex)
303 		mask |= R21A_COND_BT;
304 	if (!rs->ext_pa_2g && !rs->ext_lna_2g &&
305 	    !rs->ext_pa_5g && !rs->ext_lna_5g && !rs->bt_coex)
306 		mask = R21A_COND_BOARD_DEF;
307 
308 	if (mask == 0)
309 		return (0);
310 
311 	for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++)
312 		if (cond[i] == mask)
313 			return (1);
314 
315 	return (0);
316 }
317 
318 void
r21a_crystalcap_write(struct rtwn_softc * sc)319 r21a_crystalcap_write(struct rtwn_softc *sc)
320 {
321 	struct r12a_softc *rs = sc->sc_priv;
322 	uint32_t reg;
323 	uint8_t val;
324 
325 	val = rs->crystalcap & 0x3f;
326 	reg = rtwn_bb_read(sc, R92C_MAC_PHY_CTRL);
327 	reg = RW(reg, R21A_MAC_PHY_CRYSTALCAP, val | (val << 6));
328 	rtwn_bb_write(sc, R92C_MAC_PHY_CTRL, reg);
329 }
330 
331 int
r21a_init_bcnq1_boundary(struct rtwn_softc * sc)332 r21a_init_bcnq1_boundary(struct rtwn_softc *sc)
333 {
334 #define RTWN_CHK(res) do {	\
335 	if (res != 0)		\
336 		return (EIO);	\
337 } while(0)
338 	RTWN_CHK(rtwn_write_1(sc, R88E_TXPKTBUF_BCNQ1_BDNY,
339 	    R21A_BCNQ0_BOUNDARY));
340 	RTWN_CHK(rtwn_write_1(sc, R21A_DWBCN1_CTRL + 1,
341 	    R21A_BCNQ0_BOUNDARY));
342 	RTWN_CHK(rtwn_setbits_1_shift(sc, R21A_DWBCN1_CTRL, 0,
343 	    R21A_DWBCN1_CTRL_SEL_EN, 2));
344 
345 	return (0);
346 #undef RTWN_CHK
347 }
348 
349 void
r21a_init_ampdu_fwhw(struct rtwn_softc * sc)350 r21a_init_ampdu_fwhw(struct rtwn_softc *sc)
351 {
352 	rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL,
353 	    R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
354 	rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x03087777);
355 }
356