etherrt2860: add rt3090 support and make style more consistent

This commit is contained in:
ppatience0 2013-07-21 18:13:27 -04:00
parent 776056dcd0
commit 9a5763624f

View file

@ -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,6 +1355,9 @@ rxon(Ether *edev, Wnode *bss)
edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, ctlr->wcid);
/* Set channel */
if(ctlr->mac_ver >= 0x3071)
rt3090setchan(ctlr, ctlr->channel);
else
setchan(ctlr, ctlr->channel);
selchangroup(ctlr, 0);
microdelay(1000);
@ -1600,7 +1716,7 @@ 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;
@ -1611,14 +1727,66 @@ rfwrite(Ctlr *ctlr, u8int reg, u32int val)
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
@ -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)
{
@ -1945,29 +2463,24 @@ rt2860start(Ether *edev)
}
/* select Main antenna for 1T1R devices */
/* notyet
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);
*/
rt3090rfinit(ctlr);
mcucmd(ctlr, McuCmdSleep, 0x02ff, 1);
mcucmd(ctlr, McuCmdWakeup, 0, 1);
/* XXX: 30xx
if(ctlr->mac_ver >= 0x3071)
rt3090_rf_wakeup(ctlr);
*/
rt3090rfwakeup(ctlr);
/* disable non-existing Rx chains */
bbp3 = bbpread(ctlr, 3);
@ -1987,11 +2500,14 @@ rt2860start(Ether *edev)
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);
*/
rt3090rfsetup(ctlr);
/* select default channel */
if(ctlr->mac_ver >= 0x3071)
rt3090setchan(ctlr, 3);
else
setchan(ctlr, 3);
/* reset RF from MCU */
@ -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*
@ -2903,6 +3449,7 @@ rt2860init(Ether *edev)
break;
case RalinkRT2890:
case RalinkRT2790:
case RalinkRT3090:
case AwtRT2890:
ctlr->flags = AdvancedPs;
break;
@ -2942,7 +3489,8 @@ rt2860pci(void)
switch(pdev->did){
default:
continue;
case 0x0781: /* RT2790 */
case RalinkRT2790:
case RalinkRT3090:
break;
}