1 /* 2 * This file is based on code from OCTEON SDK by Cavium Networks. 3 * 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. 9 */ 10 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> 16 #include <net/dst.h> 17 18 #include <asm/octeon/octeon.h> 19 20 #include "ethernet-defines.h" 21 #include "octeon-ethernet.h" 22 #include "ethernet-util.h" 23 #include "ethernet-mdio.h" 24 25 #include <asm/octeon/cvmx-helper.h> 26 27 #include <asm/octeon/cvmx-ipd-defs.h> 28 #include <asm/octeon/cvmx-npi-defs.h> 29 #include <asm/octeon/cvmx-gmxx-defs.h> 30 31 static DEFINE_SPINLOCK(global_register_lock); 32 33 static 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 64 static 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 114 static void cvm_oct_rgmii_poll(struct net_device *dev) 115 { 116 struct octeon_ethernet *priv = netdev_priv(dev); 117 cvmx_helper_link_info_t link_info; 118 bool status_change; 119 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; 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 (priv->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