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.
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to