1 /*
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
5 * Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
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/usb/usb.h>
52 #include <dev/usb/usbdi.h>
53
54 #include <dev/rtwn/if_rtwnreg.h>
55 #include <dev/rtwn/if_rtwnvar.h>
56
57 #include <dev/rtwn/usb/rtwn_usb_var.h>
58
59 #include <dev/rtwn/rtl8188e/r88e_reg.h>
60
61 #include <dev/rtwn/rtl8192c/r92c_reg.h>
62
63 #include <dev/rtwn/rtl8192e/r92e_var.h>
64
65 #include <dev/rtwn/rtl8723b/r23b_reg.h>
66 #include <dev/rtwn/rtl8723b/r23b_var.h>
67
68 #include <dev/rtwn/rtl8723b/usb/r23bu.h>
69
70 #include <dev/rtwn/rtl8812a/r12a_reg.h>
71
72 int
r23bu_power_on(struct rtwn_softc * sc)73 r23bu_power_on(struct rtwn_softc *sc)
74 {
75 #define RTWN_CHK(res) do { \
76 if (res != 0) \
77 return (EIO); \
78 } while(0)
79 int ntries;
80
81 /* Clear suspend and power down bits.*/
82 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
83 R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_APDM_HPDN, 0, 1));
84
85 /* Disable GPIO9 as EXT WAKEUP. */
86 RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0x01, 0));
87
88 /* Enable WL suspend. */
89 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
90 R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
91
92 /* Enable LDOA12 MACRO block for all interfaces. */
93 RTWN_CHK(rtwn_setbits_1(sc, R92C_LDOA15_CTRL, 0, R92C_LDOA15_CTRL_EN));
94
95 /* Disable BT_GPS_SEL pins. */
96 RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0x10, 0));
97
98 /* 1 ms delay. */
99 rtwn_delay(sc, 1000);
100
101 /* Release analog Ips to digital isolation. */
102 RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL,
103 R92C_SYS_ISO_CTRL_IP2MAC, 0));
104
105 /* Disable SW LPS and WL suspend. */
106 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
107 R92C_APS_FSMCO_APFM_RSM |
108 R92C_APS_FSMCO_AFSM_HSUS |
109 R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
110
111 /* Wait for power ready bit. */
112 for (ntries = 0; ntries < 5000; ntries++) {
113 if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
114 break;
115 rtwn_delay(sc, 10);
116 }
117 if (ntries == 5000) {
118 device_printf(sc->sc_dev,
119 "timeout waiting for chip power up\n");
120 return (ETIMEDOUT);
121 }
122
123 /* Release WLON reset. */
124 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
125 R92C_APS_FSMCO_RDY_MACON, 2));
126
127 /* Disable HWPDN. */
128 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
129 R92C_APS_FSMCO_APDM_HPDN, 0, 1));
130
131 /* Disable WL suspend. */
132 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
133 R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
134
135 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
136 R92C_APS_FSMCO_APFM_ONMAC, 1));
137 for (ntries = 0; ntries < 5000; ntries++) {
138 if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
139 R92C_APS_FSMCO_APFM_ONMAC))
140 break;
141 rtwn_delay(sc, 10);
142 }
143 if (ntries == 5000)
144 return (ETIMEDOUT);
145
146 RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_MISC, 0, 0x40));
147
148 /* Enable falling edge triggering interrupt. */
149 RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0, 0x02));
150
151 /* Enable GPIO9 interrupt mode. */
152 RTWN_CHK(rtwn_setbits_1(sc, 0x063, 0, 0x02));
153
154 /* Enable GPIO9 input mode. */
155 RTWN_CHK(rtwn_setbits_1(sc, 0x062, 0x02, 0));
156
157 /* Enable HSISR GPIO interrupt. */
158 RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR, 0, 0x01));
159
160 /* Enable HSISR GPIO9 interrupt. */
161 RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR + 2, 0, 0x02));
162
163 /* GPIO9 internal pull up. */
164 RTWN_CHK(rtwn_setbits_1(sc, R92C_MULTI_FUNC_CTRL, 0, 0x08));
165 RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_MULTI_FUNC_CTRL, 0, 0x4000, 1));
166
167 /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
168 RTWN_CHK(rtwn_write_1(sc, R92C_CR, 0x00));
169 RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
170 R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
171 R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
172 R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
173 ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
174 R92C_CR_CALTMR_EN));
175
176 /* btcoex power on. */
177
178 RTWN_CHK(rtwn_write_1(sc, R88E_BB_PAD_CTRL + 3, 0x20));
179 RTWN_CHK(rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
180 R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST));
181 RTWN_CHK(rtwn_write_1(sc, R23B_GNT_BT + 1, 0x18));
182 RTWN_CHK(rtwn_write_1(sc, 0x76e, 0x4));
183 RTWN_CHK(rtwn_write_4(sc, R23B_ANT_SEL, R23B_ANT_SEL_S0));
184 RTWN_CHK(rtwn_write_1(sc, 0xfe08, 0x1));
185
186 RTWN_CHK(rtwn_setbits_2(sc, R92C_PWR_DATA, 0,
187 R23B_PWR_DATA_RFE_CTRL_EN));
188
189 RTWN_CHK(rtwn_setbits_4(sc, R92C_LEDCFG0, 0, R23B_LEDCFG0_DPDT_SEL_EN));
190
191 RTWN_CHK(rtwn_setbits_1(sc, R88E_BB_PAD_CTRL,
192 R23B_BB_PAD_CTRL_DPDT_SEL_DATA, 0));
193
194 return (0);
195 #undef RTWN_CHK
196 }
197
198 void
r23bu_power_off(struct rtwn_softc * sc)199 r23bu_power_off(struct rtwn_softc *sc)
200 {
201 int error, ntries;
202
203 /* Stop Tx report timer. */
204 error = rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, R88E_TX_RPT2_ENA, 0);
205 if (error == ENXIO) /* hardware gone */
206 return;
207
208 /* Stop Rx. */
209 rtwn_write_4(sc, R92C_CR, 0x0000);
210
211 /* Move card to Low Power state. */
212 /* Block all Tx queues. */
213 rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
214
215 for (ntries = 0; ntries < 10; ntries++) {
216 /* Should be zero if no packet is transmitting. */
217 if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
218 break;
219
220 rtwn_delay(sc, 5000);
221 }
222 if (ntries == 10) {
223 device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
224 __func__);
225 return;
226 }
227
228 /* CCK and OFDM are disabled, and clock are gated. */
229 rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0);
230
231 rtwn_delay(sc, 1);
232
233 /* Reset whole BB. */
234 rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0);
235
236 /* Reset MAC TRX. */
237 rtwn_write_1(sc, R92C_CR, R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN);
238
239 /* check if removed later. (?) */
240 rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1);
241
242 /* Respond TxOK to scheduler */
243 rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK);
244
245 #ifndef RTWN_WITHOUT_UCODE
246 if ((sc->sc_flags & RTWN_FW_LOADED) &&
247 (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL))
248 rtwn_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
249 #endif
250
251 /* Reset MCU. */
252 rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN,
253 0, 1);
254 rtwn_write_1(sc, R92C_MCUFWDL, 0);
255
256 /* Move card to Disabled state. */
257 /* Turn off RF. */
258 rtwn_write_1(sc, R92C_RF_CTRL, 0);
259
260 /* Enable rising edge triggering interrupt. */
261 rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0x02, 0);
262
263 /* Release WLON reset. */
264 rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
265 R92C_APS_FSMCO_RDY_MACON, 2);
266
267 /* Turn off MAC by HW state machine */
268 rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_OFF, 1);
269 for (ntries = 0; ntries < 10; ntries++) {
270 /* Wait until it will be disabled. */
271 if ((rtwn_read_2(sc, R92C_APS_FSMCO) &
272 R92C_APS_FSMCO_APFM_OFF) == 0)
273 break;
274
275 rtwn_delay(sc, 5000);
276 }
277 if (ntries == 10) {
278 device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
279 __func__);
280 return;
281 }
282
283 rtwn_setbits_1(sc, R92C_AFE_MISC, 0x40, 0);
284
285 /* Analog Ips to digital isolation. */
286 rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, 0, R92C_SYS_ISO_CTRL_IP2MAC);
287
288 /* Disable LDOA12 MACRO block. */
289 rtwn_setbits_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_EN, 0);
290
291 /* Enable WL suspend. */
292 rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE,
293 R92C_APS_FSMCO_AFSM_HSUS, 1);
294
295 /* Enable GPIO9 as EXT WAKEUP. */
296 rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0, 0x01);
297 }
298
299 void
r23bu_init_bb(struct rtwn_softc * sc)300 r23bu_init_bb(struct rtwn_softc *sc)
301 {
302 /* Enable BB and RF. */
303 rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_BBRSTB |
304 R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_DIO_RF);
305
306 /* Select antenna S0. */
307 rtwn_write_4(sc, R23B_ANT_SEL, R23B_ANT_SEL_S0);
308
309 return (r23b_init_bb_common(sc));
310 }
311
312 void
r23bu_init_rx_agg(struct rtwn_softc * sc)313 r23bu_init_rx_agg(struct rtwn_softc *sc)
314 {
315 struct r23b_softc *rs = sc->sc_priv;
316 uint32_t val;
317
318 rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
319
320 val = rtwn_read_4(sc, R92C_RXDMA_AGG_PG_TH);
321 val = RW(val, R23B_RXDMA_AGG_PG_TH_SIZE, rs->super.ac_usb_dma_size);
322 val = RW(val, R23B_RXDMA_AGG_PG_TH_TIME, rs->super.ac_usb_dma_time);
323 val |= R23B_RXDMA_AGG_PG_TH_EN;
324 rtwn_write_4(sc, R92C_RXDMA_AGG_PG_TH, val);
325 }
326
327 void
r23bu_init_ampdu(struct rtwn_softc * sc)328 r23bu_init_ampdu(struct rtwn_softc *sc)
329 {
330 struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
331 uint8_t val;
332
333 val = rtwn_read_1(sc, R12A_RXDMA_PRO);
334 val = RW(val, R12A_BURST_SZ,
335 usbd_get_speed(uc->uc_udev) == USB_SPEED_HIGH ?
336 R12A_BURST_SZ_USB2 : R12A_BURST_SZ_USB1);
337 val |= R12A_DMA_MODE | SM(R12A_BURST_CNT, 3);
338 rtwn_write_1(sc, R12A_RXDMA_PRO, val);
339
340 /* Enable single packet AMPDU. */
341 rtwn_setbits_1(sc, R12A_HT_SINGLE_AMPDU, 0,
342 R12A_HT_SINGLE_AMPDU_PKT_ENA);
343
344 rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0c14);
345 rtwn_write_1(sc, R12A_AMPDU_MAX_TIME, 0x5e);
346 rtwn_write_4(sc, R12A_AMPDU_MAX_LENGTH, UINT32_MAX);
347
348 /*
349 * The vendor driver says this is for
350 * "VHT packet length 11K", but this chip
351 * doesn't support VHT rates...
352 */
353 rtwn_write_1(sc, R92C_RX_PKT_LIMIT, 0x18);
354
355 rtwn_write_1(sc, R92C_PIFS, 0);
356 rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL, R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
357 rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x03086666);
358
359 rtwn_write_1(sc, R92C_USTIME_TSF, 0x50);
360 rtwn_write_1(sc, R92C_USTIME_EDCA, 0x50);
361
362 /* Do not reset MAC. */
363 rtwn_setbits_1(sc, R92C_RSV_CTRL, 0, 0x60);
364 }
365