aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBen Dooks2008-02-05 00:02:17 +0000
committerJeff Garzik2008-02-11 11:06:33 -0500
commit39c341a8dcf060b246b0beddac90cd7de11d4a20 (patch)
treeb71d29ba042edcd2dbb19da2f783eff4d27fd3a7 /drivers
parentc991d168cb649d416c5a773a50d0754299f31366 (diff)
DM9000: Fix delays used by EEPROM read and write
The code was using a delay of 8ms, when it should have been using the EEPROM status flag from the device to indicate the EEPROM transaction had finished. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/dm9000.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 851618338b2e..1d790a8e3a98 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1048,6 +1048,50 @@ dm9000_rx(struct net_device *dev)
} while (rxbyte == DM9000_PKT_RDY);
}
+static unsigned int
+dm9000_read_locked(board_info_t *db, int reg)
+{
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&db->lock, flags);
+ ret = ior(db, reg);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ return ret;
+}
+
+static int dm9000_wait_eeprom(board_info_t *db)
+{
+ unsigned int status;
+ int timeout = 8; /* wait max 8msec */
+
+ /* The DM9000 data sheets say we should be able to
+ * poll the ERRE bit in EPCR to wait for the EEPROM
+ * operation. From testing several chips, this bit
+ * does not seem to work.
+ *
+ * We attempt to use the bit, but fall back to the
+ * timeout (which is why we do not return an error
+ * on expiry) to say that the EEPROM operation has
+ * completed.
+ */
+
+ while (1) {
+ status = dm9000_read_locked(db, DM9000_EPCR);
+
+ if ((status & EPCR_ERRE) == 0)
+ break;
+
+ if (timeout-- < 0) {
+ dev_dbg(db->dev, "timeout waiting EEPROM\n");
+ break;
+ }
+ }
+
+ return 0;
+}
+
/*
* Read a word data from EEPROM
*/
@@ -1065,8 +1109,10 @@ dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
spin_unlock_irqrestore(&db->lock, flags);
- mdelay(8); /* according to the datasheet 200us should be enough,
- but it doesn't work */
+ dm9000_wait_eeprom(db);
+
+ /* delay for at-least 150uS */
+ msleep(1);
spin_lock_irqsave(&db->lock, flags);
@@ -1097,7 +1143,9 @@ dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
spin_unlock_irqrestore(&db->lock, flags);
- mdelay(8); /* same shit */
+ dm9000_wait_eeprom(db);
+
+ mdelay(1); /* wait at least 150uS to clear */
spin_lock_irqsave(&db->lock, flags);
iow(db, DM9000_EPCR, 0);