Merge tag 'dm-3.17-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device...
[linux-2.6-microblaze.git] / 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                         gmxx_rxx_int_reg.u64 =
87                             cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
88                                           (index, interface));
89                         if (gmxx_rxx_int_reg.s.pcterr) {
90
91                                 /*
92                                  * We are getting preamble errors at
93                                  * 10Mbps.  Most likely the PHY is
94                                  * giving us packets with mis aligned
95                                  * preambles. In order to get these
96                                  * packets we need to disable preamble
97                                  * checking and do it in software.
98                                  */
99                                 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
100                                 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
101
102                                 /* Disable preamble checking */
103                                 gmxx_rxx_frm_ctl.u64 =
104                                     cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
105                                                   (index, interface));
106                                 gmxx_rxx_frm_ctl.s.pre_chk = 0;
107                                 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL
108                                                (index, interface),
109                                                gmxx_rxx_frm_ctl.u64);
110
111                                 /* Disable FCS stripping */
112                                 ipd_sub_port_fcs.u64 =
113                                     cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
114                                 ipd_sub_port_fcs.s.port_bit &=
115                                     0xffffffffull ^ (1ull << priv->port);
116                                 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS,
117                                                ipd_sub_port_fcs.u64);
118
119                                 /* Clear any error bits */
120                                 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
121                                                (index, interface),
122                                                gmxx_rxx_int_reg.u64);
123                                 printk_ratelimited("%s: Using 10Mbps with software "
124                                                    "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, "
181                                                    "port %2d, queue %2d\n",
182                                                    dev->name, link_info.s.speed,
183                                                    (link_info.s.full_duplex) ?
184                                                    "Full" : "Half",
185                                                    priv->port, priv->queue);
186                         else
187                                 printk_ratelimited("%s: %u Mbps %s duplex, "
188                                                    "port %2d, POW\n",
189                                                    dev->name, link_info.s.speed,
190                                                    (link_info.s.full_duplex) ?
191                                                    "Full" : "Half",
192                                                    priv->port);
193                 } else {
194                         if (netif_carrier_ok(dev))
195                                 netif_carrier_off(dev);
196                         printk_ratelimited("%s: Link down\n", dev->name);
197                 }
198         }
199 }
200
201 static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
202 {
203         union cvmx_npi_rsl_int_blocks rsl_int_blocks;
204         int index;
205         irqreturn_t return_status = IRQ_NONE;
206
207         rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
208
209         /* Check and see if this interrupt was caused by the GMX0 block */
210         if (rsl_int_blocks.s.gmx0) {
211
212                 int interface = 0;
213                 /* Loop through every port of this interface */
214                 for (index = 0;
215                      index < cvmx_helper_ports_on_interface(interface);
216                      index++) {
217
218                         /* Read the GMX interrupt status bits */
219                         union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
220                         gmx_rx_int_reg.u64 =
221                             cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
222                                           (index, interface));
223                         gmx_rx_int_reg.u64 &=
224                             cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
225                                           (index, interface));
226                         /* Poll the port if inband status changed */
227                         if (gmx_rx_int_reg.s.phy_dupx
228                             || gmx_rx_int_reg.s.phy_link
229                             || gmx_rx_int_reg.s.phy_spd) {
230
231                                 struct net_device *dev =
232                                     cvm_oct_device[cvmx_helper_get_ipd_port
233                                                    (interface, index)];
234                                 struct octeon_ethernet *priv = netdev_priv(dev);
235
236                                 if (dev &&
237                                 !atomic_read(&cvm_oct_poll_queue_stopping))
238                                         queue_work(cvm_oct_poll_queue,
239                                                 &priv->port_work);
240
241                                 gmx_rx_int_reg.u64 = 0;
242                                 gmx_rx_int_reg.s.phy_dupx = 1;
243                                 gmx_rx_int_reg.s.phy_link = 1;
244                                 gmx_rx_int_reg.s.phy_spd = 1;
245                                 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
246                                                (index, interface),
247                                                gmx_rx_int_reg.u64);
248                                 return_status = IRQ_HANDLED;
249                         }
250                 }
251         }
252
253         /* Check and see if this interrupt was caused by the GMX1 block */
254         if (rsl_int_blocks.s.gmx1) {
255
256                 int interface = 1;
257                 /* Loop through every port of this interface */
258                 for (index = 0;
259                      index < cvmx_helper_ports_on_interface(interface);
260                      index++) {
261
262                         /* Read the GMX interrupt status bits */
263                         union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
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                         if (r == 0 && priv->phydev->link == 0)
320                                 netif_carrier_off(dev);
321                         cvm_oct_adjust_link(dev);
322                 } else {
323                         link_info = cvmx_helper_link_get(priv->port);
324                         if (!link_info.s.link_up)
325                                 netif_carrier_off(dev);
326                         priv->poll = cvm_oct_rgmii_poll;
327                 }
328         }
329
330         return 0;
331 }
332
333 int cvm_oct_rgmii_stop(struct net_device *dev)
334 {
335         union cvmx_gmxx_prtx_cfg gmx_cfg;
336         struct octeon_ethernet *priv = netdev_priv(dev);
337         int interface = INTERFACE(priv->port);
338         int index = INDEX(priv->port);
339
340         gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
341         gmx_cfg.s.en = 0;
342         cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
343         return cvm_oct_common_stop(dev);
344 }
345
346 static void cvm_oct_rgmii_immediate_poll(struct work_struct *work)
347 {
348         struct octeon_ethernet *priv =
349                 container_of(work, struct octeon_ethernet, port_work);
350         cvm_oct_rgmii_poll(cvm_oct_device[priv->port]);
351 }
352
353 int cvm_oct_rgmii_init(struct net_device *dev)
354 {
355         struct octeon_ethernet *priv = netdev_priv(dev);
356         int r;
357
358         cvm_oct_common_init(dev);
359         dev->netdev_ops->ndo_stop(dev);
360         INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll);
361         /*
362          * Due to GMX errata in CN3XXX series chips, it is necessary
363          * to take the link down immediately when the PHY changes
364          * state. In order to do this we call the poll function every
365          * time the RGMII inband status changes.  This may cause
366          * problems if the PHY doesn't implement inband status
367          * properly.
368          */
369         if (number_rgmii_ports == 0) {
370                 r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
371                                 IRQF_SHARED, "RGMII", &number_rgmii_ports);
372                 if (r != 0)
373                         return r;
374         }
375         number_rgmii_ports++;
376
377         /*
378          * Only true RGMII ports need to be polled. In GMII mode, port
379          * 0 is really a RGMII port.
380          */
381         if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
382              && (priv->port == 0))
383             || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
384
385                 if (!octeon_is_simulation()) {
386
387                         union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
388                         int interface = INTERFACE(priv->port);
389                         int index = INDEX(priv->port);
390
391                         /*
392                          * Enable interrupts on inband status changes
393                          * for this port.
394                          */
395                         gmx_rx_int_en.u64 = 0;
396                         gmx_rx_int_en.s.phy_dupx = 1;
397                         gmx_rx_int_en.s.phy_link = 1;
398                         gmx_rx_int_en.s.phy_spd = 1;
399                         cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
400                                        gmx_rx_int_en.u64);
401                 }
402         }
403
404         return 0;
405 }
406
407 void cvm_oct_rgmii_uninit(struct net_device *dev)
408 {
409         struct octeon_ethernet *priv = netdev_priv(dev);
410         cvm_oct_common_uninit(dev);
411
412         /*
413          * Only true RGMII ports need to be polled. In GMII mode, port
414          * 0 is really a RGMII port.
415          */
416         if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
417              && (priv->port == 0))
418             || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
419
420                 if (!octeon_is_simulation()) {
421
422                         union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
423                         int interface = INTERFACE(priv->port);
424                         int index = INDEX(priv->port);
425
426                         /*
427                          * Disable interrupts on inband status changes
428                          * for this port.
429                          */
430                         gmx_rx_int_en.u64 =
431                             cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
432                                           (index, interface));
433                         gmx_rx_int_en.s.phy_dupx = 0;
434                         gmx_rx_int_en.s.phy_link = 0;
435                         gmx_rx_int_en.s.phy_spd = 0;
436                         cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
437                                        gmx_rx_int_en.u64);
438                 }
439         }
440
441         /* Remove the interrupt handler when the last port is removed. */
442         number_rgmii_ports--;
443         if (number_rgmii_ports == 0)
444                 free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
445         cancel_work_sync(&priv->port_work);
446 }