Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
[firefly-linux-kernel-4.4.55.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
40 #include <asm/octeon/cvmx-helper.h>
41
42 #include <asm/octeon/cvmx-ipd-defs.h>
43 #include <asm/octeon/cvmx-npi-defs.h>
44 #include <asm/octeon/cvmx-gmxx-defs.h>
45
46 static 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;
54         cvmx_helper_link_info_t link_info;
55         int use_global_register_lock = (priv->phydev == NULL);
56
57         BUG_ON(in_interrupt());
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 &&
76                                 (link_info.s.speed == 10)) {
77
78                         /*
79                          * Read the GMXX_RXX_INT_REG[PCTERR] bit and
80                          * see if we are getting preamble errors.
81                          */
82                         int interface = INTERFACE(priv->port);
83                         int index = INDEX(priv->port);
84                         union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
85                         gmxx_rxx_int_reg.u64 =
86                             cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
87                                           (index, interface));
88                         if (gmxx_rxx_int_reg.s.pcterr) {
89
90                                 /*
91                                  * We are getting preamble errors at
92                                  * 10Mbps.  Most likely the PHY is
93                                  * giving us packets with mis aligned
94                                  * preambles. In order to get these
95                                  * packets we need to disable preamble
96                                  * checking and do it in software.
97                                  */
98                                 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
99                                 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
100
101                                 /* Disable preamble checking */
102                                 gmxx_rxx_frm_ctl.u64 =
103                                     cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
104                                                   (index, interface));
105                                 gmxx_rxx_frm_ctl.s.pre_chk = 0;
106                                 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL
107                                                (index, interface),
108                                                gmxx_rxx_frm_ctl.u64);
109
110                                 /* Disable FCS stripping */
111                                 ipd_sub_port_fcs.u64 =
112                                     cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
113                                 ipd_sub_port_fcs.s.port_bit &=
114                                     0xffffffffull ^ (1ull << priv->port);
115                                 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS,
116                                                ipd_sub_port_fcs.u64);
117
118                                 /* Clear any error bits */
119                                 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
120                                                (index, interface),
121                                                gmxx_rxx_int_reg.u64);
122                                 printk_ratelimited("%s: Using 10Mbps with software "
123                                                    "preamble removal\n",
124                                                    dev->name);
125                         }
126                 }
127
128                 if (use_global_register_lock)
129                         spin_unlock_irqrestore(&global_register_lock, flags);
130                 else
131                         mutex_unlock(&priv->phydev->bus->mdio_lock);
132                 return;
133         }
134
135         /* If the 10Mbps preamble workaround is allowed we need to on
136            preamble checking, FCS stripping, and clear error bits on
137            every speed change. If errors occur during 10Mbps operation
138            the above code will change this stuff */
139         if (USE_10MBPS_PREAMBLE_WORKAROUND) {
140
141                 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
142                 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
143                 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
144                 int interface = INTERFACE(priv->port);
145                 int index = INDEX(priv->port);
146
147                 /* Enable preamble checking */
148                 gmxx_rxx_frm_ctl.u64 =
149                     cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
150                 gmxx_rxx_frm_ctl.s.pre_chk = 1;
151                 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
152                                gmxx_rxx_frm_ctl.u64);
153                 /* Enable FCS stripping */
154                 ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
155                 ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
156                 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
157                 /* Clear any error bits */
158                 gmxx_rxx_int_reg.u64 =
159                     cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
160                 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
161                                gmxx_rxx_int_reg.u64);
162         }
163         if (priv->phydev == NULL) {
164                 link_info = cvmx_helper_link_autoconf(priv->port);
165                 priv->link_info = link_info.u64;
166         }
167
168         if (use_global_register_lock)
169                 spin_unlock_irqrestore(&global_register_lock, flags);
170         else
171                 mutex_unlock(&priv->phydev->bus->mdio_lock);
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;
214                      index < cvmx_helper_ports_on_interface(interface);
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 =
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                         gmx_rx_int_reg.u64 =
264                             cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
265                                           (index, interface));
266                         gmx_rx_int_reg.u64 &=
267                             cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
268                                           (index, interface));
269                         /* Poll the port if inband status changed */
270                         if (gmx_rx_int_reg.s.phy_dupx
271                             || gmx_rx_int_reg.s.phy_link
272                             || gmx_rx_int_reg.s.phy_spd) {
273
274                                 struct net_device *dev =
275                                     cvm_oct_device[cvmx_helper_get_ipd_port
276                                                    (interface, index)];
277                                 struct octeon_ethernet *priv = netdev_priv(dev);
278
279                                 if (dev &&
280                                 !atomic_read(&cvm_oct_poll_queue_stopping))
281                                         queue_work(cvm_oct_poll_queue,
282                                                 &priv->port_work);
283
284                                 gmx_rx_int_reg.u64 = 0;
285                                 gmx_rx_int_reg.s.phy_dupx = 1;
286                                 gmx_rx_int_reg.s.phy_link = 1;
287                                 gmx_rx_int_reg.s.phy_spd = 1;
288                                 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
289                                                (index, interface),
290                                                gmx_rx_int_reg.u64);
291                                 return_status = IRQ_HANDLED;
292                         }
293                 }
294         }
295         return return_status;
296 }
297
298 int cvm_oct_rgmii_open(struct net_device *dev)
299 {
300         union cvmx_gmxx_prtx_cfg gmx_cfg;
301         struct octeon_ethernet *priv = netdev_priv(dev);
302         int interface = INTERFACE(priv->port);
303         int index = INDEX(priv->port);
304         cvmx_helper_link_info_t link_info;
305
306         gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
307         gmx_cfg.s.en = 1;
308         cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
309
310         if (!octeon_is_simulation()) {
311                 link_info = cvmx_helper_link_get(priv->port);
312                 if (!link_info.s.link_up)
313                         netif_carrier_off(dev);
314         }
315
316         return 0;
317 }
318
319 int cvm_oct_rgmii_stop(struct net_device *dev)
320 {
321         union cvmx_gmxx_prtx_cfg gmx_cfg;
322         struct octeon_ethernet *priv = netdev_priv(dev);
323         int interface = INTERFACE(priv->port);
324         int index = INDEX(priv->port);
325
326         gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
327         gmx_cfg.s.en = 0;
328         cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
329         return 0;
330 }
331
332 static void cvm_oct_rgmii_immediate_poll(struct work_struct *work)
333 {
334         struct octeon_ethernet *priv =
335                 container_of(work, struct octeon_ethernet, port_work);
336         cvm_oct_rgmii_poll(cvm_oct_device[priv->port]);
337 }
338
339 int cvm_oct_rgmii_init(struct net_device *dev)
340 {
341         struct octeon_ethernet *priv = netdev_priv(dev);
342         int r;
343
344         cvm_oct_common_init(dev);
345         dev->netdev_ops->ndo_stop(dev);
346         INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll);
347         /*
348          * Due to GMX errata in CN3XXX series chips, it is necessary
349          * to take the link down immediately when the PHY changes
350          * state. In order to do this we call the poll function every
351          * time the RGMII inband status changes.  This may cause
352          * problems if the PHY doesn't implement inband status
353          * properly.
354          */
355         if (number_rgmii_ports == 0) {
356                 r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
357                                 IRQF_SHARED, "RGMII", &number_rgmii_ports);
358                 if (r != 0)
359                         return r;
360         }
361         number_rgmii_ports++;
362
363         /*
364          * Only true RGMII ports need to be polled. In GMII mode, port
365          * 0 is really a RGMII port.
366          */
367         if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
368              && (priv->port == 0))
369             || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
370
371                 if (!octeon_is_simulation()) {
372
373                         union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
374                         int interface = INTERFACE(priv->port);
375                         int index = INDEX(priv->port);
376
377                         /*
378                          * Enable interrupts on inband status changes
379                          * for this port.
380                          */
381                         gmx_rx_int_en.u64 = 0;
382                         gmx_rx_int_en.s.phy_dupx = 1;
383                         gmx_rx_int_en.s.phy_link = 1;
384                         gmx_rx_int_en.s.phy_spd = 1;
385                         cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
386                                        gmx_rx_int_en.u64);
387                         priv->poll = cvm_oct_rgmii_poll;
388                 }
389         }
390
391         return 0;
392 }
393
394 void cvm_oct_rgmii_uninit(struct net_device *dev)
395 {
396         struct octeon_ethernet *priv = netdev_priv(dev);
397         cvm_oct_common_uninit(dev);
398
399         /*
400          * Only true RGMII ports need to be polled. In GMII mode, port
401          * 0 is really a RGMII port.
402          */
403         if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
404              && (priv->port == 0))
405             || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
406
407                 if (!octeon_is_simulation()) {
408
409                         union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
410                         int interface = INTERFACE(priv->port);
411                         int index = INDEX(priv->port);
412
413                         /*
414                          * Disable interrupts on inband status changes
415                          * for this port.
416                          */
417                         gmx_rx_int_en.u64 =
418                             cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
419                                           (index, interface));
420                         gmx_rx_int_en.s.phy_dupx = 0;
421                         gmx_rx_int_en.s.phy_link = 0;
422                         gmx_rx_int_en.s.phy_spd = 0;
423                         cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
424                                        gmx_rx_int_en.u64);
425                 }
426         }
427
428         /* Remove the interrupt handler when the last port is removed. */
429         number_rgmii_ports--;
430         if (number_rgmii_ports == 0)
431                 free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
432         cancel_work_sync(&priv->port_work);
433 }