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**********************************************************************/
2780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include <linux/kernel.h>
2880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include <linux/netdevice.h>
297a2eaf9358250706672783eb8511835706b0922bChristian Dietrich#include <linux/ratelimit.h>
3080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include <net/dst.h>
3180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
3280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include <asm/octeon/octeon.h>
3380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
3480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include "ethernet-defines.h"
3580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include "octeon-ethernet.h"
3680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney#include "ethernet-util.h"
3780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
38af866496c7752d2c0bd97fcbb4627cac72aa9a64David Daney#include <asm/octeon/cvmx-helper.h>
3980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
40af866496c7752d2c0bd97fcbb4627cac72aa9a64David Daney#include <asm/octeon/cvmx-gmxx-defs.h>
4180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
42f696a10838ffab85e5bc07e7cff0d0e1870a30d7David Daneyint cvm_oct_sgmii_open(struct net_device *dev)
4380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney{
4480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	union cvmx_gmxx_prtx_cfg gmx_cfg;
4580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	struct octeon_ethernet *priv = netdev_priv(dev);
4680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	int interface = INTERFACE(priv->port);
4780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	int index = INDEX(priv->port);
4880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	cvmx_helper_link_info_t link_info;
4980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
5080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
5180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	gmx_cfg.s.en = 1;
5280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
5380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
5480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	if (!octeon_is_simulation()) {
5580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney		link_info = cvmx_helper_link_get(priv->port);
5680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney		if (!link_info.s.link_up)
5780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney			netif_carrier_off(dev);
5880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	}
5980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
6080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	return 0;
6180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney}
6280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
63f696a10838ffab85e5bc07e7cff0d0e1870a30d7David Daneyint cvm_oct_sgmii_stop(struct net_device *dev)
6480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney{
6580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	union cvmx_gmxx_prtx_cfg gmx_cfg;
6680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	struct octeon_ethernet *priv = netdev_priv(dev);
6780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	int interface = INTERFACE(priv->port);
6880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	int index = INDEX(priv->port);
6980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
7080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
7180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	gmx_cfg.s.en = 0;
7280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
7380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	return 0;
7480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney}
7580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
7680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daneystatic void cvm_oct_sgmii_poll(struct net_device *dev)
7780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney{
7880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	struct octeon_ethernet *priv = netdev_priv(dev);
7980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	cvmx_helper_link_info_t link_info;
8080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
8180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	link_info = cvmx_helper_link_get(priv->port);
8280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	if (link_info.u64 == priv->link_info)
8380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney		return;
8480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
8580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	link_info = cvmx_helper_link_autoconf(priv->port);
8680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	priv->link_info = link_info.u64;
8780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
8880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	/* Tell Linux */
8980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	if (link_info.s.link_up) {
9080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
9180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney		if (!netif_carrier_ok(dev))
9280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney			netif_carrier_on(dev);
9380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney		if (priv->queue != -1)
947a2eaf9358250706672783eb8511835706b0922bChristian Dietrich			printk_ratelimited
9580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney			    ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
9680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney			     dev->name, link_info.s.speed,
9780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney			     (link_info.s.full_duplex) ? "Full" : "Half",
9880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney			     priv->port, priv->queue);
9980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney		else
1007a2eaf9358250706672783eb8511835706b0922bChristian Dietrich			printk_ratelimited
1017a2eaf9358250706672783eb8511835706b0922bChristian Dietrich				("%s: %u Mbps %s duplex, port %2d, POW\n",
1027a2eaf9358250706672783eb8511835706b0922bChristian Dietrich				 dev->name, link_info.s.speed,
1037a2eaf9358250706672783eb8511835706b0922bChristian Dietrich				 (link_info.s.full_duplex) ? "Full" : "Half",
1047a2eaf9358250706672783eb8511835706b0922bChristian Dietrich				 priv->port);
10580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	} else {
10680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney		if (netif_carrier_ok(dev))
10780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney			netif_carrier_off(dev);
1087a2eaf9358250706672783eb8511835706b0922bChristian Dietrich		printk_ratelimited("%s: Link down\n", dev->name);
10980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	}
11080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney}
11180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
11280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daneyint cvm_oct_sgmii_init(struct net_device *dev)
11380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney{
11480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	struct octeon_ethernet *priv = netdev_priv(dev);
11580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	cvm_oct_common_init(dev);
116f696a10838ffab85e5bc07e7cff0d0e1870a30d7David Daney	dev->netdev_ops->ndo_stop(dev);
117f6ed1b3b3579db5c8c3aaf6fd3010c706973a35dDavid Daney	if (!octeon_is_simulation() && priv->phydev == NULL)
11880ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney		priv->poll = cvm_oct_sgmii_poll;
11980ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
12080ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	/* FIXME: Need autoneg logic */
12180ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	return 0;
12280ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney}
12380ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney
12480ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daneyvoid cvm_oct_sgmii_uninit(struct net_device *dev)
12580ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney{
12680ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney	cvm_oct_common_uninit(dev);
12780ff0fd3ab6451407a20c19b80c1643c4a6d6434David Daney}
128