xref: /freebsd/sys/dev/rtwn/rtl8723b/r23b_init.c (revision 9aff62dee28239f84b4aa4a3429cf26dbbf770cc)
1 /*
2  * Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #include <sys/param.h>
8 #include <sys/lock.h>
9 #include <sys/mutex.h>
10 #include <sys/mbuf.h>
11 #include <sys/kernel.h>
12 #include <sys/socket.h>
13 #include <sys/systm.h>
14 #include <sys/malloc.h>
15 #include <sys/queue.h>
16 #include <sys/taskqueue.h>
17 #include <sys/bus.h>
18 #include <sys/endian.h>
19 #include <sys/linker.h>
20 
21 #include <net/if.h>
22 #include <net/ethernet.h>
23 #include <net/if_media.h>
24 
25 #include <net80211/ieee80211_var.h>
26 #include <net80211/ieee80211_radiotap.h>
27 
28 #include <dev/rtwn/if_rtwnreg.h>
29 #include <dev/rtwn/if_rtwnvar.h>
30 
31 #include <dev/rtwn/rtl8188e/r88e.h>
32 #include <dev/rtwn/rtl8188e/r88e_reg.h>
33 
34 #include <dev/rtwn/rtl8192c/r92c_reg.h>
35 
36 #include <dev/rtwn/rtl8192e/r92e.h>
37 #include <dev/rtwn/rtl8192e/r92e_var.h>
38 
39 #include <dev/rtwn/rtl8723b/r23b.h>
40 #include <dev/rtwn/rtl8723b/r23b_reg.h>
41 #include <dev/rtwn/rtl8723b/r23b_var.h>
42 #include <dev/rtwn/rtl8723b/r23b_fw_cmd.h>
43 
44 #include <dev/rtwn/rtl8821a/r21a_reg.h>
45 
46 int
47 r23b_set_page_size(struct rtwn_softc *sc)
48 {
49 	return (rtwn_write_1(sc, R92C_PBP, SM(R92C_PBP_PSRX, R92C_PBP_256) |
50 	    SM(R92C_PBP_PSTX, R92C_PBP_256)));
51 }
52 
53 void
54 r23b_init_antsel(struct rtwn_softc *sc)
55 {
56 	rtwn_setbits_4(sc, R88E_BB_PAD_CTRL, 0x1100000, 0);
57 	rtwn_setbits_4(sc, R92C_GPIO_MUXCFG, 0x10, 0x8);
58 	rtwn_setbits_4(sc, R92C_LEDCFG0, 0x400000, 0x800000);
59 	rtwn_setbits_4(sc, 0x944, 0, 0x3);
60 	rtwn_setbits_4(sc, 0x930, 0xff, 0x77);
61 	rtwn_setbits_4(sc, R92C_PWR_DATA, 0, 0x800);
62 }
63 
64 void
65 r23b_init_bb_common(struct rtwn_softc *sc)
66 {
67 	struct r23b_softc *rs = sc->sc_priv;
68 	uint8_t val;
69 
70 	/* PathA RF Power On. */
71 	rtwn_write_1(sc, R92C_RF_CTRL,
72 	    R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
73 
74 	rtwn_delay(sc, 10);
75 
76 	rtwn_rf_write(sc, 0, R92C_RF_IQADJ_G(0), 0x780);
77 
78 	rtwn_write_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB |
79 	    R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_DIO_PCIE |
80 	    R92C_SYS_FUNC_EN_PCIEA | R92C_SYS_FUNC_EN_PPLL);
81 
82 	rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80);
83 
84 	for (int i = 0; i < sc->bb_size; i++) {
85 		const struct rtwn_bb_prog *bb_prog = &sc->bb_prog[i];
86 
87 		for (int j = 0; j < bb_prog->count; j++) {
88 			rtwn_write_4(sc, bb_prog->reg[j], bb_prog->val[j]);
89 			rtwn_delay(sc, 1);
90 		}
91 	}
92 
93 	for (int i = 0; i < sc->agc_size; i++) {
94 		const struct rtwn_agc_prog *agc_prog = &sc->agc_prog[i];
95 
96 		for (int j = 0; j < agc_prog->count; j++) {
97 			rtwn_write_4(sc, R92C_OFDM0_AGCRSSITABLE,
98 			    agc_prog->val[j]);
99 			rtwn_delay(sc, 1);
100 		}
101 	}
102 
103 	rtwn_write_4(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422);
104 	rtwn_delay(sc, 1);
105 	rtwn_write_4(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
106 	rtwn_delay(sc, 1);
107 	rtwn_write_4(sc, R92C_HSSI_PARAM2(0), 0x00390204);
108 	rtwn_delay(sc, 1);
109 
110 	val = rs->super.crystalcap & 0x3f;
111 	rtwn_setbits_4(sc, R92C_MAC_PHY_CTRL, R21A_MAC_PHY_CRYSTALCAP_M,
112 	    SM(R21A_MAC_PHY_CRYSTALCAP, val | (val << 6)));
113 }
114 
115 void
116 r23b_init_rf(struct rtwn_softc *sc)
117 {
118 	r92e_init_rf(sc);
119 
120 	/* Init LCK. */
121 	rtwn_rf_write(sc, 0, R23B_RF_S0S1, 0xdfbe0);
122 	rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, 0x8c01);
123 	rtwn_delay(sc, 200000);
124 	rtwn_rf_write(sc, 0, R23B_RF_S0S1, 0xdffe0);
125 }
126 
127 #ifndef RTWN_WITHOUT_UCODE
128 static void
129 r23b_write_btreg(struct rtwn_softc *sc, uint8_t addr, uint8_t data)
130 {
131 	struct r23b_fw_cmd_btoper cmd;
132 
133 	cmd.req_num = 0;
134 	cmd.opcode = R23B_BT_MP_OPER_WRITE_VAL;
135 	cmd.value = data;
136 	cmd.addr = 0;
137 	r88e_fw_cmd(sc, R23B_CMD_BT_MP_OPER, &cmd, sizeof(cmd));
138 
139 	rtwn_delay(sc, 200000); /* 200ms */
140 
141 	cmd.req_num = 1;
142 	cmd.opcode = R23B_BT_MP_OPER_WRITE_ADDR;
143 	cmd.value = 0;
144 	cmd.addr = addr;
145 	r88e_fw_cmd(sc, R23B_CMD_BT_MP_OPER, &cmd, sizeof(cmd));
146 }
147 #endif
148 
149 void
150 r23b_post_init(struct rtwn_softc *sc)
151 {
152 #ifndef RTWN_WITHOUT_UCODE
153 	struct r23b_fw_cmd_antinv cmd;
154 	const uint8_t ps_tdma[5] = { 0x8, 0x0, 0x0, 0x0, 0x0 };
155 #endif
156 
157 	if (sc->macid_rpt2_max_num > 0) {
158 		rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT2_ENA);
159 		rtwn_write_1(sc, R88E_TX_RPT_MACID_MAX, sc->macid_rpt2_max_num);
160 		/* Enable periodic TX report; 32uS units */
161 		rtwn_write_2(sc, R88E_TX_RPT_TIME, 0xcdf0);
162 	}
163 
164 	rtwn_lc_calib(sc);
165 	rtwn_iq_calib(sc);
166 
167 	/* Enable RF */
168 
169 	/* XXX lots of magic numbers here. */
170 
171 	rtwn_write_1(sc, 0x790, 0x5);
172 	rtwn_write_1(sc, 0x778, 0x1);
173 	rtwn_setbits_1(sc, R92C_GPIO_MUXCFG, 0, R92C_GPIO_MUXCFG_ENBT);
174 
175 	/* WiFi TRx Mask on */
176 	rtwn_rf_write(sc, 0, R92C_RF_IQADJ_G(0), 0x780);
177 
178 #ifndef RTWN_WITHOUT_UCODE
179 	/* BT TRx Mask on */
180 	r23b_write_btreg(sc, 0x3c, 0x15);
181 
182 	r88e_fw_cmd(sc, R23B_CMD_BT_GRANT, R23B_CMD_BT_GRANT_LOW,
183 	    sizeof(R23B_CMD_BT_GRANT_LOW));
184 #endif
185 
186 	rtwn_write_1(sc, 0x76e, 0x4);
187 	rtwn_setbits_1(sc, R88E_BB_PAD_CTRL + 3, 0, 0x20);
188 	rtwn_setbits_1(sc, R92C_PWR_DATA + 1, 0, 0x8);
189 	rtwn_write_1(sc, 0x974, 0xff);
190 	rtwn_setbits_1(sc, 0x944, 0, 0x3);
191 	rtwn_write_1(sc, 0x930, 0x77);
192 
193 	rtwn_setbits_4(sc, R92C_LEDCFG0, 0x1000000, 0x800000);
194 	rtwn_setbits_1(sc, R88E_BB_PAD_CTRL, 0x1, 0);
195 
196 #ifndef RTWN_WITHOUT_UCODE
197 	/* Inform firmware of the antenna inversion. */
198 	cmd.internal_switch = 0;
199 	cmd.invert = 1;
200 
201 	r88e_fw_cmd(sc, R23B_CMD_ANT_INV, &cmd, sizeof(cmd));
202 #endif
203 
204 	rtwn_write_4(sc, R23B_ANT_SEL, 0x80);
205 
206 #ifndef RTWN_WITHOUT_UCODE
207 	r88e_fw_cmd(sc, R23B_CMD_PS_TDMA, ps_tdma, sizeof(ps_tdma));
208 #endif
209 
210 	/* btcoex table */
211 	rtwn_write_4(sc, R23B_BTCOEX_TABLE(0), 0x55555555);
212 	rtwn_write_4(sc, R23B_BTCOEX_TABLE(1), 0x55555555);
213 	rtwn_write_4(sc, R23B_BTCOEX_TABLE(2), 0x00ffffff);
214 	rtwn_write_4(sc, R23B_BTCOEX_TABLE(3), 0x00000003);
215 
216 #ifndef RTWN_WITHOUT_UCODE
217 	r88e_fw_cmd(sc, R23B_CMD_BT_INFO, &(uint8_t){ 1 }, sizeof(uint8_t));
218 	r88e_fw_cmd(sc, R23B_CMD_BT_WLANACT, R23B_CMD_BT_WLANACT_IGNORE,
219 	    sizeof(R23B_CMD_BT_WLANACT_IGNORE));
220 #endif
221 
222 	/* ACK for xmit mgmt frames. */
223 	rtwn_setbits_4(sc, R92C_FWHW_TXQ_CTRL, 0, R23B_FWHW_TXQ_CTRL_ACK_MGNT);
224 
225 #ifndef RTWN_WITHOUT_UCODE
226 	if (sc->sc_flags & RTWN_FW_LOADED) {
227 		if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
228 			/* TODO: implement */
229 			sc->sc_ratectl = RTWN_RATECTL_NET80211;
230 		} else
231 			sc->sc_ratectl = sc->sc_ratectl_sysctl;
232 	} else
233 #endif
234 		sc->sc_ratectl = RTWN_RATECTL_NONE;
235 }
236