Commit 39c341a8 authored by Ben Dooks's avatar Ben Dooks Committed by Jeff Garzik
Browse files

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: default avatarBen Dooks <ben-linux@fluff.org>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent c991d168
Loading
Loading
Loading
Loading
+51 −3
Original line number Diff line number Diff line
@@ -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);