Merge branch 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.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 "cvmx-helper.h"
41
42 #include <asm/octeon/cvmx-ipd-defs.h>
43 #include <asm/octeon/cvmx-npi-defs.h>
44 #include "cvmx-gmxx-defs.h"
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;
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 && (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 */
138         if (USE_10MBPS_PREAMBLE_WORKAROUND) {
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;
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 && !atomic_read(&cvm_oct_poll_queue_stopping))
236                                         queue_work(cvm_oct_poll_queue, &priv->port_work);
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;
256                      index < cvmx_helper_ports_on_interface(interface);
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 =
273                                     cvm_oct_device[cvmx_helper_get_ipd_port
274                                                    (interface, index)];
275                                 struct octeon_ethernet *priv = netdev_priv(dev);
276
277                                 if (dev && !atomic_read(&cvm_oct_poll_queue_stopping))
278                                         queue_work(cvm_oct_poll_queue, &priv->port_work);
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
294 int cvm_oct_rgmii_open(struct net_device *dev)
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
315 int cvm_oct_rgmii_stop(struct net_device *dev)
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
334 int cvm_oct_rgmii_init(struct net_device *dev)
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
391 void cvm_oct_rgmii_uninit(struct net_device *dev)
392 {
393         struct octeon_ethernet *priv = netdev_priv(dev);
394         cvm_oct_common_uninit(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 }