ethernet-rgmii.c 12 KB

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