1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * This file is based on code from OCTEON SDK by Cavium Networks. 4 * 5 * Copyright (c) 2003-2007 Cavium Networks 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/netdevice.h> 10 #include <linux/interrupt.h> 11 #include <linux/phy.h> 12 #include <linux/ratelimit.h> 13 #include <net/dst.h> 14 15 #include <asm/octeon/octeon.h> 16 17 #include "ethernet-defines.h" 18 #include "octeon-ethernet.h" 19 #include "ethernet-util.h" 20 #include "ethernet-mdio.h" 21 22 #include <asm/octeon/cvmx-helper.h> 23 24 #include <asm/octeon/cvmx-ipd-defs.h> 25 #include <asm/octeon/cvmx-npi-defs.h> 26 #include <asm/octeon/cvmx-gmxx-defs.h> 27 28 static DEFINE_SPINLOCK(global_register_lock); 29 30 static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) 31 { 32 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; 33 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; 34 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; 35 int interface = INTERFACE(priv->port); 36 int index = INDEX(priv->port); 37 38 /* Set preamble checking. */ 39 gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, 40 interface)); 41 gmxx_rxx_frm_ctl.s.pre_chk = enable; 42 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), 43 gmxx_rxx_frm_ctl.u64); 44 45 /* Set FCS stripping. */ 46 ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); 47 if (enable) 48 ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port; 49 else 50 ipd_sub_port_fcs.s.port_bit &= 51 0xffffffffull ^ (1ull << priv->port); 52 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); 53 54 /* Clear any error bits. */ 55 gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, 56 interface)); 57 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), 58 gmxx_rxx_int_reg.u64); 59 } 60 61 static void cvm_oct_check_preamble_errors(struct net_device *dev) 62 { 63 struct octeon_ethernet *priv = netdev_priv(dev); 64 cvmx_helper_link_info_t link_info; 65 unsigned long flags; 66 67 link_info.u64 = priv->link_info; 68 69 /* 70 * Take the global register lock since we are going to 71 * touch registers that affect more than one port. 72 */ 73 spin_lock_irqsave(&global_register_lock, flags); 74 75 if (link_info.s.speed == 10 && priv->last_speed == 10) { 76 /* 77 * Read the GMXX_RXX_INT_REG[PCTERR] bit and see if we are 78 * getting preamble errors. 79 */ 80 int interface = INTERFACE(priv->port); 81 int index = INDEX(priv->port); 82 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; 83 84 gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG 85 (index, interface)); 86 if (gmxx_rxx_int_reg.s.pcterr) { 87 /* 88 * We are getting preamble errors at 10Mbps. Most 89 * likely the PHY is giving us packets with misaligned 90 * preambles. In order to get these packets we need to 91 * disable preamble checking and do it in software. 92 */ 93 cvm_oct_set_hw_preamble(priv, false); 94 printk_ratelimited("%s: Using 10Mbps with software preamble removal\n", 95 dev->name); 96 } 97 } else { 98 /* 99 * Since the 10Mbps preamble workaround is allowed we need to 100 * enable preamble checking, FCS stripping, and clear error 101 * bits on every speed change. If errors occur during 10Mbps 102 * operation the above code will change this stuff 103 */ 104 if (priv->last_speed != link_info.s.speed) 105 cvm_oct_set_hw_preamble(priv, true); 106 priv->last_speed = link_info.s.speed; 107 } 108 spin_unlock_irqrestore(&global_register_lock, flags); 109 } 110 111 static void cvm_oct_rgmii_poll(struct net_device *dev) 112 { 113 struct octeon_ethernet *priv = netdev_priv(dev); 114 cvmx_helper_link_info_t link_info; 115 bool status_change; 116 117 link_info = cvmx_helper_link_get(priv->port); 118 if (priv->link_info != link_info.u64 && 119 cvmx_helper_link_set(priv->port, link_info)) 120 link_info.u64 = priv->link_info; 121 status_change = priv->link_info != link_info.u64; 122 priv->link_info = link_info.u64; 123 124 cvm_oct_check_preamble_errors(dev); 125 126 if (likely(!status_change)) 127 return; 128 129 /* Tell core. */ 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); 135 } 136 cvm_oct_note_carrier(priv, link_info); 137 } 138 139 int cvm_oct_rgmii_open(struct net_device *dev) 140 { 141 struct octeon_ethernet *priv = netdev_priv(dev); 142 int ret; 143 144 ret = cvm_oct_common_open(dev, cvm_oct_rgmii_poll); 145 if (ret) 146 return ret; 147 148 if (dev->phydev) { 149 /* 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. 153 * 154 * Only true RGMII ports need to be polled. In GMII mode, port 155 * 0 is really a RGMII port. 156 */ 157 if ((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII && 158 priv->port == 0) || 159 (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { 160 priv->poll = cvm_oct_check_preamble_errors; 161 cvm_oct_check_preamble_errors(dev); 162 } 163 } 164 165 return 0; 166 } 167