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