ref: d8487e98c64cc1473e6d4158392850a9d434e418
parent: 6198954859caa0de243756291c8dad75b71dcaee
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed May 20 05:49:27 EDT 2015
etherigbe: spi eeprom support (thanks echoline)
--- a/sys/src/9/pc/etherigbe.c
+++ b/sys/src/9/pc/etherigbe.c
@@ -1572,6 +1572,12 @@
else
r = i;
continue;
+ case 'H':
+ eecd |= Do;
+ continue;
+ case 'h':
+ eecd &= ~Do;
+ continue;
case 'I': /* assert data input */
eecd |= Di;
break;
@@ -1586,7 +1592,10 @@
break;
}
csr32w(ctlr, Eecd, eecd);
- microdelay(50);
+ if (eecd & Spi)
+ microdelay(1);
+ else
+ microdelay(50);
}
if(loop >= 0)
return -1;
@@ -1600,18 +1609,9 @@
char rop[20];
int addr, areq, bits, data, eecd, i;
+ sum = 0;
eecd = csr32r(ctlr, Eecd);
- if(eecd & Spi){
- print("igbe: SPI EEPROM access not implemented\n");
- return 0;
- }
- if(eecd & (Eeszaddr|Eesz256))
- bits = 8;
- else
- bits = 6;
- sum = 0;
-
switch(ctlr->id){
default:
areq = 0;
@@ -1641,23 +1641,63 @@
}
break;
}
- snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
- for(addr = 0; addr < 0x40; addr++){
- /*
- * Read a word at address 'addr' from the Atmel AT93C46
- * 3-Wire Serial EEPROM or compatible. The EEPROM access is
- * controlled by 4 bits in Eecd. See the AT93C46 datasheet
- * for protocol details.
- */
- if(at93c46io(ctlr, rop, (0x06<<bits)|addr) != 0){
- print("igbe: can't set EEPROM address 0x%2.2X\n", addr);
+ if(eecd & Spi){
+ for(i = 0; i < 1000; i++){
+ at93c46io(ctlr, "H :8HDCc;", 0x05);
+ data = at93c46io(ctlr, "h :8COc;", 0);
+
+ if (!(data & 0x1))
+ break;
+
+ microdelay(5);
+ at93c46io(ctlr, "Ss", 0);
+ }
+ if(i == 1000){
+ print("igbe: SPI EEPROM not ready\n");
goto release;
}
- data = at93c46io(ctlr, ":16COc;", 0);
- at93c46io(ctlr, "sic", 0);
- ctlr->eeprom[addr] = data;
- sum += data;
+
+ at93c46io(ctlr, "Ss H :8HDCc;", 0x03);
+
+ if(eecd & Eeszaddr)
+ bits = 16;
+ else
+ bits = 8;
+ snprint(rop, sizeof(rop), "H :%dHDCc;", bits);
+ if(at93c46io(ctlr, rop, 0) != 0){
+ print("igbe: can't set EEPROM address 0x00\n");
+ goto release;
+ }
+
+ for(addr = 0; addr < 0x40; addr++){
+ data = at93c46io(ctlr, "h :16COc;", 0);
+ ctlr->eeprom[addr] = (data >> 8) | (data << 8);
+ sum += ctlr->eeprom[addr];
+ }
+ } else {
+ if(eecd & (Eeszaddr|Eesz256))
+ bits = 8;
+ else
+ bits = 6;
+ snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
+
+ for(addr = 0; addr < 0x40; addr++){
+ /*
+ * Read a word at address 'addr' from the Atmel AT93C46
+ * 3-Wire Serial EEPROM or compatible. The EEPROM access is
+ * controlled by 4 bits in Eecd. See the AT93C46 datasheet
+ * for protocol details.
+ */
+ if(at93c46io(ctlr, rop, (0x06<<bits)|addr) != 0){
+ print("igbe: can't set EEPROM address 0x%2.2X\n", addr);
+ goto release;
+ }
+ data = at93c46io(ctlr, ":16COc;", 0);
+ at93c46io(ctlr, "sic", 0);
+ ctlr->eeprom[addr] = data;
+ sum += data;
+ }
}
release: