2 * This file is based on code from OCTEON SDK by Cavium Networks.
4 * Copyright (c) 2003-2007 Cavium Networks
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.
11 #include <linux/kernel.h>
12 #include <linux/netdevice.h>
13 #include <linux/interrupt.h>
14 #include <linux/phy.h>
15 #include <linux/ratelimit.h>
18 #include <asm/octeon/octeon.h>
20 #include "ethernet-defines.h"
21 #include "octeon-ethernet.h"
22 #include "ethernet-util.h"
23 #include "ethernet-mdio.h"
25 #include <asm/octeon/cvmx-helper.h>
27 #include <asm/octeon/cvmx-ipd-defs.h>
28 #include <asm/octeon/cvmx-npi-defs.h>
29 #include <asm/octeon/cvmx-gmxx-defs.h>
31 static DEFINE_SPINLOCK(global_register_lock
);
33 static void cvm_oct_set_hw_preamble(struct octeon_ethernet
*priv
, bool enable
)
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
);
41 /* Set preamble checking. */
42 gmxx_rxx_frm_ctl
.u64
= cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index
,
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
);
48 /* Set FCS stripping. */
49 ipd_sub_port_fcs
.u64
= cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS
);
51 ipd_sub_port_fcs
.s
.port_bit
|= 1ull << priv
->port
;
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
);
57 /* Clear any error bits. */
58 gmxx_rxx_int_reg
.u64
= cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index
,
60 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index
, interface
),
61 gmxx_rxx_int_reg
.u64
);
64 static void cvm_oct_check_preamble_errors(struct net_device
*dev
)
66 struct octeon_ethernet
*priv
= netdev_priv(dev
);
67 cvmx_helper_link_info_t link_info
;
70 link_info
.u64
= priv
->link_info
;
73 * Take the global register lock since we are going to
74 * touch registers that affect more than one port.
76 spin_lock_irqsave(&global_register_lock
, flags
);
78 if (link_info
.s
.speed
== 10 && priv
->last_speed
== 10) {
80 * Read the GMXX_RXX_INT_REG[PCTERR] bit and see if we are
81 * getting preamble errors.
83 int interface
= INTERFACE(priv
->port
);
84 int index
= INDEX(priv
->port
);
85 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg
;
87 gmxx_rxx_int_reg
.u64
= cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
89 if (gmxx_rxx_int_reg
.s
.pcterr
) {
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.
96 cvm_oct_set_hw_preamble(priv
, false);
97 printk_ratelimited("%s: Using 10Mbps with software preamble removal\n",
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
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
;
111 spin_unlock_irqrestore(&global_register_lock
, flags
);
114 static void cvm_oct_rgmii_poll(struct net_device
*dev
)
116 struct octeon_ethernet
*priv
= netdev_priv(dev
);
117 cvmx_helper_link_info_t link_info
;
120 link_info
= cvmx_helper_link_autoconf(priv
->port
);
121 status_change
= priv
->link_info
!= link_info
.u64
;
122 priv
->link_info
= link_info
.u64
;
124 cvm_oct_check_preamble_errors(dev
);
126 if (likely(!status_change
))
130 if (link_info
.s
.link_up
) {
131 if (!netif_carrier_ok(dev
))
132 netif_carrier_on(dev
);
133 } else if (netif_carrier_ok(dev
)) {
134 netif_carrier_off(dev
);
136 cvm_oct_note_carrier(priv
, link_info
);
139 int cvm_oct_rgmii_open(struct net_device
*dev
)
141 struct octeon_ethernet
*priv
= netdev_priv(dev
);
144 ret
= cvm_oct_common_open(dev
, cvm_oct_rgmii_poll
);
150 * In phydev mode, we need still periodic polling for the
151 * preamble error checking, and we also need to call this
152 * function on every link state change.
154 * Only true RGMII ports need to be polled. In GMII mode, port
155 * 0 is really a RGMII port.
157 if ((priv
->imode
== CVMX_HELPER_INTERFACE_MODE_GMII
&&
159 (priv
->imode
== CVMX_HELPER_INTERFACE_MODE_RGMII
)) {
160 priv
->poll
= cvm_oct_check_preamble_errors
;
161 cvm_oct_check_preamble_errors(dev
);