xref: /freebsd/sys/dev/cxgb/common/cxgb_mc5.c (revision 39beb93c)
1 /**************************************************************************
2 
3 Copyright (c) 2007, Chelsio Inc.
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 
9  1. Redistributions of source code must retain the above copyright notice,
10     this list of conditions and the following disclaimer.
11 
12  2. Neither the name of the Chelsio Corporation nor the names of its
13     contributors may be used to endorse or promote products derived from
14     this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
27 
28 ***************************************************************************/
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <common/cxgb_common.h>
34 #include <common/cxgb_regs.h>
35 
36 enum {
37 	IDT75P52100 = 4,
38 	IDT75N43102 = 5
39 };
40 
41 /* DBGI command mode */
42 enum {
43 	DBGI_MODE_MBUS = 0,
44 	DBGI_MODE_IDT52100 = 5
45 };
46 
47 /* IDT 75P52100 commands */
48 #define IDT_CMD_READ   0
49 #define IDT_CMD_WRITE  1
50 #define IDT_CMD_SEARCH 2
51 #define IDT_CMD_LEARN  3
52 
53 /* IDT LAR register address and value for 144-bit mode (low 32 bits) */
54 #define IDT_LAR_ADR0   	0x180006
55 #define IDT_LAR_MODE144	0xffff0000
56 
57 /* IDT SCR and SSR addresses (low 32 bits) */
58 #define IDT_SCR_ADR0  0x180000
59 #define IDT_SSR0_ADR0 0x180002
60 #define IDT_SSR1_ADR0 0x180004
61 
62 /* IDT GMR base address (low 32 bits) */
63 #define IDT_GMR_BASE_ADR0 0x180020
64 
65 /* IDT data and mask array base addresses (low 32 bits) */
66 #define IDT_DATARY_BASE_ADR0 0
67 #define IDT_MSKARY_BASE_ADR0 0x80000
68 
69 /* IDT 75N43102 commands */
70 #define IDT4_CMD_SEARCH144 3
71 #define IDT4_CMD_WRITE     4
72 #define IDT4_CMD_READ      5
73 
74 /* IDT 75N43102 SCR address (low 32 bits) */
75 #define IDT4_SCR_ADR0  0x3
76 
77 /* IDT 75N43102 GMR base addresses (low 32 bits) */
78 #define IDT4_GMR_BASE0 0x10
79 #define IDT4_GMR_BASE1 0x20
80 #define IDT4_GMR_BASE2 0x30
81 
82 /* IDT 75N43102 data and mask array base addresses (low 32 bits) */
83 #define IDT4_DATARY_BASE_ADR0 0x1000000
84 #define IDT4_MSKARY_BASE_ADR0 0x2000000
85 
86 #define MAX_WRITE_ATTEMPTS 5
87 
88 #define MAX_ROUTES 2048
89 
90 /*
91  * Issue a command to the TCAM and wait for its completion.  The address and
92  * any data required by the command must have been setup by the caller.
93  */
94 static int mc5_cmd_write(adapter_t *adapter, u32 cmd)
95 {
96 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
97 	return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
98 			       F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
99 }
100 
101 static inline void dbgi_wr_addr3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
102 {
103 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, v1);
104 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR1, v2);
105 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR2, v3);
106 }
107 
108 static inline void dbgi_wr_data3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
109 {
110 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
111 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
112 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
113 }
114 
115 static inline void dbgi_rd_rsp3(adapter_t *adapter, u32 *v1, u32 *v2, u32 *v3)
116 {
117 	*v1 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA0);
118 	*v2 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA1);
119 	*v3 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA2);
120 }
121 
122 /*
123  * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
124  * command cmd.  The data to be written must have been set up by the caller.
125  * Returns -1 on failure, 0 on success.
126  */
127 static int mc5_write(adapter_t *adapter, u32 addr_lo, u32 cmd)
128 {
129 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
130 	if (mc5_cmd_write(adapter, cmd) == 0)
131 		return 0;
132 	CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n", addr_lo);
133 	return -1;
134 }
135 
136 static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
137 				u32 data_array_base, u32 write_cmd,
138 			        int addr_shift)
139 {
140 	unsigned int i;
141 	adapter_t *adap = mc5->adapter;
142 
143 	/*
144 	 * We need the size of the TCAM data and mask arrays in terms of
145 	 * 72-bit entries.
146 	 */
147 	unsigned int size72 = mc5->tcam_size;
148 	unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
149 
150 	if (mc5->mode == MC5_MODE_144_BIT) {
151 		size72 *= 2;      /* 1 144-bit entry is 2 72-bit entries */
152 		server_base *= 2;
153 	}
154 
155 	/* Clear the data array */
156 	dbgi_wr_data3(adap, 0, 0, 0);
157 	for (i = 0; i < size72; i++)
158 		if (mc5_write(adap, data_array_base + (i << addr_shift),
159 			      write_cmd))
160 			return -1;
161 
162 	/* Initialize the mask array. */
163 	for (i = 0; i < server_base; i++) {
164 		dbgi_wr_data3(adap, 0x3fffffff, 0xfff80000, 0xff);
165 		if (mc5_write(adap, mask_array_base + (i << addr_shift),
166 			      write_cmd))
167 			return -1;
168 		i++;
169 		dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
170 		if (mc5_write(adap, mask_array_base + (i << addr_shift),
171 			      write_cmd))
172 			return -1;
173 	}
174 
175 	dbgi_wr_data3(adap,
176 		      mc5->mode == MC5_MODE_144_BIT ? 0xfffffff9 : 0xfffffffd,
177 		      0xffffffff, 0xff);
178 	for (; i < size72; i++)
179 		if (mc5_write(adap, mask_array_base + (i << addr_shift),
180 			      write_cmd))
181 			return -1;
182 
183 	return 0;
184 }
185 
186 static int init_idt52100(struct mc5 *mc5)
187 {
188 	int i;
189 	adapter_t *adap = mc5->adapter;
190 
191 	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
192 		     V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
193 	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
194 
195 	/*
196 	 * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
197 	 * GMRs 8-9 for ACK- and AOPEN searches.
198 	 */
199 	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
200 	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
201 	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
202 	t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
203 	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
204 	t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
205 	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
206 	t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
207 	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
208 	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
209 	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
210 	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
211 
212 	/* Set DBGI command mode for IDT TCAM. */
213 	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
214 
215 	/* Set up LAR */
216 	dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
217 	if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
218 		goto err;
219 
220 	/* Set up SSRs */
221 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
222 	if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
223 	    mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
224 		goto err;
225 
226 	/* Set up GMRs */
227 	for (i = 0; i < 32; ++i) {
228 		if (i >= 12 && i < 15)
229 			dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
230 		else if (i == 15)
231 			dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
232 		else
233 			dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
234 
235 		if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
236 			goto err;
237 	}
238 
239 	/* Set up SCR */
240 	dbgi_wr_data3(adap, 1, 0, 0);
241 	if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
242 		goto err;
243 
244 	return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
245 				    IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
246  err:
247 	return -EIO;
248 }
249 
250 static int init_idt43102(struct mc5 *mc5)
251 {
252 	int i;
253 	adapter_t *adap = mc5->adapter;
254 
255 	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
256 		     adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
257 					     V_RDLAT(0xd) | V_SRCHLAT(0x12));
258 
259 	/*
260 	 * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
261 	 * for ACK- and AOPEN searches.
262 	 */
263 	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
264 	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
265 	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
266 		     IDT4_CMD_SEARCH144 | 0x3800);
267 	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
268 	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
269 	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
270 	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
271 	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
272 	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
273 
274 	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
275 
276 	/* Set DBGI command mode for IDT TCAM. */
277 	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
278 
279 	/* Set up GMRs */
280 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
281 	for (i = 0; i < 7; ++i)
282 		if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
283 			goto err;
284 
285 	for (i = 0; i < 4; ++i)
286 		if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
287 			goto err;
288 
289 	dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
290 	if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
291 	    mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
292 	    mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
293 		goto err;
294 
295 	dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
296 	if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
297 		goto err;
298 
299 	/* Set up SCR */
300 	dbgi_wr_data3(adap, 0xf0000000, 0, 0);
301 	if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
302 		goto err;
303 
304 	return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
305 				    IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
306  err:
307 	return -EIO;
308 }
309 
310 /* Put MC5 in DBGI mode. */
311 static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
312 {
313 	t3_set_reg_field(mc5->adapter, A_MC5_DB_CONFIG, F_PRTYEN | F_MBUSEN,
314 			 F_DBGIEN);
315 }
316 
317 /* Put MC5 in M-Bus mode. */
318 static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
319 {
320 	t3_set_reg_field(mc5->adapter, A_MC5_DB_CONFIG, F_DBGIEN,
321 			 V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
322 }
323 
324 /**
325  *	t3_mc5_init - initialize MC5 and the TCAM
326  *	@mc5: the MC5 handle
327  *	@nservers: desired number the TCP servers (listening ports)
328  *	@nfilters: desired number of HW filters (classifiers)
329  *	@nroutes: desired number of routes
330  *
331  *	Initialize MC5 and the TCAM and partition the TCAM for the requested
332  *	number of servers, filters, and routes.  The number of routes is
333  *	typically 0 except for specialized uses of the T3 adapters.
334  */
335 int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
336 		unsigned int nroutes)
337 {
338 	int err;
339 	unsigned int tcam_size = mc5->tcam_size;
340 	unsigned int mode72 = mc5->mode == MC5_MODE_72_BIT;
341 	adapter_t *adap = mc5->adapter;
342 
343 	if (!tcam_size)
344 		return 0;
345 
346 	if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
347 		return -EINVAL;
348 
349 	if (nfilters)
350 		mc5->parity_enabled = 0;
351 
352 	/* Reset the TCAM */
353 	t3_set_reg_field(adap, A_MC5_DB_CONFIG, F_TMMODE | F_COMPEN,
354 			 V_COMPEN(mode72) | V_TMMODE(mode72) | F_TMRST);
355 	if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
356 		CH_ERR(adap, "TCAM reset timed out\n");
357 		return -1;
358 	}
359 
360 	t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
361 	t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
362 		     tcam_size - nroutes - nfilters);
363 	t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
364 		     tcam_size - nroutes - nfilters - nservers);
365 
366 	/* All the TCAM addresses we access have only the low 32 bits non 0 */
367 	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
368 	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
369 
370 	mc5_dbgi_mode_enable(mc5);
371 
372 	switch (mc5->part_type) {
373 	case IDT75P52100:
374 		err = init_idt52100(mc5);
375 		break;
376 	case IDT75N43102:
377 		err = init_idt43102(mc5);
378 		break;
379 	default:
380 		CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
381 		err = -EINVAL;
382 		break;
383 	}
384 
385 	mc5_dbgi_mode_disable(mc5);
386 	return err;
387 }
388 
389 /**
390  *	read_mc5_range - dump a part of the memory managed by MC5
391  *	@mc5: the MC5 handle
392  *	@start: the start address for the dump
393  *	@n: number of 72-bit words to read
394  *	@buf: result buffer
395  *
396  *	Read n 72-bit words from MC5 memory from the given start location.
397  */
398 int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start,
399 		      unsigned int n, u32 *buf)
400 {
401 	u32 read_cmd;
402 	int err = 0;
403 	adapter_t *adap = mc5->adapter;
404 
405 	if (mc5->part_type == IDT75P52100)
406 		read_cmd = IDT_CMD_READ;
407 	else if (mc5->part_type == IDT75N43102)
408 		read_cmd = IDT4_CMD_READ;
409 	else
410 		return -EINVAL;
411 
412 	mc5_dbgi_mode_enable(mc5);
413 
414 	while (n--) {
415 		t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++);
416 		if (mc5_cmd_write(adap, read_cmd)) {
417 			err = -EIO;
418 			break;
419 		}
420 		dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
421 		buf += 3;
422 	}
423 
424 	mc5_dbgi_mode_disable(mc5);
425 	return err;
426 }
427 
428 #define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
429 
430 /**
431  *	t3_mc5_intr_handler - MC5 interrupt handler
432  *	@mc5: the MC5 handle
433  *
434  *	The MC5 interrupt handler.
435  */
436 void t3_mc5_intr_handler(struct mc5 *mc5)
437 {
438 	adapter_t *adap = mc5->adapter;
439 	u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
440 
441 	if ((cause & F_PARITYERR) && mc5->parity_enabled) {
442 		CH_ALERT(adap, "MC5 parity error\n");
443 		mc5->stats.parity_err++;
444 	}
445 
446 	if (cause & F_REQQPARERR) {
447 		CH_ALERT(adap, "MC5 request queue parity error\n");
448 		mc5->stats.reqq_parity_err++;
449 	}
450 
451 	if (cause & F_DISPQPARERR) {
452 		CH_ALERT(adap, "MC5 dispatch queue parity error\n");
453 		mc5->stats.dispq_parity_err++;
454 	}
455 
456 	if (cause & F_ACTRGNFULL)
457 		mc5->stats.active_rgn_full++;
458 	if (cause & F_NFASRCHFAIL)
459 		mc5->stats.nfa_srch_err++;
460 	if (cause & F_UNKNOWNCMD)
461 		mc5->stats.unknown_cmd++;
462 	if (cause & F_DELACTEMPTY)
463 		mc5->stats.del_act_empty++;
464 	if (cause & MC5_INT_FATAL)
465 		t3_fatal_err(adap);
466 
467 	t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
468 }
469 
470 /**
471  *	t3_mc5_prep - initialize the SW state for MC5
472  *	@adapter: the adapter
473  *	@mc5: the MC5 handle
474  *	@mode: whether the TCAM will be in 72- or 144-bit mode
475  *
476  *	Initialize the SW state associated with MC5.  Among other things
477  *	this determines the size of the attached TCAM.
478  */
479 void __devinit t3_mc5_prep(adapter_t *adapter, struct mc5 *mc5, int mode)
480 {
481 #define K * 1024
482 
483 	static unsigned int tcam_part_size[] = {  /* in K 72-bit entries */
484 		64 K, 128 K, 256 K, 32 K
485 	};
486 
487 #undef K
488 
489 	u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
490 
491 	mc5->adapter = adapter;
492 	mc5->parity_enabled = 1;
493 	mc5->mode = (unsigned char) mode;
494 	mc5->part_type = (unsigned char) G_TMTYPE(cfg);
495 	if (cfg & F_TMTYPEHI)
496 		mc5->part_type |= 4;
497 
498 	mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
499 	if (mode == MC5_MODE_144_BIT)
500 		mc5->tcam_size /= 2;
501 }
502