1 /********************************************************************* 2 * Author: Cavium Networks 3 * 4 * Contact: support@caviumnetworks.com 5 * This file is part of the OCTEON SDK 6 * 7 * Copyright (c) 2003-2007 Cavium Networks 8 * 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. 12 * 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 17 * details. 18 * 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/. 23 * 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 <net/dst.h> 30 31 #include <asm/octeon/octeon.h> 32 33 #include "ethernet-defines.h" 34 #include "octeon-ethernet.h" 35 #include "ethernet-util.h" 36 37 #include "cvmx-helper.h" 38 39 #include <asm/octeon/cvmx-ipd-defs.h> 40 #include <asm/octeon/cvmx-npi-defs.h> 41 #include "cvmx-gmxx-defs.h" 42 43 DEFINE_SPINLOCK(global_register_lock); 44 45 static int number_rgmii_ports; 46 47 static void cvm_oct_rgmii_poll(struct net_device *dev) 48 { 49 struct octeon_ethernet *priv = netdev_priv(dev); 50 unsigned long flags; 51 cvmx_helper_link_info_t link_info; 52 53 /* 54 * Take the global register lock since we are going to touch 55 * registers that affect more than one port. 56 */ 57 spin_lock_irqsave(&global_register_lock, flags); 58 59 link_info = cvmx_helper_link_get(priv->port); 60 if (link_info.u64 == priv->link_info) { 61 62 /* 63 * If the 10Mbps preamble workaround is supported and we're 64 * at 10Mbps we may need to do some special checking. 65 */ 66 if (USE_10MBPS_PREAMBLE_WORKAROUND && (link_info.s.speed == 10)) { 67 68 /* 69 * Read the GMXX_RXX_INT_REG[PCTERR] bit and 70 * see if we are getting preamble errors. 71 */ 72 int interface = INTERFACE(priv->port); 73 int index = INDEX(priv->port); 74 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; 75 gmxx_rxx_int_reg.u64 = 76 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG 77 (index, interface)); 78 if (gmxx_rxx_int_reg.s.pcterr) { 79 80 /* 81 * We are getting preamble errors at 82 * 10Mbps. Most likely the PHY is 83 * giving us packets with mis aligned 84 * preambles. In order to get these 85 * packets we need to disable preamble 86 * checking and do it in software. 87 */ 88 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; 89 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; 90 91 /* Disable preamble checking */ 92 gmxx_rxx_frm_ctl.u64 = 93 cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL 94 (index, interface)); 95 gmxx_rxx_frm_ctl.s.pre_chk = 0; 96 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL 97 (index, interface), 98 gmxx_rxx_frm_ctl.u64); 99 100 /* Disable FCS stripping */ 101 ipd_sub_port_fcs.u64 = 102 cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); 103 ipd_sub_port_fcs.s.port_bit &= 104 0xffffffffull ^ (1ull << priv->port); 105 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, 106 ipd_sub_port_fcs.u64); 107 108 /* Clear any error bits */ 109 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG 110 (index, interface), 111 gmxx_rxx_int_reg.u64); 112 DEBUGPRINT("%s: Using 10Mbps with software " 113 "preamble removal\n", 114 dev->name); 115 } 116 } 117 spin_unlock_irqrestore(&global_register_lock, flags); 118 return; 119 } 120 121 /* If the 10Mbps preamble workaround is allowed we need to on 122 preamble checking, FCS stripping, and clear error bits on 123 every speed change. If errors occur during 10Mbps operation 124 the above code will change this stuff */ 125 if (USE_10MBPS_PREAMBLE_WORKAROUND) { 126 127 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; 128 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; 129 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; 130 int interface = INTERFACE(priv->port); 131 int index = INDEX(priv->port); 132 133 /* Enable preamble checking */ 134 gmxx_rxx_frm_ctl.u64 = 135 cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); 136 gmxx_rxx_frm_ctl.s.pre_chk = 1; 137 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), 138 gmxx_rxx_frm_ctl.u64); 139 /* Enable FCS stripping */ 140 ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); 141 ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port; 142 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); 143 /* Clear any error bits */ 144 gmxx_rxx_int_reg.u64 = 145 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface)); 146 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), 147 gmxx_rxx_int_reg.u64); 148 } 149 if (priv->phydev == NULL) { 150 link_info = cvmx_helper_link_autoconf(priv->port); 151 priv->link_info = link_info.u64; 152 } 153 spin_unlock_irqrestore(&global_register_lock, flags); 154 155 if (priv->phydev == NULL) { 156 /* Tell core. */ 157 if (link_info.s.link_up) { 158 if (!netif_carrier_ok(dev)) 159 netif_carrier_on(dev); 160 if (priv->queue != -1) 161 DEBUGPRINT("%s: %u Mbps %s duplex, " 162 "port %2d, queue %2d\n", 163 dev->name, link_info.s.speed, 164 (link_info.s.full_duplex) ? 165 "Full" : "Half", 166 priv->port, priv->queue); 167 else 168 DEBUGPRINT("%s: %u Mbps %s duplex, " 169 "port %2d, POW\n", 170 dev->name, link_info.s.speed, 171 (link_info.s.full_duplex) ? 172 "Full" : "Half", 173 priv->port); 174 } else { 175 if (netif_carrier_ok(dev)) 176 netif_carrier_off(dev); 177 DEBUGPRINT("%s: Link down\n", dev->name); 178 } 179 } 180 } 181 182 static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) 183 { 184 union cvmx_npi_rsl_int_blocks rsl_int_blocks; 185 int index; 186 irqreturn_t return_status = IRQ_NONE; 187 188 rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); 189 190 /* Check and see if this interrupt was caused by the GMX0 block */ 191 if (rsl_int_blocks.s.gmx0) { 192 193 int interface = 0; 194 /* Loop through every port of this interface */ 195 for (index = 0; 196 index < cvmx_helper_ports_on_interface(interface); 197 index++) { 198 199 /* Read the GMX interrupt status bits */ 200 union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; 201 gmx_rx_int_reg.u64 = 202 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG 203 (index, interface)); 204 gmx_rx_int_reg.u64 &= 205 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN 206 (index, interface)); 207 /* Poll the port if inband status changed */ 208 if (gmx_rx_int_reg.s.phy_dupx 209 || gmx_rx_int_reg.s.phy_link 210 || gmx_rx_int_reg.s.phy_spd) { 211 212 struct net_device *dev = 213 cvm_oct_device[cvmx_helper_get_ipd_port 214 (interface, index)]; 215 if (dev) 216 cvm_oct_rgmii_poll(dev); 217 gmx_rx_int_reg.u64 = 0; 218 gmx_rx_int_reg.s.phy_dupx = 1; 219 gmx_rx_int_reg.s.phy_link = 1; 220 gmx_rx_int_reg.s.phy_spd = 1; 221 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG 222 (index, interface), 223 gmx_rx_int_reg.u64); 224 return_status = IRQ_HANDLED; 225 } 226 } 227 } 228 229 /* Check and see if this interrupt was caused by the GMX1 block */ 230 if (rsl_int_blocks.s.gmx1) { 231 232 int interface = 1; 233 /* Loop through every port of this interface */ 234 for (index = 0; 235 index < cvmx_helper_ports_on_interface(interface); 236 index++) { 237 238 /* Read the GMX interrupt status bits */ 239 union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; 240 gmx_rx_int_reg.u64 = 241 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG 242 (index, interface)); 243 gmx_rx_int_reg.u64 &= 244 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN 245 (index, interface)); 246 /* Poll the port if inband status changed */ 247 if (gmx_rx_int_reg.s.phy_dupx 248 || gmx_rx_int_reg.s.phy_link 249 || gmx_rx_int_reg.s.phy_spd) { 250 251 struct net_device *dev = 252 cvm_oct_device[cvmx_helper_get_ipd_port 253 (interface, index)]; 254 if (dev) 255 cvm_oct_rgmii_poll(dev); 256 gmx_rx_int_reg.u64 = 0; 257 gmx_rx_int_reg.s.phy_dupx = 1; 258 gmx_rx_int_reg.s.phy_link = 1; 259 gmx_rx_int_reg.s.phy_spd = 1; 260 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG 261 (index, interface), 262 gmx_rx_int_reg.u64); 263 return_status = IRQ_HANDLED; 264 } 265 } 266 } 267 return return_status; 268 } 269 270 int cvm_oct_rgmii_open(struct net_device *dev) 271 { 272 union cvmx_gmxx_prtx_cfg gmx_cfg; 273 struct octeon_ethernet *priv = netdev_priv(dev); 274 int interface = INTERFACE(priv->port); 275 int index = INDEX(priv->port); 276 cvmx_helper_link_info_t link_info; 277 278 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 279 gmx_cfg.s.en = 1; 280 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 281 282 if (!octeon_is_simulation()) { 283 link_info = cvmx_helper_link_get(priv->port); 284 if (!link_info.s.link_up) 285 netif_carrier_off(dev); 286 } 287 288 return 0; 289 } 290 291 int cvm_oct_rgmii_stop(struct net_device *dev) 292 { 293 union cvmx_gmxx_prtx_cfg gmx_cfg; 294 struct octeon_ethernet *priv = netdev_priv(dev); 295 int interface = INTERFACE(priv->port); 296 int index = INDEX(priv->port); 297 298 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 299 gmx_cfg.s.en = 0; 300 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 301 return 0; 302 } 303 304 int cvm_oct_rgmii_init(struct net_device *dev) 305 { 306 struct octeon_ethernet *priv = netdev_priv(dev); 307 int r; 308 309 cvm_oct_common_init(dev); 310 dev->netdev_ops->ndo_stop(dev); 311 312 /* 313 * Due to GMX errata in CN3XXX series chips, it is necessary 314 * to take the link down immediately when the PHY changes 315 * state. In order to do this we call the poll function every 316 * time the RGMII inband status changes. This may cause 317 * problems if the PHY doesn't implement inband status 318 * properly. 319 */ 320 if (number_rgmii_ports == 0) { 321 r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt, 322 IRQF_SHARED, "RGMII", &number_rgmii_ports); 323 if (r != 0) 324 return r; 325 } 326 number_rgmii_ports++; 327 328 /* 329 * Only true RGMII ports need to be polled. In GMII mode, port 330 * 0 is really a RGMII port. 331 */ 332 if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) 333 && (priv->port == 0)) 334 || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { 335 336 if (!octeon_is_simulation()) { 337 338 union cvmx_gmxx_rxx_int_en gmx_rx_int_en; 339 int interface = INTERFACE(priv->port); 340 int index = INDEX(priv->port); 341 342 /* 343 * Enable interrupts on inband status changes 344 * for this port. 345 */ 346 gmx_rx_int_en.u64 = 347 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN 348 (index, interface)); 349 gmx_rx_int_en.s.phy_dupx = 1; 350 gmx_rx_int_en.s.phy_link = 1; 351 gmx_rx_int_en.s.phy_spd = 1; 352 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), 353 gmx_rx_int_en.u64); 354 priv->poll = cvm_oct_rgmii_poll; 355 } 356 } 357 358 return 0; 359 } 360 361 void cvm_oct_rgmii_uninit(struct net_device *dev) 362 { 363 struct octeon_ethernet *priv = netdev_priv(dev); 364 cvm_oct_common_uninit(dev); 365 366 /* 367 * Only true RGMII ports need to be polled. In GMII mode, port 368 * 0 is really a RGMII port. 369 */ 370 if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) 371 && (priv->port == 0)) 372 || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { 373 374 if (!octeon_is_simulation()) { 375 376 union cvmx_gmxx_rxx_int_en gmx_rx_int_en; 377 int interface = INTERFACE(priv->port); 378 int index = INDEX(priv->port); 379 380 /* 381 * Disable interrupts on inband status changes 382 * for this port. 383 */ 384 gmx_rx_int_en.u64 = 385 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN 386 (index, interface)); 387 gmx_rx_int_en.s.phy_dupx = 0; 388 gmx_rx_int_en.s.phy_link = 0; 389 gmx_rx_int_en.s.phy_spd = 0; 390 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), 391 gmx_rx_int_en.u64); 392 } 393 } 394 395 /* Remove the interrupt handler when the last port is removed. */ 396 number_rgmii_ports--; 397 if (number_rgmii_ports == 0) 398 free_irq(OCTEON_IRQ_RML, &number_rgmii_ports); 399 } 400