180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney/********************************************************************** 280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * Author: Cavium Networks 380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * 480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * Contact: support@caviumnetworks.com 580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * This file is part of the OCTEON SDK 680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * 780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * Copyright (c) 2003-2007 Cavium Networks 880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * 980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * This file is free software; you can redistribute it and/or modify 1080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * it under the terms of the GNU General Public License, Version 2, as 1180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * published by the Free Software Foundation. 1280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * 1380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * This file is distributed in the hope that it will be useful, but 1480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 1580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 1680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * NONINFRINGEMENT. See the GNU General Public License for more 1780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * details. 1880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * 1980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * You should have received a copy of the GNU General Public License 2080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * along with this file; if not, write to the Free Software 2180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * or visit http://www.gnu.org/licenses/. 2380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * 2480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * This file may also be available under a different license from Cavium. 2580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney * Contact Cavium Networks for more information 2680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney**********************************************************************/ 27ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney#include <linux/phy.h> 2880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include <linux/kernel.h> 2980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include <linux/netdevice.h> 307a2eaf9358250706672783eb8511835706b0922bChristian Dietrich#include <linux/ratelimit.h> 3180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include <net/dst.h> 3280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 3380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include <asm/octeon/octeon.h> 3480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 3580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include "ethernet-defines.h" 3680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include "octeon-ethernet.h" 3780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include "ethernet-util.h" 38ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney#include "ethernet-mdio.h" 3980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 40af866496c7752d2c0bd97fcbb4627cac72aa9a64David Daney#include <asm/octeon/cvmx-helper.h> 4180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 42af866496c7752d2c0bd97fcbb4627cac72aa9a64David Daney#include <asm/octeon/cvmx-gmxx-defs.h> 4380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 4480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daneystatic void cvm_oct_xaui_poll(struct net_device *dev) 4580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney{ 4680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney struct octeon_ethernet *priv = netdev_priv(dev); 4780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney cvmx_helper_link_info_t link_info; 4880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 4980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney link_info = cvmx_helper_link_get(priv->port); 5080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney if (link_info.u64 == priv->link_info) 5180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney return; 5280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 5380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney link_info = cvmx_helper_link_autoconf(priv->port); 5480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney priv->link_info = link_info.u64; 5580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 5680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney /* Tell Linux */ 5780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney if (link_info.s.link_up) { 5880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 5980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney if (!netif_carrier_ok(dev)) 6080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney netif_carrier_on(dev); 6180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney if (priv->queue != -1) 627a2eaf9358250706672783eb8511835706b0922bChristian Dietrich printk_ratelimited 637a2eaf9358250706672783eb8511835706b0922bChristian Dietrich ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", 647a2eaf9358250706672783eb8511835706b0922bChristian Dietrich dev->name, link_info.s.speed, 657a2eaf9358250706672783eb8511835706b0922bChristian Dietrich (link_info.s.full_duplex) ? "Full" : "Half", 667a2eaf9358250706672783eb8511835706b0922bChristian Dietrich priv->port, priv->queue); 6780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney else 687a2eaf9358250706672783eb8511835706b0922bChristian Dietrich printk_ratelimited 697a2eaf9358250706672783eb8511835706b0922bChristian Dietrich ("%s: %u Mbps %s duplex, port %2d, POW\n", 707a2eaf9358250706672783eb8511835706b0922bChristian Dietrich dev->name, link_info.s.speed, 717a2eaf9358250706672783eb8511835706b0922bChristian Dietrich (link_info.s.full_duplex) ? "Full" : "Half", 727a2eaf9358250706672783eb8511835706b0922bChristian Dietrich priv->port); 7380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney } else { 7480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney if (netif_carrier_ok(dev)) 7580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney netif_carrier_off(dev); 767a2eaf9358250706672783eb8511835706b0922bChristian Dietrich printk_ratelimited("%s: Link down\n", dev->name); 7780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney } 7880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney} 7980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 80ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daneyint cvm_oct_xaui_open(struct net_device *dev) 81ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney{ 82ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney union cvmx_gmxx_prtx_cfg gmx_cfg; 83ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney struct octeon_ethernet *priv = netdev_priv(dev); 84ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney int interface = INTERFACE(priv->port); 85ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney int index = INDEX(priv->port); 86ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney cvmx_helper_link_info_t link_info; 87ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney int rv; 88ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney 89ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney rv = cvm_oct_phy_setup_device(dev); 90ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney if (rv) 91ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney return rv; 92ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney 93ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 94ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney gmx_cfg.s.en = 1; 95ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 96ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney 97ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney if (octeon_is_simulation()) 98ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney return 0; 99ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney 100ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney if (priv->phydev) { 101ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney int r = phy_read_status(priv->phydev); 102e2ce06152ad5fdc67b3841d74852ffd30c2488e3Aybuke Ozdemir 103ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney if (r == 0 && priv->phydev->link == 0) 104ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney netif_carrier_off(dev); 105ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney cvm_oct_adjust_link(dev); 106ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney } else { 107ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney link_info = cvmx_helper_link_get(priv->port); 108ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney if (!link_info.s.link_up) 109ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney netif_carrier_off(dev); 110ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney priv->poll = cvm_oct_xaui_poll; 111ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney cvm_oct_xaui_poll(dev); 112ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney } 113ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney return 0; 114ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney} 115ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney 116ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daneyint cvm_oct_xaui_stop(struct net_device *dev) 117ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney{ 118ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney union cvmx_gmxx_prtx_cfg gmx_cfg; 119ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney struct octeon_ethernet *priv = netdev_priv(dev); 120ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney int interface = INTERFACE(priv->port); 121ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney int index = INDEX(priv->port); 122ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney 123ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 124ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney gmx_cfg.s.en = 0; 125ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 126ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney return cvm_oct_common_stop(dev); 127ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney} 128ec3a2207c322e518f7f42c80e54b8ecaf8a6f03eDavid Daney 12980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daneyint cvm_oct_xaui_init(struct net_device *dev) 13080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney{ 13180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney struct octeon_ethernet *priv = netdev_priv(dev); 13238064eb1a4cb52507afe84d4428eaa0c8d674f05Rahul Bedarkar 13380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney cvm_oct_common_init(dev); 134f696a10838ffab85e5bc07e7cff0d0e1870a30d7David Daney dev->netdev_ops->ndo_stop(dev); 135f6ed1b3b3579db5c8c3aaf6fd3010c706973a35dDavid Daney if (!octeon_is_simulation() && priv->phydev == NULL) 13680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney priv->poll = cvm_oct_xaui_poll; 13780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 13880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney return 0; 13980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney} 14080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney 14180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daneyvoid cvm_oct_xaui_uninit(struct net_device *dev) 14280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney{ 14380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney cvm_oct_common_uninit(dev); 14480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney} 145