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 
cvm_oct_spi_rml_interrupt(int cpl,void * dev_id)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 
cvm_oct_spi_enable_error_reporting(int interface)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 
cvm_oct_spi_poll(struct net_device * dev)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 
cvm_oct_spi_init(struct net_device * dev)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 
cvm_oct_spi_uninit(struct net_device * dev)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 }
293