xref: /freebsd/sys/dev/cxgb/common/cxgb_mc5.c (revision 71e8eac4fd89dedbcb4130379add151d3ed942fa)
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_data3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
102 {
103 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
104 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
105 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
106 }
107 
108 static inline void dbgi_rd_rsp3(adapter_t *adapter, u32 *v1, u32 *v2, u32 *v3)
109 {
110 	*v1 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA0);
111 	*v2 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA1);
112 	*v3 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA2);
113 }
114 
115 /*
116  * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
117  * command cmd.  The data to be written must have been set up by the caller.
118  * Returns -1 on failure, 0 on success.
119  */
120 static int mc5_write(adapter_t *adapter, u32 addr_lo, u32 cmd)
121 {
122 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
123 	if (mc5_cmd_write(adapter, cmd) == 0)
124 		return 0;
125 	CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n", addr_lo);
126 	return -1;
127 }
128 
129 static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
130 				u32 data_array_base, u32 write_cmd,
131 			        int addr_shift)
132 {
133 	unsigned int i;
134 	adapter_t *adap = mc5->adapter;
135 
136 	/*
137 	 * We need the size of the TCAM data and mask arrays in terms of
138 	 * 72-bit entries.
139 	 */
140 	unsigned int size72 = mc5->tcam_size;
141 	unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
142 
143 	if (mc5->mode == MC5_MODE_144_BIT) {
144 		size72 *= 2;      /* 1 144-bit entry is 2 72-bit entries */
145 		server_base *= 2;
146 	}
147 
148 	/* Clear the data array */
149 	dbgi_wr_data3(adap, 0, 0, 0);
150 	for (i = 0; i < size72; i++)
151 		if (mc5_write(adap, data_array_base + (i << addr_shift),
152 			      write_cmd))
153 			return -1;
154 
155 	/* Initialize the mask array. */
156 	for (i = 0; i < server_base; i++) {
157 		dbgi_wr_data3(adap, 0x3fffffff, 0xfff80000, 0xff);
158 		if (mc5_write(adap, mask_array_base + (i << addr_shift),
159 			      write_cmd))
160 			return -1;
161 		i++;
162 		dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
163 		if (mc5_write(adap, mask_array_base + (i << addr_shift),
164 			      write_cmd))
165 			return -1;
166 	}
167 
168 	dbgi_wr_data3(adap,
169 		      mc5->mode == MC5_MODE_144_BIT ? 0xfffffff9 : 0xfffffffd,
170 		      0xffffffff, 0xff);
171 	for (; i < size72; i++)
172 		if (mc5_write(adap, mask_array_base + (i << addr_shift),
173 			      write_cmd))
174 			return -1;
175 
176 	return 0;
177 }
178 
179 static int init_idt52100(struct mc5 *mc5)
180 {
181 	int i;
182 	adapter_t *adap = mc5->adapter;
183 
184 	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
185 		     V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
186 	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
187 
188 	/*
189 	 * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
190 	 * GMRs 8-9 for ACK- and AOPEN searches.
191 	 */
192 	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
193 	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
194 	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
195 	t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
196 	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
197 	t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
198 	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
199 	t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
200 	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
201 	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
202 	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
203 	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
204 
205 	/* Set DBGI command mode for IDT TCAM. */
206 	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
207 
208 	/* Set up LAR */
209 	dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
210 	if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
211 		goto err;
212 
213 	/* Set up SSRs */
214 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
215 	if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
216 	    mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
217 		goto err;
218 
219 	/* Set up GMRs */
220 	for (i = 0; i < 32; ++i) {
221 		if (i >= 12 && i < 15)
222 			dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
223 		else if (i == 15)
224 			dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
225 		else
226 			dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
227 
228 		if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
229 			goto err;
230 	}
231 
232 	/* Set up SCR */
233 	dbgi_wr_data3(adap, 1, 0, 0);
234 	if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
235 		goto err;
236 
237 	return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
238 				    IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
239  err:
240 	return -EIO;
241 }
242 
243 static int init_idt43102(struct mc5 *mc5)
244 {
245 	int i;
246 	adapter_t *adap = mc5->adapter;
247 
248 	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
249 		     adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
250 					     V_RDLAT(0xd) | V_SRCHLAT(0x12));
251 
252 	/*
253 	 * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
254 	 * for ACK- and AOPEN searches.
255 	 */
256 	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
257 	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
258 	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
259 		     IDT4_CMD_SEARCH144 | 0x3800);
260 	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
261 	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
262 	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
263 	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
264 	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
265 	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
266 
267 	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
268 
269 	/* Set DBGI command mode for IDT TCAM. */
270 	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
271 
272 	/* Set up GMRs */
273 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
274 	for (i = 0; i < 7; ++i)
275 		if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
276 			goto err;
277 
278 	for (i = 0; i < 4; ++i)
279 		if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
280 			goto err;
281 
282 	dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
283 	if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
284 	    mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
285 	    mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
286 		goto err;
287 
288 	dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
289 	if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
290 		goto err;
291 
292 	/* Set up SCR */
293 	dbgi_wr_data3(adap, 0xf0000000, 0, 0);
294 	if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
295 		goto err;
296 
297 	return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
298 				    IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
299  err:
300 	return -EIO;
301 }
302 
303 /* Put MC5 in DBGI mode. */
304 static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
305 {
306 	t3_set_reg_field(mc5->adapter, A_MC5_DB_CONFIG, F_PRTYEN | F_MBUSEN,
307 			 F_DBGIEN);
308 }
309 
310 /* Put MC5 in M-Bus mode. */
311 static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
312 {
313 	t3_set_reg_field(mc5->adapter, A_MC5_DB_CONFIG, F_DBGIEN,
314 			 V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
315 }
316 
317 /**
318  *	t3_mc5_init - initialize MC5 and the TCAM
319  *	@mc5: the MC5 handle
320  *	@nservers: desired number the TCP servers (listening ports)
321  *	@nfilters: desired number of HW filters (classifiers)
322  *	@nroutes: desired number of routes
323  *
324  *	Initialize MC5 and the TCAM and partition the TCAM for the requested
325  *	number of servers, filters, and routes.  The number of routes is
326  *	typically 0 except for specialized uses of the T3 adapters.
327  */
328 int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
329 		unsigned int nroutes)
330 {
331 	int err;
332 	unsigned int tcam_size = mc5->tcam_size;
333 	unsigned int mode72 = mc5->mode == MC5_MODE_72_BIT;
334 	adapter_t *adap = mc5->adapter;
335 
336 	if (!tcam_size)
337 		return 0;
338 
339 	if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
340 		return -EINVAL;
341 
342 	if (nfilters)
343 		mc5->parity_enabled = 0;
344 
345 	/* Reset the TCAM */
346 	t3_set_reg_field(adap, A_MC5_DB_CONFIG, F_TMMODE | F_COMPEN,
347 			 V_COMPEN(mode72) | V_TMMODE(mode72) | F_TMRST);
348 	if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
349 		CH_ERR(adap, "TCAM reset timed out\n");
350 		return -1;
351 	}
352 
353 	t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
354 	t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
355 		     tcam_size - nroutes - nfilters);
356 	t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
357 		     tcam_size - nroutes - nfilters - nservers);
358 
359 	/* All the TCAM addresses we access have only the low 32 bits non 0 */
360 	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
361 	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
362 
363 	mc5_dbgi_mode_enable(mc5);
364 
365 	switch (mc5->part_type) {
366 	case IDT75P52100:
367 		err = init_idt52100(mc5);
368 		break;
369 	case IDT75N43102:
370 		err = init_idt43102(mc5);
371 		break;
372 	default:
373 		CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
374 		err = -EINVAL;
375 		break;
376 	}
377 
378 	mc5_dbgi_mode_disable(mc5);
379 	return err;
380 }
381 
382 /**
383  *	read_mc5_range - dump a part of the memory managed by MC5
384  *	@mc5: the MC5 handle
385  *	@start: the start address for the dump
386  *	@n: number of 72-bit words to read
387  *	@buf: result buffer
388  *
389  *	Read n 72-bit words from MC5 memory from the given start location.
390  */
391 int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start,
392 		      unsigned int n, u32 *buf)
393 {
394 	u32 read_cmd;
395 	int err = 0;
396 	adapter_t *adap = mc5->adapter;
397 
398 	if (mc5->part_type == IDT75P52100)
399 		read_cmd = IDT_CMD_READ;
400 	else if (mc5->part_type == IDT75N43102)
401 		read_cmd = IDT4_CMD_READ;
402 	else
403 		return -EINVAL;
404 
405 	mc5_dbgi_mode_enable(mc5);
406 
407 	while (n--) {
408 		t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++);
409 		if (mc5_cmd_write(adap, read_cmd)) {
410 			err = -EIO;
411 			break;
412 		}
413 		dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
414 		buf += 3;
415 	}
416 
417 	mc5_dbgi_mode_disable(mc5);
418 	return err;
419 }
420 
421 #define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
422 
423 /**
424  *	t3_mc5_intr_handler - MC5 interrupt handler
425  *	@mc5: the MC5 handle
426  *
427  *	The MC5 interrupt handler.
428  */
429 void t3_mc5_intr_handler(struct mc5 *mc5)
430 {
431 	adapter_t *adap = mc5->adapter;
432 	u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
433 
434 	if ((cause & F_PARITYERR) && mc5->parity_enabled) {
435 		CH_ALERT(adap, "MC5 parity error\n");
436 		mc5->stats.parity_err++;
437 	}
438 
439 	if (cause & F_REQQPARERR) {
440 		CH_ALERT(adap, "MC5 request queue parity error\n");
441 		mc5->stats.reqq_parity_err++;
442 	}
443 
444 	if (cause & F_DISPQPARERR) {
445 		CH_ALERT(adap, "MC5 dispatch queue parity error\n");
446 		mc5->stats.dispq_parity_err++;
447 	}
448 
449 	if (cause & F_ACTRGNFULL)
450 		mc5->stats.active_rgn_full++;
451 	if (cause & F_NFASRCHFAIL)
452 		mc5->stats.nfa_srch_err++;
453 	if (cause & F_UNKNOWNCMD)
454 		mc5->stats.unknown_cmd++;
455 	if (cause & F_DELACTEMPTY)
456 		mc5->stats.del_act_empty++;
457 	if (cause & MC5_INT_FATAL)
458 		t3_fatal_err(adap);
459 
460 	t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
461 }
462 
463 /**
464  *	t3_mc5_prep - initialize the SW state for MC5
465  *	@adapter: the adapter
466  *	@mc5: the MC5 handle
467  *	@mode: whether the TCAM will be in 72- or 144-bit mode
468  *
469  *	Initialize the SW state associated with MC5.  Among other things
470  *	this determines the size of the attached TCAM.
471  */
472 void __devinit t3_mc5_prep(adapter_t *adapter, struct mc5 *mc5, int mode)
473 {
474 #define K * 1024
475 
476 	static unsigned int tcam_part_size[] = {  /* in K 72-bit entries */
477 		64 K, 128 K, 256 K, 32 K
478 	};
479 
480 #undef K
481 
482 	u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
483 
484 	mc5->adapter = adapter;
485 	mc5->parity_enabled = 1;
486 	mc5->mode = (unsigned char) mode;
487 	mc5->part_type = (unsigned char) G_TMTYPE(cfg);
488 	if (cfg & F_TMTYPEHI)
489 		mc5->part_type |= 4;
490 
491 	mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
492 	if (mode == MC5_MODE_144_BIT)
493 		mc5->tcam_size /= 2;
494 }
495