1*3833Sxw161283 /*
2*3833Sxw161283 * CDDL HEADER START
3*3833Sxw161283 *
4*3833Sxw161283 * The contents of this file are subject to the terms of the
5*3833Sxw161283 * Common Development and Distribution License (the "License").
6*3833Sxw161283 * You may not use this file except in compliance with the License.
7*3833Sxw161283 *
8*3833Sxw161283 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3833Sxw161283 * or http://www.opensolaris.org/os/licensing.
10*3833Sxw161283 * See the License for the specific language governing permissions
11*3833Sxw161283 * and limitations under the License.
12*3833Sxw161283 *
13*3833Sxw161283 * When distributing Covered Code, include this CDDL HEADER in each
14*3833Sxw161283 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3833Sxw161283 * If applicable, add the following below this CDDL HEADER, with the
16*3833Sxw161283 * fields enclosed by brackets "[]" replaced with your own identifying
17*3833Sxw161283 * information: Portions Copyright [yyyy] [name of copyright owner]
18*3833Sxw161283 *
19*3833Sxw161283 * CDDL HEADER END
20*3833Sxw161283 */
21*3833Sxw161283
22*3833Sxw161283 /*
23*3833Sxw161283 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved.
24*3833Sxw161283 */
25*3833Sxw161283
26*3833Sxw161283 #pragma ident "%Z%%M% %I% %E% SMI" /* mc5.c */
27*3833Sxw161283
28*3833Sxw161283 #include "common.h"
29*3833Sxw161283 #include "regs.h"
30*3833Sxw161283 #include "mc5.h"
31*3833Sxw161283
32*3833Sxw161283 /* DBGI command mode */
33*3833Sxw161283 enum {
34*3833Sxw161283 DBGI_MODE_MBUS,
35*3833Sxw161283 DBGI_MODE_LARA_7000,
36*3833Sxw161283 DBGI_MODE_LARA_8000,
37*3833Sxw161283 DBGI_MODE_NETL_4000,
38*3833Sxw161283 DBGI_MODE_NETL_5000,
39*3833Sxw161283 DBGI_MODE_IDT_52100
40*3833Sxw161283 };
41*3833Sxw161283
42*3833Sxw161283 /* Lara command register address and values (low 32 bits) */
43*3833Sxw161283 #define MC5_LRA_CMDREG_ADR0 0x00180038
44*3833Sxw161283 #define MC5_LRA_CMDREG_72KEY_DATA0 0x00000182
45*3833Sxw161283 #define MC5_LRA_CMDREG_144KEY_DATA0 0x00AAAB82
46*3833Sxw161283
47*3833Sxw161283 /* Lara config register address and values (low 32 bits) */
48*3833Sxw161283 #define MC5_LRA_CFGREG_ADR0 0x0018003D
49*3833Sxw161283 #define MC5_LRA_CFGREG_72KEY_DATA0 0x00000000
50*3833Sxw161283 #define MC5_LRA_CFGREG_144KEY_DATA0 0x55555555
51*3833Sxw161283
52*3833Sxw161283 /* Lara GMR base addresses (low 32 bits) */
53*3833Sxw161283 #define MC5_LRA_GMRREG_BASE_ADR0_1 0x00180020
54*3833Sxw161283 #define MC5_LRA_GMRREG_BASE_ADR0_2 0x00180060
55*3833Sxw161283
56*3833Sxw161283 /* Lara 7000 data and mask array base addresses (low 32 bits) */
57*3833Sxw161283 #define MC5_LRA_DATARY_BASE_ADR0 0x00000000
58*3833Sxw161283 #define MC5_LRA_MSKARY_BASE_ADR0 0x00080000
59*3833Sxw161283
60*3833Sxw161283 /* Lara commands */
61*3833Sxw161283 #define MC5_LRA_CMD_READ 0x00000000
62*3833Sxw161283 #define MC5_LRA_CMD_WRITE 0x00010001
63*3833Sxw161283 #define MC5_LRA_CMD_SEARCH 0x00020002
64*3833Sxw161283 #define MC5_LRA_CMD_LEARN 0x00030003
65*3833Sxw161283
66*3833Sxw161283 /* IDT 75P52100 commands */
67*3833Sxw161283 #define MC5_IDT_CMD_READ 0x0
68*3833Sxw161283 #define MC5_IDT_CMD_WRITE 0x1
69*3833Sxw161283 #define MC5_IDT_CMD_SEARCH 0x2
70*3833Sxw161283 #define MC5_IDT_CMD_LEARN 0x3
71*3833Sxw161283 #define MC5_IDT_CMD_NFA_SEARCH 0x4
72*3833Sxw161283
73*3833Sxw161283 /* IDT LAR register address and value for 144-bit mode (low 32 bits) */
74*3833Sxw161283 #define MC5_IDT_LAR_ADR0 0x180006
75*3833Sxw161283 #define MC5_IDT_LAR_MODE144 0xffff0000
76*3833Sxw161283
77*3833Sxw161283 /* IDT SCR and SSR addresses (low 32 bits) */
78*3833Sxw161283 #define MC5_IDT_SCR_ADR0 0x180000
79*3833Sxw161283 #define MC5_IDT_SSR0_ADR0 0x180002
80*3833Sxw161283 #define MC5_IDT_SSR1_ADR0 0x180004
81*3833Sxw161283
82*3833Sxw161283 /* IDT GMR base address (low 32 bits) */
83*3833Sxw161283 #define MC5_IDT_GMR_BASE_ADR0 0x180020
84*3833Sxw161283
85*3833Sxw161283 /* IDT data and mask array base addresses (low 32 bits) */
86*3833Sxw161283 #define MC5_IDT_DATARY_BASE_ADR0 0x00000000
87*3833Sxw161283 #define MC5_IDT_MSKARY_BASE_ADR0 0x00080000
88*3833Sxw161283
89*3833Sxw161283 #define IDT_ELOOKUP_2Mb 0x7000
90*3833Sxw161283 #define IDT_ELOOKUP_9Mb 0x16000
91*3833Sxw161283
92*3833Sxw161283 enum {
93*3833Sxw161283 LARA_7000,
94*3833Sxw161283 LARA_8000,
95*3833Sxw161283 NETLOGIC_4000,
96*3833Sxw161283 NETLOGIC_5000,
97*3833Sxw161283 IDT75P52100
98*3833Sxw161283 };
99*3833Sxw161283
100*3833Sxw161283 static unsigned int tcam_part_size[] = {
101*3833Sxw161283 4718592, /* 4.5Mb */
102*3833Sxw161283 9437184, /* 9Mb */
103*3833Sxw161283 18874368 /* 18Mb */
104*3833Sxw161283 };
105*3833Sxw161283
106*3833Sxw161283 struct pemc5 {
107*3833Sxw161283 adapter_t *adapter;
108*3833Sxw161283 unsigned int tcam_size;
109*3833Sxw161283 unsigned int part_size;
110*3833Sxw161283 unsigned char part_type;
111*3833Sxw161283 unsigned char parity_enabled;
112*3833Sxw161283 unsigned char issue_syn;
113*3833Sxw161283 unsigned char mode;
114*3833Sxw161283 struct pemc5_intr_counts intr_counts;
115*3833Sxw161283 #ifdef SUPPORT_MODE72
116*3833Sxw161283 u32 lip[MC5_LIP_NUM_OF_ENTRIES];
117*3833Sxw161283 unsigned int lip_index;
118*3833Sxw161283 #endif
119*3833Sxw161283 };
120*3833Sxw161283
121*3833Sxw161283 #define MAX_WRITE_ATTEMPTS 5
122*3833Sxw161283
123*3833Sxw161283 /*
124*3833Sxw161283 * Issue a command to the TCAM and wait for its completion. The address and
125*3833Sxw161283 * any data required by the command must have been setup by the caller.
126*3833Sxw161283 */
mc5_cmd_write(adapter_t * adapter,u32 cmd)127*3833Sxw161283 static int mc5_cmd_write(adapter_t *adapter, u32 cmd)
128*3833Sxw161283 {
129*3833Sxw161283 t1_write_reg_4(adapter, A_MC5_DBGI_REQ_CMD, cmd);
130*3833Sxw161283 return t1_wait_op_done(adapter, A_MC5_DBGI_RSP_STATUS,
131*3833Sxw161283 F_DBGI_RSP_VALID, 1, MAX_WRITE_ATTEMPTS, 1);
132*3833Sxw161283 }
133*3833Sxw161283
134*3833Sxw161283
t1_mc5_get_tcam_size(struct pemc5 * mc5)135*3833Sxw161283 unsigned int t1_mc5_get_tcam_size(struct pemc5 *mc5)
136*3833Sxw161283 {
137*3833Sxw161283 return mc5->tcam_size;
138*3833Sxw161283 }
139*3833Sxw161283
set_tcam_rtbl_base(struct pemc5 * mc5,unsigned int rtbl_base)140*3833Sxw161283 static int set_tcam_rtbl_base(struct pemc5 *mc5, unsigned int rtbl_base)
141*3833Sxw161283 {
142*3833Sxw161283 if (rtbl_base >= t1_mc5_get_tcam_size(mc5)) return -1;
143*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_ROUTING_TABLE_INDEX, rtbl_base);
144*3833Sxw161283 return 0;
145*3833Sxw161283 }
146*3833Sxw161283
t1_mc5_get_tcam_rtbl_base(struct pemc5 * mc5)147*3833Sxw161283 unsigned int t1_mc5_get_tcam_rtbl_base(struct pemc5 *mc5)
148*3833Sxw161283 {
149*3833Sxw161283 return t1_read_reg_4(mc5->adapter, A_MC5_ROUTING_TABLE_INDEX);
150*3833Sxw161283 }
151*3833Sxw161283
t1_mc5_get_tcam_rtbl_size(struct pemc5 * mc5)152*3833Sxw161283 unsigned int t1_mc5_get_tcam_rtbl_size(struct pemc5 *mc5)
153*3833Sxw161283 {
154*3833Sxw161283 unsigned int tcam_size = t1_mc5_get_tcam_size(mc5);
155*3833Sxw161283 unsigned int tcam_rtable_base = t1_mc5_get_tcam_rtbl_base(mc5);
156*3833Sxw161283
157*3833Sxw161283 return tcam_size - tcam_rtable_base;
158*3833Sxw161283 }
159*3833Sxw161283
set_tcam_server_base(struct pemc5 * mc5,unsigned int server_base)160*3833Sxw161283 static int set_tcam_server_base(struct pemc5 *mc5, unsigned int server_base)
161*3833Sxw161283 {
162*3833Sxw161283 if (server_base >= t1_mc5_get_tcam_size(mc5)) return -1;
163*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_SERVER_INDEX, server_base);
164*3833Sxw161283 return 0;
165*3833Sxw161283 }
166*3833Sxw161283
t1_mc5_get_tcam_server_base(struct pemc5 * mc5)167*3833Sxw161283 unsigned int t1_mc5_get_tcam_server_base(struct pemc5 *mc5)
168*3833Sxw161283 {
169*3833Sxw161283 return t1_read_reg_4(mc5->adapter, A_MC5_SERVER_INDEX);
170*3833Sxw161283 }
171*3833Sxw161283
t1_mc5_get_tcam_server_size(struct pemc5 * mc5)172*3833Sxw161283 unsigned int t1_mc5_get_tcam_server_size(struct pemc5 *mc5)
173*3833Sxw161283 {
174*3833Sxw161283 unsigned int tcam_rtable_base = t1_mc5_get_tcam_rtbl_base(mc5);
175*3833Sxw161283 unsigned int tcam_server_base = t1_mc5_get_tcam_server_base(mc5);
176*3833Sxw161283
177*3833Sxw161283 return tcam_rtable_base - tcam_server_base;
178*3833Sxw161283 }
179*3833Sxw161283
dbgi_wr_addr3(adapter_t * adapter,u32 v1,u32 v2,u32 v3)180*3833Sxw161283 static inline void dbgi_wr_addr3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
181*3833Sxw161283 {
182*3833Sxw161283 t1_write_reg_4(adapter, A_MC5_DBGI_REQ_ADDR0, v1);
183*3833Sxw161283 t1_write_reg_4(adapter, A_MC5_DBGI_REQ_ADDR1, v2);
184*3833Sxw161283 t1_write_reg_4(adapter, A_MC5_DBGI_REQ_ADDR2, v3);
185*3833Sxw161283 }
186*3833Sxw161283
dbgi_wr_data3(adapter_t * adapter,u32 v1,u32 v2,u32 v3)187*3833Sxw161283 static inline void dbgi_wr_data3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
188*3833Sxw161283 {
189*3833Sxw161283 t1_write_reg_4(adapter, A_MC5_DBGI_REQ_DATA0, v1);
190*3833Sxw161283 t1_write_reg_4(adapter, A_MC5_DBGI_REQ_DATA1, v2);
191*3833Sxw161283 t1_write_reg_4(adapter, A_MC5_DBGI_REQ_DATA2, v3);
192*3833Sxw161283 }
193*3833Sxw161283
dbgi_rd_rsp3(adapter_t * adapter,u32 * v1,u32 * v2,u32 * v3)194*3833Sxw161283 static inline void dbgi_rd_rsp3(adapter_t *adapter, u32 *v1, u32 *v2, u32 *v3)
195*3833Sxw161283 {
196*3833Sxw161283 *v1 = t1_read_reg_4(adapter, A_MC5_DBGI_RSP_DATA0);
197*3833Sxw161283 *v2 = t1_read_reg_4(adapter, A_MC5_DBGI_RSP_DATA1);
198*3833Sxw161283 *v3 = t1_read_reg_4(adapter, A_MC5_DBGI_RSP_DATA2);
199*3833Sxw161283 }
200*3833Sxw161283
201*3833Sxw161283 /*
202*3833Sxw161283 * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
203*3833Sxw161283 * command cmd. The data to be written must have been set up by the caller.
204*3833Sxw161283 * Returns -1 on failure, 0 on success.
205*3833Sxw161283 */
mc5_write(adapter_t * adapter,u32 addr_lo,u32 cmd)206*3833Sxw161283 static int mc5_write(adapter_t *adapter, u32 addr_lo, u32 cmd)
207*3833Sxw161283 {
208*3833Sxw161283 t1_write_reg_4(adapter, A_MC5_DBGI_REQ_ADDR0, addr_lo);
209*3833Sxw161283 if (mc5_cmd_write(adapter, cmd) == 0)
210*3833Sxw161283 return 0;
211*3833Sxw161283 CH_ERR("%s: MC5 timeout writing to TCAM address 0x%x\n",
212*3833Sxw161283 adapter_name(adapter), addr_lo);
213*3833Sxw161283 return -1;
214*3833Sxw161283 }
215*3833Sxw161283
init_mask_data_array(struct pemc5 * mc5,u32 mask_array_base,u32 data_array_base,u32 write_cmd)216*3833Sxw161283 static int init_mask_data_array(struct pemc5 *mc5, u32 mask_array_base,
217*3833Sxw161283 u32 data_array_base, u32 write_cmd)
218*3833Sxw161283 {
219*3833Sxw161283 unsigned int i;
220*3833Sxw161283 adapter_t *adap = mc5->adapter;
221*3833Sxw161283
222*3833Sxw161283 /*
223*3833Sxw161283 * We need the size of the TCAM data and mask arrays in terms of
224*3833Sxw161283 * 72-bit entries.
225*3833Sxw161283 */
226*3833Sxw161283 unsigned int size72 = tcam_part_size[mc5->part_size] / 72;
227*3833Sxw161283 unsigned int server_base = t1_mc5_get_tcam_server_base(mc5);
228*3833Sxw161283 if (mc5->mode == MC5_MODE_144_BIT)
229*3833Sxw161283 server_base *= 2; /* 1 144-bit entry is 2 72-bit entries */
230*3833Sxw161283
231*3833Sxw161283 /* Clear the data array */
232*3833Sxw161283 dbgi_wr_data3(adap, 0, 0, 0);
233*3833Sxw161283 for (i = 0; i < size72; i++)
234*3833Sxw161283 if (mc5_write(adap, data_array_base + i, write_cmd))
235*3833Sxw161283 return -1;
236*3833Sxw161283
237*3833Sxw161283 /* Initialize the mask array. */
238*3833Sxw161283 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
239*3833Sxw161283 for (i = 0; i < size72; i++) {
240*3833Sxw161283 if (i == server_base) /* entering server or routing region */
241*3833Sxw161283 t1_write_reg_4(adap, A_MC5_DBGI_REQ_DATA0,
242*3833Sxw161283 mc5->mode == MC5_MODE_144_BIT ?
243*3833Sxw161283 0xfffffff9 : 0xfffffffd);
244*3833Sxw161283 if (mc5_write(adap, mask_array_base + i, write_cmd))
245*3833Sxw161283 return -1;
246*3833Sxw161283 }
247*3833Sxw161283 return 0;
248*3833Sxw161283 }
249*3833Sxw161283
init_lara7000(struct pemc5 * mc5)250*3833Sxw161283 static int init_lara7000(struct pemc5 *mc5)
251*3833Sxw161283 {
252*3833Sxw161283 int i;
253*3833Sxw161283 adapter_t *adap = mc5->adapter;
254*3833Sxw161283
255*3833Sxw161283 t1_write_reg_4(adap, A_MC5_RSP_LATENCY,
256*3833Sxw161283 t1_is_asic(adap) ? 0x0a0a0a0a : 0x09090909);
257*3833Sxw161283
258*3833Sxw161283 if (mc5->parity_enabled) {
259*3833Sxw161283 t1_write_reg_4(adap, A_MC5_AOPEN_SRCH_CMD, 0x20022);
260*3833Sxw161283 t1_write_reg_4(adap, A_MC5_SYN_SRCH_CMD, 0x20022);
261*3833Sxw161283 t1_write_reg_4(adap, A_MC5_ACK_SRCH_CMD, 0x20022);
262*3833Sxw161283 }
263*3833Sxw161283
264*3833Sxw161283 /* Set DBGI command mode for Lara TCAM. */
265*3833Sxw161283 t1_write_reg_4(adap, A_MC5_DBGI_CONFIG, DBGI_MODE_LARA_7000);
266*3833Sxw161283
267*3833Sxw161283 dbgi_wr_data3(adap, mc5->mode == MC5_MODE_144_BIT ?
268*3833Sxw161283 MC5_LRA_CMDREG_144KEY_DATA0 : MC5_LRA_CMDREG_72KEY_DATA0,
269*3833Sxw161283 0, 0);
270*3833Sxw161283 if (mc5_write(adap, MC5_LRA_CMDREG_ADR0, MC5_LRA_CMD_WRITE))
271*3833Sxw161283 goto err;
272*3833Sxw161283
273*3833Sxw161283 dbgi_wr_data3(adap, mc5->mode == MC5_MODE_144_BIT ?
274*3833Sxw161283 MC5_LRA_CFGREG_144KEY_DATA0 : MC5_LRA_CFGREG_72KEY_DATA0,
275*3833Sxw161283 0, 0);
276*3833Sxw161283 if (mc5_write(adap, MC5_LRA_CFGREG_ADR0, MC5_LRA_CMD_WRITE))
277*3833Sxw161283 goto err;
278*3833Sxw161283
279*3833Sxw161283 /* Global Mask Registers (GMR) 0-15 */
280*3833Sxw161283 for (i = 0; i < 16; i++) {
281*3833Sxw161283 if (i == 8 || i == 9)
282*3833Sxw161283 dbgi_wr_data3(adap, mc5->mode == MC5_MODE_72_BIT ?
283*3833Sxw161283 0xfffffffd : 0xfffffff9, 0xffffffff,
284*3833Sxw161283 0xff);
285*3833Sxw161283 else
286*3833Sxw161283 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
287*3833Sxw161283
288*3833Sxw161283 if (mc5_write(adap, MC5_LRA_GMRREG_BASE_ADR0_1 + i,
289*3833Sxw161283 MC5_LRA_CMD_WRITE))
290*3833Sxw161283 goto err;
291*3833Sxw161283 }
292*3833Sxw161283
293*3833Sxw161283 /* Global Mask Registers (GMR) 16-31 */
294*3833Sxw161283 for (i = 0; i < 16; i++) {
295*3833Sxw161283 if (i <= 1 && mc5->mode == MC5_MODE_72_BIT)
296*3833Sxw161283 dbgi_wr_data3(adap, 0xfffffffd, 0xffffc003, 0xff);
297*3833Sxw161283 else if (i == 0)
298*3833Sxw161283 dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
299*3833Sxw161283 else if (i == 1)
300*3833Sxw161283 dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
301*3833Sxw161283 else
302*3833Sxw161283 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
303*3833Sxw161283
304*3833Sxw161283 if (mc5_write(adap, MC5_LRA_GMRREG_BASE_ADR0_2 + i,
305*3833Sxw161283 MC5_LRA_CMD_WRITE))
306*3833Sxw161283 goto err;
307*3833Sxw161283 }
308*3833Sxw161283 return init_mask_data_array(mc5, MC5_LRA_MSKARY_BASE_ADR0,
309*3833Sxw161283 MC5_LRA_DATARY_BASE_ADR0,
310*3833Sxw161283 MC5_LRA_CMD_WRITE);
311*3833Sxw161283 err:
312*3833Sxw161283 return -EIO;
313*3833Sxw161283 }
314*3833Sxw161283
init_idt52100(struct pemc5 * mc5)315*3833Sxw161283 static int init_idt52100(struct pemc5 *mc5)
316*3833Sxw161283 {
317*3833Sxw161283 int i;
318*3833Sxw161283 adapter_t *adap = mc5->adapter;
319*3833Sxw161283
320*3833Sxw161283 t1_write_reg_4(adap, A_MC5_RSP_LATENCY, 0x151515);
321*3833Sxw161283 t1_write_reg_4(adap, A_MC5_PART_ID_INDEX, 2);
322*3833Sxw161283
323*3833Sxw161283 /*
324*3833Sxw161283 * Use GMRs 8-9 for ACK and AOPEN searches, GMRs 12-13 for SYN search,
325*3833Sxw161283 * and GMRs 14-15 for ELOOKUP.
326*3833Sxw161283 */
327*3833Sxw161283 t1_write_reg_4(adap, A_MC5_POPEN_DATA_WR_CMD, MC5_IDT_CMD_WRITE);
328*3833Sxw161283 t1_write_reg_4(adap, A_MC5_POPEN_MASK_WR_CMD, MC5_IDT_CMD_WRITE);
329*3833Sxw161283 t1_write_reg_4(adap, A_MC5_AOPEN_SRCH_CMD, MC5_IDT_CMD_SEARCH);
330*3833Sxw161283 t1_write_reg_4(adap, A_MC5_AOPEN_LRN_CMD, MC5_IDT_CMD_LEARN);
331*3833Sxw161283 t1_write_reg_4(adap, A_MC5_SYN_SRCH_CMD, MC5_IDT_CMD_SEARCH | 0x6000);
332*3833Sxw161283 t1_write_reg_4(adap, A_MC5_SYN_LRN_CMD, MC5_IDT_CMD_LEARN);
333*3833Sxw161283 t1_write_reg_4(adap, A_MC5_ACK_SRCH_CMD, MC5_IDT_CMD_SEARCH);
334*3833Sxw161283 t1_write_reg_4(adap, A_MC5_ACK_LRN_CMD, MC5_IDT_CMD_LEARN);
335*3833Sxw161283 t1_write_reg_4(adap, A_MC5_ILOOKUP_CMD, MC5_IDT_CMD_SEARCH);
336*3833Sxw161283 t1_write_reg_4(adap, A_MC5_ELOOKUP_CMD, MC5_IDT_CMD_SEARCH | 0x7000);
337*3833Sxw161283 t1_write_reg_4(adap, A_MC5_DATA_WRITE_CMD, MC5_IDT_CMD_WRITE);
338*3833Sxw161283 t1_write_reg_4(adap, A_MC5_DATA_READ_CMD, MC5_IDT_CMD_READ);
339*3833Sxw161283
340*3833Sxw161283 /* Set DBGI command mode for IDT TCAM. */
341*3833Sxw161283 t1_write_reg_4(adap, A_MC5_DBGI_CONFIG, DBGI_MODE_IDT_52100);
342*3833Sxw161283
343*3833Sxw161283 /* Set up LAR */
344*3833Sxw161283 dbgi_wr_data3(adap, MC5_IDT_LAR_MODE144, 0, 0);
345*3833Sxw161283 if (mc5_write(adap, MC5_IDT_LAR_ADR0, MC5_IDT_CMD_WRITE))
346*3833Sxw161283 goto err;
347*3833Sxw161283
348*3833Sxw161283 /* Set up SSRs */
349*3833Sxw161283 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
350*3833Sxw161283 if (mc5_write(adap, MC5_IDT_SSR0_ADR0, MC5_IDT_CMD_WRITE) ||
351*3833Sxw161283 mc5_write(adap, MC5_IDT_SSR1_ADR0, MC5_IDT_CMD_WRITE))
352*3833Sxw161283 goto err;
353*3833Sxw161283
354*3833Sxw161283 /* Set up GMRs */
355*3833Sxw161283 for (i = 0; i < 32; ++i) {
356*3833Sxw161283 if (i >= 12 && i < 15)
357*3833Sxw161283 dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
358*3833Sxw161283 else if (i == 15)
359*3833Sxw161283 dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
360*3833Sxw161283 else
361*3833Sxw161283 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
362*3833Sxw161283
363*3833Sxw161283 if (mc5_write(adap, MC5_IDT_GMR_BASE_ADR0 + i,
364*3833Sxw161283 MC5_IDT_CMD_WRITE))
365*3833Sxw161283 goto err;
366*3833Sxw161283 }
367*3833Sxw161283
368*3833Sxw161283 /* Set up SCR */
369*3833Sxw161283 dbgi_wr_data3(adap, 1, 0, 0);
370*3833Sxw161283 if (mc5_write(adap, MC5_IDT_SCR_ADR0, MC5_IDT_CMD_WRITE))
371*3833Sxw161283 goto err;
372*3833Sxw161283
373*3833Sxw161283 return init_mask_data_array(mc5, MC5_IDT_MSKARY_BASE_ADR0,
374*3833Sxw161283 MC5_IDT_DATARY_BASE_ADR0,
375*3833Sxw161283 MC5_IDT_CMD_WRITE);
376*3833Sxw161283 err:
377*3833Sxw161283 return -EIO;
378*3833Sxw161283 }
379*3833Sxw161283
380*3833Sxw161283 /* Put MC5 in DBGI mode. */
mc5_dbgi_mode_enable(struct pemc5 * mc5)381*3833Sxw161283 static inline void mc5_dbgi_mode_enable(struct pemc5 *mc5)
382*3833Sxw161283 {
383*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_CONFIG,
384*3833Sxw161283 V_MODE(mc5->mode == MC5_MODE_72_BIT) |
385*3833Sxw161283 F_DBGI_ENABLE | V_NUM_LIP(MC5_LIP_NUM_OF_ENTRIES - 1));
386*3833Sxw161283 }
387*3833Sxw161283
388*3833Sxw161283 /* Put MC5 in M-Bus mode. */
mc5_dbgi_mode_disable(struct pemc5 * mc5)389*3833Sxw161283 static void mc5_dbgi_mode_disable(struct pemc5 *mc5)
390*3833Sxw161283 {
391*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_CONFIG,
392*3833Sxw161283 V_MODE(mc5->mode == MC5_MODE_72_BIT) |
393*3833Sxw161283 V_COMPRESSION_ENABLE(mc5->mode == MC5_MODE_72_BIT) |
394*3833Sxw161283 V_PARITY_ENABLE(mc5->parity_enabled) |
395*3833Sxw161283 V_SYN_ISSUE_MODE(mc5->issue_syn) | F_M_BUS_ENABLE |
396*3833Sxw161283 V_NUM_LIP(MC5_LIP_NUM_OF_ENTRIES - 1));
397*3833Sxw161283 }
398*3833Sxw161283
399*3833Sxw161283 /*
400*3833Sxw161283 * Initialization that requires the OS and protocol layers to already
401*3833Sxw161283 * be intialized goes here.
402*3833Sxw161283 */
t1_mc5_init(struct pemc5 * mc5,unsigned int nservers,unsigned int nroutes,int parity,int syn)403*3833Sxw161283 int t1_mc5_init(struct pemc5 *mc5, unsigned int nservers,
404*3833Sxw161283 unsigned int nroutes, int parity, int syn)
405*3833Sxw161283 {
406*3833Sxw161283 u32 cfg;
407*3833Sxw161283 int err = 0;
408*3833Sxw161283 unsigned int tcam_size = t1_mc5_get_tcam_size(mc5);
409*3833Sxw161283 adapter_t *adap = mc5->adapter;
410*3833Sxw161283
411*3833Sxw161283 /* Reset the TCAM */
412*3833Sxw161283 cfg = t1_read_reg_4(adap, A_MC5_CONFIG) & ~F_MODE;
413*3833Sxw161283 cfg |= V_MODE(mc5->mode == MC5_MODE_72_BIT) | F_TCAM_RESET;
414*3833Sxw161283 t1_write_reg_4(adap, A_MC5_CONFIG, cfg);
415*3833Sxw161283 if (t1_wait_op_done(adap, A_MC5_CONFIG, F_TCAM_READY, 1, 500, 0)) {
416*3833Sxw161283 CH_ERR("%s: TCAM reset timed out\n", adapter_name(adap));
417*3833Sxw161283 return -1;
418*3833Sxw161283 }
419*3833Sxw161283
420*3833Sxw161283 if (set_tcam_rtbl_base(mc5, tcam_size - nroutes) ||
421*3833Sxw161283 set_tcam_server_base(mc5, tcam_size - nroutes - nservers))
422*3833Sxw161283 return -EINVAL;
423*3833Sxw161283
424*3833Sxw161283 #ifdef SUPPORT_MODE72
425*3833Sxw161283 if (mc5->mode == MC5_MODE_72_BIT)
426*3833Sxw161283 t1_mc5_lip_write_entries(mc5);
427*3833Sxw161283 #endif
428*3833Sxw161283 mc5->issue_syn = (unsigned char)syn;
429*3833Sxw161283 mc5->parity_enabled = (unsigned char)parity;
430*3833Sxw161283
431*3833Sxw161283 /* All the TCAM addresses we access have only the low 32 bits non 0 */
432*3833Sxw161283 t1_write_reg_4(adap, A_MC5_DBGI_REQ_ADDR1, 0);
433*3833Sxw161283 t1_write_reg_4(adap, A_MC5_DBGI_REQ_ADDR2, 0);
434*3833Sxw161283
435*3833Sxw161283 mc5_dbgi_mode_enable(mc5);
436*3833Sxw161283
437*3833Sxw161283 switch (mc5->part_type) {
438*3833Sxw161283 case LARA_7000:
439*3833Sxw161283 err = init_lara7000(mc5);
440*3833Sxw161283 break;
441*3833Sxw161283 case IDT75P52100:
442*3833Sxw161283 err = init_idt52100(mc5);
443*3833Sxw161283 break;
444*3833Sxw161283 default:
445*3833Sxw161283 CH_ERR("%s: unsupported TCAM type\n", adapter_name(adap));
446*3833Sxw161283 err = -EINVAL;
447*3833Sxw161283 break;
448*3833Sxw161283 }
449*3833Sxw161283
450*3833Sxw161283 mc5_dbgi_mode_disable(mc5);
451*3833Sxw161283 return err;
452*3833Sxw161283 }
453*3833Sxw161283
454*3833Sxw161283 /*
455*3833Sxw161283 * read_mc5_range - dump a part of the memory managed by MC5
456*3833Sxw161283 * @mc5: the MC5 handle
457*3833Sxw161283 * @start: the start address for the dump
458*3833Sxw161283 * @n: number of 72-bit words to read
459*3833Sxw161283 * @buf: result buffer
460*3833Sxw161283 *
461*3833Sxw161283 * Read n 72-bit words from MC5 memory from the given start location.
462*3833Sxw161283 */
t1_read_mc5_range(struct pemc5 * mc5,unsigned int start,unsigned int n,u32 * buf)463*3833Sxw161283 int t1_read_mc5_range(struct pemc5 *mc5, unsigned int start,
464*3833Sxw161283 unsigned int n, u32 *buf)
465*3833Sxw161283 {
466*3833Sxw161283 u32 read_cmd;
467*3833Sxw161283 /* int err = 0; */
468*3833Sxw161283 adapter_t *adap = mc5->adapter;
469*3833Sxw161283
470*3833Sxw161283 if (mc5->part_type == LARA_7000)
471*3833Sxw161283 read_cmd = MC5_LRA_CMD_READ;
472*3833Sxw161283 else if (mc5->part_type == IDT75P52100)
473*3833Sxw161283 read_cmd = MC5_IDT_CMD_READ;
474*3833Sxw161283 else
475*3833Sxw161283 return -EINVAL;
476*3833Sxw161283
477*3833Sxw161283 mc5_dbgi_mode_enable(mc5);
478*3833Sxw161283
479*3833Sxw161283 while (n--) {
480*3833Sxw161283 t1_write_reg_4(adap, A_MC5_DBGI_REQ_ADDR0, start++);
481*3833Sxw161283 if (mc5_cmd_write(adap, read_cmd)) {
482*3833Sxw161283 /* err = -EIO; */
483*3833Sxw161283 break;
484*3833Sxw161283 }
485*3833Sxw161283 dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
486*3833Sxw161283 buf += 3;
487*3833Sxw161283 }
488*3833Sxw161283
489*3833Sxw161283 mc5_dbgi_mode_disable(mc5);
490*3833Sxw161283 return 0;
491*3833Sxw161283 }
492*3833Sxw161283
493*3833Sxw161283 #define MC5_INT_MASK (F_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR | \
494*3833Sxw161283 F_MC5_INT_HIT_IN_RT_REGION_ERR | F_MC5_INT_LIP0_ERR | \
495*3833Sxw161283 F_MC5_INT_LIP_MISS_ERR | F_MC5_INT_PARITY_ERR | \
496*3833Sxw161283 F_MC5_INT_ACTIVE_REGION_FULL | F_MC5_INT_NFA_SRCH_ERR | \
497*3833Sxw161283 F_MC5_INT_UNKNOWN_CMD | F_MC5_INT_DEL_ACT_EMPTY)
498*3833Sxw161283 #define MC5_INT_FATAL (F_MC5_INT_PARITY_ERR | F_MC5_INT_REQUESTQ_PARITY_ERR | \
499*3833Sxw161283 F_MC5_INT_DISPATCHQ_PARITY_ERR)
500*3833Sxw161283
t1_mc5_intr_enable(struct pemc5 * mc5)501*3833Sxw161283 void t1_mc5_intr_enable(struct pemc5 *mc5)
502*3833Sxw161283 {
503*3833Sxw161283 u32 mask = MC5_INT_MASK;
504*3833Sxw161283
505*3833Sxw161283 if (!mc5->parity_enabled)
506*3833Sxw161283 mask &= ~F_MC5_INT_PARITY_ERR;
507*3833Sxw161283
508*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
509*3833Sxw161283 if (!t1_is_asic(mc5->adapter)) {
510*3833Sxw161283 /*
511*3833Sxw161283 * Enable child block for MC5.
512*3833Sxw161283 *
513*3833Sxw161283 * NOTE: Assumes TP parent interrupt block is enabled.
514*3833Sxw161283 * MC5 requires TP parent block to be enabled.
515*3833Sxw161283 */
516*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_INT_ENABLE, mask);
517*3833Sxw161283 } else
518*3833Sxw161283 #endif
519*3833Sxw161283 {
520*3833Sxw161283 u32 pl_intr = t1_read_reg_4(mc5->adapter, A_PL_ENABLE);
521*3833Sxw161283
522*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_PL_ENABLE,
523*3833Sxw161283 pl_intr | F_PL_INTR_MC5);
524*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_INT_ENABLE,
525*3833Sxw161283 mask | F_MC5_INT_REQUESTQ_PARITY_ERR |
526*3833Sxw161283 F_MC5_INT_DISPATCHQ_PARITY_ERR);
527*3833Sxw161283 }
528*3833Sxw161283 }
529*3833Sxw161283
t1_mc5_intr_disable(struct pemc5 * mc5)530*3833Sxw161283 void t1_mc5_intr_disable(struct pemc5 *mc5)
531*3833Sxw161283 {
532*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
533*3833Sxw161283 if (!t1_is_asic(mc5->adapter))
534*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_INT_ENABLE, 0);
535*3833Sxw161283 else
536*3833Sxw161283 #endif
537*3833Sxw161283 {
538*3833Sxw161283 u32 pl_intr = t1_read_reg_4(mc5->adapter, A_PL_ENABLE);
539*3833Sxw161283
540*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_PL_ENABLE,
541*3833Sxw161283 pl_intr & ~F_PL_INTR_MC5);
542*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_INT_ENABLE, 0);
543*3833Sxw161283 }
544*3833Sxw161283 }
545*3833Sxw161283
t1_mc5_intr_clear(struct pemc5 * mc5)546*3833Sxw161283 void t1_mc5_intr_clear(struct pemc5 *mc5)
547*3833Sxw161283 {
548*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
549*3833Sxw161283 if (!t1_is_asic(mc5->adapter)) {
550*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_INT_CAUSE, 0xffffffff);
551*3833Sxw161283 } else
552*3833Sxw161283 #endif
553*3833Sxw161283 {
554*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_PL_CAUSE, F_PL_INTR_MC5);
555*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_INT_CAUSE, 0xffffffff);
556*3833Sxw161283 }
557*3833Sxw161283 }
558*3833Sxw161283
559*3833Sxw161283 /*
560*3833Sxw161283 * We don't really do anything with MC5 interrupts, just record them.
561*3833Sxw161283 */
t1_mc5_intr_handler(struct pemc5 * mc5)562*3833Sxw161283 void t1_mc5_intr_handler(struct pemc5 *mc5)
563*3833Sxw161283 {
564*3833Sxw161283 adapter_t *adap = mc5->adapter;
565*3833Sxw161283 u32 cause = t1_read_reg_4(adap, A_MC5_INT_CAUSE);
566*3833Sxw161283
567*3833Sxw161283 if (cause & F_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR)
568*3833Sxw161283 mc5->intr_counts.hit_out_active_region_err++;
569*3833Sxw161283
570*3833Sxw161283 if (cause & F_MC5_INT_HIT_IN_ACTIVE_REGION_ERR)
571*3833Sxw161283 mc5->intr_counts.hit_in_active_region_err++;
572*3833Sxw161283
573*3833Sxw161283 if (cause & F_MC5_INT_HIT_IN_RT_REGION_ERR)
574*3833Sxw161283 mc5->intr_counts.hit_in_routing_region_err++;
575*3833Sxw161283
576*3833Sxw161283 if (cause & F_MC5_INT_MISS_ERR)
577*3833Sxw161283 mc5->intr_counts.miss_err++;
578*3833Sxw161283
579*3833Sxw161283 if (cause & F_MC5_INT_LIP0_ERR)
580*3833Sxw161283 mc5->intr_counts.lip_equal_zero_err++;
581*3833Sxw161283
582*3833Sxw161283 if (cause & F_MC5_INT_LIP_MISS_ERR)
583*3833Sxw161283 mc5->intr_counts.lip_miss_err++;
584*3833Sxw161283
585*3833Sxw161283 if ((cause & F_MC5_INT_PARITY_ERR) && mc5->parity_enabled) {
586*3833Sxw161283 CH_ALERT("%s: MC5 parity error\n", adapter_name(adap));
587*3833Sxw161283 mc5->intr_counts.parity_err++;
588*3833Sxw161283 }
589*3833Sxw161283
590*3833Sxw161283 if (cause & F_MC5_INT_ACTIVE_REGION_FULL)
591*3833Sxw161283 mc5->intr_counts.active_region_full_err++;
592*3833Sxw161283
593*3833Sxw161283 if (cause & F_MC5_INT_NFA_SRCH_ERR)
594*3833Sxw161283 mc5->intr_counts.next_free_addr_srch_err++;
595*3833Sxw161283
596*3833Sxw161283 if (cause & F_MC5_INT_SYN_COOKIE)
597*3833Sxw161283 mc5->intr_counts.syn_cookie++;
598*3833Sxw161283
599*3833Sxw161283 if (cause & F_MC5_INT_SYN_COOKIE_BAD)
600*3833Sxw161283 mc5->intr_counts.syn_cookie_bad_message++;
601*3833Sxw161283
602*3833Sxw161283 if (cause & F_MC5_INT_SYN_COOKIE_OFF)
603*3833Sxw161283 mc5->intr_counts.syn_cookie_off_message++;
604*3833Sxw161283
605*3833Sxw161283 if (cause & F_MC5_INT_UNKNOWN_CMD)
606*3833Sxw161283 mc5->intr_counts.receive_unknown_cmd++;
607*3833Sxw161283
608*3833Sxw161283 if (cause & F_MC5_INT_REQUESTQ_PARITY_ERR) {
609*3833Sxw161283 CH_ALERT("%s: MC5 request queue parity error\n",
610*3833Sxw161283 adapter_name(adap));
611*3833Sxw161283 mc5->intr_counts.parity_in_request_q_err++;
612*3833Sxw161283 }
613*3833Sxw161283
614*3833Sxw161283 if (cause & F_MC5_INT_DISPATCHQ_PARITY_ERR) {
615*3833Sxw161283 CH_ALERT("%s: MC5 dispatch queue parity error\n",
616*3833Sxw161283 adapter_name(adap));
617*3833Sxw161283 mc5->intr_counts.parity_in_dispatch_q_err++;
618*3833Sxw161283 }
619*3833Sxw161283
620*3833Sxw161283 if (cause & F_MC5_INT_DEL_ACT_EMPTY)
621*3833Sxw161283 mc5->intr_counts.del_and_act_is_empty++;
622*3833Sxw161283
623*3833Sxw161283 if (cause & MC5_INT_FATAL)
624*3833Sxw161283 t1_fatal_err(adap);
625*3833Sxw161283
626*3833Sxw161283 t1_write_reg_4(adap, A_MC5_INT_CAUSE, cause);
627*3833Sxw161283 }
628*3833Sxw161283
t1_mc5_get_intr_counts(struct pemc5 * mc5)629*3833Sxw161283 const struct pemc5_intr_counts *t1_mc5_get_intr_counts(struct pemc5 *mc5)
630*3833Sxw161283 {
631*3833Sxw161283 return &mc5->intr_counts;
632*3833Sxw161283 }
633*3833Sxw161283
t1_mc5_create(adapter_t * adapter,int mode)634*3833Sxw161283 struct pemc5 * __devinit t1_mc5_create(adapter_t *adapter, int mode)
635*3833Sxw161283 {
636*3833Sxw161283 struct pemc5 *mc5;
637*3833Sxw161283 u32 cfg, bits_per_entry;
638*3833Sxw161283
639*3833Sxw161283 if (mode != MC5_MODE_144_BIT && mode != MC5_MODE_72_BIT)
640*3833Sxw161283 return NULL;
641*3833Sxw161283
642*3833Sxw161283 mc5 = t1_os_malloc_wait_zero(sizeof(*mc5));
643*3833Sxw161283 if (!mc5) return NULL;
644*3833Sxw161283
645*3833Sxw161283 mc5->adapter = adapter;
646*3833Sxw161283 mc5->mode = (unsigned char) mode;
647*3833Sxw161283
648*3833Sxw161283 cfg = t1_read_reg_4(adapter, A_MC5_CONFIG);
649*3833Sxw161283 mc5->part_size = G_TCAM_PART_SIZE(cfg);
650*3833Sxw161283 mc5->part_type = (unsigned char) G_TCAM_PART_TYPE(cfg);
651*3833Sxw161283 if (cfg & F_TCAM_PART_TYPE_HI)
652*3833Sxw161283 mc5->part_type |= 4;
653*3833Sxw161283
654*3833Sxw161283 /*
655*3833Sxw161283 * Calculate the size of the TCAM based on the total memory, mode, and
656*3833Sxw161283 * count information retrieved from the hardware.
657*3833Sxw161283 */
658*3833Sxw161283 bits_per_entry = mode == MC5_MODE_144_BIT ? 144 : 72;
659*3833Sxw161283 mc5->tcam_size = tcam_part_size[mc5->part_size] / bits_per_entry;
660*3833Sxw161283
661*3833Sxw161283 return mc5;
662*3833Sxw161283 }
663*3833Sxw161283
t1_mc5_destroy(struct pemc5 * mc5)664*3833Sxw161283 void t1_mc5_destroy(struct pemc5 *mc5)
665*3833Sxw161283 {
666*3833Sxw161283 t1_os_free((void *)mc5, sizeof(*mc5));
667*3833Sxw161283 }
668*3833Sxw161283
669*3833Sxw161283 #ifdef SUPPORT_MODE72
mc5_cmp(const void * pi,const void * pj)670*3833Sxw161283 static int mc5_cmp(const void *pi, const void *pj)
671*3833Sxw161283 {
672*3833Sxw161283 const u32 *pii = (const u32 *)pi;
673*3833Sxw161283 const u32 *pjj = (const u32 *)pj;
674*3833Sxw161283
675*3833Sxw161283 if (*pii < *pjj)
676*3833Sxw161283 return -1;
677*3833Sxw161283
678*3833Sxw161283 return *pii > *pjj;
679*3833Sxw161283 }
680*3833Sxw161283
681*3833Sxw161283 /*
682*3833Sxw161283 * DESC: Write local IP addresses to the TCAM
683*3833Sxw161283 *
684*3833Sxw161283 * NOTES: IP addresses should be in host byte order. So, an IP address:
685*3833Sxw161283 * of 10.0.0.140 == (data = 0x0A00008C)
686*3833Sxw161283 */
mc5_set_lip_entries(struct pemc5 * mc5,u32 * p,int num_of_lip_addresses)687*3833Sxw161283 static int mc5_set_lip_entries(struct pemc5 *mc5, u32 *p,
688*3833Sxw161283 int num_of_lip_addresses)
689*3833Sxw161283 {
690*3833Sxw161283 int i;
691*3833Sxw161283
692*3833Sxw161283 /*
693*3833Sxw161283 * Disable compression and M bus mode so that the TP core
694*3833Sxw161283 * doesn't access the TCAM while we are writing.
695*3833Sxw161283 */
696*3833Sxw161283 u32 cfg = t1_read_reg_4(mc5->adapter, A_MC5_CONFIG);
697*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_CONFIG,
698*3833Sxw161283 cfg & ~(F_M_BUS_ENABLE | F_COMPRESSION_ENABLE));
699*3833Sxw161283
700*3833Sxw161283 /* MC5 should now be ready to program the LIP addresses. */
701*3833Sxw161283 for (i = 0; i < num_of_lip_addresses; i++) {
702*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_LIP_RAM_DATA, p[i]);
703*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_LIP_RAM_ADDR, 0x100 + i);
704*3833Sxw161283 }
705*3833Sxw161283
706*3833Sxw161283 /* Restore MC5 mode. */
707*3833Sxw161283 t1_write_reg_4(mc5->adapter, A_MC5_CONFIG, cfg | F_COMPRESSION_ENABLE);
708*3833Sxw161283 return 0;
709*3833Sxw161283 }
710*3833Sxw161283
711*3833Sxw161283 /*
712*3833Sxw161283 * The purpose of this routine is to write all of the local IP addresses
713*3833Sxw161283 * into the TCAM in sorted order. This is a requirement from the TCAM.
714*3833Sxw161283 */
t1_mc5_lip_write_entries(struct pemc5 * mc5)715*3833Sxw161283 void t1_mc5_lip_write_entries(struct pemc5 *mc5)
716*3833Sxw161283 {
717*3833Sxw161283 u32 filler = 0;
718*3833Sxw161283 int i;
719*3833Sxw161283
720*3833Sxw161283 if (mc5->lip_index) {
721*3833Sxw161283 qsort(mc5->lip, mc5->lip_index, sizeof(u32), mc5_cmp);
722*3833Sxw161283 filler = mc5->lip[mc5->lip_index - 1];
723*3833Sxw161283 }
724*3833Sxw161283 for (i = mc5->lip_index; i < MC5_LIP_NUM_OF_ENTRIES; i++)
725*3833Sxw161283 mc5->lip[i] = filler;
726*3833Sxw161283 mc5_set_lip_entries(mc5, mc5->lip, MC5_LIP_NUM_OF_ENTRIES);
727*3833Sxw161283 }
728*3833Sxw161283
t1_mc5_lip_clear_entries(struct pemc5 * mc5)729*3833Sxw161283 void t1_mc5_lip_clear_entries(struct pemc5 *mc5)
730*3833Sxw161283 {
731*3833Sxw161283 mc5->lip_index = 0;
732*3833Sxw161283 }
733*3833Sxw161283
734*3833Sxw161283 /*
735*3833Sxw161283 * Add a local IP address to the LIP table.
736*3833Sxw161283 */
t1_mc5_lip_add_entry(struct pemc5 * mc5,u32 lip)737*3833Sxw161283 int t1_mc5_lip_add_entry(struct pemc5 *mc5, u32 lip)
738*3833Sxw161283 {
739*3833Sxw161283 if (mc5->lip_index >= MC5_LIP_NUM_OF_ENTRIES) return 1;
740*3833Sxw161283 mc5->lip[mc5->lip_index++] = lip;
741*3833Sxw161283 return 0;
742*3833Sxw161283 }
743*3833Sxw161283 #endif
744