[RFC] net: dm9k: fix reset routine
Antony Pavlov
antonynpavlov at gmail.com
Thu Sep 11 04:20:01 PDT 2014
Based on Linux's commit:
commit 09ee9f87d02e779e4fc3f5c29212c733d6d6e349
Author: Michael Abbott <michael.abbott at diamond.ac.uk>
Date: Wed Oct 16 11:41:33 2013 +0300
dm9000: Implement full reset of DM9000 network device
A Davicom application note for the DM9000 network device recommends
performing software reset twice to correctly initialise the device.
Without this reset some devices fail to initialise correctly on
system startup.
N.B. DM9000B on MIPS Creator CI20 board needs additional workaround
(see the 'Make all GPIO pins outputs' and 'Power internal PHY' lines).
This workaround was taken from this U-boot's commit:
commit fbcb7ece0ea1e364180f1cf963e0fa0ce7f6560d
Author: Remy Bohmer <linux at bohmer.net>
Date: Tue Jun 3 15:26:24 2008 +0200
DM9000: Improve eth_reset() routine
According to the application notes of the DM9000 v1.22 chapter 5.2 bullet 2, the
reset procedure must be done twice to properly reset the DM9000 by means of software.
This errata is not needed anymore for the DM9000A, but it does not bother it.
This change has been tested with DM9000A, DM9000E, DM9000EP.
Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
drivers/net/dm9k.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dm9k.c b/drivers/net/dm9k.c
index 9e7b415..b407f19 100644
--- a/drivers/net/dm9k.c
+++ b/drivers/net/dm9k.c
@@ -48,6 +48,7 @@
# define NCR_FCOL (1 << 4)
# define NCR_FDX (1 << 3)
# define NCR_LBK (3 << 1)
+# define NCR_MAC_LBK (1 << 1)
# define NCR_RST (1 << 0)
#define DM9K_NSR 0x01
@@ -471,8 +472,28 @@ static void dm9k_reset(struct dm9k *priv)
struct device_d *dev = priv->miibus.parent;
dev_dbg(dev, "%s\n", __func__);
- dm9k_iow(priv, DM9K_NCR, NCR_RST);
- udelay(1000); /* delay 1ms */
+
+ /* Reset DM9000, see DM9000 Application Notes V1.22 Jun 11, 2004 page 29
+ * The essential point is that we have to do a double reset, and the
+ * instruction is to set LBK into MAC internal loopback mode.
+ */
+
+ /* Make all GPIO pins outputs */
+ dm9k_iow(priv, DM9K_GPCR, 0x0F);
+ /* Power internal PHY by writing 0 to GPIO0 pin */
+ dm9k_iow(priv, DM9K_GPR, 0);
+
+ dm9k_iow(priv, DM9K_NCR, NCR_RST | NCR_MAC_LBK);
+ udelay(100); /* Application note says at least 20 us */
+ if (dm9k_ior(priv, DM9K_NCR) & NCR_RST)
+ dev_err(dev, "dm9000 did not respond to first reset\n");
+
+ dm9k_iow(priv, DM9K_NCR, 0);
+ dm9k_iow(priv, DM9K_NCR, NCR_RST | NCR_MAC_LBK);
+ udelay(100);
+
+ if (dm9k_ior(priv, DM9K_NCR) & NCR_RST)
+ dev_err(dev, "dm9000 did not respond to second reset\n");
}
static int dm9k_eth_open(struct eth_device *edev)
--
2.1.0
More information about the barebox
mailing list