Deleted Added
full compact
cxgb_mc5.c (169978) cxgb_mc5.c (170076)
1/**************************************************************************
2
3Copyright (c) 2007, Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, 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
1/**************************************************************************
2
3Copyright (c) 2007, Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, 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
12 2. 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
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30POSSIBILITY OF SUCH DAMAGE.
31
32***************************************************************************/
33
34#include <sys/cdefs.h>
13 contributors may be used to endorse or promote products derived from
14 this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27
28***************************************************************************/
29
30#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/dev/cxgb/common/cxgb_mc5.c 169978 2007-05-25 09:48:20Z kmacy $");
31__FBSDID("$FreeBSD: head/sys/dev/cxgb/common/cxgb_mc5.c 170076 2007-05-28 22:57:27Z kmacy $");
36
32
37#include <dev/cxgb/common/cxgb_common.h>
38#include <dev/cxgb/common/cxgb_regs.h>
33#ifdef CONFIG_DEFINED
34#include <cxgb_include.h>
35#else
36#include <dev/cxgb/cxgb_include.h>
37#endif
39
40enum {
41 IDT75P52100 = 4,
42 IDT75N43102 = 5
43};
44
45/* DBGI command mode */
46enum {
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 */
98static 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
105static 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
112static 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
119static 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 */
131static 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
140static 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
180static 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
244static 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. */
305static 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. */
312static 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 */
324int 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 (tcam_size == 0)
333 return 0;
334
335 if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
336 return -EINVAL;
337
338 /* Reset the TCAM */
339 cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
340 cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
341 t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
342 if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
343 CH_ERR(adap, "TCAM reset timed out\n");
344 return -1;
345 }
346
347 t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
348 t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
349 tcam_size - nroutes - nfilters);
350 t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
351 tcam_size - nroutes - nfilters - nservers);
352
353 mc5->parity_enabled = 1;
354
355 /* All the TCAM addresses we access have only the low 32 bits non 0 */
356 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
357 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
358
359 mc5_dbgi_mode_enable(mc5);
360
361 switch (mc5->part_type) {
362 case IDT75P52100:
363 err = init_idt52100(mc5);
364 break;
365 case IDT75N43102:
366 err = init_idt43102(mc5);
367 break;
368 default:
369 CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
370 err = -EINVAL;
371 break;
372 }
373
374 mc5_dbgi_mode_disable(mc5);
375 return err;
376}
377
378/*
379 * read_mc5_range - dump a part of the memory managed by MC5
380 * @mc5: the MC5 handle
381 * @start: the start address for the dump
382 * @n: number of 72-bit words to read
383 * @buf: result buffer
384 *
385 * Read n 72-bit words from MC5 memory from the given start location.
386 */
387int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start,
388 unsigned int n, u32 *buf)
389{
390 u32 read_cmd;
391 int err = 0;
392 adapter_t *adap = mc5->adapter;
393
394 if (mc5->part_type == IDT75P52100)
395 read_cmd = IDT_CMD_READ;
396 else if (mc5->part_type == IDT75N43102)
397 read_cmd = IDT4_CMD_READ;
398 else
399 return -EINVAL;
400
401 mc5_dbgi_mode_enable(mc5);
402
403 while (n--) {
404 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++);
405 if (mc5_cmd_write(adap, read_cmd)) {
406 err = -EIO;
407 break;
408 }
409 dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
410 buf += 3;
411 }
412
413 mc5_dbgi_mode_disable(mc5);
414 return 0;
415}
416
417#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
418
419/*
420 * MC5 interrupt handler
421 */
422void t3_mc5_intr_handler(struct mc5 *mc5)
423{
424 adapter_t *adap = mc5->adapter;
425 u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
426
427 if ((cause & F_PARITYERR) && mc5->parity_enabled) {
428 CH_ALERT(adap, "MC5 parity error\n");
429 mc5->stats.parity_err++;
430 }
431
432 if (cause & F_REQQPARERR) {
433 CH_ALERT(adap, "MC5 request queue parity error\n");
434 mc5->stats.reqq_parity_err++;
435 }
436
437 if (cause & F_DISPQPARERR) {
438 CH_ALERT(adap, "MC5 dispatch queue parity error\n");
439 mc5->stats.dispq_parity_err++;
440 }
441
442 if (cause & F_ACTRGNFULL)
443 mc5->stats.active_rgn_full++;
444 if (cause & F_NFASRCHFAIL)
445 mc5->stats.nfa_srch_err++;
446 if (cause & F_UNKNOWNCMD)
447 mc5->stats.unknown_cmd++;
448 if (cause & F_DELACTEMPTY)
449 mc5->stats.del_act_empty++;
450 if (cause & MC5_INT_FATAL)
451 t3_fatal_err(adap);
452
453 t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
454}
455
456void __devinit t3_mc5_prep(adapter_t *adapter, struct mc5 *mc5, int mode)
457{
458#define K * 1024
459
460 static unsigned int tcam_part_size[] = { /* in K 72-bit entries */
461 64 K, 128 K, 256 K, 32 K
462 };
463
464#undef K
465
466 u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
467
468 mc5->adapter = adapter;
469 mc5->mode = (unsigned char) mode;
470 mc5->part_type = (unsigned char) G_TMTYPE(cfg);
471 if (cfg & F_TMTYPEHI)
472 mc5->part_type |= 4;
473
474 mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
475 if (mode == MC5_MODE_144_BIT)
476 mc5->tcam_size /= 2;
477}
38
39enum {
40 IDT75P52100 = 4,
41 IDT75N43102 = 5
42};
43
44/* DBGI command mode */
45enum {
46 DBGI_MODE_MBUS = 0,
47 DBGI_MODE_IDT52100 = 5
48};
49
50/* IDT 75P52100 commands */
51#define IDT_CMD_READ 0
52#define IDT_CMD_WRITE 1
53#define IDT_CMD_SEARCH 2
54#define IDT_CMD_LEARN 3
55
56/* IDT LAR register address and value for 144-bit mode (low 32 bits) */
57#define IDT_LAR_ADR0 0x180006
58#define IDT_LAR_MODE144 0xffff0000
59
60/* IDT SCR and SSR addresses (low 32 bits) */
61#define IDT_SCR_ADR0 0x180000
62#define IDT_SSR0_ADR0 0x180002
63#define IDT_SSR1_ADR0 0x180004
64
65/* IDT GMR base address (low 32 bits) */
66#define IDT_GMR_BASE_ADR0 0x180020
67
68/* IDT data and mask array base addresses (low 32 bits) */
69#define IDT_DATARY_BASE_ADR0 0
70#define IDT_MSKARY_BASE_ADR0 0x80000
71
72/* IDT 75N43102 commands */
73#define IDT4_CMD_SEARCH144 3
74#define IDT4_CMD_WRITE 4
75#define IDT4_CMD_READ 5
76
77/* IDT 75N43102 SCR address (low 32 bits) */
78#define IDT4_SCR_ADR0 0x3
79
80/* IDT 75N43102 GMR base addresses (low 32 bits) */
81#define IDT4_GMR_BASE0 0x10
82#define IDT4_GMR_BASE1 0x20
83#define IDT4_GMR_BASE2 0x30
84
85/* IDT 75N43102 data and mask array base addresses (low 32 bits) */
86#define IDT4_DATARY_BASE_ADR0 0x1000000
87#define IDT4_MSKARY_BASE_ADR0 0x2000000
88
89#define MAX_WRITE_ATTEMPTS 5
90
91#define MAX_ROUTES 2048
92
93/*
94 * Issue a command to the TCAM and wait for its completion. The address and
95 * any data required by the command must have been setup by the caller.
96 */
97static int mc5_cmd_write(adapter_t *adapter, u32 cmd)
98{
99 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
100 return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
101 F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
102}
103
104static inline void dbgi_wr_addr3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
105{
106 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, v1);
107 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR1, v2);
108 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR2, v3);
109}
110
111static inline void dbgi_wr_data3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
112{
113 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
114 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
115 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
116}
117
118static inline void dbgi_rd_rsp3(adapter_t *adapter, u32 *v1, u32 *v2, u32 *v3)
119{
120 *v1 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA0);
121 *v2 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA1);
122 *v3 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA2);
123}
124
125/*
126 * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
127 * command cmd. The data to be written must have been set up by the caller.
128 * Returns -1 on failure, 0 on success.
129 */
130static int mc5_write(adapter_t *adapter, u32 addr_lo, u32 cmd)
131{
132 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
133 if (mc5_cmd_write(adapter, cmd) == 0)
134 return 0;
135 CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n", addr_lo);
136 return -1;
137}
138
139static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
140 u32 data_array_base, u32 write_cmd,
141 int addr_shift)
142{
143 unsigned int i;
144 adapter_t *adap = mc5->adapter;
145
146 /*
147 * We need the size of the TCAM data and mask arrays in terms of
148 * 72-bit entries.
149 */
150 unsigned int size72 = mc5->tcam_size;
151 unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
152
153 if (mc5->mode == MC5_MODE_144_BIT) {
154 size72 *= 2; /* 1 144-bit entry is 2 72-bit entries */
155 server_base *= 2;
156 }
157
158 /* Clear the data array */
159 dbgi_wr_data3(adap, 0, 0, 0);
160 for (i = 0; i < size72; i++)
161 if (mc5_write(adap, data_array_base + (i << addr_shift),
162 write_cmd))
163 return -1;
164
165 /* Initialize the mask array. */
166 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
167 for (i = 0; i < size72; i++) {
168 if (i == server_base) /* entering server or routing region */
169 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0,
170 mc5->mode == MC5_MODE_144_BIT ?
171 0xfffffff9 : 0xfffffffd);
172 if (mc5_write(adap, mask_array_base + (i << addr_shift),
173 write_cmd))
174 return -1;
175 }
176 return 0;
177}
178
179static 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
243static 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. */
304static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
305{
306 t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
307 V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN);
308}
309
310/* Put MC5 in M-Bus mode. */
311static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
312{
313 t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
314 V_TMMODE(mc5->mode == MC5_MODE_72_BIT) |
315 V_COMPEN(mc5->mode == MC5_MODE_72_BIT) |
316 V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
317}
318
319/*
320 * Initialization that requires the OS and protocol layers to already
321 * be intialized goes here.
322 */
323int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
324 unsigned int nroutes)
325{
326 u32 cfg;
327 int err;
328 unsigned int tcam_size = mc5->tcam_size;
329 adapter_t *adap = mc5->adapter;
330
331 if (tcam_size == 0)
332 return 0;
333
334 if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
335 return -EINVAL;
336
337 /* Reset the TCAM */
338 cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
339 cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
340 t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
341 if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
342 CH_ERR(adap, "TCAM reset timed out\n");
343 return -1;
344 }
345
346 t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
347 t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
348 tcam_size - nroutes - nfilters);
349 t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
350 tcam_size - nroutes - nfilters - nservers);
351
352 mc5->parity_enabled = 1;
353
354 /* All the TCAM addresses we access have only the low 32 bits non 0 */
355 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
356 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
357
358 mc5_dbgi_mode_enable(mc5);
359
360 switch (mc5->part_type) {
361 case IDT75P52100:
362 err = init_idt52100(mc5);
363 break;
364 case IDT75N43102:
365 err = init_idt43102(mc5);
366 break;
367 default:
368 CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
369 err = -EINVAL;
370 break;
371 }
372
373 mc5_dbgi_mode_disable(mc5);
374 return err;
375}
376
377/*
378 * read_mc5_range - dump a part of the memory managed by MC5
379 * @mc5: the MC5 handle
380 * @start: the start address for the dump
381 * @n: number of 72-bit words to read
382 * @buf: result buffer
383 *
384 * Read n 72-bit words from MC5 memory from the given start location.
385 */
386int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start,
387 unsigned int n, u32 *buf)
388{
389 u32 read_cmd;
390 int err = 0;
391 adapter_t *adap = mc5->adapter;
392
393 if (mc5->part_type == IDT75P52100)
394 read_cmd = IDT_CMD_READ;
395 else if (mc5->part_type == IDT75N43102)
396 read_cmd = IDT4_CMD_READ;
397 else
398 return -EINVAL;
399
400 mc5_dbgi_mode_enable(mc5);
401
402 while (n--) {
403 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++);
404 if (mc5_cmd_write(adap, read_cmd)) {
405 err = -EIO;
406 break;
407 }
408 dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
409 buf += 3;
410 }
411
412 mc5_dbgi_mode_disable(mc5);
413 return 0;
414}
415
416#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
417
418/*
419 * MC5 interrupt handler
420 */
421void t3_mc5_intr_handler(struct mc5 *mc5)
422{
423 adapter_t *adap = mc5->adapter;
424 u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
425
426 if ((cause & F_PARITYERR) && mc5->parity_enabled) {
427 CH_ALERT(adap, "MC5 parity error\n");
428 mc5->stats.parity_err++;
429 }
430
431 if (cause & F_REQQPARERR) {
432 CH_ALERT(adap, "MC5 request queue parity error\n");
433 mc5->stats.reqq_parity_err++;
434 }
435
436 if (cause & F_DISPQPARERR) {
437 CH_ALERT(adap, "MC5 dispatch queue parity error\n");
438 mc5->stats.dispq_parity_err++;
439 }
440
441 if (cause & F_ACTRGNFULL)
442 mc5->stats.active_rgn_full++;
443 if (cause & F_NFASRCHFAIL)
444 mc5->stats.nfa_srch_err++;
445 if (cause & F_UNKNOWNCMD)
446 mc5->stats.unknown_cmd++;
447 if (cause & F_DELACTEMPTY)
448 mc5->stats.del_act_empty++;
449 if (cause & MC5_INT_FATAL)
450 t3_fatal_err(adap);
451
452 t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
453}
454
455void __devinit t3_mc5_prep(adapter_t *adapter, struct mc5 *mc5, int mode)
456{
457#define K * 1024
458
459 static unsigned int tcam_part_size[] = { /* in K 72-bit entries */
460 64 K, 128 K, 256 K, 32 K
461 };
462
463#undef K
464
465 u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
466
467 mc5->adapter = adapter;
468 mc5->mode = (unsigned char) mode;
469 mc5->part_type = (unsigned char) G_TMTYPE(cfg);
470 if (cfg & F_TMTYPEHI)
471 mc5->part_type |= 4;
472
473 mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
474 if (mode == MC5_MODE_144_BIT)
475 mc5->tcam_size /= 2;
476}