blob: 4e7304210bb91ee257fe077d43d6878e5e26a660 [file] [log] [blame]
Aaro Koskinen67620982015-04-04 22:51:21 +03001/*
2 * This file is based on code from OCTEON SDK by Cavium Networks.
David Daney80ff0fd2009-05-05 17:35:21 -07003 *
4 * Copyright (c) 2003-2007 Cavium Networks
5 *
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, Version 2, as
8 * published by the Free Software Foundation.
Aaro Koskinen67620982015-04-04 22:51:21 +03009 */
10
David Daney80ff0fd2009-05-05 17:35:21 -070011#include <linux/kernel.h>
12#include <linux/netdevice.h>
David Daney048316b2011-08-16 10:10:56 -070013#include <linux/interrupt.h>
David Daneyf8c26482010-02-15 12:13:17 -080014#include <linux/phy.h>
Christian Dietrich7a2eaf92011-06-04 17:35:58 +020015#include <linux/ratelimit.h>
David Daney80ff0fd2009-05-05 17:35:21 -070016#include <net/dst.h>
17
18#include <asm/octeon/octeon.h>
19
20#include "ethernet-defines.h"
21#include "octeon-ethernet.h"
David Daney80ff0fd2009-05-05 17:35:21 -070022#include "ethernet-util.h"
David Daneyec3a2202014-05-29 11:10:02 +010023#include "ethernet-mdio.h"
David Daney80ff0fd2009-05-05 17:35:21 -070024
David Daneyaf866492011-11-22 14:47:00 +000025#include <asm/octeon/cvmx-helper.h>
David Daney80ff0fd2009-05-05 17:35:21 -070026
27#include <asm/octeon/cvmx-ipd-defs.h>
28#include <asm/octeon/cvmx-npi-defs.h>
David Daneyaf866492011-11-22 14:47:00 +000029#include <asm/octeon/cvmx-gmxx-defs.h>
David Daney80ff0fd2009-05-05 17:35:21 -070030
Aaro Koskinen54bf9172014-03-02 00:09:08 +020031static DEFINE_SPINLOCK(global_register_lock);
David Daney80ff0fd2009-05-05 17:35:21 -070032
Aaro Koskinen01d30072015-04-04 22:51:10 +030033static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable)
34{
35 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
36 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
37 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
38 int interface = INTERFACE(priv->port);
39 int index = INDEX(priv->port);
40
41 /* Set preamble checking. */
42 gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index,
43 interface));
44 gmxx_rxx_frm_ctl.s.pre_chk = enable;
45 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
46 gmxx_rxx_frm_ctl.u64);
47
48 /* Set FCS stripping. */
49 ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
50 if (enable)
51 ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
52 else
53 ipd_sub_port_fcs.s.port_bit &=
54 0xffffffffull ^ (1ull << priv->port);
55 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
56
57 /* Clear any error bits. */
58 gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index,
59 interface));
60 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
61 gmxx_rxx_int_reg.u64);
62}
63
Aaro Koskinen710086d2016-02-12 01:02:26 +020064static void cvm_oct_check_preamble_errors(struct net_device *dev)
65{
66 struct octeon_ethernet *priv = netdev_priv(dev);
67 cvmx_helper_link_info_t link_info;
68 unsigned long flags;
69
70 link_info.u64 = priv->link_info;
71
72 /*
73 * Take the global register lock since we are going to
74 * touch registers that affect more than one port.
75 */
76 spin_lock_irqsave(&global_register_lock, flags);
77
78 if (link_info.s.speed == 10 && priv->last_speed == 10) {
79 /*
80 * Read the GMXX_RXX_INT_REG[PCTERR] bit and see if we are
81 * getting preamble errors.
82 */
83 int interface = INTERFACE(priv->port);
84 int index = INDEX(priv->port);
85 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
86
87 gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
88 (index, interface));
89 if (gmxx_rxx_int_reg.s.pcterr) {
90 /*
91 * We are getting preamble errors at 10Mbps. Most
92 * likely the PHY is giving us packets with misaligned
93 * preambles. In order to get these packets we need to
94 * disable preamble checking and do it in software.
95 */
96 cvm_oct_set_hw_preamble(priv, false);
97 printk_ratelimited("%s: Using 10Mbps with software preamble removal\n",
98 dev->name);
99 }
100 } else {
101 /*
102 * Since the 10Mbps preamble workaround is allowed we need to
103 * enable preamble checking, FCS stripping, and clear error
104 * bits on every speed change. If errors occur during 10Mbps
105 * operation the above code will change this stuff
106 */
107 if (priv->last_speed != link_info.s.speed)
108 cvm_oct_set_hw_preamble(priv, true);
109 priv->last_speed = link_info.s.speed;
110 }
111 spin_unlock_irqrestore(&global_register_lock, flags);
112}
113
David Daney80ff0fd2009-05-05 17:35:21 -0700114static void cvm_oct_rgmii_poll(struct net_device *dev)
115{
116 struct octeon_ethernet *priv = netdev_priv(dev);
David Daney80ff0fd2009-05-05 17:35:21 -0700117 cvmx_helper_link_info_t link_info;
Aaro Koskinen710086d2016-02-12 01:02:26 +0200118 bool status_change;
David Daney80ff0fd2009-05-05 17:35:21 -0700119
Aaro Koskinen60dcf582016-09-03 00:33:38 +0300120 link_info = cvmx_helper_link_get(priv->port);
121 if (priv->link_info != link_info.u64 &&
122 cvmx_helper_link_set(priv->port, link_info))
123 link_info.u64 = priv->link_info;
Aaro Koskinen710086d2016-02-12 01:02:26 +0200124 status_change = priv->link_info != link_info.u64;
125 priv->link_info = link_info.u64;
David Daney80ff0fd2009-05-05 17:35:21 -0700126
Aaro Koskinen710086d2016-02-12 01:02:26 +0200127 cvm_oct_check_preamble_errors(dev);
Melike Yurtoglu5a2da4a2014-09-28 15:53:21 +0300128
Aaro Koskinen710086d2016-02-12 01:02:26 +0200129 if (likely(!status_change))
David Daney80ff0fd2009-05-05 17:35:21 -0700130 return;
Aaro Koskinen710086d2016-02-12 01:02:26 +0200131
132 /* Tell core. */
133 if (link_info.s.link_up) {
134 if (!netif_carrier_ok(dev))
135 netif_carrier_on(dev);
136 } else if (netif_carrier_ok(dev)) {
137 netif_carrier_off(dev);
David Daney80ff0fd2009-05-05 17:35:21 -0700138 }
Aaro Koskinen710086d2016-02-12 01:02:26 +0200139 cvm_oct_note_carrier(priv, link_info);
David Daney80ff0fd2009-05-05 17:35:21 -0700140}
141
David Daneyf696a102009-06-23 11:34:08 -0700142int cvm_oct_rgmii_open(struct net_device *dev)
David Daney80ff0fd2009-05-05 17:35:21 -0700143{
David Daney80ff0fd2009-05-05 17:35:21 -0700144 struct octeon_ethernet *priv = netdev_priv(dev);
Aaro Koskinen710086d2016-02-12 01:02:26 +0200145 int ret;
David Daney80ff0fd2009-05-05 17:35:21 -0700146
Aaro Koskinen710086d2016-02-12 01:02:26 +0200147 ret = cvm_oct_common_open(dev, cvm_oct_rgmii_poll);
148 if (ret)
149 return ret;
David Daney80ff0fd2009-05-05 17:35:21 -0700150
Philippe Reynes5d99db12016-07-16 01:13:34 +0200151 if (dev->phydev) {
Aaro Koskinen710086d2016-02-12 01:02:26 +0200152 /*
153 * In phydev mode, we need still periodic polling for the
154 * preamble error checking, and we also need to call this
155 * function on every link state change.
156 *
157 * Only true RGMII ports need to be polled. In GMII mode, port
158 * 0 is really a RGMII port.
159 */
160 if ((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII &&
161 priv->port == 0) ||
162 (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
163 priv->poll = cvm_oct_check_preamble_errors;
164 cvm_oct_check_preamble_errors(dev);
David Daney80ff0fd2009-05-05 17:35:21 -0700165 }
166 }
167
168 return 0;
169}