]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/net/tsec.c
tsec: Clean up Broadcom PHY status parsing
[people/ms/u-boot.git] / drivers / net / tsec.c
index a9ba68399a1545a583543d6a48515a99f051a1e4..76902bcd83505d2262d7f45737375d26156f2b1f 100644 (file)
@@ -5,7 +5,7 @@
  * terms of the GNU Public License, Version 2, incorporated
  * herein by reference.
  *
- * Copyright (C) 2004-2009 Freescale Semiconductor, Inc.
+ * Copyright 2004-2009 Freescale Semiconductor, Inc.
  * (C) Copyright 2003, Motorola, Inc.
  * author Andy Fleming
  *
@@ -17,6 +17,7 @@
 #include <net.h>
 #include <command.h>
 #include <tsec.h>
+#include <asm/errno.h>
 
 #include "miiphy.h"
 
@@ -34,8 +35,6 @@ typedef volatile struct rtxbd {
 
 #define MAXCONTROLLERS (8)
 
-static int relocated = 0;
-
 static struct tsec_private *privlist[MAXCONTROLLERS];
 static int num_tsecs = 0;
 
@@ -58,7 +57,6 @@ uint read_phy_reg(struct tsec_private *priv, uint regnum);
 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);
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
        && !defined(BITBANGMII)
 static int tsec_miiphy_write(char *devname, unsigned char addr,
@@ -82,7 +80,7 @@ static struct tsec_info_struct tsec_info[] = {
 #ifdef CONFIG_MPC85XX_FEC
        {
                .regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000),
-               .miiregs = (tsec_t *)(TSEC_BASE_ADDR),
+               .miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR),
                .devname = CONFIG_MPC85XX_FEC_NAME,
                .phyaddr = FEC_PHY_ADDR,
                .flags = FEC_FLAGS
@@ -135,6 +133,7 @@ int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)
        privlist[num_tsecs++] = priv;
        priv->regs = tsec_info->regs;
        priv->phyregs = tsec_info->miiregs;
+       priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
 
        priv->phyaddr = tsec_info->phyaddr;
        priv->flags = tsec_info->flags;
@@ -221,7 +220,7 @@ int tsec_init(struct eth_device *dev, bd_t * bd)
 }
 
 /* Writes the given phy's reg with value, using the specified MDIO regs */
-static void tsec_local_mdio_write(volatile tsec_t *phyregs, uint addr,
+static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr,
                uint reg, uint value)
 {
        int timeout = 1000000;
@@ -244,7 +243,7 @@ static void tsec_local_mdio_write(volatile tsec_t *phyregs, uint addr,
  * notvalid bit cleared), and the bus to cease activity (miimind
  * busy bit cleared), and then returns the value
  */
-uint tsec_local_mdio_read(volatile tsec_t *phyregs, uint phyid, uint regnum)
+uint tsec_local_mdio_read(volatile tsec_mdio_t *phyregs, uint phyid, uint regnum)
 {
        uint value;
 
@@ -278,22 +277,23 @@ uint tsec_local_mdio_read(volatile tsec_t *phyregs, uint phyid, uint regnum)
                | TBIANA_FULL_DUPLEX \
                )
 
+/* Force the TBI PHY into 1000Mbps full duplex when in SGMII mode */
 #define TBICR_SETTINGS ( \
                TBICR_PHY_RESET \
-               | TBICR_ANEG_ENABLE \
                | TBICR_FULL_DUPLEX \
                | TBICR_SPEED1_SET \
                )
+
 /* Configure the TBI for SGMII operation */
 static void tsec_configure_serdes(struct tsec_private *priv)
 {
        /* Access TBI PHY registers at given TSEC register offset as opposed to the
         * register offset used for external PHY accesses */
-       tsec_local_mdio_write(priv->regs, priv->regs->tbipa, TBI_ANA,
+       tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_ANA,
                        TBIANA_SETTINGS);
-       tsec_local_mdio_write(priv->regs, priv->regs->tbipa, TBI_TBICON,
+       tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_TBICON,
                        TBICON_CLK_SELECT);
-       tsec_local_mdio_write(priv->regs, priv->regs->tbipa, TBI_CR,
+       tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_CR,
                        TBICR_SETTINGS);
 }
 
@@ -305,12 +305,10 @@ static int init_phy(struct eth_device *dev)
 {
        struct tsec_private *priv = (struct tsec_private *)dev->priv;
        struct phy_info *curphy;
-       volatile tsec_t *phyregs = priv->phyregs;
        volatile tsec_t *regs = priv->regs;
 
        /* Assign a Physical address to the TBI */
        regs->tbipa = CONFIG_SYS_TBIPA_VALUE;
-       phyregs->tbipa = CONFIG_SYS_TBIPA_VALUE;
        asm("sync");
 
        /* Reset MII (due to new addresses) */
@@ -320,9 +318,6 @@ static int init_phy(struct eth_device *dev)
        asm("sync");
        while (priv->phyregs->miimind & MIIMIND_BUSY) ;
 
-       if (0 == relocated)
-               relocate_cmds();
-
        /* Get the cmd structure corresponding to the attached
         * PHY */
        curphy = get_phy_info(dev);
@@ -356,8 +351,8 @@ uint mii_cr_init(uint mii_reg, struct tsec_private * priv)
                return MIIM_CR_INIT;
 }
 
-/* Parse the status register for link, and then do
- * auto-negotiation
+/*
+ * Wait for auto-negotiation to complete, then determine link
  */
 uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
 {
@@ -366,8 +361,7 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
         * (ie - we're capable and it's not done)
         */
        mii_reg = read_phy_reg(priv, MIIM_STATUS);
-       if ((mii_reg & MIIM_STATUS_LINK) && (mii_reg & PHY_BMSR_AUTN_ABLE)
-           && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
+       if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
                int i = 0;
 
                puts("Waiting for PHY auto negotiation to complete");
@@ -381,6 +375,12 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
                                return 0;
                        }
 
+                       if (ctrlc()) {
+                               puts("user interrupt!\n");
+                               priv->link = 0;
+                               return -EINTR;
+                       }
+
                        if ((i++ % 1000) == 0) {
                                putc('.');
                        }
@@ -388,15 +388,15 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
                        mii_reg = read_phy_reg(priv, MIIM_STATUS);
                }
                puts(" done\n");
-               priv->link = 1;
+
+               /* Link status bit is latched low, read it again */
+               mii_reg = read_phy_reg(priv, MIIM_STATUS);
+
                udelay(500000); /* another 500 ms (results in faster booting) */
-       } else {
-               if (mii_reg & MIIM_STATUS_LINK)
-                       priv->link = 1;
-               else
-                       priv->link = 0;
        }
 
+       priv->link = mii_reg & MIIM_STATUS_LINK ? 1 : 0;
+
        return 0;
 }
 
@@ -488,50 +488,41 @@ uint mii_BCM54xx_wirespeed(uint mii_reg, struct tsec_private *priv)
  */
 uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv)
 {
+       /* If there is no link, speed and duplex don't matter */
+       if (!priv->link)
+               return 0;
 
-       switch((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >> MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT){
-
-               case 1:
-                       printf("Enet starting in 10BT/HD\n");
-                       priv->duplexity = 0;
-                       priv->speed = 10;
-                       break;
-
-               case 2:
-                       printf("Enet starting in 10BT/FD\n");
-                       priv->duplexity = 1;
-                       priv->speed = 10;
-                       break;
-
-               case 3:
-                       printf("Enet starting in 100BT/HD\n");
-                       priv->duplexity = 0;
-                       priv->speed = 100;
-                       break;
-
-               case 5:
-                       printf("Enet starting in 100BT/FD\n");
-                       priv->duplexity = 1;
-                       priv->speed = 100;
-                       break;
-
-               case 6:
-                       printf("Enet starting in 1000BT/HD\n");
-                       priv->duplexity = 0;
-                       priv->speed = 1000;
-                       break;
-
-               case 7:
-                       printf("Enet starting in 1000BT/FD\n");
-                       priv->duplexity = 1;
-                       priv->speed = 1000;
-                       break;
-
-               default:
-                       printf("Auto-neg error, defaulting to 10BT/HD\n");
-                       priv->duplexity = 0;
-                       priv->speed = 10;
-                       break;
+       switch ((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >>
+               MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT) {
+       case 1:
+               priv->duplexity = 0;
+               priv->speed = 10;
+               break;
+       case 2:
+               priv->duplexity = 1;
+               priv->speed = 10;
+               break;
+       case 3:
+               priv->duplexity = 0;
+               priv->speed = 100;
+               break;
+       case 5:
+               priv->duplexity = 1;
+               priv->speed = 100;
+               break;
+       case 6:
+               priv->duplexity = 0;
+               priv->speed = 1000;
+               break;
+       case 7:
+               priv->duplexity = 1;
+               priv->speed = 1000;
+               break;
+       default:
+               printf("Auto-neg error, defaulting to 10BT/HD\n");
+               priv->duplexity = 0;
+               priv->speed = 10;
+               break;
        }
 
        return 0;
@@ -733,7 +724,7 @@ uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv)
 uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
 {
        uint phyid;
-       volatile tsec_t *regbase = priv->phyregs;
+       volatile tsec_mdio_t *regbase = priv->phyregs;
        int timeout = 1000000;
 
        for (phyid = 0; phyid < 4; phyid++) {
@@ -1766,7 +1757,7 @@ void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
 {
        int i;
        uint result;
-       volatile tsec_t *phyregs = priv->phyregs;
+       volatile tsec_mdio_t *phyregs = priv->phyregs;
 
        phyregs->miimcfg = MIIMCFG_RESET;
 
@@ -1794,49 +1785,6 @@ void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
        }
 }
 
-/* Relocate the function pointers in the phy cmd lists */
-static void relocate_cmds(void)
-{
-       struct phy_cmd **cmdlistptr;
-       struct phy_cmd *cmd;
-       int i, j, k;
-
-       for (i = 0; phy_info[i]; i++) {
-               /* First thing's first: relocate the pointers to the
-                * PHY command structures (the structs were done) */
-               phy_info[i] = (struct phy_info *)((uint) phy_info[i]
-                                                 + gd->reloc_off);
-               phy_info[i]->name += gd->reloc_off;
-               phy_info[i]->config =
-                   (struct phy_cmd *)((uint) phy_info[i]->config
-                                      + gd->reloc_off);
-               phy_info[i]->startup =
-                   (struct phy_cmd *)((uint) phy_info[i]->startup
-                                      + gd->reloc_off);
-               phy_info[i]->shutdown =
-                   (struct phy_cmd *)((uint) phy_info[i]->shutdown
-                                      + gd->reloc_off);
-
-               cmdlistptr = &phy_info[i]->config;
-               j = 0;
-               for (; cmdlistptr <= &phy_info[i]->shutdown; cmdlistptr++) {
-                       k = 0;
-                       for (cmd = *cmdlistptr;
-                            cmd->mii_reg != miim_end;
-                            cmd++) {
-                               /* Only relocate non-NULL pointers */
-                               if (cmd->funct)
-                                       cmd->funct += gd->reloc_off;
-
-                               k++;
-                       }
-                       j++;
-               }
-       }
-
-       relocated = 1;
-}
-
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
        && !defined(BITBANGMII)