9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] Ralink RT3090 driver
@ 2021-07-01 16:08 José Miguel Sánchez García
  2021-07-01 19:12 ` kemal
  0 siblings, 1 reply; 3+ messages in thread
From: José Miguel Sánchez García @ 2021-07-01 16:08 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 498 bytes --]

Hello everyone,

My laptop has a Ralink RT3090 Wi-Fi card, which I couldn't get
working. However, the FQA marks it as working (section 3.2.3.2.3 and
sysinfo of sl's X60s in section 3.2.5.2.1). Can somebody check if
that's true?

If the FQA is wrong, kemal has been working on the attached patch for
that card. It mostly works, but under heavy load it disconnects
(ip/ping -n 100000  -i 10 will fail at some point) and we couldn't
figure it out. Testing would be greatly appreciated!

Cheers,
jmi2k

[-- Attachment #2: rt3290.diff --]
[-- Type: application/octet-stream, Size: 25404 bytes --]

--- /sys/src/9/pc/etherrt2860.c
+++ /sys/src/9/pc/etherrt2860.c
@@ -1,9 +1,9 @@
 /* 
  * Ralink RT2860 driver
  *
- * Written without any documentation but Damien Bergaminis
- * OpenBSD ral(4) driver sources. Requires ralink firmware
- * to be present in /lib/firmware/ral-rt2860 on attach.
+ * Written without any documentation but Damien Bergamini's
+ * OpenBSD ral(4) driver sources. Requires Ralink firmware
+ * to be present in /lib/firmware/ral-rt* on attach.
  */
 
 #include "u.h"
@@ -235,6 +235,24 @@
 	Rt3090OscCtrl = 0x05a4,
 	Rt3070LdoCfg0 = 0x05d4,
 	Rt3070GpioSwitch = 0x05dc,
+
+	/* RT3290 registers */
+	Rt3290CmbCtrl = 0x0020,
+		Rt3290XtalRdy = (1 << 22),
+		Rt3290PllLd = (1 << 23),
+	Rt3290EfuseCtrl = 0x0024,
+	Rt3290EfuseData0 = 0x0034,
+	Rt3290EfuseData1 = 0x0030,
+	Rt3290EfuseData2 = 0x002c,
+	Rt3290EfuseData3 = 0x0028,
+	Rt3290WlanCtrl = 0x0080,
+		Rt3290WlanEn = (1 << 0),
+		Rt3290WlanClkEn = (1 << 1),
+		Rt3290WlanReset = (1 << 3),
+		Rt3290PcieApp0ClkReq = (1 << 4),
+		Rt3290FrcWlAntSet = (1 << 5),
+		Rt3290RadioEn = (1 << 8),
+		Rt3290GpioOutOeAll = (0xff << 24),
 };
 
 enum {
@@ -767,21 +785,23 @@
 };
 
 enum {
-	Rf2820 = 1 /* 2T3R */,
-	Rf2850 = 2 /* dual-band 2T3R */,
-	Rf2720 = 3 /* 1T2R */,
-	Rf2750 = 4 /* dual-band 1T2R */,
-	Rf3020 = 5 /* 1T1R */,
-	Rf2020 = 6 /* b/g */,
-	Rf3021 = 7 /* 1T2R */,
-	Rf3022 = 8 /* 2T2R */,
- 	Rf3052 = 9 /* dual-band 2T2R */,
-	Rf3320 = 11 /* 1T1R */,
-	Rf3053 = 13 /* dual-band 3T3R */,
+	Rf2820 = 0x0001, /* 2T3R */
+	Rf2850 = 0x0002, /* dual-band 2T3R */
+	Rf2720 = 0x0003, /* 1T2R */
+	Rf2750 = 0x0004, /* dual-band 1T2R */
+	Rf3020 = 0x0005, /* 1T1R */
+	Rf2020 = 0x0006, /* b/g */
+	Rf3021 = 0x0007, /* 1T2R */
+	Rf3022 = 0x0008, /* 2T2R */
+ 	Rf3052 = 0x0009, /* dual-band 2T2R */
+	Rf3320 = 0x000b, /* 1T1R */
+	Rf3053 = 0x000d, /* dual-band 3T3R */
+	Rf3290 = 0x3290, /* 1T1R */
 };
 
 enum {	
 	Rt3070RfBlock = (1 << 0),
+	Rt3070PllPd = (1 << 1),
 	Rt3070Rx0Pd = (1 << 2),
 	Rt3070Tx0Pd = (1 << 3),
 	Rt3070Rx1Pd = (1 << 4),
@@ -804,10 +824,16 @@
 	Rt3593LdoRfVcMask = 0xe0,
 	Rt3593CpIcMask = 0xe0,
 	Rt3593CpIcShift = 5,
-	Rt3593RxCtb = (1 << 5)
+	Rt3593RxCtb = (1 << 5),
+
+	Rt5390RxLo1 = (1 << 5),
+	Rt5390RxLo2 = (1 << 7),
+	Rt5390RxCtb = (1 << 6),
+
+	Rt3290RssiGain = 0xc0,
 };
 
-static const char* rfnames[] = {
+static char* rfnames[] = {
 	[Rf2820] "RT2820",
 	[Rf2850] "RT2850",
 	[Rf2720] "RT2720",
@@ -819,9 +845,27 @@
 	[Rf3052] "RT3052",
 	[Rf3320] "RT3320",
 	[Rf3053] "RT3053",
+	[Rf3290] "RT3290",
 };
 
 enum {
+	/* BBP register values */
+
+	/* BBP3 - RX Antenna */
+	Rt3290AdcModeSwitch = (1 << 6),
+	Rt3290AdcInitMode = (1 << 7),
+
+	/* BBP4 - Bandwidth */
+	Rt5390MacIfCtrl = (1 << 6),
+
+	/* BBP47 - Bandwith */
+	Rt3290TssiAdc6 = (1 << 7),
+	
+	/* BBP152 - RX Antenna */
+	Rt5390DefRxAnt = (1 << 7),
+};
+
+enum {
 	/* USB commands, RT2870 only */
 	Rt2870Reset = 1,
 	Rt2870Write2 = 2,
@@ -833,6 +877,7 @@
 enum {
 	EepromDelay = 1 /* minimum hold time (microsecond) */,
 
+	EepromChipId = 0x00,
 	EepromVersion = 0x01,
 	EepromMac01 = 0x02,
 	EepromMac23 = 0x03,
@@ -932,7 +977,7 @@
 
 	u16int mac_ver;
 	u16int mac_rev;
-	u8int rf_rev;
+	u16int rf_rev;
 	u8int freq;
 	u8int ntxchains;
 	u8int nrxchains;
@@ -999,32 +1044,50 @@
 	ConnPciE   = 1 << 1,
 };
 
-static const struct rt2860_rate {
+static struct rt2860_rate {
 	u8int		rate;
 	u8int		mcs;
-	/*enum		ieee80211_phytype phy;*/
 	u8int		ctl_ridx;
 	u16int		sp_ack_dur;
 	u16int		lp_ack_dur;
+	int		ofdm;
 } rt2860_rates[] = {
-	{   2, 0,/* IEEE80211_T_DS,*/   0, 314, 314 },
-	{   4, 1,/* IEEE80211_T_DS,*/   1, 258, 162 },
-	{  11, 2,/* IEEE80211_T_DS,*/   2, 223, 127 },
-	{  22, 3,/* IEEE80211_T_DS,*/   3, 213, 117 },
-	{  12, 0,/* IEEE80211_T_OFDM,*/ 4,  60,  60 },
-	{  18, 1,/* IEEE80211_T_OFDM,*/ 4,  52,  52 },
-	{  24, 2,/* IEEE80211_T_OFDM,*/ 6,  48,  48 },
-	{  36, 3,/* IEEE80211_T_OFDM,*/ 6,  44,  44 },
-	{  48, 4,/* IEEE80211_T_OFDM,*/ 8,  44,  44 },
-	{  72, 5,/* IEEE80211_T_OFDM,*/ 8,  40,  40 },
-	{  96, 6,/* IEEE80211_T_OFDM,*/ 8,  40,  40 },
-	{ 108, 7,/* IEEE80211_T_OFDM,*/ 8,  40,  40 }
+	{   2, 0, 0, 314, 314, 0 },
+	{   4, 1, 1, 258, 162, 0 },
+	{  11, 2, 2, 223, 127, 0 },
+	{  22, 3, 3, 213, 117, 0 },
+	{  12, 0, 4,  60,  60, 1 },
+	{  18, 1, 4,  52,  52, 1 },
+	{  24, 2, 6,  48,  48, 1 },
+	{  36, 3, 6,  44,  44, 1 },
+	{  48, 4, 8,  44,  44, 1 },
+	{  72, 5, 8,  40,  40, 1 },
+	{  96, 6, 8,  40,  40, 1 },
+	{ 108, 7, 8,  40,  40, 1 }
 };
 
+/* for use with the wifi stack, *must* be in order with rt2860_rates */
+static u8int rates[] = {
+	0x80 | 2,
+	0x80 | 4,
+	0x80 | 11,
+	0x80 | 22,
+
+	0x80 | 12,
+	0x80 | 18,
+	0x80 | 24,
+	0x80 | 36,
+	0x80 | 48,
+	0x80 | 72,
+	0x80 | 96,
+	0x80 | 108,
+	0
+};
+
 /*
  * Default values for MAC registers; values taken from the reference driver.
  */
-static const struct {
+static struct {
 	u32int	reg;
 	u32int	val;
 } rt2860_def_mac[] = {
@@ -1061,7 +1124,7 @@
 /*
  * Default values for BBP registers; values taken from the reference driver.
  */
-static const struct {
+static struct {
 	u8int	reg;
 	u8int	val;
 } rt2860_def_bbp[] = {
@@ -1080,12 +1143,48 @@
 	{ 103, 0x00 },	
 	{ 105, 0x05 },	
 	{ 106, 0x35 },
+}, rt3290_def_bbp[] = {
+	{  31, 0x08 },
+	{  65, 0x2c },
+	{  66, 0x38 },
+	{  68, 0x0b },
+	{  69, 0x12 },
+	{  73, 0x13 },
+	{  75, 0x46 },
+	{  76, 0x28 },
+	{  77, 0x58 },
+	{  70, 0x0a },
+	{  74, 0x0b },
+	{  79, 0x18 },
+	{  80, 0x09 },
+	{  81, 0x33 },
+	{  82, 0x62 },
+	{  83, 0x7a },
+	{  84, 0x9a },
+	{  86, 0x38 },
+	{  91, 0x04 },
+	{  92, 0x02 },
+	{ 104, 0x92 },
+	{ 105, 0x1c },
+	{ 106, 0x03 },
+	{ 128, 0x12 },
+
+	{  67, 0x24 },
+	{ 143, 0x04 },
+	{ 142, 0x99 },
+	{ 150, 0x30 },
+	{ 151, 0x2e },
+	{ 152, 0x20 },
+	{ 153, 0x34 },
+	{ 154, 0x40 },
+	{ 155, 0x3b },
+	{ 253, 0x04 }
 };
 
 /*
  * Default settings for RF registers; values derived from the reference driver.
  */
-static const struct rfprog {
+static struct rfprog {
 	u8int		chan;
 	u32int		r1, r2, r3, r4;
 } rt2860_rf2850[] = {
@@ -1204,7 +1303,7 @@
 	{ 0x61, 0,  9 }
 };
 
-static const struct {
+static struct {
 	u8int reg;
 	u8int val;
 } rt3090_def_rf[] = {
@@ -1227,6 +1326,53 @@
 	{ 24, 0x16 },
 	{ 25, 0x01 },
 	{ 29, 0x1f }
+}, rt3290_def_rf[] = {
+	{  1, 0x0f },
+	{  2, 0x80 },
+	{  3, 0x08 },
+	{  4, 0x00 },
+	{  6, 0xa0 },
+	{  8, 0xf3 },
+	{  9, 0x02 },
+	{ 10, 0x53 },
+	{ 11, 0x4a },
+	{ 12, 0x46 },
+	{ 13, 0x9f },
+	{ 18, 0x02 },
+	{ 22, 0x20 },
+	{ 25, 0x83 },
+	{ 26, 0x82 },
+	{ 27, 0x09 },
+	{ 29, 0x10 },
+	{ 30, 0x10 },
+	{ 31, 0x80 },
+	{ 32, 0x80 },
+	{ 33, 0x00 },
+	{ 34, 0x05 },
+	{ 35, 0x12 },
+	{ 36, 0x00 },
+	{ 38, 0x85 },
+	{ 39, 0x1b },
+	{ 40, 0x0b },
+	{ 41, 0xbb },
+	{ 42, 0xd5 },
+	{ 43, 0x7b },
+	{ 44, 0x0e },
+	{ 45, 0xa2 },
+	{ 46, 0x73 },
+	{ 47, 0x00 },
+	{ 48, 0x10 },
+	{ 49, 0x98 },
+	{ 52, 0x38 },
+	{ 53, 0x00 },
+	{ 54, 0x78 },
+	{ 55, 0x43 },
+	{ 56, 0x02 },
+	{ 57, 0x80 },
+	{ 58, 0x7f },
+	{ 59, 0x09 },
+	{ 60, 0x45 },
+	{ 61, 0xc1 }
 };
 
 /* vendors */
@@ -1239,6 +1385,7 @@
 	RalinkRT2890 = 0x0681,
 	RalinkRT2790 = 0x0781,
 	RalinkRT3090 = 0x3090,
+	RalinkRT3290 = 0x3290,
 	AwtRT2890 = 0x1059,
 };
 
@@ -1248,6 +1395,7 @@
 static int rbplant(Ctlr*, int);
 static void setchan(Ctlr*, uint);
 static void rt3090setchan(Ctlr*, uint);
+static void rt3290setchan(Ctlr*, uint);
 static void selchangroup(Ctlr*, int);
 static void setleds(Ctlr*, u16int);
 
@@ -1346,7 +1494,9 @@
 			edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, ctlr->wcid);
 
 	/* Set channel */
-	if(ctlr->mac_ver >= 0x3071)
+	if(ctlr->mac_ver == 0x3290)
+		rt3290setchan(ctlr, ctlr->channel);
+	else if(ctlr->mac_ver >= 0x3071)
 		rt3090setchan(ctlr, ctlr->channel);
 	else
 		setchan(ctlr, ctlr->channel);
@@ -1353,6 +1503,15 @@
 	selchangroup(ctlr, 0);
 	microdelay(1000);
 
+	if(ctlr->prom)
+		return;
+
+	/* update slot */
+	tmp = csr32r(ctlr, BkoffSlotCfg);
+	tmp &= ~0xff;
+	tmp |= (cap & (1<<10)) ? 9 : 20;
+	csr32w(ctlr, BkoffSlotCfg, tmp);
+
 	/* enable mrr(?) */
 #define CCK(mcs)	(mcs)
 #define OFDM(mcs)	(1 << 3 | (mcs))
@@ -1373,20 +1532,16 @@
 	    CCK(0));		/*   1-> 1 */
 #undef OFDM
 #undef CCK
-	/* update slot */
-	tmp = csr32r(ctlr, BkoffSlotCfg);
-	tmp &= ~0xff;
-	tmp |= (cap & (1<<10)) ? 9 : 20;
-	csr32w(ctlr, BkoffSlotCfg, tmp);
 	
 	/* set TX preamble */
 	tmp = csr32r(ctlr, AutoRspCfg);
 	tmp &= ~CckShortEn;
-	if(cap & (1<<5)) tmp |= CckShortEn;	
+	if(cap & (1<<5))
+		tmp |= CckShortEn;	
 	csr32w(ctlr, AutoRspCfg, tmp);
 
 	/* set basic rates */
-	csr32w(ctlr, LegacyBasicRate, 0x003); /* 11B */
+	csr32w(ctlr, LegacyBasicRate, 0x15f); /* 11G */
 
 	/* Set BSSID */
 	csr32w(ctlr, MacBssidDw0,
@@ -1425,9 +1580,10 @@
 {
 }
 
-static FWImage*
-readfirmware(void){
-	static char name[] = "ral-rt2860";
+static void
+readfirmware(Ctlr *ctlr)
+{
+	char *name;
 	uchar dirbuf[sizeof(Dir)+100], *data;
 	char buf[128];
 	FWImage *fw;
@@ -1437,6 +1593,10 @@
 
 	if(!iseve())
 		error(Eperm);
+	if(ctlr->mac_ver == 0x3290)
+		name = "ral-rt3290";
+	else
+		name = "ral-rt2860";
 	if(!waserror()){
 		snprint(buf, sizeof buf, "/boot/%s", name);
 		c = namec(buf, Aopen, OREAD, 0);
@@ -1470,7 +1630,7 @@
 	poperror();
 	poperror();
 	cclose(c);
-	return fw;
+	ctlr->fw = fw;
 }
 
 static char*
@@ -1635,11 +1795,26 @@
 	}
 
 	/* initialize BBP registers to default values */
-	for(i = 0; i < nelem(rt2860_def_bbp); i++){
-		bbpwrite(ctlr, rt2860_def_bbp[i].reg,
-		    rt2860_def_bbp[i].val);
-	}
+	if(ctlr->mac_ver == 0x3290){
+		/* Avoid data lost and CRC error. */
+		bbpwrite(ctlr, 4, bbpread(ctlr, 4) | Rt5390MacIfCtrl);
+		
+		for(i = 0; i < nelem(rt3290_def_bbp); i++)
+			bbpwrite(ctlr, rt3290_def_bbp[i].reg,
+			    rt3290_def_bbp[i].val);
 
+		bbpwrite(ctlr, 47, bbpread(ctlr, 47) | Rt3290TssiAdc6);
+		/* use 5-bit ADC for acquisition and 8-bit ADC for data */
+		bbpwrite(ctlr, 3, bbpread(ctlr, 3) | Rt3290AdcModeSwitch | Rt3290AdcInitMode);
+		/* switch to default rx antenna */
+		bbpwrite(ctlr, 152, bbpread(ctlr, 152) | Rt5390DefRxAnt);
+
+		return nil;
+	}else
+		for(i = 0; i < nelem(rt2860_def_bbp); i++)
+			bbpwrite(ctlr, rt2860_def_bbp[i].reg,
+				rt2860_def_bbp[i].val);
+
 	/* fix BBP84 for RT2860E */
 	if(ctlr->mac_ver == 0x2860 && ctlr->mac_rev != 0x0101)
 		bbpwrite(ctlr, 84, 0x19);
@@ -1872,7 +2047,7 @@
 static void
 setchan(Ctlr *ctlr, uint chan)
 {
-	const struct rfprog *rfprog = rt2860_rf2850;
+	struct rfprog *rfprog = rt2860_rf2850;
 	u32int r2, r3, r4;
 	s8int txpow1, txpow2;
 	uint i;
@@ -1988,6 +2163,82 @@
 	rt3090rfwrite(ctlr, 7, rf | Rt3070Tune);
 }
 
+/* Altered version of rt5390_set_chan in OpenBSD. */
+static void
+rt3290setchan(Ctlr *ctlr, uint chan)
+{
+	u8int h20mhz, rf, tmp;
+	s8int txpow1;
+	int i;
+
+	/* RT3290 is 2GHz only */
+	assert(chan >= 1 && chan <= 14);
+
+	/* 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];
+
+	rt3090rfwrite(ctlr, 8, rt3090_freqs[i].n);
+	rt3090rfwrite(ctlr, 9, rt3090_freqs[i].k & 0x0f);
+	rf = rt3090rfread(ctlr, 11);
+	rf = (rf & ~0x03) | (rt3090_freqs[i].r & 0x03);
+	rt3090rfwrite(ctlr, 11, rf);
+
+	rf = rt3090rfread(ctlr, 49);
+	rf = (rf & ~0x3f) | (txpow1 & 0x3f);
+	/* the valid range of the RF R49 is 0x00~0x27 */
+	if ((rf & 0x3f) > 0x27)
+		rf = (rf & ~0x3f) | 0x27;
+	rt3090rfwrite(ctlr, 49, rf);
+
+	rf = rt3090rfread(ctlr, 1);
+	rf |= Rt3070RfBlock | Rt3070PllPd | Rt3070Rx0Pd | Rt3070Tx0Pd;
+	rt3090rfwrite(ctlr, 1, rf);
+
+	rf = rt3090rfread(ctlr, 2);
+	rt3090rfwrite(ctlr, 2, rf | Rt3593Rescal);
+	microdelay(1000);
+	rt3090rfwrite(ctlr, 2, rf & ~Rt3593Rescal);
+
+	rf = rt3090rfread(ctlr, 17);
+	tmp = rf;
+	rf = (rf & ~0x7f) | (ctlr->freq & 0x7f);
+	rf = MIN(rf, 0x5f);
+	if (tmp != rf)
+		mcucmd(ctlr, 0x74, (tmp << 8 ) | rf, 0);
+
+	if (chan == 6)
+		bbpwrite(ctlr, 68, 0x0c);
+	else
+		bbpwrite(ctlr, 68, 0x0b);
+
+	if (chan >= 1 && chan < 6)
+		rf = 0x0f;
+	else if (chan >= 7 && chan <= 11)
+			rf = 0x0e;
+	else if (chan >= 12 && chan <= 14)
+			rf = 0x0d;
+	rt3090rfwrite(ctlr, 59, rf);
+
+	/* Tx/Rx h20M */
+	h20mhz = (ctlr->rf24_20mhz & 0x20) >> 5;
+	rf = rt3090rfread(ctlr, 30);
+	rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2);
+	rt3090rfwrite(ctlr, 30, rf);
+
+	/* Rx BB filter VCM */
+	rf = rt3090rfread(ctlr, 30);
+	rf = (rf & ~0x18) | 0x10;
+	rt3090rfwrite(ctlr, 30, rf);
+
+	/* Initiate VCO calibration. */
+	rf = rt3090rfread(ctlr, 3);
+	rf |= Rt3593Vcocal;
+	rt3090rfwrite(ctlr, 3, rf);
+}
+
 static int
 rt3090filtercalib(Ctlr *ctlr, u8int init, u8int target, u8int *val)
 {
@@ -2070,7 +2321,7 @@
 	}
 }
 
-static int
+static void
 rt3090rfinit(Ctlr *ctlr)
 {
 	u32int tmp;
@@ -2174,8 +2425,41 @@
 
 	rf = rt3090rfread(ctlr, 21);
 	rt3090rfwrite(ctlr, 21, rf & ~Rt3070RxLo2);
+}
 
-	return 0;
+/*
+ * rt5390_rf_init was full of stuff that wasn't for rt3290,
+ * this is a function from scratch.
+ */
+static void
+rt3290rfinit(Ctlr *ctlr)
+{
+	u8int rf;
+	int i;
+
+	rf = rt3090rfread(ctlr, 2);
+	/* Toggle RF R2 bit 7. */
+	rt3090rfwrite(ctlr, 2, rf | Rt3593Rescal);
+	microdelay(1000);
+	rt3090rfwrite(ctlr, 2, rf & ~Rt3593Rescal);
+
+	/* Initialize RF registers to default value. */
+	for(i = 0; i < nelem(rt3290_def_rf); i++)
+		rt3090rfwrite(ctlr, rt3290_def_rf[i].reg,
+			rt3290_def_rf[i].val);
+
+	rt3090rfwrite(ctlr, 29, rt3090rfread(ctlr, 29) | Rt3290RssiGain);
+	
+	ctlr->rf24_20mhz = 0x1f;
+	ctlr->rf24_40mhz = 0x2f;
+
+	csr32w(ctlr, Rt3070Opt14, csr32r(ctlr, Rt3070Opt14) | 1);
+
+	rf = rt3090rfread(ctlr, 17);
+	rf &= ~Rt3070TxLo1;
+	if(ctlr->txmixgain_2ghz >= 2)
+		rf = (rf & ~0x7) | ctlr->txmixgain_2ghz;
+	rt3090rfwrite(ctlr, 17, rf);
 }
 
 static void
@@ -2244,7 +2528,32 @@
 	}
 }
 
+/* Altered version of rt5390_rf_wakeup in OpenBSD. */
 static void
+rt3290rfwakeup(Ctlr *ctlr)
+{
+	u8int rf;
+	
+	rf = rt3090rfread(ctlr, 1);
+	rf |= Rt3070RfBlock | Rt3070PllPd | Rt3070Rx0Pd | Rt3070Tx0Pd;
+	rt3090rfwrite(ctlr, 1, rf);
+
+	rf = rt3090rfread(ctlr, 6);
+	rf |= Rt3593VcoIc | Rt3593Vcocal;
+	rt3090rfwrite(ctlr, 6, rf);
+
+	rt3090rfwrite(ctlr, 2, rt3090rfread(ctlr, 2) | Rt3593Rescal);
+
+	rf = rt3090rfread(ctlr, 22);
+	rf = (rf & ~0xe0) | 0x20;
+	rt3090rfwrite(ctlr, 22, rf);
+
+	rt3090rfwrite(ctlr, 42, rt3090rfread(ctlr, 42) | Rt5390RxCtb);
+	rt3090rfwrite(ctlr, 20, rt3090rfread(ctlr, 20) & ~0x77);
+	rt3090rfwrite(ctlr, 3, rt3090rfread(ctlr, 3) | Rt3593Vcocal);
+}
+
+static void
 rt3090rfsetup(Ctlr *ctlr)
 {
 	u8int bbp;
@@ -2294,9 +2603,48 @@
 		else if(ic->ic_protmode == IEEE80211_PROT_CTSONLY)
 			tmp |= ProtCtrlCts;
 	}
-	csr32w(ctlr, OfdmProtCfg, tmp); */
+*/
+	csr32w(ctlr, OfdmProtCfg, tmp);
 }
 
+static char *
+rt3290wlanenable(Ctlr *ctlr)
+{
+	u32int tmp;
+	int ntries;
+
+	/* enable chip and check readiness */
+	tmp = csr32r(ctlr, Rt3290WlanCtrl);
+	tmp |= Rt3290WlanEn | Rt3290FrcWlAntSet |
+	    Rt3290GpioOutOeAll;
+	csr32w(ctlr, Rt3290WlanCtrl, tmp);
+
+	for (ntries = 0; ntries < 200; ntries++) {
+		tmp = csr32r(ctlr, Rt3290CmbCtrl);
+		if ((tmp & Rt3290PllLd) &&
+		    (tmp & Rt3290XtalRdy))
+			break;
+		microdelay(20);
+	}
+	if (ntries == 200)
+		return "timeout while enabling wlan";
+
+	/* toggle reset */
+	tmp = csr32r(ctlr, Rt3290WlanCtrl);
+	tmp |= Rt3290WlanReset | Rt3290WlanClkEn;
+	tmp &= ~Rt3290PcieApp0ClkReq;
+	csr32w(ctlr, Rt3290WlanCtrl, tmp);
+	microdelay(20);
+	tmp &= ~Rt3290WlanReset;
+	csr32w(ctlr, Rt3290WlanCtrl, tmp);
+	microdelay(1000);
+
+	/* clear garbage interrupts */
+	csr32w(ctlr, IntStatus, 0x7fffffff);
+
+	return nil;
+}
+
 static char*
 rt2860start(Ether *edev)
 {
@@ -2307,6 +2655,26 @@
 	Ctlr *ctlr;
 
 	ctlr = edev->ctlr;
+
+	if(ctlr->rfswitch)
+		if(ctlr->mac_ver == 0x3290){
+			/* hardware has a radio switch on GPIO pin 0 */
+			if(!(csr32r(ctlr, Rt3290WlanCtrl) & Rt3290RadioEn))
+				/*XXX: rt2860stop(ifp, 1);*/
+				return "radio disabled";
+		}else
+			/* hardware has a radio switch on GPIO pin 2 */
+			if(!(csr32r(ctlr, GpioCtrl) & 1 << 2))
+				/*XXX: rt2860stop(ifp, 1);*/
+				return "radio disabled";
+
+	if(ctlr->mac_ver == 0x3290){
+		err = rt3290wlanenable(ctlr);
+		if(err != nil)
+			/*XXX: rt2860stop(ifp, 1);*/
+			return err;
+	}
+
 	csr32w(ctlr, PwrPinCfg, IoRaPe);
 
 	/* disable DMA */
@@ -2366,7 +2734,9 @@
 
 	for(i = 0; i < nelem(rt2860_def_mac); i++)
 		csr32w(ctlr, rt2860_def_mac[i].reg, rt2860_def_mac[i].val);
-	if(ctlr->mac_ver >= 0x3071){
+	if(ctlr->mac_ver == 0x3290)
+		csr32w(ctlr, TxSwCfg0, 0x000000404);
+	else if(ctlr->mac_ver >= 0x3071){
 		/* set delay of PA_PE assertion to 1us (unit of 0.25us) */
 		csr32w(ctlr, TxSwCfg0,
 		    4 << DlyPapeEnShift);
@@ -2451,7 +2821,7 @@
 	csr32w(ctlr, DelayIntCfg, 0);
 
 	/* write vendor-specific BBP values (from EEPROM) */
-	for(i = 0; i < 8; i++){
+	for(i = 0; i < nelem(ctlr->bbp); i++){
 		if(ctlr->bbp[i].reg == 0 || ctlr->bbp[i].reg == 0xff)
 			continue;
 		bbpwrite(ctlr, ctlr->bbp[i].reg, ctlr->bbp[i].val);
@@ -2460,6 +2830,7 @@
 	/* select Main antenna for 1T1R devices */
 	if(ctlr->rf_rev == Rf2020 ||
 	    ctlr->rf_rev == Rf3020 ||
+	    ctlr->rf_rev == Rf3290 ||
 	    ctlr->rf_rev == Rf3320)
 		rt3090setrxantenna(ctlr, 0);
 
@@ -2468,13 +2839,17 @@
 	mcucmd(ctlr, McuCmdLed2, ctlr->led[1], 0);
 	mcucmd(ctlr, McuCmdLed3, ctlr->led[2], 0);
 
-	if(ctlr->mac_ver >= 0x3071)
+	if(ctlr->mac_ver == 0x3290)
+		rt3290rfinit(ctlr);
+	else if(ctlr->mac_ver >= 0x3071)
 		rt3090rfinit(ctlr);
 
 	mcucmd(ctlr, McuCmdSleep, 0x02ff, 1);
 	mcucmd(ctlr, McuCmdWakeup, 0, 1);
 
-	if(ctlr->mac_ver >= 0x3071)
+	if(ctlr->mac_ver == 0x3290)
+		rt3290rfwakeup(ctlr);
+	else if(ctlr->mac_ver >= 0x3071)
 		rt3090rfwakeup(ctlr);
 
 	/* disable non-existing Rx chains */
@@ -2500,7 +2875,9 @@
 		rt3090rfsetup(ctlr);
 
 	/* select default channel */
-	if(ctlr->mac_ver >= 0x3071)
+	if(ctlr->mac_ver == 0x3290)
+		rt3290setchan(ctlr, 3);
+	else if(ctlr->mac_ver >= 0x3071)
 		rt3090setchan(ctlr, 3);
 	else
 		setchan(ctlr, 3);
@@ -2564,7 +2941,7 @@
 	Ctlr *ctlr;
 	Wifipkt *w;
 	u8int mcs, qid;
-	int ridx, /*ctl_ridx,*/ hdrlen;
+	int ridx, ctl_ridx, hdrlen;
 	uchar *p;
 	int nodeid;
 	Block *outb;
@@ -2592,7 +2969,10 @@
 
 	pool = &ctlr->pool;
 	qid = 0; /* for now */
-	ridx = 0; 
+	if(wn->minrate >= wifi->rates)
+		ridx = wn->minrate - wifi->rates;
+	else
+		ridx = 0;
 	tx = &ctlr->tx[qid];
 
 	nodeid = ctlr->bcastnodeid;
@@ -2603,26 +2983,43 @@
 	if((w->a1[0] & 1) == 0){
 		*(p+4) = TxAck; /* xflags */
 
+		/* txop, decide if we need protection */
 		if(BLEN(b) > 512-4)
-			*(p+1) = TxTxopBackoff; /* txop */ 
+			*(p+1) = TxTxopHt;
+		else
+			*(p+1) = TxTxopBackoff;
 
 		if((w->fc[0] & 0x0c) == 0x08 &&	ctlr->bssnodeid != -1){
 			nodeid = ctlr->bssnodeid;
-			ridx = 2; /* BUG: hardcode 11Mbit */
+			if(wn->actrate >= wifi->rates)
+				ridx = wn->actrate - wifi->rates;
 		}
 	}
 
-	/*ctl_ridx = rt2860_rates[ridx].ctl_ridx;*/
+	ctl_ridx = rt2860_rates[ridx].ctl_ridx;
 	mcs = rt2860_rates[ridx].mcs;
 
 	/* setup TX Wireless Information */
 	*p = 0; /* flags */
-	*(p+2) = PhyCck | mcs; /* phy */
+	/* phy */
+	if(rt2860_rates[ridx].ofdm)
+		*(p+2) = PhyOfdm | mcs;
+	else{
+		*(p+2) = PhyCck | mcs;
+		if(ridx != 0 && wn->cap & (1<<5))
+			*(p+2) |= PhyShpre;
+	}
 	/* let HW generate seq numbers */
 	*(p+4) |= TxNseq; /* xflags */
 	put16(p + 6, BLEN(b) | (((mcs+1) & 0xf) << TxPidShift) ); /* length */
 
-/*	put16((uchar*)&w->dur[0], rt2860_rates[ctl_ridx].lp_ack_dur); */
+	/* ack duration */
+	if(*(p+4) & TxAck){
+		if(wn->cap & (1<<5))
+			put16(w->dur, rt2860_rates[ctl_ridx].sp_ack_dur);
+		else
+			put16(w->dur, rt2860_rates[ctl_ridx].lp_ack_dur);
+	}
 
 	*(p+5) = nodeid; /* wcid */
 
@@ -2655,9 +3052,9 @@
 
 	p = pool->p + pool->i * TxwiDmaSz;
 	w = (Wifipkt*)(p + Txwisize);
-	if(ctlr->wifi->debug){
-		print("transmit: %E->%E,%E nodeid=%x txq[%d]=%d size=%zd\n", w->a2, w->a1, w->a3, nodeid, qid, ctlr->tx[qid].i, BLEN(outb));
-	}
+	if(ctlr->wifi->debug)
+		print("transmit: %E->%E,%E nodeid=%x txq[%d]=%d size=%zd\n",
+			w->a2, w->a1, w->a3, nodeid, qid, ctlr->tx[qid].i, BLEN(outb));
 
 	tx->i = (tx->i + 1) % Ntx;
 	pool->i = (pool->i + 1) % Ntxpool;
@@ -2674,7 +3071,6 @@
 static void
 rt2860attach(Ether *edev)
 {
-	FWImage *fw;
 	Ctlr *ctlr;
 	char *err;
 
@@ -2691,13 +3087,11 @@
 		if(ctlr->wifi == nil)
 			ctlr->wifi = wifiattach(edev, transmit);
 
-		if(ctlr->fw == nil){
-			fw = readfirmware();
-			ctlr->fw = fw;
-		}
-		if((err = rt2860start(edev)) != nil){
+		ctlr->wifi->rates = rates;
+		if(ctlr->fw == nil)
+			readfirmware(ctlr);
+		if((err = rt2860start(edev)) != nil)
 			error(err);
-		} 
 
 		ctlr->bcastnodeid = -1;
 		ctlr->bssnodeid = -1;
@@ -2841,14 +3235,10 @@
 	debug = ctlr->wifi->debug;
 
 	r = csr32r(ctlr, IntStatus);
-	if(r == 0xffffffff){
-		iunlock(ctlr);
-		return;
-	}
-	if(r == 0){
-		iunlock(ctlr);
-		return;
-	}
+	if(r == 0xffffffff)
+		goto Exit;
+	if(r == 0)
+		goto Exit;
 
 	/* acknowledge interrupts */
 	csr32w(ctlr, IntStatus, r);
@@ -2866,7 +3256,7 @@
 
 		txrxon(ctlr);
 	}
-	if(r & MacInt2)
+	if(r & MacInt2) /* TX status */
 		stats(ctlr);
 	
 	if(r & TxDoneInt5)
@@ -2889,7 +3279,7 @@
 
 	if(r & TxDoneInt0)
 		rt2860tx(ctlr, 0);
-
+Exit:
 	iunlock(ctlr);
 }
 
@@ -2959,7 +3349,7 @@
 	return val;
 }
 
-/* Read 16-bit from eFUSE ROM (>=RT3071 only.) */
+/* Read 16 bits from eFUSE ROM */
 static u16int
 efuseread2(Ctlr *ctlr, u16int addr)
 {
@@ -2968,19 +3358,17 @@
 	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);
+
+	if(ctlr->mac_ver == 0x3290)
+		reg = Rt3290EfuseCtrl;
+	else
+		reg = Rt3070EfuseCtrl;
+	tmp = csr32r(ctlr, reg);
 	tmp &= ~(Rt3070EfsromModeMask | Rt3070EfsromAinMask);
 	tmp |= (addr & ~0xf) << Rt3070EfsromAinShift | Rt3070EfsromKick;
-	csr32w(ctlr, Rt3070EfuseCtrl, tmp);
+	csr32w(ctlr, reg, tmp);
 	for(ntries = 0; ntries < 500; ntries++){
-		tmp = csr32r(ctlr, Rt3070EfuseCtrl);
+		tmp = csr32r(ctlr, reg);
 		if(!(tmp & Rt3070EfsromKick))
 			break;
 		microdelay(2);
@@ -2992,7 +3380,10 @@
 		return 0xffff;	/* address not found */
 
 	/* determine to which 32-bit register our 16-bit word belongs */
-	reg = Rt3070EfuseData3 - (addr & 0xc);
+	if(ctlr->mac_ver == 0x3290)
+		reg = Rt3290EfuseData3 + (addr & 0xc);
+	else
+		reg = Rt3070EfuseData3 - (addr & 0xc);
 	tmp = csr32r(ctlr, reg);
 
 	return (addr & 2) ? tmp >> 16 : tmp & 0xffff;
@@ -3014,7 +3405,10 @@
 	/* check whether the ROM is eFUSE ROM or EEPROM */
 	rom_read = eeread2;
 	if(ctlr->mac_ver >= 0x3071){
-		tmp = csr32r(ctlr, Rt3070EfuseCtrl);
+		if(ctlr->mac_ver == 0x3290)
+			tmp = csr32r(ctlr, Rt3290EfuseCtrl);
+		else
+			tmp = csr32r(ctlr, Rt3070EfuseCtrl);
 		if(tmp & Rt3070SelEfuse)
 			rom_read = efuseread2;
 	}
@@ -3031,7 +3425,7 @@
 	edev->ea[5] = val >> 8;
 
 	/* read vendor BBP settings */
-	for(i = 0; i < 8; i++){
+	for(i = 0; i < nelem(ctlr->bbp); i++){
 		val = rom_read(ctlr, EepromBbpBase + i);
 		ctlr->bbp[i].val = val & 0xff;
 		ctlr->bbp[i].reg = val >> 8;
@@ -3070,6 +3464,11 @@
 			ctlr->rf_rev = Rf3053;
 			ctlr->ntxchains = 3;
 			ctlr->nrxchains = 3;
+		}else if(ctlr->mac_ver == 0x3290){
+			/* default to RF3290 1T1R */
+			ctlr->rf_rev = Rf3290;
+			ctlr->ntxchains = 1;
+			ctlr->nrxchains = 1;
 		}else if(ctlr->mac_ver >= 0x3071){
 			/* default to RF3020 1T1R */
 			ctlr->rf_rev = Rf3020;
@@ -3082,7 +3481,10 @@
 			ctlr->nrxchains = 2;
 		}
 	}else{
-		ctlr->rf_rev = (val >> 8) & 0xf;
+		if(ctlr->mac_ver == 0x3290)
+			ctlr->rf_rev = rom_read(ctlr, EepromChipId);
+		else
+			ctlr->rf_rev = (val >> 8) & 0xf;
 		ctlr->ntxchains = (val >> 4) & 0xf;
 		ctlr->nrxchains = val & 0xf;
 	}
@@ -3270,8 +3672,8 @@
 	return 0;
 }
 
-static const char *
-getrfname(u8int rev)
+static char *
+getrfname(u16int rev)
 {
 	if((rev == 0) || (rev >= nelem(rfnames)))
 		return "unknown";
@@ -3420,13 +3822,17 @@
 	Ctlr *ctlr;
 	int ntries;
 	char *err;
-	u32int tmp;
+	u32int tmp, reg;
 
 	SET(tmp);
 	ctlr = edev->ctlr;
+	if(ctlr->pdev->did == RalinkRT3290)
+		reg = PciCfg;
+	else
+		reg = AsicVerId;
 	/* wait for NIC to initialize */
 	for(ntries = 0; ntries < 100; ntries++){
-		tmp = csr32r(ctlr, AsicVerId);
+		tmp = csr32r(ctlr, reg);
 		if(tmp != 0 && tmp != 0xffffffff)
 			break;
 		microdelay(10);
@@ -3438,18 +3844,15 @@
 	ctlr->mac_ver = tmp >> 16;
 	ctlr->mac_rev = tmp & 0xffff;
 
-	if(ctlr->mac_ver != 0x2860){
+	if(ctlr->mac_ver != 0x2860)
 		switch(ctlr->pdev->did){
-			default:
-					break;
-			case RalinkRT2890:
-			case RalinkRT2790:
-			case RalinkRT3090:
-			case AwtRT2890:
-					ctlr->flags = AdvancedPs;
-					break;
+		case RalinkRT2890:
+		case RalinkRT2790:
+		case AwtRT2890:
+			ctlr->flags |= AdvancedPs;
+		default:
+			break;
 		}
-	}
 	/* retrieve RF rev. no and various other things from EEPROM */
 	eepromread(edev);
 
@@ -3478,17 +3881,18 @@
 		
 		if(pdev->ccrb != 2 || pdev->ccru != 0x80)
 			continue;
-		if(pdev->vid != 0x1814) /* Ralink */
+		if(pdev->vid != Ralink)
 			continue;
 		if(pdev->mem[0].bar & 1)
 			continue;
 
 		switch(pdev->did){
-		default:
-			continue;
 		case RalinkRT2790:
 		case RalinkRT3090:
+		case RalinkRT3290:
 			break;
+		default:
+			continue;
 		}
 
 		ctlr = malloc(sizeof(Ctlr));
@@ -3547,7 +3951,7 @@
 	edev->ctl = rt2860ctl;
 	edev->promiscuous = rt2860promiscuous;
 	edev->multicast = rt2860multicast;
-	edev->mbps = 10;
+	edev->mbps = 54;
 
 	if(rt2860init(edev) < 0){
 		edev->ctlr = nil;

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-07-09  3:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-01 16:08 [9front] Ralink RT3090 driver José Miguel Sánchez García
2021-07-01 19:12 ` kemal
2021-07-09  3:11   ` ori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).