1
/*********************************************************************
2
* Author: Cavium Networks
4
* Contact: support@caviumnetworks.com
5
* This file is part of the OCTEON SDK
7
* Copyright (c) 2003-2007 Cavium Networks
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.
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
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/.
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/interrupt.h>
30
#include <linux/phy.h>
31
#include <linux/ratelimit.h>
34
#include <asm/octeon/octeon.h>
36
#include "ethernet-defines.h"
37
#include "octeon-ethernet.h"
38
#include "ethernet-util.h"
40
#include "cvmx-helper.h"
42
#include <asm/octeon/cvmx-ipd-defs.h>
43
#include <asm/octeon/cvmx-npi-defs.h>
44
#include "cvmx-gmxx-defs.h"
46
DEFINE_SPINLOCK(global_register_lock);
48
static int number_rgmii_ports;
50
static void cvm_oct_rgmii_poll(struct net_device *dev)
52
struct octeon_ethernet *priv = netdev_priv(dev);
53
unsigned long flags = 0;
54
cvmx_helper_link_info_t link_info;
55
int use_global_register_lock = (priv->phydev == NULL);
57
BUG_ON(in_interrupt());
58
if (use_global_register_lock) {
60
* Take the global register lock since we are going to
61
* touch registers that affect more than one port.
63
spin_lock_irqsave(&global_register_lock, flags);
65
mutex_lock(&priv->phydev->bus->mdio_lock);
68
link_info = cvmx_helper_link_get(priv->port);
69
if (link_info.u64 == priv->link_info) {
72
* If the 10Mbps preamble workaround is supported and we're
73
* at 10Mbps we may need to do some special checking.
75
if (USE_10MBPS_PREAMBLE_WORKAROUND && (link_info.s.speed == 10)) {
78
* Read the GMXX_RXX_INT_REG[PCTERR] bit and
79
* see if we are getting preamble errors.
81
int interface = INTERFACE(priv->port);
82
int index = INDEX(priv->port);
83
union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
84
gmxx_rxx_int_reg.u64 =
85
cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
87
if (gmxx_rxx_int_reg.s.pcterr) {
90
* We are getting preamble errors at
91
* 10Mbps. Most likely the PHY is
92
* giving us packets with mis aligned
93
* preambles. In order to get these
94
* packets we need to disable preamble
95
* checking and do it in software.
97
union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
98
union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
100
/* Disable preamble checking */
101
gmxx_rxx_frm_ctl.u64 =
102
cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
104
gmxx_rxx_frm_ctl.s.pre_chk = 0;
105
cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL
107
gmxx_rxx_frm_ctl.u64);
109
/* Disable FCS stripping */
110
ipd_sub_port_fcs.u64 =
111
cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
112
ipd_sub_port_fcs.s.port_bit &=
113
0xffffffffull ^ (1ull << priv->port);
114
cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS,
115
ipd_sub_port_fcs.u64);
117
/* Clear any error bits */
118
cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
120
gmxx_rxx_int_reg.u64);
121
printk_ratelimited("%s: Using 10Mbps with software "
122
"preamble removal\n",
127
if (use_global_register_lock)
128
spin_unlock_irqrestore(&global_register_lock, flags);
130
mutex_unlock(&priv->phydev->bus->mdio_lock);
134
/* If the 10Mbps preamble workaround is allowed we need to on
135
preamble checking, FCS stripping, and clear error bits on
136
every speed change. If errors occur during 10Mbps operation
137
the above code will change this stuff */
138
if (USE_10MBPS_PREAMBLE_WORKAROUND) {
140
union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
141
union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
142
union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
143
int interface = INTERFACE(priv->port);
144
int index = INDEX(priv->port);
146
/* Enable preamble checking */
147
gmxx_rxx_frm_ctl.u64 =
148
cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
149
gmxx_rxx_frm_ctl.s.pre_chk = 1;
150
cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
151
gmxx_rxx_frm_ctl.u64);
152
/* Enable FCS stripping */
153
ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
154
ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
155
cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
156
/* Clear any error bits */
157
gmxx_rxx_int_reg.u64 =
158
cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
159
cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
160
gmxx_rxx_int_reg.u64);
162
if (priv->phydev == NULL) {
163
link_info = cvmx_helper_link_autoconf(priv->port);
164
priv->link_info = link_info.u64;
167
if (use_global_register_lock)
168
spin_unlock_irqrestore(&global_register_lock, flags);
170
mutex_unlock(&priv->phydev->bus->mdio_lock);
173
if (priv->phydev == NULL) {
175
if (link_info.s.link_up) {
176
if (!netif_carrier_ok(dev))
177
netif_carrier_on(dev);
178
if (priv->queue != -1)
179
printk_ratelimited("%s: %u Mbps %s duplex, "
180
"port %2d, queue %2d\n",
181
dev->name, link_info.s.speed,
182
(link_info.s.full_duplex) ?
184
priv->port, priv->queue);
186
printk_ratelimited("%s: %u Mbps %s duplex, "
188
dev->name, link_info.s.speed,
189
(link_info.s.full_duplex) ?
193
if (netif_carrier_ok(dev))
194
netif_carrier_off(dev);
195
printk_ratelimited("%s: Link down\n", dev->name);
200
static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
202
union cvmx_npi_rsl_int_blocks rsl_int_blocks;
204
irqreturn_t return_status = IRQ_NONE;
206
rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
208
/* Check and see if this interrupt was caused by the GMX0 block */
209
if (rsl_int_blocks.s.gmx0) {
212
/* Loop through every port of this interface */
214
index < cvmx_helper_ports_on_interface(interface);
217
/* Read the GMX interrupt status bits */
218
union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
220
cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
222
gmx_rx_int_reg.u64 &=
223
cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
225
/* Poll the port if inband status changed */
226
if (gmx_rx_int_reg.s.phy_dupx
227
|| gmx_rx_int_reg.s.phy_link
228
|| gmx_rx_int_reg.s.phy_spd) {
230
struct net_device *dev =
231
cvm_oct_device[cvmx_helper_get_ipd_port
233
struct octeon_ethernet *priv = netdev_priv(dev);
235
if (dev && !atomic_read(&cvm_oct_poll_queue_stopping))
236
queue_work(cvm_oct_poll_queue, &priv->port_work);
238
gmx_rx_int_reg.u64 = 0;
239
gmx_rx_int_reg.s.phy_dupx = 1;
240
gmx_rx_int_reg.s.phy_link = 1;
241
gmx_rx_int_reg.s.phy_spd = 1;
242
cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
245
return_status = IRQ_HANDLED;
250
/* Check and see if this interrupt was caused by the GMX1 block */
251
if (rsl_int_blocks.s.gmx1) {
254
/* Loop through every port of this interface */
256
index < cvmx_helper_ports_on_interface(interface);
259
/* Read the GMX interrupt status bits */
260
union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
262
cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
264
gmx_rx_int_reg.u64 &=
265
cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
267
/* Poll the port if inband status changed */
268
if (gmx_rx_int_reg.s.phy_dupx
269
|| gmx_rx_int_reg.s.phy_link
270
|| gmx_rx_int_reg.s.phy_spd) {
272
struct net_device *dev =
273
cvm_oct_device[cvmx_helper_get_ipd_port
275
struct octeon_ethernet *priv = netdev_priv(dev);
277
if (dev && !atomic_read(&cvm_oct_poll_queue_stopping))
278
queue_work(cvm_oct_poll_queue, &priv->port_work);
280
gmx_rx_int_reg.u64 = 0;
281
gmx_rx_int_reg.s.phy_dupx = 1;
282
gmx_rx_int_reg.s.phy_link = 1;
283
gmx_rx_int_reg.s.phy_spd = 1;
284
cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
287
return_status = IRQ_HANDLED;
291
return return_status;
294
int cvm_oct_rgmii_open(struct net_device *dev)
296
union cvmx_gmxx_prtx_cfg gmx_cfg;
297
struct octeon_ethernet *priv = netdev_priv(dev);
298
int interface = INTERFACE(priv->port);
299
int index = INDEX(priv->port);
300
cvmx_helper_link_info_t link_info;
302
gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
304
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
306
if (!octeon_is_simulation()) {
307
link_info = cvmx_helper_link_get(priv->port);
308
if (!link_info.s.link_up)
309
netif_carrier_off(dev);
315
int cvm_oct_rgmii_stop(struct net_device *dev)
317
union cvmx_gmxx_prtx_cfg gmx_cfg;
318
struct octeon_ethernet *priv = netdev_priv(dev);
319
int interface = INTERFACE(priv->port);
320
int index = INDEX(priv->port);
322
gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
324
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
328
static void cvm_oct_rgmii_immediate_poll(struct work_struct *work)
330
struct octeon_ethernet *priv = container_of(work, struct octeon_ethernet, port_work);
331
cvm_oct_rgmii_poll(cvm_oct_device[priv->port]);
334
int cvm_oct_rgmii_init(struct net_device *dev)
336
struct octeon_ethernet *priv = netdev_priv(dev);
339
cvm_oct_common_init(dev);
340
dev->netdev_ops->ndo_stop(dev);
341
INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll);
343
* Due to GMX errata in CN3XXX series chips, it is necessary
344
* to take the link down immediately when the PHY changes
345
* state. In order to do this we call the poll function every
346
* time the RGMII inband status changes. This may cause
347
* problems if the PHY doesn't implement inband status
350
if (number_rgmii_ports == 0) {
351
r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
352
IRQF_SHARED, "RGMII", &number_rgmii_ports);
356
number_rgmii_ports++;
359
* Only true RGMII ports need to be polled. In GMII mode, port
360
* 0 is really a RGMII port.
362
if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
363
&& (priv->port == 0))
364
|| (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
366
if (!octeon_is_simulation()) {
368
union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
369
int interface = INTERFACE(priv->port);
370
int index = INDEX(priv->port);
373
* Enable interrupts on inband status changes
377
cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
379
gmx_rx_int_en.s.phy_dupx = 1;
380
gmx_rx_int_en.s.phy_link = 1;
381
gmx_rx_int_en.s.phy_spd = 1;
382
cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
384
priv->poll = cvm_oct_rgmii_poll;
391
void cvm_oct_rgmii_uninit(struct net_device *dev)
393
struct octeon_ethernet *priv = netdev_priv(dev);
394
cvm_oct_common_uninit(dev);
397
* Only true RGMII ports need to be polled. In GMII mode, port
398
* 0 is really a RGMII port.
400
if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
401
&& (priv->port == 0))
402
|| (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
404
if (!octeon_is_simulation()) {
406
union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
407
int interface = INTERFACE(priv->port);
408
int index = INDEX(priv->port);
411
* Disable interrupts on inband status changes
415
cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
417
gmx_rx_int_en.s.phy_dupx = 0;
418
gmx_rx_int_en.s.phy_link = 0;
419
gmx_rx_int_en.s.phy_spd = 0;
420
cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
425
/* Remove the interrupt handler when the last port is removed. */
426
number_rgmii_ports--;
427
if (number_rgmii_ports == 0)
428
free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
429
cancel_work_sync(&priv->port_work);