ethernet-rgmii.c 4.8 KB

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