linux/drivers/staging/octeon/ethernet-sgmii.c
<<
>>
Prefs
   1/**********************************************************************
   2 * Author: Cavium Networks
   3 *
   4 * Contact: support@caviumnetworks.com
   5 * This file is part of the OCTEON SDK
   6 *
   7 * Copyright (c) 2003-2007 Cavium Networks
   8 *
   9 * This file is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License, Version 2, as
  11 * published by the Free Software Foundation.
  12 *
  13 * This file is distributed in the hope that it will be useful, but
  14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
  15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  16 * NONINFRINGEMENT.  See the GNU General Public License for more
  17 * details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this file; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22 * or visit http://www.gnu.org/licenses/.
  23 *
  24 * This file may also be available under a different license from Cavium.
  25 * Contact Cavium Networks for more information
  26**********************************************************************/
  27#include <linux/kernel.h>
  28#include <linux/netdevice.h>
  29#include <linux/ratelimit.h>
  30#include <net/dst.h>
  31
  32#include <asm/octeon/octeon.h>
  33
  34#include "ethernet-defines.h"
  35#include "octeon-ethernet.h"
  36#include "ethernet-util.h"
  37
  38#include <asm/octeon/cvmx-helper.h>
  39
  40#include <asm/octeon/cvmx-gmxx-defs.h>
  41
  42int cvm_oct_sgmii_open(struct net_device *dev)
  43{
  44        union cvmx_gmxx_prtx_cfg gmx_cfg;
  45        struct octeon_ethernet *priv = netdev_priv(dev);
  46        int interface = INTERFACE(priv->port);
  47        int index = INDEX(priv->port);
  48        cvmx_helper_link_info_t link_info;
  49
  50        gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
  51        gmx_cfg.s.en = 1;
  52        cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
  53
  54        if (!octeon_is_simulation()) {
  55                link_info = cvmx_helper_link_get(priv->port);
  56                if (!link_info.s.link_up)
  57                        netif_carrier_off(dev);
  58        }
  59
  60        return 0;
  61}
  62
  63int cvm_oct_sgmii_stop(struct net_device *dev)
  64{
  65        union cvmx_gmxx_prtx_cfg gmx_cfg;
  66        struct octeon_ethernet *priv = netdev_priv(dev);
  67        int interface = INTERFACE(priv->port);
  68        int index = INDEX(priv->port);
  69
  70        gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
  71        gmx_cfg.s.en = 0;
  72        cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
  73        return 0;
  74}
  75
  76static void cvm_oct_sgmii_poll(struct net_device *dev)
  77{
  78        struct octeon_ethernet *priv = netdev_priv(dev);
  79        cvmx_helper_link_info_t link_info;
  80
  81        link_info = cvmx_helper_link_get(priv->port);
  82        if (link_info.u64 == priv->link_info)
  83                return;
  84
  85        link_info = cvmx_helper_link_autoconf(priv->port);
  86        priv->link_info = link_info.u64;
  87
  88        /* Tell Linux */
  89        if (link_info.s.link_up) {
  90
  91                if (!netif_carrier_ok(dev))
  92                        netif_carrier_on(dev);
  93                if (priv->queue != -1)
  94                        printk_ratelimited
  95                            ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
  96                             dev->name, link_info.s.speed,
  97                             (link_info.s.full_duplex) ? "Full" : "Half",
  98                             priv->port, priv->queue);
  99                else
 100                        printk_ratelimited
 101                                ("%s: %u Mbps %s duplex, port %2d, POW\n",
 102                                 dev->name, link_info.s.speed,
 103                                 (link_info.s.full_duplex) ? "Full" : "Half",
 104                                 priv->port);
 105        } else {
 106                if (netif_carrier_ok(dev))
 107                        netif_carrier_off(dev);
 108                printk_ratelimited("%s: Link down\n", dev->name);
 109        }
 110}
 111
 112int cvm_oct_sgmii_init(struct net_device *dev)
 113{
 114        struct octeon_ethernet *priv = netdev_priv(dev);
 115        cvm_oct_common_init(dev);
 116        dev->netdev_ops->ndo_stop(dev);
 117        if (!octeon_is_simulation() && priv->phydev == NULL)
 118                priv->poll = cvm_oct_sgmii_poll;
 119
 120        /* FIXME: Need autoneg logic */
 121        return 0;
 122}
 123
 124void cvm_oct_sgmii_uninit(struct net_device *dev)
 125{
 126        cvm_oct_common_uninit(dev);
 127}
 128