git: 9front

Download patch

ref: 03ea832847e6356184e12a6ec3b9745836805351
parent: 75e386ea714adb2a8ff3589582877adf74b74457
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sat Feb 16 16:16:05 EST 2013

etheriwl: add otp rom initialization (for 1000er series, untested)

--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -69,6 +69,7 @@
 
 	EepromIo	= 0x02c,	/* EEPROM i/o register */
 	EepromGp	= 0x030,
+		
 	OtpromGp	= 0x034,
 		DevSelOtp	= 1<<16,
 		RelativeAccess	= 1<<17,
@@ -105,6 +106,7 @@
 	AnaPll		= 0x20c,
 
 	Dbghpetmem	= 0x240,
+	Dbglinkpwrmgmt	= 0x250,
 
 	MemRaddr	= 0x40c,
 	MemWaddr	= 0x410,
@@ -355,6 +357,9 @@
 	} rfcfg;
 
 	struct {
+		int	otp;
+		uint	off;
+
 		uchar	version;
 		uchar	type;
 		u16int	volt;
@@ -542,10 +547,11 @@
 eepromread(Ctlr *ctlr, void *data, int count, uint off)
 {
 	uchar *out = data;
-	u32int w;
+	u32int w, s;
 	int i;
 
 	w = 0;
+	off += ctlr->eeprom.off;
 	for(; count > 0; count -= 2, off++){
 		csr32w(ctlr, EepromIo, off << 2);
 		for(i=0; i<10; i++){
@@ -556,6 +562,13 @@
 		}
 		if(i == 10)
 			return "eepromread: timeout";
+		if(ctlr->eeprom.otp){
+			s = csr32r(ctlr, OtpromGp);
+			if(s & EccUncorrStts)
+				return "eepromread: otprom ecc error";
+			if(s & EccCorrStts)
+				csr32w(ctlr, OtpromGp, s);
+		}
 		*out++ = w >> 16;
 		if(count > 1)
 			*out++ = w >> 24;
@@ -728,6 +741,65 @@
 	ctlr->power = 0;
 }
 
+static char*
+rominit(Ctlr *ctlr)
+{
+	uchar buf[2];
+	char *err;
+	uint off;
+	int i;
+
+	ctlr->eeprom.otp = 0;
+	ctlr->eeprom.off = 0;
+	if(ctlr->type < Type1000 || (csr32r(ctlr, OtpromGp) & DevSelOtp) == 0)
+		return nil;
+
+	/* Wait for clock stabilization before accessing prph. */
+	if((err = clockwait(ctlr)) != nil)
+		return err;
+
+	if((err = niclock(ctlr)) != nil)
+		return err;
+	prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq);
+	delay(5);
+	prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq);
+	nicunlock(ctlr);
+
+	/* Set auto clock gate disable bit for HW with OTP shadow RAM. */
+	if(ctlr->type != Type1000)
+		csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
+
+	csr32w(ctlr, EepromGp, csr32r(ctlr, EepromGp) & ~0x00000180);
+
+	/* Clear ECC status. */
+	csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) | (EccCorrStts | EccUncorrStts));
+
+	ctlr->eeprom.otp = 1;
+	if(ctlr->type != Type1000)
+		return nil;
+
+	/* Switch to absolute addressing mode. */
+	csr32w(ctlr, OtpromGp, csr32r(ctlr, OtpromGp) & ~RelativeAccess);
+
+	/*
+	 * Find the block before last block (contains the EEPROM image)
+	 * for HW without OTP shadow RAM.
+	 */
+	off = 0;
+	for(i=0; i<3; i++){
+		if((err = eepromread(ctlr, buf, 2, off)) != nil)
+			return err;
+		if(get16(buf) == 0)
+			break;
+		off = get16(buf);
+	}
+	if(i == 0 || i >= 3)
+		return "rominit: missing eeprom image";
+
+	ctlr->eeprom.off = off+1;
+	return nil;
+}
+
 static int
 iwlinit(Ether *edev)
 {
@@ -747,6 +819,8 @@
 	}
 	if((err = eepromlock(ctlr)) != nil)
 		goto Err;
+	if((err = rominit(ctlr)) != nil)
+		goto Err2;
 	if((err = eepromread(ctlr, edev->ea, sizeof(edev->ea), 0x15)) != nil){
 		eepromunlock(ctlr);
 		goto Err;
--