aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb3/mc5.c
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2007-01-18 22:04:14 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-05 16:58:46 -0500
commit4d22de3e6cc4a09c369b504cd8bcde3385a974cd (patch)
treeaf13a2ee582105d961c79fc4e55fce0b5e043310 /drivers/net/cxgb3/mc5.c
parent0bf94faf64afaba6e7b49fd11541b59d2ba06d0e (diff)
Add support for the latest 1G/10G Chelsio adapter, T3.
This driver is required by the Chelsio T3 RDMA driver posted by Steve Wise. Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/cxgb3/mc5.c')
-rw-r--r--drivers/net/cxgb3/mc5.c453
1 files changed, 453 insertions, 0 deletions
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c
new file mode 100644
index 000000000000..44fa9eaedcc3
--- /dev/null
+++ b/drivers/net/cxgb3/mc5.c
@@ -0,0 +1,453 @@
1/*
2 * This file is part of the Chelsio T3 Ethernet driver.
3 *
4 * Copyright (C) 2003-2006 Chelsio Communications. All rights reserved.
5 *
6 * This program is distributed in the hope that it will be useful, but WITHOUT
7 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
9 * release for licensing terms and conditions.
10 */
11
12#include "common.h"
13#include "regs.h"
14
15enum {
16 IDT75P52100 = 4,
17 IDT75N43102 = 5
18};
19
20/* DBGI command mode */
21enum {
22 DBGI_MODE_MBUS = 0,
23 DBGI_MODE_IDT52100 = 5
24};
25
26/* IDT 75P52100 commands */
27#define IDT_CMD_READ 0
28#define IDT_CMD_WRITE 1
29#define IDT_CMD_SEARCH 2
30#define IDT_CMD_LEARN 3
31
32/* IDT LAR register address and value for 144-bit mode (low 32 bits) */
33#define IDT_LAR_ADR0 0x180006
34#define IDT_LAR_MODE144 0xffff0000
35
36/* IDT SCR and SSR addresses (low 32 bits) */
37#define IDT_SCR_ADR0 0x180000
38#define IDT_SSR0_ADR0 0x180002
39#define IDT_SSR1_ADR0 0x180004
40
41/* IDT GMR base address (low 32 bits) */
42#define IDT_GMR_BASE_ADR0 0x180020
43
44/* IDT data and mask array base addresses (low 32 bits) */
45#define IDT_DATARY_BASE_ADR0 0
46#define IDT_MSKARY_BASE_ADR0 0x80000
47
48/* IDT 75N43102 commands */
49#define IDT4_CMD_SEARCH144 3
50#define IDT4_CMD_WRITE 4
51#define IDT4_CMD_READ 5
52
53/* IDT 75N43102 SCR address (low 32 bits) */
54#define IDT4_SCR_ADR0 0x3
55
56/* IDT 75N43102 GMR base addresses (low 32 bits) */
57#define IDT4_GMR_BASE0 0x10
58#define IDT4_GMR_BASE1 0x20
59#define IDT4_GMR_BASE2 0x30
60
61/* IDT 75N43102 data and mask array base addresses (low 32 bits) */
62#define IDT4_DATARY_BASE_ADR0 0x1000000
63#define IDT4_MSKARY_BASE_ADR0 0x2000000
64
65#define MAX_WRITE_ATTEMPTS 5
66
67#define MAX_ROUTES 2048
68
69/*
70 * Issue a command to the TCAM and wait for its completion. The address and
71 * any data required by the command must have been setup by the caller.
72 */
73static int mc5_cmd_write(struct adapter *adapter, u32 cmd)
74{
75 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
76 return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
77 F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
78}
79
80static inline void dbgi_wr_addr3(struct adapter *adapter, u32 v1, u32 v2,
81 u32 v3)
82{
83 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, v1);
84 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR1, v2);
85 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR2, v3);
86}
87
88static inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2,
89 u32 v3)
90{
91 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
92 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
93 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
94}
95
96static inline void dbgi_rd_rsp3(struct adapter *adapter, u32 *v1, u32 *v2,
97 u32 *v3)
98{
99 *v1 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA0);
100 *v2 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA1);
101 *v3 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA2);
102}
103
104/*
105 * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
106 * command cmd. The data to be written must have been set up by the caller.
107 * Returns -1 on failure, 0 on success.
108 */
109static int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd)
110{
111 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
112 if (mc5_cmd_write(adapter, cmd) == 0)
113 return 0;
114 CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n",
115 addr_lo);
116 return -1;
117}
118
119static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
120 u32 data_array_base, u32 write_cmd,
121 int addr_shift)
122{
123 unsigned int i;
124 struct adapter *adap = mc5->adapter;
125
126 /*
127 * We need the size of the TCAM data and mask arrays in terms of
128 * 72-bit entries.
129 */
130 unsigned int size72 = mc5->tcam_size;
131 unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
132
133 if (mc5->mode == MC5_MODE_144_BIT) {
134 size72 *= 2; /* 1 144-bit entry is 2 72-bit entries */
135 server_base *= 2;
136 }
137
138 /* Clear the data array */
139 dbgi_wr_data3(adap, 0, 0, 0);
140 for (i = 0; i < size72; i++)
141 if (mc5_write(adap, data_array_base + (i << addr_shift),
142 write_cmd))
143 return -1;
144
145 /* Initialize the mask array. */
146 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
147 for (i = 0; i < size72; i++) {
148 if (i == server_base) /* entering server or routing region */
149 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0,
150 mc5->mode == MC5_MODE_144_BIT ?
151 0xfffffff9 : 0xfffffffd);
152 if (mc5_write(adap, mask_array_base + (i << addr_shift),
153 write_cmd))
154 return -1;
155 }
156 return 0;
157}
158
159static int init_idt52100(struct mc5 *mc5)
160{
161 int i;
162 struct adapter *adap = mc5->adapter;
163
164 t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
165 V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
166 t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
167
168 /*
169 * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
170 * GMRs 8-9 for ACK- and AOPEN searches.
171 */
172 t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
173 t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
174 t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
175 t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
176 t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
177 t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
178 t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
179 t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
180 t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
181 t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
182 t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
183 t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
184
185 /* Set DBGI command mode for IDT TCAM. */
186 t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
187
188 /* Set up LAR */
189 dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
190 if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
191 goto err;
192
193 /* Set up SSRs */
194 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
195 if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
196 mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
197 goto err;
198
199 /* Set up GMRs */
200 for (i = 0; i < 32; ++i) {
201 if (i >= 12 && i < 15)
202 dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
203 else if (i == 15)
204 dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
205 else
206 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
207
208 if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
209 goto err;
210 }
211
212 /* Set up SCR */
213 dbgi_wr_data3(adap, 1, 0, 0);
214 if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
215 goto err;
216
217 return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
218 IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
219err:
220 return -EIO;
221}
222
223static int init_idt43102(struct mc5 *mc5)
224{
225 int i;
226 struct adapter *adap = mc5->adapter;
227
228 t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
229 adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
230 V_RDLAT(0xd) | V_SRCHLAT(0x12));
231
232 /*
233 * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
234 * for ACK- and AOPEN searches.
235 */
236 t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
237 t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
238 t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
239 IDT4_CMD_SEARCH144 | 0x3800);
240 t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
241 t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
242 t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
243 t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
244 t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
245 t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
246
247 t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
248
249 /* Set DBGI command mode for IDT TCAM. */
250 t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
251
252 /* Set up GMRs */
253 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
254 for (i = 0; i < 7; ++i)
255 if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
256 goto err;
257
258 for (i = 0; i < 4; ++i)
259 if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
260 goto err;
261
262 dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
263 if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
264 mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
265 mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
266 goto err;
267
268 dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
269 if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
270 goto err;
271
272 /* Set up SCR */
273 dbgi_wr_data3(adap, 0xf0000000, 0, 0);
274 if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
275 goto err;
276
277 return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
278 IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
279err:
280 return -EIO;
281}
282
283/* Put MC5 in DBGI mode. */
284static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
285{
286 t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
287 V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN);
288}
289
290/* Put MC5 in M-Bus mode. */
291static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
292{
293 t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
294 V_TMMODE(mc5->mode == MC5_MODE_72_BIT) |
295 V_COMPEN(mc5->mode == MC5_MODE_72_BIT) |
296 V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
297}
298
299/*
300 * Initialization that requires the OS and protocol layers to already
301 * be intialized goes here.
302 */
303int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
304 unsigned int nroutes)
305{
306 u32 cfg;
307 int err;
308 unsigned int tcam_size = mc5->tcam_size;
309 struct adapter *adap = mc5->adapter;
310
311 if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
312 return -EINVAL;
313
314 /* Reset the TCAM */
315 cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
316 cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
317 t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
318 if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
319 CH_ERR(adap, "TCAM reset timed out\n");
320 return -1;
321 }
322
323 t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
324 t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
325 tcam_size - nroutes - nfilters);
326 t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
327 tcam_size - nroutes - nfilters - nservers);
328
329 mc5->parity_enabled = 1;
330
331 /* All the TCAM addresses we access have only the low 32 bits non 0 */
332 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
333 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
334
335 mc5_dbgi_mode_enable(mc5);
336
337 switch (mc5->part_type) {
338 case IDT75P52100:
339 err = init_idt52100(mc5);
340 break;
341 case IDT75N43102:
342 err = init_idt43102(mc5);
343 break;
344 default:
345 CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
346 err = -EINVAL;
347 break;
348 }
349
350 mc5_dbgi_mode_disable(mc5);
351 return err;
352}
353
354/*
355 * read_mc5_range - dump a part of the memory managed by MC5
356 * @mc5: the MC5 handle
357 * @start: the start address for the dump
358 * @n: number of 72-bit words to read
359 * @buf: result buffer
360 *
361 * Read n 72-bit words from MC5 memory from the given start location.
362 */
363int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start,
364 unsigned int n, u32 *buf)
365{
366 u32 read_cmd;
367 int err = 0;
368 struct adapter *adap = mc5->adapter;
369
370 if (mc5->part_type == IDT75P52100)
371 read_cmd = IDT_CMD_READ;
372 else if (mc5->part_type == IDT75N43102)
373 read_cmd = IDT4_CMD_READ;
374 else
375 return -EINVAL;
376
377 mc5_dbgi_mode_enable(mc5);
378
379 while (n--) {
380 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++);
381 if (mc5_cmd_write(adap, read_cmd)) {
382 err = -EIO;
383 break;
384 }
385 dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
386 buf += 3;
387 }
388
389 mc5_dbgi_mode_disable(mc5);
390 return 0;
391}
392
393#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
394
395/*
396 * MC5 interrupt handler
397 */
398void t3_mc5_intr_handler(struct mc5 *mc5)
399{
400 struct adapter *adap = mc5->adapter;
401 u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
402
403 if ((cause & F_PARITYERR) && mc5->parity_enabled) {
404 CH_ALERT(adap, "MC5 parity error\n");
405 mc5->stats.parity_err++;
406 }
407
408 if (cause & F_REQQPARERR) {
409 CH_ALERT(adap, "MC5 request queue parity error\n");
410 mc5->stats.reqq_parity_err++;
411 }
412
413 if (cause & F_DISPQPARERR) {
414 CH_ALERT(adap, "MC5 dispatch queue parity error\n");
415 mc5->stats.dispq_parity_err++;
416 }
417
418 if (cause & F_ACTRGNFULL)
419 mc5->stats.active_rgn_full++;
420 if (cause & F_NFASRCHFAIL)
421 mc5->stats.nfa_srch_err++;
422 if (cause & F_UNKNOWNCMD)
423 mc5->stats.unknown_cmd++;
424 if (cause & F_DELACTEMPTY)
425 mc5->stats.del_act_empty++;
426 if (cause & MC5_INT_FATAL)
427 t3_fatal_err(adap);
428
429 t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
430}
431
432void __devinit t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode)
433{
434#define K * 1024
435
436 static unsigned int tcam_part_size[] = { /* in K 72-bit entries */
437 64 K, 128 K, 256 K, 32 K
438 };
439
440#undef K
441
442 u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
443
444 mc5->adapter = adapter;
445 mc5->mode = (unsigned char)mode;
446 mc5->part_type = (unsigned char)G_TMTYPE(cfg);
447 if (cfg & F_TMTYPEHI)
448 mc5->part_type |= 4;
449
450 mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
451 if (mode == MC5_MODE_144_BIT)
452 mc5->tcam_size /= 2;
453}