mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
rtwn: add support for the RTL8188FTV USB chipset
Add support for the RTL8188FTV chipset to rtwn(4)/rtwn_usb(4). Differential Revision: https://reviews.freebsd.org/D60875
This commit is contained in:
1 parent
4ab9e73994
commit
2c38dc04d6
39 files changed
+3336
-5
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 September 1, 2026
|
||||
.Dd October 22, 2026
|
||||
.Dt RTWN 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -89,6 +89,8 @@ driver supports USB and PCI devices with the following chipsets:
|
||||
.It
|
||||
Realtek 802.11n wireless 8188e (RTL8188E)
|
||||
.It
|
||||
Realtek 802.11n wireless 8188f (RTL8188F)
|
||||
.It
|
||||
Realtek 802.11n wireless 8192c (RTL8192C)
|
||||
.It
|
||||
Realtek 802.11n wireless 8192e (RTL8192E)
|
||||
@@ -119,6 +121,7 @@ which are loaded when an interface is brought up:
|
||||
.Bl -tag -width Ds -offset indent -compact
|
||||
.It Pa /boot/kernel/rtwn-rtl8188eefw.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8188eufw.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8188fufw.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8192cfwE_B.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8192cfwE.ko
|
||||
.It Pa /boot/kernel/rtwn-rtl8192cfwT.ko
|
||||
|
||||
@@ -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 September 11, 2026
|
||||
.Dd October 22, 2026
|
||||
.Dt RTWN_USB 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -101,6 +101,7 @@ Realtek RTL 8188/8192/8723/8812 and 8821 chipsets, including:
|
||||
.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 "Realtek RTL8188FTV" Ta RTL8188FTV Ta USB 2.0
|
||||
.It "Sitecom WLA-7100" Ta RTL8812AU Ta USB 3.0
|
||||
.It "TP-Link Archer T2U Nano" Ta RTL8821AU Ta USB 2.0
|
||||
.It "TP-Link Archer T2U Plus" Ta RTL8821AU Ta USB 2.0
|
||||
|
||||
@@ -41,6 +41,7 @@ of the following:
|
||||
.Bd -ragged -offset indent
|
||||
.Cd "device rtwn-rtl8188eefw"
|
||||
.Cd "device rtwn-rtl8188eufw"
|
||||
.Cd "device rtwn-rtl8188fufw"
|
||||
.Cd "device rtwn-rtl8192cfwE_B"
|
||||
.Cd "device rtwn-rtl8192cfwE"
|
||||
.Cd "device rtwn-rtl8192cfwT"
|
||||
@@ -56,6 +57,7 @@ module at boot time, place the following line in
|
||||
.Bd -literal -offset indent
|
||||
rtwn-rtl8188eefw_load="YES"
|
||||
rtwn-rtl8188eufw_load="YES"
|
||||
rtwn-rtl8188fufw_load="YES"
|
||||
rtwn-rtl8192cfwE_B_load="YES"
|
||||
rtwn-rtl8192cfwE_load="YES"
|
||||
rtwn-rtl8192cfwT_load="YES"
|
||||
@@ -70,7 +72,7 @@ to firmware sets for the Realtek RTL8188CE chip based PCIe adapters.
|
||||
rtwn-rtl8188ee module provides access to firmware sets for the
|
||||
Realtek RTL8188EE chip based PCIe adapters.
|
||||
Other modules provide access to firmware sets for the Realtek RTL8188CUS,
|
||||
RTL8188CE-VAU, RTL8188EUS, RTL8188RU, RTL8192CU, RTL8192EU, RTL8812AU and
|
||||
RTL8188CE-VAU, RTL8188EUS, RTL8188FTV, RTL8188RU, RTL8192CU, RTL8192EU, RTL8812AU and
|
||||
RTL8821AU chip based USB WiFi adapters.
|
||||
They may be
|
||||
statically linked into the kernel, or loaded as a modules.
|
||||
|
||||
@@ -2964,6 +2964,17 @@ dev/rtwn/rtl8188e/pci/r88ee_init.c optional rtwn_pci pci
|
||||
dev/rtwn/rtl8188e/pci/r88ee_rx.c optional rtwn_pci pci
|
||||
dev/rtwn/rtl8188e/usb/r88eu_attach.c optional rtwn_usb
|
||||
dev/rtwn/rtl8188e/usb/r88eu_init.c optional rtwn_usb
|
||||
|
||||
# RTL8188F
|
||||
dev/rtwn/rtl8188f/r88f_calib.c optional rtwn
|
||||
dev/rtwn/rtl8188f/r88f_chan.c optional rtwn
|
||||
dev/rtwn/rtl8188f/r88f_fw.c optional rtwn
|
||||
dev/rtwn/rtl8188f/r88f_init.c optional rtwn
|
||||
dev/rtwn/rtl8188f/r88f_rom.c optional rtwn
|
||||
dev/rtwn/rtl8188f/r88f_rx.c optional rtwn
|
||||
dev/rtwn/rtl8188f/usb/r88fu_attach.c optional rtwn_usb
|
||||
dev/rtwn/rtl8188f/usb/r88fu_init.c optional rtwn_usb
|
||||
|
||||
# RTL8192C
|
||||
dev/rtwn/rtl8192c/r92c_attach.c optional rtwn
|
||||
dev/rtwn/rtl8192c/r92c_beacon.c optional rtwn
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
begin 644 rtwn-rtl8188fufw.fw.uu
|
||||
M\8@0``0````((A<V_%$"`+PX```````````````````"AWT"R%4`````````
|
||||
M`````````K4G``````````````````+(IP``````````````````````````
|
||||
M`````````````LA6```````"PB$```````+(I@``````````````````````
|
||||
M``````````````````````````````````*(&`**V0*`A@*`B0*I60*C#`*V
|
||||
M8@*`E0*`F`*`FP*`G@*`H0*`I`*`IP*`J@*`K0*`L`*@/0*`M@*`N0*S&P*X
|
||||
MS0*X4@*W^0*Q8@*S?`*`S@*`T0*`U`*`UP````*`W0*`X`*`XP*`Y@*`Z0*`
|
||||
M[`*`[P*`\@*`]0*`^`*`^P*`_@*!`0*!!`*!!P*!"@*!#0*!$`*!$P*!%@*!
|
||||
M&0````````````````````````````````*_BP+)+0*6[@*8XP*!0`*D:P+-
|
||||
M\0*!20*!3`*!3P*!4@*!50*!6`*!6P*9^`*!80*!9`+&MP+/Z`+0'0``````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
M`````!7P_P\````5\`\`````!?#_#P````7P#P`````0\/\/````$/`/````
|
||||
M`/4/``````#P#P``````#0````````H(`P,`!`D'`P,`!`@&`P(`!`@%`P$`
|
||||
M!`T*!P4`"`P*!P0`"`L*!@4`"`L*!0,`"`L*`P(`"!02#`0`$!02"00`$"0B
|
||||
M'!(`("0B&`P`("0B%`8`("0B#P0`("0A"@0`(",A#`0`(",?"@0`("(?#P0`
|
||||
M("$?%@P`(#$O(!0`,#$O&!``,#$L&`P`,#$J%`P`,#$H%```,#$D%```,#$>
|
||||
M%```,`("`P0$"`D)#`X0$@()"PX-#Q`2``0`!``(`!``(P`M`%``D0##`2<!
|
||||
M,0%>`(P`R`#<`5X!:`&:`<P!Z@("!`@,$A@D,$A@;!0H,E!XH,CF`0$!`@$!
|
||||
M`@(#`P0$`@0&!P<("`@!`0$"`0$!`0$!`@(!`0$!`0("`@$!`0$!`0("`P,$
|
||||
M!0$"`P0%!@<(`P,#`@,#`P,#`@("`@("`@("`@(9!@0"`!@`````````````
|
||||
M````````````````````````````````````````````````````````````
|
||||
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
|
||||
M`_'N5!\2`SR0D\IT`?"0D\K@_\.4!%`4[Q*/4H^"CH/[email protected])/*X`3P@.*0
|
||||
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
|
||||
%#R(`:2H`
|
||||
`
|
||||
end
|
||||
@@ -1520,6 +1520,8 @@ rtwn_dma_init(struct rtwn_softc *sc)
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
rtwn_enable_mac_txrx(sc);
|
||||
|
||||
/* Set the number of pages for each queue. */
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
|
||||
"%s: pages per queue: high %d, normal %d, low %d, public %d\n",
|
||||
@@ -1903,7 +1905,7 @@ rtwn_init_beacon_reg(struct rtwn_softc *sc)
|
||||
rtwn_write_1(sc, R92C_BCN_CTRL(0), R92C_BCN_CTRL_DIS_TSF_UDT0);
|
||||
rtwn_write_1(sc, R92C_BCN_CTRL(1), R92C_BCN_CTRL_DIS_TSF_UDT0);
|
||||
rtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404);
|
||||
rtwn_write_1(sc, R92C_DRVERLYINT, 0x05);
|
||||
rtwn_init_beacon_timer(sc);
|
||||
rtwn_write_1(sc, R92C_BCNDMATIM, 0x02);
|
||||
rtwn_write_2(sc, R92C_BCNTCFG, 0x660f);
|
||||
}
|
||||
|
||||
@@ -308,6 +308,7 @@ struct rtwn_softc {
|
||||
void (*sc_fw_download_enable)(struct rtwn_softc *, int);
|
||||
#endif
|
||||
int (*sc_llt_init)(struct rtwn_softc *);
|
||||
void (*sc_enable_mac_txrx)(struct rtwn_softc *);
|
||||
int (*sc_set_page_size)(struct rtwn_softc *);
|
||||
void (*sc_lc_calib)(struct rtwn_softc *);
|
||||
void (*sc_iq_calib)(struct rtwn_softc *);
|
||||
@@ -362,6 +363,7 @@ struct rtwn_softc {
|
||||
uint8_t (*sc_temp_read)(struct rtwn_softc *);
|
||||
void (*sc_init_tx_agg)(struct rtwn_softc *);
|
||||
void (*sc_init_rx_agg)(struct rtwn_softc *);
|
||||
void (*sc_init_beacon_timer)(struct rtwn_softc *);
|
||||
void (*sc_init_intr)(struct rtwn_softc *);
|
||||
void (*sc_init_ampdu)(struct rtwn_softc *);
|
||||
void (*sc_init_edca)(struct rtwn_softc *);
|
||||
@@ -515,6 +517,8 @@ void rtwn_attach_vht_cap_info_mcs(struct rtwn_softc *);
|
||||
#endif
|
||||
#define rtwn_llt_init(_sc) \
|
||||
(((_sc)->sc_llt_init)((_sc)))
|
||||
#define rtwn_enable_mac_txrx(_sc) \
|
||||
(((_sc)->sc_enable_mac_txrx)((_sc)))
|
||||
#define rtwn_set_page_size(_sc) \
|
||||
(((_sc)->sc_set_page_size)((_sc)))
|
||||
#define rtwn_lc_calib(_sc) \
|
||||
@@ -587,6 +591,8 @@ void rtwn_attach_vht_cap_info_mcs(struct rtwn_softc *);
|
||||
(((_sc)->sc_init_tx_agg)((_sc)))
|
||||
#define rtwn_init_rx_agg(_sc) \
|
||||
(((_sc)->sc_init_rx_agg)((_sc)))
|
||||
#define rtwn_init_beacon_timer(_sc) \
|
||||
(((_sc)->sc_init_beacon_timer)((_sc)))
|
||||
#define rtwn_init_intr(_sc) \
|
||||
(((_sc)->sc_init_intr)((_sc)))
|
||||
#define rtwn_init_ampdu(_sc) \
|
||||
|
||||
@@ -162,6 +162,7 @@ r88ee_attach(struct rtwn_pci_softc *pc)
|
||||
sc->sc_fw_download_enable = r88e_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92c_llt_init;
|
||||
sc->sc_enable_mac_txrx = rtwn_nop_softc;
|
||||
sc->sc_set_page_size = r92c_set_page_size;
|
||||
sc->sc_lc_calib = r92c_lc_calib;
|
||||
sc->sc_iq_calib = r88e_iq_calib;
|
||||
@@ -185,6 +186,7 @@ r88ee_attach(struct rtwn_pci_softc *pc)
|
||||
sc->sc_temp_read = r88e_temp_read;
|
||||
sc->sc_init_tx_agg = rtwn_nop_softc;
|
||||
sc->sc_init_rx_agg = rtwn_nop_softc;
|
||||
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
|
||||
sc->sc_init_ampdu = r92ce_init_ampdu;
|
||||
sc->sc_init_intr = r88ee_init_intr;
|
||||
sc->sc_init_edca = r92ce_init_edca;
|
||||
|
||||
@@ -155,6 +155,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_fw_download_enable = r88e_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92c_llt_init;
|
||||
sc->sc_enable_mac_txrx = rtwn_nop_softc;
|
||||
sc->sc_set_page_size = r92c_set_page_size;
|
||||
sc->sc_lc_calib = r92c_lc_calib;
|
||||
sc->sc_iq_calib = r88e_iq_calib;
|
||||
@@ -178,6 +179,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_temp_read = r88e_temp_read;
|
||||
sc->sc_init_tx_agg = r92cu_init_tx_agg;
|
||||
sc->sc_init_rx_agg = r88eu_init_rx_agg;
|
||||
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
|
||||
sc->sc_init_ampdu = rtwn_nop_softc;
|
||||
sc->sc_init_intr = r88eu_init_intr;
|
||||
sc->sc_init_edca = r92c_init_edca;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef RTL8188F_H
|
||||
#define RTL8188F_H
|
||||
|
||||
#include <dev/rtwn/if_rtwn_ridx.h>
|
||||
|
||||
/*
|
||||
* Global Definitions.
|
||||
*/
|
||||
#define R88F_HQ_NPAGES 12
|
||||
#define R88F_LQ_NPAGES 2
|
||||
#define R88F_NQ_NPAGES 2
|
||||
#define R88F_TXPKTBUF_COUNT 177
|
||||
#define R88F_TX_PAGE_COUNT 247
|
||||
#define R88F_RX_DMA_BUFFER_SIZE 0x3f80
|
||||
#define R88F_MAX_FW_SIZE 21020
|
||||
#define R88F_RTWN_POWER_COUNT 28
|
||||
|
||||
/*
|
||||
* Function declarations.
|
||||
*/
|
||||
|
||||
/* r88f_rom.c */
|
||||
int r88f_efuse_preread(struct rtwn_softc *);
|
||||
void r88f_parse_rom(struct rtwn_softc *, uint8_t *);
|
||||
|
||||
/* r88f_rx.c */
|
||||
int8_t r88f_get_rssi_cck(struct rtwn_softc *, void *);
|
||||
int8_t r88f_get_rssi_ofdm(struct rtwn_softc *, void *);
|
||||
void r88f_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *,
|
||||
const void *, const void *);
|
||||
|
||||
/* r88f_init.c */
|
||||
int r88f_set_page_size(struct rtwn_softc *);
|
||||
void r88f_init_ampdu(struct rtwn_softc *);
|
||||
int r88f_llt_init(struct rtwn_softc *);
|
||||
void r88f_init_rf(struct rtwn_softc *);
|
||||
|
||||
/* r88f_calib.c */
|
||||
void r88f_lc_calib(struct rtwn_softc *);
|
||||
void r88f_iq_calib(struct rtwn_softc *);
|
||||
|
||||
/* r88f_chan.c */
|
||||
void r88f_set_chan(struct rtwn_softc *, struct ieee80211_channel *);
|
||||
void r88f_get_txpower(struct rtwn_softc *, int, struct ieee80211_channel *,
|
||||
uint8_t[RTWN_RIDX_COUNT]);
|
||||
|
||||
/* r88f_fw.c */
|
||||
void r88f_fw_reset(struct rtwn_softc *, int);
|
||||
void r88f_fw_download_enable(struct rtwn_softc *, int);
|
||||
|
||||
#endif /* RTL8188F_H */
|
||||
@@ -0,0 +1,728 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#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/rtl8723b/r23b_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_reg.h>
|
||||
|
||||
#define OFDM_LSTF_MASK 0x70000000
|
||||
|
||||
void
|
||||
r88f_lc_calib(struct rtwn_softc *sc)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t rf_amode, lstf;
|
||||
int i;
|
||||
|
||||
/* Check continuous TX and Packet TX */
|
||||
lstf = rtwn_bb_read(sc, R92C_OFDM1_LSTF);
|
||||
|
||||
if (lstf & OFDM_LSTF_MASK) {
|
||||
/* Disable all continuous TX */
|
||||
reg = lstf & ~OFDM_LSTF_MASK;
|
||||
rtwn_bb_write(sc, R92C_OFDM1_LSTF, reg);
|
||||
} else {
|
||||
/* Deal with Packet TX case */
|
||||
/* block all queues */
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, 0xff);
|
||||
}
|
||||
|
||||
/* Read original RF mode Path A */
|
||||
rf_amode = rtwn_rf_read(sc, 0, R92C_RF_CHNLBW);
|
||||
|
||||
/* Start LC calibration */
|
||||
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, rf_amode | 0x08000);
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
if ((rtwn_rf_read(sc, 0, R92C_RF_CHNLBW) & 0x08000) == 0)
|
||||
break;
|
||||
rtwn_delay(sc, 10);
|
||||
}
|
||||
|
||||
if (i == 100)
|
||||
device_printf(sc->sc_dev, "LC calibration timed out.\n");
|
||||
|
||||
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, rf_amode);
|
||||
|
||||
/* Restore original parameters */
|
||||
if (lstf & OFDM_LSTF_MASK)
|
||||
rtwn_bb_write(sc, R92C_OFDM1_LSTF, lstf);
|
||||
else /* Deal with Packet TX case */
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
|
||||
}
|
||||
|
||||
#define R88F_ADDA_REGS 16
|
||||
#define R88F_MAC_REGS 4
|
||||
#define R88F_BB_REGS 9
|
||||
|
||||
struct r88f_iqk_calib_regs {
|
||||
uint32_t adda_regs[R88F_ADDA_REGS];
|
||||
uint32_t mac_regs[R88F_MAC_REGS];
|
||||
uint32_t bb_regs[R88F_BB_REGS];
|
||||
uint32_t hssi_param1;
|
||||
};
|
||||
|
||||
struct r88f_iqk_result {
|
||||
uint32_t before;
|
||||
uint32_t after;
|
||||
};
|
||||
|
||||
static const uint32_t iqk_adda_regs[R88F_ADDA_REGS] = {
|
||||
R88F_FPGA0_XCD_SWITCH_CTRL, R88F_BLUETOOTH,
|
||||
R88F_RX_WAIT_CCA, R88F_TX_CCK_RFON,
|
||||
R88F_TX_CCK_BBON, R88F_TX_OFDM_RFON,
|
||||
R88F_TX_OFDM_BBON, R88F_TX_TO_RX,
|
||||
R88F_TX_TO_TX, R88F_RX_CCK,
|
||||
R88F_RX_OFDM, R88F_RX_WAIT_RIFS,
|
||||
R88F_RX_TO_RX, R88F_STANDBY,
|
||||
R88F_SLEEP, R88F_PMPD_ANAEN
|
||||
};
|
||||
static const uint32_t iqk_mac_regs[R88F_MAC_REGS] = {
|
||||
R92C_TXPAUSE, R92C_BCN_CTRL(0),
|
||||
R92C_BCN_CTRL(1), R92C_GPIO_MUXCFG
|
||||
};
|
||||
static const uint32_t iqk_bb_regs[R88F_BB_REGS] = {
|
||||
R92C_OFDM0_TRXPATHENA, R92C_OFDM0_TRMUXPAR,
|
||||
R88F_FPGA0_XCD_RF_SW_CTRL, R92C_CONFIG_ANT(0), R92C_CONFIG_ANT(1),
|
||||
R92C_FPGA0_RFIFACESW(0), R92C_FPGA0_RFIFACEOE(0),
|
||||
R92C_FPGA0_RFIFACEOE(1), R92C_FPGA0_RFMOD
|
||||
};
|
||||
|
||||
static void
|
||||
r88f_iqk_save_regs(struct rtwn_softc *sc, struct r88f_iqk_calib_regs *backup)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < R88F_ADDA_REGS; i++)
|
||||
backup->adda_regs[i] = rtwn_bb_read(sc, iqk_adda_regs[i]);
|
||||
|
||||
for (i = 0; i < R88F_MAC_REGS - 1; i++)
|
||||
backup->mac_regs[i] = rtwn_read_1(sc, iqk_mac_regs[i]);
|
||||
|
||||
backup->mac_regs[i] = rtwn_bb_read(sc, iqk_mac_regs[i]);
|
||||
|
||||
for (i = 0; i < R88F_BB_REGS; i++)
|
||||
backup->bb_regs[i] = rtwn_bb_read(sc, iqk_bb_regs[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
r88f_iqk_restore_regs(struct rtwn_softc *sc,
|
||||
const struct r88f_iqk_calib_regs *backup)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < R88F_ADDA_REGS; i++)
|
||||
rtwn_bb_write(sc, iqk_adda_regs[i], backup->adda_regs[i]);
|
||||
|
||||
for (i = 0; i < R88F_MAC_REGS - 1; i++)
|
||||
rtwn_write_1(sc, iqk_mac_regs[i], backup->mac_regs[i]);
|
||||
|
||||
rtwn_bb_write(sc, iqk_mac_regs[i], backup->mac_regs[i]);
|
||||
|
||||
for (i = 0; i < R88F_BB_REGS; i++)
|
||||
rtwn_bb_write(sc, iqk_bb_regs[i], backup->bb_regs[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
r88f_path_adda_on(struct rtwn_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
rtwn_bb_write(sc, iqk_adda_regs[0], 0x03c00014);
|
||||
|
||||
for (i = 1; i < R88F_ADDA_REGS; i++)
|
||||
rtwn_bb_write(sc, iqk_adda_regs[i], 0x03c00014);
|
||||
}
|
||||
|
||||
static void
|
||||
r88f_fill_iqk_matrix_a(struct rtwn_softc *sc,
|
||||
const struct r88f_iqk_result *tx_result,
|
||||
const struct r88f_iqk_result *rx_result,
|
||||
bool tx_only)
|
||||
{
|
||||
uint32_t oldval, x, tx0_a, result_reg;
|
||||
int y, tx0_c;
|
||||
uint32_t reg;
|
||||
|
||||
reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0));
|
||||
oldval = reg >> 22;
|
||||
|
||||
x = tx_result->before;
|
||||
if ((x & 0x00000200) != 0)
|
||||
x = x | 0xfffffc00;
|
||||
tx0_a = (x * oldval) >> 8;
|
||||
|
||||
reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0));
|
||||
reg &= ~0x3ff;
|
||||
reg |= tx0_a;
|
||||
rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(0), reg);
|
||||
|
||||
reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD);
|
||||
reg &= ~0x80000000;
|
||||
if ((x * oldval >> 7) & 0x1)
|
||||
reg |= 0x80000000;
|
||||
rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg);
|
||||
|
||||
y = tx_result->after;
|
||||
if ((y & 0x00000200) != 0)
|
||||
y |= 0xfffffc00;
|
||||
tx0_c = (y * oldval) >> 8;
|
||||
|
||||
rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(0), 0xf0000000,
|
||||
((tx0_c & 0x3c0) >> 6) << 28);
|
||||
|
||||
reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0));
|
||||
reg &= ~0x003f0000;
|
||||
reg |= ((tx0_a & 0x3f) << 16);
|
||||
rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(0), reg);
|
||||
|
||||
reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD);
|
||||
reg &= ~0x20000000;
|
||||
if ((y * oldval >> 7) & 0x1)
|
||||
reg |= 0x20000000;
|
||||
rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg);
|
||||
|
||||
if (tx_only) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: only TX\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
result_reg = rx_result->before;
|
||||
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0x3ff,
|
||||
result_reg & 0x3ff);
|
||||
|
||||
result_reg = rx_result->after & 0x3f;
|
||||
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0xfc00,
|
||||
(result_reg << 10) & 0xfc00);
|
||||
|
||||
result_reg = (rx_result->after >> 6) & 0xf;
|
||||
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000,
|
||||
result_reg << 28);
|
||||
}
|
||||
|
||||
static bool
|
||||
r88f_iq_calib_get_tx_result(struct rtwn_softc *sc,
|
||||
struct r88f_iqk_result *tx_result)
|
||||
{
|
||||
uint32_t reg_eac, reg_e94, reg_e9c;
|
||||
|
||||
reg_eac = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
|
||||
|
||||
reg_e94 = rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(0));
|
||||
tx_result->before = (reg_e94 >> 16) & 0x3ff;
|
||||
|
||||
reg_e9c = rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(0));
|
||||
tx_result->after = (reg_e9c >> 16) & 0x3ff;
|
||||
|
||||
return (!(reg_eac & 0x10000000) &&
|
||||
(tx_result->before != 0x142) &&
|
||||
(tx_result->after != 0x042));
|
||||
}
|
||||
|
||||
static bool
|
||||
r88f_iq_calib_get_rx_result(struct rtwn_softc *sc, uint32_t lok_result,
|
||||
struct r88f_iqk_result *rx_result)
|
||||
{
|
||||
|
||||
uint32_t reg_eac, reg_ea4;
|
||||
|
||||
/* Reload LOK value from TX calibration */
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXM_IDAC, lok_result);
|
||||
|
||||
reg_eac = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
|
||||
reg_ea4 = rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(0));
|
||||
rx_result->before = (reg_ea4 >> 16) & 0x3ff;
|
||||
rx_result->after = (reg_eac >> 16) & 0x3ff;
|
||||
|
||||
return (!(reg_eac & 0x08000000) &&
|
||||
(rx_result->before != 0x132) &&
|
||||
(rx_result->after != 0x036));
|
||||
}
|
||||
|
||||
static bool
|
||||
r88f_iqk_path_a_tx(struct rtwn_softc *sc, uint32_t *lok_result,
|
||||
struct r88f_iqk_result *tx_result)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Leave IQK mode */
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
/* Enable path A PA in TX IQK mode */
|
||||
rtwn_rf_setbits(sc, 0, R88E_RF_WE_LUT, 0, 0x80000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x20000);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0000f);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0x07ff7);
|
||||
|
||||
/* PA, PAD gain adjust */
|
||||
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x980);
|
||||
rtwn_rf_write(sc, 0, R88F_RF_PAD_TXG, 0x5102a);
|
||||
|
||||
/* Enter IQK mode */
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
reg |= 0x80800000;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
/* path-A IQK settings */
|
||||
rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x18008c1c);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x38008c1c);
|
||||
|
||||
rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x821403ff);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160000);
|
||||
|
||||
/* LO calibration setting */
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x00462911);
|
||||
|
||||
/* One shot, path A LOK & IQK */
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
|
||||
|
||||
rtwn_delay(sc, 25);
|
||||
|
||||
/* Leave IQK mode */
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x180);
|
||||
|
||||
*lok_result = rtwn_rf_read(sc, 0, R92C_RF_TXM_IDAC);
|
||||
|
||||
return (r88f_iq_calib_get_tx_result(sc, tx_result));
|
||||
}
|
||||
|
||||
static bool
|
||||
r88f_iqk_path_a_tx_rx(struct rtwn_softc *sc, uint32_t lok_result,
|
||||
struct r88f_iqk_result *rx_result)
|
||||
{
|
||||
uint32_t reg;
|
||||
struct r88f_iqk_result tx_verify;
|
||||
|
||||
/*
|
||||
* Leave IQK mode
|
||||
*/
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
/*
|
||||
* Enable path A PA in TX IQK mode
|
||||
*/
|
||||
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), 0x0000f);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf1173);
|
||||
|
||||
/* PA,PAD gain adjust */
|
||||
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x980);
|
||||
rtwn_rf_write(sc, 0, R88F_RF_PAD_TXG, 0x5102a);
|
||||
|
||||
/*
|
||||
* Enter IQK mode
|
||||
*/
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
reg |= 0x80800000;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
/*
|
||||
* TX IQK settings
|
||||
*/
|
||||
rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
|
||||
|
||||
/* path-A IQK setting */
|
||||
rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1c);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x30008c1c);
|
||||
|
||||
rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160fff);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160000);
|
||||
|
||||
/* LO calibration setting */
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x00462911);
|
||||
|
||||
/* One shot, path A LOK & IQK */
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
|
||||
|
||||
rtwn_delay(sc, 25);
|
||||
|
||||
/*
|
||||
* Leave IQK mode
|
||||
*/
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x180);
|
||||
|
||||
if (!r88f_iq_calib_get_tx_result(sc, &tx_verify)) {
|
||||
/* TX verification failed */
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: TX verification failed in RX path\n", __func__);
|
||||
return (false);
|
||||
}
|
||||
|
||||
rtwn_bb_write(sc, R92C_TX_IQK, 0x80007c00 |
|
||||
(tx_verify.before << 16) | tx_verify.after);
|
||||
|
||||
/*
|
||||
* Modify RX IQK mode table
|
||||
*/
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
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), 0x0000f);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7ff2);
|
||||
|
||||
/*
|
||||
* PA, PAD setting
|
||||
*/
|
||||
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x980);
|
||||
rtwn_rf_write(sc, 0, R88F_RF_PAD_TXG, 0x51000);
|
||||
/*
|
||||
* Enter IQK mode
|
||||
*/
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
reg |= 0x80800000;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
/*
|
||||
* RX IQK setting
|
||||
*/
|
||||
rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
|
||||
|
||||
/* path-A IQK setting */
|
||||
rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x30008c1c);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1c);
|
||||
|
||||
rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160000);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x281613ff);
|
||||
|
||||
/* LO calibration setting */
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911);
|
||||
|
||||
/* One shot, path A LOK & IQK */
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
|
||||
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
|
||||
|
||||
rtwn_delay(sc, 25);
|
||||
|
||||
/*
|
||||
* Leave IQK Mode
|
||||
*/
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0x000000ff;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x180);
|
||||
|
||||
return (r88f_iq_calib_get_rx_result(sc, lok_result, rx_result));
|
||||
|
||||
}
|
||||
|
||||
#define R88F_MAX_TOLERANCE 5
|
||||
|
||||
static bool
|
||||
r88f_iq_calib_compare_results(struct r88f_iqk_result *tx_result1,
|
||||
struct r88f_iqk_result *rx_result1,
|
||||
struct r88f_iqk_result *tx_result2,
|
||||
struct r88f_iqk_result *rx_result2,
|
||||
struct r88f_iqk_result **tx_candidate,
|
||||
struct r88f_iqk_result **rx_candidate)
|
||||
{
|
||||
uint32_t diff;
|
||||
bool tx_good = false;
|
||||
int32_t tmp1, tmp2;
|
||||
|
||||
diff = abs((int32_t)tx_result1->before - (int32_t)tx_result2->before);
|
||||
|
||||
if (diff <= R88F_MAX_TOLERANCE) {
|
||||
tmp1 = tx_result1->after & 0x00000200 ?
|
||||
(tx_result1->after | 0xfffffc00) : tx_result1->after;
|
||||
tmp2 = tx_result2->after & 0x00000200 ?
|
||||
(tx_result2->after | 0xfffffc00) : tx_result2->after;
|
||||
diff = abs(tmp1 - tmp2);
|
||||
|
||||
if (diff <= R88F_MAX_TOLERANCE) {
|
||||
*tx_candidate = tx_result1;
|
||||
tx_good = true;
|
||||
}
|
||||
}
|
||||
|
||||
diff = abs((int32_t)rx_result1->before - (int32_t)rx_result2->before);
|
||||
|
||||
if (diff > R88F_MAX_TOLERANCE) {
|
||||
if (tx_good && (rx_result1->before + rx_result1->after) == 0)
|
||||
*tx_candidate = tx_result2;
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
tmp1 = (rx_result1->after & 0x200) ?
|
||||
(0xfffffc00 | rx_result1->after) : rx_result1->after;
|
||||
tmp2 = (rx_result2->after & 0x200) ?
|
||||
(0xfffffc00 | rx_result2->after) : rx_result2->after;
|
||||
diff = abs(tmp1 - tmp2);
|
||||
|
||||
if (diff > R88F_MAX_TOLERANCE)
|
||||
return (false);
|
||||
|
||||
*rx_candidate = rx_result1;
|
||||
|
||||
return (tx_good);
|
||||
}
|
||||
|
||||
static void
|
||||
r88f_iq_calib_run(struct rtwn_softc *sc, struct r88f_iqk_calib_regs *regs,
|
||||
struct r88f_iqk_result *tx_result, struct r88f_iqk_result *rx_result, int t)
|
||||
{
|
||||
uint32_t rx_initial_gain, lok_result;
|
||||
uint32_t path_sel_rf, path_sel_bb;
|
||||
uint32_t reg;
|
||||
int retry = 2;
|
||||
int i;
|
||||
bool path_a_ok;
|
||||
|
||||
/*
|
||||
* Note: IQ calibration must be performed after loading
|
||||
* PHY_REG.txt , and radio_a, radio_b.txt
|
||||
*/
|
||||
|
||||
rx_initial_gain = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
|
||||
|
||||
if (t == 0) {
|
||||
r88f_iqk_save_regs(sc, regs);
|
||||
}
|
||||
|
||||
r88f_path_adda_on(sc);
|
||||
|
||||
if (t == 0) {
|
||||
/* Save ADDA parameters, turn Path A ADDA on */
|
||||
regs->hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
|
||||
}
|
||||
|
||||
/* save RF path */
|
||||
path_sel_bb = rtwn_bb_read(sc, R23B_ANT_SEL);
|
||||
path_sel_rf = rtwn_rf_read(sc, 0, R23B_RF_S0S1);
|
||||
|
||||
/* BB setting */
|
||||
rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
|
||||
rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
|
||||
rtwn_bb_write(sc, R88F_FPGA0_XCD_RF_SW_CTRL, 0x25204000);
|
||||
|
||||
rtwn_bb_setbits(sc, R92C_TX_PTCL_CTRL, 0, 0x00ff0000);
|
||||
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0xff;
|
||||
reg |= 0x80800000;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
|
||||
|
||||
for (i = 0; i < retry; i++) {
|
||||
path_a_ok = r88f_iqk_path_a_tx(sc, &lok_result, tx_result);
|
||||
if (path_a_ok) {
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < retry; i++) {
|
||||
path_a_ok = r88f_iqk_path_a_tx_rx(sc, lok_result, rx_result);
|
||||
if (path_a_ok) {
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!path_a_ok)
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: Path A IQK failed!\n", __func__);
|
||||
|
||||
/* Back to BB mode, load original value */
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
|
||||
reg &= 0xff;
|
||||
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
|
||||
|
||||
if (t == 0)
|
||||
return;
|
||||
|
||||
if (!(regs->hssi_param1 & R92C_HSSI_PARAM1_PI)) {
|
||||
/*
|
||||
* Switch back BB to SI mode after finishing
|
||||
* IQ Calibration
|
||||
*/
|
||||
rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), 0x01000000);
|
||||
rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), 0x01000000);
|
||||
}
|
||||
|
||||
/* Reload ADDA power saving, MAC and BB paramters */
|
||||
r88f_iqk_restore_regs(sc, regs);
|
||||
|
||||
/* Reload RF path */
|
||||
rtwn_bb_write(sc, R23B_ANT_SEL, path_sel_bb);
|
||||
rtwn_rf_write(sc, 0, R23B_RF_S0S1, path_sel_rf);
|
||||
|
||||
/* Restore RX initial gain */
|
||||
reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
|
||||
reg &= 0xffffff00;
|
||||
reg |= 0x50;
|
||||
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
|
||||
reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
|
||||
reg &= 0xffffff00;
|
||||
reg |= rx_initial_gain & 0xff;
|
||||
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
|
||||
|
||||
/* Load 0xe30 IQC default value */
|
||||
rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x01008c00);
|
||||
rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x01008c00);
|
||||
}
|
||||
|
||||
void
|
||||
r88f_iq_calib(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r88f_iqk_calib_regs regs;
|
||||
struct r88f_iqk_result tx_result[3] = { {0, 0} };
|
||||
struct r88f_iqk_result rx_result[3] = { {0, 0} };
|
||||
/* Final results */
|
||||
struct r88f_iqk_result *tx_candidate = NULL;
|
||||
struct r88f_iqk_result *rx_candidate = NULL;
|
||||
uint32_t path_sel_bb, path_sel_rf;
|
||||
int i;
|
||||
|
||||
/* Save RF path */
|
||||
path_sel_bb = rtwn_bb_read(sc, R23B_ANT_SEL);
|
||||
path_sel_rf = rtwn_rf_read(sc, 0, R23B_RF_S0S1);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
r88f_iq_calib_run(sc, ®s, &tx_result[i], &rx_result[i], i);
|
||||
|
||||
if (i == 1) {
|
||||
/* Compare 0 vs 1 */
|
||||
if (r88f_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: Run 0-1 passed\n", __func__);
|
||||
goto write;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 2) {
|
||||
/* Compare 0 vs 2 */
|
||||
if (r88f_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: Run 0-2 passed\n", __func__);
|
||||
goto write;
|
||||
}
|
||||
|
||||
/* Compare 1 vs 2 */
|
||||
if (r88f_iq_calib_compare_results(&tx_result[1],
|
||||
&rx_result[1], &tx_result[2],
|
||||
&rx_result[2], &tx_candidate,
|
||||
&rx_candidate)) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: Run 1-2 passed\n", __func__);
|
||||
} else {
|
||||
if (tx_candidate == NULL)
|
||||
tx_candidate = &tx_result[0];
|
||||
if (rx_candidate == NULL)
|
||||
rx_candidate = &rx_result[0];
|
||||
|
||||
/* check complete failure */
|
||||
if (tx_candidate->before == 0 &&
|
||||
tx_candidate->after == 0 &&
|
||||
rx_candidate->before == 0 &&
|
||||
rx_candidate->after == 0) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: IQK failed completely\n", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: using fallback candidate\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"IQK run %d: TX b=%#x a=%#x RX b=%#x a=%#x\n", i,
|
||||
tx_result[i].before, tx_result[i].after,
|
||||
rx_result[i].before, rx_result[i].after);
|
||||
}
|
||||
|
||||
write:
|
||||
|
||||
r88f_fill_iqk_matrix_a(sc, tx_candidate, rx_candidate ?
|
||||
rx_candidate : NULL,
|
||||
(rx_candidate == NULL || rx_candidate->before == 0));
|
||||
|
||||
if (tx_candidate == NULL || (tx_candidate->before == 0 &&
|
||||
tx_candidate->after == 0)) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: TX IQK failed completely\n", __func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
|
||||
"%s: IQK candidate - TX: before=%#x after=%#x RX: before=%#x after=%#x\n",
|
||||
__func__, tx_candidate->before, tx_candidate->after,
|
||||
rx_candidate ? rx_candidate->before : 0,
|
||||
rx_candidate ? rx_candidate->after : 0);
|
||||
|
||||
done:
|
||||
r88f_iqk_save_regs(sc, ®s);
|
||||
|
||||
/* Restore RF path */
|
||||
rtwn_bb_write(sc, R23B_ANT_SEL, path_sel_bb);
|
||||
rtwn_rf_write(sc, 0, R23B_RF_S0S1, path_sel_rf);
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#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_ridx.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e.h>
|
||||
#include <dev/rtwn/rtl8188e/r88e_priv.h>
|
||||
#include <dev/rtwn/rtl8188e/r88e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8812a/r12a_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_reg.h>
|
||||
|
||||
static int
|
||||
rtwn_chan2group(int chan)
|
||||
{
|
||||
int group;
|
||||
|
||||
if (chan <= 2)
|
||||
group = 0;
|
||||
else if (chan <= 5)
|
||||
group = 1;
|
||||
else if (chan <= 8)
|
||||
group = 2;
|
||||
else if (chan <= 11)
|
||||
group = 3;
|
||||
else
|
||||
group = 4;
|
||||
|
||||
return (group);
|
||||
}
|
||||
|
||||
void
|
||||
r88f_get_txpower(struct rtwn_softc *sc, int chain,
|
||||
struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT])
|
||||
{
|
||||
struct r92c_softc *rs = sc->sc_priv;
|
||||
const struct rtwn_r88e_txpwr *rt = rs->rs_txpwr;
|
||||
uint32_t reg;
|
||||
uint8_t cckpow, htpow, ofdmpow;
|
||||
int8_t diff;
|
||||
int ridx, chan, group;
|
||||
|
||||
/* Determine channel group. */
|
||||
chan = rtwn_chan2centieee(c); /* XXX center freq! */
|
||||
group = rtwn_chan2group(chan);
|
||||
|
||||
memset(power, 0, R88F_RTWN_POWER_COUNT * sizeof(power[0]));
|
||||
|
||||
/* Compute per-CCK rate Tx power. */
|
||||
cckpow = rt->cck_tx_pwr[group];
|
||||
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
|
||||
power[ridx] = cckpow;
|
||||
if (power[ridx] > R92C_MAX_TX_PWR)
|
||||
power[ridx] = R92C_MAX_TX_PWR;
|
||||
}
|
||||
|
||||
reg = rtwn_read_4(sc, R92C_TXAGC_A_CCK1_MCS32);
|
||||
reg &= 0xffff00ff;
|
||||
reg |= (cckpow << 8);
|
||||
rtwn_write_4(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
|
||||
|
||||
reg = rtwn_read_4(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
|
||||
reg &= 0xff;
|
||||
reg |= ((cckpow << 8) | (cckpow << 16) | (cckpow << 24));
|
||||
rtwn_write_4(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
|
||||
|
||||
htpow = rt->ht40_tx_pwr[group];
|
||||
|
||||
/* Compute per-OFDM rate Tx power. */
|
||||
diff = rt->ofdm_tx_pwr_diff;
|
||||
ofdmpow = htpow + diff;
|
||||
for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
|
||||
power[ridx] = ofdmpow;
|
||||
if (power[ridx] > R92C_MAX_TX_PWR)
|
||||
power[ridx] = R92C_MAX_TX_PWR;
|
||||
}
|
||||
|
||||
/* Compute per-MCS Tx power. */
|
||||
diff = rt->bw20_tx_pwr_diff;
|
||||
htpow += diff;
|
||||
for (ridx = RTWN_RIDX_HT_MCS(0); ridx < RTWN_RIDX_HT_MCS(8); ridx++) {
|
||||
power[ridx] = htpow;
|
||||
if (power[ridx] > R92C_MAX_TX_PWR)
|
||||
power[ridx] = R92C_MAX_TX_PWR;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
r88f_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
uint8_t power[RTWN_RIDX_COUNT];
|
||||
|
||||
memset(power, 0, sizeof(power));
|
||||
/* Compute per-rate Tx power values. */
|
||||
r88f_get_txpower(sc, 0, c, power);
|
||||
/* Write per-rate Tx power values to hardware. */
|
||||
r92c_write_txpower(sc, 0, power);
|
||||
}
|
||||
|
||||
static void
|
||||
r88f_spur_calibration(struct rtwn_softc *sc, struct ieee80211_channel *c,
|
||||
int chan)
|
||||
{
|
||||
static const uint32_t frequencies[14 + 1] = {
|
||||
[5] = 0xFCCD,
|
||||
[6] = 0xFC4D,
|
||||
[7] = 0xFFCD,
|
||||
[8] = 0xFF4D,
|
||||
[11] = 0xFDCD,
|
||||
[13] = 0xFCCD,
|
||||
[14] = 0xFF9A
|
||||
};
|
||||
|
||||
static const uint32_t reg_d40[14 + 1] = {
|
||||
[5] = 0x06000000,
|
||||
[6] = 0x00000600,
|
||||
[13] = 0x06000000
|
||||
};
|
||||
|
||||
static const uint32_t reg_d44[14 + 1] = {
|
||||
[11] = 0x04000000
|
||||
};
|
||||
|
||||
static const uint32_t reg_d4c[14 + 1] = {
|
||||
[7] = 0x06000000,
|
||||
[8] = 0x00000380,
|
||||
[14] = 0x00180000
|
||||
};
|
||||
|
||||
const uint8_t threshold = 0x16;
|
||||
bool do_notch, hw_ctrl, sw_ctrl, hw_ctrl_s1 = 0, sw_ctrl_s1 = 0;
|
||||
uint32_t reg, initial_gain, reg948;
|
||||
|
||||
rtwn_bb_setbits(sc, R88F_OFDM0_RX_D_SYNC_PATH, 0, 0x1f000000);
|
||||
|
||||
/* enable notch filter */
|
||||
rtwn_bb_setbits(sc, R88F_OFDM0_RX_D_SYNC_PATH, 0, 0x00000200);
|
||||
|
||||
if (chan <= 14 && frequencies[chan] > 0) {
|
||||
reg948 = rtwn_read_4(sc, R23B_ANT_SEL);
|
||||
hw_ctrl = reg948 & 0x00000040;
|
||||
sw_ctrl = !hw_ctrl;
|
||||
if (hw_ctrl) {
|
||||
reg = rtwn_read_4(sc, R88F_FPGA0_XB_RF_INT_OE);
|
||||
reg &= 0x00000038;
|
||||
hw_ctrl_s1 = reg == 0x00000008;
|
||||
} else if (sw_ctrl) {
|
||||
sw_ctrl_s1 = !(reg948 & 0x00000200);
|
||||
}
|
||||
|
||||
if (hw_ctrl_s1 || sw_ctrl_s1) {
|
||||
initial_gain = rtwn_read_4(sc, R92C_OFDM0_AGCCORE1(0));
|
||||
|
||||
/* Disable CCK block */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD,
|
||||
R92C_RFMOD_CCK_EN, 0);
|
||||
|
||||
rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0),
|
||||
R92C_OFDM0_AGCCORE1_GAIN_M, 0x30);
|
||||
|
||||
/* disable 3-wire */
|
||||
rtwn_bb_write(sc, R88F_FPGA0_ANALOG4, 0xccf000c0);
|
||||
|
||||
/* Setup PSD */
|
||||
rtwn_bb_write(sc, R88F_FPGA0_PSD_FUNC,
|
||||
frequencies[chan]);
|
||||
|
||||
/* Start PSD */
|
||||
rtwn_bb_write(sc, R88F_FPGA0_PSD_FUNC,
|
||||
0x400000 | frequencies[chan]);
|
||||
|
||||
rtwn_delay(sc, 30);
|
||||
|
||||
do_notch = rtwn_bb_read(sc, R88F_FPGA0_PSD_REPORT) >=
|
||||
threshold;
|
||||
|
||||
/* turn off PSD */
|
||||
rtwn_bb_write(sc, R88F_FPGA0_PSD_FUNC,
|
||||
frequencies[chan]);
|
||||
|
||||
/* enable 3-wire */
|
||||
rtwn_bb_write(sc, R88F_FPGA0_ANALOG4, 0xccc000c0);
|
||||
|
||||
/* Enable CCK block */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0,
|
||||
R92C_RFMOD_CCK_EN);
|
||||
|
||||
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), initial_gain);
|
||||
|
||||
if (do_notch) {
|
||||
rtwn_bb_write(sc, R88F_OFDM1_CSI_FIX_MASK1,
|
||||
reg_d40[chan]);
|
||||
rtwn_bb_write(sc, R88F_OFDM1_CSI_FIX_MASK2,
|
||||
reg_d44[chan]);
|
||||
|
||||
rtwn_bb_write(sc, 0xd48, 0x0);
|
||||
rtwn_bb_write(sc, 0xd4c, reg_d4c[chan]);
|
||||
|
||||
/* enable CSI mask */
|
||||
rtwn_bb_setbits(sc, R88F_OFDM1_CFO_TRACKING, 0,
|
||||
0x10000000);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* disable CSI mask function */
|
||||
rtwn_bb_setbits(sc, R88F_OFDM1_CFO_TRACKING, 0x10000000, 0);
|
||||
}
|
||||
|
||||
void
|
||||
r88f_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
struct r92c_softc *rs = sc->sc_priv;
|
||||
uint32_t reg;
|
||||
uint8_t chan, subchannel;
|
||||
bool sec_ch_above;
|
||||
|
||||
chan = rtwn_chan2centieee(c); /* XXX center freq! */
|
||||
|
||||
/* Set Tx power for this new channel. */
|
||||
r88f_set_txpower(sc, c);
|
||||
|
||||
/* Spur calibration */
|
||||
r88f_spur_calibration(sc, c, chan);
|
||||
|
||||
/* Set bandwidth mode */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ,
|
||||
IEEE80211_IS_CHAN_HT40(c));
|
||||
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ,
|
||||
IEEE80211_IS_CHAN_HT40(c));
|
||||
|
||||
/* RXADC CLK */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, 0x00000700);
|
||||
|
||||
/* TXDAC CLK */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0x00002000,
|
||||
0x00004000 | 0x00001000);
|
||||
|
||||
/* Small bandwidth */
|
||||
rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0xc0000000, 0);
|
||||
|
||||
/* ADC buffer clk */
|
||||
rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0x20000000,
|
||||
0x10000000);
|
||||
|
||||
/* ADC buffer clk */
|
||||
rtwn_bb_setbits(sc, R88F_OFDM0_XA_RX_AFE, 0x20000000, 0x10000000);
|
||||
|
||||
/* OFDM Rx DFIR */
|
||||
rtwn_bb_setbits(sc, R88F_RX_DFIR, 0x00080000, 0);
|
||||
|
||||
reg = rtwn_bb_read(sc, R88F_RX_DFIR);
|
||||
reg &= ~0x00f00000;
|
||||
reg |= 0x00200000;
|
||||
if (IEEE80211_IS_CHAN_HT20(c) || IEEE80211_IS_CHAN_VHT20(c) ||
|
||||
(!IEEE80211_IS_CHAN_HT(c) && !IEEE80211_IS_CHAN_VHT(c)))
|
||||
reg |= 0x00100000;
|
||||
else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c))
|
||||
reg |= 0x00400000;
|
||||
rtwn_bb_write(sc, R88F_RX_DFIR, reg);
|
||||
|
||||
if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c)) {
|
||||
if (IEEE80211_IS_CHAN_HT40U(c) ||
|
||||
IEEE80211_IS_CHAN_VHT40U(c)) {
|
||||
sec_ch_above = 1;
|
||||
chan += 2;
|
||||
} else {
|
||||
sec_ch_above = 0;
|
||||
chan -= 2;
|
||||
}
|
||||
|
||||
/* Set Control channel to upper or lower. */
|
||||
reg = rtwn_bb_read(sc, R92C_CCK0_SYSTEM);
|
||||
reg &= ~R92C_CCK0_SYSTEM_CCK_SIDEBAND;
|
||||
if (!sec_ch_above)
|
||||
reg |= R92C_CCK0_SYSTEM_CCK_SIDEBAND;
|
||||
rtwn_bb_write(sc, R92C_CCK0_SYSTEM, reg);
|
||||
|
||||
if (sec_ch_above)
|
||||
subchannel = 2;
|
||||
else
|
||||
subchannel = 1;
|
||||
rtwn_bb_setbits(sc, R12A_DATA_SEC, 0x0000000F, subchannel);
|
||||
|
||||
rtwn_bb_setbits(sc, R92C_RRSR, R92C_RRSR_RSC_LOWSUBCHNL |
|
||||
R92C_RRSR_RSC_UPSUBCHNL, 0);
|
||||
}
|
||||
|
||||
/* RF TRX_BW */
|
||||
|
||||
reg = chan;
|
||||
if (IEEE80211_IS_CHAN_HT20(c) || IEEE80211_IS_CHAN_VHT20(c) ||
|
||||
(!IEEE80211_IS_CHAN_HT(c) && !IEEE80211_IS_CHAN_VHT(c)))
|
||||
reg |= R88F_RF_CHNLBW_BW20;
|
||||
else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c))
|
||||
reg |= R88F_RF_CHNLBW_BW40;
|
||||
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, reg);
|
||||
|
||||
/* FILTER BW&RC Corner (ACPR) */
|
||||
if (IEEE80211_IS_CHAN_HT20(c) || IEEE80211_IS_CHAN_VHT20(c) ||
|
||||
(!IEEE80211_IS_CHAN_HT(c) && !IEEE80211_IS_CHAN_VHT(c)))
|
||||
reg = 0x00065;
|
||||
else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c))
|
||||
reg = 0x00025;
|
||||
rtwn_rf_write(sc, 0, R88F_RF_RXG_GAIN, reg);
|
||||
|
||||
if (IEEE80211_IS_CHAN_HT20(c) || IEEE80211_IS_CHAN_VHT20(c) ||
|
||||
(!IEEE80211_IS_CHAN_HT(c) && !IEEE80211_IS_CHAN_VHT(c)))
|
||||
reg = 0x0;
|
||||
else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c))
|
||||
reg = 0x01000;
|
||||
rtwn_rf_write(sc, 0, R92C_RF_RX_BB2, reg);
|
||||
|
||||
rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x1c6c);
|
||||
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA,
|
||||
R88F_RF_PKTBUF_DBG_CTRL);
|
||||
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
|
||||
(rs->rf_chnlbw[0] & ~0xfff) | chan | R88E_RF_CHNLBW_BW20);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#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/rtl8192e/r92e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f.h>
|
||||
|
||||
#define R88E_RSV_CTRL_MIO_EN 0x0100
|
||||
#define R88E_RSV_CTRL_MCU_RST 0x0800
|
||||
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
void
|
||||
r88f_fw_reset(struct rtwn_softc *sc, int reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case RTWN_FW_RESET_CHECKSUM:
|
||||
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_CHKSUM_RPT);
|
||||
/* FALLTHROUGH */
|
||||
case RTWN_FW_RESET_DOWNLOAD:
|
||||
case RTWN_FW_RESET_SHUTDOWN:
|
||||
/* Reset MCU IO wrapper. */
|
||||
rtwn_setbits_2(sc, R92C_RSV_CTRL, R88E_RSV_CTRL_MIO_EN, 0);
|
||||
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN, 0);
|
||||
|
||||
/* Enable MCU IO wrapper. */
|
||||
rtwn_setbits_2(sc, R92C_RSV_CTRL, 0, R88E_RSV_CTRL_MIO_EN);
|
||||
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_CPUEN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
r88f_fw_download_enable(struct rtwn_softc *sc, int enable)
|
||||
{
|
||||
if (enable) {
|
||||
/* Enable FW download. */
|
||||
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN);
|
||||
rtwn_setbits_4(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN, 0);
|
||||
/* Wait 100ms */
|
||||
rtwn_delay(sc, 100);
|
||||
} else {
|
||||
rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#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/rtl8192c/r92c.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_priv.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_var.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192e/r92e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8812a/r12a_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_reg.h>
|
||||
|
||||
int
|
||||
r88f_llt_init(struct rtwn_softc *sc)
|
||||
{
|
||||
int ntries;
|
||||
|
||||
rtwn_setbits_4(sc, R92E_AUTO_LLT, 0, R92E_AUTO_LLT_EN);
|
||||
for (ntries = 0; ntries < 1000; ntries++) {
|
||||
if (!(rtwn_read_4(sc, R92E_AUTO_LLT) & R92E_AUTO_LLT_EN))
|
||||
return (0);
|
||||
rtwn_delay(sc, 2);
|
||||
}
|
||||
return (ETIMEDOUT);
|
||||
}
|
||||
|
||||
int
|
||||
r88f_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
|
||||
r88f_init_ampdu(struct rtwn_softc *sc)
|
||||
{
|
||||
/* Setup AMPDU aggregation. */
|
||||
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, 0x70);
|
||||
rtwn_write_4(sc, R92C_AGGLEN_LMT, 0xffffffff);
|
||||
|
||||
/* For VHT packet length 11K */
|
||||
rtwn_write_1(sc, R92C_RX_PKT_LIMIT, 0x18);
|
||||
|
||||
rtwn_write_1(sc, R92C_PIFS, 0);
|
||||
rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL, 0x80);
|
||||
rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x03086666);
|
||||
rtwn_write_1(sc, R92C_USTIME_TSF, 0x28);
|
||||
rtwn_write_1(sc, R92C_USTIME_EDCA, 0x28);
|
||||
|
||||
/* To prevent bus resetting the mac. */
|
||||
rtwn_setbits_1(sc, R92C_RSV_CTRL, 0,
|
||||
R92C_RSV_CTRL_R_DIS_PRST_0 | R92C_RSV_CTRL_R_DIS_PRST_1);
|
||||
}
|
||||
|
||||
static int
|
||||
r88f_read_efuse_1(struct rtwn_softc *sc, uint16_t offset, uint8_t *data)
|
||||
{
|
||||
int i;
|
||||
uint8_t val8;
|
||||
uint32_t reg;
|
||||
|
||||
/* Write Address */
|
||||
rtwn_write_1(sc, R92C_EFUSE_CTRL + 1, offset & 0xff);
|
||||
val8 = rtwn_read_1(sc, R92C_EFUSE_CTRL + 2);
|
||||
val8 &= 0xfc;
|
||||
val8 |= (offset >> 8) & 0x03;
|
||||
rtwn_write_1(sc, R92C_EFUSE_CTRL + 2, val8);
|
||||
|
||||
val8 = rtwn_read_1(sc, R92C_EFUSE_CTRL + 3);
|
||||
rtwn_write_1(sc, R92C_EFUSE_CTRL + 3, val8 & 0x7f);
|
||||
|
||||
/* Poll for data read */
|
||||
reg = rtwn_bb_read(sc, R92C_EFUSE_CTRL);
|
||||
for (i = 0; i < 500; i++) {
|
||||
reg = rtwn_bb_read(sc, R92C_EFUSE_CTRL);
|
||||
if (reg & 0x80000000)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 500)
|
||||
return (-EIO);
|
||||
|
||||
rtwn_delay(sc, 50);
|
||||
reg = rtwn_bb_read(sc, R92C_EFUSE_CTRL);
|
||||
|
||||
*data = reg & 0xff;
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define PPG_BB_GAIN_2G_TXA_OFFSET_8188F 0xee
|
||||
#define PPG_BB_GAIN_2G_TX_OFFSET_MASK 0x0f
|
||||
#define OFDM_RF_PATH_RX_A 0x00000001
|
||||
#define OFDM_RF_PATH_TX_A 0x00000010
|
||||
#define OFDM_RF_PATH_TX_MASK 0xf0
|
||||
#define OFDM_RF_PATH_RX_MASK 0x0f
|
||||
|
||||
static void
|
||||
r88f_enable_rf(struct rtwn_softc *sc)
|
||||
{
|
||||
uint8_t pg_pwrtrim = 0xff, val8;
|
||||
int8_t bb_gain;
|
||||
|
||||
/* Somehow this is not found in the efuse we read earlier. */
|
||||
r88f_read_efuse_1(sc, PPG_BB_GAIN_2G_TXA_OFFSET_8188F, &pg_pwrtrim);
|
||||
|
||||
if (pg_pwrtrim != 0xff) {
|
||||
bb_gain = pg_pwrtrim & PPG_BB_GAIN_2G_TX_OFFSET_MASK;
|
||||
|
||||
if (bb_gain == PPG_BB_GAIN_2G_TX_OFFSET_MASK)
|
||||
bb_gain = 0;
|
||||
else if (bb_gain & 1)
|
||||
bb_gain = bb_gain >> 1;
|
||||
else
|
||||
bb_gain = -(bb_gain >> 1);
|
||||
|
||||
val8 = abs(bb_gain);
|
||||
if (bb_gain > 0)
|
||||
val8 |= 0x00000020;
|
||||
|
||||
rtwn_rf_setbits(sc, 0, R88F_RF_UNKNOWN_55,
|
||||
0xfc000, val8 << 14);
|
||||
}
|
||||
|
||||
rtwn_write_1(sc, R92C_RF_CTRL, R92C_RF_CTRL_EN |
|
||||
R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
|
||||
rtwn_bb_setbits(sc, R92C_OFDM0_TRXPATHENA, OFDM_RF_PATH_RX_MASK |
|
||||
OFDM_RF_PATH_TX_MASK, OFDM_RF_PATH_RX_A | OFDM_RF_PATH_TX_A);
|
||||
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
|
||||
}
|
||||
|
||||
void
|
||||
r88f_init_rf(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r92c_softc *rs = sc->sc_priv;
|
||||
uint32_t reg, type;
|
||||
int i = 0;
|
||||
|
||||
r88f_enable_rf(sc);
|
||||
|
||||
/* Save RF_ENV control type. */
|
||||
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0));
|
||||
type = reg & 0x10;
|
||||
|
||||
/* Set RF_ENV enable. */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0, 0x100000);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
/* Set RF_ENV output high. */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0, 0x10);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
/* Set address and data lengths of RF registers. */
|
||||
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(0),
|
||||
R92C_HSSI_PARAM2_ADDR_LENGTH, 0);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(0),
|
||||
R92C_HSSI_PARAM2_DATA_LENGTH, 0);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
/* Write RF initialization values for this chain. */
|
||||
i += r92c_init_rf_chain(sc, &sc->rf_prog[0], 0);
|
||||
|
||||
/* Restore RF_ENV control type. */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0x10, type);
|
||||
|
||||
/* Cache RF register CHNLBW. */
|
||||
rs->rf_chnlbw[i] = rtwn_rf_read(sc, 0, R92C_RF_CHNLBW);
|
||||
|
||||
/* Turn CCK and OFDM blocks on. */
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_CCK_EN);
|
||||
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_OFDM_EN);
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/* $OpenBSD: r92creg.h,v 1.30 2023/04/28 01:24:14 kevlo Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
|
||||
* Copyright (c) 2023 Kevin Lo <kevlo@FreeBSD.org>
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef R88F_PRIV_H
|
||||
#define R88F_PRIV_H
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f_rom_defs.h>
|
||||
|
||||
/*
|
||||
* MAC initialization values.
|
||||
*/
|
||||
static const struct rtwn_mac_prog rtl8188ftv_mac[] = {
|
||||
{ 0x024, 0xdf }, { 0x025, 0x07 }, { 0x02b, 0x1c }, { 0x283, 0x20 },
|
||||
{ 0x421, 0x0f }, { 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, 0x44 },
|
||||
{ 0x461, 0x44 }, { 0x4bc, 0xc0 }, { 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, 0x28 }, { 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, 0x28 },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Baseband initialization values.
|
||||
*/
|
||||
static const uint16_t rtl8188ftv_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, 0x948, 0x94c, 0x950, 0x954, 0x958, 0x95c, 0x96c, 0xa00,
|
||||
0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, 0xa20, 0xa24,
|
||||
0xa28, 0xa2c, 0xa70, 0xa74, 0xa78, 0xa7c, 0xa80, 0xa84, 0xa88,
|
||||
0xa8c, 0xa90, 0xa94, 0xa98, 0xa9c, 0xaa0, 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, 0xe60, 0xe64,
|
||||
0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
|
||||
0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xf14, 0xf4c, 0xf00
|
||||
};
|
||||
|
||||
static const uint32_t rtl8188ftv_bb_vals[] = {
|
||||
0x80045700, 0x00000001, 0x0000fc00, 0x0000000a, 0x10001331,
|
||||
0x020c3d10, 0x00200385, 0x00000000, 0x01000100, 0x00390204,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00030000, 0x00000000, 0x569a569a, 0x569a569a, 0x00000130,
|
||||
0x00000000, 0x00000000, 0x27272700, 0x00000000, 0x25004000,
|
||||
0x00000808, 0x004f0201, 0xb0000b1e, 0x00000007, 0x00000000,
|
||||
0xccc000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00706050,
|
||||
0x00000000, 0x00000023, 0x00000000, 0x81121111, 0x00000002,
|
||||
0x00000201, 0x99000000, 0x00000010, 0x20003000, 0x4a880000,
|
||||
0x4bc5d87a, 0x04eb9b79, 0x00000003, 0x00d047c8, 0x80ff800c,
|
||||
0x8c898300, 0x2e7f120f, 0x9500bb78, 0x1114d028, 0x00881117,
|
||||
0x89140f00, 0xd1d80000, 0x5a7da0bd, 0x0000223b, 0x00d30000,
|
||||
0x101fbf00, 0x00000007, 0x00000900, 0x225b0606, 0x218075b1,
|
||||
0x00120000, 0x040c0000, 0x12345678, 0xabcdef00, 0x001b1b89,
|
||||
0x05100000, 0x3f000000, 0x00000000, 0x00000000, 0x48071d40,
|
||||
0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x18800000, 0x40000100,
|
||||
0x08800000, 0x40000100, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x69e9cc4a, 0x31000040, 0x21688080, 0x00001714,
|
||||
0x1f78403f, 0x00010036, 0xec020107, 0x007f037f, 0x69553420,
|
||||
0x43bc0094, 0x00013169, 0x00250492, 0x00000000, 0x7112848b,
|
||||
0x47c07bff, 0x00000036, 0x2c7f000d, 0x020600db, 0x0000001f,
|
||||
0x00b91612, 0x390000e4, 0x11f60000, 0x40000100, 0x20200000,
|
||||
0x00091521, 0x00000000, 0x00121820, 0x00007f7f, 0x00000000,
|
||||
0x000300a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x28000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x64b22427, 0x00766932,
|
||||
0x00222222, 0x10000000, 0x37644302, 0x2f97d40c, 0x04030740,
|
||||
0x40020401, 0x0000907f, 0x20010201, 0xa0633333, 0x3333bc53,
|
||||
0x7a8f5b6f, 0xcb979975, 0x00000000, 0x80608000, 0x98000000,
|
||||
0x40127353, 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, 0x021400a0, 0x281600a0, 0x01c00010,
|
||||
0x01c00010, 0x02000010, 0x02000010, 0x02000010, 0x02000010,
|
||||
0x01c00010, 0x02000010, 0x01c00010, 0x01c00010, 0x01c00010,
|
||||
0x01c00010, 0x00000010, 0x00000010, 0x03c00010, 0x00000003,
|
||||
0x00000000, 0x00000300
|
||||
};
|
||||
|
||||
static const struct rtwn_bb_prog rtl8188ftv_bb[] = {
|
||||
{
|
||||
nitems(rtl8188ftv_bb_regs),
|
||||
rtl8188ftv_bb_regs,
|
||||
rtl8188ftv_bb_vals,
|
||||
{ 0 },
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
static const uint32_t rtl8188ftv_agc_vals[] = {
|
||||
0xfc000001, 0xfb010001, 0xfa020001, 0xf9030001, 0xf8040001,
|
||||
0xf7050001, 0xf6060001, 0xf5070001, 0xf4080001, 0xf3090001,
|
||||
0xf20a0001, 0xf10b0001, 0xf00c0001, 0xef0d0001, 0xee0e0001,
|
||||
0xed0f0001, 0xec100001, 0xeb110001, 0xea120001, 0xe9130001,
|
||||
0xe8140001, 0xe7150001, 0xe6160001, 0xe5170001, 0xe4180001,
|
||||
0xe3190001, 0xe21a0001, 0xe11b0001, 0xe01c0001, 0xc21d0001,
|
||||
0xc11e0001, 0xc01f0001, 0xa5200001, 0xa4210001, 0xa3220001,
|
||||
0xa2230001, 0xa1240001, 0xa0250001, 0x65260001, 0x64270001,
|
||||
0x63280001, 0x62290001, 0x612a0001, 0x442b0001, 0x432c0001,
|
||||
0x422d0001, 0x412e0001, 0x402f0001, 0x21300001, 0x20310001,
|
||||
0x05320001, 0x04330001, 0x03340001, 0x02350001, 0x01360001,
|
||||
0x00370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001,
|
||||
0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001
|
||||
};
|
||||
|
||||
static const struct rtwn_agc_prog rtl8188ftv_agc[] = {
|
||||
{
|
||||
nitems(rtl8188ftv_agc_vals),
|
||||
rtl8188ftv_agc_vals,
|
||||
{ 0 },
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* RF initialization values.
|
||||
*/
|
||||
static const uint8_t rtl8188ftv_rf_regs[] = {
|
||||
0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f, 0x3f, 0x42,
|
||||
0x57, 0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb5, 0xb6,
|
||||
0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbf, 0xc2, 0xc3, 0xc4, 0xc5,
|
||||
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xdf, 0xef, 0x51, 0x52, 0x53,
|
||||
0x56, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x18, 0x5a,
|
||||
0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
|
||||
0x34, 0x34, 0x00, 0x84, 0x86, 0x87, 0x8e, 0x8f, 0xef, 0x3b,
|
||||
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
|
||||
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xef, 0xef, 0x3b, 0x3b, 0xef,
|
||||
0xef, 0x30, 0x31, 0x32, 0xef, 0x00, 0x18, 0xfe, 0xfe, 0x1f,
|
||||
0xfe, 0xfe, 0x1e, 0x1f, 0x00
|
||||
};
|
||||
|
||||
static const uint32_t rtl8188ftv_rf_vals[] = {
|
||||
0x30000, 0x08400, 0x00407, 0x00012, 0x01c6c, 0x80009, 0x00880,
|
||||
0x1a060, 0x28000, 0x060c0, 0xd0000, 0xc0160, 0x01552, 0x00000,
|
||||
0xff9f0, 0x22218, 0x34c00, 0x4484b, 0x0112a, 0x0053e, 0x10408,
|
||||
0x10200, 0x80001, 0x40001, 0x00400, 0xc0000, 0x02400, 0x00009,
|
||||
0x40c91, 0x99999, 0x000a3, 0x8f820, 0x76c06, 0x00000, 0x80000,
|
||||
0x00180, 0x001a0, 0xe8231, 0xfac2c, 0x00141, 0x517f0, 0x00090,
|
||||
0x00190, 0x00290, 0x01064, 0x09064, 0x11064, 0x19064, 0x00c07,
|
||||
0x48000, 0x739d0, 0x0add2, 0x09dd0, 0x08cf3, 0x07cf0, 0x06ced,
|
||||
0x05cd2, 0x04ccf, 0x03ccc, 0x02cc9, 0x01c4c, 0x00c49, 0x30159,
|
||||
0x48000, 0x0002a, 0x00025, 0x65540, 0x88000, 0x020a0, 0xf0f00,
|
||||
0xe0b00, 0xd0900, 0xc0700, 0xb0600, 0xa0400, 0x90200, 0x80000,
|
||||
0x7bf00, 0x60b00, 0x5c900, 0x40700, 0x30600, 0x2d500, 0x10200,
|
||||
0x0e000, 0x000a0, 0x00010, 0x0c0a8, 0x10400, 0x00000, 0x80000,
|
||||
0x10000, 0x0000f, 0x07efe, 0x00000, 0x10159, 0x0fc07, 0x00000,
|
||||
0x00000, 0x80003, 0x00000, 0x00000, 0x00001, 0x80000, 0x33d95
|
||||
};
|
||||
|
||||
static const struct rtwn_rf_prog rtl8188ftv_rf[] = {
|
||||
{
|
||||
nitems(rtl8188ftv_rf_regs),
|
||||
rtl8188ftv_rf_regs,
|
||||
rtl8188ftv_rf_vals,
|
||||
{ 0 },
|
||||
NULL
|
||||
},
|
||||
{ 0, NULL, NULL, { 0 }, NULL }
|
||||
};
|
||||
|
||||
#endif /* R88F_PRIV_H */
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef R88F_REG_H
|
||||
#define R88F_REG_H
|
||||
|
||||
/*
|
||||
* Baseband registers.
|
||||
*/
|
||||
|
||||
/* FPGA0. */
|
||||
#define R88F_FPGA0_PSD_FUNC 0x808
|
||||
#define R88F_FPGA0_XB_RF_INT_OE 0x864
|
||||
#define R88F_FPGA0_XCD_RF_SW_CTRL 0x874
|
||||
#define R88F_FPGA0_ANALOG4 0x88c
|
||||
#define R88F_FPGA0_PSD_REPORT 0x8b4
|
||||
|
||||
/* Noise Histogram. */
|
||||
#define R88F_NHM_TH9_TH10_8723B 0x890
|
||||
#define R88F_NHM_TIMER_8723B 0x894
|
||||
#define R88F_NHM_TH3_TO_TH0_8723B 0x898
|
||||
#define R88F_NHM_TH7_TO_TH4_8723B 0x89c
|
||||
|
||||
/* RX/CCK. */
|
||||
#define R88F_RX_DFIR 0x954
|
||||
#define R88F_CCK_PD_THRESH 0xa0a
|
||||
|
||||
/* OFDM0. */
|
||||
#define R88F_OFDM0_FA_RSTC 0xc0c
|
||||
#define R88F_OFDM0_XA_RX_AFE 0xc10
|
||||
#define R88F_OFDM0_RX_D_SYNC_PATH 0xc40
|
||||
|
||||
/* OFDM1. */
|
||||
#define R88F_OFDM1_CFO_TRACKING 0xd2c
|
||||
#define R88F_OFDM1_CSI_FIX_MASK1 0xd40
|
||||
#define R88F_OFDM1_CSI_FIX_MASK2 0xd44
|
||||
|
||||
/* ADDA registers. */
|
||||
#define R88F_SLEEP 0xee0
|
||||
#define R88F_RX_OFDM 0xed0
|
||||
#define R88F_STANDBY 0xedc
|
||||
#define R88F_RX_WAIT_RIFS 0xed4
|
||||
#define R88F_RX_TO_RX 0xed8
|
||||
#define R88F_PMPD_ANAEN 0xeec
|
||||
#define R88F_RX_CCK 0xe8c
|
||||
#define R88F_TX_OFDM_RFON 0xe7c
|
||||
#define R88F_TX_TO_TX 0xe88
|
||||
#define R88F_FPGA0_XCD_SWITCH_CTRL 0x85c
|
||||
#define R88F_BLUETOOTH 0xe6c
|
||||
#define R88F_TX_OFDM_BBON 0xe80
|
||||
#define R88F_TX_CCK_RFON 0xe74
|
||||
#define R88F_TX_TO_RX 0xe84
|
||||
#define R88F_TX_CCK_BBON 0xe78
|
||||
#define R88F_RX_WAIT_CCA 0xe70
|
||||
|
||||
/*
|
||||
* RF (6052) registers.
|
||||
*/
|
||||
#define R88F_RF_GAIN_CCA 0xdf
|
||||
#define R88F_RF_UNKNOWN_55 0x55
|
||||
#define R88F_RF_PAD_TXG 0x56
|
||||
#define R88F_RF_RXG_GAIN 0x87
|
||||
|
||||
/* Bits for R92C_RF_CHNLBW. */
|
||||
#define R88F_RF_CHNLBW_BW20 0xc00
|
||||
#define R88F_RF_CHNLBW_BW40 0x400
|
||||
|
||||
/* Bits for R88F_RF_RXG_GAIN. */
|
||||
#define R88F_RF_TXA_PREPAD 0x65
|
||||
|
||||
/* Bits for R88F_RF_GAIN_CCA. */
|
||||
#define R88F_RF_PKTBUF_DBG_CTRL 0x140
|
||||
|
||||
/* Bits for R88F_CCK_PD_THRESH. */
|
||||
#define R88F_CCK_PD_TYPE1_LV1_TH 0x83
|
||||
|
||||
#endif /* R88F_REG_H */
|
||||
@@ -0,0 +1,121 @@
|
||||
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#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_priv.h>
|
||||
#include <dev/rtwn/rtl8188e/r88e_rom_image.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c_var.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_priv.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_rom_image.h>
|
||||
|
||||
#define R88F_XTAL1_MASK 0x007e0000 /* bits 22:17 */
|
||||
#define R88F_XTAL0_MASK 0x0001f800 /* bits 16:11 */
|
||||
|
||||
int
|
||||
r88f_efuse_preread(struct rtwn_softc *sc)
|
||||
{
|
||||
int error;
|
||||
uint32_t reg;
|
||||
|
||||
/* Switch to the WIFI bank. */
|
||||
reg = rtwn_read_4(sc, R92C_EFUSE_TEST);
|
||||
reg = RW(reg, R92C_EFUSE_TEST_SEL, 0);
|
||||
error = rtwn_write_4(sc, R92C_EFUSE_TEST, reg);
|
||||
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
|
||||
rtwn_delay(sc, 10);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
r88f_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
|
||||
{
|
||||
struct r92c_softc *rs = sc->sc_priv;
|
||||
struct rtwn_r88e_txpwr *rt = rs->rs_txpwr;
|
||||
struct r88f_rom *rom = (struct r88f_rom *)buf;
|
||||
int i;
|
||||
|
||||
rt->bw20_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, HIGH_PART));
|
||||
rt->ofdm_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, LOW_PART));
|
||||
|
||||
for (i = 0; i < nitems(rom->ht40_tx_pwr); i++) {
|
||||
rt->ht40_tx_pwr[i] = rom->ht40_tx_pwr[i];
|
||||
if (rt->ht40_tx_pwr[i] > 0x3f)
|
||||
rt->ht40_tx_pwr[i] = 0x27;
|
||||
}
|
||||
for (i = 0; i < nitems(rom->cck_tx_pwr); i++) {
|
||||
rt->cck_tx_pwr[i] = rom->cck_tx_pwr[i];
|
||||
if (rt->cck_tx_pwr[i] > 0x3f)
|
||||
rt->cck_tx_pwr[i] = 0x22;
|
||||
}
|
||||
|
||||
rs->crystalcap = rom->crystalcap & 0x3f;
|
||||
|
||||
rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
|
||||
|
||||
rs->board_type =
|
||||
MS(RTWN_GET_ROM_VAR(rom->rf_board_opt, R92C_BOARD_TYPE_DONGLE),
|
||||
R92C_ROM_RF1_BOARD_TYPE);
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: regulatory type %d\n",
|
||||
__func__, rs->regulatory);
|
||||
|
||||
sc->thermal_meter = rom->thermal_meter;
|
||||
|
||||
rtwn_r92c_set_rom_opts(sc, buf);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef R88F_ROM_DEFS_H
|
||||
#define R88F_ROM_DEFS_H
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e_rom_defs.h>
|
||||
|
||||
#endif /* R88F_ROM_DEFS_H */
|
||||
@@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef R88F_ROM_IMAGE_H
|
||||
#define R88F_ROM_IMAGE_H
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f_rom_defs.h>
|
||||
|
||||
/*
|
||||
* RTL8188FTV ROM image.
|
||||
*/
|
||||
struct r88f_rom {
|
||||
uint8_t reserved1[16];
|
||||
uint8_t cck_tx_pwr[R88E_GROUP_2G];
|
||||
uint8_t ht40_tx_pwr[R88E_GROUP_2G - 1];
|
||||
uint8_t tx_pwr_diff;
|
||||
uint8_t reserved2[156];
|
||||
uint8_t channel_plan;
|
||||
uint8_t crystalcap;
|
||||
uint8_t thermal_meter;
|
||||
uint8_t iqk_lck;
|
||||
uint8_t pa_type;
|
||||
uint8_t lna_type_2g;
|
||||
uint8_t reserved3[3];
|
||||
uint8_t rf_board_opt;
|
||||
uint8_t rf_feature_opt;
|
||||
uint8_t rf_bt_opt;
|
||||
uint8_t version;
|
||||
uint8_t customer_id;
|
||||
uint8_t reserved4[10];
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
uint8_t usb_opt;
|
||||
uint8_t reserved5[2];
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
uint8_t reserved6[291];
|
||||
} __packed;
|
||||
|
||||
_Static_assert(sizeof(struct r88f_rom) == R88E_EFUSE_MAP_LEN,
|
||||
"R88E_EFUSE_MAP_LEN must be equal to sizeof(struct r88f_rom)!");
|
||||
|
||||
#endif /* R88F_ROM_IMAGE_H */
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#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_ridx.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
|
||||
#include <dev/rtwn/rtl8192e/r92e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f.h>
|
||||
|
||||
int8_t
|
||||
r88f_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 7:
|
||||
if (vga_idx > 27)
|
||||
rssi = -100;
|
||||
else
|
||||
rssi += -46;
|
||||
break;
|
||||
case 5:
|
||||
rssi += -32;
|
||||
break;
|
||||
case 3:
|
||||
rssi += -20;
|
||||
break;
|
||||
case 1:
|
||||
rssi += -6;
|
||||
break;
|
||||
default:
|
||||
rssi = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return (rssi);
|
||||
}
|
||||
|
||||
int8_t
|
||||
r88f_get_rssi_ofdm(struct rtwn_softc *sc, void *physt)
|
||||
{
|
||||
struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt;
|
||||
int rssi;
|
||||
|
||||
/* Get average RSSI. */
|
||||
rssi = ((le32toh(phy->sig_qual) >> 1) & 0x7f) - 110;
|
||||
|
||||
return (rssi);
|
||||
}
|
||||
|
||||
void
|
||||
r88f_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
|
||||
const void *desc, const void *physt_ptr)
|
||||
{
|
||||
const struct r92c_rx_stat *stat = desc;
|
||||
uint32_t rxdw1, rxdw3;
|
||||
uint8_t rate;
|
||||
|
||||
rxdw1 = le32toh(stat->rxdw1);
|
||||
rxdw3 = le32toh(stat->rxdw3);
|
||||
rate = MS(rxdw3, R92E_RXDW3_RATE);
|
||||
|
||||
if (rxdw1 & R92C_RXDW1_AMPDU)
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU;
|
||||
else if (rxdw1 & R92C_RXDW1_AMPDU_MORE)
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE;
|
||||
if ((rxdw3 & R92C_RXDW3_SPLCP) && RTWN_RATE_IS_HT(rate))
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI;
|
||||
|
||||
if (rxdw3 & R92C_RXDW3_HT40)
|
||||
rxs->c_width = IEEE80211_RX_FW_40MHZ;
|
||||
else
|
||||
rxs->c_width = IEEE80211_RX_FW_20MHZ;
|
||||
|
||||
if (RTWN_RATE_IS_CCK(rate))
|
||||
rxs->c_phytype = IEEE80211_RX_FP_11B;
|
||||
else if (RTWN_RATE_IS_OFDM(rate))
|
||||
rxs->c_phytype = IEEE80211_RX_FP_11G;
|
||||
else
|
||||
rxs->c_phytype = IEEE80211_RX_FP_11NG;
|
||||
|
||||
/* Map HW rate index to 802.11 rate. */
|
||||
if (RTWN_RATE_IS_CCK(rate) || RTWN_RATE_IS_OFDM(rate)) {
|
||||
rxs->c_rate = ridx2rate[rate];
|
||||
if (RTWN_RATE_IS_CCK(rate))
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_CCK;
|
||||
else
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_OFDM;
|
||||
} else { /* MCS0~15. */
|
||||
rxs->c_rate =
|
||||
IEEE80211_RATE_MCS | (RTWN_RIDX_TO_MCS(rate));
|
||||
rxs->c_pktflags |= IEEE80211_RX_F_HT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef RTL8188FU_H
|
||||
#define RTL8188FU_H
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f.h>
|
||||
|
||||
/*
|
||||
* Function declarations
|
||||
*/
|
||||
|
||||
/* r88fu_init.c */
|
||||
int r88fu_power_on(struct rtwn_softc *);
|
||||
void r88fu_power_off(struct rtwn_softc *);
|
||||
void r88fu_init_rx_agg(struct rtwn_softc *);
|
||||
void r88fu_init_tx_agg(struct rtwn_softc *);
|
||||
void r88fu_init_bb(struct rtwn_softc *);
|
||||
void r88fu_post_init(struct rtwn_softc *);
|
||||
|
||||
#endif /* RTL8188FU_H */
|
||||
@@ -0,0 +1,254 @@
|
||||
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#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_priv.h>
|
||||
#include <dev/rtwn/rtl8188e/r88e_rom_image.h> /* for 'macaddr' field */
|
||||
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_var.h>
|
||||
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
|
||||
#include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192e/r92e.h>
|
||||
|
||||
#include <dev/rtwn/rtl8723b/r23b.h>
|
||||
|
||||
#include <dev/rtwn/rtl8812a/r12a.h>
|
||||
#include <dev/rtwn/rtl8812a/usb/r12au.h>
|
||||
#include <dev/rtwn/rtl8812a/usb/r12au_tx_desc.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_priv.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_reg.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_rom_defs.h>
|
||||
#include <dev/rtwn/rtl8188f/r88f_rom_image.h>
|
||||
#include <dev/rtwn/rtl8188f/usb/r88fu.h>
|
||||
|
||||
static struct rtwn_r88e_txpwr r88e_txpwr;
|
||||
|
||||
void r88fu_attach(struct rtwn_usb_softc *);
|
||||
|
||||
static void
|
||||
r88fu_set_macaddr(struct rtwn_softc *sc, uint8_t *buf)
|
||||
{
|
||||
struct r88f_rom *rom = (struct r88f_rom *)buf;
|
||||
|
||||
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
|
||||
}
|
||||
|
||||
static void
|
||||
r88f_postattach(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r92c_softc *rs = sc->sc_priv;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
|
||||
rs->rs_scan_start = ic->ic_scan_start;
|
||||
ic->ic_scan_start = r92c_scan_start;
|
||||
rs->rs_scan_end = ic->ic_scan_end;
|
||||
ic->ic_scan_end = r92c_scan_end;
|
||||
}
|
||||
|
||||
static void
|
||||
r88fu_attach_private(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r92c_softc *rs;
|
||||
|
||||
rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO);
|
||||
|
||||
rs->rs_txpwr = &r88e_txpwr;
|
||||
rs->rs_txagc = NULL;
|
||||
|
||||
rs->rs_set_bw20 = r88e_set_bw20;
|
||||
rs->rs_get_txpower = r88f_get_txpower;
|
||||
rs->rs_set_gain = r88e_set_gain;
|
||||
rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu;
|
||||
rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq;
|
||||
rs->rs_tx_setup_macid = r88e_tx_setup_macid;
|
||||
rs->rs_set_rom_opts = r88fu_set_macaddr;
|
||||
|
||||
rs->rf_read_delay[0] = 10;
|
||||
rs->rf_read_delay[1] = 100;
|
||||
rs->rf_read_delay[2] = 10;
|
||||
|
||||
sc->sc_priv = rs;
|
||||
}
|
||||
|
||||
static void
|
||||
r88fu_enable_mac_txrx(struct rtwn_softc *sc)
|
||||
{
|
||||
rtwn_setbits_2(sc, R92C_CR, 0, R92C_CR_MACTXEN | R92C_CR_MACRXEN);
|
||||
rtwn_bb_setbits(sc, R92C_TXDMA_OFFSET_CHK, 0, R92C_RQPN);
|
||||
}
|
||||
|
||||
static void
|
||||
r88fu_adj_devcaps(struct rtwn_softc *sc)
|
||||
{
|
||||
/* XXX TODO? */
|
||||
}
|
||||
|
||||
void
|
||||
r88fu_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 = 6;
|
||||
|
||||
/* Common part. */
|
||||
sc->sc_flags = RTWN_FLAG_EXT_HDR;
|
||||
|
||||
sc->sc_set_chan = r88f_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 = r88f_get_rx_stats;
|
||||
sc->sc_get_rssi_cck = r88f_get_rssi_cck;
|
||||
sc->sc_get_rssi_ofdm = r88f_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 = r92c_rf_read;
|
||||
sc->sc_rf_write = r88e_rf_write;
|
||||
sc->sc_check_condition = r92c_check_condition;
|
||||
sc->sc_efuse_postread = rtwn_nop_softc;
|
||||
sc->sc_efuse_preread = r88f_efuse_preread;
|
||||
sc->sc_parse_rom = r88f_parse_rom;
|
||||
sc->sc_set_led = r88e_set_led;
|
||||
sc->sc_power_on = r88fu_power_on;
|
||||
sc->sc_power_off = r88fu_power_off;
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
sc->sc_fw_reset = r88f_fw_reset;
|
||||
sc->sc_fw_download_enable = r88f_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r88f_llt_init;
|
||||
sc->sc_enable_mac_txrx = r88fu_enable_mac_txrx;
|
||||
sc->sc_set_page_size = r88f_set_page_size;
|
||||
sc->sc_lc_calib = r88f_lc_calib;
|
||||
sc->sc_iq_calib = r88f_iq_calib;
|
||||
sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32;
|
||||
sc->sc_adj_devcaps = r88fu_adj_devcaps;
|
||||
sc->sc_vap_preattach = rtwn_nop_softc_vap;
|
||||
sc->sc_postattach = r88f_postattach;
|
||||
sc->sc_detach_private = r92c_detach_private;
|
||||
sc->sc_set_media_status = r88e_set_media_status;
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
sc->sc_set_rsvd_page = r88e_set_rsvd_page;
|
||||
sc->sc_set_pwrmode = r88e_set_pwrmode;
|
||||
sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */
|
||||
#endif
|
||||
sc->sc_beacon_init = r92c_beacon_init;
|
||||
sc->sc_beacon_enable = r88e_beacon_enable;
|
||||
sc->sc_sta_beacon_enable = r88e_sta_beacon_enable;
|
||||
sc->sc_beacon_set_rate = rtwn_nop_void_int;
|
||||
sc->sc_beacon_select = rtwn_nop_softc_int;
|
||||
sc->sc_temp_measure = r88e_temp_measure;
|
||||
sc->sc_temp_read = r88e_temp_read;
|
||||
sc->sc_init_tx_agg = r88fu_init_tx_agg;
|
||||
sc->sc_init_rx_agg = r88fu_init_rx_agg;
|
||||
sc->sc_init_beacon_timer = rtwn_nop_softc;
|
||||
sc->sc_init_ampdu = r88f_init_ampdu;
|
||||
sc->sc_init_intr = r88eu_init_intr;
|
||||
sc->sc_init_edca = r92c_init_edca;
|
||||
sc->sc_init_bb = r88fu_init_bb;
|
||||
sc->sc_init_rf = r88f_init_rf;
|
||||
sc->sc_init_antsel = r23b_init_antsel;
|
||||
sc->sc_post_init = r88fu_post_init;
|
||||
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
|
||||
sc->sc_set_tx_power = r92c_set_tx_power;
|
||||
|
||||
sc->mac_prog = &rtl8188ftv_mac[0];
|
||||
sc->mac_size = nitems(rtl8188ftv_mac);
|
||||
sc->bb_prog = &rtl8188ftv_bb[0];
|
||||
sc->bb_size = nitems(rtl8188ftv_bb);
|
||||
sc->agc_prog = &rtl8188ftv_agc[0];
|
||||
sc->agc_size = nitems(rtl8188ftv_agc);
|
||||
sc->rf_prog = &rtl8188ftv_rf[0];
|
||||
|
||||
sc->name = "RTL8188FTV";
|
||||
sc->fwname = "rtwn-rtl8188fufw";
|
||||
sc->fwsig = 0x88f;
|
||||
|
||||
sc->ackto = 0x40;
|
||||
sc->npubqpages = R88EU_PUBQ_NPAGES;
|
||||
sc->nhqpages = R88F_HQ_NPAGES;
|
||||
sc->nlqpages = R88F_LQ_NPAGES;
|
||||
sc->nnqpages = R88F_NQ_NPAGES;
|
||||
sc->page_size = R92C_TX_PAGE_SIZE;
|
||||
|
||||
sc->page_count = R88F_TX_PAGE_COUNT;
|
||||
sc->pktbuf_count = R88F_TXPKTBUF_COUNT;
|
||||
|
||||
sc->txdesc_len = sizeof(struct r12au_tx_desc);
|
||||
sc->efuse_maxlen = R88E_EFUSE_MAX_LEN;
|
||||
sc->efuse_maplen = R88E_EFUSE_MAP_LEN;
|
||||
sc->rx_dma_size = R88F_RX_DMA_BUFFER_SIZE;
|
||||
|
||||
sc->macid_limit = R88E_MACID_MAX + 1;
|
||||
sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT;
|
||||
sc->fwsize_limit = R88F_MAX_FW_SIZE;
|
||||
sc->temp_delta = R88E_CALIB_THRESHOLD;
|
||||
|
||||
sc->bcn_status_reg[0] = R92C_TDECTRL;
|
||||
sc->bcn_status_reg[1] = R92C_TDECTRL;
|
||||
sc->rcr = 0;
|
||||
|
||||
sc->ntxchains = 1;
|
||||
sc->nrxchains = 1;
|
||||
|
||||
r88fu_attach_private(sc);
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
|
||||
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
|
||||
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#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/usb/rtwn_usb_var.h>
|
||||
#include <dev/rtwn/if_rtwn_debug.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188e/r88e.h>
|
||||
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
|
||||
#include <dev/rtwn/rtl8188e/usb/r88eu_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8192c/r92c.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_var.h>
|
||||
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
|
||||
#include <dev/rtwn/rtl8192e/r92e_reg.h>
|
||||
|
||||
#include <dev/rtwn/rtl8188f/r88f_reg.h>
|
||||
#include <dev/rtwn/rtl8188f/usb/r88fu.h>
|
||||
|
||||
void
|
||||
r88fu_init_tx_agg(struct rtwn_softc *sc)
|
||||
{
|
||||
uint8_t agg_ctrl, rxdma_mode, usb_tx_agg_desc_num = 6;
|
||||
uint32_t agg_rx;
|
||||
|
||||
/* TX aggregation */
|
||||
rtwn_setbits_4(sc, R92C_TDECTRL, 0xf << 4, usb_tx_agg_desc_num << 4);
|
||||
rtwn_write_1(sc, R92E_DWBCN1_CTRL, usb_tx_agg_desc_num << 1);
|
||||
|
||||
/* RX aggegation */
|
||||
agg_ctrl = rtwn_read_1(sc, R92C_TRXDMA_CTRL);
|
||||
agg_ctrl &= ~0x00000004;
|
||||
|
||||
agg_rx = rtwn_read_1(sc, R92C_RXDMA_AGG_PG_TH);
|
||||
agg_rx &= ~0x80000000;
|
||||
agg_rx &= ~0xff0f; /* reset agg size and timeout */
|
||||
|
||||
rxdma_mode = rtwn_read_1(sc, R92E_RXDMA_PRO);
|
||||
rxdma_mode &= ~0x00000002;
|
||||
|
||||
rtwn_write_1(sc, R92C_TRXDMA_CTRL, agg_ctrl);
|
||||
rtwn_write_4(sc, R92C_RXDMA_AGG_PG_TH, agg_rx);
|
||||
rtwn_write_1(sc, R92E_RXDMA_PRO, rxdma_mode);
|
||||
}
|
||||
|
||||
int
|
||||
r88fu_power_on(struct rtwn_softc *sc)
|
||||
{
|
||||
#define RTWN_CHK(res) do { \
|
||||
if (res != 0) \
|
||||
return (EIO); \
|
||||
} while (0)
|
||||
int ntries;
|
||||
|
||||
/* Enable WL suspend. */
|
||||
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO,
|
||||
R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0));
|
||||
|
||||
/* Turn off USB APHY LDO under suspend mode. */
|
||||
RTWN_CHK(rtwn_setbits_1(sc, 0xc4, 0x10, 0));
|
||||
|
||||
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_APFM_RSM, 0));
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Disable HWPDN. */
|
||||
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_APDM_HPDN, 0));
|
||||
|
||||
/* Disable WL suspend. */
|
||||
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_HSUS, 0));
|
||||
|
||||
/* Auto enable WLAN. */
|
||||
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_ONMAC));
|
||||
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);
|
||||
|
||||
/* Reduce RF noise. */
|
||||
rtwn_write_1(sc, R92C_AFE_LDO_CTRL, 0x35);
|
||||
|
||||
/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
|
||||
RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0));
|
||||
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 |
|
||||
R92C_CR_ENSEC | R92C_CR_CALTMR_EN));
|
||||
|
||||
return (0);
|
||||
#undef RTWN_CHK
|
||||
}
|
||||
|
||||
#define R88F_RXPKT_NUM_RW_RELEASE_ENABLE 0x00040000
|
||||
#define R88F_RXPKT_NUM_RXDMA_IDLE 0x00020000
|
||||
|
||||
static int
|
||||
r88fu_flush_fifo(struct rtwn_softc *sc)
|
||||
{
|
||||
uint32_t reg;
|
||||
int retry, retval;
|
||||
|
||||
rtwn_write_1(sc, R92C_TXPAUSE, 0xff);
|
||||
|
||||
rtwn_bb_setbits(sc, R92C_RXPKT_NUM, 0, R88F_RXPKT_NUM_RW_RELEASE_ENABLE);
|
||||
|
||||
retry = 100;
|
||||
|
||||
/* setting retval to (EBUSY = 16) */
|
||||
retval = -16;
|
||||
|
||||
do {
|
||||
reg = rtwn_bb_read(sc, R92C_RXPKT_NUM);
|
||||
if (reg & R88F_RXPKT_NUM_RXDMA_IDLE) {
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
} while (retry--);
|
||||
|
||||
rtwn_write_2(sc, R92C_RQPN_NPQ, 0);
|
||||
rtwn_bb_write(sc, R92C_RQPN, 0x80000000);
|
||||
rtwn_delay(sc, 2);
|
||||
|
||||
if (!retry)
|
||||
device_printf(sc->sc_dev, "%s: Failed to flush FIFO\n", __func__);
|
||||
|
||||
return (retval);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
r88fu_power_off(struct rtwn_softc *sc)
|
||||
{
|
||||
uint8_t reg;
|
||||
int error, ntries;
|
||||
|
||||
r88fu_flush_fifo(sc);
|
||||
|
||||
/* Disable any kind of TX reports. */
|
||||
error = rtwn_setbits_1(sc, R88E_TX_RPT_CTRL,
|
||||
R88E_TX_RPT1_ENA | R88E_TX_RPT2_ENA, 0);
|
||||
if (error == ENXIO) /* hardware gone */
|
||||
return;
|
||||
|
||||
/* Stop Rx. */
|
||||
rtwn_write_1(sc, R92C_CR, 0);
|
||||
|
||||
/* 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 MAC TRX */
|
||||
rtwn_write_1(sc, R92C_CR,
|
||||
R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
|
||||
R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN |
|
||||
R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_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, 0x20);
|
||||
|
||||
/* If firmware in ram code, do reset. */
|
||||
#ifndef RTWN_WITHOUT_UCODE
|
||||
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY)
|
||||
r88f_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
|
||||
#endif
|
||||
|
||||
/* Reset MCU ready status. */
|
||||
rtwn_write_1(sc, R92C_MCUFWDL, 0);
|
||||
|
||||
/* Disable 32k. */
|
||||
rtwn_setbits_1(sc, R88E_32K_CTRL, 0x01, 0);
|
||||
|
||||
/* Move card to Disabled state. */
|
||||
/* Turn off RF. */
|
||||
rtwn_write_1(sc, R92C_RF_CTRL, 0);
|
||||
|
||||
/* LDO Sleep mode. */
|
||||
rtwn_setbits_1(sc, R92C_LPLDO_CTRL, 0, R92C_LPLDO_CTRL_SLEEP);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* schmit trigger */
|
||||
rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80);
|
||||
|
||||
/* Enable WL suspend. */
|
||||
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
|
||||
R92C_APS_FSMCO_AFSM_PCIE, R92C_APS_FSMCO_AFSM_HSUS, 1);
|
||||
|
||||
/* Enable bandgap mbias in suspend. */
|
||||
rtwn_write_1(sc, R92C_APS_FSMCO + 3, 0);
|
||||
|
||||
/* Clear SIC_EN register. */
|
||||
rtwn_setbits_1(sc, R92C_GPIO_MUXCFG + 1, 0x10, 0);
|
||||
|
||||
/* Set USB suspend enable local register */
|
||||
rtwn_setbits_1(sc, R92C_USB_SUSPEND, 0, 0x10);
|
||||
|
||||
/* Reset MCU IO Wrapper. */
|
||||
reg = rtwn_read_1(sc, R92C_RSV_CTRL + 1);
|
||||
rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg & ~0x08);
|
||||
rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg | 0x08);
|
||||
|
||||
/* marked as 'For Power Consumption' code. */
|
||||
rtwn_write_1(sc, R92C_GPIO_OUT, rtwn_read_1(sc, R92C_GPIO_IN));
|
||||
rtwn_write_1(sc, R92C_GPIO_IOSEL, 0xff);
|
||||
|
||||
rtwn_write_1(sc, R92C_GPIO_IO_SEL,
|
||||
rtwn_read_1(sc, R92C_GPIO_IO_SEL) << 4);
|
||||
rtwn_setbits_1(sc, R92C_GPIO_MOD, 0, 0x0f);
|
||||
|
||||
/* Set LNA, TRSW, EX_PA Pin to output mode. */
|
||||
rtwn_write_4(sc, R88E_BB_PAD_CTRL, 0x00080808);
|
||||
}
|
||||
|
||||
void
|
||||
r88fu_init_rx_agg(struct rtwn_softc *sc)
|
||||
{
|
||||
rtwn_setbits_1(sc, R92E_RXDMA_PRO, 0x3c, 0x1c);
|
||||
rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
|
||||
/* set 5 is the dmasize */
|
||||
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 5);
|
||||
/* set 32 is the dmatiming */
|
||||
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 32);
|
||||
rtwn_setbits_1(sc, R92E_RXDMA_PRO, 0, R92E_RXDMA_PRO_DMA_MODE);
|
||||
}
|
||||
|
||||
#define R88F_XTAL1_M 0x007E0000U
|
||||
#define R88F_XTAL1_S 17
|
||||
#define R88F_XTAL0_M 0x0001F800U
|
||||
#define R88F_XTAL0_S 11
|
||||
|
||||
static void
|
||||
r88fu_set_crystal_cap(struct rtwn_softc *sc)
|
||||
{
|
||||
struct r92c_softc *rs = sc->sc_priv;
|
||||
uint32_t reg;
|
||||
uint8_t cap;
|
||||
|
||||
cap = rs->crystalcap & 0x3f;
|
||||
|
||||
reg = rtwn_bb_read(sc, R92C_AFE_XTAL_CTRL);
|
||||
|
||||
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_USB,
|
||||
"%s: Adjusting crystal cap from 0x%x (actually 0x%x 0x%x) to 0x%x\n",
|
||||
__func__,
|
||||
rs->crystalcap,
|
||||
MS(reg, R88F_XTAL1),
|
||||
MS(reg, R88F_XTAL0),
|
||||
cap);
|
||||
|
||||
reg &= ~(R88F_XTAL1_M | R88F_XTAL0_M);
|
||||
reg |= SM(R88F_XTAL1, cap) | SM(R88F_XTAL0, cap);
|
||||
rtwn_bb_write(sc, R92C_AFE_XTAL_CTRL, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
r88f_init_bb_common(struct rtwn_softc *sc)
|
||||
{
|
||||
r92c_init_bb_common(sc);
|
||||
|
||||
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422);
|
||||
rtwn_delay(sc, 1);
|
||||
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
|
||||
rtwn_delay(sc, 1);
|
||||
|
||||
r88fu_set_crystal_cap(sc);
|
||||
}
|
||||
|
||||
void
|
||||
r88fu_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);
|
||||
|
||||
/*
|
||||
* Per vendor driver, run power sequence before init of RF
|
||||
*/
|
||||
rtwn_write_1(sc, R92C_RF_CTRL, R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
|
||||
|
||||
rtwn_write_1(sc, R92C_SYS_FUNC_EN,
|
||||
R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
|
||||
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
|
||||
|
||||
rtwn_delay(sc, 10);
|
||||
|
||||
rtwn_rf_write(sc, 0, R92C_RF_IQADJ_G(0), 0x780);
|
||||
|
||||
r88f_init_bb_common(sc);
|
||||
|
||||
/* CCK PD */
|
||||
rtwn_write_1(sc, R88F_CCK_PD_THRESH, R88F_CCK_PD_TYPE1_LV1_TH);
|
||||
}
|
||||
|
||||
static void
|
||||
r88fu_init_stats(struct rtwn_softc *sc)
|
||||
{
|
||||
uint32_t clr;
|
||||
|
||||
rtwn_write_2(sc, R88F_NHM_TIMER_8723B + 2, 0xc350);
|
||||
rtwn_write_2(sc, R88F_NHM_TH9_TH10_8723B + 2, 0xffff);
|
||||
rtwn_write_4(sc, R88F_NHM_TH3_TO_TH0_8723B, 0xffffff50);
|
||||
rtwn_write_4(sc, R88F_NHM_TH7_TO_TH4_8723B, 0xffffffff);
|
||||
|
||||
rtwn_setbits_4(sc, R92C_FPGA0_IQK, 0, 0xff);
|
||||
|
||||
clr = 0x00000100 | 0x00000200 | 0x00000400;
|
||||
rtwn_setbits_4(sc, R88F_NHM_TH9_TH10_8723B, clr, 0x00000100);
|
||||
|
||||
rtwn_setbits_4(sc, R88F_OFDM0_FA_RSTC, 0, 0x00000080);
|
||||
}
|
||||
|
||||
void
|
||||
r88fu_post_init(struct rtwn_softc *sc)
|
||||
{
|
||||
uint8_t reg8;
|
||||
|
||||
/*
|
||||
* This should enable thermal meter
|
||||
*/
|
||||
rtwn_rf_setbits(sc, 0, R88E_RF_T_METER, 0, 0x30000);
|
||||
|
||||
rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT2_ENA);
|
||||
/* Set MAX RPT MACID */
|
||||
rtwn_write_1(sc, R88E_TX_RPT_CTRL + 1, R88E_TX_RPT2_ENA);
|
||||
/* TX report Timer. Unit: 32us */
|
||||
rtwn_write_2(sc, R88E_TX_RPT_TIME, 0xcdf0);
|
||||
/* tmp ps ? */
|
||||
reg8 = rtwn_read_1(sc, 0xa3);
|
||||
reg8 &= 0xf8;
|
||||
rtwn_write_1(sc, 0xa3, reg8);
|
||||
|
||||
/* Perform LO and IQ calibrations. */
|
||||
r88f_iq_calib(sc);
|
||||
/* Perform LC calibration. */
|
||||
r88f_lc_calib(sc);
|
||||
|
||||
rtwn_write_1(sc, R92C_USB_HRPWM, 0);
|
||||
|
||||
if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
|
||||
/* No support (yet?) for f/w rate adaptation. */
|
||||
sc->sc_ratectl = RTWN_RATECTL_NET80211;
|
||||
} else
|
||||
sc->sc_ratectl = sc->sc_ratectl_sysctl;
|
||||
|
||||
r88fu_init_stats(sc);
|
||||
}
|
||||
|
||||
@@ -192,6 +192,7 @@ r92ce_attach(struct rtwn_pci_softc *pc)
|
||||
sc->sc_fw_download_enable = r92c_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92c_llt_init;
|
||||
sc->sc_enable_mac_txrx = rtwn_nop_softc;
|
||||
sc->sc_set_page_size = r92c_set_page_size;
|
||||
sc->sc_lc_calib = r92c_lc_calib;
|
||||
sc->sc_iq_calib = r92ce_iq_calib;
|
||||
@@ -215,6 +216,7 @@ r92ce_attach(struct rtwn_pci_softc *pc)
|
||||
sc->sc_temp_read = r92c_temp_read;
|
||||
sc->sc_init_tx_agg = rtwn_nop_softc;
|
||||
sc->sc_init_rx_agg = rtwn_nop_softc;
|
||||
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
|
||||
sc->sc_init_ampdu = r92ce_init_ampdu;
|
||||
sc->sc_init_intr = r92ce_init_intr;
|
||||
sc->sc_init_edca = r92ce_init_edca;
|
||||
|
||||
@@ -45,6 +45,7 @@ void r92c_read_chipid_vendor(struct rtwn_softc *, uint32_t);
|
||||
|
||||
/* r92c_beacon.c */
|
||||
void r92c_beacon_init(struct rtwn_softc *, void *, int);
|
||||
void r92c_init_beacon_timer(struct rtwn_softc *);
|
||||
void r92c_beacon_enable(struct rtwn_softc *, int, int);
|
||||
void r92c_sta_beacon_enable(struct rtwn_softc *, int, bool);
|
||||
|
||||
|
||||
@@ -48,6 +48,12 @@
|
||||
#include <dev/rtwn/rtl8192c/r92c_reg.h>
|
||||
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
|
||||
|
||||
void
|
||||
r92c_init_beacon_timer(struct rtwn_softc *sc)
|
||||
{
|
||||
rtwn_write_1(sc, R92C_DRVERLYINT, 0x05);
|
||||
}
|
||||
|
||||
void
|
||||
r92c_beacon_init(struct rtwn_softc *sc, void *buf, int id)
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#define R92C_LDOHCI12_CTRL 0x022
|
||||
#define R92C_LPLDO_CTRL 0x023
|
||||
#define R92C_AFE_XTAL_CTRL 0x024
|
||||
#define R92C_AFE_LDO_CTRL 0x027
|
||||
#define R92C_AFE_PLL_CTRL 0x028
|
||||
#define R92C_APE_PLL_CTRL_EXT 0x02c
|
||||
#define R92C_MAC_PHY_CTRL R92C_APE_PLL_CTRL_EXT
|
||||
@@ -338,6 +339,10 @@
|
||||
#define R92C_AFE_PLL_CTRL_WDOGB 0x0010
|
||||
#define R92C_AFE_PLL_CTRL_LPFEN 0x0020
|
||||
|
||||
/* Bits for R92C_EFUSE_TEST. */
|
||||
#define R92C_EFUSE_TEST_SEL_M 0x00000300
|
||||
#define R92C_EFUSE_TEST_SEL_S 8
|
||||
|
||||
/* Bits for R92C_EFUSE_CTRL. */
|
||||
#define R92C_EFUSE_CTRL_DATA_M 0x000000ff
|
||||
#define R92C_EFUSE_CTRL_DATA_S 0
|
||||
|
||||
@@ -184,6 +184,7 @@ r92cu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_fw_download_enable = r92c_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92c_llt_init;
|
||||
sc->sc_enable_mac_txrx = rtwn_nop_softc;
|
||||
sc->sc_set_page_size = r92c_set_page_size;
|
||||
sc->sc_lc_calib = r92c_lc_calib;
|
||||
sc->sc_iq_calib = r92c_iq_calib;
|
||||
@@ -207,6 +208,7 @@ r92cu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_temp_read = r92c_temp_read;
|
||||
sc->sc_init_tx_agg = r92cu_init_tx_agg;
|
||||
sc->sc_init_rx_agg = r92cu_init_rx_agg;
|
||||
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
|
||||
sc->sc_init_ampdu = r92c_init_ampdu;
|
||||
sc->sc_init_intr = r92cu_init_intr;
|
||||
sc->sc_init_edca = r92c_init_edca;
|
||||
|
||||
@@ -37,9 +37,20 @@
|
||||
#define R92E_LDOV12_CTRL 0x014
|
||||
#define R92E_AFE_XTAL_CTRL 0x02c
|
||||
#define R92E_APE_PLL_CTRL_EXT 0x078
|
||||
#define R92E_AUTO_LLT 0x224
|
||||
#define R92E_DWBCN1_CTRL 0x228
|
||||
#define R92E_RXDMA_PRO 0x290
|
||||
#define R92E_RXDW3_RATE_M 0x0000007f
|
||||
#define R92E_RXDW3_RATE_S 0
|
||||
|
||||
/* Bits for R92E_AFE_XTAL_CTRL. */
|
||||
#define R92E_AFE_XTAL_CTRL_ADDR_M 0x00fff000
|
||||
#define R92E_AFE_XTAL_CTRL_ADDR_S 12
|
||||
|
||||
/* Bits for R92E_AUTO_LLT. */
|
||||
#define R92E_AUTO_LLT_EN 0x00010000
|
||||
|
||||
/* Bits for R92E_RXDMA_PRO. */
|
||||
#define R92E_RXDMA_PRO_DMA_MODE 0x02
|
||||
|
||||
#endif /* R92E_REG_H */
|
||||
@@ -133,6 +133,7 @@ r92eu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_fw_download_enable = r12a_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92e_llt_init;
|
||||
sc->sc_enable_mac_txrx = rtwn_nop_softc;
|
||||
sc->sc_set_page_size = rtwn_nop_int_softc;
|
||||
sc->sc_lc_calib = r92c_lc_calib;
|
||||
sc->sc_iq_calib = rtwn_nop_softc; /* XXX TODO */
|
||||
@@ -158,6 +159,7 @@ r92eu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_temp_read = r88e_temp_read;
|
||||
sc->sc_init_tx_agg = r21au_init_tx_agg;
|
||||
sc->sc_init_rx_agg = r92eu_init_rx_agg;
|
||||
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
|
||||
sc->sc_init_ampdu = rtwn_nop_softc;
|
||||
sc->sc_init_intr = r12a_init_intr;
|
||||
sc->sc_init_edca = r92c_init_edca;
|
||||
|
||||
@@ -118,6 +118,7 @@ r23bu_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_fw_download_enable = r23b_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92e_llt_init;
|
||||
sc->sc_enable_mac_txrx = rtwn_nop_softc;
|
||||
sc->sc_set_page_size = r23b_set_page_size;
|
||||
sc->sc_lc_calib = r23b_lc_calib;
|
||||
sc->sc_iq_calib = r23b_iq_calib;
|
||||
@@ -143,6 +144,7 @@ r23bu_attach(struct rtwn_usb_softc *uc)
|
||||
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_beacon_timer = r92c_init_beacon_timer;
|
||||
sc->sc_init_ampdu = r23bu_init_ampdu;
|
||||
sc->sc_init_intr = r92cu_init_intr;
|
||||
sc->sc_init_edca = r92c_init_edca;
|
||||
|
||||
@@ -234,6 +234,7 @@ r12au_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_fw_download_enable = r12a_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92c_llt_init;
|
||||
sc->sc_enable_mac_txrx = rtwn_nop_softc;
|
||||
sc->sc_set_page_size = r12a_set_page_size;
|
||||
sc->sc_lc_calib = r12a_lc_calib;
|
||||
sc->sc_iq_calib = r12a_iq_calib;
|
||||
@@ -259,6 +260,7 @@ r12au_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_temp_read = r88e_temp_read;
|
||||
sc->sc_init_tx_agg = r92cu_init_tx_agg;
|
||||
sc->sc_init_rx_agg = r12au_init_rx_agg;
|
||||
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
|
||||
sc->sc_init_ampdu = r12au_init_ampdu;
|
||||
sc->sc_init_intr = r12a_init_intr;
|
||||
sc->sc_init_edca = r12a_init_edca;
|
||||
|
||||
@@ -218,6 +218,7 @@ r21au_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_fw_download_enable = r12a_fw_download_enable;
|
||||
#endif
|
||||
sc->sc_llt_init = r92c_llt_init;
|
||||
sc->sc_enable_mac_txrx = rtwn_nop_softc;
|
||||
sc->sc_set_page_size = rtwn_nop_int_softc;
|
||||
sc->sc_lc_calib = rtwn_nop_softc; /* XXX not used */
|
||||
sc->sc_iq_calib = r12a_iq_calib;
|
||||
@@ -243,6 +244,7 @@ r21au_attach(struct rtwn_usb_softc *uc)
|
||||
sc->sc_temp_read = r88e_temp_read;
|
||||
sc->sc_init_tx_agg = r21au_init_tx_agg;
|
||||
sc->sc_init_rx_agg = r12au_init_rx_agg;
|
||||
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
|
||||
sc->sc_init_ampdu = r12au_init_ampdu;
|
||||
sc->sc_init_intr = r12a_init_intr;
|
||||
sc->sc_init_edca = r12a_init_edca;
|
||||
|
||||
@@ -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 r88fu_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 *);
|
||||
@@ -29,6 +30,7 @@ enum {
|
||||
RTWN_CHIP_RTL8192CU,
|
||||
RTWN_CHIP_RTL8192EU,
|
||||
RTWN_CHIP_RTL8188EU,
|
||||
RTWN_CHIP_RTL8188FU,
|
||||
RTWN_CHIP_RTL8723BU,
|
||||
RTWN_CHIP_RTL8812AU,
|
||||
RTWN_CHIP_RTL8821AU,
|
||||
@@ -134,6 +136,13 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = {
|
||||
RTWN_RTL8188EU_DEV(MERCUSYS, MW150US),
|
||||
#undef RTWN_RTL8188EU_DEV
|
||||
|
||||
/* RTL8188FU */
|
||||
#define RTWN_RTL8188FU_DEV(v,p) \
|
||||
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, \
|
||||
RTWN_USB_DEVINFO(RTWN_CHIP_RTL8188FU, 0)) }
|
||||
RTWN_RTL8188FU_DEV(REALTEK, RTL8188FTV),
|
||||
#undef RTWN_RTL8188FU_DEV
|
||||
|
||||
/* RTL8723BU */
|
||||
#define RTWN_RTL8723BU_DEV(v, p, i) \
|
||||
{ USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p), \
|
||||
@@ -196,6 +205,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_RTL8188FU] = r88fu_attach,
|
||||
[RTWN_CHIP_RTL8723BU] = r23bu_attach,
|
||||
[RTWN_CHIP_RTL8812AU] = r12au_attach,
|
||||
[RTWN_CHIP_RTL8821AU] = r21au_attach
|
||||
|
||||
@@ -4134,6 +4134,7 @@ product RATOC REXUSB60F 0xb020 USB serial adapter REX-USB60F
|
||||
/* Green House and CompUSA OEM this part */
|
||||
product REALTEK USB20CRW 0x0158 USB20CRW Card Reader
|
||||
product REALTEK RTL8188ETV 0x0179 RTL8188ETV
|
||||
product REALTEK RTL8188FTV 0xf179 RTL8188FTV
|
||||
product REALTEK RTL8188CTV 0x018a RTL8188CTV
|
||||
product REALTEK RTL8821AU_2 0x0811 RTL8821AU
|
||||
product REALTEK RTW8821CU_CD 0x1a2b RTW8821CU_CD
|
||||
|
||||
@@ -22,6 +22,11 @@ SRCS += r88e_beacon.c r88e_calib.c r88e_chan.c r88e_fw.c r88e_init.c \
|
||||
r88e_priv.h r88e_reg.h r88e_rom_defs.h r88e_rom_image.h \
|
||||
r88e_fw_cmd.h r88e_rx_desc.h r88e_tx_desc.h
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8188f
|
||||
SRCS += r88f.h r88f_calib.c r88f_chan.c r88f_fw.c r88f_init.c \
|
||||
r88f_priv.h r88f_reg.h r88f_rx.c r88f_rom.c r88f_rom_defs.h \
|
||||
r88f_rom_image.h
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8192e
|
||||
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 \
|
||||
|
||||
@@ -12,6 +12,10 @@ SRCS = rtwn_usb_attach.c rtwn_usb_ep.c rtwn_usb_reg.c rtwn_usb_rx.c \
|
||||
SRCS += r88eu_attach.c r88eu_init.c \
|
||||
r88eu.h r88eu_reg.h
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8188f/usb
|
||||
SRCS += r88fu_attach.c r88fu_init.c \
|
||||
r88fu.h
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8192c/usb
|
||||
SRCS += r92cu_attach.c r92cu_init.c r92cu_led.c r92cu_rx.c r92cu_tx.c \
|
||||
r92cu.h r92cu_priv.h r92cu_reg.h r92cu_tx_desc.h
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
SUBDIR= rtwnrtl8188eu rtwnrtl8192cT rtwnrtl8192cU rtwnrtl8192eu rtwnrtl8812au \
|
||||
rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB rtwnrtl8188ee rtwnrtl8723bu
|
||||
rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB rtwnrtl8188ee rtwnrtl8723bu \
|
||||
rtwnrtl8188fu
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
@@ -0,0 +1,4 @@
|
||||
KMOD= rtwn-rtl8188fufw
|
||||
IMG= rtwn-rtl8188fufw
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
Reference in new issue
Block a user