git: 7722d5e21477 - main - rtwn: add RTL8812/RTL8821 VHT80 channel programming, spur management

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Sat, 14 Dec 2024 02:17:57 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=7722d5e214772be22ef20bee46afeed2e9f78858

commit 7722d5e214772be22ef20bee46afeed2e9f78858
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2024-12-04 05:58:05 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2024-12-14 02:17:27 +0000

    rtwn: add RTL8812/RTL8821 VHT80 channel programming, spur management
    
    * add VHT80 channel programming
    * add VHT80 spur management, sync with Linux rtw88
    
    Obtained from: Linux rtw88
    
    Differential Revision:  https://reviews.freebsd.org/D47901
---
 sys/dev/rtwn/rtl8812a/r12a_chan.c | 81 ++++++++++++++++++++++++++++++++++-----
 sys/dev/rtwn/rtl8812a/r12a_reg.h  |  4 ++
 2 files changed, 75 insertions(+), 10 deletions(-)

diff --git a/sys/dev/rtwn/rtl8812a/r12a_chan.c b/sys/dev/rtwn/rtl8812a/r12a_chan.c
index 789a14b0e1d6..749f0e09e831 100644
--- a/sys/dev/rtwn/rtl8812a/r12a_chan.c
+++ b/sys/dev/rtwn/rtl8812a/r12a_chan.c
@@ -374,12 +374,20 @@ r12a_fix_spur(struct rtwn_softc *sc, struct ieee80211_channel *c)
 		} else {
 			rtwn_bb_setbits(sc, R12A_RFMOD, 0x400, 0x800);
 
-			if (!IEEE80211_IS_CHAN_HT40(c) &&	/* 20 MHz */
+			if ((IEEE80211_IS_CHAN_B(c) ||
+			    IEEE80211_IS_CHAN_ANYG(c) ||
+			    IEEE80211_IS_CHAN_HT20(c)) &&	/* 2GHz, 20 MHz */
 			    (chan == 13 || chan == 14)) {
 				rtwn_bb_setbits(sc, R12A_RFMOD, 0, 0x300);
 				rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK,
 				    0, 0x40000000);
-			} else {	/* !80 Mhz */
+			} else if (IEEE80211_IS_CHAN_HT40(c) ||
+			    IEEE80211_IS_CHAN_VHT40(c)) {
+				/* XXX double check! */
+				rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK,
+				    0, 0x40000000);
+			} else if (IEEE80211_IS_CHAN_VHT80(c)) {
+				/* XXX double check! */
 				rtwn_bb_setbits(sc, R12A_RFMOD, 0x100, 0x200);
 				rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK,
 				    0x40000000, 0);
@@ -387,7 +395,9 @@ r12a_fix_spur(struct rtwn_softc *sc, struct ieee80211_channel *c)
 		}
 	} else {
 		/* Set ADC clock to 160M to resolve 2480 MHz spur. */
-		if (!IEEE80211_IS_CHAN_HT40(c) &&	/* 20 MHz */
+		if ((IEEE80211_IS_CHAN_B(c) ||
+		    IEEE80211_IS_CHAN_ANYG(c) ||
+		    IEEE80211_IS_CHAN_HT20(c)) &&	/* 2GHz, 20 MHz */
 		    (chan == 13 || chan == 14))
 			rtwn_bb_setbits(sc, R12A_RFMOD, 0, 0x300);
 		else if (IEEE80211_IS_CHAN_2GHZ(c))
@@ -489,16 +499,67 @@ r12a_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
 		rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, 0xff, chan);
 	}
 
-#ifdef notyet
-	if (IEEE80211_IS_CHAN_HT80(c)) {	/* 80 MHz */
-		rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x80, 0x100);
+	if (IEEE80211_IS_CHAN_VHT80(c)) {	/* 80 MHz */
+		uint8_t ext20 = 0, ext40 = 0;
+		uint8_t txsc;
+		/* calculate ext20/ext40 */
+		if (c->ic_ieee > c->ic_vht_ch_freq1) {
+			if (c->ic_ieee - c->ic_vht_ch_freq1 == 2) {
+				ext20 = R12A_DATA_SEC_PRIM_UP_20;
+				ext40 = R12A_DATA_SEC_PRIM_UP_40;
+			} else {
+				ext20 = R12A_DATA_SEC_PRIM_UPPER_20;
+				ext40 = R12A_DATA_SEC_PRIM_UP_40;
+			}
+		} else {
+			if (c->ic_vht_ch_freq1 - c->ic_ieee == 2) {
+				ext20 = R12A_DATA_SEC_PRIM_DOWN_20;
+				ext40 = R12A_DATA_SEC_PRIM_DOWN_40;
+			} else {
+				ext20 = R12A_DATA_SEC_PRIM_LOWER_20;
+				ext40 = R12A_DATA_SEC_PRIM_DOWN_40;
+			}
+		}
+		/* Form txsc from sec20/sec40 config */
+		txsc = SM(R12A_DATA_SEC_TXSC_20M, ext20);
+		txsc |= SM(R12A_DATA_SEC_TXSC_40M, ext40);
+
+		rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x180, 0x100);
 
-		/* TODO */
+		/* DATA_SEC, for ext20/ext40 */
+		rtwn_write_1(sc, R12A_DATA_SEC, txsc);
+
+		/* ADCCLK */
+		rtwn_bb_setbits(sc, R12A_RFMOD, 0x003003c3, 0x00300202);
+
+		/* ADC160 - Set bit 30 */
+		rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK, 0, 0x40000000);
+
+		/* ADCCLK, ext20 */
+		/* discard high 4 bits */
+		val = rtwn_bb_read(sc, R12A_RFMOD);
+		val = RW(val, R12A_RFMOD_EXT_CHAN, ext20);
+		rtwn_bb_write(sc, R12A_RFMOD, val);
 
+		/* CCA2ND, ext20 */
+		val = rtwn_bb_read(sc, R12A_CCA_ON_SEC);
+		val = RW(val, R12A_CCA_ON_SEC_EXT_CHAN, ext20);
+		rtwn_bb_write(sc, R12A_CCA_ON_SEC, val);
+
+		/* PEAK_TH */
+		if (rtwn_read_1(sc, 0x837) & 0x04)
+			val = 0x01400000;
+		else if (sc->nrxchains == 2 && sc->ntxchains == 2)
+			val = 0x01800000;
+		else
+			val = 0x01c00000;
+
+		rtwn_bb_setbits(sc, R12A_L1_PEAK_TH, 0x03c00000, val);
+		/* BWMASK */
 		val = 0x0;
-	} else
-#endif
-	if (IEEE80211_IS_CHAN_HT40(c)) {	/* 40 MHz */
+
+	} else if (IEEE80211_IS_CHAN_HT40(c) ||
+	    IEEE80211_IS_CHAN_VHT40(c)) {	/* 40 MHz */
 		uint8_t ext_chan;
 
 		if (IEEE80211_IS_CHAN_HT40U(c))
diff --git a/sys/dev/rtwn/rtl8812a/r12a_reg.h b/sys/dev/rtwn/rtl8812a/r12a_reg.h
index 4f5f6f28c11a..13867fb76973 100644
--- a/sys/dev/rtwn/rtl8812a/r12a_reg.h
+++ b/sys/dev/rtwn/rtl8812a/r12a_reg.h
@@ -45,6 +45,10 @@
 #define R12A_AMPDU_MAX_TIME		0x456
 #define R12A_AMPDU_MAX_LENGTH		R92C_AGGLEN_LMT
 #define R12A_DATA_SEC			0x483
+#define R12A_DATA_SEC_TXSC_20M_M	0x0000000f
+#define R12A_DATA_SEC_TXSC_20M_S	0
+#define R12A_DATA_SEC_TXSC_40M_M	0x000000f0
+#define R12A_DATA_SEC_TXSC_40M_S	4
 #define R12A_ARFR_2G(i)			(0x48c + (i) * 8)
 #define R12A_HT_SINGLE_AMPDU		0x4c7