Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6 and git://git.infradea...
[pandora-kernel.git] / drivers / staging / octeon / ethernet-spi.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 <net/dst.h>
31
32 #include <asm/octeon/octeon.h>
33
34 #include "ethernet-defines.h"
35 #include "octeon-ethernet.h"
36 #include "ethernet-util.h"
37
38 #include "cvmx-spi.h"
39
40 #include <asm/octeon/cvmx-npi-defs.h>
41 #include "cvmx-spxx-defs.h"
42 #include "cvmx-stxx-defs.h"
43
44 static int number_spi_ports;
45 static int need_retrain[2] = { 0, 0 };
46
47 static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id)
48 {
49         irqreturn_t return_status = IRQ_NONE;
50         union cvmx_npi_rsl_int_blocks rsl_int_blocks;
51
52         /* Check and see if this interrupt was caused by the GMX block */
53         rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
54         if (rsl_int_blocks.s.spx1) {    /* 19 - SPX1_INT_REG & STX1_INT_REG */
55
56                 union cvmx_spxx_int_reg spx_int_reg;
57                 union cvmx_stxx_int_reg stx_int_reg;
58
59                 spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1));
60                 cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64);
61                 if (!need_retrain[1]) {
62
63                         spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1));
64                         if (spx_int_reg.s.spf)
65                                 pr_err("SPI1: SRX Spi4 interface down\n");
66                         if (spx_int_reg.s.calerr)
67                                 pr_err("SPI1: SRX Spi4 Calendar table "
68                                        "parity error\n");
69                         if (spx_int_reg.s.syncerr)
70                                 pr_err("SPI1: SRX Consecutive Spi4 DIP4 "
71                                        "errors have exceeded "
72                                        "SPX_ERR_CTL[ERRCNT]\n");
73                         if (spx_int_reg.s.diperr)
74                                 pr_err("SPI1: SRX Spi4 DIP4 error\n");
75                         if (spx_int_reg.s.tpaovr)
76                                 pr_err("SPI1: SRX Selected port has hit "
77                                        "TPA overflow\n");
78                         if (spx_int_reg.s.rsverr)
79                                 pr_err("SPI1: SRX Spi4 reserved control "
80                                        "word detected\n");
81                         if (spx_int_reg.s.drwnng)
82                                 pr_err("SPI1: SRX Spi4 receive FIFO "
83                                        "drowning/overflow\n");
84                         if (spx_int_reg.s.clserr)
85                                 pr_err("SPI1: SRX Spi4 packet closed on "
86                                        "non-16B alignment without EOP\n");
87                         if (spx_int_reg.s.spiovr)
88                                 pr_err("SPI1: SRX Spi4 async FIFO overflow\n");
89                         if (spx_int_reg.s.abnorm)
90                                 pr_err("SPI1: SRX Abnormal packet "
91                                        "termination (ERR bit)\n");
92                         if (spx_int_reg.s.prtnxa)
93                                 pr_err("SPI1: SRX Port out of range\n");
94                 }
95
96                 stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1));
97                 cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64);
98                 if (!need_retrain[1]) {
99
100                         stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1));
101                         if (stx_int_reg.s.syncerr)
102                                 pr_err("SPI1: STX Interface encountered a "
103                                        "fatal error\n");
104                         if (stx_int_reg.s.frmerr)
105                                 pr_err("SPI1: STX FRMCNT has exceeded "
106                                        "STX_DIP_CNT[MAXFRM]\n");
107                         if (stx_int_reg.s.unxfrm)
108                                 pr_err("SPI1: STX Unexpected framing "
109                                        "sequence\n");
110                         if (stx_int_reg.s.nosync)
111                                 pr_err("SPI1: STX ERRCNT has exceeded "
112                                        "STX_DIP_CNT[MAXDIP]\n");
113                         if (stx_int_reg.s.diperr)
114                                 pr_err("SPI1: STX DIP2 error on the Spi4 "
115                                        "Status channel\n");
116                         if (stx_int_reg.s.datovr)
117                                 pr_err("SPI1: STX Spi4 FIFO overflow error\n");
118                         if (stx_int_reg.s.ovrbst)
119                                 pr_err("SPI1: STX Transmit packet burst "
120                                        "too big\n");
121                         if (stx_int_reg.s.calpar1)
122                                 pr_err("SPI1: STX Calendar Table Parity "
123                                        "Error Bank1\n");
124                         if (stx_int_reg.s.calpar0)
125                                 pr_err("SPI1: STX Calendar Table Parity "
126                                        "Error Bank0\n");
127                 }
128
129                 cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0);
130                 cvmx_write_csr(CVMX_STXX_INT_MSK(1), 0);
131                 need_retrain[1] = 1;
132                 return_status = IRQ_HANDLED;
133         }
134
135         if (rsl_int_blocks.s.spx0) {    /* 18 - SPX0_INT_REG & STX0_INT_REG */
136                 union cvmx_spxx_int_reg spx_int_reg;
137                 union cvmx_stxx_int_reg stx_int_reg;
138
139                 spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0));
140                 cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64);
141                 if (!need_retrain[0]) {
142
143                         spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0));
144                         if (spx_int_reg.s.spf)
145                                 pr_err("SPI0: SRX Spi4 interface down\n");
146                         if (spx_int_reg.s.calerr)
147                                 pr_err("SPI0: SRX Spi4 Calendar table "
148                                        "parity error\n");
149                         if (spx_int_reg.s.syncerr)
150                                 pr_err("SPI0: SRX Consecutive Spi4 DIP4 "
151                                        "errors have exceeded "
152                                        "SPX_ERR_CTL[ERRCNT]\n");
153                         if (spx_int_reg.s.diperr)
154                                 pr_err("SPI0: SRX Spi4 DIP4 error\n");
155                         if (spx_int_reg.s.tpaovr)
156                                 pr_err("SPI0: SRX Selected port has hit "
157                                        "TPA overflow\n");
158                         if (spx_int_reg.s.rsverr)
159                                 pr_err("SPI0: SRX Spi4 reserved control "
160                                        "word detected\n");
161                         if (spx_int_reg.s.drwnng)
162                                 pr_err("SPI0: SRX Spi4 receive FIFO "
163                                        "drowning/overflow\n");
164                         if (spx_int_reg.s.clserr)
165                                 pr_err("SPI0: SRX Spi4 packet closed on "
166                                        "non-16B alignment without EOP\n");
167                         if (spx_int_reg.s.spiovr)
168                                 pr_err("SPI0: SRX Spi4 async FIFO overflow\n");
169                         if (spx_int_reg.s.abnorm)
170                                 pr_err("SPI0: SRX Abnormal packet "
171                                        "termination (ERR bit)\n");
172                         if (spx_int_reg.s.prtnxa)
173                                 pr_err("SPI0: SRX Port out of range\n");
174                 }
175
176                 stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0));
177                 cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64);
178                 if (!need_retrain[0]) {
179
180                         stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0));
181                         if (stx_int_reg.s.syncerr)
182                                 pr_err("SPI0: STX Interface encountered a "
183                                        "fatal error\n");
184                         if (stx_int_reg.s.frmerr)
185                                 pr_err("SPI0: STX FRMCNT has exceeded "
186                                        "STX_DIP_CNT[MAXFRM]\n");
187                         if (stx_int_reg.s.unxfrm)
188                                 pr_err("SPI0: STX Unexpected framing "
189                                        "sequence\n");
190                         if (stx_int_reg.s.nosync)
191                                 pr_err("SPI0: STX ERRCNT has exceeded "
192                                        "STX_DIP_CNT[MAXDIP]\n");
193                         if (stx_int_reg.s.diperr)
194                                 pr_err("SPI0: STX DIP2 error on the Spi4 "
195                                        "Status channel\n");
196                         if (stx_int_reg.s.datovr)
197                                 pr_err("SPI0: STX Spi4 FIFO overflow error\n");
198                         if (stx_int_reg.s.ovrbst)
199                                 pr_err("SPI0: STX Transmit packet burst "
200                                        "too big\n");
201                         if (stx_int_reg.s.calpar1)
202                                 pr_err("SPI0: STX Calendar Table Parity "
203                                        "Error Bank1\n");
204                         if (stx_int_reg.s.calpar0)
205                                 pr_err("SPI0: STX Calendar Table Parity "
206                                        "Error Bank0\n");
207                 }
208
209                 cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0);
210                 cvmx_write_csr(CVMX_STXX_INT_MSK(0), 0);
211                 need_retrain[0] = 1;
212                 return_status = IRQ_HANDLED;
213         }
214
215         return return_status;
216 }
217
218 static void cvm_oct_spi_enable_error_reporting(int interface)
219 {
220         union cvmx_spxx_int_msk spxx_int_msk;
221         union cvmx_stxx_int_msk stxx_int_msk;
222
223         spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface));
224         spxx_int_msk.s.calerr = 1;
225         spxx_int_msk.s.syncerr = 1;
226         spxx_int_msk.s.diperr = 1;
227         spxx_int_msk.s.tpaovr = 1;
228         spxx_int_msk.s.rsverr = 1;
229         spxx_int_msk.s.drwnng = 1;
230         spxx_int_msk.s.clserr = 1;
231         spxx_int_msk.s.spiovr = 1;
232         spxx_int_msk.s.abnorm = 1;
233         spxx_int_msk.s.prtnxa = 1;
234         cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64);
235
236         stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface));
237         stxx_int_msk.s.frmerr = 1;
238         stxx_int_msk.s.unxfrm = 1;
239         stxx_int_msk.s.nosync = 1;
240         stxx_int_msk.s.diperr = 1;
241         stxx_int_msk.s.datovr = 1;
242         stxx_int_msk.s.ovrbst = 1;
243         stxx_int_msk.s.calpar1 = 1;
244         stxx_int_msk.s.calpar0 = 1;
245         cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64);
246 }
247
248 static void cvm_oct_spi_poll(struct net_device *dev)
249 {
250         static int spi4000_port;
251         struct octeon_ethernet *priv = netdev_priv(dev);
252         int interface;
253
254         for (interface = 0; interface < 2; interface++) {
255
256                 if ((priv->port == interface * 16) && need_retrain[interface]) {
257
258                         if (cvmx_spi_restart_interface
259                             (interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) {
260                                 need_retrain[interface] = 0;
261                                 cvm_oct_spi_enable_error_reporting(interface);
262                         }
263                 }
264
265                 /*
266                  * The SPI4000 TWSI interface is very slow. In order
267                  * not to bring the system to a crawl, we only poll a
268                  * single port every second. This means negotiation
269                  * speed changes take up to 10 seconds, but at least
270                  * we don't waste absurd amounts of time waiting for
271                  * TWSI.
272                  */
273                 if (priv->port == spi4000_port) {
274                         /*
275                          * This function does nothing if it is called on an
276                          * interface without a SPI4000.
277                          */
278                         cvmx_spi4000_check_speed(interface, priv->port);
279                         /*
280                          * Normal ordering increments. By decrementing
281                          * we only match once per iteration.
282                          */
283                         spi4000_port--;
284                         if (spi4000_port < 0)
285                                 spi4000_port = 10;
286                 }
287         }
288 }
289
290 int cvm_oct_spi_init(struct net_device *dev)
291 {
292         int r;
293         struct octeon_ethernet *priv = netdev_priv(dev);
294
295         if (number_spi_ports == 0) {
296                 r = request_irq(OCTEON_IRQ_RML, cvm_oct_spi_rml_interrupt,
297                                 IRQF_SHARED, "SPI", &number_spi_ports);
298                 if (r)
299                         return r;
300         }
301         number_spi_ports++;
302
303         if ((priv->port == 0) || (priv->port == 16)) {
304                 cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port));
305                 priv->poll = cvm_oct_spi_poll;
306         }
307         cvm_oct_common_init(dev);
308         return 0;
309 }
310
311 void cvm_oct_spi_uninit(struct net_device *dev)
312 {
313         int interface;
314
315         cvm_oct_common_uninit(dev);
316         number_spi_ports--;
317         if (number_spi_ports == 0) {
318                 for (interface = 0; interface < 2; interface++) {
319                         cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0);
320                         cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0);
321                 }
322                 free_irq(OCTEON_IRQ_RML, &number_spi_ports);
323         }
324 }