]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[realtek] Force EEPROM CS low before disabling EEPROM access mode
authorMichael Brown <mcb30@ipxe.org>
Fri, 24 Aug 2012 15:44:29 +0000 (16:44 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 24 Aug 2012 16:26:11 +0000 (17:26 +0100)
Some RTL8169 cards seem to drive the EEPROM CS line high (i.e. active)
when 9346CR.EEM is set to "normal operating mode", with the result
that the CS line is never deasserted.  The symptom of this is that the
first read from the EEPROM will work, while all subsequent reads will
return garbage data.

Reported-by: Thomas Miletich <thomas.miletich@gmail.com>
Debugged-by: Thomas Miletich <thomas.miletich@gmail.com>
Tested-by: Thomas Miletich <thomas.miletich@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/net/realtek.c
src/drivers/net/realtek.h

index 09b3fd06f13c2fdbad747385b3a5f1c77e86387a..76fa47bbc3991b7abcf9ff3a0feb991612a97892 100644 (file)
@@ -60,9 +60,35 @@ static const uint8_t realtek_eeprom_bits[] = {
        [SPI_BIT_SCLK]  = RTL_9346CR_EESK,
        [SPI_BIT_MOSI]  = RTL_9346CR_EEDI,
        [SPI_BIT_MISO]  = RTL_9346CR_EEDO,
-       [SPI_BIT_SS(0)] = ( RTL_9346CR_EECS | RTL_9346CR_EEM1 ),
+       [SPI_BIT_SS(0)] = RTL_9346CR_EECS,
 };
 
+/**
+ * Open bit-bashing interface
+ *
+ * @v basher           Bit-bashing interface
+ */
+static void realtek_spi_open_bit ( struct bit_basher *basher ) {
+       struct realtek_nic *rtl = container_of ( basher, struct realtek_nic,
+                                                spibit.basher );
+
+       /* Enable EEPROM access */
+       writeb ( RTL_9346CR_EEM_EEPROM, rtl->regs + RTL_9346CR );
+}
+
+/**
+ * Close bit-bashing interface
+ *
+ * @v basher           Bit-bashing interface
+ */
+static void realtek_spi_close_bit ( struct bit_basher *basher ) {
+       struct realtek_nic *rtl = container_of ( basher, struct realtek_nic,
+                                                spibit.basher );
+
+       /* Disable EEPROM access */
+       writeb ( RTL_9346CR_EEM_NORMAL, rtl->regs + RTL_9346CR );
+}
+
 /**
  * Read input bit
  *
@@ -108,6 +134,8 @@ static void realtek_spi_write_bit ( struct bit_basher *basher,
 
 /** SPI bit-bashing interface */
 static struct bit_basher_operations realtek_basher_ops = {
+       .open = realtek_spi_open_bit,
+       .close = realtek_spi_close_bit,
        .read = realtek_spi_read_bit,
        .write = realtek_spi_write_bit,
 };
index 2591e7255817d0cb4290876b9a127d7115eb8fc5..6a7b10a9314bc19f6306b8d481646fe016019a7f 100644 (file)
@@ -158,8 +158,9 @@ enum realtek_legacy_status {
 
 /** 93C46 (93C56) Command Register (byte) */
 #define RTL_9346CR 0x50
-#define RTL_9346CR_EEM1                0x80    /**< Mode select bit 1 */
-#define RTL_9346CR_EEM0                0x40    /**< Mode select bit 0 */
+#define RTL_9346CR_EEM(x)      ( (x) << 6 ) /**< Mode select */
+#define RTL_9346CR_EEM_EEPROM  RTL_9346CR_EEM ( 0x2 ) /**< EEPROM mode */
+#define RTL_9346CR_EEM_NORMAL  RTL_9346CR_EEM ( 0x0 ) /**< Normal mode */
 #define RTL_9346CR_EECS                0x08    /**< Chip select */
 #define RTL_9346CR_EESK                0x04    /**< Clock */
 #define RTL_9346CR_EEDI                0x02    /**< Data in */