Module Name:    src
Committed By:   mlelstv
Date:           Fri Sep 16 09:25:30 UTC 2016

Modified Files:
        src/sys/dev/ic: rt2860reg.h
        src/sys/dev/usb: if_run.c if_runvar.h
        src/sys/net80211: ieee80211.h

Log Message:
Merge enough FreeBSD code to make RT5592 work.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ic/rt2860reg.h
cvs rdiff -u -r1.15 -r1.16 src/sys/dev/usb/if_run.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/usb/if_runvar.h
cvs rdiff -u -r1.27 -r1.28 src/sys/net80211/ieee80211.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ic/rt2860reg.h
diff -u src/sys/dev/ic/rt2860reg.h:1.5 src/sys/dev/ic/rt2860reg.h:1.6
--- src/sys/dev/ic/rt2860reg.h:1.5	Fri Jul  8 01:24:53 2016
+++ src/sys/dev/ic/rt2860reg.h	Fri Sep 16 09:25:30 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: rt2860reg.h,v 1.5 2016/07/08 01:24:53 christos Exp $	*/
+/*	$NetBSD: rt2860reg.h,v 1.6 2016/09/16 09:25:30 mlelstv Exp $	*/
 /*	$OpenBSD: rt2860reg.h,v 1.32 2014/05/24 10:10:17 stsp Exp $	*/
 
 /*-
@@ -83,6 +83,8 @@
 #define RT3070_LDO_CFG0			0x05d4
 #define RT3070_GPIO_SWITCH		0x05dc
 
+
+
 /* RT5592 registers */
 #define RT5592_DEBUG_INDEX		0x05e8
 
@@ -783,6 +785,12 @@
 /* possible flags for RT3053 RF register 51 */
 #define RT3593_TX_LO1	(1U << 4)
 
+/* Possible flags for RT5390 RF register 2. */
+#define RT5390_RESCAL	(1 << 7)
+
+/* Possible flags for RT5390 RF register 3. */
+#define RT5390_VCOCAL	(1 << 7)
+
 /* Possible flags for RT5390 BBP register 4. */
 #define RT5390_MAC_IF_CTRL	(1U << 6)
 

Index: src/sys/dev/usb/if_run.c
diff -u src/sys/dev/usb/if_run.c:1.15 src/sys/dev/usb/if_run.c:1.16
--- src/sys/dev/usb/if_run.c:1.15	Fri Jun 10 13:27:15 2016
+++ src/sys/dev/usb/if_run.c	Fri Sep 16 09:25:30 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_run.c,v 1.15 2016/06/10 13:27:15 ozaki-r Exp $	*/
+/*	$NetBSD: if_run.c,v 1.16 2016/09/16 09:25:30 mlelstv Exp $	*/
 /*	$OpenBSD: if_run.c,v 1.90 2012/03/24 15:11:04 jsg Exp $	*/
 
 /*-
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.15 2016/06/10 13:27:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.16 2016/09/16 09:25:30 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/sockio.h>
@@ -74,6 +74,8 @@ int run_debug = 0;
 #define DPRINTFN(n, x)
 #endif
 
+#define IEEE80211_HAS_ADDR4(wh) IEEE80211_IS_DSTODS(wh)
+
 #define USB_ID(v, p)	{ USB_VENDOR_##v, USB_PRODUCT_##v##_##p }
 static const struct usb_devno run_devs[] = {
 	USB_ID(ABOCOM,		RT2770),
@@ -251,6 +253,7 @@ static const struct usb_devno run_devs[]
 	USB_ID(RALINK,		RT3072),
 	USB_ID(RALINK,		RT3370),
 	USB_ID(RALINK,		RT3572),
+	USB_ID(RALINK,		RT5572),
 	USB_ID(RALINK,		RT8070),
 	USB_ID(SAMSUNG,		RT2870_1),
 	USB_ID(SENAO,		RT2870_1),
@@ -329,6 +332,8 @@ static int		run_write_region_1(struct ru
 			    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,
@@ -343,6 +348,8 @@ static int		run_bbp_read(struct run_soft
 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(int);
+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 ieee80211_node_table *);
@@ -378,13 +385,18 @@ static void		run_start(struct ifnet *);
 static void		run_watchdog(struct ifnet *);
 static int		run_ioctl(struct ifnet *, u_long, void *);
 static void		run_select_chan_group(struct run_softc *, int);
+static void		run_iq_calib(struct run_softc *, u_int);
 static void		run_set_agc(struct run_softc *, uint8_t);
 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 *);
+static void		run_updateprot(struct run_softc *);
 static void		run_enable_tsf_sync(struct run_softc *);
 static void		run_enable_mrr(struct run_softc *);
 static void		run_set_txpreamble(struct run_softc *);
@@ -395,12 +407,18 @@ static void		run_set_macaddr(struct run_
 static void		run_updateslot(struct ifnet *);
 static void		run_updateslot_cb(struct run_softc *, void *);
 static int8_t		run_rssi2dbm(struct run_softc *, uint8_t, uint8_t);
+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 int		run_rt3593_rf_init(struct run_softc *);
+static int		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 int     		run_adjust_freq_offset(struct run_softc *);
 static int		run_init(struct ifnet *);
 static void		run_stop(struct ifnet *, int);
 #ifndef IEEE80211_STA_ONLY
@@ -419,6 +437,25 @@ static const struct {
 	uint8_t val;
 } rt2860_def_bbp[] = {
 	RT2860_DEF_BBP
+}, rt5390_def_bbp[] = {
+	RT5390_DEF_BBP
+}, rt5592_def_bbp[] = {
+	RT5592_DEF_BBP
+};
+
+/*
+ * Default values for BBP register R196 for RT5592.
+ */
+static const uint8_t rt5592_bbp_r196[] = {
+	0xe0, 0x1f, 0x38, 0x32, 0x08, 0x28, 0x19, 0x0a, 0xff, 0x00,
+	0x16, 0x10, 0x10, 0x0b, 0x36, 0x2c, 0x26, 0x24, 0x42, 0x36,
+	0x30, 0x2d, 0x4c, 0x46, 0x3d, 0x40, 0x3e, 0x42, 0x3d, 0x40,
+	0x3c, 0x34, 0x2c, 0x2f, 0x3c, 0x35, 0x2e, 0x2a, 0x49, 0x41,
+	0x36, 0x31, 0x30, 0x30, 0x0e, 0x0d, 0x28, 0x21, 0x1c, 0x16,
+	0x50, 0x4a, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x7d, 0x14, 0x32, 0x2c, 0x36, 0x4c, 0x43, 0x2c,
+	0x2e, 0x36, 0x30, 0x6e
 };
 
 static const struct rfprog {
@@ -434,6 +471,15 @@ static const struct {
 	RT3070_RF3052
 };
 
+static const struct rt5592_freqs {
+	uint16_t n;
+	uint8_t k, m, r;
+} rt5592_freqs_20mhz[] = {
+	RT5592_RF5592_20MHZ
+},rt5592_freqs_40mhz[] = {
+	RT5592_RF5592_40MHZ
+};
+
 static const struct {
 	uint8_t reg;
 	uint8_t val;
@@ -441,6 +487,27 @@ 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[] = {   
+	RT5392_DEF_RF   
+},rt5592_def_rf[] = {   
+	RT5592_DEF_RF   
+},rt5592_2ghz_def_rf[] = {
+	RT5592_2GHZ_DEF_RF
+},rt5592_5ghz_def_rf[] = {
+	RT5592_5GHZ_DEF_RF
+};
+
+static const struct {
+	u_int firstchan;
+	u_int lastchan;
+	uint8_t reg;
+	uint8_t val;
+} rt5592_chan_5ghz[] = {
+	RT5592_CHAN_5GHZ
 };
 
 static int
@@ -596,7 +663,9 @@ run_attach(device_t parent, device_t sel
 
 	if (sc->rf_rev == RT2860_RF_2750 ||
 	    sc->rf_rev == RT2860_RF_2850 ||
-	    sc->rf_rev == RT3070_RF_3052) {
+	    sc->rf_rev == RT3070_RF_3052 ||
+	    sc->rf_rev == RT3070_RF_3053 ||
+	    sc->rf_rev == RT5592_RF_5592) {
 		/* set supported .11a rates */
 		ic->ic_sup_rates[IEEE80211_MODE_11A] =
 		    ieee80211_std_rateset_11a;
@@ -698,6 +767,9 @@ run_detach(device_t self, int flags)
 
 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
 
+	callout_stop(&sc->scan_to);
+	callout_stop(&sc->calib_to);
+
 	callout_destroy(&sc->scan_to);
 	callout_destroy(&sc->calib_to);
 
@@ -872,7 +944,7 @@ run_load_microcode(struct run_softc *sc)
 			return error;
 		if (tmp & RT2860_MCU_READY)
 			break;
-		DELAY(1000);
+		usbd_delay_ms(sc->sc_udev, 10);
 	}
 	if (ntries == 1000) {
 		aprint_error_dev(sc->sc_dev,
@@ -985,9 +1057,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;
@@ -996,7 +1067,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
@@ -1012,7 +1084,7 @@ run_efuse_read_2(struct run_softc *sc, u
 			return error;
 		if (!(tmp & RT3070_EFSROM_KICK))
 			break;
-		DELAY(2);
+		usbd_delay_ms(sc->sc_udev, 2);
 	}
 	if (ntries == 100)
 		return ETIMEDOUT;
@@ -1026,10 +1098,17 @@ 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;
+	*val = (addr & 1) ? tmp >> 16 : tmp & 0xffff;
 	return 0;
 }
 
+/* Read 16-bit from eFUSE ROM for RT3xxxx. */
+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)
 {
@@ -1240,10 +1319,133 @@ run_get_rf(int rev)
 	case RT3070_RF_3021:	return "RT3021";
 	case RT3070_RF_3022:	return "RT3022";
 	case RT3070_RF_3052:	return "RT3052";
+	case RT3070_RF_3053:    return "RT3053";
+	case RT5592_RF_5592:    return "RT5592";
+	case RT5390_RF_5370:    return "RT5370";
+	case RT5390_RF_5372:    return "RT5372";
 	}
 	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] > 39)
+				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] > 39)
+				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)
 {
@@ -1284,15 +1486,14 @@ run_read_eeprom(struct run_softc *sc)
 		sc->bbp[i].reg = val >> 8;
 		DPRINTF(("BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val));
 	}
-	if (sc->mac_ver >= 0x3071) {
-		/* read vendor RF settings */
-		for (i = 0; i < 10; i++) {
-			run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, &val);
-			sc->rf[i].val = val & 0xff;
-			sc->rf[i].reg = val >> 8;
-			DPRINTF(("RF%d=0x%02x\n", sc->rf[i].reg,
-			    sc->rf[i].val));
-		}
+
+	/* read vendor RF settings */
+	for (i = 0; i < 8; i++) {
+		run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, &val);
+		sc->rf[i].val = val & 0xff;
+		sc->rf[i].reg = val >> 8;
+		DPRINTF(("RF%d=0x%02x\n", sc->rf[i].reg,
+		    sc->rf[i].val));
 	}
 
 	/* read RF frequency offset from EEPROM */
@@ -1358,45 +1559,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);
-
-		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->txpow1[i] < 0 || sc->txpow1[i] > 31)
-			sc->txpow1[i] = 5;
-		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->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);
@@ -1438,22 +1605,31 @@ run_read_eeprom(struct run_softc *sc)
 	sc->rssi_2ghz[1] = val >> 8;	/* Ant B */
 	run_srom_read(sc, RT2860_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_RSSI2_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
@@ -1465,9 +1641,14 @@ run_read_eeprom(struct run_softc *sc)
 	} 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 */
 
@@ -2010,7 +2191,7 @@ run_rx_frame(struct run_softc *sc, uint8
 	struct rt2860_rxwi *rxwi;
 	struct mbuf *m;
 	uint32_t flags;
-	uint16_t len, phy;
+	uint16_t len, rxwisize, phy;
 	uint8_t ant, rssi;
 	int s;
 #ifdef RUN_HWCRYPTO
@@ -2032,7 +2213,13 @@ run_rx_frame(struct run_softc *sc, uint8
 		return;
 	}
 
-	wh = (struct ieee80211_frame *)(rxwi + 1);
+	rxwisize = sizeof(struct rt2860_rxwi);
+	if (sc->mac_ver == 0x5592)
+		rxwisize += sizeof(uint64_t);
+	else if (sc->mac_ver == 0x3593)
+		rxwisize += sizeof(uint32_t);
+
+	wh = (struct ieee80211_frame *)(((uint8_t *)rxwi) + rxwisize);
 #ifdef RUN_HWCRYPTO
 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
 		wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
@@ -2169,7 +2356,8 @@ run_rxeof(struct usbd_xfer *xfer, void *
 	while (xferlen > 8) {
 		dmalen = le32toh(*(uint32_t *)buf) & 0xffff;
 
-		if (__predict_false(dmalen == 0 || (dmalen & 3) != 0)) {
+		if (__predict_false((dmalen >= (uint32_t)-8) || dmalen == 0 ||
+		    (dmalen & 3) != 0)) {
 			DPRINTF(("bad DMA length %u (%x)\n", dmalen, dmalen));
 			break;
 		}
@@ -2232,7 +2420,8 @@ run_tx(struct run_softc *sc, struct mbuf
 	struct rt2860_txwi *txwi;
 	uint16_t dur;
 	uint8_t type, mcs, tid, qid, qos = 0;
-	int error, hasqos, ridx, ctl_ridx, xferlen;
+	int error, hasqos, ridx, ctl_ridx, xferlen, txwisize;
+	uint8_t pad;
 
 	wh = mtod(m, struct ieee80211_frame *);
 
@@ -2278,7 +2467,9 @@ run_tx(struct run_softc *sc, struct mbuf
 	/* get MCS code from rate index */
 	mcs = rt2860_rates[ridx].mcs;
 
-	xferlen = sizeof(*txwi) + m->m_pkthdr.len;
+	txwisize = (sc->mac_ver == 0x5592) ?
+	    sizeof(*txwi) + sizeof(uint32_t) : sizeof(*txwi);
+	xferlen = txwisize + m->m_pkthdr.len;
 	/* roundup to 32-bit alignment */
 	xferlen = (xferlen + 3) & ~3;
 
@@ -2286,20 +2477,29 @@ run_tx(struct run_softc *sc, struct mbuf
 	txd->flags = RT2860_TX_QSEL_EDCA;
 	txd->len = htole16(xferlen);
 
+	/* 
+	 * Ether both are true or both are false, the header
+	 * are nicely aligned to 32-bit. So, no L2 padding.
+	 */     
+	if (IEEE80211_HAS_ADDR4(wh) == IEEE80211_QOS_HAS_SEQ(wh))
+		pad = 0;
+	else    
+		pad = 2;
+
 	/* setup TX Wireless Information */
 	txwi = (struct rt2860_txwi *)(txd + 1);
 	txwi->flags = 0;
 	txwi->xflags = hasqos ? 0 : RT2860_TX_NSEQ;
 	txwi->wcid = (type == IEEE80211_FC0_TYPE_DATA) ?
 	    RUN_AID2WCID(ni->ni_associd) : 0xff;
-	txwi->len = htole16(m->m_pkthdr.len);
+	txwi->len = htole16(m->m_pkthdr.len - pad);
 	if (rt2860_rates[ridx].phy == IEEE80211_T_DS) {
 		txwi->phy = htole16(RT2860_PHY_CCK);
 		if (ridx != RT2860_RIDX_CCK1 &&
 		    (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
 			mcs |= RT2860_PHY_SHPRE;
 	} else
-		txwi->phy = htole16(RT2860_PHY_OFDM);
+		mcs |= RT2860_PHY_OFDM;
 	txwi->phy |= htole16(mcs);
 
 	txwi->txop = RT2860_TX_TXOP_BACKOFF;
@@ -2338,7 +2538,7 @@ run_tx(struct run_softc *sc, struct mbuf
 		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m);
 	}
 
-	m_copydata(m, 0, m->m_pkthdr.len, (void *)(txwi + 1));
+	m_copydata(m, 0, m->m_pkthdr.len, ((uint8_t *)txwi) + txwisize);
 	m_freem(m);
 
 	xferlen += sizeof(*txd) + 4;
@@ -2609,14 +2809,14 @@ run_rt2870_set_chan(struct run_softc *sc
 	run_rt2870_rf_write(sc, RT2860_RF3, r3);
 	run_rt2870_rf_write(sc, RT2860_RF4, r4);
 
-	DELAY(200);
+	usbd_delay_ms(sc->sc_udev, 10);
 
 	run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
 	run_rt2870_rf_write(sc, RT2860_RF2, r2);
 	run_rt2870_rf_write(sc, RT2860_RF3, r3 | 1);
 	run_rt2870_rf_write(sc, RT2860_RF4, r4);
 
-	DELAY(200);
+	usbd_delay_ms(sc->sc_udev, 10);
 
 	run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
 	run_rt2870_rf_write(sc, RT2860_RF2, r2);
@@ -2834,7 +3034,515 @@ run_rt3572_set_chan(struct run_softc *sc
 	run_rt3070_rf_read(sc, 7, &rf);
 	run_rt3070_rf_write(sc, 7, rf | 0x01);
 
-	DELAY(2000);
+	usbd_delay_ms(sc->sc_udev, 2);
+}
+
+static void
+run_rt3593_set_chan(struct run_softc *sc, u_int chan)
+{
+	int8_t txpow1, txpow2, txpow3;
+	uint8_t h20mhz, rf;
+	int i;
+
+	/* find the settings for this channel (we know it exists) */
+	for (i = 0; rt2860_rf2850[i].chan != chan; i++);
+
+	/* use Tx power values from EEPROM */
+	txpow1 = sc->txpow1[i];
+	txpow2 = sc->txpow2[i];
+	txpow3 = (sc->ntxchains == 3) ? sc->txpow3[i] : 0;
+
+	if (chan <= 14) {
+		run_bbp_write(sc, 25, sc->bbp25);
+		run_bbp_write(sc, 26, sc->bbp26);
+	} else {
+		/* Enable IQ phase correction. */
+		run_bbp_write(sc, 25, 0x09);
+		run_bbp_write(sc, 26, 0xff);
+	}
+
+	run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n);
+	run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f);
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03);
+	run_rt3070_rf_write(sc, 11, rf);
+
+	/* Set pll_idoh. */
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf &= ~0x4c;
+	rf |= (chan <= 14) ? 0x44 : 0x48;
+	run_rt3070_rf_write(sc, 11, rf);
+
+	if (chan <= 14)
+		rf = txpow1 & 0x1f;
+	else
+		rf = 0x40 | ((txpow1 & 0x18) << 1) | (txpow1 & 0x07);
+	run_rt3070_rf_write(sc, 53, rf);
+
+	if (chan <= 14)
+		rf = txpow2 & 0x1f;
+	else
+		rf = 0x40 | ((txpow2 & 0x18) << 1) | (txpow2 & 0x07);
+	run_rt3070_rf_write(sc, 55, rf);
+
+	if (chan <= 14)
+		rf = txpow3 & 0x1f;
+	else
+		rf = 0x40 | ((txpow3 & 0x18) << 1) | (txpow3 & 0x07);
+	run_rt3070_rf_write(sc, 54, rf);
+
+	rf = RT3070_RF_BLOCK | RT3070_PLL_PD;
+	if (sc->ntxchains == 3)
+		rf |= RT3070_TX0_PD | RT3070_TX1_PD | RT3070_TX2_PD;
+	else
+		rf |= RT3070_TX0_PD | RT3070_TX1_PD;
+	rf |= RT3070_RX0_PD | RT3070_RX1_PD | RT3070_RX2_PD;
+	run_rt3070_rf_write(sc, 1, rf);
+
+	run_adjust_freq_offset(sc);
+
+	run_rt3070_rf_write(sc, 31, (chan <= 14) ? 0xa0 : 0x80);
+
+	h20mhz = (sc->rf24_20mhz & 0x20) >> 5;
+	run_rt3070_rf_read(sc, 30, &rf);
+	rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2);
+	run_rt3070_rf_write(sc, 30, rf);
+
+	run_rt3070_rf_read(sc, 36, &rf);
+	if (chan <= 14)
+		rf |= 0x80;
+	else
+		rf &= ~0x80;
+	run_rt3070_rf_write(sc, 36, rf);
+
+	/* Set vcolo_bs. */
+	run_rt3070_rf_write(sc, 34, (chan <= 14) ? 0x3c : 0x20);
+	/* Set pfd_delay. */
+	run_rt3070_rf_write(sc, 12, (chan <= 14) ? 0x1a : 0x12);
+
+	/* Set vco bias current control. */
+	run_rt3070_rf_read(sc, 6, &rf);
+	rf &= ~0xc0;
+	if (chan <= 14)
+		rf |= 0x40;
+	else if (chan <= 128)
+		rf |= 0x80;
+	else
+		rf |= 0x40;
+	run_rt3070_rf_write(sc, 6, rf);
+
+	run_rt3070_rf_read(sc, 30, &rf);
+	rf = (rf & ~0x18) | 0x10;
+	run_rt3070_rf_write(sc, 30, rf);
+
+	run_rt3070_rf_write(sc, 10, (chan <= 14) ? 0xd3 : 0xd8);
+	run_rt3070_rf_write(sc, 13, (chan <= 14) ? 0x12 : 0x23);
+
+	run_rt3070_rf_read(sc, 51, &rf);
+	rf = (rf & ~0x03) | 0x01;
+	run_rt3070_rf_write(sc, 51, rf);
+	/* Set tx_mx1_cc. */
+	run_rt3070_rf_read(sc, 51, &rf);
+	rf &= ~0x1c;
+	rf |= (chan <= 14) ? 0x14 : 0x10;
+	run_rt3070_rf_write(sc, 51, rf);
+	/* Set tx_mx1_ic. */
+	run_rt3070_rf_read(sc, 51, &rf);
+	rf &= ~0xe0;
+	rf |= (chan <= 14) ? 0x60 : 0x40;
+	run_rt3070_rf_write(sc, 51, rf);
+	/* Set tx_lo1_ic. */
+	run_rt3070_rf_read(sc, 49, &rf);
+	rf &= ~0x1c;
+	rf |= (chan <= 14) ? 0x0c : 0x08;
+	run_rt3070_rf_write(sc, 49, rf);
+	/* Set tx_lo1_en. */
+	run_rt3070_rf_read(sc, 50, &rf);
+	run_rt3070_rf_write(sc, 50, rf & ~0x20);
+	/* Set drv_cc. */
+	run_rt3070_rf_read(sc, 57, &rf);
+	rf &= ~0xfc;
+	rf |= (chan <= 14) ?  0x6c : 0x3c;
+	run_rt3070_rf_write(sc, 57, rf);
+	/* Set rx_mix1_ic, rxa_lnactr, lna_vc, lna_inbias_en and lna_en. */
+	run_rt3070_rf_write(sc, 44, (chan <= 14) ? 0x93 : 0x9b);
+	/* Set drv_gnd_a, tx_vga_cc_a and tx_mx2_gain. */
+	run_rt3070_rf_write(sc, 52, (chan <= 14) ? 0x45 : 0x05);
+	/* Enable VCO calibration. */
+	run_rt3070_rf_read(sc, 3, &rf);
+	rf &= ~RT5390_VCOCAL;
+	rf |= (chan <= 14) ? RT5390_VCOCAL : 0xbe;
+	run_rt3070_rf_write(sc, 3, rf);
+
+	if (chan <= 14)
+		rf = 0x23;
+	else if (chan <= 64)
+		rf = 0x36;
+	else if (chan <= 128)
+		rf = 0x32;
+	else
+		rf = 0x30;
+	run_rt3070_rf_write(sc, 39, rf);
+	if (chan <= 14)
+		rf = 0xbb;
+	else if (chan <= 64)
+		rf = 0xeb;
+	else if (chan <= 128)
+		rf = 0xb3;
+	else
+		rf = 0x9b;
+	run_rt3070_rf_write(sc, 45, rf);
+
+	/* Set FEQ/AEQ control. */
+	run_bbp_write(sc, 105, 0x34);
+}
+
+static void
+run_rt5390_set_chan(struct run_softc *sc, u_int chan)
+{
+	int8_t txpow1, txpow2;
+	uint8_t rf;
+	int i;
+
+	/* find the settings for this channel (we know it exists) */
+	for (i = 0; rt2860_rf2850[i].chan != chan; i++);
+
+	/* use Tx power values from EEPROM */
+	txpow1 = sc->txpow1[i];
+	txpow2 = sc->txpow2[i];
+
+	run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n);
+	run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f);
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03);
+	run_rt3070_rf_write(sc, 11, rf);
+
+	run_rt3070_rf_read(sc, 49, &rf);
+	rf = (rf & ~0x3f) | (txpow1 & 0x3f);
+	/* The valid range of the RF R49 is 0x00 to 0x27. */
+	if ((rf & 0x3f) > 0x27)
+		rf = (rf & ~0x3f) | 0x27;
+	run_rt3070_rf_write(sc, 49, rf);
+
+	if (sc->mac_ver == 0x5392) {
+		run_rt3070_rf_read(sc, 50, &rf);
+		rf = (rf & ~0x3f) | (txpow2 & 0x3f);
+		/* The valid range of the RF R50 is 0x00 to 0x27. */
+		if ((rf & 0x3f) > 0x27)
+			rf = (rf & ~0x3f) | 0x27;
+		run_rt3070_rf_write(sc, 50, rf);
+	}
+
+	run_rt3070_rf_read(sc, 1, &rf);
+	rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD;
+	if (sc->mac_ver == 0x5392)
+		rf |= RT3070_RX1_PD | RT3070_TX1_PD;
+	run_rt3070_rf_write(sc, 1, rf);
+
+	if (sc->mac_ver != 0x5392) {
+		run_rt3070_rf_read(sc, 2, &rf);
+		rf |= 0x80;
+		run_rt3070_rf_write(sc, 2, rf);
+		usbd_delay_ms(sc->sc_udev, 10);
+		rf &= 0x7f;
+		run_rt3070_rf_write(sc, 2, rf);
+	}
+
+	run_adjust_freq_offset(sc);
+
+	if (sc->mac_ver == 0x5392) {
+		/* Fix for RT5392C. */
+		if (sc->mac_rev >= 0x0223) {
+			if (chan <= 4)
+				rf = 0x0f;
+			else if (chan >= 5 && chan <= 7)
+				rf = 0x0e;
+			else
+				rf = 0x0d;
+			run_rt3070_rf_write(sc, 23, rf);
+
+			if (chan <= 4)
+				rf = 0x0c;
+			else if (chan == 5)
+				rf = 0x0b;
+			else if (chan >= 6 && chan <= 7)
+				rf = 0x0a;
+			else if (chan >= 8 && chan <= 10)
+				rf = 0x09;
+			else
+				rf = 0x08;
+			run_rt3070_rf_write(sc, 59, rf);
+		} else {
+			if (chan <= 11)
+				rf = 0x0f;
+			else
+				rf = 0x0b;
+			run_rt3070_rf_write(sc, 59, rf);
+		}
+	} else {
+		/* Fix for RT5390F. */
+		if (sc->mac_rev >= 0x0502) {
+			if (chan <= 11)
+				rf = 0x43;
+			else
+				rf = 0x23;
+			run_rt3070_rf_write(sc, 55, rf);
+
+			if (chan <= 11)
+				rf = 0x0f;
+			else if (chan == 12)
+				rf = 0x0d;
+			else
+				rf = 0x0b;
+			run_rt3070_rf_write(sc, 59, rf);
+		} else {
+			run_rt3070_rf_write(sc, 55, 0x44);
+			run_rt3070_rf_write(sc, 59, 0x8f);
+		}
+	}
+
+	/* Enable VCO calibration. */
+	run_rt3070_rf_read(sc, 3, &rf);
+	rf |= RT5390_VCOCAL;
+	run_rt3070_rf_write(sc, 3, rf);
+}
+
+static void
+run_rt5592_set_chan(struct run_softc *sc, u_int chan)
+{
+	const struct rt5592_freqs *freqs;
+	uint32_t tmp;
+	uint8_t reg, rf, txpow_bound;
+	int8_t txpow1, txpow2;
+	int i;
+
+	run_read(sc, RT5592_DEBUG_INDEX, &tmp);
+	freqs = (tmp & RT5592_SEL_XTAL) ?
+	    rt5592_freqs_40mhz : rt5592_freqs_20mhz;
+
+	/* find the settings for this channel (we know it exists) */
+	for (i = 0; rt2860_rf2850[i].chan != chan; i++, freqs++);
+
+	/* use Tx power values from EEPROM */
+	txpow1 = sc->txpow1[i];
+	txpow2 = sc->txpow2[i];
+
+	run_read(sc, RT3070_LDO_CFG0, &tmp);
+	tmp &= ~0x1c000000;
+	if (chan > 14)
+		tmp |= 0x14000000;
+	run_write(sc, RT3070_LDO_CFG0, tmp);
+
+	/* N setting. */
+	run_rt3070_rf_write(sc, 8, freqs->n & 0xff);
+	run_rt3070_rf_read(sc, 9, &rf);
+	rf &= ~(1 << 4);
+	rf |= ((freqs->n & 0x0100) >> 8) << 4;
+	run_rt3070_rf_write(sc, 9, rf);
+
+	/* K setting. */
+	run_rt3070_rf_read(sc, 9, &rf);
+	rf &= ~0x0f;
+	rf |= (freqs->k & 0x0f);
+	run_rt3070_rf_write(sc, 9, rf);
+
+	/* Mode setting. */
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf &= ~0x0c;
+	rf |= ((freqs->m - 0x8) & 0x3) << 2;
+	run_rt3070_rf_write(sc, 11, rf);
+	run_rt3070_rf_read(sc, 9, &rf);
+	rf &= ~(1 << 7);
+	rf |= (((freqs->m - 0x8) & 0x4) >> 2) << 7;
+	run_rt3070_rf_write(sc, 9, rf);
+
+	/* R setting. */
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf &= ~0x03;
+	rf |= (freqs->r - 0x1);
+	run_rt3070_rf_write(sc, 11, rf);
+
+	if (chan <= 14) {
+		/* Initialize RF registers for 2GHZ. */
+		for (i = 0; i < (int)__arraycount(rt5592_2ghz_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5592_2ghz_def_rf[i].reg,
+			    rt5592_2ghz_def_rf[i].val);
+		}
+
+		rf = (chan <= 10) ? 0x07 : 0x06;
+		run_rt3070_rf_write(sc, 23, rf);
+		run_rt3070_rf_write(sc, 59, rf);
+
+		run_rt3070_rf_write(sc, 55, 0x43);
+
+		/*
+		 * RF R49/R50 Tx power ALC code.
+		 * G-band bit<7:6>=1:0, bit<5:0> range from 0x0 ~ 0x27.
+		 */
+		reg = 2;
+		txpow_bound = 0x27;
+	} else {
+		/* Initialize RF registers for 5GHZ. */
+		for (i = 0; i < (int)__arraycount(rt5592_5ghz_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5592_5ghz_def_rf[i].reg,
+			    rt5592_5ghz_def_rf[i].val);
+		}
+		for (i = 0; i < (int)__arraycount(rt5592_chan_5ghz); i++) {
+			if (chan >= rt5592_chan_5ghz[i].firstchan &&
+			    chan <= rt5592_chan_5ghz[i].lastchan) {
+				run_rt3070_rf_write(sc, rt5592_chan_5ghz[i].reg,
+				    rt5592_chan_5ghz[i].val);
+			}
+		}
+
+		/*
+		 * RF R49/R50 Tx power ALC code.
+		 * A-band bit<7:6>=1:1, bit<5:0> range from 0x0 ~ 0x2b.
+		 */
+		reg = 3;
+		txpow_bound = 0x2b;
+	}
+
+	/* RF R49 ch0 Tx power ALC code. */
+	run_rt3070_rf_read(sc, 49, &rf);
+	rf &= ~0xc0;
+	rf |= (reg << 6);
+	rf = (rf & ~0x3f) | (txpow1 & 0x3f);
+	if ((rf & 0x3f) > txpow_bound)
+		rf = (rf & ~0x3f) | txpow_bound;
+	run_rt3070_rf_write(sc, 49, rf);
+
+	/* RF R50 ch1 Tx power ALC code. */
+	run_rt3070_rf_read(sc, 50, &rf);
+	rf &= ~(1 << 7 | 1 << 6);
+	rf |= (reg << 6);
+	rf = (rf & ~0x3f) | (txpow2 & 0x3f);
+	if ((rf & 0x3f) > txpow_bound)
+		rf = (rf & ~0x3f) | txpow_bound;
+	run_rt3070_rf_write(sc, 50, rf);
+
+	/* Enable RF_BLOCK, PLL_PD, RX0_PD, and TX0_PD. */
+	run_rt3070_rf_read(sc, 1, &rf);
+	rf |= (RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD);
+	if (sc->ntxchains > 1)
+		rf |= RT3070_TX1_PD;
+	if (sc->nrxchains > 1)
+		rf |= RT3070_RX1_PD;
+	run_rt3070_rf_write(sc, 1, rf);
+
+	run_rt3070_rf_write(sc, 6, 0xe4);
+
+	run_rt3070_rf_write(sc, 30, 0x10);
+	run_rt3070_rf_write(sc, 31, 0x80);
+	run_rt3070_rf_write(sc, 32, 0x80);
+
+	run_adjust_freq_offset(sc);
+
+	/* Enable VCO calibration. */
+	run_rt3070_rf_read(sc, 3, &rf);
+	rf |= RT5390_VCOCAL;
+	run_rt3070_rf_write(sc, 3, rf);
+}
+
+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
@@ -2857,13 +3565,22 @@ static void
 run_set_rx_antenna(struct run_softc *sc, int aux)
 {
 	uint32_t tmp;
+	uint8_t bbp152;
 
-	run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, !aux);
-	run_read(sc, RT2860_GPIO_CTRL, &tmp);
-	tmp &= ~0x0808;
-	if (aux)
-		tmp |= 0x08;
-	run_write(sc, RT2860_GPIO_CTRL, tmp);
+	if (sc->rf_rev == RT5390_RF_5370) {
+		run_bbp_read(sc, 152, &bbp152);
+		bbp152 &= ~0x80;
+		if (aux)
+			bbp152 |= 0x80;
+		run_bbp_write(sc, 152, bbp152);
+	} else {
+		run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, !aux);
+		run_read(sc, RT2860_GPIO_CTRL, &tmp);
+		tmp &= ~0x0808;
+		if (aux)
+			tmp |= 0x08;
+		run_write(sc, RT2860_GPIO_CTRL, tmp);
+	}
 }
 
 static int
@@ -2876,7 +3593,13 @@ run_set_chan(struct run_softc *sc, struc
 	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
 		return EINVAL;
 
-	if (sc->mac_ver == 0x3572)
+	if (sc->mac_ver == 0x5592)
+		run_rt5592_set_chan(sc, chan);
+	else if (sc->mac_ver >= 0x5390)
+		run_rt5390_set_chan(sc, chan);
+	else if (sc->mac_ver == 0x3593)
+		run_rt3593_set_chan(sc, chan);
+	else if (sc->mac_ver == 0x3572)
 		run_rt3572_set_chan(sc, chan);
 	else if (sc->mac_ver >= 0x3070)
 		run_rt3070_set_chan(sc, chan);
@@ -2896,11 +3619,39 @@ run_set_chan(struct run_softc *sc, struc
 	/* XXX necessary only when group has changed! */
 	run_select_chan_group(sc, group);
 
-	DELAY(1000);
+	usbd_delay_ms(sc->sc_udev, 10);
+
+	/* Perform IQ calibration. */
+	if (sc->mac_ver >= 0x5392) 
+		run_iq_calib(sc, chan); 
+
 	return 0;
 }
 
 static void
+run_updateprot(struct run_softc *sc)
+{
+	struct ieee80211com *ic = &sc->sc_ic; 
+	uint32_t tmp;
+
+	tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
+	/* setup protection frame rate (MCS code) */
+	tmp |= (ic->ic_curmode == IEEE80211_MODE_11A) ?
+	    rt2860_rates[RT2860_RIDX_OFDM6].mcs | RT2860_PHY_OFDM :
+	    rt2860_rates[RT2860_RIDX_CCK11].mcs;
+
+	/* CCK frames don't require protection */
+	run_write(sc, RT2860_CCK_PROT_CFG, tmp);
+	if (ic->ic_flags & IEEE80211_F_USEPROT) {
+		if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
+			tmp |= RT2860_PROT_CTRL_RTS_CTS;
+		else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
+			tmp |= RT2860_PROT_CTRL_CTS;
+	}
+	run_write(sc, RT2860_OFDM_PROT_CFG, tmp);
+}
+
+static void
 run_enable_tsf_sync(struct run_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -3057,6 +3808,64 @@ run_rssi2dbm(struct run_softc *sc, uint8
 	return -12 - delta - rssi;
 }
 
+static void     
+run_rt5390_bbp_init(struct run_softc *sc)
+{
+	u_int i;
+	uint8_t bbp;
+
+	/* Apply maximum likelihood detection for 2 stream case. */
+	run_bbp_read(sc, 105, &bbp);
+	if (sc->nrxchains > 1)
+		run_bbp_write(sc, 105, bbp | RT5390_MLD);
+
+	/* Avoid data lost and CRC error. */
+	run_bbp_read(sc, 4, &bbp);
+	run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+	if (sc->mac_ver == 0x5592) {
+		for (i = 0; i < (int)__arraycount(rt5592_def_bbp); i++) {
+			run_bbp_write(sc, rt5592_def_bbp[i].reg,
+			    rt5592_def_bbp[i].val);
+		}
+		for (i = 0; i < (int)__arraycount(rt5592_bbp_r196); i++) {
+			run_bbp_write(sc, 195, i + 0x80);
+			run_bbp_write(sc, 196, rt5592_bbp_r196[i]);
+		}       
+	} else {        
+		for (i = 0; i < (int)__arraycount(rt5390_def_bbp); i++) {
+			run_bbp_write(sc, rt5390_def_bbp[i].reg,
+			    rt5390_def_bbp[i].val);
+		} 
+	}  
+	if (sc->mac_ver == 0x5392) {
+		run_bbp_write(sc, 88, 0x90); 
+		run_bbp_write(sc, 95, 0x9a); 
+		run_bbp_write(sc, 98, 0x12); 
+		run_bbp_write(sc, 106, 0x12);
+		run_bbp_write(sc, 134, 0xd0);
+		run_bbp_write(sc, 135, 0xf6);
+		run_bbp_write(sc, 148, 0x84);
+	} 
+  
+	run_bbp_read(sc, 152, &bbp);
+	run_bbp_write(sc, 152, bbp | 0x80);
+	
+	/* Fix BBP254 for RT5592C. */
+	if (sc->mac_ver == 0x5592 && sc->mac_rev >= 0x0221) {
+		run_bbp_read(sc, 254, &bbp);
+		run_bbp_write(sc, 254, bbp | 0x80);
+	}
+
+	/* Disable hardware antenna diversity. */
+	if (sc->mac_ver == 0x5390)
+		run_bbp_write(sc, 154, 0);
+
+	/* Initialize Rx CCK/OFDM frequency offset report. */
+	run_bbp_write(sc, 142, 1);
+	run_bbp_write(sc, 143, 57);
+}
+
 static int
 run_bbp_init(struct run_softc *sc)
 {
@@ -3074,9 +3883,21 @@ run_bbp_init(struct run_softc *sc)
 		return ETIMEDOUT;
 
 	/* initialize BBP registers to default values */
-	for (i = 0; i < (int)__arraycount(rt2860_def_bbp); i++) {
-		run_bbp_write(sc, rt2860_def_bbp[i].reg,
-		    rt2860_def_bbp[i].val);
+	if (sc->mac_ver >= 0x5390)
+		run_rt5390_bbp_init(sc);
+	else {
+		for (i = 0; i < (int)__arraycount(rt2860_def_bbp); i++) {
+			run_bbp_write(sc, rt2860_def_bbp[i].reg,
+			    rt2860_def_bbp[i].val);
+		}
+	}
+
+	if (sc->mac_ver == 0x3593) {
+		run_bbp_write(sc, 79, 0x13);
+		run_bbp_write(sc, 80, 0x05);
+		run_bbp_write(sc, 81, 0x33);
+		run_bbp_write(sc, 86, 0x46);
+		run_bbp_write(sc, 137, 0x0f);
 	}
 
 	/* fix BBP84 for RT2860E */
@@ -3104,7 +3925,7 @@ run_rt3070_rf_init(struct run_softc *sc)
 	run_rt3070_rf_read(sc, 30, &rf);
 	/* toggle RF R30 bit 7 */
 	run_rt3070_rf_write(sc, 30, rf | 0x80);
-	DELAY(1000);
+	usbd_delay_ms(sc->sc_udev, 10);
 	run_rt3070_rf_write(sc, 30, rf & ~0x80);
 
 	/* initialize RF registers to default value */
@@ -3122,17 +3943,15 @@ run_rt3070_rf_init(struct run_softc *sc)
 	if (sc->mac_ver == 0x3572) {
 		run_rt3070_rf_read(sc, 6, &rf);
 		run_rt3070_rf_write(sc, 6, rf | 0x40);
+		run_rt3070_rf_write(sc, 31, 0x14);
 
-		/* increase voltage from 1.2V to 1.35V */
 		run_read(sc, RT3070_LDO_CFG0, &tmp);
-		tmp = (tmp & ~0x1f000000) | 0x0d000000;
+		tmp &= ~0x1f000000;
+		if (sc->mac_rev < 0x0211 && sc->patch_dac)
+			tmp |= 0x0d000000;	/* 1.3V */
+		else
+			tmp |= 0x01000000;	/* 1.2V */
 		run_write(sc, RT3070_LDO_CFG0, tmp);
-		if (sc->mac_rev >= 0x0211 || !sc->patch_dac) {
-			/* decrease voltage back to 1.2V */
-			DELAY(1000);
-			tmp = (tmp & ~0x1f000000) | 0x01000000;
-			run_write(sc, RT3070_LDO_CFG0, tmp);
-		}
 	} else if (sc->mac_ver == 0x3071) {
 		run_rt3070_rf_read(sc, 6, &rf);
 		run_rt3070_rf_write(sc, 6, rf | 0x40);
@@ -3228,6 +4047,121 @@ run_rt3070_rf_init(struct run_softc *sc)
 }
 
 static int
+run_rt3593_rf_init(struct run_softc *sc)
+{
+	uint32_t tmp;
+	uint8_t rf;
+	int i;
+
+	/* Disable the GPIO bits 4 and 7 for LNA PE control. */
+	run_read(sc, RT3070_GPIO_SWITCH, &tmp);
+	tmp &= ~(1 << 4 | 1 << 7);
+	run_write(sc, RT3070_GPIO_SWITCH, tmp);
+
+	/* Initialize RF registers to default value. */
+	for (i = 0; i < __arraycount(rt3593_def_rf); i++) {
+		run_rt3070_rf_write(sc, rt3593_def_rf[i].reg,
+			rt3593_def_rf[i].val);
+	}
+
+	/* Toggle RF R2 to initiate calibration. */
+	run_rt3070_rf_write(sc, 2, RT5390_RESCAL);
+
+	/* Initialize RF frequency offset. */
+	run_adjust_freq_offset(sc);
+
+	run_rt3070_rf_read(sc, 18, &rf);
+	run_rt3070_rf_write(sc, 18, rf | RT3593_AUTOTUNE_BYPASS);
+
+	/*
+	 * Increase voltage from 1.2V to 1.35V, wait for 1 msec to
+	 * decrease voltage back to 1.2V.
+	 */
+	run_read(sc, RT3070_LDO_CFG0, &tmp);
+	tmp = (tmp & ~0x1f000000) | 0x0d000000;
+	run_write(sc, RT3070_LDO_CFG0, tmp);
+	usbd_delay_ms(sc->sc_udev, 1);
+	tmp = (tmp & ~0x1f000000) | 0x01000000;
+	run_write(sc, RT3070_LDO_CFG0, tmp);
+
+	sc->rf24_20mhz = 0x1f;
+	sc->rf24_40mhz = 0x2f;
+
+	/* Save default BBP registers 25 and 26 values. */
+	run_bbp_read(sc, 25, &sc->bbp25);
+	run_bbp_read(sc, 26, &sc->bbp26);
+
+	run_read(sc, RT3070_OPT_14, &tmp);
+	run_write(sc, RT3070_OPT_14, tmp | 1);
+	return (0);
+}
+
+static int
+run_rt5390_rf_init(struct run_softc *sc)
+{
+	uint32_t tmp;
+	uint8_t rf;
+	int i;
+
+	/* Toggle RF R2 to initiate calibration. */
+	if (sc->mac_ver == 0x5390) {
+		run_rt3070_rf_read(sc, 2, &rf);
+		run_rt3070_rf_write(sc, 2, rf | RT5390_RESCAL);
+		usbd_delay_ms(sc->sc_udev, 10);
+		run_rt3070_rf_write(sc, 2, rf & ~RT5390_RESCAL);
+	} else {
+		run_rt3070_rf_write(sc, 2, RT5390_RESCAL);
+		usbd_delay_ms(sc->sc_udev, 10);
+	}
+
+	/* Initialize RF registers to default value. */
+	if (sc->mac_ver == 0x5592) {
+		for (i = 0; i < __arraycount(rt5592_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5592_def_rf[i].reg,
+			    rt5592_def_rf[i].val);
+		}
+		/* Initialize RF frequency offset. */
+		run_adjust_freq_offset(sc);
+	} else if (sc->mac_ver == 0x5392) {
+		for (i = 0; i < __arraycount(rt5392_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5392_def_rf[i].reg,
+			    rt5392_def_rf[i].val);
+		}
+		if (sc->mac_rev >= 0x0223) {
+			run_rt3070_rf_write(sc, 23, 0x0f);
+			run_rt3070_rf_write(sc, 24, 0x3e);
+			run_rt3070_rf_write(sc, 51, 0x32);
+			run_rt3070_rf_write(sc, 53, 0x22);
+			run_rt3070_rf_write(sc, 56, 0xc1);
+			run_rt3070_rf_write(sc, 59, 0x0f);
+		}
+	} else {
+		for (i = 0; i < __arraycount(rt5390_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5390_def_rf[i].reg,
+			    rt5390_def_rf[i].val);
+		}
+		if (sc->mac_rev >= 0x0502) {
+			run_rt3070_rf_write(sc, 6, 0xe0);
+			run_rt3070_rf_write(sc, 25, 0x80);
+			run_rt3070_rf_write(sc, 46, 0x73);
+			run_rt3070_rf_write(sc, 53, 0x00);
+			run_rt3070_rf_write(sc, 56, 0x42);
+			run_rt3070_rf_write(sc, 61, 0xd1);
+		}
+	}
+
+	sc->rf24_20mhz = 0x1f;  /* default value */
+	sc->rf24_40mhz = (sc->mac_ver == 0x5592) ? 0 : 0x2f;
+
+	if (sc->mac_rev < 0x0211)
+		run_rt3070_rf_write(sc, 27, 0x3);
+
+	run_read(sc, RT3070_OPT_14, &tmp);
+	run_write(sc, RT3070_OPT_14, tmp | 1);
+	return (0);
+}
+
+static int
 run_rt3070_filter_calib(struct run_softc *sc, uint8_t init, uint8_t target,
     uint8_t *val)
 {
@@ -3249,7 +4183,7 @@ run_rt3070_filter_calib(struct run_softc
 	for (ntries = 0; ntries < 100; ntries++) {
 		/* transmit test tone */
 		run_bbp_write(sc, 25, 0x90);
-		DELAY(1000);
+		usbd_delay_ms(sc->sc_udev, 10);
 		/* read received power */
 		run_bbp_read(sc, 55, &bbp55_pb);
 		if (bbp55_pb != 0)
@@ -3263,7 +4197,7 @@ run_rt3070_filter_calib(struct run_softc
 	for (ntries = 0; ntries < 100; ntries++) {
 		/* transmit test tone */
 		run_bbp_write(sc, 25, 0x90);
-		DELAY(1000);
+		usbd_delay_ms(sc->sc_udev, 10);
 		/* read received power */
 		run_bbp_read(sc, 55, &bbp55_sb);
 
@@ -3370,6 +4304,123 @@ run_rt3070_rf_setup(struct run_softc *sc
 	}
 }
 
+static void     
+run_rt3593_rf_setup(struct run_softc *sc)
+{
+	uint8_t bbp, rf;
+
+	if (sc->mac_rev >= 0x0211) {
+		/* Enable DC filter. */
+		run_bbp_write(sc, 103, 0xc0); 
+	}
+	run_write(sc, RT2860_TX_SW_CFG1, 0);
+	if (sc->mac_rev < 0x0211) {
+		run_write(sc, RT2860_TX_SW_CFG2,
+		    sc->patch_dac ? 0x2c : 0x0f);
+	} else
+		run_write(sc, RT2860_TX_SW_CFG2, 0);
+	
+	run_rt3070_rf_read(sc, 50, &rf);
+	run_rt3070_rf_write(sc, 50, rf & ~RT3593_TX_LO2);
+
+	run_rt3070_rf_read(sc, 51, &rf);
+	rf = (rf & ~(RT3593_TX_LO1 | 0x0c)) |
+	    ((sc->txmixgain_2ghz & 0x07) << 2); 
+	run_rt3070_rf_write(sc, 51, rf);
+	
+	run_rt3070_rf_read(sc, 38, &rf);
+	run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1);
+	
+	run_rt3070_rf_read(sc, 39, &rf);
+	run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2);
+
+	run_rt3070_rf_read(sc, 1, &rf); 
+	run_rt3070_rf_write(sc, 1, rf & ~(RT3070_RF_BLOCK | RT3070_PLL_PD));
+
+	run_rt3070_rf_read(sc, 30, &rf);
+	rf = (rf & ~0x18) | 0x10;
+	run_rt3070_rf_write(sc, 30, rf);
+
+	/* Apply maximum likelihood detection for 2 stream case. */
+	run_bbp_read(sc, 105, &bbp);
+	if (sc->nrxchains > 1)
+		run_bbp_write(sc, 105, bbp | RT5390_MLD);
+	
+	/* Avoid data lost and CRC error. */
+	run_bbp_read(sc, 4, &bbp);
+	run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+	run_bbp_write(sc, 92, 0x02);
+	run_bbp_write(sc, 82, 0x82);
+	run_bbp_write(sc, 106, 0x05);
+	run_bbp_write(sc, 104, 0x92);
+	run_bbp_write(sc, 88, 0x90);
+	run_bbp_write(sc, 148, 0xc8);
+	run_bbp_write(sc, 47, 0x48);
+	run_bbp_write(sc, 120, 0x50);
+
+	run_bbp_write(sc, 163, 0x9d);
+
+	/* SNR mapping. */
+	run_bbp_write(sc, 142, 0x06);
+	run_bbp_write(sc, 143, 0xa0);
+	run_bbp_write(sc, 142, 0x07);
+	run_bbp_write(sc, 143, 0xa1);
+	run_bbp_write(sc, 142, 0x08);
+	run_bbp_write(sc, 143, 0xa2);
+
+	run_bbp_write(sc, 31, 0x08);
+	run_bbp_write(sc, 68, 0x0b);
+	run_bbp_write(sc, 105, 0x04);
+}
+
+static void
+run_rt5390_rf_setup(struct run_softc *sc)
+{
+	uint8_t bbp, rf;
+
+	if (sc->mac_rev >= 0x0211) {
+		/* Enable DC filter. */
+		run_bbp_write(sc, 103, 0xc0);
+
+		if (sc->mac_ver != 0x5592) {
+			/* Improve power consumption. */
+			run_bbp_read(sc, 31, &bbp);
+			run_bbp_write(sc, 31, bbp & ~0x03);
+		}
+	}
+
+	run_bbp_read(sc, 138, &bbp);
+	if (sc->ntxchains == 1)
+		bbp |= 0x20;    /* turn off DAC1 */
+	if (sc->nrxchains == 1)
+		bbp &= ~0x02;   /* turn off ADC1 */
+	run_bbp_write(sc, 138, bbp);
+
+	run_rt3070_rf_read(sc, 38, &rf);
+	run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1);
+
+	run_rt3070_rf_read(sc, 39, &rf);
+	run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2);
+
+	/* Avoid data lost and CRC error. */
+	run_bbp_read(sc, 4, &bbp);
+	run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+	run_rt3070_rf_read(sc, 30, &rf);
+	rf = (rf & ~0x18) | 0x10;
+	run_rt3070_rf_write(sc, 30, rf);
+
+	if (sc->mac_ver != 0x5592) {
+		run_write(sc, RT2860_TX_SW_CFG1, 0);
+		if (sc->mac_rev < 0x0211) {
+			run_write(sc, RT2860_TX_SW_CFG2,
+			    sc->patch_dac ? 0x2c : 0x0f);
+		} else
+			run_write(sc, RT2860_TX_SW_CFG2, 0);
+	}
+}
+
 static int
 run_txrx_enable(struct run_softc *sc)
 {
@@ -3382,12 +4433,12 @@ run_txrx_enable(struct run_softc *sc)
 			return error;
 		if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0)
 			break;
-		DELAY(1000);
+		usbd_delay_ms(sc->sc_udev, 50);
 	}
 	if (ntries == 200)
 		return ETIMEDOUT;
 
-	DELAY(50);
+	usbd_delay_ms(sc->sc_udev, 50);
 
 	tmp |= RT2860_RX_DMA_EN | RT2860_TX_DMA_EN | RT2860_TX_WB_DDONE;
 	run_write(sc, RT2860_WPDMA_GLO_CFG, tmp);
@@ -3416,6 +4467,22 @@ run_txrx_enable(struct run_softc *sc)
 }
 
 static int
+run_adjust_freq_offset(struct run_softc *sc)
+{
+	uint8_t rf, tmp;
+
+	run_rt3070_rf_read(sc, 17, &rf);
+	tmp = rf;
+	rf = (rf & ~0x7f) | (sc->freq & 0x7f);
+	rf = MIN(rf, 0x5f);
+
+	if (tmp != rf)
+		run_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf);
+
+	return (0);
+}
+
+static int
 run_init(struct ifnet *ifp)
 {
 	struct run_softc *sc = ifp->if_softc;
@@ -3429,7 +4496,7 @@ run_init(struct ifnet *ifp)
 			goto fail;
 		if (tmp != 0 && tmp != 0xffffffff)
 			break;
-		DELAY(10);
+		usbd_delay_ms(sc->sc_udev, 10);
 	}
 	if (ntries == 100) {
 		error = ETIMEDOUT;
@@ -3466,7 +4533,7 @@ run_init(struct ifnet *ifp)
 			goto fail;
 		if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0)
 			break;
-		DELAY(1000);
+		usbd_delay_ms(sc->sc_udev, 10);
 	}
 	if (ntries == 100) {
 		aprint_error_dev(sc->sc_dev,
@@ -3506,7 +4573,23 @@ run_init(struct ifnet *ifp)
 	run_write(sc, RT2860_WMM_CWMIN_CFG, 0x00002344);
 	run_write(sc, RT2860_WMM_CWMAX_CFG, 0x000034aa);
 
-	if (sc->mac_ver >= 0x3070) {
+	if (sc->mac_ver >= 0x5390) {
+		run_write(sc, RT2860_TX_SW_CFG0,
+		    4 << RT2860_DLY_PAPE_EN_SHIFT | 4);
+		if (sc->mac_ver >= 0x5392) {
+			run_write(sc, RT2860_MAX_LEN_CFG, 0x00002fff);
+			if (sc->mac_ver == 0x5592) {
+				run_write(sc, RT2860_HT_FBK_CFG1, 0xedcba980);
+				run_write(sc, RT2860_TXOP_HLDR_ET, 0x00000082);
+			} else {
+				run_write(sc, RT2860_HT_FBK_CFG1, 0xedcb4980);
+				run_write(sc, RT2860_LG_FBK_CFG0, 0xedcba322);
+			}
+		}
+	} else if (sc->mac_ver >= 0x3593) {
+		run_write(sc, RT2860_TX_SW_CFG0,
+		    4 << RT2860_DLY_PAPE_EN_SHIFT | 2);
+	} else if (sc->mac_ver >= 0x3070) {
 		/* set delay of PA_PE assertion to 1us (unit of 0.25us) */
 		run_write(sc, RT2860_TX_SW_CFG0,
 		    4 << RT2860_DLY_PAPE_EN_SHIFT);
@@ -3528,13 +4611,14 @@ run_init(struct ifnet *ifp)
 	/* clear Host to MCU mailbox */
 	run_write(sc, RT2860_H2M_BBPAGENT, 0);
 	run_write(sc, RT2860_H2M_MAILBOX, 0);
-	DELAY(1000);
+	usbd_delay_ms(sc->sc_udev, 10);
 
 	if ((error = run_bbp_init(sc)) != 0) {
 		aprint_error_dev(sc->sc_dev, "could not initialize BBP\n");
 		goto fail;
 	}
 
+	/* abort TSF synchronization */
 	run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
 	tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
 	    RT2860_TBTT_TIMER_EN);
@@ -3553,6 +4637,11 @@ run_init(struct ifnet *ifp)
 	/* clear shared key mode */
 	run_set_region_4(sc, RT2860_SKEY_MODE_0_7, 0, 4);
 
+	/* clear RX WCID search table */
+	run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512);
+	/* clear WCID attribute table */
+	run_set_region_4(sc, RT2860_WCID_ATTR(0), 0, 8 * 32);
+
 	run_read(sc, RT2860_US_CYC_CNT, &tmp);
 	tmp = (tmp & ~0xff) | 0x1e;
 	run_write(sc, RT2860_US_CYC_CNT, tmp);
@@ -3564,14 +4653,16 @@ run_init(struct ifnet *ifp)
 	run_write(sc, RT2860_WMM_TXOP1_CFG, 48 << 16 | 96);
 
 	/* write vendor-specific BBP values (from EEPROM) */
-	for (i = 0; i < 8; i++) {
-		if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff)
-			continue;
-		run_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val);
+	if (sc->mac_ver < 0x3593) {
+		for (i = 0; i < 10; i++) {
+			if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff)
+				continue;
+			run_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val);
+		}
 	}
 
 	/* select Main antenna for 1T1R devices */
-	if (sc->rf_rev == RT3070_RF_3020)
+	if (sc->rf_rev == RT3070_RF_3020 || sc->rf_rev == RT5390_RF_5370)
 		run_set_rx_antenna(sc, 0);
 
 	/* send LEDs operating mode to microcontroller */
@@ -3579,7 +4670,11 @@ run_init(struct ifnet *ifp)
 	(void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1]);
 	(void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2]);
 
-	if (sc->mac_ver >= 0x3070)
+	if (sc->mac_ver >= 0x5390)
+		run_rt5390_rf_init(sc);
+	else if (sc->mac_ver == 0x3593)
+		run_rt3593_rf_init(sc);
+	else if (sc->mac_ver >= 0x3070)
 		run_rt3070_rf_init(sc);
 
 	/* disable non-existing Rx chains */
@@ -3597,12 +4692,19 @@ run_init(struct ifnet *ifp)
 		bbp1 &= ~(1 << 3 | 1 << 4);
 	run_bbp_write(sc, 1, bbp1);
 
-	if (sc->mac_ver >= 0x3070)
+	if (sc->mac_ver >= 0x5390)
+		run_rt5390_rf_setup(sc);
+	else if (sc->mac_ver == 0x3593)
+		run_rt3593_rf_setup(sc);
+	else if (sc->mac_ver >= 0x3070)
 		run_rt3070_rf_setup(sc);
 
 	/* select default channel */
 	run_set_chan(sc, ic->ic_curchan);
 
+	/* setup initial protection mode */
+	run_updateprot(sc);
+
 	/* turn radio LED on */
 	run_set_leds(sc, RT2860_LED_RADIO);
 
@@ -3698,6 +4800,7 @@ run_setup_beacon(struct run_softc *sc)
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct rt2860_txwi txwi;
 	struct mbuf *m;
+	uint16_t txwisize;
 	int ridx;
 
 	if ((m = ieee80211_beacon_alloc(ic, ic->ic_bss, &sc->sc_bo)) == NULL)
@@ -3715,10 +4818,12 @@ run_setup_beacon(struct run_softc *sc)
 	txwi.txop = RT2860_TX_TXOP_HT;
 	txwi.flags = RT2860_TX_TS;
 
+	txwisize = (sc->mac_ver == 0x5592) ?
+	    sizeof(txwi) + sizeof(uint32_t) : sizeof(txwi);
 	run_write_region_1(sc, RT2860_BCN_BASE(0),
-	    (uint8_t *)&txwi, sizeof(txwi));
-	run_write_region_1(sc, RT2860_BCN_BASE(0) + sizeof(txwi),
-	    mtod(m, uint8_t *), m->m_pkthdr.len);
+	    (uint8_t *)&txwi, txwisize);
+	run_write_region_1(sc, RT2860_BCN_BASE(0) + txwisize,
+	    mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1);
 
 	m_freem(m);
 

Index: src/sys/dev/usb/if_runvar.h
diff -u src/sys/dev/usb/if_runvar.h:1.2 src/sys/dev/usb/if_runvar.h:1.3
--- src/sys/dev/usb/if_runvar.h:1.2	Sat Apr 23 10:15:31 2016
+++ src/sys/dev/usb/if_runvar.h	Fri Sep 16 09:25:30 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_runvar.h,v 1.2 2016/04/23 10:15:31 skrll Exp $	*/
+/*	$NetBSD: if_runvar.h,v 1.3 2016/09/16 09:25:30 mlelstv Exp $	*/
 /*	$OpenBSD: if_runvar.h,v 1.8 2010/02/08 18:46:47 damien Exp $	*/
 
 /*-
@@ -147,7 +147,7 @@ struct run_softc {
 
 	uint16_t			mac_ver;
 	uint16_t			mac_rev;
-	uint8_t				rf_rev;
+	uint16_t			rf_rev;
 	uint8_t				freq;
 	uint8_t				ntxchains;
 	uint8_t				nrxchains;
@@ -167,6 +167,7 @@ struct run_softc {
 	uint8_t				txmixgain_5ghz;
 	int8_t				txpow1[54];
 	int8_t				txpow2[54];
+	int8_t				txpow3[54];
 	int8_t				rssi_2ghz[3];
 	int8_t				rssi_5ghz[3];
 	uint8_t				lna[4];

Index: src/sys/net80211/ieee80211.h
diff -u src/sys/net80211/ieee80211.h:1.27 src/sys/net80211/ieee80211.h:1.28
--- src/sys/net80211/ieee80211.h:1.27	Wed Apr 27 20:17:00 2016
+++ src/sys/net80211/ieee80211.h	Fri Sep 16 09:25:30 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ieee80211.h,v 1.27 2016/04/27 20:17:00 christos Exp $	*/
+/*	$NetBSD: ieee80211.h,v 1.28 2016/09/16 09:25:30 mlelstv Exp $	*/
 /*-
  * Copyright (c) 2001 Atsushi Onoe
  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
@@ -181,6 +181,9 @@ struct ieee80211_qosframe_addr4 {
 #define	IEEE80211_FC1_DIR_FROMDS		0x02	/* AP ->STA */
 #define	IEEE80211_FC1_DIR_DSTODS		0x03	/* AP ->AP  */
 
+#define IEEE80211_IS_DSTODS(wh) \
+	(((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
+
 #define	IEEE80211_FC1_MORE_FRAG			0x04
 #define	IEEE80211_FC1_RETRY			0x08
 #define	IEEE80211_FC1_PWR_MGT			0x10
@@ -213,6 +216,12 @@ struct ieee80211_qosframe_addr4 {
 #define	IEEE80211_QOS_ESOP_S			4
 #define	IEEE80211_QOS_TID			0x000f
 
+/* does frame have QoS sequence control data */
+#define IEEE80211_QOS_HAS_SEQ(wh) \
+	(((wh)->i_fc[0] & \
+	    (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == \
+	    (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
+
 /*
  * WME/802.11e information element.
  */

Reply via email to