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