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