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