diff options
Diffstat (limited to 'drivers/staging/octeon/ethernet-sgmii.c')
-rw-r--r-- | drivers/staging/octeon/ethernet-sgmii.c | 87 |
1 files changed, 50 insertions, 37 deletions
diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index d3e82430eba6..e1878449e683 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c @@ -24,6 +24,7 @@ * This file may also be available under a different license from Cavium. * Contact Cavium Networks for more information **********************************************************************/ +#include <linux/phy.h> #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/ratelimit.h> @@ -34,45 +35,12 @@ #include "ethernet-defines.h" #include "octeon-ethernet.h" #include "ethernet-util.h" +#include "ethernet-mdio.h" #include <asm/octeon/cvmx-helper.h> #include <asm/octeon/cvmx-gmxx-defs.h> -int cvm_oct_sgmii_open(struct net_device *dev) -{ - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - cvmx_helper_link_info_t link_info; - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 1; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - - if (!octeon_is_simulation()) { - link_info = cvmx_helper_link_get(priv->port); - if (!link_info.s.link_up) - netif_carrier_off(dev); - } - - return 0; -} - -int cvm_oct_sgmii_stop(struct net_device *dev) -{ - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 0; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - return 0; -} - static void cvm_oct_sgmii_poll(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); @@ -109,13 +77,58 @@ static void cvm_oct_sgmii_poll(struct net_device *dev) } } -int cvm_oct_sgmii_init(struct net_device *dev) +int cvm_oct_sgmii_open(struct net_device *dev) { + union cvmx_gmxx_prtx_cfg gmx_cfg; struct octeon_ethernet *priv = netdev_priv(dev); + int interface = INTERFACE(priv->port); + int index = INDEX(priv->port); + cvmx_helper_link_info_t link_info; + int rv; + + rv = cvm_oct_phy_setup_device(dev); + if (rv) + return rv; + + gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); + gmx_cfg.s.en = 1; + cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); + + if (octeon_is_simulation()) + return 0; + + if (priv->phydev) { + int r = phy_read_status(priv->phydev); + if (r == 0 && priv->phydev->link == 0) + netif_carrier_off(dev); + cvm_oct_adjust_link(dev); + } else { + link_info = cvmx_helper_link_get(priv->port); + if (!link_info.s.link_up) + netif_carrier_off(dev); + priv->poll = cvm_oct_sgmii_poll; + cvm_oct_sgmii_poll(dev); + } + return 0; +} + +int cvm_oct_sgmii_stop(struct net_device *dev) +{ + union cvmx_gmxx_prtx_cfg gmx_cfg; + struct octeon_ethernet *priv = netdev_priv(dev); + int interface = INTERFACE(priv->port); + int index = INDEX(priv->port); + + gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); + gmx_cfg.s.en = 0; + cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); + return cvm_oct_common_stop(dev); +} + +int cvm_oct_sgmii_init(struct net_device *dev) +{ cvm_oct_common_init(dev); dev->netdev_ops->ndo_stop(dev); - if (!octeon_is_simulation() && priv->phydev == NULL) - priv->poll = cvm_oct_sgmii_poll; /* FIXME: Need autoneg logic */ return 0; |