ethernet-rgmii.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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 int number_rgmii_ports;
  27. static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable)
  28. {
  29. union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
  30. union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
  31. union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
  32. int interface = INTERFACE(priv->port);
  33. int index = INDEX(priv->port);
  34. /* Set preamble checking. */
  35. gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index,
  36. interface));
  37. gmxx_rxx_frm_ctl.s.pre_chk = enable;
  38. cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
  39. gmxx_rxx_frm_ctl.u64);
  40. /* Set FCS stripping. */
  41. ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
  42. if (enable)
  43. ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
  44. else
  45. ipd_sub_port_fcs.s.port_bit &=
  46. 0xffffffffull ^ (1ull << priv->port);
  47. cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
  48. /* Clear any error bits. */
  49. gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index,
  50. interface));
  51. cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
  52. gmxx_rxx_int_reg.u64);
  53. }
  54. static void cvm_oct_rgmii_poll(struct net_device *dev)
  55. {
  56. struct octeon_ethernet *priv = netdev_priv(dev);
  57. unsigned long flags = 0;
  58. cvmx_helper_link_info_t link_info;
  59. int use_global_register_lock = (priv->phydev == NULL);
  60. BUG_ON(in_interrupt());
  61. if (use_global_register_lock) {
  62. /*
  63. * Take the global register lock since we are going to
  64. * touch registers that affect more than one port.
  65. */
  66. spin_lock_irqsave(&global_register_lock, flags);
  67. } else {
  68. mutex_lock(&priv->phydev->bus->mdio_lock);
  69. }
  70. link_info = cvmx_helper_link_get(priv->port);
  71. if (link_info.u64 == priv->link_info) {
  72. if (link_info.s.speed == 10) {
  73. /*
  74. * Read the GMXX_RXX_INT_REG[PCTERR] bit and
  75. * see if we are getting preamble errors.
  76. */
  77. int interface = INTERFACE(priv->port);
  78. int index = INDEX(priv->port);
  79. union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
  80. gmxx_rxx_int_reg.u64 =
  81. cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
  82. (index, interface));
  83. if (gmxx_rxx_int_reg.s.pcterr) {
  84. /*
  85. * We are getting preamble errors at
  86. * 10Mbps. Most likely the PHY is
  87. * giving us packets with mis aligned
  88. * preambles. In order to get these
  89. * packets we need to disable preamble
  90. * checking and do it in software.
  91. */
  92. cvm_oct_set_hw_preamble(priv, false);
  93. printk_ratelimited("%s: Using 10Mbps with software preamble removal\n",
  94. dev->name);
  95. }
  96. }
  97. if (use_global_register_lock)
  98. spin_unlock_irqrestore(&global_register_lock, flags);
  99. else
  100. mutex_unlock(&priv->phydev->bus->mdio_lock);
  101. return;
  102. }
  103. /* Since the 10Mbps preamble workaround is allowed we need to enable
  104. * preamble checking, FCS stripping, and clear error bits on
  105. * every speed change. If errors occur during 10Mbps operation
  106. * the above code will change this stuff
  107. */
  108. cvm_oct_set_hw_preamble(priv, true);
  109. if (priv->phydev == NULL) {
  110. link_info = cvmx_helper_link_autoconf(priv->port);
  111. priv->link_info = link_info.u64;
  112. }
  113. if (use_global_register_lock)
  114. spin_unlock_irqrestore(&global_register_lock, flags);
  115. else
  116. mutex_unlock(&priv->phydev->bus->mdio_lock);
  117. if (priv->phydev == NULL) {
  118. /* Tell core. */
  119. if (link_info.s.link_up) {
  120. if (!netif_carrier_ok(dev))
  121. netif_carrier_on(dev);
  122. } else if (netif_carrier_ok(dev)) {
  123. netif_carrier_off(dev);
  124. }
  125. cvm_oct_note_carrier(priv, link_info);
  126. }
  127. }
  128. static int cmv_oct_rgmii_gmx_interrupt(int interface)
  129. {
  130. int index;
  131. int count = 0;
  132. /* Loop through every port of this interface */
  133. for (index = 0;
  134. index < cvmx_helper_ports_on_interface(interface);
  135. index++) {
  136. union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
  137. /* Read the GMX interrupt status bits */
  138. gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
  139. (index, interface));
  140. gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
  141. (index, interface));
  142. /* Poll the port if inband status changed */
  143. if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link ||
  144. gmx_rx_int_reg.s.phy_spd) {
  145. struct net_device *dev =
  146. cvm_oct_device[cvmx_helper_get_ipd_port
  147. (interface, index)];
  148. struct octeon_ethernet *priv = netdev_priv(dev);
  149. if (dev && !atomic_read(&cvm_oct_poll_queue_stopping))
  150. queue_work(cvm_oct_poll_queue,
  151. &priv->port_work);
  152. gmx_rx_int_reg.u64 = 0;
  153. gmx_rx_int_reg.s.phy_dupx = 1;
  154. gmx_rx_int_reg.s.phy_link = 1;
  155. gmx_rx_int_reg.s.phy_spd = 1;
  156. cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
  157. gmx_rx_int_reg.u64);
  158. count++;
  159. }
  160. }
  161. return count;
  162. }
  163. static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
  164. {
  165. union cvmx_npi_rsl_int_blocks rsl_int_blocks;
  166. int count = 0;
  167. rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
  168. /* Check and see if this interrupt was caused by the GMX0 block */
  169. if (rsl_int_blocks.s.gmx0)
  170. count += cmv_oct_rgmii_gmx_interrupt(0);
  171. /* Check and see if this interrupt was caused by the GMX1 block */
  172. if (rsl_int_blocks.s.gmx1)
  173. count += cmv_oct_rgmii_gmx_interrupt(1);
  174. return count ? IRQ_HANDLED : IRQ_NONE;
  175. }
  176. int cvm_oct_rgmii_open(struct net_device *dev)
  177. {
  178. return cvm_oct_common_open(dev, cvm_oct_rgmii_poll);
  179. }
  180. static void cvm_oct_rgmii_immediate_poll(struct work_struct *work)
  181. {
  182. struct octeon_ethernet *priv =
  183. container_of(work, struct octeon_ethernet, port_work);
  184. cvm_oct_rgmii_poll(cvm_oct_device[priv->port]);
  185. }
  186. int cvm_oct_rgmii_init(struct net_device *dev)
  187. {
  188. struct octeon_ethernet *priv = netdev_priv(dev);
  189. int r;
  190. cvm_oct_common_init(dev);
  191. INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll);
  192. /*
  193. * Due to GMX errata in CN3XXX series chips, it is necessary
  194. * to take the link down immediately when the PHY changes
  195. * state. In order to do this we call the poll function every
  196. * time the RGMII inband status changes. This may cause
  197. * problems if the PHY doesn't implement inband status
  198. * properly.
  199. */
  200. if (number_rgmii_ports == 0) {
  201. r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
  202. IRQF_SHARED, "RGMII", &number_rgmii_ports);
  203. if (r != 0)
  204. return r;
  205. }
  206. number_rgmii_ports++;
  207. /*
  208. * Only true RGMII ports need to be polled. In GMII mode, port
  209. * 0 is really a RGMII port.
  210. */
  211. if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
  212. && (priv->port == 0))
  213. || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
  214. if (!octeon_is_simulation()) {
  215. union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
  216. int interface = INTERFACE(priv->port);
  217. int index = INDEX(priv->port);
  218. /*
  219. * Enable interrupts on inband status changes
  220. * for this port.
  221. */
  222. gmx_rx_int_en.u64 = 0;
  223. gmx_rx_int_en.s.phy_dupx = 1;
  224. gmx_rx_int_en.s.phy_link = 1;
  225. gmx_rx_int_en.s.phy_spd = 1;
  226. cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
  227. gmx_rx_int_en.u64);
  228. }
  229. }
  230. return 0;
  231. }
  232. void cvm_oct_rgmii_uninit(struct net_device *dev)
  233. {
  234. struct octeon_ethernet *priv = netdev_priv(dev);
  235. cvm_oct_common_uninit(dev);
  236. /*
  237. * Only true RGMII ports need to be polled. In GMII mode, port
  238. * 0 is really a RGMII port.
  239. */
  240. if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
  241. && (priv->port == 0))
  242. || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
  243. if (!octeon_is_simulation()) {
  244. union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
  245. int interface = INTERFACE(priv->port);
  246. int index = INDEX(priv->port);
  247. /*
  248. * Disable interrupts on inband status changes
  249. * for this port.
  250. */
  251. gmx_rx_int_en.u64 =
  252. cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
  253. (index, interface));
  254. gmx_rx_int_en.s.phy_dupx = 0;
  255. gmx_rx_int_en.s.phy_link = 0;
  256. gmx_rx_int_en.s.phy_spd = 0;
  257. cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
  258. gmx_rx_int_en.u64);
  259. }
  260. }
  261. /* Remove the interrupt handler when the last port is removed. */
  262. number_rgmii_ports--;
  263. if (number_rgmii_ports == 0)
  264. free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
  265. cancel_work_sync(&priv->port_work);
  266. }