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 <net/dst.h> 30 31#include <asm/octeon/octeon.h> 32 33#include "ethernet-defines.h" 34#include "octeon-ethernet.h" 35#include "ethernet-util.h" 36 37#include "cvmx-helper.h" 38 39#include "cvmx-gmxx-defs.h" 40 41int cvm_oct_sgmii_open(struct net_device *dev) 42{ 43 union cvmx_gmxx_prtx_cfg gmx_cfg; 44 struct octeon_ethernet *priv = netdev_priv(dev); 45 int interface = INTERFACE(priv->port); 46 int index = INDEX(priv->port); 47 cvmx_helper_link_info_t link_info; 48 49 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 50 gmx_cfg.s.en = 1; 51 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 52 53 if (!octeon_is_simulation()) { 54 link_info = cvmx_helper_link_get(priv->port); 55 if (!link_info.s.link_up) 56 netif_carrier_off(dev); 57 } 58 59 return 0; 60} 61 62int cvm_oct_sgmii_stop(struct net_device *dev) 63{ 64 union cvmx_gmxx_prtx_cfg gmx_cfg; 65 struct octeon_ethernet *priv = netdev_priv(dev); 66 int interface = INTERFACE(priv->port); 67 int index = INDEX(priv->port); 68 69 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 70 gmx_cfg.s.en = 0; 71 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 72 return 0; 73} 74 75static void cvm_oct_sgmii_poll(struct net_device *dev) 76{ 77 struct octeon_ethernet *priv = netdev_priv(dev); 78 cvmx_helper_link_info_t link_info; 79 80 link_info = cvmx_helper_link_get(priv->port); 81 if (link_info.u64 == priv->link_info) 82 return; 83 84 link_info = cvmx_helper_link_autoconf(priv->port); 85 priv->link_info = link_info.u64; 86 87 /* Tell Linux */ 88 if (link_info.s.link_up) { 89 90 if (!netif_carrier_ok(dev)) 91 netif_carrier_on(dev); 92 if (priv->queue != -1) 93 DEBUGPRINT 94 ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", 95 dev->name, link_info.s.speed, 96 (link_info.s.full_duplex) ? "Full" : "Half", 97 priv->port, priv->queue); 98 else 99 DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", 100 dev->name, link_info.s.speed, 101 (link_info.s.full_duplex) ? "Full" : "Half", 102 priv->port); 103 } else { 104 if (netif_carrier_ok(dev)) 105 netif_carrier_off(dev); 106 DEBUGPRINT("%s: Link down\n", dev->name); 107 } 108} 109 110int cvm_oct_sgmii_init(struct net_device *dev) 111{ 112 struct octeon_ethernet *priv = netdev_priv(dev); 113 cvm_oct_common_init(dev); 114 dev->netdev_ops->ndo_stop(dev); 115 if (!octeon_is_simulation() && priv->phydev == NULL) 116 priv->poll = cvm_oct_sgmii_poll; 117 118 return 0; 119} 120 121void cvm_oct_sgmii_uninit(struct net_device *dev) 122{ 123 cvm_oct_common_uninit(dev); 124} 125