This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
i82546 eeprom fixes
- From: Mark Salter <msalter at redhat dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: Mon, 17 Mar 2003 21:49:01 -0500 (EST)
- Subject: i82546 eeprom fixes
Index: devs/eth/intel/i82544/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/intel/i82544/current/ChangeLog,v
retrieving revision 1.6
diff -u -p -5 -r1.6 ChangeLog
--- devs/eth/intel/i82544/current/ChangeLog 11 Mar 2003 19:56:15 -0000 1.6
+++ devs/eth/intel/i82544/current/ChangeLog 18 Mar 2003 02:37:55 -0000
@@ -1,5 +1,10 @@
+2003-03-17 Mark Salter <msalter at redhat dot com>
+
+ * src/if_i82544.c: Fix 82546 EEPROM access. Fix ESA address for second
+ port of 82546.
+
2003-03-11 Mark Salter <msalter at redhat dot com>
* src/if_i82544.c (find_82544s_match_func): Add 82546 devid.
2003-02-05 Nick Garnett <nickg at calivar dot com>
Index: devs/eth/intel/i82544/current/src/if_i82544.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/intel/i82544/current/src/if_i82544.c,v
retrieving revision 1.6
diff -u -p -5 -r1.6 if_i82544.c
--- devs/eth/intel/i82544/current/src/if_i82544.c 11 Mar 2003 19:56:15 -0000 1.6
+++ devs/eth/intel/i82544/current/src/if_i82544.c 18 Mar 2003 02:37:57 -0000
@@ -392,10 +392,14 @@ static inline cyg_uint32 bus_to_virt(cyg
// EEPROM_Ctrl bits.
#define EE_SHIFT_CLK 0x01 // EEPROM shift clock.
#define EE_CS 0x02 // EEPROM chip select.
#define EE_DATA_WRITE 0x04 // EEPROM chip data in.
#define EE_DATA_READ 0x08 // EEPROM chip data out.
+#define EE_REQ 0x40 // EEPROM request (82546 only)
+#define EE_GNT 0x80 // EEPROM grant (82546 only)
+#define EE_PRES 0x100 // EEPROM present (82546 only)
+#define EE_SIZE 0x200 // EEPROM size (82546 only)
#define EE_ENB (0x10|EE_CS)
// ------------------------------------------------------------------------
//
@@ -791,14 +795,13 @@ static int mii_read_register( struct i82
MII_WRITE_REGNUM( regnum );
MII_READ_TURNAROUND();
value = MII_READ_REGVAL();
MII_IDLE();
}
- else if( p_i82544->device == 0x1008 )
+ else
{
- // An 82544, read MII register via MDIC register.
- // UNTESTED
+ // Others, read MII register via MDIC register.
cyg_uint32 mdic = (2<<26) | (phy<<21) | (regnum<<16);
OUTL( mdic, ioaddr + I82544_MDIC );
@@ -830,14 +833,13 @@ static void mii_write_register( struct i
MII_WRITE_REGNUM( regnum );
MII_WRITE_TURNAROUND();
MII_WRITE_REGVAL( value );
MII_IDLE();
}
- else if( p_i82544->device == 0x1008 )
+ else
{
- // An 82544, write MII register via MDIC register.
- // UNTESTED
+ // Others, write MII register via MDIC register.
cyg_uint32 mdic = (1<<26) | (phy<<21) | (regnum<<16) | (value&0xFFFF);
OUTL( mdic, ioaddr + I82544_MDIC );
@@ -899,11 +901,21 @@ static void show_phy( struct i82544 *p_i
static inline void ee_select( int ioaddr )
{
cyg_uint32 l;
- l = EE_ENB;
+ l = INL( ioaddr + I82544_EECD );
+ if (l & EE_PRES) {
+ // i82546 has EE_PRES bit and requires REQ/GNT before EEPROM access
+ l |= EE_REQ;
+ OUTL( l, ioaddr + I82544_EECD );
+ EE_DELAY();
+ while ((l & EE_GNT) == 0)
+ l = INL( ioaddr + I82544_EECD );
+ }
+ l &= ~0x3f;
+ l |= EE_ENB;
OUTL( l, ioaddr + I82544_EECD );
EE_DELAY();
l |= EE_CS;
OUTL( l, ioaddr + I82544_EECD );
l = INL( ioaddr + I82544_EECD );
@@ -912,23 +924,29 @@ static inline void ee_select( int ioaddr
}
static inline void ee_deselect( int ioaddr )
{
cyg_uint32 l;
- l = EE_ENB;
+ l = INL( ioaddr + I82544_EECD ) & ~0x3f;
+ l |= EE_ENB;
OUTL( l, ioaddr + I82544_EECD );
EE_PRINTF( "ee_deselect 1 : " EE_STUFF );
EE_DELAY();
EE_DELAY();
EE_DELAY();
- l = EE_ENB & ~EE_CS;
+ l &= ~EE_CS;
OUTL( l, ioaddr + I82544_EECD );
l = INL( ioaddr + I82544_EECD );
EE_PRINTF( "ee_deselect 2 : " EE_STUFF );
EE_DELAY();
EE_DELAY();
EE_DELAY();
+ if (l & EE_REQ) {
+ l &= ~EE_REQ;
+ OUTL( l, ioaddr + I82544_EECD );
+ EE_DELAY();
+ }
}
static inline void ee_clock_up( int ioaddr )
{
cyg_uint32 l;
@@ -986,78 +1004,25 @@ static inline void ee_write_data_bit( in
// ------------------------------------------------------------------------
static int
get_eeprom_size( struct i82544 *p_i82544 )
{
-// int i, addrbits, tmp;
-// cyg_uint32 ioaddr = p_i82544->io_address;
+ cyg_uint32 l, ioaddr = p_i82544->io_address;
#ifdef DEBUG_EE
diag_printf( "get_eeprom_size\n" );
#endif
-#if 1
- return 6;
-#else
- // Should already be not-selected, but anyway:
- EE_SELECT();
-
-#ifdef DEBUG_EE
- diag_printf( "send command\n" );
-#endif
-
- // Shift the read command bits out.
- for (i = 3; i >= 0; i--) { // Doc says to shift out a zero then:
- tmp = (6 & (1 << i)) ? 1 : 0; // "6" is the "read" command.
- EE_WRITE_DATA_BIT(tmp);
- EE_CLOCK_UP();
- EE_CLOCK_DOWN();
- }
-#ifdef DEBUG_EE
- diag_printf( "send address zero\n" );
-#endif
- // Now clock out address zero, looking for the dummy 0 data bit
- for ( i = 1; i <= 12; i++ ) {
- EE_WRITE_DATA_BIT(0);
- EE_CLOCK_UP();
- tmp = EE_READ_DATA_BIT();
- EE_CLOCK_DOWN();
- if ( !tmp )
- break;
- }
-
-#ifdef DEBUG_EE
- diag_printf( "eeprom data bits %d\n", i );
-#endif
-
- if ( 6 != i && 8 != i && 1 != i) {
+ l = INL( ioaddr + I82544_EECD );
+ if (l & EE_PRES) {
#ifdef DEBUG_EE
- diag_printf( "*****EEPROM data bits not 6, 8 or 1*****\n" );
+ diag_printf("eeprom size: %d\n", (l & EE_SIZE) ? 8 : 6 );
#endif
- addrbits = 1; // Flag no eeprom here.
- }
- else
- addrbits = i;
-
- // read in the data regardless
- tmp = 0;
- for (i = 15; i >= 0; i--) {
- EE_CLOCK_UP();
- if ( EE_READ_DATA_BIT() )
- tmp |= (1<<i);
- EE_CLOCK_DOWN();
+ return (l & EE_SIZE) ? 8 : 6;
}
-#ifdef DEBUG_EE
- diag_printf( "eeprom first data word %x\n", tmp );
-#endif
-
- // Terminate the EEPROM access.
- EE_DESELECT();
-
- return addrbits;
-#endif
+ return 6;
}
static int
read_eeprom_word( struct i82544 *p_i82544, int addrbits, int address )
{
@@ -1255,10 +1220,16 @@ i82544_init(struct cyg_netdevtab_entry *
{
p_i82544->mac_addr_ok = 1;
#ifdef DEBUG_EE
os_printf("Valid EEPROM checksum\n");
#endif
+ // Second port of dual-port 82546 uses EEPROM ESA | 1
+ if (p_i82544->device == 0x1010) {
+ cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(p_i82544->devid);
+ if (CYG_PCI_DEV_GET_FN(devfn) == 1)
+ mac_address[5] |= 1;
+ }
eth_set_mac_address(p_i82544, mac_address, 0);
}
}
// record the MAC address in the device structure