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