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