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