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