mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
rtwn: add support for the RTL8723BU
Pushed using the RTL8723BU. Reviewed by: ziaee, avos, adrian Relnotes: yes Differential Revision: https://reviews.freebsd.org/D59205
This commit is contained in:
1 parent
b2fd2f9063
commit
551b7c5e12
28 files changed
+3162
-4
No files matched your search
@@ -19,7 +19,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd November 10, 2024
|
||||
.Dd September 1, 2026
|
||||
.Dt RTWN 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -93,6 +93,8 @@ Realtek 802.11n wireless 8192c (RTL8192C)
|
||||
.It
|
||||
Realtek 802.11n wireless 8192e (RTL8192E)
|
||||
.It
|
||||
Realtek 802.11n wireless 8723b (RTL8723B)
|
||||
.It
|
||||
Realtek 802.11ac wireless 8812a (RTL8812A)
|
||||
.It
|
||||
Realtek 802.11ac wireless 8821a (RTL8821A)
|
||||
@@ -122,6 +124,7 @@ which are loaded when an interface is brought up:
|
||||
.It Pa /boot/kernel/rtwn-rtl8192cfwT.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8192cfwU.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8192eufw.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8723bufw.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8812aufw.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8821aufw.ko
|
||||
.El
|
||||
@@ -266,3 +269,6 @@ driver written by
|
||||
The
|
||||
.Nm
|
||||
driver currently does not implement firmware-based rate control.
|
||||
The RTL8723BU seems to depend on some firmware commands for antenna
|
||||
setup.
|
||||
Hence, it does not work without firmware.
|
||||
@@ -29,7 +29,7 @@
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
.\" THE POSSIBILITY OF SUCH DAMAGES.
|
||||
.\"
|
||||
.Dd November 10, 2024
|
||||
.Dd September 1, 2026
|
||||
.Dt RTWN_USB 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -59,7 +59,7 @@ driver.
|
||||
The
|
||||
.Nm
|
||||
driver supports USB wireless network adapters based on certain
|
||||
Realtek RTL 8188/8192/8812 and 8821 chipsets, including:
|
||||
Realtek RTL 8188/8192/8723/8812 and 8821 chipsets, including:
|
||||
.Pp
|
||||
.Bl -column -compact "Belkin F7D1102 Surf Wireless Micro" "RTL8188CUS" "USB 2.0"
|
||||
.It Em Card Ta Em Chip Ta Em Bus
|
||||
@@ -97,6 +97,7 @@ Realtek RTL 8188/8192/8812 and 8821 chipsets, including:
|
||||
.It "Netgear WNA1000M" Ta RTL8188CUS Ta USB 2.0
|
||||
.It "Mercusys MW150US" Ta RTL8188EU Ta USB 2.0
|
||||
.It "Planex GW-900D" Ta RTL8812AU Ta USB 3.0
|
||||
.It "Realtek RTL8723BU" Ta RTL8723BU Ta USB 2.0
|
||||
.It "Realtek RTL8192CU" Ta RTL8192CU Ta USB 2.0
|
||||
.It "Realtek RTL8188CUS" Ta RTL8188CUS Ta USB 2.0
|
||||
.It "Sitecom WLA-7100" Ta RTL8812AU Ta USB 3.0
|
||||
|
||||
@@ -2990,6 +2990,17 @@ dev/rtwn/rtl8192e/r92e_rom.c optional rtwn
|
||||
dev/rtwn/rtl8192e/r92e_rx.c optional rtwn
|
||||
dev/rtwn/rtl8192e/usb/r92eu_attach.c optional rtwn_usb
|
||||
dev/rtwn/rtl8192e/usb/r92eu_init.c optional rtwn_usb
|
||||
# RTL8723B
|
||||
dev/rtwn/rtl8723b/r23b_calib.c optional rtwn
|
||||
dev/rtwn/rtl8723b/r23b_fw.c optional rtwn
|
||||
dev/rtwn/rtl8723b/r23b_init.c optional rtwn
|
||||
dev/rtwn/rtl8723b/r23b_led.c optional rtwn
|
||||
dev/rtwn/rtl8723b/r23b_rf.c optional rtwn
|
||||
dev/rtwn/rtl8723b/r23b_rom.c optional rtwn
|
||||
dev/rtwn/rtl8723b/r23b_rx.c optional rtwn
|
||||
dev/rtwn/rtl8723b/usb/r23bu_attach.c optional rtwn_usb
|
||||
dev/rtwn/rtl8723b/usb/r23bu_init.c optional rtwn_usb
|
||||
dev/rtwn/rtl8723b/usb/r23bu_rom.c optional rtwn_usb
|
||||
# RTL8812A
|
||||
dev/rtwn/rtl8812a/r12a_beacon.c optional rtwn
|
||||
dev/rtwn/rtl8812a/r12a_calib.c optional rtwn
|
||||
|
||||
@@ -0,0 +1,717 @@
|
||||
begin 644 rtwn-rtl8723bufw.fw.uu
|
||||
M`5,0`",````#)A0U3'T``.4<```````````````````"1<X"=^L`````````
|
||||
M`````````GD&``````````````````)X'P``````````````````````````
|
||||
M`````````````GA&```````"?^<```````*'WP`$#`0("`H(`P,`!`D'`P,`
|
||||
M!`@&`P(`!`@%`P$`!`T*!P4`"`P*!P0`"`L*!@4`"`L*!0,`"`L*`P(`"!02
|
||||
M#`0`$!02"00`$"0B'!(`("0B&`P`("0B%`8`("0B#P0`("0A"@0`(",A#`0`
|
||||
M(",?"@0`("(?#P0`("$?%@P`(#$O(!0`,#$O&!``,#$L&`P`,#$J%`P`,#$H
|
||||
M%```,#$D%```,#$>%```,!7P_P\````5\`\`````!?#_#P````7P#P`````0
|
||||
M\/\/````$/`/`````/4/``````#P#P``````#0```````````````````"0F
|
||||
M*@```!\A)2<H``0`!``(`!``&``D`#``2`!@`)``P`#8`#P`9`!X`*``\`%`
|
||||
M`9`!X``"``(`!``(``P`$@`8`"0`,`!(`&``;``4`#(`/`!0`'@`H`#(`/`"
|
||||
M!`8("@P0&"`P0%`!`0$"`0(#`P0$!04"!`8'!P@("`$!`0$!`@,$!08'"`$"
|
||||
M`P0%!@<(&08$`@`8``0,!`@(!`0$!00$!0<'!P@*!`<*#A$3%!4$!`0%!P<)
|
||||
M"0P.$!(%!@<-$!$2$@``````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````````````````,*O@/XR$D*4A=`+==`(JN#"C.6*)&?UBN6,-'GUC-*,
|
||||
M["2'^.:\`@)T_\.5@;1``$#.>0-X@!;F"'`+PJ_F,.$#1!CVTJ\(V>WJB]`B
|
||||
MY0S_(R2!^`\("+\#!'\`>('F,.3R`.4,PY]0(`4,=(8E#/CF_::!".:N#+X"
|
||||
M`G3_S?CH;6#@".;`X(#VY0S3GT`GY0PDA_CFK@R^`@)T__T8YLWXY8%M8`;0
|
||||
MX/88@/7E#"2&R/85#(#3Y0PC)('X?P3"K^8PX`,0X@Q_`##A!S#C!'\(5/14
|
||||
M?,;2KU2`0@<B>(:F@70"8`;_"';_W_M_`^1X@/8(]@C?^GB!=C"01G%T`9/`
|
||||
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
|
||||
MH%/PX,,3H_"0H$S@=?`#A)"@5?"[email protected]%;PD*!,X,,3D*!7\)`!/G0(
|
||||
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
|
||||
M'[email protected]@E`-`#)`!P.!$(/#QZG\`(G\R?@`2/E"0HOOQW("E?V^1
|
||||
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
|
||||
MD*`_X)`!/R+1.O'[email protected]_]&,[V0!(N]@,O&H<"Z0G]7@5/[P?2M_#Q)4QI`&
|
||||
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
|
||||
MD)_2=`3P([email protected]^5!#][U3O32+D^_K]?P$21-Z0H<KO\&#PD)Z2X/]P!*/@
|
||||
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
|
||||
M,?&0HL31N.!@),[email protected];@E`-`"Y`!P.!$@/!_`(`,D*+&$E?<T4:`
|
||||
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
|
||||
M\*/O\)"B:G0,\)"B>'0"\'L!>J)Y:A*7W-#0DJ\BTQ"O`</`[email protected]"N^0
|
||||
MC0$23Y7P=?`*[Y"-`Q)/E?!U\`KOD(T%$D^5\'7P"N^0C0<23Y7P=?`*[Y"-
|
||||
M"1)/E9'@Y/`2?Y#@5+]$@/X2?Y#N\-#0DJ\B\.\EX"0!]8+D-)+U@^3PH_!T
|
||||
MD2_U@N0TF/6#(M,0KP'#P-"0HPGO\'^/$D:K[S#F07^-$D:K[V0!<#>0HPKP
|
||||
MD*,*X/V0HPG@=?`0$G6.Y8(M$GI5X/OD_Q)-]Y"C"N`$\.##E!!`V'^/$D:K
|
||||
M[S#@`K%7T-"2KR+D_7^-`D:-TQ"O`</`T)"B&>SPH^WPD*(8[_"CH^#]$CX"
|
||||
MD*(C$@AMD*(;$D5R$@@ZD*(CT73`!,`%P`;`!Y"B&Q)%<I"B']%TT`/0`M`!
|
||||
MT``21520HB<2"&V0HAFCX/W`!9"B)Q)%<I"JEA((;9"B&.#_T`42/0G0T)*O
|
||||
M(I"@W!)%BN#^5`/][A,35`?[D*"NX/[$5`^0HM_PKP33$*\!P\#0D*+<[_#M
|
||||
M9`%P+NNT`0?@)`+U<(`(D*+<X"3^]7"0HAL2"'D```#_KW#19=%=$@AY````
|
||||
M_Z]P@""0HAL2"'D```#_D*+<$EU!T6G171((>0```/^0HMS@_]%E?P&Q7M#0
|
||||
MDJ\BY/^Q7I"B&R+D_/W^D*(?$@AM?1A\`"(217X"14>/59`%(N"0H=CP$E=/
|
||||
M[V0!<$9U\`OE51*?U?QU\`OE5;'4=?`+Y54254D25^-4!R#@''7P"^55$G?8
|
||||
M_V`#OP(.=?`+Y5425Q_D^_T25'&M57\!$E31?P$BD*'8X/]]21)4QG\`(M,0
|
||||
MKP'#P-"0HQ/M\.3^_>^T`0WKM`(##8`&Z[0!`GT"KP;OQ%3P3?_0T)*O(N3^
|
||||
M[U3@Q!-4!_WO5!__[6`L%&`>)/U@#R3^<"KO)>#_PW3>G_Z`'^\EX/_#=/*?
|
||||
M_H`4[R7@_\-T!I_^@`GO)>#_PW00G_ZO!B+3[V2`E!Q`!^]D@)240`-_`"+#
|
||||
M[V2`E(!``W]D(N\D9/\B\9._`1:0H;_@5##_OR`'D*$Z=`'P(N20H3KP(GL!
|
||||
M>J%YOW_[?@$"-,'3$*\!P\#0?P!^"!(W3I"APA((;7\`?@D2-TZ0H<82"&V0
|
||||
MH<(2N!%@&9"APA*X")"APA((;9"APA)'S'\`?@@2.$60H<82N!%@&9"AQA*X
|
||||
M")"AQA((;9"AQA)'S'\`?@D2.$70T)*O(A)%<N]4_O_L(A)%<N]4`?_D_OW\
|
||||
M[R)^`'\!?0![`7J?><\2"*J0G\_@5/WPY!)@=*-T#/`B$53DD)_2\"(29Z*`
|
||||
M\Q)GD8#[email protected]!2?@5+_P(GTN?V\25,9]`G\!$F'&$520G]-T`O`B?2`1
|
||||
M@'0"\"(29^J`\W__$E3&$D?KD)_2(A&%=`+P(A)G['TC$8!T`O`B?2%__Q)4
|
||||
MQI"?TG0#\"(29^J`[1)FN(#O?2)__Q)4QA)G[(#C$F?J`F_/$F:X?20";]&N
|
||||
M!Q)K';\!$Y"?SQ)?WR#@"J\&?0$28EI_`2)_`"*0G]3@5/OPY)"?XO"C\)"?
|
||||
MW?"0G]7@5/?P5+\29'E]$'\#`F8-[R3^8`L$<"20G]]T`O"`$^UP!I"@.>"`
|
||||
M`NT4D)_?\)"?W^"C\)"?U>!$"/`BTQ"O`</`T)"@2N`PX!>0H%S@<&&0G]O@
|
||||
MTY0`4%B0H#S@8$Z`4!*BM^]D`7!(D)_=X/]4`W`_D)_;X/[DPYY`->\@XC&0
|
||||
MG]W@(.0JD)_5X!,35#\PX!^0H#S@<!F0!F+@(.$2D`9BX##@!^!4_&2`8`1_
|
||||
M`8`"?P#0T)*O(I"@,'0$\*,4\*/D\*-T9/"C=`7PH_`B?2]__Q)4QA)'ZWT(
|
||||
M?P$28<:0G]-T"/`BD**RX/_3$*\!P\#0D*,8[_"0GLO@_Y`$'.!O<#F0G]S@
|
||||
M9`YP$)"C&.!P*U%%D`8$$F&^@!Z0G]S@9`9P&9"C&.!@$Y"?U.!4O_!13?"0
|
||||
MG]QT!/`29CK0T)*O(I"?U.!4?_`BD`8$X$1`\.!$@"+3$*\!P\#0D*+H[_"0
|
||||
M!!W@8!^0!2+@D*+K\'TI$E=1OP$#$H>,D*+KX/]]*A)4QH`#$H>,D`0?="#P
|
||||
MT-"2KR+D_N_#$_WO,.`"?H"0_1#M\*\&(I"@KN#_PQ/^[U3Q_^X$5`<EX$_P
|
||||
MH^#_D*"NX/[#$U0'(O]U\`Z0H+L218K@_G7P#N^0H+H218K@D**L\)"BJ^XB
|
||||
MD*'.$D66=?`"Y5JD]8*%\(,2!ZNN\"+E4R7@)%'U@N0T0?6#(N53)>`D>?6"
|
||||
MY#1!]8,BCUCO=?`&I"1<^71`-?#Z>_\B=?`#$D6*X/YT`:@&""+E427@)`'U
|
||||
M@N0TDO6#(G21)5'U@N0TG/6#(G0H+_6"Y#2A]8/@(G7P"J0D`?ETC37P^GL!
|
||||
M(OITT"[email protected]#[O##(I"?U^#_Q%0/(G@($@A:J`2I!:H&JP<B\.Y4"/[O
|
||||
M5/<B?@!_!'T`>P%ZH'D](I"@_N!$$/"0H?O@_R(218K@_*/@]8*,@R(2"%J0
|
||||
MHC$2"&U_`")T!2[U@N0T_/6#X")T(2_U@N0T_/6#X"+O$Q,35!_^[U0'_R)_
|
||||
MA'X($E:PD*(;(OSE5L,3_N57$_\BD`58=`+P(I"BX^#_D*+AX")T`9.55>23
|
||||
ME50B_E0@_>]4WTW_(A)%BN#[Y/T/(G\P?@D2-T[D(I`$'W0@\'\!(I"@/^"0
|
||||
M!7/P(E0!Q#,S,U2`(I`%(N"0H?OP(I"A_^#_=?`+(G7P#N54D*"R(I"!`1)%
|
||||
MBN_P(N5H5'^0HIGP(O"0!.#@D)_5(I"@4.!4W_#D(G].$D:K[U1_(I"BP^!_
|
||||
M2'X)(I"@3>#$$U0'(O!_$'X``CY0D`8*X%3X\"*0!@3@5'_P(GT"?P("7[F0
|
||||
M!2+@5&__(I"?W^#_H^`BD)_?X)`%<R*0H-\218K@(I")!Q)%BN`B_7P`$@<#
|
||||
M[R*0``82!ZLO(O_N7/[O74XBD`4`=!SPHR)4@/[O5'].(I"BB!)%<N\B$D5R
|
||||
7[T2`_R(O^.;^[?1>(A)&J^]$0/TB1,<`
|
||||
`
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef RTL8723B_H
|
||||
#define RTL8723B_H
|
||||
|
||||
/*
|
||||
* Global definitions.
|
||||
*/
|
||||
#define R23B_PUBQ_NPAGES 231
|
||||
#define R23B_HPQ_NPAGES 12
|
||||
#define R23B_LPQ_NPAGES 2
|
||||
#define R23B_NPQ_NPAGES 2
|
||||
|
||||
#define R23B_TX_PAGE_COUNT 247
|
||||
|
||||
#define R23B_RX_DMA_BUFFER_SIZE 0x3f80
|
||||
|
||||
#define R23B_CALIB_THRESHOLD 7
|
||||
|
||||
/*
|
||||
* Function declarations.
|
||||
*/
|
||||
|
||||
/* r23b_calib.c */
|
||||
void r23b_iq_calib(struct rtwn_softc *);
|
||||
void r23b_lc_calib(struct rtwn_softc *);
|
||||
void r23b_temp_measure(struct rtwn_softc *);
|
||||
|
||||
/* r23b_fw.c */
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
void r23b_fw_download_enable(struct rtwn_softc *, int);
|
||||
void r23b_fw_reset(struct rtwn_softc *, int);
|
||||
#endif
|
||||
|
||||
/* r23b_init.c */
|
||||
void r23b_init_antsel(struct rtwn_softc *);
|
||||
void r23b_init_bb_common(struct rtwn_softc *);
|
||||
void r23b_init_rf(struct rtwn_softc *);
|
||||
void r23b_post_init(struct rtwn_softc *);
|
||||
int r23b_set_page_size(struct rtwn_softc *);
|
||||
|
||||
/* r23b_led.c */
|
||||
void r23b_set_led(struct rtwn_softc *, int, int);
|
||||
|
||||
/* r23b_rf.c */
|
||||
void r23b_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
|
||||
|
||||
/* r23b_rom.c */
|
||||
int r23b_efuse_preread(struct rtwn_softc *);
|
||||
void r23b_parse_rom(struct rtwn_softc *, uint8_t *);
|
||||
|
||||
/* r23b_rx.c */
|
||||
int8_t r23b_get_rssi_cck(struct rtwn_softc *, void *);
|
||||
|
||||
#endif /* RTL8723B_H */
|
||||
@@ -0,0 +1,620 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwn_debug.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e.h>
|
||||
#include <dev/rtwn/rtl8188e/r88e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192e/r92e_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_var.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_reg.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_fw_cmd.h>
|
||||
|
||||
struct r23b_iqk_reg_vals {
|
||||
uint32_t adaa[16];
|
||||
uint32_t iqk_bb[9];
|
||||
uint8_t txpause;
|
||||
uint8_t bcn_ctrl[2];
|
||||
uint8_t gpio_muxcfg;
|
||||
};
|
||||
|
||||
struct r23b_iqk_result {
|
||||
int32_t iqk_before;
|
||||
int32_t iqk_after;
|
||||
};
|
||||
|
||||
enum r23b_iqk_stage {
|
||||
R23B_IQK_TX,
|
||||
R23B_IQK_TX_RX,
|
||||
R23B_IQK_RX
|
||||
};
|
||||
|
||||
static const uint16_t r23b_iq_calib_reg_adaa[16] = {
|
||||
0x85c, 0xe6c, 0xe70, 0xe74,
|
||||
0xe78, 0xe7c, 0xe80, 0xe84,
|
||||
0xe88, 0xe8c, 0xed0, 0xed4,
|
||||
0xed8, 0xedc, 0xee0, 0xeec
|
||||
};
|
||||
|
||||
static const uint16_t r23b_iq_calib_reg_iqk_bb[9] = {
|
||||
0xc04, 0xc08, 0x874, 0xb68,
|
||||
0xb6c, 0x870, 0x860, 0x864,
|
||||
0xa04
|
||||
};
|
||||
|
||||
#define R23B_IQK_MAX_TOLERANCE 5
|
||||
#define R23B_IQK_SIGN(r) (((r) & 0x200) ? (0xfffffc00 | (r)) : (r))
|
||||
|
||||
/* XXX
|
||||
* Same as r92c_lc_calib except for LDO on and LDO off
|
||||
*/
|
||||
void
|
||||
r23b_lc_calib(struct rtwn_softc *sc)
|
||||
{
|
||||
uint32_t rf_ac[2];
|
||||
uint8_t txmode;
|
||||
int i;
|
||||
|
||||
txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3);
|
||||
if ((txmode & 0x70) != 0) {
|
||||
/* Disable all continuous Tx. */
|
||||
rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70);
|
||||
|
||||
/* Set RF mode to standby mode. */
|
||||
for (i = 0; i < sc->nrxchains; i++) {
|
||||
rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC);
|
||||
rtwn_rf_write(sc, i, R92C_RF_AC,
|
||||
RW(rf_ac[i], R92C_RF_AC_MODE,
|
||||
R92C_RF_AC_MODE_STANDBY));
|
||||
}
|
||||
} else {
|
||||
/* Block all Tx queues. */
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
|
||||
}
|
||||
|
||||
/* LDO on */
|
||||
rtwn_rf_write(sc, 0, R23B_RF_S0S1, 0xdfbe0);
|
||||
|
||||
/* Start calibration. */
|
||||
rtwn_rf_setbits(sc, 0, R92C_RF_CHNLBW, 0, R92C_RF_CHNLBW_LCSTART);
|
||||
|
||||
/* Give calibration the time to complete. */
|
||||
rtwn_delay(sc, 100000); /* 100ms */
|
||||
|
||||
/* LDO off */
|
||||
rtwn_rf_write(sc, 0, R23B_RF_S0S1, 0xdffe0);
|
||||
|
||||
/* Restore configuration. */
|
||||
if ((txmode & 0x70) != 0) {
|
||||
/* Restore Tx mode. */
|
||||
rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode);
|
||||
/* Restore RF mode. */
|
||||
for (i = 0; i < sc->nrxchains; i++)
|
||||
rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]);
|
||||
} else {
|
||||
/* Unblock all Tx queues. */
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
r23b_iq_calib_chain(struct rtwn_softc *sc, enum r23b_iqk_stage stage)
|
||||
{
|
||||
struct r23b_softc *rs = sc->sc_priv;
|
||||
uint32_t rf_path;
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: starting stage: %s\n",
|
||||
__func__, stage == R23B_IQK_TX ? "R23B_IQK_TX" :
|
||||
stage == R23B_IQK_TX_RX ? "R23B_IQK_TX_RX" : "R23B_IQK_RX");
|
||||
|
||||
/* Save RF path. */
|
||||
rf_path = rtwn_read_4(sc, R23B_ANT_SEL);
|
||||
|
||||
/* Leave IQK mode. */
|
||||
rtwn_setbits_4(sc, R92C_FPGA0_IQK, ~0xff, 0);
|
||||
|
||||
rtwn_rf_setbits(sc, 0, R88E_RF_WE_LUT, 0, 0x80000);
|
||||
switch (stage) {
|
||||
case R23B_IQK_TX:
|
||||
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x20000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0003f);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xc7f87);
|
||||
|
||||
rtwn_write_4(sc, R92C_TX_IQK, 0x01007c00);
|
||||
break;
|
||||
case R23B_IQK_TX_RX:
|
||||
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0001f);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7fb7);
|
||||
|
||||
rtwn_write_4(sc, R92C_TX_IQK, 0x01007c00);
|
||||
break;
|
||||
case R23B_IQK_RX:
|
||||
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0001f);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7d77);
|
||||
|
||||
rtwn_rf_write(sc, 0, 0xdf, 0xf80);
|
||||
rtwn_rf_write(sc, 0, 0x55, 0x4021f);
|
||||
break;
|
||||
default:
|
||||
KASSERT(0, ("%s: Invalid stage %d", __func__, stage));
|
||||
}
|
||||
|
||||
rtwn_write_4(sc, R92C_RX_IQK, 0x01004800);
|
||||
|
||||
switch (stage) {
|
||||
case R23B_IQK_TX:
|
||||
case R23B_IQK_TX_RX:
|
||||
rtwn_write_4(sc, R92C_TX_IQK_TONE(0), 0x18008c1c);
|
||||
rtwn_write_4(sc, R92C_RX_IQK_TONE(0), 0x38008c1c);
|
||||
break;
|
||||
case R23B_IQK_RX:
|
||||
rtwn_write_4(sc, R92C_TX_IQK_TONE(0), 0x38008c1c);
|
||||
rtwn_write_4(sc, R92C_RX_IQK_TONE(0), 0x18008c1c);
|
||||
break;
|
||||
}
|
||||
rtwn_write_4(sc, R92C_TX_IQK_TONE(1), 0x38008c1c);
|
||||
rtwn_write_4(sc, R92C_RX_IQK_TONE(1), 0x38008c1c);
|
||||
|
||||
switch (stage) {
|
||||
case R23B_IQK_TX:
|
||||
rtwn_write_4(sc, R92C_TX_IQK_PI(0), 0x821403ea);
|
||||
rtwn_write_4(sc, R92C_RX_IQK_PI(0), 0x28110000);
|
||||
break;
|
||||
case R23B_IQK_TX_RX:
|
||||
rtwn_write_4(sc, R92C_TX_IQK_PI(0), 0x82160ff0);
|
||||
rtwn_write_4(sc, R92C_RX_IQK_PI(0), 0x28110000);
|
||||
break;
|
||||
case R23B_IQK_RX:
|
||||
rtwn_write_4(sc, R92C_TX_IQK_PI(0), 0x82110000);
|
||||
rtwn_write_4(sc, R92C_RX_IQK_PI(0), 0x2816001f);
|
||||
break;
|
||||
}
|
||||
|
||||
rtwn_write_4(sc, R92C_TX_IQK_PI(1), 0x82110000);
|
||||
rtwn_write_4(sc, R92C_RX_IQK_PI(1), 0x28110000);
|
||||
|
||||
switch (stage) {
|
||||
case R23B_IQK_TX:
|
||||
rtwn_write_4(sc, R92C_IQK_AGC_RSP, 0x00462911);
|
||||
break;
|
||||
case R23B_IQK_TX_RX:
|
||||
rtwn_write_4(sc, R92C_IQK_AGC_RSP, 0x0046a911);
|
||||
break;
|
||||
case R23B_IQK_RX:
|
||||
rtwn_write_4(sc, R92C_IQK_AGC_RSP, 0x0046a8d1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enter IQK mode. */
|
||||
rtwn_setbits_4(sc, R92C_FPGA0_IQK, ~0xff, 0x80800000);
|
||||
|
||||
rtwn_write_4(sc, R23B_ANT_SEL, rs->bt_antnum == 0 ?
|
||||
R23B_ANT_SEL_S0 : R23B_ANT_SEL_S1);
|
||||
|
||||
/* GNT_BT = 0 */
|
||||
rtwn_write_4(sc, R23B_GNT_BT, 0x00000800);
|
||||
|
||||
/* We're doing LO and IQ calibration in one shot. */
|
||||
rtwn_write_4(sc, R92C_IQK_AGC_PTS, 0xf9000000);
|
||||
rtwn_write_4(sc, R92C_IQK_AGC_PTS, 0xf8000000);
|
||||
|
||||
rtwn_delay(sc, 20000); /* 20ms */
|
||||
|
||||
/* Restore RF path. */
|
||||
rtwn_write_4(sc, R23B_ANT_SEL, rf_path);
|
||||
|
||||
/* GNT_BT = 1 */
|
||||
rtwn_write_4(sc, R23B_GNT_BT, 0x00001800);
|
||||
|
||||
/* Leave IQK mode. */
|
||||
rtwn_setbits_4(sc, R92C_FPGA0_IQK, ~0xff, 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
r23b_iq_calib_get_tx_result(struct rtwn_softc *sc,
|
||||
struct r23b_iqk_result *tx_result)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = rtwn_read_4(sc, R92C_RX_POWER_IQK_AFTER(0));
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: rx_after (%#x): %#x\n",
|
||||
__func__, R92C_RX_POWER_IQK_AFTER(0), val);
|
||||
if (val & 0x10000000)
|
||||
return (false);
|
||||
|
||||
val = rtwn_read_4(sc, R92C_TX_POWER_IQK_BEFORE(0));
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: tx_before (%#x): %#x\n",
|
||||
__func__, R92C_TX_POWER_IQK_BEFORE(0), val);
|
||||
val = MS(val, R92C_POWER_IQK_RESULT);
|
||||
if (val == 0x142 || val >= 0x110 || val <= 0xf0)
|
||||
return (false);
|
||||
tx_result->iqk_before = val;
|
||||
|
||||
val = rtwn_read_4(sc, R92C_TX_POWER_IQK_AFTER(0));
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: tx_after (%#x): %#x\n",
|
||||
__func__, R92C_TX_POWER_IQK_AFTER(0), val);
|
||||
|
||||
val = MS(val, R92C_POWER_IQK_RESULT);
|
||||
if (val == 0x42)
|
||||
return (false);
|
||||
tx_result->iqk_after = val;
|
||||
|
||||
if ((val & 0x200) != 0)
|
||||
val = 0x400 - val;
|
||||
return (val < 0xf);
|
||||
}
|
||||
|
||||
static bool
|
||||
r23b_iq_calib_get_rx_result(struct rtwn_softc *sc,
|
||||
struct r23b_iqk_result *rx_result)
|
||||
{
|
||||
uint32_t iqk_before, iqk_after, val;
|
||||
|
||||
iqk_after = rtwn_read_4(sc, R92C_RX_POWER_IQK_AFTER(0));
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: rx_after (%#x): %#x\n",
|
||||
__func__, R92C_RX_POWER_IQK_AFTER(0), iqk_after);
|
||||
|
||||
iqk_after = MS(iqk_after, R92C_POWER_IQK_RESULT);
|
||||
|
||||
iqk_before = rtwn_read_4(sc, R92C_RX_POWER_IQK_BEFORE(0));
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: rx_before (%#x): %#x\n",
|
||||
__func__, R92C_RX_POWER_IQK_BEFORE(0), iqk_before);
|
||||
|
||||
iqk_before = MS(iqk_before, R92C_POWER_IQK_RESULT);
|
||||
|
||||
/* Leave IQK mode. */
|
||||
rtwn_setbits_4(sc, R92C_FPGA0_IQK, ~0xff, 0);
|
||||
rtwn_rf_write(sc, 0, 0xdf, 0x780);
|
||||
|
||||
val = (iqk_after & 0x200) != 0 ? 0x400 - iqk_after : iqk_after;
|
||||
if (iqk_after & 0x8000000)
|
||||
return (false);
|
||||
|
||||
if (iqk_before == 0x132 || iqk_before >= 0x110 || iqk_before <= 0xf0)
|
||||
return (false);
|
||||
|
||||
if (iqk_after == 0x36)
|
||||
return (false);
|
||||
|
||||
if (val >= 0xf)
|
||||
return (false);
|
||||
|
||||
rx_result->iqk_before = iqk_before;
|
||||
rx_result->iqk_after = iqk_after;
|
||||
return (true);
|
||||
}
|
||||
|
||||
static inline void
|
||||
r23b_iq_calib_save_regs(struct rtwn_softc *sc,
|
||||
struct r23b_iqk_reg_vals *vals)
|
||||
{
|
||||
for (int i = 0; i < nitems(r23b_iq_calib_reg_adaa); i++)
|
||||
vals->adaa[i] = rtwn_read_4(sc, r23b_iq_calib_reg_adaa[i]);
|
||||
|
||||
vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE);
|
||||
|
||||
for (int i = 0; i < sizeof(vals->bcn_ctrl); i++)
|
||||
vals->bcn_ctrl[i] = rtwn_read_1(sc, R92C_BCN_CTRL(i));
|
||||
|
||||
vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG);
|
||||
|
||||
for (int i = 0; i < nitems(r23b_iq_calib_reg_iqk_bb); i++)
|
||||
vals->iqk_bb[i] = rtwn_read_4(sc, r23b_iq_calib_reg_iqk_bb[i]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
r23b_iq_calib_restore_regs(struct rtwn_softc *sc,
|
||||
const struct r23b_iqk_reg_vals *vals)
|
||||
{
|
||||
for (int i = 0; i < nitems(r23b_iq_calib_reg_adaa); i++)
|
||||
rtwn_write_4(sc, r23b_iq_calib_reg_adaa[i], vals->adaa[i]);
|
||||
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause);
|
||||
|
||||
for (int i = 0; i < sizeof(vals->bcn_ctrl); i++)
|
||||
rtwn_write_1(sc, R92C_BCN_CTRL(i), vals->bcn_ctrl[i]);
|
||||
|
||||
rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg);
|
||||
|
||||
for (int i = 0; i < nitems(r23b_iq_calib_reg_iqk_bb); i++)
|
||||
rtwn_write_4(sc, r23b_iq_calib_reg_iqk_bb[i], vals->iqk_bb[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
r23b_iq_calib_run(struct rtwn_softc *sc, struct r23b_iqk_result *tx_result,
|
||||
struct r23b_iqk_result *rx_result, const struct r23b_iqk_reg_vals *vals)
|
||||
{
|
||||
struct r23b_softc *rs = sc->sc_priv;
|
||||
|
||||
for (int i = 0; i < nitems(r23b_iq_calib_reg_adaa); i++)
|
||||
rtwn_write_4(sc, r23b_iq_calib_reg_adaa[i], 0x01c00014);
|
||||
|
||||
/* MAC settings */
|
||||
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_AC |
|
||||
R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH);
|
||||
|
||||
for (int i = 0; i < sizeof(vals->bcn_ctrl); i++) {
|
||||
rtwn_write_1(sc, R92C_BCN_CTRL(i),
|
||||
vals->bcn_ctrl[i] & ~R92C_BCN_CTRL_EN_BCN);
|
||||
}
|
||||
|
||||
rtwn_write_1(sc, R92C_GPIO_MUXCFG,
|
||||
vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT);
|
||||
|
||||
/* BB settings */
|
||||
|
||||
rtwn_setbits_4(sc, R92C_CCK0_AFESETTING, 0, 0x0f000000);
|
||||
rtwn_write_4(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
|
||||
rtwn_write_4(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
|
||||
rtwn_write_4(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
|
||||
|
||||
/* IQ calibration settings */
|
||||
|
||||
rtwn_setbits_4(sc, R92C_FPGA0_IQK, ~0xff, 0);
|
||||
rtwn_rf_setbits(sc, 0, R88E_RF_WE_LUT, 0, 0x80000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0001f);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7fb7);
|
||||
rtwn_rf_setbits(sc, 0, 0xed, 0, 0x20);
|
||||
rtwn_rf_write(sc, 0, 0x43, 0x60fbd);
|
||||
|
||||
/* Path A Tx IQ calibration. */
|
||||
for (int retry = 0; retry < 2; retry++) {
|
||||
r23b_iq_calib_chain(sc, R23B_IQK_TX);
|
||||
|
||||
if (r23b_iq_calib_get_tx_result(sc, tx_result)) {
|
||||
rtwn_setbits_4(sc, R92C_FPGA0_IQK, ~0xff, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: Tx failed, retry=%d\n", __func__, retry);
|
||||
}
|
||||
|
||||
/* Path A Rx IQ calibration. */
|
||||
for (int retry = 0; retry < 2; retry++) {
|
||||
struct r23b_iqk_result result;
|
||||
|
||||
r23b_iq_calib_chain(sc, R23B_IQK_TX_RX);
|
||||
if (!r23b_iq_calib_get_tx_result(sc, &result)) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: Rx (Tx) failed, retry=%d\n", __func__, retry);
|
||||
continue;
|
||||
}
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: writing %#x to TX_IQK\n", __func__,
|
||||
0x80007c00 | (result.iqk_before << 16) | result.iqk_after);
|
||||
|
||||
rtwn_write_4(sc, R92C_TX_IQK,
|
||||
0x80007c00 | (result.iqk_before << 16) | result.iqk_after);
|
||||
|
||||
r23b_iq_calib_chain(sc, R23B_IQK_RX);
|
||||
if (!r23b_iq_calib_get_rx_result(sc, rx_result)) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: Rx failed, retry=%d\n", __func__, retry);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (rs->bt_antnum == 0) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: path B IQK not implemented!\n", __func__);
|
||||
}
|
||||
|
||||
rtwn_setbits_4(sc, R92C_FPGA0_IQK, ~0xff, 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
r23b_iq_calib_compare_results(
|
||||
struct r23b_iqk_result *tx_result1, struct r23b_iqk_result *rx_result1,
|
||||
struct r23b_iqk_result *tx_result2, struct r23b_iqk_result *rx_result2,
|
||||
struct r23b_iqk_result **tx_candidate,
|
||||
struct r23b_iqk_result **rx_candidate) {
|
||||
uint32_t diff;
|
||||
bool tx_good = false;
|
||||
|
||||
diff = abs(tx_result1->iqk_before - tx_result2->iqk_before);
|
||||
if (diff > R23B_IQK_MAX_TOLERANCE)
|
||||
goto rx_compare;
|
||||
|
||||
diff = abs(R23B_IQK_SIGN(tx_result1->iqk_after) -
|
||||
R23B_IQK_SIGN(tx_result2->iqk_after));
|
||||
if (diff <= R23B_IQK_MAX_TOLERANCE) {
|
||||
*tx_candidate = tx_result1;
|
||||
tx_good = true;
|
||||
}
|
||||
|
||||
rx_compare:
|
||||
diff = abs(rx_result1->iqk_before - rx_result2->iqk_before);
|
||||
if (diff > R23B_IQK_MAX_TOLERANCE) {
|
||||
if (tx_good &&
|
||||
rx_result1->iqk_before + rx_result1->iqk_after == 0)
|
||||
*tx_candidate = tx_result2;
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
diff = abs(R23B_IQK_SIGN(rx_result1->iqk_after) -
|
||||
R23B_IQK_SIGN(rx_result2->iqk_after));
|
||||
if (diff > R23B_IQK_MAX_TOLERANCE)
|
||||
return (false);
|
||||
|
||||
*rx_candidate = rx_result1;
|
||||
return (tx_good);
|
||||
}
|
||||
|
||||
void
|
||||
r23b_iq_calib(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r23b_iqk_reg_vals vals;
|
||||
struct r23b_iqk_result tx_result[3] = { 0 };
|
||||
struct r23b_iqk_result rx_result[3] = { 0 };
|
||||
struct r23b_iqk_result *tx_candidate = NULL, *rx_candidate = NULL;
|
||||
uint32_t oldval, val;
|
||||
uint32_t gnt_bt;
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
/* Inform firmware that we're begininng IQK. */
|
||||
r88e_fw_cmd(sc, R23B_CMD_WLAN_CALIB, R23B_CMD_WLAN_CALIB_BEGIN,
|
||||
sizeof(R23B_CMD_WLAN_CALIB_BEGIN));
|
||||
#endif
|
||||
|
||||
/* Save GNT_BT. */
|
||||
gnt_bt = rtwn_read_4(sc, R23B_GNT_BT);
|
||||
|
||||
r23b_iq_calib_save_regs(sc, &vals);
|
||||
r23b_iq_calib_run(sc, &tx_result[0], &rx_result[0], &vals);
|
||||
r23b_iq_calib_run(sc, &tx_result[1], &rx_result[1], &vals);
|
||||
r23b_iq_calib_restore_regs(sc, &vals);
|
||||
|
||||
if (r23b_iq_calib_compare_results(&tx_result[0], &rx_result[0],
|
||||
&tx_result[1], &rx_result[1], &tx_candidate, &rx_candidate)) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: comparing 0 and 1 succeeded\n", __func__);
|
||||
goto write;
|
||||
}
|
||||
|
||||
r23b_iq_calib_run(sc, &tx_result[2], &rx_result[2], &vals);
|
||||
r23b_iq_calib_restore_regs(sc, &vals);
|
||||
|
||||
if (r23b_iq_calib_compare_results(&tx_result[0], &rx_result[0],
|
||||
&tx_result[2], &rx_result[2], &tx_candidate, &rx_candidate)) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: comparing 0 and 2 succeeded\n", __func__);
|
||||
goto write;
|
||||
}
|
||||
|
||||
if (!r23b_iq_calib_compare_results(&tx_result[1], &rx_result[1],
|
||||
&tx_result[2], &rx_result[2], &tx_candidate, &rx_candidate)) {
|
||||
/* If no candidate was assigned, set the result to zero. */
|
||||
if (tx_candidate == NULL) {
|
||||
tx_result[0] = (struct r23b_iqk_result){ 0 };
|
||||
tx_candidate = &tx_result[0];
|
||||
}
|
||||
|
||||
if (rx_candidate == NULL) {
|
||||
rx_result[0] = (struct r23b_iqk_result){ 0 };
|
||||
rx_candidate = &rx_result[0];
|
||||
}
|
||||
|
||||
if (tx_candidate->iqk_before == 0 &&
|
||||
tx_candidate->iqk_after == 0 &&
|
||||
rx_candidate->iqk_before == 0 &&
|
||||
rx_candidate->iqk_after == 0) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: IQK failed\n", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: comparison failed but a candidate was assigned\n",
|
||||
__func__);
|
||||
} else {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: comparing 1 and 2 succeeded\n", __func__);
|
||||
}
|
||||
|
||||
write:
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: IQK candidate dump:\n"
|
||||
"\ttx_candidate->iqk_before 0x%x\ttx_candidate->iqk_after 0x%x\n"
|
||||
"\trx_candidate->iqk_before 0x%x\trx_candidate->iqk_after 0x%x\n",
|
||||
__func__, tx_candidate->iqk_before, tx_candidate->iqk_after,
|
||||
rx_candidate->iqk_before, rx_candidate->iqk_after);
|
||||
|
||||
/*
|
||||
* Don't write both the tx and rx configuration
|
||||
* values if tx IQK failed.
|
||||
*/
|
||||
if (tx_candidate->iqk_before == 0)
|
||||
goto done;
|
||||
|
||||
/* Write path A values */
|
||||
|
||||
oldval = rtwn_read_4(sc, R92C_OFDM0_TXIQIMBALANCE(0));
|
||||
oldval = (oldval >> 22) & 0x3ff;
|
||||
|
||||
val = (R23B_IQK_SIGN(tx_candidate->iqk_before) * oldval) >> 7;
|
||||
rtwn_setbits_4(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x3ff,
|
||||
(val >> 1) & 0x3ff);
|
||||
rtwn_setbits_4(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000, val << 31);
|
||||
|
||||
val = (R23B_IQK_SIGN(tx_candidate->iqk_after) * oldval) >> 7;
|
||||
rtwn_setbits_4(sc, R92C_TX_POWER_IQK_BEFORE(0),
|
||||
0xf0000000, (((val >> 1) & 0x3c0) >> 6) << 28);
|
||||
rtwn_setbits_4(sc, R92C_OFDM0_TXIQIMBALANCE(0),
|
||||
0x3f0000, ((val >> 1) & 0x3f) << 16);
|
||||
rtwn_setbits_4(sc, R92C_OFDM0_ECCATHRESHOLD,
|
||||
0x10000000, (val << 29) & 0x1);
|
||||
|
||||
/* Skip the rx configuration values if rx IQK failed. */
|
||||
if (rx_candidate->iqk_before == 0)
|
||||
goto done;
|
||||
|
||||
val = rx_candidate->iqk_after & 0x3f;
|
||||
rtwn_setbits_4(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0x3ff,
|
||||
rx_candidate->iqk_before);
|
||||
rtwn_setbits_4(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0xfc00, val << 10);
|
||||
|
||||
val = (rx_candidate->iqk_after >> 6) & 0xf;
|
||||
rtwn_setbits_4(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000, val << 28);
|
||||
done:
|
||||
/* Restore GNT_BT. */
|
||||
rtwn_write_4(sc, R23B_GNT_BT, gnt_bt);
|
||||
|
||||
rtwn_rf_setbits(sc, 0, R88E_RF_WE_LUT, 0, 0x80000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x18000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0001f);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xe6177);
|
||||
rtwn_rf_setbits(sc, 0, 0xed, 0, 0x20);
|
||||
rtwn_rf_write(sc, 0, 0x43, 0x300bd);
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
/* Inform firmware that we're done. */
|
||||
r88e_fw_cmd(sc, R23B_CMD_WLAN_CALIB, R23B_CMD_WLAN_CALIB_END,
|
||||
sizeof(R23B_CMD_WLAN_CALIB_END));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
r23b_temp_measure(struct rtwn_softc *sc)
|
||||
{
|
||||
rtwn_rf_setbits(sc, 0, R88E_RF_T_METER, 0, R88E_RF_T_METER_START);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192e/r92e.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
void
|
||||
r23b_fw_reset(struct rtwn_softc *sc, int reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case RTWN_FW_RESET_DOWNLOAD:
|
||||
case RTWN_FW_RESET_SHUTDOWN:
|
||||
return (r92c_fw_reset(sc, reason));
|
||||
case RTWN_FW_RESET_CHECKSUM:
|
||||
return (r92e_fw_reset(sc, reason));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
r23b_fw_download_enable(struct rtwn_softc *sc, int enable)
|
||||
{
|
||||
if (!enable) {
|
||||
/* MCU download disable. */
|
||||
rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 8051 enable. */
|
||||
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, 0,
|
||||
R92C_SYS_FUNC_EN_CPUEN, 1);
|
||||
/* MCU firmware download enable. */
|
||||
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN);
|
||||
|
||||
for (int ntries = 0; ntries <= 100; ntries++) {
|
||||
uint8_t val;
|
||||
|
||||
val = rtwn_read_1(sc, R92C_MCUFWDL);
|
||||
if (val & R92C_MCUFWDL_EN)
|
||||
break;
|
||||
|
||||
rtwn_write_1(sc, R92C_MCUFWDL, val | R92C_MCUFWDL_EN);
|
||||
rtwn_delay(sc, 1000);
|
||||
}
|
||||
|
||||
/* 8051 reset. */
|
||||
rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN,
|
||||
0, 2);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef R23B_FW_CMD_H
|
||||
#define R23B_FW_CMD_H
|
||||
|
||||
/*
|
||||
* Host to firmware commands.
|
||||
*/
|
||||
#define R23B_CMD_RSSI_SETTING 0x42
|
||||
#define R23B_CMD_PS_TDMA 0x60
|
||||
#define R23B_CMD_BT_INFO 0x61
|
||||
#define R23B_CMD_BT_WLANACT 0x63
|
||||
#define R23B_CMD_ANT_INV 0x65
|
||||
#define R23B_CMD_BT_MP_OPER 0x67
|
||||
#define R23B_CMD_WLAN_CALIB 0x6d
|
||||
#define R23B_CMD_BT_GRANT 0x6e
|
||||
|
||||
#define R23B_CMD_BT_WLANACT_IGNORE ((uint8_t[]){ 0 })
|
||||
|
||||
#define R23B_CMD_WLAN_CALIB_BEGIN ((uint8_t[]){ 1 })
|
||||
#define R23B_CMD_WLAN_CALIB_END ((uint8_t[]){ 0 })
|
||||
|
||||
#define R23B_CMD_BT_GRANT_LOW ((uint8_t[]){ 0 })
|
||||
#define R23B_CMD_BT_GRANT_HIGH ((uint8_t[]){ 1 })
|
||||
|
||||
/* Structure for R23B_CMD_RSSI_SETTING. */
|
||||
struct r23b_fw_cmd_rssi {
|
||||
uint8_t macid;
|
||||
uint8_t reserved;
|
||||
uint8_t pwdb;
|
||||
uint8_t uldl;
|
||||
} __packed;
|
||||
|
||||
/* Structure for R23B_CMD_BT_MP_OPER. */
|
||||
struct r23b_fw_cmd_btoper {
|
||||
uint8_t req_num;
|
||||
uint8_t opcode;
|
||||
#define R23B_BT_MP_OPER_WRITE_VAL 0xd
|
||||
#define R23B_BT_MP_OPER_WRITE_ADDR 0xc
|
||||
|
||||
uint8_t value;
|
||||
uint8_t addr;
|
||||
} __packed;
|
||||
|
||||
/* Structure for R23B_CMD_ANT_INV. */
|
||||
struct r23b_fw_cmd_antinv {
|
||||
uint8_t invert;
|
||||
uint8_t internal_switch;
|
||||
} __packed;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e.h>
|
||||
#include <dev/rtwn/rtl8188e/r88e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192e/r92e.h>
|
||||
#include <dev/rtwn/rtl8192e/r92e_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_reg.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_var.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_fw_cmd.h>
|
||||
|
||||
#include <dev/rtwn/rtl8821a/r21a_reg.h>
|
||||
|
||||
int
|
||||
r23b_set_page_size(struct rtwn_softc *sc)
|
||||
{
|
||||
return (rtwn_write_1(sc, R92C_PBP, SM(R92C_PBP_PSRX, R92C_PBP_256) |
|
||||
SM(R92C_PBP_PSTX, R92C_PBP_256)));
|
||||
}
|
||||
|
||||
void
|
||||
r23b_init_antsel(struct rtwn_softc *sc)
|
||||
{
|
||||
rtwn_setbits_4(sc, R88E_BB_PAD_CTRL, 0x1100000, 0);
|
||||
rtwn_setbits_4(sc, R92C_GPIO_MUXCFG, 0x10, 0x8);
|
||||
rtwn_setbits_4(sc, R92C_LEDCFG0, 0x400000, 0x800000);
|
||||
rtwn_setbits_4(sc, 0x944, 0, 0x3);
|
||||
rtwn_setbits_4(sc, 0x930, 0xff, 0x77);
|
||||
rtwn_setbits_4(sc, R92C_PWR_DATA, 0, 0x800);
|
||||
}
|
||||
|
||||
void
|
||||
r23b_init_bb_common(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r23b_softc *rs = sc->sc_priv;
|
||||
uint8_t val;
|
||||
|
||||
/* PathA RF Power On. */
|
||||
rtwn_write_1(sc, R92C_RF_CTRL,
|
||||
R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
|
||||
|
||||
rtwn_delay(sc, 10);
|
||||
|
||||
rtwn_rf_write(sc, 0, R92C_RF_IQADJ_G(0), 0x780);
|
||||
|
||||
rtwn_write_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB |
|
||||
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_DIO_PCIE |
|
||||
R92C_SYS_FUNC_EN_PCIEA | R92C_SYS_FUNC_EN_PPLL);
|
||||
|
||||
rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80);
|
||||
|
||||
for (int i = 0; i < sc->bb_size; i++) {
|
||||
const struct rtwn_bb_prog *bb_prog = &sc->bb_prog[i];
|
||||
|
||||
for (int j = 0; j < bb_prog->count; j++) {
|
||||
rtwn_write_4(sc, bb_prog->reg[j], bb_prog->val[j]);
|
||||
rtwn_delay(sc, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < sc->agc_size; i++) {
|
||||
const struct rtwn_agc_prog *agc_prog = &sc->agc_prog[i];
|
||||
|
||||
for (int j = 0; j < agc_prog->count; j++) {
|
||||
rtwn_write_4(sc, R92C_OFDM0_AGCRSSITABLE,
|
||||
agc_prog->val[j]);
|
||||
rtwn_delay(sc, 1);
|
||||
}
|
||||
}
|
||||
|
||||
rtwn_write_4(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422);
|
||||
rtwn_delay(sc, 1);
|
||||
rtwn_write_4(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
|
||||
rtwn_delay(sc, 1);
|
||||
rtwn_write_4(sc, R92C_HSSI_PARAM2(0), 0x00390204);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
val = rs->super.crystalcap & 0x3f;
|
||||
rtwn_setbits_4(sc, R92C_MAC_PHY_CTRL, R21A_MAC_PHY_CRYSTALCAP_M,
|
||||
SM(R21A_MAC_PHY_CRYSTALCAP, val | (val << 6)));
|
||||
}
|
||||
|
||||
void
|
||||
r23b_init_rf(struct rtwn_softc *sc)
|
||||
{
|
||||
r92e_init_rf(sc);
|
||||
|
||||
/* Init LCK. */
|
||||
rtwn_rf_write(sc, 0, R23B_RF_S0S1, 0xdfbe0);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, 0x8c01);
|
||||
rtwn_delay(sc, 200000);
|
||||
rtwn_rf_write(sc, 0, R23B_RF_S0S1, 0xdffe0);
|
||||
}
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
static void
|
||||
r23b_write_btreg(struct rtwn_softc *sc, uint8_t addr, uint8_t data)
|
||||
{
|
||||
struct r23b_fw_cmd_btoper cmd;
|
||||
|
||||
cmd.req_num = 0;
|
||||
cmd.opcode = R23B_BT_MP_OPER_WRITE_VAL;
|
||||
cmd.value = data;
|
||||
cmd.addr = 0;
|
||||
r88e_fw_cmd(sc, R23B_CMD_BT_MP_OPER, &cmd, sizeof(cmd));
|
||||
|
||||
rtwn_delay(sc, 200000); /* 200ms */
|
||||
|
||||
cmd.req_num = 1;
|
||||
cmd.opcode = R23B_BT_MP_OPER_WRITE_ADDR;
|
||||
cmd.value = 0;
|
||||
cmd.addr = addr;
|
||||
r88e_fw_cmd(sc, R23B_CMD_BT_MP_OPER, &cmd, sizeof(cmd));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
r23b_post_init(struct rtwn_softc *sc)
|
||||
{
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
struct r23b_fw_cmd_antinv cmd;
|
||||
const uint8_t ps_tdma[5] = { 0x8, 0x0, 0x0, 0x0, 0x0 };
|
||||
#endif
|
||||
|
||||
if (sc->macid_rpt2_max_num > 0) {
|
||||
rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT2_ENA);
|
||||
rtwn_write_1(sc, R88E_TX_RPT_MACID_MAX, sc->macid_rpt2_max_num);
|
||||
/* Enable periodic TX report; 32uS units */
|
||||
rtwn_write_2(sc, R88E_TX_RPT_TIME, 0xcdf0);
|
||||
}
|
||||
|
||||
rtwn_lc_calib(sc);
|
||||
rtwn_iq_calib(sc);
|
||||
|
||||
/* Enable RF */
|
||||
|
||||
/* XXX lots of magic numbers here. */
|
||||
|
||||
rtwn_write_1(sc, 0x790, 0x5);
|
||||
rtwn_write_1(sc, 0x778, 0x1);
|
||||
rtwn_setbits_1(sc, R92C_GPIO_MUXCFG, 0, R92C_GPIO_MUXCFG_ENBT);
|
||||
|
||||
/* WiFi TRx Mask on */
|
||||
rtwn_rf_write(sc, 0, R92C_RF_IQADJ_G(0), 0x780);
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
/* BT TRx Mask on */
|
||||
r23b_write_btreg(sc, 0x3c, 0x15);
|
||||
|
||||
r88e_fw_cmd(sc, R23B_CMD_BT_GRANT, R23B_CMD_BT_GRANT_LOW,
|
||||
sizeof(R23B_CMD_BT_GRANT_LOW));
|
||||
#endif
|
||||
|
||||
rtwn_write_1(sc, 0x76e, 0x4);
|
||||
rtwn_setbits_1(sc, R88E_BB_PAD_CTRL + 3, 0, 0x20);
|
||||
rtwn_setbits_1(sc, R92C_PWR_DATA + 1, 0, 0x8);
|
||||
rtwn_write_1(sc, 0x974, 0xff);
|
||||
rtwn_setbits_1(sc, 0x944, 0, 0x3);
|
||||
rtwn_write_1(sc, 0x930, 0x77);
|
||||
|
||||
rtwn_setbits_4(sc, R92C_LEDCFG0, 0x1000000, 0x800000);
|
||||
rtwn_setbits_1(sc, R88E_BB_PAD_CTRL, 0x1, 0);
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
/* Inform firmware of the antenna inversion. */
|
||||
cmd.internal_switch = 0;
|
||||
cmd.invert = 1;
|
||||
|
||||
r88e_fw_cmd(sc, R23B_CMD_ANT_INV, &cmd, sizeof(cmd));
|
||||
#endif
|
||||
|
||||
rtwn_write_4(sc, R23B_ANT_SEL, 0x80);
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
r88e_fw_cmd(sc, R23B_CMD_PS_TDMA, ps_tdma, sizeof(ps_tdma));
|
||||
#endif
|
||||
|
||||
/* btcoex table */
|
||||
rtwn_write_4(sc, R23B_BTCOEX_TABLE(0), 0x55555555);
|
||||
rtwn_write_4(sc, R23B_BTCOEX_TABLE(1), 0x55555555);
|
||||
rtwn_write_4(sc, R23B_BTCOEX_TABLE(2), 0x00ffffff);
|
||||
rtwn_write_4(sc, R23B_BTCOEX_TABLE(3), 0x00000003);
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
r88e_fw_cmd(sc, R23B_CMD_BT_INFO, &(uint8_t){ 1 }, sizeof(uint8_t));
|
||||
r88e_fw_cmd(sc, R23B_CMD_BT_WLANACT, R23B_CMD_BT_WLANACT_IGNORE,
|
||||
sizeof(R23B_CMD_BT_WLANACT_IGNORE));
|
||||
#endif
|
||||
|
||||
/* ACK for xmit mgmt frames. */
|
||||
rtwn_setbits_4(sc, R92C_FWHW_TXQ_CTRL, 0, R23B_FWHW_TXQ_CTRL_ACK_MGNT);
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
if (sc->sc_flags & RTWN_FW_LOADED) {
|
||||
if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
|
||||
/* TODO: implement */
|
||||
sc->sc_ratectl = RTWN_RATECTL_NET80211;
|
||||
} else
|
||||
sc->sc_ratectl = sc->sc_ratectl_sysctl;
|
||||
} else
|
||||
#endif
|
||||
sc->sc_ratectl = RTWN_RATECTL_NONE;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_reg.h>
|
||||
|
||||
void
|
||||
r23b_set_led(struct rtwn_softc *sc, int led, int on)
|
||||
{
|
||||
if (led != RTWN_LED_LINK)
|
||||
return;
|
||||
|
||||
sc->ledlink = on;
|
||||
rtwn_setbits_1(sc, R92C_LEDCFG2, R23B_LEDCFG2_LED_M,
|
||||
R23B_LEDCFG2_LED_SW_CTRL | (on ? 0 : R23B_LEDCFG2_LED_DISABLE));
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef R23B_PRIV_H
|
||||
#define R23B_PRIV_H
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b_rom_defs.h>
|
||||
|
||||
static const struct rtwn_mac_prog rtl8723b_mac[] = {
|
||||
{ 0x02f, 0x30 }, { 0x035, 0x00 }, { 0x039, 0x08 }, { 0x04e, 0xe0 },
|
||||
{ 0x064, 0x00 }, { 0x067, 0x20 }, { 0x428, 0x0a }, { 0x429, 0x10 },
|
||||
{ 0x430, 0x00 }, { 0x431, 0x00 }, { 0x432, 0x00 }, { 0x433, 0x01 },
|
||||
{ 0x434, 0x04 }, { 0x435, 0x05 }, { 0x436, 0x07 }, { 0x437, 0x08 },
|
||||
{ 0x43c, 0x04 }, { 0x43d, 0x05 }, { 0x43e, 0x07 }, { 0x43f, 0x08 },
|
||||
{ 0x440, 0x5d }, { 0x441, 0x01 }, { 0x442, 0x00 }, { 0x444, 0x10 },
|
||||
{ 0x445, 0x00 }, { 0x446, 0x00 }, { 0x447, 0x00 }, { 0x448, 0x00 },
|
||||
{ 0x449, 0xf0 }, { 0x44a, 0x0f }, { 0x44b, 0x3e }, { 0x44c, 0x10 },
|
||||
{ 0x44d, 0x00 }, { 0x44e, 0x00 }, { 0x44f, 0x00 }, { 0x450, 0x00 },
|
||||
{ 0x451, 0xf0 }, { 0x452, 0x0f }, { 0x453, 0x00 }, { 0x456, 0x5e },
|
||||
{ 0x460, 0x66 }, { 0x461, 0x66 }, { 0x4c8, 0xff }, { 0x4c9, 0x08 },
|
||||
{ 0x4cc, 0xff }, { 0x4cd, 0xff }, { 0x4ce, 0x01 }, { 0x500, 0x26 },
|
||||
{ 0x501, 0xa2 }, { 0x502, 0x2f }, { 0x503, 0x00 }, { 0x504, 0x28 },
|
||||
{ 0x505, 0xa3 }, { 0x506, 0x5e }, { 0x507, 0x00 }, { 0x508, 0x2b },
|
||||
{ 0x509, 0xa4 }, { 0x50a, 0x5e }, { 0x50b, 0x00 }, { 0x50c, 0x4f },
|
||||
{ 0x50d, 0xa4 }, { 0x50e, 0x00 }, { 0x50f, 0x00 }, { 0x512, 0x1c },
|
||||
{ 0x514, 0x0a }, { 0x516, 0x0a }, { 0x525, 0x4f }, { 0x550, 0x10 },
|
||||
{ 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55c, 0x50 }, { 0x55d, 0xff },
|
||||
{ 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a }, { 0x620, 0xff },
|
||||
{ 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff }, { 0x624, 0xff },
|
||||
{ 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff }, { 0x638, 0x50 },
|
||||
{ 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e }, { 0x63f, 0x0e },
|
||||
{ 0x640, 0x40 }, { 0x642, 0x40 }, { 0x643, 0x00 }, { 0x652, 0xc8 },
|
||||
{ 0x66e, 0x05 }, { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 },
|
||||
{ 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 },
|
||||
{ 0x70b, 0x87 }, { 0x765, 0x18 }, { 0x76e, 0x04 }
|
||||
};
|
||||
|
||||
static const uint16_t rtl8723b_bb_regs[] = {
|
||||
0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c, 0x820, 0x824,
|
||||
0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, 0x840, 0x844, 0x848, 0x84c,
|
||||
0x850, 0x854, 0x858, 0x85c, 0x860, 0x864, 0x868, 0x86c, 0x870, 0x874,
|
||||
0x878, 0x87c, 0x880, 0x884, 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c,
|
||||
0x900, 0x904, 0x908, 0x90c, 0x910, 0x914, 0xa00, 0xa04, 0xa08, 0xa0c,
|
||||
0xa10, 0xa14, 0xa18, 0xa1c, 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74,
|
||||
0xa78, 0xa7c, 0xa80, 0xb2c, 0xc00, 0xc04, 0xc08, 0xc0c, 0xc10, 0xc14,
|
||||
0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c,
|
||||
0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64,
|
||||
0xc68, 0xc6c, 0xc70, 0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88, 0xc8c,
|
||||
0xc90, 0xc94, 0xc98, 0xc9c, 0xca0, 0xca4, 0xca8, 0xcac, 0xcb0, 0xcb4,
|
||||
0xcb8, 0xcbc, 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc,
|
||||
0xce0, 0xce4, 0xce8, 0xcec, 0xd00, 0xd04, 0xd08, 0xd0c, 0xd10, 0xd14,
|
||||
0xd18, 0xd2c, 0xd30, 0xd34, 0xd38, 0xd3c, 0xd40, 0xd44, 0xd48, 0xd4c,
|
||||
0xd50, 0xd54, 0xd58, 0xd5c, 0xd60, 0xd64, 0xd68, 0xd6c, 0xd70, 0xd74,
|
||||
0xd78, 0xe00, 0xe04, 0xe08, 0xe10, 0xe14, 0xe18, 0xe1c, 0xe28, 0xe30,
|
||||
0xe34, 0xe38, 0xe3c, 0xe40, 0xe44, 0xe48, 0xe4c, 0xe50, 0xe54, 0xe58,
|
||||
0xe5c, 0xe60, 0xe68, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84,
|
||||
0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xf14, 0xf4c,
|
||||
0xf00, 0x820, 0x800
|
||||
};
|
||||
|
||||
static const uint32_t rtl8723b_bb_vals[] = {
|
||||
0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331, 0x020c3d10,
|
||||
0x02200385, 0x00000000, 0x01000100, 0x00190204, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a11a9, 0x01000014,
|
||||
0x66f60110, 0x061f0649, 0x00000000, 0x27272700, 0x07000760, 0x25004000,
|
||||
0x00000808, 0x00000000, 0xb0000c1c, 0x00000001, 0x00000000, 0xccc000c0,
|
||||
0x00000800, 0xfffffffe, 0x40302010, 0x00706050, 0x00000000, 0x00000023,
|
||||
0x00000000, 0x81121111, 0x00000002, 0x00000201, 0x00d047c8, 0x80ff800c,
|
||||
0x8c838300, 0x2e7f120f, 0x9500bb78, 0x1114d028, 0x00881117, 0x89140f00,
|
||||
0x1a1b0000, 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007,
|
||||
0x00000900, 0x225b0606, 0x21806490, 0x00000000, 0x48071d40, 0x03a05611,
|
||||
0x000000e4, 0x6c6c6c6c, 0x08800000, 0x40000100, 0x08800000, 0x40000100,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x69e9ac44, 0x469652af,
|
||||
0x49795994, 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f,
|
||||
0x69553420, 0x43bc0094, 0x00013149, 0x00250492, 0x00000000, 0x7112848b,
|
||||
0x47c00bff, 0x00000036, 0x2c7f000d, 0x020610db, 0x0000001f, 0x00b91612,
|
||||
0x390000e4, 0x20f60000, 0x40000100, 0x20200000, 0x00020e1a, 0x00000000,
|
||||
0x00020e1a, 0x00007f7f, 0x00000000, 0x000300a0, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427, 0x00766932,
|
||||
0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, 0x00000740, 0x40020401,
|
||||
0x0000907f, 0x20010201, 0xa0633333, 0x3333bc53, 0x7a8f5b6f, 0xcc979975,
|
||||
0x00000000, 0x80608000, 0x00000000, 0x00127353, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x6437140a, 0x00000000, 0x00000282, 0x30032064,
|
||||
0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, 0x322c2220,
|
||||
0x000e3c24, 0x2d2d2d2d, 0x2d2d2d2d, 0x0390272d, 0x2d2d2d2d, 0x2d2d2d2d,
|
||||
0x2d2d2d2d, 0x2d2d2d2d, 0x00000000, 0x1000dc1f, 0x10008c1f, 0x02140102,
|
||||
0x681604c2, 0x01007c00, 0x01004800, 0xfb000000, 0x000028d1, 0x1000dc1f,
|
||||
0x10008c1f, 0x02140102, 0x28160d05, 0x00000008, 0x001b2556, 0x00c00096,
|
||||
0x00c00096, 0x01000056, 0x01000014, 0x01000056, 0x01000014, 0x00c00096,
|
||||
0x01000056, 0x00c00096, 0x00c00096, 0x00c00096, 0x00c00096, 0x000000d6,
|
||||
0x000000d6, 0x01c00016, 0x00000003, 0x00000000, 0x00000300, 0x01000100,
|
||||
0x83040000
|
||||
};
|
||||
|
||||
static const struct rtwn_bb_prog rtl8723b_bb[] = {
|
||||
{
|
||||
nitems(rtl8723b_bb_regs),
|
||||
rtl8723b_bb_regs,
|
||||
rtl8723b_bb_vals,
|
||||
{ 0 },
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
static const uint32_t rtl8723b_agc_vals[] = {
|
||||
0xfd000001, 0xfc010001, 0xfb020001, 0xfa030001, 0xf9040001, 0xf8050001,
|
||||
0xf7060001, 0xf6070001, 0xf5080001, 0xf4090001, 0xf30a0001, 0xf20b0001,
|
||||
0xf10c0001, 0xf00d0001, 0xef0e0001, 0xee0f0001, 0xed100001, 0xec110001,
|
||||
0xeb120001, 0xea130001, 0xe9140001, 0xe8150001, 0xe7160001, 0xe6170001,
|
||||
0xe5180001, 0xe4190001, 0xe31a0001, 0xa51b0001, 0xa41c0001, 0xa31d0001,
|
||||
0x671e0001, 0x661f0001, 0x65200001, 0x64210001, 0x63220001, 0x4a230001,
|
||||
0x49240001, 0x48250001, 0x47260001, 0x46270001, 0x45280001, 0x44290001,
|
||||
0x432a0001, 0x422b0001, 0x292c0001, 0x282d0001, 0x272e0001, 0x262f0001,
|
||||
0x0a300001, 0x09310001, 0x08320001, 0x07330001, 0x06340001, 0x05350001,
|
||||
0x04360001, 0x03370001, 0x02380001, 0x01390001, 0x013a0001, 0x013b0001,
|
||||
0x013c0001, 0x013d0001, 0x013e0001, 0x013f0001, 0xfc400001, 0xfb410001,
|
||||
0xfa420001, 0xf9430001, 0xf8440001, 0xf7450001, 0xf6460001, 0xf5470001,
|
||||
0xf4480001, 0xf3490001, 0xf24a0001, 0xf14b0001, 0xf04c0001, 0xef4d0001,
|
||||
0xee4e0001, 0xed4f0001, 0xec500001, 0xeb510001, 0xea520001, 0xe9530001,
|
||||
0xe8540001, 0xe7550001, 0xe6560001, 0xe5570001, 0xe4580001, 0xe3590001,
|
||||
0xa65a0001, 0xa55b0001, 0xa45c0001, 0xa35d0001, 0x675e0001, 0x665f0001,
|
||||
0x65600001, 0x64610001, 0x63620001, 0x62630001, 0x61640001, 0x48650001,
|
||||
0x47660001, 0x46670001, 0x45680001, 0x44690001, 0x436a0001, 0x426b0001,
|
||||
0x286c0001, 0x276d0001, 0x266e0001, 0x256f0001, 0x24700001, 0x09710001,
|
||||
0x08720001, 0x07730001, 0x06740001, 0x05750001, 0x04760001, 0x03770001,
|
||||
0x02780001, 0x01790001, 0x017a0001, 0x017b0001, 0x017c0001, 0x017d0001,
|
||||
0x017e0001, 0x017f0001
|
||||
};
|
||||
|
||||
static const struct rtwn_agc_prog rtl8723b_agc[] = {
|
||||
{
|
||||
nitems(rtl8723b_agc_vals),
|
||||
rtl8723b_agc_vals,
|
||||
{ 0 },
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
static const uint8_t rtl8723b_rf_regs[] = {
|
||||
0x000, 0x0b0, 0x0fe, 0x0fe, 0x0fe, 0x0b1, 0x0fe, 0x0fe, 0x0fe, 0x0b2,
|
||||
0x0b5, 0x0b6, 0x0b7, 0x0b8, 0x05c, 0x07c, 0x07e, 0x08b, 0x0b0, 0x01c,
|
||||
0x01e, 0x0df, 0x050,
|
||||
|
||||
/*
|
||||
* The vendor driver has a condition here that sets this to 0x0006b10e
|
||||
* if the package type is TFBGA90, TFBGA80 or TFBGA79.
|
||||
*
|
||||
* However, it seems to never actually read the package type from the
|
||||
* ROM, so in practice this is always ignored.
|
||||
*/
|
||||
0x051,
|
||||
|
||||
0x052, 0x053, 0x054, 0x055, 0x0dd, 0x070,
|
||||
|
||||
/* Same here. */
|
||||
0x071,
|
||||
|
||||
0x072, 0x073, 0x074, 0x075, 0x0ef, 0x034, 0x035, 0x034, 0x035, 0x034,
|
||||
0x035, 0x034, 0x035, 0x034, 0x035, 0x034, 0x035, 0x034, 0x035, 0x034,
|
||||
0x035, 0x034, 0x035, 0x034, 0x035, 0x034, 0x035, 0x0ef, 0x0ef, 0x0ed,
|
||||
0x044, 0x044, 0x044, 0x044, 0x044, 0x044, 0x044, 0x044, 0x044, 0x044,
|
||||
0x044, 0x0ef, 0x0ed, 0x07f, 0x0ef, 0x03b, 0x03b, 0x03b, 0x03b, 0x03b,
|
||||
0x03b, 0x03b, 0x03b, 0x0ef, 0x0ed, 0x040, 0x040, 0x040, 0x040, 0x040,
|
||||
0x040, 0x040, 0x040, 0x0ed, 0x082, 0x083, 0x084, 0x085, 0x0a2, 0x0a3,
|
||||
0x0a4, 0x0a5, 0x0ed, 0x0ef, 0x056, 0x076, 0x001
|
||||
};
|
||||
|
||||
static const uint32_t rtl8723b_rf_vals[] = {
|
||||
0x00010000, 0x000dffe0, 0x00000000, 0x00000000, 0x00000000, 0x00000018,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00084c00, 0x0000d2cc, 0x000925aa,
|
||||
0x00000010, 0x0000907f, 0x00000002, 0x00000002, 0x00000005, 0x0006fc00,
|
||||
0x000ff9f0, 0x000739d2, 0x00000000, 0x00000780, 0x00067435,
|
||||
|
||||
0x0006b04e,
|
||||
|
||||
0x000007D2, 0x00000000, 0x00050400, 0x0004026E, 0x0000004C, 0x00067435,
|
||||
|
||||
0x0006b04e,
|
||||
|
||||
0x000007d2, 0x00000000, 0x00050400, 0x0004026e, 0x00000100, 0x0000add7,
|
||||
0x00005c00, 0x00009dd4, 0x00005000, 0x00008dd1, 0x00004400, 0x00007dce,
|
||||
0x00003800, 0x00006cd1, 0x00004400, 0x00005cce, 0x00003800, 0x000048ce,
|
||||
0x00004400, 0x000034ce, 0x00003800, 0x00002451, 0x00004400, 0x0000144e,
|
||||
0x00003800, 0x00000051, 0x00004400, 0x00000000, 0x00000100, 0x00000010,
|
||||
0x0000add7, 0x00009dd4, 0x00008dd1, 0x00007dce, 0x00006cc1, 0x00005cce,
|
||||
0x000044d1, 0x000034ce, 0x00002451, 0x0000144e, 0x00000051, 0x00000000,
|
||||
0x00000000, 0x00020080, 0x00002000, 0x000380ef, 0x000302fe, 0x00028ce6,
|
||||
0x000200bc, 0x000188a5, 0x00010fbc, 0x00008f71, 0x00000900, 0x00000000,
|
||||
0x00000001, 0x000380ef, 0x000302fe, 0x00028ce6, 0x000200bc, 0x000188a5,
|
||||
0x00010fbc, 0x00008f71, 0x00000900, 0x00000000, 0x00080000, 0x00008000,
|
||||
0x00048d80, 0x00068000, 0x00080000, 0x00008000, 0x00048d80, 0x00068000,
|
||||
0x00000002, 0x00000002, 0x00000032, 0x00000032, 0x00000780
|
||||
};
|
||||
|
||||
static const struct rtwn_rf_prog rtl8723b_rf[] = {
|
||||
{
|
||||
nitems(rtl8723b_rf_regs),
|
||||
rtl8723b_rf_regs,
|
||||
rtl8723b_rf_vals,
|
||||
{ 0 },
|
||||
NULL
|
||||
},
|
||||
{ 0, NULL, NULL, { 0 }, NULL }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef R23B_REG_H
|
||||
#define R23B_REG_H
|
||||
|
||||
#define R23B_BTCOEX_TABLE(i) (0x6c0 + (i) * 4)
|
||||
#define R23B_GNT_BT 0x764
|
||||
#define R23B_ANT_SEL 0x948
|
||||
|
||||
/* Bits for R92C_EFUSE_TEST. */
|
||||
#define R23B_EFUSE_TEST_SEL_M 0x300
|
||||
#define R23B_EFUSE_TEST_SEL_S 8
|
||||
#define R23B_EFUSE_TEST_SEL_WIFI 0
|
||||
#define R23B_EFUSE_TEST_SEL_BT0 1
|
||||
#define R23B_EFUSE_TEST_SEL_BT1 2
|
||||
#define R23B_EFUSE_TEST_SEL_BT2 3
|
||||
#define R23B_EFUSE_TEST_PGMEN 0x800
|
||||
|
||||
/* Bits for R92C_PWR_DATA. */
|
||||
#define R23B_PWR_DATA_RFE_CTRL_EN 0x800
|
||||
|
||||
/* Bits for R92C_LEDCFG0. */
|
||||
#define R23B_LEDCFG0_DPDT_SEL_EN 0x800000
|
||||
|
||||
/* Bits for R92C_LEDCFG2. */
|
||||
#define R23B_LEDCFG2_LED_SW_CTRL 0x20
|
||||
#define R23B_LEDCFG2_LED_DISABLE 0x04
|
||||
#define R23B_LEDCFG2_LED_M 0x7f
|
||||
|
||||
/* Bits for R88E_BB_PAD_CTRL. */
|
||||
#define R23B_BB_PAD_CTRL_DPDT_SEL_DATA 0x1
|
||||
|
||||
/* Bits for R92C_RXDMA_AGG_PG_TH. */
|
||||
#define R23B_RXDMA_AGG_PG_TH_EN 0x80000000
|
||||
#define R23B_RXDMA_AGG_PG_TH_SIZE_M 0xf
|
||||
#define R23B_RXDMA_AGG_PG_TH_SIZE_S 0
|
||||
#define R23B_RXDMA_AGG_PG_TH_TIME_M 0xff00
|
||||
#define R23B_RXDMA_AGG_PG_TH_TIME_S 8
|
||||
|
||||
/* Bits for R92C_FWHW_TXQ_CTRL. */
|
||||
#define R23B_FWHW_TXQ_CTRL_ACK_MGNT 0x1000
|
||||
|
||||
/* Bits for R92C_WMAC_TRXPTCL_CTL. */
|
||||
#define R23B_WMAC_TRXPTCL_CTL_HT40 0x80
|
||||
#define R23B_WMAC_TRXPTCL_CTL_VHT80 0x100
|
||||
|
||||
/* Bits for R23B_ANT_SEL. */
|
||||
#define R23B_ANT_SEL_S0 0x000
|
||||
#define R23B_ANT_SEL_S1 0x280
|
||||
|
||||
/*
|
||||
* RF (6052) registers.
|
||||
*/
|
||||
#define R23B_RF_S0S1 0xb0
|
||||
|
||||
/* Bits for R92C_RF_CHNLBW. */
|
||||
#define R23B_RF_CHNLBW_BW40 0x00400
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
|
||||
void
|
||||
r23b_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
rtwn_write_4(sc, R92C_LSSI_PARAM(chain),
|
||||
SM(R88E_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val));
|
||||
|
||||
/*
|
||||
* The vendor driver claims that writing to 0xb6 may fail under high
|
||||
* temperature conditions, but only attempts to retry during RF init.
|
||||
*
|
||||
* It is not mentioned why 0xb2 is also special.
|
||||
*/
|
||||
switch (addr) {
|
||||
case 0xb6:
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
reg = rtwn_rf_read(sc, chain, addr);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
for (int retry = 0; (reg & ~0xff) != (val & ~0xff) &&
|
||||
retry < 6; retry++) {
|
||||
rtwn_write_4(sc, R92C_LSSI_PARAM(chain),
|
||||
SM(R88E_LSSI_PARAM_ADDR, addr) |
|
||||
SM(R92C_LSSI_PARAM_DATA, val));
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
reg = rtwn_rf_read(sc, chain, addr);
|
||||
}
|
||||
break;
|
||||
case 0xb2:
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
reg = rtwn_rf_read(sc, chain, addr);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
for (int retry = 0; reg != val && retry < 6; retry++) {
|
||||
rtwn_write_4(sc, R92C_LSSI_PARAM(chain),
|
||||
SM(R88E_LSSI_PARAM_ADDR, addr) |
|
||||
SM(R92C_LSSI_PARAM_DATA, val));
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
rtwn_rf_write(sc, chain, R92C_RF_CHNLBW, 0x0fc07);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
reg = rtwn_rf_read(sc, chain, addr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192e/r92e_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_reg.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_var.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_rom_image.h>
|
||||
|
||||
#include <dev/rtwn/rtl8812a/r12a_rom_image.h>
|
||||
|
||||
int
|
||||
r23b_efuse_preread(struct rtwn_softc *sc)
|
||||
{
|
||||
int error;
|
||||
|
||||
/* Switch to the WIFI bank. */
|
||||
error = rtwn_setbits_4(sc, R92C_EFUSE_TEST, R23B_EFUSE_TEST_SEL_M,
|
||||
SM(R23B_EFUSE_TEST_SEL, R23B_EFUSE_TEST_SEL_WIFI));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* NB: Vendor driver does this on every read. */
|
||||
error = rtwn_setbits_2(sc, R92C_EFUSE_TEST, R23B_EFUSE_TEST_PGMEN, 0);
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
r23b_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
|
||||
{
|
||||
struct r23b_rom *rom = (struct r23b_rom *)buf;
|
||||
struct r23b_softc *rs = sc->sc_priv;
|
||||
|
||||
for (int i = 0; i < sc->ntxchains; i++) {
|
||||
struct r23b_tx_pwr_2g *pwr_2g = &rom->tx_pwr[i].pwr_2g;
|
||||
struct r23b_tx_pwr_diff_2g *pwr_diff_2g =
|
||||
&rom->tx_pwr[i].pwr_diff_2g;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < R23B_GROUP_2G - 1; j++) {
|
||||
rs->super.cck_tx_pwr[i][j] = RTWN_GET_ROM_VAR(
|
||||
pwr_2g->cck[j], R23B_DEF_TX_PWR_2G);
|
||||
rs->super.ht40_tx_pwr_2g[i][j] =
|
||||
RTWN_GET_ROM_VAR(pwr_2g->ht40[j],
|
||||
R23B_DEF_TX_PWR_2G);
|
||||
}
|
||||
rs->super.cck_tx_pwr[i][j] = RTWN_GET_ROM_VAR(pwr_2g->cck[j],
|
||||
R23B_DEF_TX_PWR_2G);
|
||||
|
||||
rs->super.cck_tx_pwr_diff_2g[i][0] = 0;
|
||||
rs->super.bw40_tx_pwr_diff_2g[i][0] = 0;
|
||||
if (pwr_diff_2g->ht20_ofdm == 0xff) {
|
||||
rs->super.ofdm_tx_pwr_diff_2g[i][0] =
|
||||
R23B_DEF_TX_OFDM_DIFF;
|
||||
rs->super.bw20_tx_pwr_diff_2g[i][0] =
|
||||
R23B_DEF_TX_HT20_DIFF;
|
||||
} else {
|
||||
rs->super.ofdm_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8(
|
||||
MS(pwr_diff_2g->ht20_ofdm, LOW_PART));
|
||||
rs->super.bw20_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8(
|
||||
MS(pwr_diff_2g->ht20_ofdm, HIGH_PART));
|
||||
}
|
||||
|
||||
for (j = 1; j < R23B_MAX_TX_COUNT; j++) {
|
||||
struct r23b_tx_pwr_diff123_2g *diff =
|
||||
&pwr_diff_2g->diff123[j - 1];
|
||||
|
||||
if (diff->ofdm_cck == 0xff) {
|
||||
rs->super.ofdm_tx_pwr_diff_2g[i][j] =
|
||||
rs->super.cck_tx_pwr_diff_2g[i][j] =
|
||||
R23B_DEF_TX_DIFF;
|
||||
} else {
|
||||
rs->super.cck_tx_pwr_diff_2g[i][j] =
|
||||
RTWN_SIGN4TO8(MS(diff->ofdm_cck, LOW_PART));
|
||||
rs->super.ofdm_tx_pwr_diff_2g[i][j] =
|
||||
RTWN_SIGN4TO8(
|
||||
MS(diff->ofdm_cck, HIGH_PART));
|
||||
}
|
||||
|
||||
if (diff->ht40_ht20 == 0xff) {
|
||||
rs->super.bw40_tx_pwr_diff_2g[i][j] =
|
||||
rs->super.bw20_tx_pwr_diff_2g[i][j] =
|
||||
R23B_DEF_TX_DIFF;
|
||||
} else {
|
||||
rs->super.bw40_tx_pwr_diff_2g[i][j] =
|
||||
RTWN_SIGN4TO8(
|
||||
MS(diff->ht40_ht20, HIGH_PART));
|
||||
rs->super.bw20_tx_pwr_diff_2g[i][j] =
|
||||
RTWN_SIGN4TO8(
|
||||
MS(diff->ht40_ht20, LOW_PART));
|
||||
}
|
||||
}
|
||||
|
||||
rs->bt_antnum = rom->rf_bt_opt & R12A_RF_BT_OPT_ANT_NUM;
|
||||
}
|
||||
|
||||
rs->super.crystalcap = RTWN_GET_ROM_VAR(rom->crystal_cap,
|
||||
R23B_ROM_CRYSTALCAP_DEF);
|
||||
|
||||
sc->thermal_meter = RTWN_GET_ROM_VAR(rom->thermal_meter,
|
||||
R23B_ROM_THERMALMETER_DEF);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef R23B_ROM_DEFS_H
|
||||
#define R23B_ROM_DEFS_H
|
||||
|
||||
#define R23B_MAX_TX_COUNT 4
|
||||
#define R23B_MAX_RF_PATH 4
|
||||
#define R23B_GROUP_2G 6
|
||||
|
||||
#define R23B_EFUSE_MAX_LEN 512
|
||||
#define R23B_EFUSE_MAP_LEN 512
|
||||
|
||||
#endif /* R23B_ROM_DEFS_H */
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef R23B_ROM_IMAGE_H
|
||||
#define R23B_ROM_IMAGE_H
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b_rom_defs.h>
|
||||
|
||||
#define R23B_DEF_TX_PWR_2G 0x2d
|
||||
#define R23B_DEF_TX_HT20_DIFF 0x02
|
||||
#define R23B_DEF_TX_OFDM_DIFF 0x04
|
||||
#define R23B_DEF_TX_DIFF 0xfe
|
||||
|
||||
struct r23b_tx_pwr_2g {
|
||||
uint8_t cck[R23B_GROUP_2G];
|
||||
uint8_t ht40[R23B_GROUP_2G - 1];
|
||||
} __packed;
|
||||
|
||||
struct r23b_tx_pwr_diff123_2g {
|
||||
uint8_t ht40_ht20;
|
||||
uint8_t ofdm_cck;
|
||||
} __packed;
|
||||
|
||||
struct r23b_tx_pwr_diff_2g {
|
||||
uint8_t ht20_ofdm;
|
||||
struct r23b_tx_pwr_diff123_2g diff123[R23B_MAX_TX_COUNT - 1];
|
||||
} __packed;
|
||||
|
||||
struct r23b_tx_pwr {
|
||||
struct r23b_tx_pwr_2g pwr_2g;
|
||||
struct r23b_tx_pwr_diff_2g pwr_diff_2g;
|
||||
uint8_t reserved[24];
|
||||
} __packed;
|
||||
|
||||
struct r23b_rom {
|
||||
uint16_t id;
|
||||
uint8_t reserved1[14];
|
||||
struct r23b_tx_pwr tx_pwr[R23B_MAX_RF_PATH];
|
||||
uint8_t channel_plan;
|
||||
uint8_t crystal_cap;
|
||||
#define R23B_ROM_CRYSTALCAP_DEF 0x20
|
||||
|
||||
uint8_t thermal_meter;
|
||||
#define R23B_ROM_THERMALMETER_DEF 0x18
|
||||
|
||||
uint8_t iqk_lck;
|
||||
uint8_t pa_type;
|
||||
uint8_t lna_type_2g;
|
||||
uint8_t reserved2;
|
||||
uint8_t lna_type_5g;
|
||||
uint8_t reserved3;
|
||||
uint8_t rf_board_opt;
|
||||
uint8_t rf_feature_opt;
|
||||
uint8_t rf_bt_opt;
|
||||
uint8_t version;
|
||||
uint8_t customer_id;
|
||||
uint8_t tx_bswing_2g;
|
||||
uint8_t reserved4;
|
||||
uint8_t tx_pwr_calib_rate;
|
||||
uint8_t rf_antenna_opt;
|
||||
uint8_t rfe_opt;
|
||||
uint8_t country_code;
|
||||
|
||||
struct {
|
||||
uint8_t reserved1[52];
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
uint8_t reserved2[3];
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
uint8_t reserved3[243];
|
||||
} __packed usb;
|
||||
} __packed;
|
||||
|
||||
_Static_assert(sizeof(struct r23b_rom) == R23B_EFUSE_MAP_LEN,
|
||||
"R23B_EFUSE_MAP_LEN must be equal to sizeof(struct r23b_rom)!");
|
||||
|
||||
#endif /* R23B_ROM_IMAGE_H */
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
|
||||
int8_t
|
||||
r23b_get_rssi_cck(struct rtwn_softc *sc, void *physt)
|
||||
{
|
||||
struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt;
|
||||
int8_t lna_idx, vga_idx, rssi;
|
||||
|
||||
lna_idx = (phy->agc_rpt & 0xe0) >> 5;
|
||||
vga_idx = (phy->agc_rpt & 0x1f);
|
||||
|
||||
rssi = -2 * vga_idx;
|
||||
switch (lna_idx) {
|
||||
case 6:
|
||||
rssi -= 34;
|
||||
break;
|
||||
case 4:
|
||||
rssi -= 14;
|
||||
break;
|
||||
case 1:
|
||||
rssi += 6;
|
||||
break;
|
||||
case 0:
|
||||
rssi += 16;
|
||||
break;
|
||||
default:
|
||||
rssi = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return (rssi);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef R23B_VAR_H
|
||||
#define R23B_VAR_H
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b_rom_defs.h>
|
||||
|
||||
struct r23b_softc {
|
||||
struct r92e_softc super;
|
||||
|
||||
uint8_t bt_antnum;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef RTL8723BU_H
|
||||
#define RTL8723BU_H
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
|
||||
/* r23bu_init.c */
|
||||
int r23bu_power_on(struct rtwn_softc *);
|
||||
void r23bu_power_off(struct rtwn_softc *);
|
||||
void r23bu_init_bb(struct rtwn_softc *);
|
||||
void r23bu_init_ampdu(struct rtwn_softc *);
|
||||
void r23bu_init_rx_agg(struct rtwn_softc *sc);
|
||||
|
||||
/* r23bu_rom.c */
|
||||
void r23bu_parse_rom(struct rtwn_softc *, uint8_t *);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
#include <dev/rtwn/if_rtwn_nop.h>
|
||||
|
||||
#include <dev/rtwn/usb/rtwn_usb_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192e/r92e.h>
|
||||
#include <dev/rtwn/rtl8192e/r92e_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_var.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_priv.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/usb/r23bu.h>
|
||||
|
||||
#include <dev/rtwn/rtl8812a/r12a_tx_desc.h>
|
||||
|
||||
#include <dev/rtwn/rtl8812a/usb/r12au.h>
|
||||
|
||||
#include <dev/rtwn/rtl8821a/r21a_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8821a/usb/r21au.h>
|
||||
|
||||
void r23bu_attach(struct rtwn_usb_softc *);
|
||||
|
||||
static void
|
||||
r23bu_attach_private(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r23b_softc *rs;
|
||||
|
||||
sc->sc_priv = rs = malloc(sizeof(struct r23b_softc),
|
||||
M_RTWN_PRIV, M_WAITOK | M_ZERO);
|
||||
|
||||
rs->super.ac_usb_dma_size = 0x3;
|
||||
rs->super.ac_usb_dma_time = 0x20;
|
||||
}
|
||||
|
||||
static void
|
||||
r23bu_detach_private(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r23b_softc *rs = sc->sc_priv;
|
||||
|
||||
free(rs, M_RTWN_PRIV);
|
||||
}
|
||||
|
||||
void
|
||||
r23bu_attach(struct rtwn_usb_softc *uc)
|
||||
{
|
||||
struct rtwn_softc *sc = &uc->uc_sc;
|
||||
|
||||
/* USB part. */
|
||||
uc->uc_align_rx = r12au_align_rx;
|
||||
uc->tx_agg_desc_num = 0x6;
|
||||
|
||||
/* Common part. */
|
||||
sc->sc_flags = RTWN_FLAG_EXT_HDR;
|
||||
|
||||
sc->sc_set_chan = r92e_set_chan;
|
||||
sc->sc_fill_tx_desc = r12a_fill_tx_desc;
|
||||
sc->sc_fill_tx_desc_raw = r12a_fill_tx_desc_raw;
|
||||
sc->sc_fill_tx_desc_null = r12a_fill_tx_desc_null;
|
||||
sc->sc_dump_tx_desc = r12au_dump_tx_desc;
|
||||
sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags;
|
||||
sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags;
|
||||
sc->sc_get_rx_stats = r12a_get_rx_stats;
|
||||
sc->sc_get_rssi_cck = r23b_get_rssi_cck;
|
||||
sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm;
|
||||
sc->sc_classify_intr = r12au_classify_intr;
|
||||
sc->sc_handle_tx_report = r12a_ratectl_tx_complete;
|
||||
sc->sc_handle_tx_report2 = rtwn_nop_softc_uint8_int;
|
||||
sc->sc_handle_c2h_report = r92e_handle_c2h_report;
|
||||
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
|
||||
sc->sc_rf_read = r92e_rf_read;
|
||||
sc->sc_rf_write = r23b_rf_write;
|
||||
sc->sc_check_condition = r92c_check_condition;
|
||||
sc->sc_efuse_postread = rtwn_nop_softc;
|
||||
sc->sc_efuse_preread = r23b_efuse_preread;
|
||||
sc->sc_parse_rom = r23bu_parse_rom;
|
||||
sc->sc_set_led = r23b_set_led;
|
||||
sc->sc_power_on = r23bu_power_on;
|
||||
sc->sc_power_off = r23bu_power_off;
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
sc->sc_fw_reset = r23b_fw_reset;
|
||||
sc->sc_fw_download_enable = r23b_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92e_llt_init;
|
||||
sc->sc_set_page_size = r23b_set_page_size;
|
||||
sc->sc_lc_calib = r23b_lc_calib;
|
||||
sc->sc_iq_calib = r23b_iq_calib;
|
||||
sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32;
|
||||
sc->sc_adj_devcaps = rtwn_nop_softc;
|
||||
sc->sc_vap_preattach = rtwn_nop_softc_vap;
|
||||
sc->sc_postattach = rtwn_nop_softc;
|
||||
sc->sc_detach_private = r23bu_detach_private;
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
sc->sc_set_media_status = r12a_set_media_status;
|
||||
sc->sc_set_rsvd_page = r88e_set_rsvd_page;
|
||||
sc->sc_set_pwrmode = r12a_set_pwrmode;
|
||||
sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO */
|
||||
#else
|
||||
sc->sc_set_media_status = rtwn_nop_softc_int;
|
||||
#endif
|
||||
sc->sc_beacon_init = r12a_beacon_init;
|
||||
sc->sc_beacon_enable = r92c_beacon_enable;
|
||||
sc->sc_sta_beacon_enable = r12a_sta_beacon_enable;
|
||||
sc->sc_beacon_set_rate = r12a_beacon_set_rate;
|
||||
sc->sc_beacon_select = r21a_beacon_select;
|
||||
sc->sc_temp_measure = r23b_temp_measure;
|
||||
sc->sc_temp_read = r88e_temp_read;
|
||||
sc->sc_init_tx_agg = r21au_init_tx_agg;
|
||||
sc->sc_init_rx_agg = r23bu_init_rx_agg;
|
||||
sc->sc_init_ampdu = r23bu_init_ampdu;
|
||||
sc->sc_init_intr = r92cu_init_intr;
|
||||
sc->sc_init_edca = r92c_init_edca;
|
||||
sc->sc_init_bb = r23bu_init_bb;
|
||||
sc->sc_init_rf = r23b_init_rf;
|
||||
sc->sc_init_antsel = r23b_init_antsel;
|
||||
sc->sc_post_init = r23b_post_init;
|
||||
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
|
||||
sc->sc_set_tx_power = r92e_set_tx_power;
|
||||
|
||||
sc->mac_prog = &rtl8723b_mac[0];
|
||||
sc->mac_size = nitems(rtl8723b_mac);
|
||||
sc->bb_prog = &rtl8723b_bb[0];
|
||||
sc->bb_size = nitems(rtl8723b_bb);
|
||||
sc->agc_prog = &rtl8723b_agc[0];
|
||||
sc->agc_size = nitems(rtl8723b_agc);
|
||||
sc->rf_prog = &rtl8723b_rf[0];
|
||||
|
||||
sc->name = "RTL8723BU";
|
||||
sc->fwname = "rtwn-rtl8723bufw";
|
||||
sc->fwsig = 0x530;
|
||||
|
||||
sc->page_count = R23B_TX_PAGE_COUNT;
|
||||
sc->pktbuf_count = 0; /* Unused */
|
||||
sc->ackto = 0x40;
|
||||
|
||||
sc->npubqpages = R23B_PUBQ_NPAGES;
|
||||
sc->nhqpages = R23B_HPQ_NPAGES;
|
||||
sc->nlqpages = R23B_LPQ_NPAGES;
|
||||
sc->nnqpages = R23B_NPQ_NPAGES;
|
||||
|
||||
sc->page_size = R92C_TX_PAGE_SIZE;
|
||||
sc->txdesc_len = sizeof(struct r12a_tx_desc);
|
||||
sc->efuse_maxlen = R23B_EFUSE_MAX_LEN;
|
||||
sc->efuse_maplen = R23B_EFUSE_MAP_LEN;
|
||||
sc->rx_dma_size = R23B_RX_DMA_BUFFER_SIZE;
|
||||
|
||||
sc->macid_limit = R12A_MACID_MAX + 1;
|
||||
sc->macid_rpt2_max_num = 2;
|
||||
sc->cam_entry_limit = R12A_CAM_ENTRY_COUNT;
|
||||
sc->fwsize_limit = R12A_MAX_FW_SIZE;
|
||||
sc->temp_delta = R23B_CALIB_THRESHOLD;
|
||||
|
||||
sc->bcn_status_reg[0] = R92C_TDECTRL;
|
||||
sc->bcn_status_reg[1] = R21A_DWBCN1_CTRL;
|
||||
sc->rcr = 0;
|
||||
|
||||
sc->ntxchains = 1;
|
||||
sc->nrxchains = 1;
|
||||
|
||||
r23bu_attach_private(sc);
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usbdi.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/usb/rtwn_usb_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192e/r92e_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b_reg.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/usb/r23bu.h>
|
||||
|
||||
#include <dev/rtwn/rtl8812a/r12a_reg.h>
|
||||
|
||||
int
|
||||
r23bu_power_on(struct rtwn_softc *sc)
|
||||
{
|
||||
#define RTWN_CHK(res) do { \
|
||||
if (res != 0) \
|
||||
return (EIO); \
|
||||
} while(0)
|
||||
int ntries;
|
||||
|
||||
/* Clear suspend and power down bits.*/
|
||||
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
|
||||
R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_APDM_HPDN, 0, 1));
|
||||
|
||||
/* Disable GPIO9 as EXT WAKEUP. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0x01, 0));
|
||||
|
||||
/* Enable WL suspend. */
|
||||
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
|
||||
R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
|
||||
|
||||
/* Enable LDOA12 MACRO block for all interfaces. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R92C_LDOA15_CTRL, 0, R92C_LDOA15_CTRL_EN));
|
||||
|
||||
/* Disable BT_GPS_SEL pins. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0x10, 0));
|
||||
|
||||
/* 1 ms delay. */
|
||||
rtwn_delay(sc, 1000);
|
||||
|
||||
/* Release analog Ips to digital isolation. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL,
|
||||
R92C_SYS_ISO_CTRL_IP2MAC, 0));
|
||||
|
||||
/* Disable SW LPS and WL suspend. */
|
||||
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
|
||||
R92C_APS_FSMCO_APFM_RSM |
|
||||
R92C_APS_FSMCO_AFSM_HSUS |
|
||||
R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
|
||||
|
||||
/* Wait for power ready bit. */
|
||||
for (ntries = 0; ntries < 5000; ntries++) {
|
||||
if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
|
||||
break;
|
||||
rtwn_delay(sc, 10);
|
||||
}
|
||||
if (ntries == 5000) {
|
||||
device_printf(sc->sc_dev,
|
||||
"timeout waiting for chip power up\n");
|
||||
return (ETIMEDOUT);
|
||||
}
|
||||
|
||||
/* Release WLON reset. */
|
||||
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
|
||||
R92C_APS_FSMCO_RDY_MACON, 2));
|
||||
|
||||
/* Disable HWPDN. */
|
||||
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
|
||||
R92C_APS_FSMCO_APDM_HPDN, 0, 1));
|
||||
|
||||
/* Disable WL suspend. */
|
||||
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
|
||||
R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
|
||||
|
||||
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
|
||||
R92C_APS_FSMCO_APFM_ONMAC, 1));
|
||||
for (ntries = 0; ntries < 5000; ntries++) {
|
||||
if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
|
||||
R92C_APS_FSMCO_APFM_ONMAC))
|
||||
break;
|
||||
rtwn_delay(sc, 10);
|
||||
}
|
||||
if (ntries == 5000)
|
||||
return (ETIMEDOUT);
|
||||
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_MISC, 0, 0x40));
|
||||
|
||||
/* Enable falling edge triggering interrupt. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0, 0x02));
|
||||
|
||||
/* Enable GPIO9 interrupt mode. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, 0x063, 0, 0x02));
|
||||
|
||||
/* Enable GPIO9 input mode. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, 0x062, 0x02, 0));
|
||||
|
||||
/* Enable HSISR GPIO interrupt. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR, 0, 0x01));
|
||||
|
||||
/* Enable HSISR GPIO9 interrupt. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR + 2, 0, 0x02));
|
||||
|
||||
/* GPIO9 internal pull up. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R92C_MULTI_FUNC_CTRL, 0, 0x08));
|
||||
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_MULTI_FUNC_CTRL, 0, 0x4000, 1));
|
||||
|
||||
/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
|
||||
RTWN_CHK(rtwn_write_1(sc, R92C_CR, 0x00));
|
||||
RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
|
||||
R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
|
||||
R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
|
||||
R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
|
||||
((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
|
||||
R92C_CR_CALTMR_EN));
|
||||
|
||||
/* btcoex power on. */
|
||||
|
||||
RTWN_CHK(rtwn_write_1(sc, R88E_BB_PAD_CTRL + 3, 0x20));
|
||||
RTWN_CHK(rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
|
||||
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST));
|
||||
RTWN_CHK(rtwn_write_1(sc, R23B_GNT_BT + 1, 0x18));
|
||||
RTWN_CHK(rtwn_write_1(sc, 0x76e, 0x4));
|
||||
RTWN_CHK(rtwn_write_4(sc, R23B_ANT_SEL, R23B_ANT_SEL_S0));
|
||||
RTWN_CHK(rtwn_write_1(sc, 0xfe08, 0x1));
|
||||
|
||||
RTWN_CHK(rtwn_setbits_2(sc, R92C_PWR_DATA, 0,
|
||||
R23B_PWR_DATA_RFE_CTRL_EN));
|
||||
|
||||
RTWN_CHK(rtwn_setbits_4(sc, R92C_LEDCFG0, 0, R23B_LEDCFG0_DPDT_SEL_EN));
|
||||
|
||||
RTWN_CHK(rtwn_setbits_1(sc, R88E_BB_PAD_CTRL,
|
||||
R23B_BB_PAD_CTRL_DPDT_SEL_DATA, 0));
|
||||
|
||||
return (0);
|
||||
#undef RTWN_CHK
|
||||
}
|
||||
|
||||
void
|
||||
r23bu_power_off(struct rtwn_softc *sc)
|
||||
{
|
||||
int error, ntries;
|
||||
|
||||
/* Stop Tx report timer. */
|
||||
error = rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, R88E_TX_RPT2_ENA, 0);
|
||||
if (error == ENXIO) /* hardware gone */
|
||||
return;
|
||||
|
||||
/* Stop Rx. */
|
||||
rtwn_write_4(sc, R92C_CR, 0x0000);
|
||||
|
||||
/* Move card to Low Power state. */
|
||||
/* Block all Tx queues. */
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
|
||||
|
||||
for (ntries = 0; ntries < 10; ntries++) {
|
||||
/* Should be zero if no packet is transmitting. */
|
||||
if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
|
||||
break;
|
||||
|
||||
rtwn_delay(sc, 5000);
|
||||
}
|
||||
if (ntries == 10) {
|
||||
device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* CCK and OFDM are disabled, and clock are gated. */
|
||||
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0);
|
||||
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
/* Reset whole BB. */
|
||||
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0);
|
||||
|
||||
/* Reset MAC TRX. */
|
||||
rtwn_write_1(sc, R92C_CR, R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN);
|
||||
|
||||
/* check if removed later. (?) */
|
||||
rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1);
|
||||
|
||||
/* Respond TxOK to scheduler */
|
||||
rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK);
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
if ((sc->sc_flags & RTWN_FW_LOADED) &&
|
||||
(rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL))
|
||||
rtwn_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
|
||||
#endif
|
||||
|
||||
/* Reset MCU. */
|
||||
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN,
|
||||
0, 1);
|
||||
rtwn_write_1(sc, R92C_MCUFWDL, 0);
|
||||
|
||||
/* Move card to Disabled state. */
|
||||
/* Turn off RF. */
|
||||
rtwn_write_1(sc, R92C_RF_CTRL, 0);
|
||||
|
||||
/* Enable rising edge triggering interrupt. */
|
||||
rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0x02, 0);
|
||||
|
||||
/* Release WLON reset. */
|
||||
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
|
||||
R92C_APS_FSMCO_RDY_MACON, 2);
|
||||
|
||||
/* Turn off MAC by HW state machine */
|
||||
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_OFF, 1);
|
||||
for (ntries = 0; ntries < 10; ntries++) {
|
||||
/* Wait until it will be disabled. */
|
||||
if ((rtwn_read_2(sc, R92C_APS_FSMCO) &
|
||||
R92C_APS_FSMCO_APFM_OFF) == 0)
|
||||
break;
|
||||
|
||||
rtwn_delay(sc, 5000);
|
||||
}
|
||||
if (ntries == 10) {
|
||||
device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rtwn_setbits_1(sc, R92C_AFE_MISC, 0x40, 0);
|
||||
|
||||
/* Analog Ips to digital isolation. */
|
||||
rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, 0, R92C_SYS_ISO_CTRL_IP2MAC);
|
||||
|
||||
/* Disable LDOA12 MACRO block. */
|
||||
rtwn_setbits_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_EN, 0);
|
||||
|
||||
/* Enable WL suspend. */
|
||||
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE,
|
||||
R92C_APS_FSMCO_AFSM_HSUS, 1);
|
||||
|
||||
/* Enable GPIO9 as EXT WAKEUP. */
|
||||
rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0, 0x01);
|
||||
}
|
||||
|
||||
void
|
||||
r23bu_init_bb(struct rtwn_softc *sc)
|
||||
{
|
||||
/* Enable BB and RF. */
|
||||
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_BBRSTB |
|
||||
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_DIO_RF);
|
||||
|
||||
/* Select antenna S0. */
|
||||
rtwn_write_4(sc, R23B_ANT_SEL, R23B_ANT_SEL_S0);
|
||||
|
||||
return (r23b_init_bb_common(sc));
|
||||
}
|
||||
|
||||
void
|
||||
r23bu_init_rx_agg(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r23b_softc *rs = sc->sc_priv;
|
||||
uint32_t val;
|
||||
|
||||
rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
|
||||
|
||||
val = rtwn_read_4(sc, R92C_RXDMA_AGG_PG_TH);
|
||||
val = RW(val, R23B_RXDMA_AGG_PG_TH_SIZE, rs->super.ac_usb_dma_size);
|
||||
val = RW(val, R23B_RXDMA_AGG_PG_TH_TIME, rs->super.ac_usb_dma_time);
|
||||
val |= R23B_RXDMA_AGG_PG_TH_EN;
|
||||
rtwn_write_4(sc, R92C_RXDMA_AGG_PG_TH, val);
|
||||
}
|
||||
|
||||
void
|
||||
r23bu_init_ampdu(struct rtwn_softc *sc)
|
||||
{
|
||||
struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
|
||||
uint8_t val;
|
||||
|
||||
val = rtwn_read_1(sc, R12A_RXDMA_PRO);
|
||||
val = RW(val, R12A_BURST_SZ,
|
||||
usbd_get_speed(uc->uc_udev) == USB_SPEED_HIGH ?
|
||||
R12A_BURST_SZ_USB2 : R12A_BURST_SZ_USB1);
|
||||
val |= R12A_DMA_MODE | SM(R12A_BURST_CNT, 3);
|
||||
rtwn_write_1(sc, R12A_RXDMA_PRO, val);
|
||||
|
||||
/* Enable single packet AMPDU. */
|
||||
rtwn_setbits_1(sc, R12A_HT_SINGLE_AMPDU, 0,
|
||||
R12A_HT_SINGLE_AMPDU_PKT_ENA);
|
||||
|
||||
rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0c14);
|
||||
rtwn_write_1(sc, R12A_AMPDU_MAX_TIME, 0x5e);
|
||||
rtwn_write_4(sc, R12A_AMPDU_MAX_LENGTH, UINT32_MAX);
|
||||
|
||||
/*
|
||||
* The vendor driver says this is for
|
||||
* "VHT packet length 11K", but this chip
|
||||
* doesn't support VHT rates...
|
||||
*/
|
||||
rtwn_write_1(sc, R92C_RX_PKT_LIMIT, 0x18);
|
||||
|
||||
rtwn_write_1(sc, R92C_PIFS, 0);
|
||||
rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL, R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
|
||||
rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x03086666);
|
||||
|
||||
rtwn_write_1(sc, R92C_USTIME_TSF, 0x50);
|
||||
rtwn_write_1(sc, R92C_USTIME_EDCA, 0x50);
|
||||
|
||||
/* Do not reset MAC. */
|
||||
rtwn_setbits_1(sc, R92C_RSV_CTRL, 0, 0x60);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Ahmad Khalifa <vexeduxr@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/linker.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
|
||||
#include <dev/rtwn/if_rtwnreg.h>
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
#include <dev/rtwn/rtl8723b/r23b_rom_image.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/usb/r23bu.h>
|
||||
|
||||
void
|
||||
r23bu_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
|
||||
{
|
||||
struct r23b_rom *rom = (struct r23b_rom *)buf;
|
||||
|
||||
r23b_parse_rom(sc, buf);
|
||||
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->usb.macaddr);
|
||||
}
|
||||
@@ -115,6 +115,12 @@ struct r12a_tx_desc {
|
||||
#define R12A_TXDW5_RTS_PRIM_CHAN_M 0x0001e000
|
||||
#define R12A_TXDW5_RTS_PRIM_CHAN_S 13
|
||||
|
||||
/*
|
||||
* TODO: some chips (at least the 23bu)
|
||||
* let us pass arbitrary data in the first
|
||||
* 12 bits that is persisted through to the
|
||||
* TX report.
|
||||
*/
|
||||
uint32_t txdw6;
|
||||
#define R21A_TXDW6_MBSSID_M 0x0000f000
|
||||
#define R21A_TXDW6_MBSSID_S 12
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
void r92cu_attach(struct rtwn_usb_softc *);
|
||||
void r92eu_attach(struct rtwn_usb_softc *);
|
||||
void r88eu_attach(struct rtwn_usb_softc *);
|
||||
void r23bu_attach(struct rtwn_usb_softc *);
|
||||
void r12au_attach(struct rtwn_usb_softc *);
|
||||
void r21au_attach(struct rtwn_usb_softc *);
|
||||
|
||||
@@ -28,6 +29,7 @@ enum {
|
||||
RTWN_CHIP_RTL8192CU,
|
||||
RTWN_CHIP_RTL8192EU,
|
||||
RTWN_CHIP_RTL8188EU,
|
||||
RTWN_CHIP_RTL8723BU,
|
||||
RTWN_CHIP_RTL8812AU,
|
||||
RTWN_CHIP_RTL8821AU,
|
||||
RTWN_CHIP_MAX_USB
|
||||
@@ -132,6 +134,14 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = {
|
||||
RTWN_RTL8188EU_DEV(MERCUSYS, MW150US),
|
||||
#undef RTWN_RTL8188EU_DEV
|
||||
|
||||
/* RTL8723BU */
|
||||
#define RTWN_RTL8723BU_DEV(v, p, i) \
|
||||
{ USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p), \
|
||||
USB_IF_CSI(UICLASS_VENDOR, UISUBCLASS_VENDOR, \
|
||||
RTWN_USB_DEVINFO(RTWN_CHIP_RTL8723BU, i)) }
|
||||
RTWN_RTL8723BU_DEV(REALTEK, RTL8723BU, 2),
|
||||
#undef RTWN_RTL8723BU_DEV
|
||||
|
||||
/* RTL8812AU */
|
||||
#define RTWN_RTL8812AU_DEV(v,p) \
|
||||
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, \
|
||||
@@ -185,6 +195,7 @@ static const chip_usb_attach rtwn_chip_usb_attach[RTWN_CHIP_MAX_USB] = {
|
||||
[RTWN_CHIP_RTL8192CU] = r92cu_attach,
|
||||
[RTWN_CHIP_RTL8192EU] = r92eu_attach,
|
||||
[RTWN_CHIP_RTL8188EU] = r88eu_attach,
|
||||
[RTWN_CHIP_RTL8723BU] = r23bu_attach,
|
||||
[RTWN_CHIP_RTL8812AU] = r12au_attach,
|
||||
[RTWN_CHIP_RTL8821AU] = r21au_attach
|
||||
};
|
||||
|
||||
@@ -27,6 +27,11 @@ SRCS += r92e_chan.c r92e_fw.c r92e_init.c r92e_led.c r92e_rf.c \
|
||||
r92e_rom.c r92e_rx.c r92e.h r92e_priv.h r92e_reg.h \
|
||||
r92e_rom_image.h r92e_rom_defs.h
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8723b
|
||||
SRCS += r23b_calib.c r23b_fw.c r23b_init.c r23b_led.c r23b_rf.c \
|
||||
r23b_rom.c r23b_rx.c r23b.h r23b_priv.h r23b_reg.h \
|
||||
r23b_var.h r23b_rom_defs.h r23b_rom_image.h r23b_fw_cmd.h
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8812a
|
||||
SRCS += r12a_beacon.c r12a_calib.c r12a_caps.c r12a_chan.c r12a_fw.c \
|
||||
r12a_init.c r12a_led.c r12a_rf.c r12a_rom.c r12a_rx.c r12a_tx.c \
|
||||
|
||||
@@ -19,6 +19,9 @@ SRCS += r92cu_attach.c r92cu_init.c r92cu_led.c r92cu_rx.c r92cu_tx.c \
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8192e/usb
|
||||
SRCS += r92eu_attach.c r92eu_init.c r92eu.h r92eu_reg.h
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8723b/usb
|
||||
SRCS += r23bu_attach.c r23bu_init.c r23bu_rom.c r23bu.h
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8812a/usb
|
||||
SRCS += r12au_attach.c r12au_init.c r12au_rx.c r12au_tx.c \
|
||||
r12au.h r12au_reg.h r12au_tx_desc.h
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SUBDIR= rtwnrtl8188eu rtwnrtl8192cT rtwnrtl8192cU rtwnrtl8192eu rtwnrtl8812au \
|
||||
rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB rtwnrtl8188ee
|
||||
rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB rtwnrtl8188ee rtwnrtl8723bu
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
@@ -0,0 +1,4 @@
|
||||
KMOD= rtwn-rtl8723bufw
|
||||
IMG= rtwn-rtl8723bufw
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
Reference in new issue
Block a user