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