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