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 "
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 }
325