ethernet-rgmii.c 4.7 KB

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