diff --git a/sys/src/9/pc/etherrt2860.c b/sys/src/9/pc/etherrt2860.c index 426aa18b4..5f4ee4a5d 100644 --- a/sys/src/9/pc/etherrt2860.c +++ b/sys/src/9/pc/etherrt2860.c @@ -783,6 +783,33 @@ enum { 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 @@ enum { ConnPciE = 1 << 1, }; - static const struct rt2860_rate { u8int rate; u8int mcs; @@ -1122,6 +1148,91 @@ static const struct rfprog { { 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 { enum { RalinkRT2890 = 0x0681, RalinkRT2790 = 0x0781, + RalinkRT3090 = 0x3090, AwtRT2890 = 0x1059, }; @@ -1139,6 +1251,7 @@ enum { 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 @@ rxon(Ether *edev, Wnode *bss) 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 @@ rxon(Ether *edev, Wnode *bss) /* 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 @@ readfirmware(void){ 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 @@ boot(Ctlr *ctlr) /* 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 @@ mcucmd(Ctlr *ctlr, u8int cmd, u16int arg, int wait) 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 @@ bbpinit(Ctlr *ctlr) /* 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,25 +1716,77 @@ txrxon(Ctlr *ctlr) /* * Write to one of the 4 programmable 24-bit RF registers. */ -static char* +static void rfwrite(Ctlr *ctlr, u8int reg, u32int val) { u32int tmp; 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 @@ -1632,7 +1800,7 @@ selchangroup(Ctlr *ctlr, int group) 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 @@ selchangroup(Ctlr *ctlr, int group) 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 @@ selchangroup(Ctlr *ctlr, int group) } 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 @@ setchan(Ctlr *ctlr, uint chan) 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 @@ setchan(Ctlr *ctlr, uint chan) 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; @@ -1761,6 +1929,356 @@ setchan(Ctlr *ctlr, uint chan) rfwrite(ctlr, Rf4, r4); } +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) { @@ -1775,10 +2293,10 @@ updateprot(Ctlr *ctlr) /* 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 @@ rt2860start(Ether *edev) /* 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 @@ rt2860start(Ether *edev) /* 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 @@ rt2860start(Ether *edev) 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,61 +2456,59 @@ rt2860start(Ether *edev) 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); 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 @@ rt2860start(Ether *edev) 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 @@ rt2860start(Ether *edev) /* 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 @@ b4inc(u32int b32, s8int delta) { 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 @@ stats(Ctlr *ctlr) 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 @@ eeread2(Ctlr *ctlr, u16int addr) /* 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 @@ eepromread(Ether *edev) 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 @@ eepromread(Ether *edev) /* 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 @@ eepromread(Ether *edev) } /* 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 @@ eepromread(Ether *edev) /* 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 @@ eepromread(Ether *edev) /* 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 @@ eepromread(Ether *edev) } /* 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,29 +3150,29 @@ eepromread(Ether *edev) } /* 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; } /* 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 @@ eepromread(Ether *edev) 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 @@ eepromread(Ether *edev) 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 @@ eepromread(Ether *edev) 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,26 +3248,26 @@ eepromread(Ether *edev) 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; 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 @@ initring(Ctlr *ctlr) * 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 @@ initring(Ctlr *ctlr) 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 @@ rt2860init(Ether *edev) break; case RalinkRT2890: case RalinkRT2790: + case RalinkRT3090: case AwtRT2890: ctlr->flags = AdvancedPs; break; @@ -2930,7 +3477,7 @@ rt2860pci(void) Pcidev *pdev; pdev = nil; - while(pdev = pcimatch(pdev, 0, 0)) { + while(pdev = pcimatch(pdev, 0, 0)){ Ctlr *ctlr; void *mem; @@ -2942,7 +3489,8 @@ rt2860pci(void) switch(pdev->did){ default: continue; - case 0x0781: /* RT2790 */ + case RalinkRT2790: + case RalinkRT3090: break; } @@ -2950,13 +3498,13 @@ rt2860pci(void) 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;