git: 9front

Download patch

ref: 724696463f55333ccc3f5af3bb71dac7106c66d0
parent: 287b1bd53d13ef56fc68170ff1a09a3d38a9fdd8
author: ppatience0 <ppatience0@gmail.com>
date: Sun Jul 21 14:13:27 EDT 2013

etherrt2860: add rt3090 support and make style more consistent

--- a/sys/src/9/pc/etherrt2860.c
+++ b/sys/src/9/pc/etherrt2860.c
@@ -783,6 +783,33 @@
 	Rf3053 = 13 /* dual-band 3T3R */,
 };
 
+enum {	
+	Rt3070RfBlock = (1 << 0),
+	Rt3070Rx0Pd = (1 << 2),
+	Rt3070Tx0Pd = (1 << 3),
+	Rt3070Rx1Pd = (1 << 4),
+	Rt3070Tx1Pd = (1 << 5),
+	Rt3070Rx2Pd = (1 << 6),
+	Rt3070Tx2Pd = (1 << 7),
+	Rt3070Tune = (1 << 0),
+	Rt3070TxLo2 = (1 << 3),
+	Rt3070TxLo1 = (1 << 3),
+	Rt3070RxLo1 = (1 << 3),
+	Rt3070RxLo2 = (1 << 3),
+	Rt3070RxCtb = (1 << 7),
+	Rt3070BbLoopback = (1 << 0),
+
+	Rt3593Vco = (1 << 0),
+	Rt3593Rescal = (1 << 7),
+	Rt3593Vcocal = (1 << 7),
+	Rt3593VcoIc = (1 << 6),
+	Rt3593LdoPllVcMask = 0x0e,
+	Rt3593LdoRfVcMask = 0xe0,
+	Rt3593CpIcMask = 0xe0,
+	Rt3593CpIcShift = 5,
+	Rt3593RxCtb = (1 << 5)
+};
+
 static const char* rfnames[] = {
 	[Rf2820] "RT2820",
 	[Rf2850] "RT2850",
@@ -976,7 +1003,6 @@
 	ConnPciE   = 1 << 1,
 };
 
-
 static const struct rt2860_rate {
 	u8int		rate;
 	u8int		mcs;
@@ -1122,6 +1148,91 @@
 	{ 173, 0x100bb1, 0x1300f5, 0x05e014, 0x001403 },
 };
 
+struct {
+	u8int n;
+	u8int r;
+	u8int k;
+} rt3090_freqs[] = {
+	{ 0xf1, 2,  2 },
+	{ 0xf1, 2,  7 },
+	{ 0xf2, 2,  2 },
+	{ 0xf2, 2,  7 },
+	{ 0xf3, 2,  2 },
+	{ 0xf3, 2,  7 },
+	{ 0xf4, 2,  2 },
+	{ 0xf4, 2,  7 },
+	{ 0xf5, 2,  2 },
+	{ 0xf5, 2,  7 },
+	{ 0xf6, 2,  2 },
+	{ 0xf6, 2,  7 },
+	{ 0xf7, 2,  2 },
+	{ 0xf8, 2,  4 },
+	{ 0x56, 0,  4 },
+	{ 0x56, 0,  6 },
+	{ 0x56, 0,  8 },
+	{ 0x57, 0,  0 },
+	{ 0x57, 0,  2 },
+	{ 0x57, 0,  4 },
+	{ 0x57, 0,  8 },
+	{ 0x57, 0, 10 },
+	{ 0x58, 0,  0 },
+	{ 0x58, 0,  4 },
+	{ 0x58, 0,  6 },
+	{ 0x58, 0,  8 },
+	{ 0x5b, 0,  8 },
+	{ 0x5b, 0, 10 },
+	{ 0x5c, 0,  0 },
+	{ 0x5c, 0,  4 },
+	{ 0x5c, 0,  6 },
+	{ 0x5c, 0,  8 },
+	{ 0x5d, 0,  0 },
+	{ 0x5d, 0,  2 },
+	{ 0x5d, 0,  4 },
+	{ 0x5d, 0,  8 },
+	{ 0x5d, 0, 10 },
+	{ 0x5e, 0,  0 },
+	{ 0x5e, 0,  4 },
+	{ 0x5e, 0,  6 },
+	{ 0x5e, 0,  8 },
+	{ 0x5f, 0,  0 },
+	{ 0x5f, 0,  9 },
+	{ 0x5f, 0, 11 },
+	{ 0x60, 0,  1 },
+	{ 0x60, 0,  5 },
+	{ 0x60, 0,  7 },
+	{ 0x60, 0,  9 },
+	{ 0x61, 0,  1 },
+	{ 0x61, 0,  3 },
+	{ 0x61, 0,  5 },
+	{ 0x61, 0,  7 },
+	{ 0x61, 0,  9 }
+};
+
+static const struct {
+	u8int reg;
+	u8int val;
+} rt3090_def_rf[] = {
+	{  4, 0x40 },
+	{  5, 0x03 },
+	{  6, 0x02 },
+	{  7, 0x70 },
+	{  9, 0x0f },
+	{ 10, 0x41 },
+	{ 11, 0x21 },
+	{ 12, 0x7b },
+	{ 14, 0x90 },
+	{ 15, 0x58 },
+	{ 16, 0xb3 },
+	{ 17, 0x92 },
+	{ 18, 0x2c },
+	{ 19, 0x02 },
+	{ 20, 0xba },
+	{ 21, 0xdb },
+	{ 24, 0x16 },
+	{ 25, 0x01 },
+	{ 29, 0x1f }
+};
+
 /* vendors */
 enum {
 	Ralink = 0x1814,
@@ -1131,6 +1242,7 @@
 enum {
 	RalinkRT2890 = 0x0681,
 	RalinkRT2790 = 0x0781,
+	RalinkRT3090 = 0x3090,
 	AwtRT2890 = 0x1059,
 };
 
@@ -1139,6 +1251,7 @@
 
 static int rbplant(Ctlr*, int);
 static void setchan(Ctlr*, uint);
+static void rt3090setchan(Ctlr*, uint);
 static void selchangroup(Ctlr*, int);
 static void setleds(Ctlr*, u16int);
 
@@ -1242,7 +1355,10 @@
 			edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, ctlr->wcid);
 
 	/* Set channel */
-	setchan(ctlr, ctlr->channel);
+	if(ctlr->mac_ver >= 0x3071)
+		rt3090setchan(ctlr, ctlr->channel);
+	else
+		setchan(ctlr, ctlr->channel);
 	selchangroup(ctlr, 0);
 	microdelay(1000);
 
@@ -1275,7 +1391,7 @@
 	/* set TX preamble */
 	tmp = csr32r(ctlr, AutoRspCfg);
 	tmp &= ~CckShortEn;
-/*	if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
+/*	if(sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
 		tmp |= CckShortEn; */
 	csr32w(ctlr, AutoRspCfg, tmp);
 
@@ -1330,7 +1446,7 @@
 		snprint(buf, sizeof buf, "/boot/%s", name);
 		c = namec(buf, Aopen, OREAD, 0);
 		poperror();
-	} else {
+	}else{
 		snprint(buf, sizeof buf, "/lib/firmware/%s", name);
 		c = namec(buf, Aopen, OREAD, 0);
 	}
@@ -1382,11 +1498,11 @@
 	/* wait until microcontroller is ready */
 	coherence();
 	for(ntries = 0; ntries < 1000; ntries++){
-		if (csr32r(ctlr, SysCtrl) & McuReady)
+		if(csr32r(ctlr, SysCtrl) & McuReady)
 			break;
 		microdelay(1000);
 	}
-	if (ntries == 1000)
+	if(ntries == 1000)
 		return "timeout waiting for MCU to initialize";
 	return 0;
 }
@@ -1422,7 +1538,7 @@
 		tmp = csr32r(ctlr, H2mMailboxCid);
 		/* find the command slot */
 		for(slot = 0; slot < 4; slot++, tmp >>= 8)
-			if ((tmp & 0xff) == cid)
+			if((tmp & 0xff) == cid)
 				break;
 		if(slot < 4)
 			break;
@@ -1515,7 +1631,7 @@
 	/* wait for BBP to wake up */
 	for(ntries = 0; ntries < 20; ntries++){
 		u8int bbp0 = bbpread(ctlr, 0);
-		if (bbp0 != 0 && bbp0 != 0xff)
+		if(bbp0 != 0 && bbp0 != 0xff)
 			break;
 	}
 	if(ntries == 20){
@@ -1600,7 +1716,7 @@
 /*
  * Write to one of the 4 programmable 24-bit RF registers.
  */
-static char*
+static void
 rfwrite(Ctlr *ctlr, u8int reg, u32int val)
 {
 	u32int tmp;
@@ -1607,21 +1723,73 @@
 	int ntries;
 
 	for(ntries = 0; ntries < 100; ntries++){
-		if (!(csr32r(ctlr, RfCsrCfg0) & RfRegCtrl))
+		if(!(csr32r(ctlr, RfCsrCfg0) & RfRegCtrl))
 			break;
 		microdelay(1);
 	}
-	if(ntries == 100)
-		return "could not write to RF";
+	if(ntries == 100){
+		print("could not write to RF\n");
+		return;
+	}
 
 	/* RF registers are 24-bit on the RT2860 */
 	tmp = RfRegCtrl | 24 << RfRegWidthShift |
 	    (val & 0x3fffff) << 2 | (reg & 3);
 	csr32w(ctlr, RfCsrCfg0, tmp);
-	return nil;
 }
 
+u8int
+rt3090rfread(Ctlr *ctlr, u8int reg)
+{
+	u32int tmp;
+	int ntries;
+
+	for(ntries = 0; ntries < 100; ntries++){
+		if(!(csr32r(ctlr, Rt3070RfCsrCfg) & Rt3070RfKick))
+			break;
+		microdelay(1);
+	}
+	if(ntries == 100){
+		print("could not read RF register\n");
+		return 0xff;
+	}
+	tmp = Rt3070RfKick | reg << 8;
+	csr32w(ctlr, Rt3070RfCsrCfg, tmp);
+
+	for(ntries = 0; ntries < 100; ntries++){
+		tmp = csr32r(ctlr, Rt3070RfCsrCfg);
+		if(!(tmp & Rt3070RfKick))
+			break;
+		microdelay(1);
+	}
+	if(ntries == 100){
+		print("could not read RF register\n");
+		return 0xff;
+	}
+	return tmp & 0xff;
+}
+
 static void
+rt3090rfwrite(Ctlr *ctlr, u8int reg, u8int val)
+{
+	u32int tmp;
+	int ntries;
+
+	for(ntries = 0; ntries < 10; ntries++){
+		if(!(csr32r(ctlr, Rt3070RfCsrCfg) & Rt3070RfKick))
+			break;
+		microdelay(10);
+	}
+	if(ntries == 10){
+		print("could not write to RF\n");
+		return;
+	}
+
+	tmp = Rt3070RfWrite | Rt3070RfKick | reg << 8 | val;
+	csr32w(ctlr, Rt3070RfCsrCfg, tmp);
+}
+
+static void
 selchangroup(Ctlr *ctlr, int group)
 {
 	u32int tmp;
@@ -1632,7 +1800,7 @@
 	bbpwrite(ctlr, 64, 0x37 - ctlr->lna[group]);
 	bbpwrite(ctlr, 86, 0x00);
 
-	if (group == 0){
+	if(group == 0){
 		if(ctlr->ext_2ghz_lna){
 			bbpwrite(ctlr, 82, 0x62);
 			bbpwrite(ctlr, 75, 0x46);
@@ -1641,7 +1809,7 @@
 			bbpwrite(ctlr, 75, 0x50);
 		}
 	}else{
-		if (ctlr->ext_5ghz_lna){
+		if(ctlr->ext_5ghz_lna){
 			bbpwrite(ctlr, 82, 0xf2);
 			bbpwrite(ctlr, 75, 0x46);
 		}else{
@@ -1676,9 +1844,9 @@
 	}
 	csr32w(ctlr, TxPinCfg, tmp);
 
-	if(ctlr->mac_ver == 0x3593) {
+	if(ctlr->mac_ver == 0x3593){
 		tmp = csr32r(ctlr, GpioCtrl);
-		if(ctlr->flags & ConnPciE) {
+		if(ctlr->flags & ConnPciE){
 			tmp &= ~0x01010000;
 			if(group == 0)
 				tmp |= 0x00010000;
@@ -1715,7 +1883,7 @@
 	uint i;
 
 	/* find the settings for this channel (we know it exists) */
-	for (i = 0; rfprog[i].chan != chan; i++);
+	for(i = 0; rfprog[i].chan != chan; i++);
 
 	r2 = rfprog[i].r2;
 	if(ctlr->ntxchains == 1)
@@ -1729,11 +1897,11 @@
 	txpow1 = ctlr->txpow1[i];
 	txpow2 = ctlr->txpow2[i];
 	if(chan > 14){
-		if (txpow1 >= 0)
+		if(txpow1 >= 0)
 			txpow1 = txpow1 << 1 | 1;
 		else
 			txpow1 = (7 + txpow1) << 1;
-		if (txpow2 >= 0)
+		if(txpow2 >= 0)
 			txpow2 = txpow2 << 1 | 1;
 		else
 			txpow2 = (7 + txpow2) << 1;
@@ -1762,6 +1930,356 @@
 }
 
 static void
+rt3090setchan(Ctlr *ctlr, uint chan)
+{
+	s8int txpow1, txpow2;
+	u8int rf;
+	int i;
+
+	assert(chan >= 1 && chan <= 14);	/* RT3090 is 2GHz only */
+
+	/* 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 = ctlr->txpow1[i];
+	txpow2 = ctlr->txpow2[i];
+
+	rt3090rfwrite(ctlr, 2, rt3090_freqs[i].n);
+	rf = rt3090rfread(ctlr, 3);
+	rf = (rf & ~0x0f) | rt3090_freqs[i].k;
+	rt3090rfwrite(ctlr, 3, rf);
+	rf = rt3090rfread(ctlr, 6);
+	rf = (rf & ~0x03) | rt3090_freqs[i].r;
+	rt3090rfwrite(ctlr, 6, rf);
+
+	/* set Tx0 power */
+	rf = rt3090rfread(ctlr, 12);
+	rf = (rf & ~0x1f) | txpow1;
+	rt3090rfwrite(ctlr, 12, rf);
+
+	/* set Tx1 power */
+	rf = rt3090rfread(ctlr, 13);
+	rf = (rf & ~0x1f) | txpow2;
+	rt3090rfwrite(ctlr, 13, rf);
+
+	rf = rt3090rfread(ctlr, 1);
+	rf &= ~0xfc;
+	if(ctlr->ntxchains == 1)
+		rf |= Rt3070Tx1Pd | Rt3070Tx2Pd;
+	else if(ctlr->ntxchains == 2)
+		rf |= Rt3070Tx2Pd;
+	if(ctlr->nrxchains == 1)
+		rf |= Rt3070Rx1Pd | Rt3070Rx2Pd;
+	else if(ctlr->nrxchains == 2)
+		rf |= Rt3070Rx2Pd;
+	rt3090rfwrite(ctlr, 1, rf);
+
+	/* set RF offset */
+	rf = rt3090rfread(ctlr, 23);
+	rf = (rf & ~0x7f) | ctlr->freq;
+	rt3090rfwrite(ctlr, 23, rf);
+
+	/* program RF filter */
+	rf = rt3090rfread(ctlr, 24);	/* Tx */
+	rf = (rf & ~0x3f) | ctlr->rf24_20mhz;
+	rt3090rfwrite(ctlr, 24, rf);
+	rf = rt3090rfread(ctlr, 31);	/* Rx */
+	rf = (rf & ~0x3f) | ctlr->rf24_20mhz;
+	rt3090rfwrite(ctlr, 31, rf);
+
+	/* enable RF tuning */
+	rf = rt3090rfread(ctlr, 7);
+	rt3090rfwrite(ctlr, 7, rf | Rt3070Tune);
+}
+
+static int
+rt3090filtercalib(Ctlr *ctlr, u8int init, u8int target, u8int *val)
+{
+	u8int rf22, rf24;
+	u8int bbp55_pb, bbp55_sb, delta;
+	int ntries;
+
+	/* program filter */
+	rf24 = rt3090rfread(ctlr, 24);
+	rf24 = (rf24 & 0xc0) | init;	/* initial filter value */
+	rt3090rfwrite(ctlr, 24, rf24);
+
+	/* enable baseband loopback mode */
+	rf22 = rt3090rfread(ctlr, 22);
+	rt3090rfwrite(ctlr, 22, rf22 | Rt3070BbLoopback);
+
+	/* set power and frequency of passband test tone */
+	bbpwrite(ctlr, 24, 0x00);
+	for(ntries = 0, bbp55_pb = 0; ntries < 100; ntries++){
+		/* transmit test tone */
+		bbpwrite(ctlr, 25, 0x90);
+		microdelay(1000);
+		/* read received power */
+		bbp55_pb = bbpread(ctlr, 55);
+		if(bbp55_pb != 0)
+			break;
+	}
+	if(ntries == 100)
+		return -1;
+
+	/* set power and frequency of stopband test tone */
+	bbpwrite(ctlr, 24, 0x06);
+	for(ntries = 0; ntries < 100; ntries++){
+		/* transmit test tone */
+		bbpwrite(ctlr, 25, 0x90);
+		microdelay(1000);
+		/* read received power */
+		bbp55_sb = bbpread(ctlr, 55);
+
+		delta = bbp55_pb - bbp55_sb;
+		if(delta > target)
+			break;
+
+		/* reprogram filter */
+		rf24++;
+		rt3090rfwrite(ctlr, 24, rf24);
+	}
+	if(ntries < 100){
+		if(rf24 != init)
+			rf24--;	/* backtrack */
+		*val = rf24;
+		rt3090rfwrite(ctlr, 24, rf24);
+	}
+
+	/* restore initial state */
+	bbpwrite(ctlr, 24, 0x00);
+
+	/* disable baseband loopback mode */
+	rf22 = rt3090rfread(ctlr, 22);
+	rt3090rfwrite(ctlr, 22, rf22 & ~Rt3070BbLoopback);
+
+	return 0;
+}
+
+static void
+rt3090setrxantenna(Ctlr *ctlr, int aux)
+{
+	u32int tmp;
+
+	if(aux){
+		tmp = csr32r(ctlr, PciEectrl);
+		csr32w(ctlr, PciEectrl, tmp & ~EectrlC);
+		tmp = csr32r(ctlr, GpioCtrl);
+		csr32w(ctlr, GpioCtrl, (tmp & ~0x0808) | 0x08);
+	}else{
+		tmp = csr32r(ctlr, PciEectrl);
+		csr32w(ctlr, PciEectrl, tmp | EectrlC);
+		tmp = csr32r(ctlr, GpioCtrl);
+		csr32w(ctlr, GpioCtrl, tmp & ~0x0808);
+	}
+}
+
+static int
+rt3090rfinit(Ctlr *ctlr)
+{
+	u32int tmp;
+	u8int rf, bbp;
+	int i;
+
+	rf = rt3090rfread(ctlr, 30);
+	/* toggle RF R30 bit 7 */
+	rt3090rfwrite(ctlr, 30, rf | 0x80);
+	microdelay(1000);
+	rt3090rfwrite(ctlr, 30, rf & ~0x80);
+
+	tmp = csr32r(ctlr, Rt3070LdoCfg0);
+	tmp &= ~0x1f000000;
+	if(ctlr->patch_dac && ctlr->mac_rev < 0x0211)
+		tmp |= 0x0d000000;	/* 1.35V */
+	else
+		tmp |= 0x01000000;	/* 1.2V */
+	csr32w(ctlr, Rt3070LdoCfg0, tmp);
+
+	/* patch LNA_PE_G1 */
+	tmp = csr32r(ctlr, Rt3070GpioSwitch);
+	csr32w(ctlr, Rt3070GpioSwitch, tmp & ~0x20);
+
+	/* initialize RF registers to default value */
+	for(i = 0; i < nelem(rt3090_def_rf); i++){
+		rt3090rfwrite(ctlr, rt3090_def_rf[i].reg,
+		    rt3090_def_rf[i].val);
+	}
+
+	/* select 20MHz bandwidth */
+	rt3090rfwrite(ctlr, 31, 0x14);
+
+	rf = rt3090rfread(ctlr, 6);
+	rt3090rfwrite(ctlr, 6, rf | 0x40);
+
+	if(ctlr->mac_ver != 0x3593){
+		/* calibrate filter for 20MHz bandwidth */
+		ctlr->rf24_20mhz = 0x1f;	/* default value */
+		rt3090filtercalib(ctlr, 0x07, 0x16, &ctlr->rf24_20mhz);
+
+		/* select 40MHz bandwidth */
+		bbp = bbpread(ctlr, 4);
+		bbpwrite(ctlr, 4, (bbp & ~0x08) | 0x10);
+		rf = rt3090rfread(ctlr, 31);
+		rt3090rfwrite(ctlr, 31, rf | 0x20);
+
+		/* calibrate filter for 40MHz bandwidth */
+		ctlr->rf24_40mhz = 0x2f;	/* default value */
+		rt3090filtercalib(ctlr, 0x27, 0x19, &ctlr->rf24_40mhz);
+
+		/* go back to 20MHz bandwidth */
+		bbp = bbpread(ctlr, 4);
+		bbpwrite(ctlr, 4, bbp & ~0x18);
+	}
+	if(ctlr->mac_rev < 0x0211)
+		rt3090rfwrite(ctlr, 27, 0x03);
+
+	tmp = csr32r(ctlr, Rt3070Opt14);
+	csr32w(ctlr, Rt3070Opt14, tmp | 1);
+
+	if(ctlr->rf_rev == Rf3020)
+		rt3090setrxantenna(ctlr, 0);
+
+	bbp = bbpread(ctlr, 138);
+	if(ctlr->mac_ver == 0x3593){
+		if(ctlr->ntxchains == 1)
+			bbp |= 0x60;	/* turn off DAC1 and DAC2 */
+		else if(ctlr->ntxchains == 2)
+			bbp |= 0x40;	/* turn off DAC2 */
+		if(ctlr->nrxchains == 1)
+			bbp &= ~0x06;	/* turn off ADC1 and ADC2 */
+		else if(ctlr->nrxchains == 2)
+			bbp &= ~0x04;	/* turn off ADC2 */
+	}else{
+		if(ctlr->ntxchains == 1)
+			bbp |= 0x20;	/* turn off DAC1 */
+		if(ctlr->nrxchains == 1)
+			bbp &= ~0x02;	/* turn off ADC1 */
+	}
+	bbpwrite(ctlr, 138, bbp);
+
+	rf = rt3090rfread(ctlr, 1);
+	rf &= ~(Rt3070Rx0Pd | Rt3070Tx0Pd);
+	rf |= Rt3070RfBlock | Rt3070Rx1Pd | Rt3070Tx1Pd;
+	rt3090rfwrite(ctlr, 1, rf);
+
+	rf = rt3090rfread(ctlr, 15);
+	rt3090rfwrite(ctlr, 15, rf & ~Rt3070TxLo2);
+
+	rf = rt3090rfread(ctlr, 17);
+	rf &= ~Rt3070TxLo1;
+	if(ctlr->mac_rev >= 0x0211 && !ctlr->ext_2ghz_lna)
+		rf |= 0x20;	/* fix for long range Rx issue */
+	if(ctlr->txmixgain_2ghz >= 2)
+		rf = (rf & ~0x7) | ctlr->txmixgain_2ghz;
+	rt3090rfwrite(ctlr, 17, rf);
+
+	rf = rt3090rfread(ctlr, 20);
+	rt3090rfwrite(ctlr, 20, rf & ~Rt3070RxLo1);
+
+	rf = rt3090rfread(ctlr, 21);
+	rt3090rfwrite(ctlr, 21, rf & ~Rt3070RxLo2);
+
+	return 0;
+}
+
+static void
+rt3090rfwakeup(Ctlr *ctlr)
+{
+	u32int tmp;
+	u8int rf;
+
+	if(ctlr->mac_ver == 0x3593){
+		/* enable VCO */
+		rf = rt3090rfread(ctlr, 1);
+		rt3090rfwrite(ctlr, 1, rf | Rt3593Vco);
+
+		/* initiate VCO calibration */
+		rf = rt3090rfread(ctlr, 3);
+		rt3090rfwrite(ctlr, 3, rf | Rt3593Vcocal);
+
+		/* enable VCO bias current control */
+		rf = rt3090rfread(ctlr, 6);
+		rt3090rfwrite(ctlr, 6, rf | Rt3593VcoIc);
+
+		/* initiate res calibration */
+		rf = rt3090rfread(ctlr, 2);
+		rt3090rfwrite(ctlr, 2, rf | Rt3593Rescal);
+
+		/* set reference current control to 0.33 mA */
+		rf = rt3090rfread(ctlr, 22);
+		rf &= ~Rt3593CpIcMask;
+		rf |= 1 << Rt3593CpIcShift;
+		rt3090rfwrite(ctlr, 22, rf);
+
+		/* enable RX CTB */
+		rf = rt3090rfread(ctlr, 46);
+		rt3090rfwrite(ctlr, 46, rf | Rt3593RxCtb);
+
+		rf = rt3090rfread(ctlr, 20);
+		rf &= ~(Rt3593LdoRfVcMask | Rt3593LdoPllVcMask);
+		rt3090rfwrite(ctlr, 20, rf);
+	}else{
+		/* enable RF block */
+		rf = rt3090rfread(ctlr, 1);
+		rt3090rfwrite(ctlr, 1, rf | Rt3070RfBlock);
+
+		/* enable VCO bias current control */
+		rf = rt3090rfread(ctlr, 7);
+		rt3090rfwrite(ctlr, 7, rf | 0x30);
+
+		rf = rt3090rfread(ctlr, 9);
+		rt3090rfwrite(ctlr, 9, rf | 0x0e);
+
+		/* enable RX CTB */
+		rf = rt3090rfread(ctlr, 21);
+		rt3090rfwrite(ctlr, 21, rf | Rt3070RxCtb);
+
+		/* fix Tx to Rx IQ glitch by raising RF voltage */
+		rf = rt3090rfread(ctlr, 27);
+		rf &= ~0x77;
+		if(ctlr->mac_rev < 0x0211)
+			rf |= 0x03;
+		rt3090rfwrite(ctlr, 27, rf);
+	}
+	if(ctlr->patch_dac && ctlr->mac_rev < 0x0211){
+		tmp = csr32r(ctlr, Rt3070LdoCfg0);
+		tmp = (tmp & ~0x1f000000) | 0x0d000000;
+		csr32w(ctlr, Rt3070LdoCfg0, tmp);
+	}
+}
+
+static void
+rt3090rfsetup(Ctlr *ctlr)
+{
+	u8int bbp;
+	int i;
+
+	if(ctlr->mac_rev >= 0x0211){
+		/* enable DC filter */
+		bbpwrite(ctlr, 103, 0xc0);
+
+		/* improve power consumption */
+		bbp = bbpread(ctlr, 31);
+		bbpwrite(ctlr, 31, bbp & ~0x03);
+	}
+
+	csr32w(ctlr, TxSwCfg1, 0);
+	if(ctlr->mac_rev < 0x0211){
+		csr32w(ctlr, TxSwCfg2,
+		    ctlr->patch_dac ? 0x2c : 0x0f);
+	}else
+		csr32w(ctlr, TxSwCfg2, 0);
+
+	/* initialize RF registers from ROM */
+	for(i = 0; i < 10; i++){
+		if(ctlr->rf[i].reg == 0 || ctlr->rf[i].reg == 0xff)
+			continue;
+		rt3090rfwrite(ctlr, ctlr->rf[i].reg, ctlr->rf[i].val);
+	}
+}
+
+static void
 updateprot(Ctlr *ctlr)
 {
 	u32int tmp;
@@ -1775,10 +2293,10 @@
 	/* CCK frames don't require protection */
 	csr32w(ctlr, CckProtCfg, tmp);
 /* XXX
-	if (ic->ic_flags & IEEE80211_F_USEPROT) {
-		if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
+	if(ic->ic_flags & IEEE80211_F_USEPROT){
+		if(ic->ic_protmode == IEEE80211_PROT_RTSCTS)
 			tmp |= ProtCtrlRtsCts;
-		else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
+		else if(ic->ic_protmode == IEEE80211_PROT_CTSONLY)
 			tmp |= ProtCtrlCts;
 	}
 	csr32w(ctlr, OfdmProtCfg, tmp); */
@@ -1818,18 +2336,18 @@
 
 	/* init Tx power for all Tx rates (from EEPROM) */
 	for(ridx = 0; ridx < 5; ridx++){
-		if (ctlr->txpow20mhz[ridx] == 0xffffffff)
+		if(ctlr->txpow20mhz[ridx] == 0xffffffff)
 			continue;
 		csr32w(ctlr, TxPwrCfg(ridx), ctlr->txpow20mhz[ridx]);
 	}
 
-	for (ntries = 0; ntries < 100; ntries++) {
+	for(ntries = 0; ntries < 100; ntries++){
 		tmp = csr32r(ctlr, WpdmaGloCfg);
-		if ((tmp & (TxDmaBusy | RxDmaBusy)) == 0)
+		if((tmp & (TxDmaBusy | RxDmaBusy)) == 0)
 			break;
 		microdelay(1000);
 	}
-	if (ntries == 100) {
+	if(ntries == 100){
 		err = "timeout waiting for DMA engine";
 		/*rt2860_stop(ifp, 1);*/
 		return err;
@@ -1869,7 +2387,7 @@
 
 	/* wait while MAC is busy */
 	for(ntries = 0; ntries < 100; ntries++){
-		if (!(csr32r(ctlr, MacStatusReg) &
+		if(!(csr32r(ctlr, MacStatusReg) &
 		    (RxStatusBusy | TxStatusBusy)))
 			break;
 		microdelay(1000);
@@ -1922,11 +2440,11 @@
 
 	for(ntries = 0; ntries < 100; ntries++){
 		tmp = csr32r(ctlr, WpdmaGloCfg);
-		if ((tmp & (TxDmaBusy | RxDmaBusy)) == 0)
+		if((tmp & (TxDmaBusy | RxDmaBusy)) == 0)
 			break;
 		microdelay(1000);
 	}
-	if (ntries == 100) {
+	if(ntries == 100){
 		err = "timeout waiting for DMA engine";
 		/*rt2860_stop(ifp, 1);*/
 		return err;
@@ -1938,19 +2456,17 @@
 	csr32w(ctlr, DelayIntCfg, 0);
 
 	/* write vendor-specific BBP values (from EEPROM) */
-	for (i = 0; i < 8; i++) {
-		if (ctlr->bbp[i].reg == 0 || ctlr->bbp[i].reg == 0xff)
+	for(i = 0; i < 8; i++){
+		if(ctlr->bbp[i].reg == 0 || ctlr->bbp[i].reg == 0xff)
 			continue;
 		bbpwrite(ctlr, ctlr->bbp[i].reg, ctlr->bbp[i].val);
 	}
 
 	/* select Main antenna for 1T1R devices */
-/* notyet
-	if (ctlr->rf_rev == Rf2020 ||
+	if(ctlr->rf_rev == Rf2020 ||
 	    ctlr->rf_rev == Rf3020 ||
 	    ctlr->rf_rev == Rf3320)
-		rt3090_set_rx_antenna(ctlr, 0);
-*/
+		rt3090setrxantenna(ctlr, 0);
 
 	/* send LEDs operating mode to microcontroller */
 	mcucmd(ctlr, McuCmdLed1, ctlr->led[0], 0);
@@ -1957,42 +2473,42 @@
 	mcucmd(ctlr, McuCmdLed2, ctlr->led[1], 0);
 	mcucmd(ctlr, McuCmdLed3, ctlr->led[2], 0);
 
-/* XXX: 30xx
-	if (ctlr->mac_ver >= 0x3071)
-		rt3090_rf_init(ctlr);
-*/
+	if(ctlr->mac_ver >= 0x3071)
+		rt3090rfinit(ctlr);
 
 	mcucmd(ctlr, McuCmdSleep, 0x02ff, 1);
 	mcucmd(ctlr, McuCmdWakeup, 0, 1);
-/* XXX: 30xx
-	if (ctlr->mac_ver >= 0x3071)
-		rt3090_rf_wakeup(ctlr);
-*/
 
+	if(ctlr->mac_ver >= 0x3071)
+		rt3090rfwakeup(ctlr);
+
 	/* disable non-existing Rx chains */
 	bbp3 = bbpread(ctlr, 3);
 	bbp3 &= ~(1 << 3 | 1 << 4);
-	if (ctlr->nrxchains == 2)
+	if(ctlr->nrxchains == 2)
 		bbp3 |= 1 << 3;
-	else if (ctlr->nrxchains == 3)
+	else if(ctlr->nrxchains == 3)
 		bbp3 |= 1 << 4;
 	bbpwrite(ctlr, 3, bbp3);
 
 	/* disable non-existing Tx chains */
 	bbp1 = bbpread(ctlr, 1);
-	if (ctlr->ntxchains == 1)
+	if(ctlr->ntxchains == 1)
 		bbp1 = (bbp1 & ~(1 << 3 | 1 << 4));
-	else if (ctlr->mac_ver == 0x3593 && ctlr->ntxchains == 2)
+	else if(ctlr->mac_ver == 0x3593 && ctlr->ntxchains == 2)
 		bbp1 = (bbp1 & ~(1 << 4)) | 1 << 3;
-	else if (ctlr->mac_ver == 0x3593 && ctlr->ntxchains == 3)
+	else if(ctlr->mac_ver == 0x3593 && ctlr->ntxchains == 3)
 		bbp1 = (bbp1 & ~(1 << 3)) | 1 << 4;
 	bbpwrite(ctlr, 1, bbp1);
-/* XXX: 30xx
-	if (ctlr->mac_ver >= 0x3071)
-		rt3090_rf_setup(ctlr);
-*/
+
+	if(ctlr->mac_ver >= 0x3071)
+		rt3090rfsetup(ctlr);
+
 	/* select default channel */
-	setchan(ctlr, 3);
+	if(ctlr->mac_ver >= 0x3071)
+		rt3090setchan(ctlr, 3);
+	else
+		setchan(ctlr, 3);
 
 	/* reset RF from MCU */
 	mcucmd(ctlr, McuCmdRfreset, 0, 0);
@@ -2010,7 +2526,7 @@
 	setleds(ctlr, LedRadio);
 
 	/* enable Tx/Rx DMA engine */
-	if ((err = txrxon(ctlr)) != 0) {
+	if((err = txrxon(ctlr)) != 0){
 		/*rt2860_stop(ifp, 1);*/
 		return err;
 	}
@@ -2020,7 +2536,7 @@
 	/* enable interrupts */
 	csr32w(ctlr, IntMask, 0x3fffc);
 
-	if (ctlr->flags & AdvancedPs)
+	if(ctlr->flags & AdvancedPs)
 		mcucmd(ctlr, McuCmdPslevel, ctlr->pslevel, 0);
 	return nil;
 }
@@ -2034,12 +2550,12 @@
 {
 	s8int i, b4;
 
-	for (i = 0; i < 8; i++) {
+	for(i = 0; i < 8; i++){
 		b4 = b32 & 0xf;
 		b4 += delta;
-		if (b4 < 0)
+		if(b4 < 0)
 			b4 = 0;
-		else if (b4 > 0xf)
+		else if(b4 > 0xf)
 			b4 = 0xf;
 		b32 = b32 >> 4 | b4 << 28;
 	}
@@ -2279,7 +2795,7 @@
 	while((stat = csr32r(ctlr, TxStatFifo)) & TxqVld){
 		wcid = (stat >> TxqWcidShift) & 0xff;
 		/* if no ACK was requested, no feedback is available */
-		if (!(stat & TxqAckreq) || wcid == 0xff){
+		if(!(stat & TxqAckreq) || wcid == 0xff){
 			continue;
 		}
 	}
@@ -2450,11 +2966,41 @@
 
 /* Read 16-bit from eFUSE ROM (>=RT3071 only.) */
 static u16int
-efuseread2(Ctlr *, u16int)
+efuseread2(Ctlr *ctlr, u16int addr)
 {
-	/* XXX: 30xx */
-	print("efuse rom not implemented\n");
-	return 0;
+	u32int tmp;
+	u16int reg;
+	int ntries;
+
+	addr *= 2;
+	/*-
+	 * Read one 16-byte block into registers EFUSE_DATA[0-3]:
+	 * DATA0: F E D C
+	 * DATA1: B A 9 8
+	 * DATA2: 7 6 5 4
+	 * DATA3: 3 2 1 0
+	 */
+	tmp = csr32r(ctlr, Rt3070EfuseCtrl);
+	tmp &= ~(Rt3070EfsromModeMask | Rt3070EfsromAinMask);
+	tmp |= (addr & ~0xf) << Rt3070EfsromAinShift | Rt3070EfsromKick;
+	csr32w(ctlr, Rt3070EfuseCtrl, tmp);
+	for(ntries = 0; ntries < 500; ntries++){
+		tmp = csr32r(ctlr, Rt3070EfuseCtrl);
+		if(!(tmp & Rt3070EfsromKick))
+			break;
+		microdelay(2);
+	}
+	if(ntries == 500)
+		return 0xffff;
+
+	if((tmp & Rt3070EfuseAoutMask) == Rt3070EfuseAoutMask)
+		return 0xffff;	/* address not found */
+
+	/* determine to which 32-bit register our 16-bit word belongs */
+	reg = Rt3070EfuseData3 - (addr & 0xc);
+	tmp = csr32r(ctlr, reg);
+
+	return (addr & 2) ? tmp >> 16 : tmp & 0xffff;
 }
 
 static char*
@@ -2496,7 +3042,7 @@
 		ctlr->bbp[i].reg = val >> 8;
 	}
 
-	if (ctlr->mac_ver >= 0x3071) {
+	if(ctlr->mac_ver >= 0x3071){
 		/* read vendor RF settings */
 		for(i = 0; i < 10; i++){
 			val = rom_read(ctlr, Rt3071EepromRfBase + i);
@@ -2508,13 +3054,13 @@
 	/* read RF frequency offset from EEPROM */
 	val = rom_read(ctlr, EepromFreqLeds);
 	ctlr->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0;
-	if ((val >> 8) != 0xff) {
+	if((val >> 8) != 0xff){
 		/* read LEDs operating mode */
 		ctlr->leds = val >> 8;
 		ctlr->led[0] = rom_read(ctlr, EepromLed1);
 		ctlr->led[1] = rom_read(ctlr, EepromLed2);
 		ctlr->led[2] = rom_read(ctlr, EepromLed3);
-	} else {
+	}else{
 		/* broken EEPROM, use default settings */
 		ctlr->leds = 0x01;
 		ctlr->led[0] = 0x5555;
@@ -2523,24 +3069,24 @@
 	}
 	/* read RF information */
 	val = rom_read(ctlr, EepromAntenna);
-	if (val == 0xffff) {
-		if (ctlr->mac_ver == 0x3593) {
+	if(val == 0xffff){
+		if(ctlr->mac_ver == 0x3593){
 			/* default to RF3053 3T3R */
 			ctlr->rf_rev = Rf3053;
 			ctlr->ntxchains = 3;
 			ctlr->nrxchains = 3;
-		} else if (ctlr->mac_ver >= 0x3071) {
+		}else if(ctlr->mac_ver >= 0x3071){
 			/* default to RF3020 1T1R */
 			ctlr->rf_rev = Rf3020;
 			ctlr->ntxchains = 1;
 			ctlr->nrxchains = 1;
-		} else {
+		}else{
 			/* default to RF2820 1T2R */
 			ctlr->rf_rev = Rf2820;
 			ctlr->ntxchains = 1;
 			ctlr->nrxchains = 2;
 		}
-	} else {
+	}else{
 		ctlr->rf_rev = (val >> 8) & 0xf;
 		ctlr->ntxchains = (val >> 4) & 0xf;
 		ctlr->nrxchains = val & 0xf;
@@ -2549,9 +3095,9 @@
 	/* check if RF supports automatic Tx access gain control */
 	val = rom_read(ctlr, EepromConfig);
 	/* check if driver should patch the DAC issue */
-	if ((val >> 8) != 0xff)
+	if((val >> 8) != 0xff)
 		ctlr->patch_dac = (val >> 15) & 1;
-	if ((val & 0xff) != 0xff) {
+	if((val & 0xff) != 0xff){
 		ctlr->ext_5ghz_lna = (val >> 3) & 1;
 		ctlr->ext_2ghz_lna = (val >> 2) & 1;
 		/* check if RF supports automatic Tx access gain control */
@@ -2559,19 +3105,19 @@
 		/* check if we have a hardware radio switch */
 		ctlr->rfswitch = val & 1;
 	}
-	if (ctlr->flags & AdvancedPs) {
+	if(ctlr->flags & AdvancedPs){
 		/* read PCIe power save level */
 		val = rom_read(ctlr, EepromPciePslevel);
-		if ((val & 0xff) != 0xff) {
+		if((val & 0xff) != 0xff){
 			ctlr->pslevel = val & 0x3;
 			val = rom_read(ctlr, EepromRev);
-			if ((val & 0xff80) != 0x9280)
+			if((val & 0xff80) != 0x9280)
 				ctlr->pslevel = MIN(ctlr->pslevel, 1);
 		}
 	}
 
 	/* read power settings for 2GHz channels */
-	for (i = 0; i < 14; i += 2) {
+	for(i = 0; i < 14; i += 2){
 		val = rom_read(ctlr,
 		    EepromPwr2ghzBase1 + i / 2);
 		ctlr->txpow1[i + 0] = (s8int)(val & 0xff);
@@ -2584,14 +3130,14 @@
 	}
 	/* fix broken Tx power entries */
 
-	for (i = 0; i < 14; i++) {
-		if (ctlr->txpow1[i] < 0 || ctlr->txpow1[i] > 31)
+	for(i = 0; i < 14; i++){
+		if(ctlr->txpow1[i] < 0 || ctlr->txpow1[i] > 31)
 			ctlr->txpow1[i] = 5;
-		if (ctlr->txpow2[i] < 0 || ctlr->txpow2[i] > 31)
+		if(ctlr->txpow2[i] < 0 || ctlr->txpow2[i] > 31)
 			ctlr->txpow2[i] = 5;
 	}
 	/* read power settings for 5GHz channels */
-	for (i = 0; i < 40; i += 2) {
+	for(i = 0; i < 40; i += 2){
 		val = rom_read(ctlr,
 		    EepromPwr5ghzBase1 + i / 2);
 		ctlr->txpow1[i + 14] = (s8int)(val & 0xff);
@@ -2604,10 +3150,10 @@
 	}
 
 	/* fix broken Tx power entries */
-	for (i = 0; i < 40; i++) {
-		if (ctlr->txpow1[14 + i] < -7 || ctlr->txpow1[14 + i] > 15)
+	for(i = 0; i < 40; i++){
+		if(ctlr->txpow1[14 + i] < -7 || ctlr->txpow1[14 + i] > 15)
 			ctlr->txpow1[14 + i] = 5;
-		if (ctlr->txpow2[14 + i] < -7 || ctlr->txpow2[14 + i] > 15)
+		if(ctlr->txpow2[14 + i] < -7 || ctlr->txpow2[14 + i] > 15)
 			ctlr->txpow2[14 + i] = 5;
 	}
 
@@ -2614,19 +3160,19 @@
 	/* read Tx power compensation for each Tx rate */
 	val = rom_read(ctlr, EepromDeltapwr);
 	delta_2ghz = delta_5ghz = 0;
-	if ((val & 0xff) != 0xff && (val & 0x80)) {
+	if((val & 0xff) != 0xff && (val & 0x80)){
 		delta_2ghz = val & 0xf;
-		if (!(val & 0x40))	/* negative number */
+		if(!(val & 0x40))	/* negative number */
 			delta_2ghz = -delta_2ghz;
 	}
 	val >>= 8;
-	if ((val & 0xff) != 0xff && (val & 0x80)) {
+	if((val & 0xff) != 0xff && (val & 0x80)){
 		delta_5ghz = val & 0xf;
-		if (!(val & 0x40))	/* negative number */
+		if(!(val & 0x40))	/* negative number */
 			delta_5ghz = -delta_5ghz;
 	}
 
-	for (ridx = 0; ridx < 5; ridx++) {
+	for(ridx = 0; ridx < 5; ridx++){
 		u32int reg;
 
 		val = rom_read(ctlr, EepromRpwr + ridx * 2);
@@ -2656,7 +3202,7 @@
 	ctlr->tssi_2ghz[8] = val & 0xff;	/* [+4] */
 	ctlr->step_2ghz = val >> 8;
 	/* check that ref value is correct, otherwise disable calibration */
-	if (ctlr->tssi_2ghz[4] == 0xff)
+	if(ctlr->tssi_2ghz[4] == 0xff)
 		ctlr->calib_2ghz = 0;
 
 	val = rom_read(ctlr, EepromTssi15ghz);
@@ -2675,7 +3221,7 @@
 	ctlr->tssi_5ghz[8] = val & 0xff;	/* [+4] */
 	ctlr->step_5ghz = val >> 8;
 	/* check that ref value is correct, otherwise disable calibration */
-	if (ctlr->tssi_5ghz[4] == 0xff)
+	if(ctlr->tssi_5ghz[4] == 0xff)
 		ctlr->calib_5ghz = 0;
 
 	/* read RSSI offsets and LNA gains from EEPROM */
@@ -2683,14 +3229,14 @@
 	ctlr->rssi_2ghz[0] = val & 0xff;	/* Ant A */
 	ctlr->rssi_2ghz[1] = val >> 8;	/* Ant B */
 	val = rom_read(ctlr, EepromRssi22ghz);
-	if (ctlr->mac_ver >= 0x3071) {
+	if(ctlr->mac_ver >= 0x3071){
 		/*
 		 * On RT3090 chips (limited to 2 Rx chains), this ROM
 		 * field contains the Tx mixer gain for the 2GHz band.
 		 */
-		if ((val & 0xff) != 0xff)
+		if((val & 0xff) != 0xff)
 			ctlr->txmixgain_2ghz = val & 0x7;
-	} else
+	}else
 		ctlr->rssi_2ghz[2] = val & 0xff;	/* Ant C */
 	ctlr->lna[2] = val >> 8;		/* channel group 2 */
 
@@ -2702,7 +3248,7 @@
 	ctlr->lna[3] = val >> 8;		/* channel group 3 */
 
 	val = rom_read(ctlr, EepromLna);
-	if (ctlr->mac_ver >= 0x3071)
+	if(ctlr->mac_ver >= 0x3071)
 		ctlr->lna[0] = DefLna;
 	else				/* channel group 0 */
 		ctlr->lna[0] = val & 0xff;
@@ -2709,19 +3255,19 @@
 	ctlr->lna[1] = val >> 8;		/* channel group 1 */
 
 	/* fix broken 5GHz LNA entries */
-	if (ctlr->lna[2] == 0 || ctlr->lna[2] == 0xff) {
+	if(ctlr->lna[2] == 0 || ctlr->lna[2] == 0xff){
 		ctlr->lna[2] = ctlr->lna[1];
 	}
-	if (ctlr->lna[3] == 0 || ctlr->lna[3] == 0xff) {
+	if(ctlr->lna[3] == 0 || ctlr->lna[3] == 0xff){
 		ctlr->lna[3] = ctlr->lna[1];
 	}
 
 	/* fix broken RSSI offset entries */
-	for (ant = 0; ant < 3; ant++) {
-		if (ctlr->rssi_2ghz[ant] < -10 || ctlr->rssi_2ghz[ant] > 10) {
+	for(ant = 0; ant < 3; ant++){
+		if(ctlr->rssi_2ghz[ant] < -10 || ctlr->rssi_2ghz[ant] > 10){
 			ctlr->rssi_2ghz[ant] = 0;
 		}
-		if (ctlr->rssi_5ghz[ant] < -10 || ctlr->rssi_5ghz[ant] > 10) {
+		if(ctlr->rssi_5ghz[ant] < -10 || ctlr->rssi_5ghz[ant] > 10){
 			ctlr->rssi_5ghz[ant] = 0;
 		}
 	}
@@ -2852,13 +3398,13 @@
 	 * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings.
 	 */
 	for(qid = 0; qid < 6; qid++){
-		if ((err = alloctx(ctlr, &ctlr->tx[qid])) != nil)
+		if((err = alloctx(ctlr, &ctlr->tx[qid])) != nil)
 			goto fail1;
 	}
-	if ((err = allocrx(ctlr, &ctlr->rx)) != nil)
+	if((err = allocrx(ctlr, &ctlr->rx)) != nil)
 		goto fail1;
 
-	if ((err = alloctxpool(ctlr)) != nil)
+	if((err = alloctxpool(ctlr)) != nil)
 		goto fail2;
 	/* mgmt ring is broken on RT2860C, use EDCA AC VO ring instead */
 
@@ -2868,7 +3414,7 @@
 		return nil;
 fail2:	freerx(ctlr, &ctlr->rx);
 		return err;
-fail1:	while (--qid >= 0)
+fail1:	while(--qid >= 0)
 			freetx(ctlr, &ctlr->tx[qid]);
 		return err;
 }
@@ -2903,6 +3449,7 @@
 					break;
 			case RalinkRT2890:
 			case RalinkRT2790:
+			case RalinkRT3090:
 			case AwtRT2890:
 					ctlr->flags = AdvancedPs;
 					break;
@@ -2930,7 +3477,7 @@
 	Pcidev *pdev;
 	
 	pdev = nil;
-	while(pdev = pcimatch(pdev, 0, 0)) {
+	while(pdev = pcimatch(pdev, 0, 0)){
 		Ctlr *ctlr;
 		void *mem;
 		
@@ -2942,7 +3489,8 @@
 		switch(pdev->did){
 		default:
 			continue;
-		case 0x0781: /* RT2790 */
+		case RalinkRT2790:
+		case RalinkRT3090:
 			break;
 		}
 
@@ -2950,13 +3498,13 @@
 		pcisetpms(pdev, 0);
 
 		ctlr = malloc(sizeof(Ctlr));
-		if(ctlr == nil) {
+		if(ctlr == nil){
 			print("rt2860: unable to alloc Ctlr\n");
 			continue;
 		}
 		ctlr->port = pdev->mem[0].bar & ~0x0F;
 		mem = vmap(pdev->mem[0].bar & ~0x0F, pdev->mem[0].size);
-		if(mem == nil) {
+		if(mem == nil){
 			print("rt2860: can't map %8.8luX\n", pdev->mem[0].bar);
 			free(ctlr);
 			continue;
--