1f7917c00SJeff Kirsher /*
2f7917c00SJeff Kirsher  * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
3f7917c00SJeff Kirsher  *
4f7917c00SJeff Kirsher  * This software is available to you under a choice of one of two
5f7917c00SJeff Kirsher  * licenses.  You may choose to be licensed under the terms of the GNU
6f7917c00SJeff Kirsher  * General Public License (GPL) Version 2, available from the file
7f7917c00SJeff Kirsher  * COPYING in the main directory of this source tree, or the
8f7917c00SJeff Kirsher  * OpenIB.org BSD license below:
9f7917c00SJeff Kirsher  *
10f7917c00SJeff Kirsher  *     Redistribution and use in source and binary forms, with or
11f7917c00SJeff Kirsher  *     without modification, are permitted provided that the following
12f7917c00SJeff Kirsher  *     conditions are met:
13f7917c00SJeff Kirsher  *
14f7917c00SJeff Kirsher  *      - Redistributions of source code must retain the above
15f7917c00SJeff Kirsher  *        copyright notice, this list of conditions and the following
16f7917c00SJeff Kirsher  *        disclaimer.
17f7917c00SJeff Kirsher  *
18f7917c00SJeff Kirsher  *      - Redistributions in binary form must reproduce the above
19f7917c00SJeff Kirsher  *        copyright notice, this list of conditions and the following
20f7917c00SJeff Kirsher  *        disclaimer in the documentation and/or other materials
21f7917c00SJeff Kirsher  *        provided with the distribution.
22f7917c00SJeff Kirsher  *
23f7917c00SJeff Kirsher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24f7917c00SJeff Kirsher  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25f7917c00SJeff Kirsher  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26f7917c00SJeff Kirsher  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27f7917c00SJeff Kirsher  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28f7917c00SJeff Kirsher  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29f7917c00SJeff Kirsher  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30f7917c00SJeff Kirsher  * SOFTWARE.
31f7917c00SJeff Kirsher  */
32f7917c00SJeff Kirsher #include "common.h"
33f7917c00SJeff Kirsher #include "regs.h"
34f7917c00SJeff Kirsher 
35f7917c00SJeff Kirsher enum {
36f7917c00SJeff Kirsher 	IDT75P52100 = 4,
37f7917c00SJeff Kirsher 	IDT75N43102 = 5
38f7917c00SJeff Kirsher };
39f7917c00SJeff Kirsher 
40f7917c00SJeff Kirsher /* DBGI command mode */
41f7917c00SJeff Kirsher enum {
42f7917c00SJeff Kirsher 	DBGI_MODE_MBUS = 0,
43f7917c00SJeff Kirsher 	DBGI_MODE_IDT52100 = 5
44f7917c00SJeff Kirsher };
45f7917c00SJeff Kirsher 
46f7917c00SJeff Kirsher /* IDT 75P52100 commands */
47f7917c00SJeff Kirsher #define IDT_CMD_READ   0
48f7917c00SJeff Kirsher #define IDT_CMD_WRITE  1
49f7917c00SJeff Kirsher #define IDT_CMD_SEARCH 2
50f7917c00SJeff Kirsher #define IDT_CMD_LEARN  3
51f7917c00SJeff Kirsher 
52f7917c00SJeff Kirsher /* IDT LAR register address and value for 144-bit mode (low 32 bits) */
53f7917c00SJeff Kirsher #define IDT_LAR_ADR0   	0x180006
54f7917c00SJeff Kirsher #define IDT_LAR_MODE144	0xffff0000
55f7917c00SJeff Kirsher 
56f7917c00SJeff Kirsher /* IDT SCR and SSR addresses (low 32 bits) */
57f7917c00SJeff Kirsher #define IDT_SCR_ADR0  0x180000
58f7917c00SJeff Kirsher #define IDT_SSR0_ADR0 0x180002
59f7917c00SJeff Kirsher #define IDT_SSR1_ADR0 0x180004
60f7917c00SJeff Kirsher 
61f7917c00SJeff Kirsher /* IDT GMR base address (low 32 bits) */
62f7917c00SJeff Kirsher #define IDT_GMR_BASE_ADR0 0x180020
63f7917c00SJeff Kirsher 
64f7917c00SJeff Kirsher /* IDT data and mask array base addresses (low 32 bits) */
65f7917c00SJeff Kirsher #define IDT_DATARY_BASE_ADR0 0
66f7917c00SJeff Kirsher #define IDT_MSKARY_BASE_ADR0 0x80000
67f7917c00SJeff Kirsher 
68f7917c00SJeff Kirsher /* IDT 75N43102 commands */
69f7917c00SJeff Kirsher #define IDT4_CMD_SEARCH144 3
70f7917c00SJeff Kirsher #define IDT4_CMD_WRITE     4
71f7917c00SJeff Kirsher #define IDT4_CMD_READ      5
72f7917c00SJeff Kirsher 
73f7917c00SJeff Kirsher /* IDT 75N43102 SCR address (low 32 bits) */
74f7917c00SJeff Kirsher #define IDT4_SCR_ADR0  0x3
75f7917c00SJeff Kirsher 
76f7917c00SJeff Kirsher /* IDT 75N43102 GMR base addresses (low 32 bits) */
77f7917c00SJeff Kirsher #define IDT4_GMR_BASE0 0x10
78f7917c00SJeff Kirsher #define IDT4_GMR_BASE1 0x20
79f7917c00SJeff Kirsher #define IDT4_GMR_BASE2 0x30
80f7917c00SJeff Kirsher 
81f7917c00SJeff Kirsher /* IDT 75N43102 data and mask array base addresses (low 32 bits) */
82f7917c00SJeff Kirsher #define IDT4_DATARY_BASE_ADR0 0x1000000
83f7917c00SJeff Kirsher #define IDT4_MSKARY_BASE_ADR0 0x2000000
84f7917c00SJeff Kirsher 
85f7917c00SJeff Kirsher #define MAX_WRITE_ATTEMPTS 5
86f7917c00SJeff Kirsher 
87f7917c00SJeff Kirsher #define MAX_ROUTES 2048
88f7917c00SJeff Kirsher 
89f7917c00SJeff Kirsher /*
90f7917c00SJeff Kirsher  * Issue a command to the TCAM and wait for its completion.  The address and
91f7917c00SJeff Kirsher  * any data required by the command must have been setup by the caller.
92f7917c00SJeff Kirsher  */
mc5_cmd_write(struct adapter * adapter,u32 cmd)93f7917c00SJeff Kirsher static int mc5_cmd_write(struct adapter *adapter, u32 cmd)
94f7917c00SJeff Kirsher {
95f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
96f7917c00SJeff Kirsher 	return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
97f7917c00SJeff Kirsher 			       F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
98f7917c00SJeff Kirsher }
99f7917c00SJeff Kirsher 
dbgi_wr_data3(struct adapter * adapter,u32 v1,u32 v2,u32 v3)100f7917c00SJeff Kirsher static inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2,
101f7917c00SJeff Kirsher 				 u32 v3)
102f7917c00SJeff Kirsher {
103f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
104f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
105f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
106f7917c00SJeff Kirsher }
107f7917c00SJeff Kirsher 
108f7917c00SJeff Kirsher /*
109f7917c00SJeff Kirsher  * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
110f7917c00SJeff Kirsher  * command cmd.  The data to be written must have been set up by the caller.
111f7917c00SJeff Kirsher  * Returns -1 on failure, 0 on success.
112f7917c00SJeff Kirsher  */
mc5_write(struct adapter * adapter,u32 addr_lo,u32 cmd)113f7917c00SJeff Kirsher static int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd)
114f7917c00SJeff Kirsher {
115f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
116f7917c00SJeff Kirsher 	if (mc5_cmd_write(adapter, cmd) == 0)
117f7917c00SJeff Kirsher 		return 0;
118f7917c00SJeff Kirsher 	CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n",
119f7917c00SJeff Kirsher 	       addr_lo);
120f7917c00SJeff Kirsher 	return -1;
121f7917c00SJeff Kirsher }
122f7917c00SJeff Kirsher 
init_mask_data_array(struct mc5 * mc5,u32 mask_array_base,u32 data_array_base,u32 write_cmd,int addr_shift)123f7917c00SJeff Kirsher static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
124f7917c00SJeff Kirsher 				u32 data_array_base, u32 write_cmd,
125f7917c00SJeff Kirsher 				int addr_shift)
126f7917c00SJeff Kirsher {
127f7917c00SJeff Kirsher 	unsigned int i;
128f7917c00SJeff Kirsher 	struct adapter *adap = mc5->adapter;
129f7917c00SJeff Kirsher 
130f7917c00SJeff Kirsher 	/*
131f7917c00SJeff Kirsher 	 * We need the size of the TCAM data and mask arrays in terms of
132f7917c00SJeff Kirsher 	 * 72-bit entries.
133f7917c00SJeff Kirsher 	 */
134f7917c00SJeff Kirsher 	unsigned int size72 = mc5->tcam_size;
135f7917c00SJeff Kirsher 	unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
136f7917c00SJeff Kirsher 
137f7917c00SJeff Kirsher 	if (mc5->mode == MC5_MODE_144_BIT) {
138f7917c00SJeff Kirsher 		size72 *= 2;	/* 1 144-bit entry is 2 72-bit entries */
139f7917c00SJeff Kirsher 		server_base *= 2;
140f7917c00SJeff Kirsher 	}
141f7917c00SJeff Kirsher 
142f7917c00SJeff Kirsher 	/* Clear the data array */
143f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, 0, 0, 0);
144f7917c00SJeff Kirsher 	for (i = 0; i < size72; i++)
145f7917c00SJeff Kirsher 		if (mc5_write(adap, data_array_base + (i << addr_shift),
146f7917c00SJeff Kirsher 			      write_cmd))
147f7917c00SJeff Kirsher 			return -1;
148f7917c00SJeff Kirsher 
149f7917c00SJeff Kirsher 	/* Initialize the mask array. */
150f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
151f7917c00SJeff Kirsher 	for (i = 0; i < size72; i++) {
152f7917c00SJeff Kirsher 		if (i == server_base)	/* entering server or routing region */
153f7917c00SJeff Kirsher 			t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0,
154f7917c00SJeff Kirsher 				     mc5->mode == MC5_MODE_144_BIT ?
155f7917c00SJeff Kirsher 				     0xfffffff9 : 0xfffffffd);
156f7917c00SJeff Kirsher 		if (mc5_write(adap, mask_array_base + (i << addr_shift),
157f7917c00SJeff Kirsher 			      write_cmd))
158f7917c00SJeff Kirsher 			return -1;
159f7917c00SJeff Kirsher 	}
160f7917c00SJeff Kirsher 	return 0;
161f7917c00SJeff Kirsher }
162f7917c00SJeff Kirsher 
init_idt52100(struct mc5 * mc5)163f7917c00SJeff Kirsher static int init_idt52100(struct mc5 *mc5)
164f7917c00SJeff Kirsher {
165f7917c00SJeff Kirsher 	int i;
166f7917c00SJeff Kirsher 	struct adapter *adap = mc5->adapter;
167f7917c00SJeff Kirsher 
168f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
169f7917c00SJeff Kirsher 		     V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
170f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
171f7917c00SJeff Kirsher 
172f7917c00SJeff Kirsher 	/*
173f7917c00SJeff Kirsher 	 * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
174f7917c00SJeff Kirsher 	 * GMRs 8-9 for ACK- and AOPEN searches.
175f7917c00SJeff Kirsher 	 */
176f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
177f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
178f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
179f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
180f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
181f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
182f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
183f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
184f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
185f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
186f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
187f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
188f7917c00SJeff Kirsher 
189f7917c00SJeff Kirsher 	/* Set DBGI command mode for IDT TCAM. */
190f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
191f7917c00SJeff Kirsher 
192f7917c00SJeff Kirsher 	/* Set up LAR */
193f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
194f7917c00SJeff Kirsher 	if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
195f7917c00SJeff Kirsher 		goto err;
196f7917c00SJeff Kirsher 
197f7917c00SJeff Kirsher 	/* Set up SSRs */
198f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
199f7917c00SJeff Kirsher 	if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
200f7917c00SJeff Kirsher 	    mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
201f7917c00SJeff Kirsher 		goto err;
202f7917c00SJeff Kirsher 
203f7917c00SJeff Kirsher 	/* Set up GMRs */
204f7917c00SJeff Kirsher 	for (i = 0; i < 32; ++i) {
205f7917c00SJeff Kirsher 		if (i >= 12 && i < 15)
206f7917c00SJeff Kirsher 			dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
207f7917c00SJeff Kirsher 		else if (i == 15)
208f7917c00SJeff Kirsher 			dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
209f7917c00SJeff Kirsher 		else
210f7917c00SJeff Kirsher 			dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
211f7917c00SJeff Kirsher 
212f7917c00SJeff Kirsher 		if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
213f7917c00SJeff Kirsher 			goto err;
214f7917c00SJeff Kirsher 	}
215f7917c00SJeff Kirsher 
216f7917c00SJeff Kirsher 	/* Set up SCR */
217f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, 1, 0, 0);
218f7917c00SJeff Kirsher 	if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
219f7917c00SJeff Kirsher 		goto err;
220f7917c00SJeff Kirsher 
221f7917c00SJeff Kirsher 	return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
222f7917c00SJeff Kirsher 				    IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
223f7917c00SJeff Kirsher err:
224f7917c00SJeff Kirsher 	return -EIO;
225f7917c00SJeff Kirsher }
226f7917c00SJeff Kirsher 
init_idt43102(struct mc5 * mc5)227f7917c00SJeff Kirsher static int init_idt43102(struct mc5 *mc5)
228f7917c00SJeff Kirsher {
229f7917c00SJeff Kirsher 	int i;
230f7917c00SJeff Kirsher 	struct adapter *adap = mc5->adapter;
231f7917c00SJeff Kirsher 
232f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
233f7917c00SJeff Kirsher 		     adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
234f7917c00SJeff Kirsher 		     V_RDLAT(0xd) | V_SRCHLAT(0x12));
235f7917c00SJeff Kirsher 
236f7917c00SJeff Kirsher 	/*
237f7917c00SJeff Kirsher 	 * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
238f7917c00SJeff Kirsher 	 * for ACK- and AOPEN searches.
239f7917c00SJeff Kirsher 	 */
240f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
241f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
242f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
243f7917c00SJeff Kirsher 		     IDT4_CMD_SEARCH144 | 0x3800);
244f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
245f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
246f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
247f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
248f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
249f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
250f7917c00SJeff Kirsher 
251f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
252f7917c00SJeff Kirsher 
253f7917c00SJeff Kirsher 	/* Set DBGI command mode for IDT TCAM. */
254f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
255f7917c00SJeff Kirsher 
256f7917c00SJeff Kirsher 	/* Set up GMRs */
257f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
258f7917c00SJeff Kirsher 	for (i = 0; i < 7; ++i)
259f7917c00SJeff Kirsher 		if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
260f7917c00SJeff Kirsher 			goto err;
261f7917c00SJeff Kirsher 
262f7917c00SJeff Kirsher 	for (i = 0; i < 4; ++i)
263f7917c00SJeff Kirsher 		if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
264f7917c00SJeff Kirsher 			goto err;
265f7917c00SJeff Kirsher 
266f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
267f7917c00SJeff Kirsher 	if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
268f7917c00SJeff Kirsher 	    mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
269f7917c00SJeff Kirsher 	    mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
270f7917c00SJeff Kirsher 		goto err;
271f7917c00SJeff Kirsher 
272f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
273f7917c00SJeff Kirsher 	if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
274f7917c00SJeff Kirsher 		goto err;
275f7917c00SJeff Kirsher 
276f7917c00SJeff Kirsher 	/* Set up SCR */
277f7917c00SJeff Kirsher 	dbgi_wr_data3(adap, 0xf0000000, 0, 0);
278f7917c00SJeff Kirsher 	if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
279f7917c00SJeff Kirsher 		goto err;
280f7917c00SJeff Kirsher 
281f7917c00SJeff Kirsher 	return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
282f7917c00SJeff Kirsher 				    IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
283f7917c00SJeff Kirsher err:
284f7917c00SJeff Kirsher 	return -EIO;
285f7917c00SJeff Kirsher }
286f7917c00SJeff Kirsher 
287f7917c00SJeff Kirsher /* Put MC5 in DBGI mode. */
mc5_dbgi_mode_enable(const struct mc5 * mc5)288f7917c00SJeff Kirsher static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
289f7917c00SJeff Kirsher {
290f7917c00SJeff Kirsher 	t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
291f7917c00SJeff Kirsher 		     V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN);
292f7917c00SJeff Kirsher }
293f7917c00SJeff Kirsher 
294f7917c00SJeff Kirsher /* Put MC5 in M-Bus mode. */
mc5_dbgi_mode_disable(const struct mc5 * mc5)295f7917c00SJeff Kirsher static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
296f7917c00SJeff Kirsher {
297f7917c00SJeff Kirsher 	t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
298f7917c00SJeff Kirsher 		     V_TMMODE(mc5->mode == MC5_MODE_72_BIT) |
299f7917c00SJeff Kirsher 		     V_COMPEN(mc5->mode == MC5_MODE_72_BIT) |
300f7917c00SJeff Kirsher 		     V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
301f7917c00SJeff Kirsher }
302f7917c00SJeff Kirsher 
303f7917c00SJeff Kirsher /*
304f7917c00SJeff Kirsher  * Initialization that requires the OS and protocol layers to already
305f7917c00SJeff Kirsher  * be initialized goes here.
306f7917c00SJeff Kirsher  */
t3_mc5_init(struct mc5 * mc5,unsigned int nservers,unsigned int nfilters,unsigned int nroutes)307f7917c00SJeff Kirsher int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
308f7917c00SJeff Kirsher 		unsigned int nroutes)
309f7917c00SJeff Kirsher {
310f7917c00SJeff Kirsher 	u32 cfg;
311f7917c00SJeff Kirsher 	int err;
312f7917c00SJeff Kirsher 	unsigned int tcam_size = mc5->tcam_size;
313f7917c00SJeff Kirsher 	struct adapter *adap = mc5->adapter;
314f7917c00SJeff Kirsher 
315f7917c00SJeff Kirsher 	if (!tcam_size)
316f7917c00SJeff Kirsher 		return 0;
317f7917c00SJeff Kirsher 
318f7917c00SJeff Kirsher 	if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
319f7917c00SJeff Kirsher 		return -EINVAL;
320f7917c00SJeff Kirsher 
321f7917c00SJeff Kirsher 	/* Reset the TCAM */
322f7917c00SJeff Kirsher 	cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
323f7917c00SJeff Kirsher 	cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
324f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
325f7917c00SJeff Kirsher 	if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
326f7917c00SJeff Kirsher 		CH_ERR(adap, "TCAM reset timed out\n");
327f7917c00SJeff Kirsher 		return -1;
328f7917c00SJeff Kirsher 	}
329f7917c00SJeff Kirsher 
330f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
331f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
332f7917c00SJeff Kirsher 		     tcam_size - nroutes - nfilters);
333f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
334f7917c00SJeff Kirsher 		     tcam_size - nroutes - nfilters - nservers);
335f7917c00SJeff Kirsher 
336f7917c00SJeff Kirsher 	mc5->parity_enabled = 1;
337f7917c00SJeff Kirsher 
338f7917c00SJeff Kirsher 	/* All the TCAM addresses we access have only the low 32 bits non 0 */
339f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
340f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
341f7917c00SJeff Kirsher 
342f7917c00SJeff Kirsher 	mc5_dbgi_mode_enable(mc5);
343f7917c00SJeff Kirsher 
344f7917c00SJeff Kirsher 	switch (mc5->part_type) {
345f7917c00SJeff Kirsher 	case IDT75P52100:
346f7917c00SJeff Kirsher 		err = init_idt52100(mc5);
347f7917c00SJeff Kirsher 		break;
348f7917c00SJeff Kirsher 	case IDT75N43102:
349f7917c00SJeff Kirsher 		err = init_idt43102(mc5);
350f7917c00SJeff Kirsher 		break;
351f7917c00SJeff Kirsher 	default:
352f7917c00SJeff Kirsher 		CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
353f7917c00SJeff Kirsher 		err = -EINVAL;
354f7917c00SJeff Kirsher 		break;
355f7917c00SJeff Kirsher 	}
356f7917c00SJeff Kirsher 
357f7917c00SJeff Kirsher 	mc5_dbgi_mode_disable(mc5);
358f7917c00SJeff Kirsher 	return err;
359f7917c00SJeff Kirsher }
360f7917c00SJeff Kirsher 
361f7917c00SJeff Kirsher 
362f7917c00SJeff Kirsher #define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
363f7917c00SJeff Kirsher 
364f7917c00SJeff Kirsher /*
365f7917c00SJeff Kirsher  * MC5 interrupt handler
366f7917c00SJeff Kirsher  */
t3_mc5_intr_handler(struct mc5 * mc5)367f7917c00SJeff Kirsher void t3_mc5_intr_handler(struct mc5 *mc5)
368f7917c00SJeff Kirsher {
369f7917c00SJeff Kirsher 	struct adapter *adap = mc5->adapter;
370f7917c00SJeff Kirsher 	u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
371f7917c00SJeff Kirsher 
372f7917c00SJeff Kirsher 	if ((cause & F_PARITYERR) && mc5->parity_enabled) {
373f7917c00SJeff Kirsher 		CH_ALERT(adap, "MC5 parity error\n");
374f7917c00SJeff Kirsher 		mc5->stats.parity_err++;
375f7917c00SJeff Kirsher 	}
376f7917c00SJeff Kirsher 
377f7917c00SJeff Kirsher 	if (cause & F_REQQPARERR) {
378f7917c00SJeff Kirsher 		CH_ALERT(adap, "MC5 request queue parity error\n");
379f7917c00SJeff Kirsher 		mc5->stats.reqq_parity_err++;
380f7917c00SJeff Kirsher 	}
381f7917c00SJeff Kirsher 
382f7917c00SJeff Kirsher 	if (cause & F_DISPQPARERR) {
383f7917c00SJeff Kirsher 		CH_ALERT(adap, "MC5 dispatch queue parity error\n");
384f7917c00SJeff Kirsher 		mc5->stats.dispq_parity_err++;
385f7917c00SJeff Kirsher 	}
386f7917c00SJeff Kirsher 
387f7917c00SJeff Kirsher 	if (cause & F_ACTRGNFULL)
388f7917c00SJeff Kirsher 		mc5->stats.active_rgn_full++;
389f7917c00SJeff Kirsher 	if (cause & F_NFASRCHFAIL)
390f7917c00SJeff Kirsher 		mc5->stats.nfa_srch_err++;
391f7917c00SJeff Kirsher 	if (cause & F_UNKNOWNCMD)
392f7917c00SJeff Kirsher 		mc5->stats.unknown_cmd++;
393f7917c00SJeff Kirsher 	if (cause & F_DELACTEMPTY)
394f7917c00SJeff Kirsher 		mc5->stats.del_act_empty++;
395f7917c00SJeff Kirsher 	if (cause & MC5_INT_FATAL)
396f7917c00SJeff Kirsher 		t3_fatal_err(adap);
397f7917c00SJeff Kirsher 
398f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
399f7917c00SJeff Kirsher }
400f7917c00SJeff Kirsher 
t3_mc5_prep(struct adapter * adapter,struct mc5 * mc5,int mode)401f7917c00SJeff Kirsher void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode)
402f7917c00SJeff Kirsher {
403f7917c00SJeff Kirsher #define K * 1024
404f7917c00SJeff Kirsher 
405f7917c00SJeff Kirsher 	static unsigned int tcam_part_size[] = {	/* in K 72-bit entries */
406f7917c00SJeff Kirsher 		64 K, 128 K, 256 K, 32 K
407f7917c00SJeff Kirsher 	};
408f7917c00SJeff Kirsher 
409f7917c00SJeff Kirsher #undef K
410f7917c00SJeff Kirsher 
411f7917c00SJeff Kirsher 	u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
412f7917c00SJeff Kirsher 
413f7917c00SJeff Kirsher 	mc5->adapter = adapter;
414f7917c00SJeff Kirsher 	mc5->mode = (unsigned char)mode;
415f7917c00SJeff Kirsher 	mc5->part_type = (unsigned char)G_TMTYPE(cfg);
416f7917c00SJeff Kirsher 	if (cfg & F_TMTYPEHI)
417f7917c00SJeff Kirsher 		mc5->part_type |= 4;
418f7917c00SJeff Kirsher 
419f7917c00SJeff Kirsher 	mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
420f7917c00SJeff Kirsher 	if (mode == MC5_MODE_144_BIT)
421f7917c00SJeff Kirsher 		mc5->tcam_size /= 2;
422f7917c00SJeff Kirsher }
423