xref: /illumos-gate/usr/src/uts/common/io/chxge/com/mc5.c (revision dd72704bd9e794056c558153663c739e2012d721)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
24  */
25 
26 #include "common.h"
27 #include "regs.h"
28 #include "mc5.h"
29 
30 /* DBGI command mode */
31 enum {
32       	DBGI_MODE_MBUS,
33 	DBGI_MODE_LARA_7000,
34 	DBGI_MODE_LARA_8000,
35 	DBGI_MODE_NETL_4000,
36 	DBGI_MODE_NETL_5000,
37 	DBGI_MODE_IDT_52100
38 };
39 
40 /* Lara command register address and values (low 32 bits) */
41 #define MC5_LRA_CMDREG_ADR0		0x00180038
42 #define MC5_LRA_CMDREG_72KEY_DATA0	0x00000182
43 #define MC5_LRA_CMDREG_144KEY_DATA0	0x00AAAB82
44 
45 /* Lara config register address and values (low 32 bits) */
46 #define MC5_LRA_CFGREG_ADR0		0x0018003D
47 #define MC5_LRA_CFGREG_72KEY_DATA0	0x00000000
48 #define MC5_LRA_CFGREG_144KEY_DATA0	0x55555555
49 
50 /* Lara GMR base addresses (low 32 bits) */
51 #define MC5_LRA_GMRREG_BASE_ADR0_1	0x00180020
52 #define MC5_LRA_GMRREG_BASE_ADR0_2	0x00180060
53 
54 /* Lara 7000 data and mask array base addresses (low 32 bits) */
55 #define MC5_LRA_DATARY_BASE_ADR0	0x00000000
56 #define MC5_LRA_MSKARY_BASE_ADR0	0x00080000
57 
58 /* Lara commands */
59 #define MC5_LRA_CMD_READ		0x00000000
60 #define MC5_LRA_CMD_WRITE		0x00010001
61 #define MC5_LRA_CMD_SEARCH		0x00020002
62 #define MC5_LRA_CMD_LEARN		0x00030003
63 
64 /* IDT 75P52100 commands */
65 #define MC5_IDT_CMD_READ		0x0
66 #define MC5_IDT_CMD_WRITE		0x1
67 #define MC5_IDT_CMD_SEARCH		0x2
68 #define MC5_IDT_CMD_LEARN		0x3
69 #define MC5_IDT_CMD_NFA_SEARCH		0x4
70 
71 /* IDT LAR register address and value for 144-bit mode (low 32 bits) */
72 #define MC5_IDT_LAR_ADR0		0x180006
73 #define MC5_IDT_LAR_MODE144		0xffff0000
74 
75 /* IDT SCR and SSR addresses (low 32 bits) */
76 #define MC5_IDT_SCR_ADR0		0x180000
77 #define MC5_IDT_SSR0_ADR0		0x180002
78 #define MC5_IDT_SSR1_ADR0		0x180004
79 
80 /* IDT GMR base address (low 32 bits) */
81 #define MC5_IDT_GMR_BASE_ADR0		0x180020
82 
83 /* IDT data and mask array base addresses (low 32 bits) */
84 #define MC5_IDT_DATARY_BASE_ADR0	0x00000000
85 #define MC5_IDT_MSKARY_BASE_ADR0	0x00080000
86 
87 #define IDT_ELOOKUP_2Mb			0x7000
88 #define IDT_ELOOKUP_9Mb			0x16000
89 
90 enum {
91 	LARA_7000,
92 	LARA_8000,
93 	NETLOGIC_4000,
94 	NETLOGIC_5000,
95 	IDT75P52100
96 };
97 
98 static unsigned int tcam_part_size[] = {
99 	4718592, /* 4.5Mb */
100 	9437184, /* 9Mb */
101 	18874368 /* 18Mb */
102 };
103 
104 struct pemc5 {
105 	adapter_t *adapter;
106 	unsigned int tcam_size;
107 	unsigned int part_size;
108 	unsigned char part_type;
109 	unsigned char parity_enabled;
110 	unsigned char issue_syn;
111 	unsigned char mode;
112 	struct pemc5_intr_counts intr_counts;
113 #ifdef SUPPORT_MODE72
114 	u32 lip[MC5_LIP_NUM_OF_ENTRIES];
115 	unsigned int lip_index;
116 #endif
117 };
118 
119 #define MAX_WRITE_ATTEMPTS 5
120 
121 /*
122  * Issue a command to the TCAM and wait for its completion.  The address and
123  * any data required by the command must have been setup by the caller.
124  */
125 static int mc5_cmd_write(adapter_t *adapter, u32 cmd)
126 {
127 	t1_write_reg_4(adapter, A_MC5_DBGI_REQ_CMD, cmd);
128 	return t1_wait_op_done(adapter, A_MC5_DBGI_RSP_STATUS,
129 		F_DBGI_RSP_VALID, 1, MAX_WRITE_ATTEMPTS, 1);
130 }
131 
132 
133 unsigned int t1_mc5_get_tcam_size(struct pemc5 *mc5)
134 {
135 	return mc5->tcam_size;
136 }
137 
138 static int set_tcam_rtbl_base(struct pemc5 *mc5, unsigned int rtbl_base)
139 {
140 	if (rtbl_base >= t1_mc5_get_tcam_size(mc5)) return -1;
141 	t1_write_reg_4(mc5->adapter, A_MC5_ROUTING_TABLE_INDEX, rtbl_base);
142 	return 0;
143 }
144 
145 unsigned int t1_mc5_get_tcam_rtbl_base(struct pemc5 *mc5)
146 {
147 	return t1_read_reg_4(mc5->adapter, A_MC5_ROUTING_TABLE_INDEX);
148 }
149 
150 unsigned int t1_mc5_get_tcam_rtbl_size(struct pemc5 *mc5)
151 {
152 	unsigned int tcam_size = t1_mc5_get_tcam_size(mc5);
153 	unsigned int tcam_rtable_base = t1_mc5_get_tcam_rtbl_base(mc5);
154 
155 	return tcam_size - tcam_rtable_base;
156 }
157 
158 static int set_tcam_server_base(struct pemc5 *mc5, unsigned int server_base)
159 {
160 	if (server_base >= t1_mc5_get_tcam_size(mc5)) return -1;
161 	t1_write_reg_4(mc5->adapter, A_MC5_SERVER_INDEX, server_base);
162 	return 0;
163 }
164 
165 unsigned int t1_mc5_get_tcam_server_base(struct pemc5 *mc5)
166 {
167 	return t1_read_reg_4(mc5->adapter, A_MC5_SERVER_INDEX);
168 }
169 
170 unsigned int t1_mc5_get_tcam_server_size(struct pemc5 *mc5)
171 {
172 	unsigned int tcam_rtable_base = t1_mc5_get_tcam_rtbl_base(mc5);
173 	unsigned int tcam_server_base = t1_mc5_get_tcam_server_base(mc5);
174 
175 	return tcam_rtable_base - tcam_server_base;
176 }
177 
178 static inline void dbgi_wr_addr3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
179 {
180 	t1_write_reg_4(adapter, A_MC5_DBGI_REQ_ADDR0, v1);
181 	t1_write_reg_4(adapter, A_MC5_DBGI_REQ_ADDR1, v2);
182 	t1_write_reg_4(adapter, A_MC5_DBGI_REQ_ADDR2, v3);
183 }
184 
185 static inline void dbgi_wr_data3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
186 {
187 	t1_write_reg_4(adapter, A_MC5_DBGI_REQ_DATA0, v1);
188 	t1_write_reg_4(adapter, A_MC5_DBGI_REQ_DATA1, v2);
189 	t1_write_reg_4(adapter, A_MC5_DBGI_REQ_DATA2, v3);
190 }
191 
192 static inline void dbgi_rd_rsp3(adapter_t *adapter, u32 *v1, u32 *v2, u32 *v3)
193 {
194 	*v1 = t1_read_reg_4(adapter, A_MC5_DBGI_RSP_DATA0);
195 	*v2 = t1_read_reg_4(adapter, A_MC5_DBGI_RSP_DATA1);
196 	*v3 = t1_read_reg_4(adapter, A_MC5_DBGI_RSP_DATA2);
197 }
198 
199 /*
200  * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
201  * command cmd.  The data to be written must have been set up by the caller.
202  * Returns -1 on failure, 0 on success.
203  */
204 static int mc5_write(adapter_t *adapter, u32 addr_lo, u32 cmd)
205 {
206 	t1_write_reg_4(adapter, A_MC5_DBGI_REQ_ADDR0, addr_lo);
207 	if (mc5_cmd_write(adapter, cmd) == 0)
208 		return 0;
209 	CH_ERR("%s: MC5 timeout writing to TCAM address 0x%x\n",
210 	       adapter_name(adapter), addr_lo);
211 	return -1;
212 }
213 
214 static int init_mask_data_array(struct pemc5 *mc5, u32 mask_array_base,
215 				u32 data_array_base, u32 write_cmd)
216 {
217 	unsigned int i;
218 	adapter_t *adap = mc5->adapter;
219 
220 	/*
221 	 * We need the size of the TCAM data and mask arrays in terms of
222 	 * 72-bit entries.
223 	 */
224 	unsigned int size72 = tcam_part_size[mc5->part_size] / 72;
225 	unsigned int server_base = t1_mc5_get_tcam_server_base(mc5);
226 	if (mc5->mode == MC5_MODE_144_BIT)
227 		server_base *= 2;  /* 1 144-bit entry is 2 72-bit entries */
228 
229 	/* Clear the data array */
230 	dbgi_wr_data3(adap, 0, 0, 0);
231 	for (i = 0; i < size72; i++)
232 		if (mc5_write(adap, data_array_base + i, write_cmd))
233 			return -1;
234 
235 	/* Initialize the mask array. */
236 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
237 	for (i = 0; i < size72; i++) {
238 		if (i == server_base)   /* entering server or routing region */
239 			t1_write_reg_4(adap, A_MC5_DBGI_REQ_DATA0,
240 				       mc5->mode == MC5_MODE_144_BIT ?
241 				       0xfffffff9 : 0xfffffffd);
242 		if (mc5_write(adap, mask_array_base + i, write_cmd))
243 			return -1;
244 	}
245 	return 0;
246 }
247 
248 static int init_lara7000(struct pemc5 *mc5)
249 {
250 	int i;
251 	adapter_t *adap = mc5->adapter;
252 
253 	t1_write_reg_4(adap, A_MC5_RSP_LATENCY,
254 		       t1_is_asic(adap) ? 0x0a0a0a0a : 0x09090909);
255 
256 	if (mc5->parity_enabled) {
257 		t1_write_reg_4(adap, A_MC5_AOPEN_SRCH_CMD, 0x20022);
258 		t1_write_reg_4(adap, A_MC5_SYN_SRCH_CMD, 0x20022);
259 		t1_write_reg_4(adap, A_MC5_ACK_SRCH_CMD, 0x20022);
260 	}
261 
262 	/* Set DBGI command mode for Lara TCAM. */
263 	t1_write_reg_4(adap, A_MC5_DBGI_CONFIG, DBGI_MODE_LARA_7000);
264 
265 	dbgi_wr_data3(adap, mc5->mode == MC5_MODE_144_BIT ?
266 		      MC5_LRA_CMDREG_144KEY_DATA0 : MC5_LRA_CMDREG_72KEY_DATA0,
267 		      0, 0);
268 	if (mc5_write(adap, MC5_LRA_CMDREG_ADR0, MC5_LRA_CMD_WRITE))
269 		goto err;
270 
271 	dbgi_wr_data3(adap, mc5->mode == MC5_MODE_144_BIT ?
272 		      MC5_LRA_CFGREG_144KEY_DATA0 : MC5_LRA_CFGREG_72KEY_DATA0,
273 		      0, 0);
274 	if (mc5_write(adap, MC5_LRA_CFGREG_ADR0, MC5_LRA_CMD_WRITE))
275 		goto err;
276 
277 	/* Global Mask Registers (GMR) 0-15 */
278 	for (i = 0; i < 16; i++) {
279 		if (i == 8 || i == 9)
280 			dbgi_wr_data3(adap, mc5->mode == MC5_MODE_72_BIT ?
281 				      0xfffffffd : 0xfffffff9, 0xffffffff,
282 				      0xff);
283 		else
284 			dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
285 
286 		if (mc5_write(adap, MC5_LRA_GMRREG_BASE_ADR0_1 + i,
287 			      MC5_LRA_CMD_WRITE))
288 			goto err;
289 	}
290 
291 	/* Global Mask Registers (GMR) 16-31 */
292 	for (i = 0; i < 16; i++) {
293 		if (i <= 1 && mc5->mode == MC5_MODE_72_BIT)
294 			dbgi_wr_data3(adap, 0xfffffffd, 0xffffc003, 0xff);
295 		else if (i == 0)
296 			dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
297 		else if (i == 1)
298 			dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
299 		else
300 			dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
301 
302 		if (mc5_write(adap, MC5_LRA_GMRREG_BASE_ADR0_2 + i,
303 			      MC5_LRA_CMD_WRITE))
304 			goto err;
305 	}
306 	return init_mask_data_array(mc5, MC5_LRA_MSKARY_BASE_ADR0,
307 				    MC5_LRA_DATARY_BASE_ADR0,
308 				    MC5_LRA_CMD_WRITE);
309  err:
310 	return -EIO;
311 }
312 
313 static int init_idt52100(struct pemc5 *mc5)
314 {
315 	int i;
316 	adapter_t *adap = mc5->adapter;
317 
318 	t1_write_reg_4(adap, A_MC5_RSP_LATENCY, 0x151515);
319 	t1_write_reg_4(adap, A_MC5_PART_ID_INDEX, 2);
320 
321 	/*
322 	 * Use GMRs 8-9 for ACK and AOPEN searches, GMRs 12-13 for SYN search,
323 	 * and GMRs 14-15 for ELOOKUP.
324 	 */
325 	t1_write_reg_4(adap, A_MC5_POPEN_DATA_WR_CMD, MC5_IDT_CMD_WRITE);
326 	t1_write_reg_4(adap, A_MC5_POPEN_MASK_WR_CMD, MC5_IDT_CMD_WRITE);
327 	t1_write_reg_4(adap, A_MC5_AOPEN_SRCH_CMD, MC5_IDT_CMD_SEARCH);
328 	t1_write_reg_4(adap, A_MC5_AOPEN_LRN_CMD, MC5_IDT_CMD_LEARN);
329 	t1_write_reg_4(adap, A_MC5_SYN_SRCH_CMD, MC5_IDT_CMD_SEARCH | 0x6000);
330 	t1_write_reg_4(adap, A_MC5_SYN_LRN_CMD, MC5_IDT_CMD_LEARN);
331 	t1_write_reg_4(adap, A_MC5_ACK_SRCH_CMD, MC5_IDT_CMD_SEARCH);
332 	t1_write_reg_4(adap, A_MC5_ACK_LRN_CMD, MC5_IDT_CMD_LEARN);
333 	t1_write_reg_4(adap, A_MC5_ILOOKUP_CMD, MC5_IDT_CMD_SEARCH);
334 	t1_write_reg_4(adap, A_MC5_ELOOKUP_CMD, MC5_IDT_CMD_SEARCH | 0x7000);
335 	t1_write_reg_4(adap, A_MC5_DATA_WRITE_CMD, MC5_IDT_CMD_WRITE);
336 	t1_write_reg_4(adap, A_MC5_DATA_READ_CMD, MC5_IDT_CMD_READ);
337 
338 	/* Set DBGI command mode for IDT TCAM. */
339 	t1_write_reg_4(adap, A_MC5_DBGI_CONFIG, DBGI_MODE_IDT_52100);
340 
341 	/* Set up LAR */
342 	dbgi_wr_data3(adap, MC5_IDT_LAR_MODE144, 0, 0);
343 	if (mc5_write(adap, MC5_IDT_LAR_ADR0, MC5_IDT_CMD_WRITE))
344 		goto err;
345 
346 	/* Set up SSRs */
347 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
348 	if (mc5_write(adap, MC5_IDT_SSR0_ADR0, MC5_IDT_CMD_WRITE) ||
349 	    mc5_write(adap, MC5_IDT_SSR1_ADR0, MC5_IDT_CMD_WRITE))
350 		goto err;
351 
352 	/* Set up GMRs */
353 	for (i = 0; i < 32; ++i) {
354 		if (i >= 12 && i < 15)
355 			dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
356 		else if (i == 15)
357 			dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
358 		else
359 			dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
360 
361 		if (mc5_write(adap, MC5_IDT_GMR_BASE_ADR0 + i,
362 			      MC5_IDT_CMD_WRITE))
363 			goto err;
364 	}
365 
366 	/* Set up SCR */
367 	dbgi_wr_data3(adap, 1, 0, 0);
368 	if (mc5_write(adap, MC5_IDT_SCR_ADR0, MC5_IDT_CMD_WRITE))
369 		goto err;
370 
371 	return init_mask_data_array(mc5, MC5_IDT_MSKARY_BASE_ADR0,
372 				    MC5_IDT_DATARY_BASE_ADR0,
373 				    MC5_IDT_CMD_WRITE);
374  err:
375 	return -EIO;
376 }
377 
378 /* Put MC5 in DBGI mode. */
379 static inline void mc5_dbgi_mode_enable(struct pemc5 *mc5)
380 {
381 	t1_write_reg_4(mc5->adapter, A_MC5_CONFIG,
382 		       V_MODE(mc5->mode == MC5_MODE_72_BIT) |
383 		       F_DBGI_ENABLE | V_NUM_LIP(MC5_LIP_NUM_OF_ENTRIES - 1));
384 }
385 
386 /* Put MC5 in M-Bus mode. */
387 static void mc5_dbgi_mode_disable(struct pemc5 *mc5)
388 {
389 	t1_write_reg_4(mc5->adapter, A_MC5_CONFIG,
390 		       V_MODE(mc5->mode == MC5_MODE_72_BIT) |
391 		       V_COMPRESSION_ENABLE(mc5->mode == MC5_MODE_72_BIT) |
392 		       V_PARITY_ENABLE(mc5->parity_enabled) |
393 		       V_SYN_ISSUE_MODE(mc5->issue_syn) | F_M_BUS_ENABLE |
394 		       V_NUM_LIP(MC5_LIP_NUM_OF_ENTRIES - 1));
395 }
396 
397 /*
398  * Initialization that requires the OS and protocol layers to already
399  * be intialized goes here.
400  */
401 int t1_mc5_init(struct pemc5 *mc5, unsigned int nservers,
402 		unsigned int nroutes, int parity, int syn)
403 {
404 	u32 cfg;
405 	int err = 0;
406 	unsigned int tcam_size = t1_mc5_get_tcam_size(mc5);
407 	adapter_t *adap = mc5->adapter;
408 
409 	/* Reset the TCAM */
410 	cfg = t1_read_reg_4(adap, A_MC5_CONFIG) & ~F_MODE;
411 	cfg |= V_MODE(mc5->mode == MC5_MODE_72_BIT) | F_TCAM_RESET;
412 	t1_write_reg_4(adap, A_MC5_CONFIG, cfg);
413 	if (t1_wait_op_done(adap, A_MC5_CONFIG, F_TCAM_READY, 1, 500, 0)) {
414 		CH_ERR("%s: TCAM reset timed out\n", adapter_name(adap));
415 		return -1;
416 	}
417 
418 	if (set_tcam_rtbl_base(mc5, tcam_size - nroutes) ||
419 	    set_tcam_server_base(mc5, tcam_size - nroutes - nservers))
420 		return -EINVAL;
421 
422 #ifdef SUPPORT_MODE72
423 	if (mc5->mode == MC5_MODE_72_BIT)
424 		t1_mc5_lip_write_entries(mc5);
425 #endif
426 	mc5->issue_syn = (unsigned char)syn;
427 	mc5->parity_enabled = (unsigned char)parity;
428 
429 	/* All the TCAM addresses we access have only the low 32 bits non 0 */
430 	t1_write_reg_4(adap, A_MC5_DBGI_REQ_ADDR1, 0);
431 	t1_write_reg_4(adap, A_MC5_DBGI_REQ_ADDR2, 0);
432 
433 	mc5_dbgi_mode_enable(mc5);
434 
435 	switch (mc5->part_type) {
436 	case LARA_7000:
437 		err = init_lara7000(mc5);
438 		break;
439 	case IDT75P52100:
440 		err = init_idt52100(mc5);
441 		break;
442 	default:
443 		CH_ERR("%s: unsupported TCAM type\n", adapter_name(adap));
444 		err = -EINVAL;
445 		break;
446 	}
447 
448 	mc5_dbgi_mode_disable(mc5);
449 	return err;
450 }
451 
452 /*
453  *	read_mc5_range - dump a part of the memory managed by MC5
454  *	@mc5: the MC5 handle
455  *	@start: the start address for the dump
456  *	@n: number of 72-bit words to read
457  *	@buf: result buffer
458  *
459  *	Read n 72-bit words from MC5 memory from the given start location.
460  */
461 int t1_read_mc5_range(struct pemc5 *mc5, unsigned int start,
462 		      unsigned int n, u32 *buf)
463 {
464 	u32 read_cmd;
465 	/* int err = 0; */
466 	adapter_t *adap = mc5->adapter;
467 
468 	if (mc5->part_type == LARA_7000)
469 		read_cmd = MC5_LRA_CMD_READ;
470 	else if (mc5->part_type == IDT75P52100)
471 		read_cmd = MC5_IDT_CMD_READ;
472 	else
473 		return -EINVAL;
474 
475 	mc5_dbgi_mode_enable(mc5);
476 
477 	while (n--) {
478 		t1_write_reg_4(adap, A_MC5_DBGI_REQ_ADDR0, start++);
479 		if (mc5_cmd_write(adap, read_cmd)) {
480 			/* err = -EIO; */
481 			break;
482 		}
483 		dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
484 		buf += 3;
485 	}
486 
487 	mc5_dbgi_mode_disable(mc5);
488 	return 0;
489 }
490 
491 #define MC5_INT_MASK (F_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR | \
492 	F_MC5_INT_HIT_IN_RT_REGION_ERR | F_MC5_INT_LIP0_ERR | \
493 	F_MC5_INT_LIP_MISS_ERR | F_MC5_INT_PARITY_ERR | \
494 	F_MC5_INT_ACTIVE_REGION_FULL | F_MC5_INT_NFA_SRCH_ERR | \
495 	F_MC5_INT_UNKNOWN_CMD | F_MC5_INT_DEL_ACT_EMPTY)
496 #define MC5_INT_FATAL (F_MC5_INT_PARITY_ERR | F_MC5_INT_REQUESTQ_PARITY_ERR | \
497 	F_MC5_INT_DISPATCHQ_PARITY_ERR)
498 
499 void t1_mc5_intr_enable(struct pemc5 *mc5)
500 {
501 	u32 mask = MC5_INT_MASK;
502 
503 	if (!mc5->parity_enabled)
504 		mask &= ~F_MC5_INT_PARITY_ERR;
505 
506 #ifdef CONFIG_CHELSIO_T1_1G
507 	if (!t1_is_asic(mc5->adapter)) {
508 		/*
509 		 * Enable child block for MC5.
510 		 *
511 		 * NOTE: Assumes TP parent interrupt block is enabled.
512 		 *       MC5 requires TP parent block to be enabled.
513 		 */
514 		t1_write_reg_4(mc5->adapter, A_MC5_INT_ENABLE, mask);
515 	} else
516 #endif
517 	{
518 		u32 pl_intr = t1_read_reg_4(mc5->adapter, A_PL_ENABLE);
519 
520 		t1_write_reg_4(mc5->adapter, A_PL_ENABLE,
521 			       pl_intr | F_PL_INTR_MC5);
522 		t1_write_reg_4(mc5->adapter, A_MC5_INT_ENABLE,
523 			       mask | F_MC5_INT_REQUESTQ_PARITY_ERR |
524 			       F_MC5_INT_DISPATCHQ_PARITY_ERR);
525 	}
526 }
527 
528 void t1_mc5_intr_disable(struct pemc5 *mc5)
529 {
530 #ifdef CONFIG_CHELSIO_T1_1G
531 	if (!t1_is_asic(mc5->adapter))
532 		t1_write_reg_4(mc5->adapter, A_MC5_INT_ENABLE, 0);
533 	else
534 #endif
535 	{
536 		u32 pl_intr = t1_read_reg_4(mc5->adapter, A_PL_ENABLE);
537 
538 		t1_write_reg_4(mc5->adapter, A_PL_ENABLE,
539 			       pl_intr & ~F_PL_INTR_MC5);
540 		t1_write_reg_4(mc5->adapter, A_MC5_INT_ENABLE, 0);
541 	}
542 }
543 
544 void t1_mc5_intr_clear(struct pemc5 *mc5)
545 {
546 #ifdef CONFIG_CHELSIO_T1_1G
547 	if (!t1_is_asic(mc5->adapter)) {
548 		t1_write_reg_4(mc5->adapter, A_MC5_INT_CAUSE, 0xffffffff);
549 	} else
550 #endif
551 	{
552 		t1_write_reg_4(mc5->adapter, A_PL_CAUSE, F_PL_INTR_MC5);
553 		t1_write_reg_4(mc5->adapter, A_MC5_INT_CAUSE, 0xffffffff);
554 	}
555 }
556 
557 /*
558  * We don't really do anything with MC5 interrupts, just record them.
559  */
560 void t1_mc5_intr_handler(struct pemc5 *mc5)
561 {
562 	adapter_t *adap = mc5->adapter;
563 	u32 cause = t1_read_reg_4(adap, A_MC5_INT_CAUSE);
564 
565 	if (cause & F_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR)
566 		mc5->intr_counts.hit_out_active_region_err++;
567 
568 	if (cause & F_MC5_INT_HIT_IN_ACTIVE_REGION_ERR)
569 		mc5->intr_counts.hit_in_active_region_err++;
570 
571 	if (cause & F_MC5_INT_HIT_IN_RT_REGION_ERR)
572 		mc5->intr_counts.hit_in_routing_region_err++;
573 
574 	if (cause & F_MC5_INT_MISS_ERR)
575 		mc5->intr_counts.miss_err++;
576 
577 	if (cause & F_MC5_INT_LIP0_ERR)
578 		mc5->intr_counts.lip_equal_zero_err++;
579 
580 	if (cause & F_MC5_INT_LIP_MISS_ERR)
581 		mc5->intr_counts.lip_miss_err++;
582 
583 	if ((cause & F_MC5_INT_PARITY_ERR) && mc5->parity_enabled) {
584 		CH_ALERT("%s: MC5 parity error\n", adapter_name(adap));
585 		mc5->intr_counts.parity_err++;
586 	}
587 
588 	if (cause & F_MC5_INT_ACTIVE_REGION_FULL)
589 		mc5->intr_counts.active_region_full_err++;
590 
591 	if (cause & F_MC5_INT_NFA_SRCH_ERR)
592 		mc5->intr_counts.next_free_addr_srch_err++;
593 
594 	if (cause & F_MC5_INT_SYN_COOKIE)
595 		mc5->intr_counts.syn_cookie++;
596 
597 	if (cause & F_MC5_INT_SYN_COOKIE_BAD)
598 		mc5->intr_counts.syn_cookie_bad_message++;
599 
600 	if (cause & F_MC5_INT_SYN_COOKIE_OFF)
601 		mc5->intr_counts.syn_cookie_off_message++;
602 
603 	if (cause & F_MC5_INT_UNKNOWN_CMD)
604 		mc5->intr_counts.receive_unknown_cmd++;
605 
606 	if (cause & F_MC5_INT_REQUESTQ_PARITY_ERR) {
607 		CH_ALERT("%s: MC5 request queue parity error\n",
608 			 adapter_name(adap));
609 		mc5->intr_counts.parity_in_request_q_err++;
610 	}
611 
612 	if (cause & F_MC5_INT_DISPATCHQ_PARITY_ERR) {
613 		CH_ALERT("%s: MC5 dispatch queue parity error\n",
614 			 adapter_name(adap));
615 		mc5->intr_counts.parity_in_dispatch_q_err++;
616 	}
617 
618 	if (cause & F_MC5_INT_DEL_ACT_EMPTY)
619 		mc5->intr_counts.del_and_act_is_empty++;
620 
621 	if (cause & MC5_INT_FATAL)
622 		t1_fatal_err(adap);
623 
624 	t1_write_reg_4(adap, A_MC5_INT_CAUSE, cause);
625 }
626 
627 const struct pemc5_intr_counts *t1_mc5_get_intr_counts(struct pemc5 *mc5)
628 {
629 	return &mc5->intr_counts;
630 }
631 
632 struct pemc5 * __devinit t1_mc5_create(adapter_t *adapter, int mode)
633 {
634 	struct pemc5 *mc5;
635 	u32 cfg, bits_per_entry;
636 
637 	if (mode != MC5_MODE_144_BIT && mode != MC5_MODE_72_BIT)
638 		return NULL;
639 
640 	mc5 = t1_os_malloc_wait_zero(sizeof(*mc5));
641 	if (!mc5) return NULL;
642 
643 	mc5->adapter = adapter;
644 	mc5->mode = (unsigned char) mode;
645 
646 	cfg = t1_read_reg_4(adapter, A_MC5_CONFIG);
647 	mc5->part_size = G_TCAM_PART_SIZE(cfg);
648 	mc5->part_type = (unsigned char) G_TCAM_PART_TYPE(cfg);
649 	if (cfg & F_TCAM_PART_TYPE_HI)
650 		mc5->part_type |= 4;
651 
652 	/*
653 	 * Calculate the size of the TCAM based on the total memory, mode, and
654 	 * count information retrieved from the hardware.
655 	 */
656 	bits_per_entry = mode == MC5_MODE_144_BIT ? 144 : 72;
657 	mc5->tcam_size = tcam_part_size[mc5->part_size] / bits_per_entry;
658 
659 	return mc5;
660 }
661 
662 void t1_mc5_destroy(struct pemc5 *mc5)
663 {
664 	t1_os_free((void *)mc5, sizeof(*mc5));
665 }
666 
667 #ifdef SUPPORT_MODE72
668 static int mc5_cmp(const void *pi, const void *pj)
669 {
670 	const u32 *pii = (const u32 *)pi;
671 	const u32 *pjj = (const u32 *)pj;
672 
673 	if (*pii < *pjj)
674 		return -1;
675 
676 	return *pii > *pjj;
677 }
678 
679 /*
680  * DESC: Write local IP addresses to the TCAM
681  *
682  * NOTES: IP addresses should be in host byte order. So, an IP address:
683  *        of 10.0.0.140 == (data = 0x0A00008C)
684  */
685 static int mc5_set_lip_entries(struct pemc5 *mc5, u32 *p,
686 			       int num_of_lip_addresses)
687 {
688 	int i;
689 
690 	/*
691 	 * Disable compression and M bus mode so that the TP core
692 	 * doesn't access the TCAM  while we are writing.
693 	 */
694 	u32 cfg = t1_read_reg_4(mc5->adapter, A_MC5_CONFIG);
695 	t1_write_reg_4(mc5->adapter, A_MC5_CONFIG,
696 		       cfg & ~(F_M_BUS_ENABLE | F_COMPRESSION_ENABLE));
697 
698 	/* MC5 should now be ready to program the LIP addresses. */
699 	for (i = 0; i < num_of_lip_addresses; i++) {
700 		t1_write_reg_4(mc5->adapter, A_MC5_LIP_RAM_DATA, p[i]);
701 		t1_write_reg_4(mc5->adapter, A_MC5_LIP_RAM_ADDR, 0x100 + i);
702 	}
703 
704 	/* Restore MC5 mode. */
705 	t1_write_reg_4(mc5->adapter, A_MC5_CONFIG, cfg | F_COMPRESSION_ENABLE);
706 	return 0;
707 }
708 
709 /*
710  * The purpose of this routine is to write all of the local IP addresses
711  * into the TCAM in sorted order. This is a requirement from the TCAM.
712  */
713 void t1_mc5_lip_write_entries(struct pemc5 *mc5)
714 {
715 	u32 filler = 0;
716 	int i;
717 
718 	if (mc5->lip_index) {
719 		qsort(mc5->lip, mc5->lip_index, sizeof(u32), mc5_cmp);
720 		filler = mc5->lip[mc5->lip_index - 1];
721 	}
722 	for (i = mc5->lip_index; i < MC5_LIP_NUM_OF_ENTRIES; i++)
723 		mc5->lip[i] = filler;
724 	mc5_set_lip_entries(mc5, mc5->lip, MC5_LIP_NUM_OF_ENTRIES);
725 }
726 
727 void t1_mc5_lip_clear_entries(struct pemc5 *mc5)
728 {
729 	mc5->lip_index = 0;
730 }
731 
732 /*
733  * Add a local IP address to the LIP table.
734  */
735 int t1_mc5_lip_add_entry(struct pemc5 *mc5, u32 lip)
736 {
737 	if (mc5->lip_index >= MC5_LIP_NUM_OF_ENTRIES) return 1;
738 	mc5->lip[mc5->lip_index++] = lip;
739 	return 0;
740 }
741 #endif
742