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