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