0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/netdevice.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/phy.h>
0012 #include <linux/ratelimit.h>
0013 #include <net/dst.h>
0014
0015 #include "octeon-ethernet.h"
0016 #include "ethernet-defines.h"
0017 #include "ethernet-util.h"
0018 #include "ethernet-mdio.h"
0019
0020 static DEFINE_SPINLOCK(global_register_lock);
0021
0022 static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable)
0023 {
0024 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
0025 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
0026 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
0027 int interface = INTERFACE(priv->port);
0028 int index = INDEX(priv->port);
0029
0030
0031 gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index,
0032 interface));
0033 gmxx_rxx_frm_ctl.s.pre_chk = enable;
0034 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
0035 gmxx_rxx_frm_ctl.u64);
0036
0037
0038 ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
0039 if (enable)
0040 ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
0041 else
0042 ipd_sub_port_fcs.s.port_bit &=
0043 0xffffffffull ^ (1ull << priv->port);
0044 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
0045
0046
0047 gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index,
0048 interface));
0049 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
0050 gmxx_rxx_int_reg.u64);
0051 }
0052
0053 static void cvm_oct_check_preamble_errors(struct net_device *dev)
0054 {
0055 struct octeon_ethernet *priv = netdev_priv(dev);
0056 union cvmx_helper_link_info link_info;
0057 unsigned long flags;
0058
0059 link_info.u64 = priv->link_info;
0060
0061
0062
0063
0064
0065 spin_lock_irqsave(&global_register_lock, flags);
0066
0067 if (link_info.s.speed == 10 && priv->last_speed == 10) {
0068
0069
0070
0071
0072 int interface = INTERFACE(priv->port);
0073 int index = INDEX(priv->port);
0074 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
0075
0076 gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
0077 (index, interface));
0078 if (gmxx_rxx_int_reg.s.pcterr) {
0079
0080
0081
0082
0083
0084
0085 cvm_oct_set_hw_preamble(priv, false);
0086 printk_ratelimited("%s: Using 10Mbps with software preamble removal\n",
0087 dev->name);
0088 }
0089 } else {
0090
0091
0092
0093
0094
0095
0096 if (priv->last_speed != link_info.s.speed)
0097 cvm_oct_set_hw_preamble(priv, true);
0098 priv->last_speed = link_info.s.speed;
0099 }
0100 spin_unlock_irqrestore(&global_register_lock, flags);
0101 }
0102
0103 static void cvm_oct_rgmii_poll(struct net_device *dev)
0104 {
0105 struct octeon_ethernet *priv = netdev_priv(dev);
0106 union cvmx_helper_link_info link_info;
0107 bool status_change;
0108
0109 link_info = cvmx_helper_link_get(priv->port);
0110 if (priv->link_info != link_info.u64 &&
0111 cvmx_helper_link_set(priv->port, link_info))
0112 link_info.u64 = priv->link_info;
0113 status_change = priv->link_info != link_info.u64;
0114 priv->link_info = link_info.u64;
0115
0116 cvm_oct_check_preamble_errors(dev);
0117
0118 if (likely(!status_change))
0119 return;
0120
0121
0122 if (link_info.s.link_up) {
0123 if (!netif_carrier_ok(dev))
0124 netif_carrier_on(dev);
0125 } else if (netif_carrier_ok(dev)) {
0126 netif_carrier_off(dev);
0127 }
0128 cvm_oct_note_carrier(priv, link_info);
0129 }
0130
0131 int cvm_oct_rgmii_open(struct net_device *dev)
0132 {
0133 struct octeon_ethernet *priv = netdev_priv(dev);
0134 int ret;
0135
0136 ret = cvm_oct_common_open(dev, cvm_oct_rgmii_poll);
0137 if (ret)
0138 return ret;
0139
0140 if (dev->phydev) {
0141
0142
0143
0144
0145
0146
0147
0148
0149 if ((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII &&
0150 priv->port == 0) ||
0151 (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
0152 priv->poll = cvm_oct_check_preamble_errors;
0153 cvm_oct_check_preamble_errors(dev);
0154 }
0155 }
0156
0157 return 0;
0158 }