summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2012-08-24 17:44:29 +0200
committerMichael Brown2012-08-24 18:26:11 +0200
commit70618161ad66cabee15a36554d72169e6b9ea3a9 (patch)
tree24cbc8d8e458a0a76a9bacd5e36b6f16b97ee705
parent[bitbash] Add optional open() and close() methods for bit-bashing interfaces (diff)
downloadipxe-70618161ad66cabee15a36554d72169e6b9ea3a9.tar.gz
ipxe-70618161ad66cabee15a36554d72169e6b9ea3a9.tar.xz
ipxe-70618161ad66cabee15a36554d72169e6b9ea3a9.zip
[realtek] Force EEPROM CS low before disabling EEPROM access mode
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>
-rw-r--r--src/drivers/net/realtek.c30
-rw-r--r--src/drivers/net/realtek.h5
2 files changed, 32 insertions, 3 deletions
diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c
index 09b3fd06..76fa47bb 100644
--- a/src/drivers/net/realtek.c
+++ b/src/drivers/net/realtek.c
@@ -60,10 +60,36 @@ 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
*
* @v basher Bit-bashing interface
@@ -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,
};
diff --git a/src/drivers/net/realtek.h b/src/drivers/net/realtek.h
index 2591e725..6a7b10a9 100644
--- a/src/drivers/net/realtek.h
+++ b/src/drivers/net/realtek.h
@@ -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 */