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