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