summaryrefslogtreecommitdiffstats
path: root/drivers/tsec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tsec.c')
-rw-r--r--drivers/tsec.c94
1 files changed, 77 insertions, 17 deletions
diff --git a/drivers/tsec.c b/drivers/tsec.c
index 0c8b0de587..f860dae8b0 100644
--- a/drivers/tsec.c
+++ b/drivers/tsec.c
@@ -21,8 +21,9 @@
#if defined(CONFIG_TSEC_ENET)
#include "tsec.h"
+#include "miiphy.h"
-#define TX_BUF_CNT 2
+#define TX_BUF_CNT 2
static uint rxIdx; /* index of the current RX buffer */
static uint txIdx; /* index of the current TX buffer */
@@ -120,6 +121,10 @@ struct phy_info * get_phy_info(struct eth_device *dev);
void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
static void adjust_link(struct eth_device *dev);
static void relocate_cmds(void);
+static int tsec_miiphy_write(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value);
+static int tsec_miiphy_read(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value);
/* Initialize device structure. Returns success if PHY
* initialization succeeded (i.e. if it recognizes the PHY)
@@ -169,6 +174,11 @@ int tsec_initialize(bd_t *bis, int index, char *devname)
priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
+ && !defined(BITBANGMII)
+ miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
+#endif
+
/* Try to initialize PHY here, and return */
return init_phy(dev);
}
@@ -200,11 +210,11 @@ int tsec_init(struct eth_device* dev, bd_t * bd)
for(i=0;i<MAC_ADDR_LEN;i++) {
tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
}
- (uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));
+ regs->macstnaddr1 = *((uint *)(tmpbuf));
tempval = *((uint *)(tmpbuf +4));
- (uint)(regs->macstnaddr2) = tempval;
+ regs->macstnaddr2 = tempval;
/* reset the indices to zero */
rxIdx = 0;
@@ -338,16 +348,35 @@ uint mii_cr_init(uint mii_reg, struct tsec_private *priv)
* auto-negotiation */
uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)
{
- uint timeout = TSEC_TIMEOUT;
-
- if(mii_reg & MIIM_STATUS_LINK)
- priv->link = 1;
- else
- priv->link = 0;
+ /*
+ * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
+ */
+ mii_reg = read_phy_reg(priv, MIIM_STATUS);
+ if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
+ int i = 0;
+
+ puts ("Waiting for PHY auto negotiation to complete");
+ while (!((mii_reg & PHY_BMSR_AUTN_COMP) && (mii_reg & MIIM_STATUS_LINK))) {
+ /*
+ * Timeout reached ?
+ */
+ if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+ puts (" TIMEOUT !\n");
+ priv->link = 0;
+ break;
+ }
- if(priv->link) {
- while((!(mii_reg & MIIM_STATUS_AN_DONE)) && timeout--)
+ if ((i++ % 1000) == 0) {
+ putc ('.');
+ }
+ udelay (1000); /* 1 ms */
mii_reg = read_phy_reg(priv, MIIM_STATUS);
+ }
+ puts (" done\n");
+ priv->link = 1;
+ udelay (500000); /* another 500 ms (results in faster booting) */
+ } else {
+ priv->link = 1;
}
return 0;
@@ -360,6 +389,34 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
{
uint speed;
+ mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
+
+ if (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
+ (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
+ int i = 0;
+
+ puts ("Waiting for PHY realtime link");
+ while (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
+ (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
+ /*
+ * Timeout reached ?
+ */
+ if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+ puts (" TIMEOUT !\n");
+ priv->link = 0;
+ break;
+ }
+
+ if ((i++ % 1000) == 0) {
+ putc ('.');
+ }
+ udelay (1000); /* 1 ms */
+ mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
+ }
+ puts (" done\n");
+ udelay (500000); /* another 500 ms (results in faster booting) */
+ }
+
if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
priv->duplexity = 1;
else
@@ -926,8 +983,7 @@ struct phy_info * get_phy_info(struct eth_device *dev)
printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
return NULL;
} else {
- printf("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
- phy_ID);
+ debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
}
return theInfo;
@@ -1012,7 +1068,8 @@ static void relocate_cmds(void)
}
-#ifndef CONFIG_BITBANGMII
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
+ && !defined(BITBANGMII)
struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
{
@@ -1032,7 +1089,8 @@ struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
* Returns:
* 0 on success
*/
-int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
+static int tsec_miiphy_read(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value)
{
unsigned short ret;
struct tsec_private *priv = get_priv_for_phy(addr);
@@ -1054,7 +1112,8 @@ int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
* Returns:
* 0 on success
*/
-int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
+static int tsec_miiphy_write(char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value)
{
struct tsec_private *priv = get_priv_for_phy(addr);
@@ -1068,6 +1127,7 @@ int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
return 0;
}
-#endif /* CONFIG_BITBANGMII */
+#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+ && !defined(BITBANGMII) */
#endif /* CONFIG_TSEC_ENET */
OpenPOWER on IntegriCloud