Author: kevlo
Date: Fri Feb 14 03:45:49 2014
New Revision: 261868
URL: http://svnweb.freebsd.org/changeset/base/261868

Log:
  MFC r259544, r259545, r259546, r259547, r259812, r259939, r260219, r260542,
      r261118, r261124, r261330:
  
  - Add support for the MediaTek/Ralink RT3593 chipset.
  - Various minor USB WLAN fixes and improvements.

Modified:
  stable/10/share/man/man4/run.4
  stable/10/sys/dev/usb/usbdevs
  stable/10/sys/dev/usb/wlan/if_run.c
  stable/10/sys/dev/usb/wlan/if_runreg.h
  stable/10/sys/dev/usb/wlan/if_runvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/share/man/man4/run.4
==============================================================================
--- stable/10/share/man/man4/run.4      Fri Feb 14 03:34:12 2014        
(r261867)
+++ stable/10/share/man/man4/run.4      Fri Feb 14 03:45:49 2014        
(r261868)
@@ -16,7 +16,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 11, 2013
+.Dd January 3, 2014
 .Dt RUN 4
 .Os
 .Sh NAME
@@ -64,8 +64,17 @@ The RT3000U is a single-chip solution ba
 an RT3020 (1T1R), RT3021 (1T2R) or RT3022 (2T2R) single-band radio
 transceiver.
 .Pp
-The RT3900E is a single-chip solution based on an RT5390 MAC/BBP and
-an RT5370 (1T1R) or RT5372 (2T2R) single-band radio transceiver.
+The RT3900E is a single-chip USB 2.0 802.11n solution.
+The MAC/Baseband Processor can be an RT3593, RT5390, RT5392 or an RT5592.
+The radio can be an RT3053, RT5370, RT5372 or an RT5572.
+The RT3053 chip operates in the 2GHz and 5GHz spectra and supports up to
+3 transmit paths and 3 receiver paths (3T3R).
+The RT5370 chip operates in the 2GHz spectrum and supports 1 transmit path
+and 1 receiver path (1T1R).
+The RT5372 chip operates in the 2GHz spectrum and supports up to 2 transmit
+paths and 2 receiver paths (2T2R).
+The RT5572 chip operates in the 2GHz and 5GHz spectra and supports up to
+2 transmit paths and 2 receiver paths (2T2R).
 .Pp
 These are the modes the
 .Nm
@@ -116,11 +125,13 @@ driver supports the following wireless a
 .It Airlink101 AWLL6090
 .It ASUS USB-N11
 .It ASUS USB-N13 ver. A1
+.It ASUS USB-N66
 .It ASUS WL-160N
 .It Belkin F5D8051 ver 3000
 .It Belkin F5D8053
 .It Belkin F5D8055
 .It Belkin F6D4050 ver 1
+.It Belkin F9L1103
 .It Buffalo WLI-UC-AG300N
 .It Buffalo WLI-UC-G300N
 .It Buffalo WLI-UC-G301N
@@ -132,13 +143,15 @@ driver supports the following wireless a
 .It Corega CG-WLUSB300AGN
 .It Corega CG-WLUSB300GNM
 .It D-Link DWA-130 rev B1
-.It D-Link DWA-140 rev B1, B2, B3
+.It D-Link DWA-140 rev B1, B2, B3, D1
 .It D-Link DWA-160 rev B2
+.It D-Link DWA-162
 .It DrayTek Vigor N61
 .It Edimax EW-7711UAn
 .It Edimax EW-7711UTn
 .It Edimax EW-7717Un
 .It Edimax EW-7718Un
+.It Edimax EW-7733UnD
 .It Gigabyte GN-WB30N
 .It Gigabyte GN-WB31N
 .It Gigabyte GN-WB32L
@@ -164,6 +177,7 @@ driver supports the following wireless a
 .It TP-LINK TL-WN727N v3
 .It Unex DNUR-81
 .It Unex DNUR-82
+.It ZyXEL NWD2705
 .It ZyXEL NWD210N
 .It ZyXEL NWD270N
 .El
@@ -235,4 +249,4 @@ driver was written by
 The
 .Nm
 driver does not support any of the 802.11n capabilities offered by the
-RT2800 and RT3000 chipsets.
+RT2800, RT3000 and RT3900 chipsets.

Modified: stable/10/sys/dev/usb/usbdevs
==============================================================================
--- stable/10/sys/dev/usb/usbdevs       Fri Feb 14 03:34:12 2014        
(r261867)
+++ stable/10/sys/dev/usb/usbdevs       Fri Feb 14 03:45:49 2014        
(r261868)
@@ -1183,6 +1183,7 @@ product   ASUS USBN13             0x1784  USB-N13
 product        ASUS RT3070_1           0x1790  RT3070
 product ASUS USBN10            0x1786  USB-N10
 product ASUS RTL8192CU         0x17ab  RTL8192CU
+product ASUS USBN66            0x17ad  USB-N66
 product ASUS RTL8192SU         0x1791  RTL8192SU
 product ASUS A730W             0x4202  ASUS MyPal A730W
 product ASUS P535              0x420f  ASUS P535 PDA
@@ -1285,6 +1286,7 @@ product BELKIN F5U409             0x0409  F5U409 Ser
 product BELKIN F6C550AVR       0x0551  F6C550-AVR UPS
 product BELKIN F5U120          0x1203  F5U120-PC Hub
 product BELKIN RTL8188CU       0x1102  RTL8188CU Wireless Adapter
+product BELKIN F9L1103         0x1103  F9L1103 Wireless Adapter
 product BELKIN RTL8192CU       0x2102  RTL8192CU Wireless Adapter
 product BELKIN F7D2102         0x2103  F7D2102 Wireless Adapter
 product BELKIN ZD1211B         0x4050  ZD1211B
@@ -1598,6 +1600,8 @@ product DLINK RT3072              0x3c0a  RT3072
 product DLINK DWA140B3         0x3c15  DWA-140 rev B3
 product DLINK DWA160B2         0x3c1a  DWA-160 rev B2
 product DLINK DWA127           0x3c1b  DWA-127 Wireless Adapter
+product DLINK DWA162           0x3c1f  DWA-162 Wireless Adapter
+product DLINK DWA140D1         0x3c20  DWA-140 rev D1
 product DLINK DSB650C          0x4000  10Mbps Ethernet
 product DLINK DSB650TX1                0x4001  10/100 Ethernet
 product DLINK DSB650TX         0x4002  10/100 Ethernet
@@ -1658,6 +1662,7 @@ product EDIMAX RTL8192SU_3        0x7622  RTL819
 product EDIMAX RT2870_1                0x7711  RT2870
 product EDIMAX EW7717          0x7717  EW-7717
 product EDIMAX EW7718          0x7718  EW-7718
+product EDIMAX EW7733UND       0x7733  EW-7733UnD
 product EDIMAX EW7811UN                0x7811  EW-7811Un
 product        EDIMAX RTL8192CU        0x7822  RTL8192CU
 
@@ -3617,11 +3622,13 @@ product RALINK RT2573           0x2573  RT2501USB 
 product RALINK RT2671          0x2671  RT2601USB Wireless Adapter
 product RALINK RT2770          0x2770  RT2770
 product RALINK RT2870          0x2870  RT2870
+product RALINK RT_STOR         0x2878  USB Storage
 product RALINK RT3070          0x3070  RT3070
 product RALINK RT3071          0x3071  RT3071
 product RALINK RT3072          0x3072  RT3072
 product RALINK RT3370          0x3370  RT3370
 product RALINK RT3572          0x3572  RT3572
+product RALINK RT3573          0x3573  RT3573
 product RALINK RT5370          0x5370  RT5370
 product RALINK RT5572          0x5572  RT5572
 product RALINK RT8070          0x8070  RT8070
@@ -3643,10 +3650,11 @@ product REALTEK RTL8171         0x8171  RTL8171
 product REALTEK RTL8172                0x8172  RTL8172
 product REALTEK RTL8173                0x8173  RTL8173
 product REALTEK RTL8174                0x8174  RTL8174
-product REALTEK RTL8188CE_1     0x817e  RTL8188CE
-product REALTEK RTL8188CU_0     0x8176  RTL8188CU
-product REALTEK RTL8188CU_1     0x817a  RTL8188CU
-product REALTEK RTL8188CU_2     0x817b  RTL8188CU
+product REALTEK RTL8188CU_0    0x8176  RTL8188CU
+product REALTEK RTL8188EU      0x8179  RTL8188EU
+product REALTEK RTL8188CE_1    0x817e  RTL8188CE
+product REALTEK RTL8188CU_1    0x817a  RTL8188CU
+product REALTEK RTL8188CU_2    0x817b  RTL8188CU
 product REALTEK RTL8187                0x8187  RTL8187 Wireless Adapter
 product REALTEK RTL8187B_0     0x8189  RTL8187B Wireless Adapter
 product REALTEK RTL8187B_1     0x8197  RTL8187B Wireless Adapter
@@ -4486,3 +4494,4 @@ product ZYXEL G202                0x3410  G-202
 product ZYXEL RT2870_1         0x3416  RT2870
 product ZYXEL RT2870_2         0x341a  RT2870
 product ZYXEL RTL8192CU                0x341f  RTL8192CU
+product ZYXEL NWD2705          0x3421  NWD2705

Modified: stable/10/sys/dev/usb/wlan/if_run.c
==============================================================================
--- stable/10/sys/dev/usb/wlan/if_run.c Fri Feb 14 03:34:12 2014        
(r261867)
+++ stable/10/sys/dev/usb/wlan/if_run.c Fri Feb 14 03:45:49 2014        
(r261868)
@@ -2,7 +2,7 @@
  * Copyright (c) 2008,2010 Damien Bergamini <damien.bergam...@free.fr>
  * ported to FreeBSD by Akinori Furukoshi <moonlightak...@yahoo.ca>
  * USB Consulting, Hans Petter Selasky <hsela...@freebsd.org>
- * Copyright (c) 2013 Kevin Lo
+ * Copyright (c) 2013-2014 Kevin Lo
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -69,14 +69,15 @@ __FBSDID("$FreeBSD$");
 #include <dev/usb/usbdi.h>
 #include "usbdevs.h"
 
-#define USB_DEBUG_VAR run_debug
+#define        USB_DEBUG_VAR   run_debug
 #include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_msctest.h>
 
 #include <dev/usb/wlan/if_runreg.h>
 #include <dev/usb/wlan/if_runvar.h>
 
 #ifdef USB_DEBUG
-#define RUN_DEBUG
+#define        RUN_DEBUG
 #endif
 
 #ifdef RUN_DEBUG
@@ -86,17 +87,19 @@ SYSCTL_INT(_hw_usb_run, OID_AUTO, debug,
     "run debug level");
 #endif
 
-#define IEEE80211_HAS_ADDR4(wh) \
+#define        IEEE80211_HAS_ADDR4(wh) \
        (((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
 
 /*
  * Because of LOR in run_key_delete(), use atomic instead.
  * '& RUN_CMDQ_MASQ' is to loop cmdq[].
  */
-#define RUN_CMDQ_GET(c)        (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ)
+#define        RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ)
 
 static const STRUCT_USB_HOST_ID run_devs[] = {
-#define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+#define        RUN_DEV(v,p)    { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) 
}
+#define        RUN_DEV_EJECT(v,p)      \
+       { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, 0) }
     RUN_DEV(ABOCOM,            RT2770),
     RUN_DEV(ABOCOM,            RT2870),
     RUN_DEV(ABOCOM,            RT3070),
@@ -135,6 +138,7 @@ static const STRUCT_USB_HOST_ID run_devs
     RUN_DEV(ASUS,              RT2870_5),
     RUN_DEV(ASUS,              USBN13),
     RUN_DEV(ASUS,              RT3070_1),
+    RUN_DEV(ASUS,              USBN66),
     RUN_DEV(ASUS,              USB_N53),
     RUN_DEV(ASUS2,             USBN11),
     RUN_DEV(AZUREWAVE,         RT2870_1),
@@ -142,6 +146,7 @@ static const STRUCT_USB_HOST_ID run_devs
     RUN_DEV(AZUREWAVE,         RT3070_1),
     RUN_DEV(AZUREWAVE,         RT3070_2),
     RUN_DEV(AZUREWAVE,         RT3070_3),
+    RUN_DEV(BELKIN,            F9L1103),
     RUN_DEV(BELKIN,            F5D8053V3),
     RUN_DEV(BELKIN,            F5D8055),
     RUN_DEV(BELKIN,            F5D8055V2),
@@ -174,6 +179,7 @@ static const STRUCT_USB_HOST_ID run_devs
     RUN_DEV(DLINK,             DWA127),
     RUN_DEV(DLINK,             DWA140B3),
     RUN_DEV(DLINK,             DWA160B2),
+    RUN_DEV(DLINK,             DWA162),
     RUN_DEV(DLINK2,            DWA130),
     RUN_DEV(DLINK2,            RT2870_1),
     RUN_DEV(DLINK2,            RT2870_2),
@@ -186,6 +192,7 @@ static const STRUCT_USB_HOST_ID run_devs
     RUN_DEV(DLINK2,            RT3072_1),
     RUN_DEV(EDIMAX,            EW7717),
     RUN_DEV(EDIMAX,            EW7718),
+    RUN_DEV(EDIMAX,            EW7733UND),
     RUN_DEV(EDIMAX,            RT2870_1),
     RUN_DEV(ENCORE,            RT3070_1),
     RUN_DEV(ENCORE,            RT3070_2),
@@ -257,6 +264,7 @@ static const STRUCT_USB_HOST_ID run_devs
     RUN_DEV(RALINK,            RT3072),
     RUN_DEV(RALINK,            RT3370),
     RUN_DEV(RALINK,            RT3572),
+    RUN_DEV(RALINK,            RT3573),
     RUN_DEV(RALINK,            RT5370),
     RUN_DEV(RALINK,            RT5572),
     RUN_DEV(RALINK,            RT8070),
@@ -306,6 +314,9 @@ static const STRUCT_USB_HOST_ID run_devs
     RUN_DEV(ZINWELL,           RT3072_2),
     RUN_DEV(ZYXEL,             RT2870_1),
     RUN_DEV(ZYXEL,             RT2870_2),
+    RUN_DEV(ZYXEL,             NWD2705),
+    RUN_DEV_EJECT(RALINK,      RT_STOR),
+#undef RUN_DEV_EJECT
 #undef RUN_DEV
 };
 
@@ -321,6 +332,9 @@ static usb_callback_t       run_bulk_tx_callba
 static usb_callback_t  run_bulk_tx_callback4;
 static usb_callback_t  run_bulk_tx_callback5;
 
+static void    run_autoinst(void *, struct usb_device *,
+                   struct usb_attach_arg *);
+static int     run_driver_loaded(struct module *, int, void *);
 static void    run_bulk_tx_callbackN(struct usb_xfer *xfer,
                    usb_error_t error, u_int index);
 static struct ieee80211vap *run_vap_create(struct ieee80211com *,
@@ -344,6 +358,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);
@@ -353,6 +368,8 @@ static int  run_bbp_read(struct run_softc
 static int     run_bbp_write(struct run_softc *, uint8_t, uint8_t);
 static int     run_mcu_cmd(struct run_softc *, uint8_t, uint16_t);
 static const char *run_get_rf(uint16_t);
+static void    run_rt3593_get_txpower(struct run_softc *);
+static void    run_get_txpower(struct run_softc *);
 static int     run_read_eeprom(struct run_softc *);
 static struct ieee80211_node *run_node_alloc(struct ieee80211vap *,
                            const uint8_t mac[IEEE80211_ADDR_LEN]);
@@ -390,12 +407,14 @@ 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);
 static void    run_rt2870_set_chan(struct run_softc *, u_int);
 static void    run_rt3070_set_chan(struct run_softc *, u_int);
 static void    run_rt3572_set_chan(struct run_softc *, u_int);
+static void    run_rt3593_set_chan(struct run_softc *, u_int);
 static void    run_rt5390_set_chan(struct run_softc *, u_int);
 static void    run_rt5592_set_chan(struct run_softc *, u_int);
 static int     run_set_chan(struct run_softc *, struct ieee80211_channel *);
@@ -424,10 +443,13 @@ static void       run_update_promisc(struct if
 static void    run_rt5390_bbp_init(struct run_softc *);
 static int     run_bbp_init(struct run_softc *);
 static int     run_rt3070_rf_init(struct run_softc *);
+static void    run_rt3593_rf_init(struct run_softc *);
 static void    run_rt5390_rf_init(struct run_softc *);
 static int     run_rt3070_filter_calib(struct run_softc *, uint8_t, uint8_t,
                    uint8_t *);
 static void    run_rt3070_rf_setup(struct run_softc *);
+static void    run_rt3593_rf_setup(struct run_softc *);
+static void    run_rt5390_rf_setup(struct run_softc *);
 static int     run_txrx_enable(struct run_softc *);
 static void    run_adjust_freq_offset(struct run_softc *);
 static void    run_init(void *);
@@ -435,6 +457,30 @@ static void        run_init_locked(struct run_s
 static void    run_stop(void *);
 static void    run_delay(struct run_softc *, u_int);
 
+static eventhandler_tag run_etag;
+
+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;
@@ -497,6 +543,8 @@ static const struct {
        RT3070_DEF_RF
 },rt3572_def_rf[] = {
        RT3572_DEF_RF
+},rt3593_def_rf[] = {
+       RT3593_DEF_RF
 },rt5390_def_rf[] = {
        RT5390_DEF_RF
 },rt5392_def_rf[] = {
@@ -589,6 +637,46 @@ static const struct usb_config run_confi
     }
 };
 
+static void
+run_autoinst(void *arg, struct usb_device *udev,
+    struct usb_attach_arg *uaa)
+{
+       struct usb_interface *iface;
+       struct usb_interface_descriptor *id;
+
+       if (uaa->dev_state != UAA_DEV_READY)
+               return;
+
+       iface = usbd_get_iface(udev, 0);
+       if (iface == NULL)
+               return;
+       id = iface->idesc;
+       if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
+               return;
+       if (usbd_lookup_id_by_uaa(run_devs, sizeof(run_devs), uaa))
+               return;
+
+       if (usb_msc_eject(udev, 0, MSC_EJECT_STOPUNIT) == 0)
+               uaa->dev_state = UAA_DEV_EJECTING;
+}
+
+static int
+run_driver_loaded(struct module *mod, int what, void *arg)
+{
+       switch (what) {
+       case MOD_LOAD:
+               run_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
+                   run_autoinst, NULL, EVENTHANDLER_PRI_ANY);
+               break;
+       case MOD_UNLOAD:
+               EVENTHANDLER_DEREGISTER(usb_dev_configured, run_etag);
+               break;
+       default:
+               return (EOPNOTSUPP);
+       }
+       return (0);
+}
+
 static int
 run_match(device_t self)
 {
@@ -710,7 +798,8 @@ run_attach(device_t self)
        setbit(&bands, IEEE80211_MODE_11B);
        setbit(&bands, IEEE80211_MODE_11G);
        if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 ||
-           sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT5592_RF_5592)
+           sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 ||
+           sc->rf_rev == RT5592_RF_5592)
                setbit(&bands, IEEE80211_MODE_11A);
        ieee80211_init_channels(ic, NULL, &bands);
 
@@ -1061,9 +1150,11 @@ run_load_microcode(struct run_softc *sc)
        }
 
        /* write microcode image */
-       run_write_region_1(sc, RT2870_FW_BASE, base, 4096);
-       run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff);
-       run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff);
+       if (sc->mac_ver != 0x3593) {
+               run_write_region_1(sc, RT2870_FW_BASE, base, 4096);
+               run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff);
+               run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff);
+       }
 
        req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
        req.bRequest = RT2870_RESET;
@@ -1078,15 +1169,16 @@ run_load_microcode(struct run_softc *sc)
 
        run_delay(sc, 10);
 
+       run_write(sc, RT2860_H2M_BBPAGENT, 0);
        run_write(sc, RT2860_H2M_MAILBOX, 0);
+       run_write(sc, RT2860_H2M_INTSRC, 0);
        if ((error = run_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0)) != 0)
                goto fail;
 
        /* wait until microcontroller is ready */
        for (ntries = 0; ntries < 1000; ntries++) {
-               if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0) {
+               if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0)
                        goto fail;
-               }
                if (tmp & RT2860_MCU_READY)
                        break;
                run_delay(sc, 10);
@@ -1248,9 +1340,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;
@@ -1259,7 +1350,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
@@ -1289,10 +1381,19 @@ 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;
+       tmp >>= (8 * (addr & 0x3));
+       *val = (addr & 1) ? tmp >> 16 : tmp & 0xffff;
+
        return (0);
 }
 
+/* Read 16-bit from eFUSE ROM for RT3xxx. */
+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)
 {
@@ -1305,7 +1406,7 @@ run_eeprom_read_2(struct run_softc *sc, 
        req.bRequest = RT2870_EEPROM_READ;
        USETW(req.wValue, 0);
        USETW(req.wIndex, addr);
-       USETW(req.wLength, sizeof tmp);
+       USETW(req.wLength, sizeof(tmp));
 
        error = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, &tmp);
        if (error == 0)
@@ -1500,6 +1601,7 @@ run_get_rf(uint16_t rev)
        case RT3070_RF_3021:    return "RT3021";
        case RT3070_RF_3022:    return "RT3022";
        case RT3070_RF_3052:    return "RT3052";
+       case RT3593_RF_3053:    return "RT3053";
        case RT5592_RF_5592:    return "RT5592";
        case RT5390_RF_5370:    return "RT5370";
        case RT5390_RF_5372:    return "RT5372";
@@ -1507,6 +1609,125 @@ run_get_rf(uint16_t rev)
        return ("unknown");
 }
 
+static void
+run_rt3593_get_txpower(struct run_softc *sc)
+{
+       uint16_t addr, val;
+       int i;
+
+       /* Read power settings for 2GHz channels. */
+       for (i = 0; i < 14; i += 2) {
+               addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE1 :
+                   RT2860_EEPROM_PWR2GHZ_BASE1;
+               run_srom_read(sc, addr + i / 2, &val);
+               sc->txpow1[i + 0] = (int8_t)(val & 0xff);
+               sc->txpow1[i + 1] = (int8_t)(val >> 8);
+
+               addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE2 :
+                   RT2860_EEPROM_PWR2GHZ_BASE2;
+               run_srom_read(sc, addr + i / 2, &val);
+               sc->txpow2[i + 0] = (int8_t)(val & 0xff);
+               sc->txpow2[i + 1] = (int8_t)(val >> 8);
+
+               if (sc->ntxchains == 3) {
+                       run_srom_read(sc, RT3593_EEPROM_PWR2GHZ_BASE3 + i / 2,
+                           &val);
+                       sc->txpow3[i + 0] = (int8_t)(val & 0xff);
+                       sc->txpow3[i + 1] = (int8_t)(val >> 8);
+               }
+       }
+       /* Fix broken Tx power entries. */
+       for (i = 0; i < 14; i++) {
+               if (sc->txpow1[i] > 31)
+                       sc->txpow1[i] = 5;
+               if (sc->txpow2[i] > 31)
+                       sc->txpow2[i] = 5;
+               if (sc->ntxchains == 3) {
+                       if (sc->txpow3[i] > 31)
+                               sc->txpow3[i] = 5;
+               }
+       }
+       /* Read power settings for 5GHz channels. */
+       for (i = 0; i < 40; i += 2) {
+               run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
+               sc->txpow1[i + 14] = (int8_t)(val & 0xff);
+               sc->txpow1[i + 15] = (int8_t)(val >> 8);
+
+               run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
+               sc->txpow2[i + 14] = (int8_t)(val & 0xff);
+               sc->txpow2[i + 15] = (int8_t)(val >> 8);
+
+               if (sc->ntxchains == 3) {
+                       run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE3 + i / 2,
+                           &val);
+                       sc->txpow3[i + 14] = (int8_t)(val & 0xff);
+                       sc->txpow3[i + 15] = (int8_t)(val >> 8);
+               }
+       }
+}
+
+static void
+run_get_txpower(struct run_softc *sc)
+{
+       uint16_t val;
+       int i;
+
+       /* Read power settings for 2GHz channels. */
+       for (i = 0; i < 14; i += 2) {
+               run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val);
+               sc->txpow1[i + 0] = (int8_t)(val & 0xff);
+               sc->txpow1[i + 1] = (int8_t)(val >> 8);
+
+               if (sc->mac_ver != 0x5390) {
+                       run_srom_read(sc,
+                           RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val);
+                       sc->txpow2[i + 0] = (int8_t)(val & 0xff);
+                       sc->txpow2[i + 1] = (int8_t)(val >> 8);
+               }
+       }
+       /* Fix broken Tx power entries. */
+       for (i = 0; i < 14; i++) {
+               if (sc->mac_ver >= 0x5390) {
+                       if (sc->txpow1[i] < 0 || sc->txpow1[i] > 27)
+                               sc->txpow1[i] = 5;
+               } else {
+                       if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
+                               sc->txpow1[i] = 5;
+               }
+               if (sc->mac_ver > 0x5390) {
+                       if (sc->txpow2[i] < 0 || sc->txpow2[i] > 27)
+                               sc->txpow2[i] = 5;
+               } else if (sc->mac_ver < 0x5390) {
+                       if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
+                               sc->txpow2[i] = 5;
+               }
+               DPRINTF("chan %d: power1=%d, power2=%d\n",
+                   rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]);
+       }
+       /* Read power settings for 5GHz channels. */
+       for (i = 0; i < 40; i += 2) {
+               run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
+               sc->txpow1[i + 14] = (int8_t)(val & 0xff);
+               sc->txpow1[i + 15] = (int8_t)(val >> 8);
+
+               run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
+               sc->txpow2[i + 14] = (int8_t)(val & 0xff);
+               sc->txpow2[i + 15] = (int8_t)(val >> 8);
+       }
+       /* Fix broken Tx power entries. */
+       for (i = 0; i < 40; i++ ) {
+               if (sc->mac_ver != 0x5592) {
+                       if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15)
+                               sc->txpow1[14 + i] = 5;
+                       if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
+                               sc->txpow2[14 + i] = 5;
+               }
+               DPRINTF("chan %d: power1=%d, power2=%d\n",
+                   rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i],
+                   sc->txpow2[14 + i]);
+       }
+}
+
 static int
 run_read_eeprom(struct run_softc *sc)
 {
@@ -1520,7 +1741,7 @@ run_read_eeprom(struct run_softc *sc)
        if (sc->mac_ver >= 0x3070) {
                run_read(sc, RT3070_EFUSE_CTRL, &tmp);
                DPRINTF("EFUSE_CTRL=0x%08x\n", tmp);
-               if (tmp & RT3070_SEL_EFUSE)
+               if ((tmp & RT3070_SEL_EFUSE) || sc->mac_ver == 0x3593)
                        sc->sc_srom_read = run_efuse_read_2;
        }
 
@@ -1539,7 +1760,7 @@ run_read_eeprom(struct run_softc *sc)
        sc->sc_bssid[4] = val & 0xff;
        sc->sc_bssid[5] = val >> 8;
 
-       if (sc->mac_ver < 0x5390) {
+       if (sc->mac_ver < 0x3593) {
                /* read vender BBP settings */
                for (i = 0; i < 10; i++) {
                        run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
@@ -1562,16 +1783,22 @@ run_read_eeprom(struct run_softc *sc)
        }
 
        /* read RF frequency offset from EEPROM */
-       run_srom_read(sc, RT2860_EEPROM_FREQ_LEDS, &val);
+       run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS :
+           RT3593_EEPROM_FREQ, &val);
        sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0;
        DPRINTF("EEPROM freq offset %d\n", sc->freq & 0xff);
 
+       run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS :
+           RT3593_EEPROM_FREQ_LEDS, &val);
        if (val >> 8 != 0xff) {
                /* read LEDs operating mode */
                sc->leds = val >> 8;
-               run_srom_read(sc, RT2860_EEPROM_LED1, &sc->led[0]);
-               run_srom_read(sc, RT2860_EEPROM_LED2, &sc->led[1]);
-               run_srom_read(sc, RT2860_EEPROM_LED3, &sc->led[2]);
+               run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED1 :
+                   RT3593_EEPROM_LED1, &sc->led[0]);
+               run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED2 :
+                   RT3593_EEPROM_LED2, &sc->led[1]);
+               run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED3 :
+                   RT3593_EEPROM_LED3, &sc->led[2]);
        } else {
                /* broken EEPROM, use default settings */
                sc->leds = 0x01;
@@ -1589,6 +1816,8 @@ run_read_eeprom(struct run_softc *sc)
                run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
 
        if (val == 0xffff) {
+               device_printf(sc->sc_dev,
+                   "invalid EEPROM antenna info, using default\n");
                DPRINTF("invalid EEPROM antenna info, using default\n");
                if (sc->mac_ver == 0x3572) {
                        /* default to RF3052 2T2R */
@@ -1633,60 +1862,11 @@ run_read_eeprom(struct run_softc *sc)
                sc->rfswitch = val & 1;
        }
 
-       /* read power settings for 2GHz channels */
-       for (i = 0; i < 14; i += 2) {
-               run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val);
-               sc->txpow1[i + 0] = (int8_t)(val & 0xff);
-               sc->txpow1[i + 1] = (int8_t)(val >> 8);
-
-               if (sc->mac_ver != 0x5390) {
-                       run_srom_read(sc,
-                           RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val);
-                       sc->txpow2[i + 0] = (int8_t)(val & 0xff);
-                       sc->txpow2[i + 1] = (int8_t)(val >> 8);
-               }
-       }
-       /* fix broken Tx power entries */
-       for (i = 0; i < 14; i++) {
-               if (sc->mac_ver >= 0x5390) {
-                       if (sc->txpow1[i] < 0 || sc->txpow1[i] > 27)
-                               sc->txpow1[i] = 5;
-               } else {
-                       if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
-                               sc->txpow1[i] = 5;
-               }
-               if (sc->mac_ver > 0x5390) {
-                       if (sc->txpow2[i] < 0 || sc->txpow2[i] > 27)
-                               sc->txpow2[i] = 5;
-               } else if (sc->mac_ver < 0x5390) {
-                       if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
-                               sc->txpow2[i] = 5;
-               }
-               DPRINTF("chan %d: power1=%d, power2=%d\n",
-                   rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]);
-       }
-       /* read power settings for 5GHz channels */
-       for (i = 0; i < 40; i += 2) {
-               run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
-               sc->txpow1[i + 14] = (int8_t)(val & 0xff);
-               sc->txpow1[i + 15] = (int8_t)(val >> 8);
-
-               run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
-               sc->txpow2[i + 14] = (int8_t)(val & 0xff);
-               sc->txpow2[i + 15] = (int8_t)(val >> 8);
-       }
-       /* fix broken Tx power entries */
-       for (i = 0; i < 40; i++ ) {
-               if (sc->mac_ver != 0x5592) {
-                       if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15)
-                               sc->txpow1[14 + i] = 5;
-                       if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
-                               sc->txpow2[14 + i] = 5;
-               }
-               DPRINTF("chan %d: power1=%d, power2=%d\n",
-                   rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i],
-                   sc->txpow2[14 + i]);
-       }
+       /* Read Tx power settings. */
+       if (sc->mac_ver == 0x3593)
+               run_rt3593_get_txpower(sc);
+       else
+               run_get_txpower(sc);
 
        /* read Tx power compensation for each Tx rate */
        run_srom_read(sc, RT2860_EEPROM_DELTAPWR, &val);
@@ -1722,27 +1902,38 @@ run_read_eeprom(struct run_softc *sc)
                    sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]);
        }
 
-       /* read RSSI offsets and LNA gains from EEPROM */
-       run_srom_read(sc, RT2860_EEPROM_RSSI1_2GHZ, &val);
+       /* Read RSSI offsets and LNA gains from EEPROM. */
+       run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_2GHZ :
+           RT3593_EEPROM_RSSI1_2GHZ, &val);
        sc->rssi_2ghz[0] = val & 0xff;  /* Ant A */
        sc->rssi_2ghz[1] = val >> 8;    /* Ant B */
-       run_srom_read(sc, RT2860_EEPROM_RSSI2_2GHZ, &val);
+       run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_2GHZ :
+           RT3593_EEPROM_RSSI2_2GHZ, &val);
        if (sc->mac_ver >= 0x3070) {
-               /*
-                * On RT3070 chips (limited to 2 Rx chains), this ROM
-                * field contains the Tx mixer gain for the 2GHz band.
-                */
-               if ((val & 0xff) != 0xff)
-                       sc->txmixgain_2ghz = val & 0x7;
+               if (sc->mac_ver == 0x3593) {
+                       sc->txmixgain_2ghz = 0;
+                       sc->rssi_2ghz[2] = val & 0xff;  /* Ant C */
+               } else {
+                       /*
+                        * On RT3070 chips (limited to 2 Rx chains), this ROM
+                        * field contains the Tx mixer gain for the 2GHz band.
+                        */
+                       if ((val & 0xff) != 0xff)
+                               sc->txmixgain_2ghz = val & 0x7;
+               }
                DPRINTF("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz);
        } else
                sc->rssi_2ghz[2] = val & 0xff;  /* Ant C */
+       if (sc->mac_ver == 0x3593)
+               run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val);
        sc->lna[2] = val >> 8;          /* channel group 2 */
 
-       run_srom_read(sc, RT2860_EEPROM_RSSI1_5GHZ, &val);
+       run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_5GHZ :
+           RT3593_EEPROM_RSSI1_5GHZ, &val);
        sc->rssi_5ghz[0] = val & 0xff;  /* Ant A */
        sc->rssi_5ghz[1] = val >> 8;    /* Ant B */
-       run_srom_read(sc, RT2860_EEPROM_RSSI2_5GHZ, &val);
+       run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_5GHZ :
+           RT3593_EEPROM_RSSI2_5GHZ, &val);
        if (sc->mac_ver == 0x3572) {
                /*
                 * On RT3572 chips (limited to 2 Rx chains), this ROM
@@ -1753,9 +1944,14 @@ run_read_eeprom(struct run_softc *sc)
                DPRINTF("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz);
        } else
                sc->rssi_5ghz[2] = val & 0xff;  /* Ant C */
+       if (sc->mac_ver == 0x3593) {
+               sc->txmixgain_5ghz = 0;
+               run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val);
+       }
        sc->lna[3] = val >> 8;          /* channel group 3 */
 
-       run_srom_read(sc, RT2860_EEPROM_LNA, &val);
+       run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LNA :
+           RT3593_EEPROM_LNA, &val);
        sc->lna[0] = val & 0xff;        /* channel group 0 */
        sc->lna[1] = val >> 8;          /* channel group 1 */
 
@@ -2570,9 +2766,11 @@ run_rx_frame(struct run_softc *sc, struc
 
        rxwi = mtod(m, struct rt2860_rxwi *);
        len = le16toh(rxwi->len) & 0xfff;
-       rxwisize = (sc->mac_ver == 0x5592) ?
-           sizeof(struct rt2860_rxwi) + sizeof(uint64_t) :
-           sizeof(struct rt2860_rxwi);
+       rxwisize = sizeof(struct rt2860_rxwi);
+       if (sc->mac_ver == 0x5592)
+               rxwisize += sizeof(uint64_t);
+       else if (sc->mac_ver == 0x3593)
+               rxwisize += sizeof(uint32_t);
        if (__predict_false(len > dmalen)) {
                m_freem(m);
                ifp->if_ierrors++;
@@ -2683,9 +2881,11 @@ run_bulk_rx_callback(struct usb_xfer *xf
        uint16_t rxwisize;
        int xferlen;
 
-       rxwisize = (sc->mac_ver == 0x5592) ?
-           sizeof(struct rt2860_rxwi) + sizeof(uint64_t) :
-           sizeof(struct rt2860_rxwi);
+       rxwisize = sizeof(struct rt2860_rxwi);
+       if (sc->mac_ver == 0x5592)
+               rxwisize += sizeof(uint64_t);
+       else if (sc->mac_ver == 0x3593)
+               rxwisize += sizeof(uint32_t);
 
        usbd_xfer_status(xfer, &xferlen, NULL, NULL, NULL);
 
@@ -2869,10 +3069,10 @@ tr_setup:
                STAILQ_REMOVE_HEAD(&pq->tx_qh, next);
 
                m = data->m;
-               size = (sc->mac_ver == 0x5592) ? 
-                   RUN_MAX_TXSZ + sizeof(uint32_t) : RUN_MAX_TXSZ;
+               size = (sc->mac_ver == 0x5592) ?
+                   sizeof(data->desc) + sizeof(uint32_t) : sizeof(data->desc);
                if ((m->m_pkthdr.len +
-                   sizeof(data->desc) + 3 + 8) > size) {
+                   size + 3 + 8) > RUN_MAX_TXSZ) {
                        DPRINTF("data overflow, %u bytes\n",
                            m->m_pkthdr.len);
 
@@ -2884,8 +3084,6 @@ tr_setup:
                }
 
                pc = usbd_xfer_get_frame(xfer, 0);
-               size = (sc->mac_ver == 0x5592) ?
-                   sizeof(data->desc) + sizeof(uint32_t) : sizeof(data->desc);
                usbd_copy_in(pc, 0, &data->desc, size);
                usbd_m_copy_in(pc, size, m, 0, m->m_pkthdr.len);
                size += m->m_pkthdr.len;
@@ -3599,6 +3797,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);
+
+       /* 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);
+
+       /* 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);
+
+       /* 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);
+
+       /* 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);
+
+       /* 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);
+}
+
+static void
 run_set_agc(struct run_softc *sc, uint8_t agc)
 {
        uint8_t bbp;
@@ -3626,6 +3925,11 @@ run_select_chan_group(struct run_softc *
        if (sc->mac_ver < 0x3572)
                run_bbp_write(sc, 86, 0x00);
 
+       if (sc->mac_ver == 0x3593) {
+               run_bbp_write(sc, 77, 0x98);
+               run_bbp_write(sc, 83, (group == 0) ? 0x8a : 0x9a);
+       }
+
        if (group == 0) {
                if (sc->ext_2ghz_lna) {
                        if (sc->mac_ver >= 0x5390)
@@ -3656,7 +3960,8 @@ run_select_chan_group(struct run_softc *
                        } else if (sc->mac_ver >= 0x5390)
                                run_bbp_write(sc, 75, 0x50);
                        else {
-                               run_bbp_write(sc, 82, 0x84);
+                               run_bbp_write(sc, 82,
+                                   (sc->mac_ver == 0x3593) ? 0x62 : 0x84);
                                run_bbp_write(sc, 75, 0x50);
                        }
                }
@@ -3682,7 +3987,8 @@ run_select_chan_group(struct run_softc *
                } else if (sc->mac_ver == 0x3572)
                        run_bbp_write(sc, 82, 0x94);
                else
-                       run_bbp_write(sc, 82, 0xf2);
+                       run_bbp_write(sc, 82,
+                           (sc->mac_ver == 0x3593) ? 0x82 : 0xf2);
                if (sc->ext_5ghz_lna)
                        run_bbp_write(sc, 75, 0x46);
                else 
@@ -3696,12 +4002,18 @@ run_select_chan_group(struct run_softc *

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to