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;
--
⑨