X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Ftsec.c;h=7ec565ca67bf9b3a8c226888c4122b485c72517e;hb=b86d7622b33892b1dafe761a7a9eaeeab9f3816b;hp=0c8b0de58778942b663883fd7366bc948d70fa6e;hpb=cbf9c117282b8729bdb86071997b58fcab58c444;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/tsec.c b/drivers/tsec.c index 0c8b0de..7ec565c 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -21,8 +21,11 @@ #if defined(CONFIG_TSEC_ENET) #include "tsec.h" +#include "miiphy.h" -#define TX_BUF_CNT 2 +DECLARE_GLOBAL_DATA_PTR; + +#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 +123,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 +176,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 +212,11 @@ int tsec_init(struct eth_device* dev, bd_t * bd) for(i=0;ienetaddr[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 +350,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 +391,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 @@ -883,6 +942,56 @@ static struct phy_info phy_info_lxt971 = { }, }; +/* Parse the DP83865's link and auto-neg status register for speed and duplex + * information */ +uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv) +{ + switch (mii_reg & MIIM_DP83865_SPD_MASK) { + + case MIIM_DP83865_SPD_1000: + priv->speed = 1000; + break; + + case MIIM_DP83865_SPD_100: + priv->speed = 100; + break; + + default: + priv->speed = 10; + break; + + } + + if (mii_reg & MIIM_DP83865_DPX_FULL) + priv->duplexity = 1; + else + priv->duplexity = 0; + + return 0; +} + +struct phy_info phy_info_dp83865 = { + 0x20005c7, + "NatSemi DP83865", + 4, + (struct phy_cmd[]) { /* config */ + {MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL}, + {miim_end,} + }, + (struct phy_cmd[]) { /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the link and auto-neg status */ + {MIIM_DP83865_LANR, miim_read, &mii_parse_dp83865_lanr}, + {miim_end,} + }, + (struct phy_cmd[]) { /* shutdown */ + {miim_end,} + }, +}; + struct phy_info *phy_info[] = { #if 0 &phy_info_cis8201, @@ -892,6 +1001,7 @@ struct phy_info *phy_info[] = { &phy_info_M88E1111S, &phy_info_dm9161, &phy_info_lxt971, + &phy_info_dp83865, NULL }; @@ -926,8 +1036,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; @@ -975,7 +1084,6 @@ static void relocate_cmds(void) struct phy_cmd **cmdlistptr; struct phy_cmd *cmd; int i,j,k; - DECLARE_GLOBAL_DATA_PTR; for(i=0; phy_info[i]; i++) { /* First thing's first: relocate the pointers to the @@ -1012,7 +1120,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 +1141,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 +1164,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 +1179,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 */