svn commit: r259544 - head/sys/dev/usb/wlan

Kevin Lo kevlo at FreeBSD.org
Wed Dec 18 07:34:58 UTC 2013


Author: kevlo
Date: Wed Dec 18 07:34:57 2013
New Revision: 259544
URL: http://svnweb.freebsd.org/changeset/base/259544

Log:
  Add support to IQ calibration.

Modified:
  head/sys/dev/usb/wlan/if_run.c
  head/sys/dev/usb/wlan/if_runreg.h

Modified: head/sys/dev/usb/wlan/if_run.c
==============================================================================
--- head/sys/dev/usb/wlan/if_run.c	Wed Dec 18 07:23:42 2013	(r259543)
+++ head/sys/dev/usb/wlan/if_run.c	Wed Dec 18 07:34:57 2013	(r259544)
@@ -345,6 +345,7 @@ static int	run_write(struct run_softc *,
 static int	run_write_region_1(struct run_softc *, uint16_t,
 		    const uint8_t *, int);
 static int	run_set_region_4(struct run_softc *, uint16_t, uint32_t, int);
+static int	run_efuse_read(struct run_softc *, uint16_t, uint16_t *, int);
 static int	run_efuse_read_2(struct run_softc *, uint16_t, uint16_t *);
 static int	run_eeprom_read_2(struct run_softc *, uint16_t, uint16_t *);
 static int	run_rt2870_rf_write(struct run_softc *, uint32_t);
@@ -391,6 +392,7 @@ static int	run_raw_xmit(struct ieee80211
 		    const struct ieee80211_bpf_params *);
 static void	run_start(struct ifnet *);
 static int	run_ioctl(struct ifnet *, u_long, caddr_t);
+static void	run_iq_calib(struct run_softc *, u_int);
 static void	run_set_agc(struct run_softc *, uint8_t);
 static void	run_select_chan_group(struct run_softc *, int);
 static void	run_set_rx_antenna(struct run_softc *, int);
@@ -436,6 +438,28 @@ static void	run_init_locked(struct run_s
 static void	run_stop(void *);
 static void	run_delay(struct run_softc *, u_int);
 
+static const struct rt2860_rate {
+	uint8_t		rate;
+	uint8_t		mcs;
+	enum		ieee80211_phytype phy;
+	uint8_t		ctl_ridx;
+	uint16_t	sp_ack_dur;
+	uint16_t	lp_ack_dur;
+} rt2860_rates[] = {
+	{   2, 0, IEEE80211_T_DS,   0, 314, 314 },
+	{   4, 1, IEEE80211_T_DS,   1, 258, 162 },
+	{  11, 2, IEEE80211_T_DS,   2, 223, 127 },
+	{  22, 3, IEEE80211_T_DS,   3, 213, 117 },
+	{  12, 0, IEEE80211_T_OFDM, 4,  60,  60 },
+	{  18, 1, IEEE80211_T_OFDM, 4,  52,  52 },
+	{  24, 2, IEEE80211_T_OFDM, 6,  48,  48 },
+	{  36, 3, IEEE80211_T_OFDM, 6,  44,  44 },
+	{  48, 4, IEEE80211_T_OFDM, 8,  44,  44 },
+	{  72, 5, IEEE80211_T_OFDM, 8,  40,  40 },
+	{  96, 6, IEEE80211_T_OFDM, 8,  40,  40 },
+	{ 108, 7, IEEE80211_T_OFDM, 8,  40,  40 }
+};
+
 static const struct {
 	uint16_t	reg;
 	uint32_t	val;
@@ -1249,9 +1273,8 @@ run_set_region_4(struct run_softc *sc, u
 	return (error);
 }
 
-/* Read 16-bit from eFUSE ROM (RT3070 only.) */
 static int
-run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
+run_efuse_read(struct run_softc *sc, uint16_t addr, uint16_t *val, int count)
 {
 	uint32_t tmp;
 	uint16_t reg;
@@ -1260,7 +1283,8 @@ run_efuse_read_2(struct run_softc *sc, u
 	if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0)
 		return (error);
 
-	addr *= 2;
+	if (count == 2)
+		addr *= 2;
 	/*-
 	 * Read one 16-byte block into registers EFUSE_DATA[0-3]:
 	 * DATA0: F E D C
@@ -1290,10 +1314,23 @@ run_efuse_read_2(struct run_softc *sc, u
 	if ((error = run_read(sc, reg, &tmp)) != 0)
 		return (error);
 
-	*val = (addr & 2) ? tmp >> 16 : tmp & 0xffff;
+	if (count == 2)
+		*val = (addr & 2) ? tmp >> 16 : tmp & 0xffff;
+	else {
+		tmp >>= (8 *(addr & 0x3));
+		memmove(val, &tmp, sizeof(*val));
+	}
 	return (0);
 }
 
+
+/* Read 16-bit from eFUSE ROM (RT3070 only.) */
+static int
+run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
+{
+	return (run_efuse_read(sc, addr, val, 2));
+}
+
 static int
 run_eeprom_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
 {
@@ -3600,6 +3637,107 @@ run_ioctl(struct ifnet *ifp, u_long cmd,
 }
 
 static void
+run_iq_calib(struct run_softc *sc, u_int chan)
+{
+	uint16_t val;
+
+	/* Tx0 IQ gain. */
+	run_bbp_write(sc, 158, 0x2c);
+	if (chan <= 14)
+		run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ, &val, 1);
+	else if (chan <= 64) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ,
+		    &val, 1);
+	} else if (chan <= 138) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ,
+		    &val, 1);
+	} else if (chan <= 165) {
+		run_efuse_read(sc,
+	    RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ,
+		    &val, 1);
+	} else
+		val = 0;
+	run_bbp_write(sc, 159, val & 0xff);
+
+	/* Tx0 IQ phase. */
+	run_bbp_write(sc, 158, 0x2d);
+	if (chan <= 14) {
+		run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ,
+		    &val, 1);
+	} else if (chan <= 64) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ,
+		    &val, 1);
+	} else if (chan <= 138) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ,
+		    &val, 1);
+	} else if (chan <= 165) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ,
+		    &val, 1);
+	} else
+		val = 0;
+	run_bbp_write(sc, 159, val & 0xff);
+
+	/* Tx1 IQ gain. */
+	run_bbp_write(sc, 158, 0x4a);
+	if (chan <= 14) {
+		run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ,
+		    &val, 1);
+	} else if (chan <= 64) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ,
+		    &val, 1);
+	} else if (chan <= 138) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ,
+		    &val, 1);
+	} else if (chan <= 165) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ,
+		    &val, 1);
+	} else
+		val = 0;
+	run_bbp_write(sc, 159, val & 0xff);
+
+	/* Tx1 IQ phase. */
+	run_bbp_write(sc, 158, 0x4b);
+	if (chan <= 14) {
+		run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ,
+		    &val, 1);
+	} else if (chan <= 64) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ,
+		    &val, 1);
+	} else if (chan <= 138) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ,
+		    &val, 1);
+	} else if (chan <= 165) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ,
+		    &val, 1);
+	} else
+		val = 0;
+	run_bbp_write(sc, 159, val & 0xff);
+
+	/* RF IQ compensation control. */
+	run_bbp_write(sc, 158, 0x04);
+	run_efuse_read(sc, RT5390_EEPROM_RF_IQ_COMPENSATION_CTL,
+	    &val, 1);
+	run_bbp_write(sc, 159, val & 0xff);
+
+	/* RF IQ imbalance compensation control. */
+	run_bbp_write(sc, 158, 0x03);
+	run_efuse_read(sc,
+	    RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL, &val, 1);
+	run_bbp_write(sc, 159, val & 0xff);
+}
+
+static void
 run_set_agc(struct run_softc *sc, uint8_t agc)
 {
 	uint8_t bbp;
@@ -4333,6 +4471,10 @@ run_set_chan(struct run_softc *sc, struc
 
 	run_delay(sc, 10);
 
+	/* Perform IQ calibrations. */
+	if (sc->mac_ver >= 0x5392)
+		run_iq_calib(sc, chan);
+
 	return (0);
 }
 

Modified: head/sys/dev/usb/wlan/if_runreg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_runreg.h	Wed Dec 18 07:23:42 2013	(r259543)
+++ head/sys/dev/usb/wlan/if_runreg.h	Wed Dec 18 07:34:57 2013	(r259544)
@@ -905,31 +905,32 @@ struct rt2860_rxwi {
 #define RT2860_EEPROM_BBP_BASE		0x78
 #define RT3071_EEPROM_RF_BASE		0x82
 
+/*
+ * EEPROM IQ calibration.
+ */
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ			0x130
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ			0x131
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ			0x133
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ			0x134
+#define	RT5390_EEPROM_RF_IQ_COMPENSATION_CTL			0x13c
+#define	RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL		0x13d
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ		0x144
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ	0x145
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ	0x146
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ	0x147
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ	0x148
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ	0x149
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ		0x14a
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ	0x14b
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ	0x14c
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ	0x14d
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ	0x14e
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ	0x14f
+
 #define RT2860_RIDX_CCK1	 0
 #define RT2860_RIDX_CCK11	 3
 #define RT2860_RIDX_OFDM6	 4
 #define RT2860_RIDX_MAX		12
-static const struct rt2860_rate {
-	uint8_t		rate;
-	uint8_t		mcs;
-	enum		ieee80211_phytype phy;
-	uint8_t		ctl_ridx;
-	uint16_t	sp_ack_dur;
-	uint16_t	lp_ack_dur;
-} rt2860_rates[] = {
-	{   2, 0, IEEE80211_T_DS,   0, 314, 314 },
-	{   4, 1, IEEE80211_T_DS,   1, 258, 162 },
-	{  11, 2, IEEE80211_T_DS,   2, 223, 127 },
-	{  22, 3, IEEE80211_T_DS,   3, 213, 117 },
-	{  12, 0, IEEE80211_T_OFDM, 4,  60,  60 },
-	{  18, 1, IEEE80211_T_OFDM, 4,  52,  52 },
-	{  24, 2, IEEE80211_T_OFDM, 6,  48,  48 },
-	{  36, 3, IEEE80211_T_OFDM, 6,  44,  44 },
-	{  48, 4, IEEE80211_T_OFDM, 8,  44,  44 },
-	{  72, 5, IEEE80211_T_OFDM, 8,  40,  40 },
-	{  96, 6, IEEE80211_T_OFDM, 8,  40,  40 },
-	{ 108, 7, IEEE80211_T_OFDM, 8,  40,  40 }
-};
 
 /*
  * EEPROM access macro.


More information about the svn-src-head mailing list