etheriwl: add otp rom initialization (for 1000er series, untested)
This commit is contained in:
parent
f6290afb14
commit
c5c9233c3d
1 changed files with 75 additions and 1 deletions
|
@ -69,6 +69,7 @@ enum {
|
|||
|
||||
EepromIo = 0x02c, /* EEPROM i/o register */
|
||||
EepromGp = 0x030,
|
||||
|
||||
OtpromGp = 0x034,
|
||||
DevSelOtp = 1<<16,
|
||||
RelativeAccess = 1<<17,
|
||||
|
@ -105,6 +106,7 @@ enum {
|
|||
AnaPll = 0x20c,
|
||||
|
||||
Dbghpetmem = 0x240,
|
||||
Dbglinkpwrmgmt = 0x250,
|
||||
|
||||
MemRaddr = 0x40c,
|
||||
MemWaddr = 0x410,
|
||||
|
@ -355,6 +357,9 @@ struct Ctlr {
|
|||
} rfcfg;
|
||||
|
||||
struct {
|
||||
int otp;
|
||||
uint off;
|
||||
|
||||
uchar version;
|
||||
uchar type;
|
||||
u16int volt;
|
||||
|
@ -542,10 +547,11 @@ static char*
|
|||
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 @@ eepromread(Ctlr *ctlr, void *data, int count, uint off)
|
|||
}
|
||||
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 @@ poweroff(Ctlr *ctlr)
|
|||
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 @@ iwlinit(Ether *edev)
|
|||
}
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue