diff options
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_init.h')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_init.h | 567 |
1 files changed, 567 insertions, 0 deletions
diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h new file mode 100644 index 00000000000..4d748e77d1a --- /dev/null +++ b/drivers/net/bnx2x/bnx2x_init.h | |||
@@ -0,0 +1,567 @@ | |||
1 | /* bnx2x_init.h: Broadcom Everest network driver. | ||
2 | * Structures and macroes needed during the initialization. | ||
3 | * | ||
4 | * Copyright (c) 2007-2011 Broadcom Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | ||
11 | * Written by: Eliezer Tamir | ||
12 | * Modified by: Vladislav Zolotarov <vladz@broadcom.com> | ||
13 | */ | ||
14 | |||
15 | #ifndef BNX2X_INIT_H | ||
16 | #define BNX2X_INIT_H | ||
17 | |||
18 | /* Init operation types and structures */ | ||
19 | enum { | ||
20 | OP_RD = 0x1, /* read a single register */ | ||
21 | OP_WR, /* write a single register */ | ||
22 | OP_SW, /* copy a string to the device */ | ||
23 | OP_ZR, /* clear memory */ | ||
24 | OP_ZP, /* unzip then copy with DMAE */ | ||
25 | OP_WR_64, /* write 64 bit pattern */ | ||
26 | OP_WB, /* copy a string using DMAE */ | ||
27 | OP_WB_ZR, /* Clear a string using DMAE or indirect-wr */ | ||
28 | /* Skip the following ops if all of the init modes don't match */ | ||
29 | OP_IF_MODE_OR, | ||
30 | /* Skip the following ops if any of the init modes don't match */ | ||
31 | OP_IF_MODE_AND, | ||
32 | OP_MAX | ||
33 | }; | ||
34 | |||
35 | enum { | ||
36 | STAGE_START, | ||
37 | STAGE_END, | ||
38 | }; | ||
39 | |||
40 | /* Returns the index of start or end of a specific block stage in ops array*/ | ||
41 | #define BLOCK_OPS_IDX(block, stage, end) \ | ||
42 | (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end)) | ||
43 | |||
44 | |||
45 | /* structs for the various opcodes */ | ||
46 | struct raw_op { | ||
47 | u32 op:8; | ||
48 | u32 offset:24; | ||
49 | u32 raw_data; | ||
50 | }; | ||
51 | |||
52 | struct op_read { | ||
53 | u32 op:8; | ||
54 | u32 offset:24; | ||
55 | u32 val; | ||
56 | }; | ||
57 | |||
58 | struct op_write { | ||
59 | u32 op:8; | ||
60 | u32 offset:24; | ||
61 | u32 val; | ||
62 | }; | ||
63 | |||
64 | struct op_arr_write { | ||
65 | u32 op:8; | ||
66 | u32 offset:24; | ||
67 | #ifdef __BIG_ENDIAN | ||
68 | u16 data_len; | ||
69 | u16 data_off; | ||
70 | #else /* __LITTLE_ENDIAN */ | ||
71 | u16 data_off; | ||
72 | u16 data_len; | ||
73 | #endif | ||
74 | }; | ||
75 | |||
76 | struct op_zero { | ||
77 | u32 op:8; | ||
78 | u32 offset:24; | ||
79 | u32 len; | ||
80 | }; | ||
81 | |||
82 | struct op_if_mode { | ||
83 | u32 op:8; | ||
84 | u32 cmd_offset:24; | ||
85 | u32 mode_bit_map; | ||
86 | }; | ||
87 | |||
88 | |||
89 | union init_op { | ||
90 | struct op_read read; | ||
91 | struct op_write write; | ||
92 | struct op_arr_write arr_wr; | ||
93 | struct op_zero zero; | ||
94 | struct raw_op raw; | ||
95 | struct op_if_mode if_mode; | ||
96 | }; | ||
97 | |||
98 | |||
99 | /* Init Phases */ | ||
100 | enum { | ||
101 | PHASE_COMMON, | ||
102 | PHASE_PORT0, | ||
103 | PHASE_PORT1, | ||
104 | PHASE_PF0, | ||
105 | PHASE_PF1, | ||
106 | PHASE_PF2, | ||
107 | PHASE_PF3, | ||
108 | PHASE_PF4, | ||
109 | PHASE_PF5, | ||
110 | PHASE_PF6, | ||
111 | PHASE_PF7, | ||
112 | NUM_OF_INIT_PHASES | ||
113 | }; | ||
114 | |||
115 | /* Init Modes */ | ||
116 | enum { | ||
117 | MODE_ASIC = 0x00000001, | ||
118 | MODE_FPGA = 0x00000002, | ||
119 | MODE_EMUL = 0x00000004, | ||
120 | MODE_E2 = 0x00000008, | ||
121 | MODE_E3 = 0x00000010, | ||
122 | MODE_PORT2 = 0x00000020, | ||
123 | MODE_PORT4 = 0x00000040, | ||
124 | MODE_SF = 0x00000080, | ||
125 | MODE_MF = 0x00000100, | ||
126 | MODE_MF_SD = 0x00000200, | ||
127 | MODE_MF_SI = 0x00000400, | ||
128 | MODE_MF_NIV = 0x00000800, | ||
129 | MODE_E3_A0 = 0x00001000, | ||
130 | MODE_E3_B0 = 0x00002000, | ||
131 | MODE_COS3 = 0x00004000, | ||
132 | MODE_COS6 = 0x00008000, | ||
133 | MODE_LITTLE_ENDIAN = 0x00010000, | ||
134 | MODE_BIG_ENDIAN = 0x00020000, | ||
135 | }; | ||
136 | |||
137 | /* Init Blocks */ | ||
138 | enum { | ||
139 | BLOCK_ATC, | ||
140 | BLOCK_BRB1, | ||
141 | BLOCK_CCM, | ||
142 | BLOCK_CDU, | ||
143 | BLOCK_CFC, | ||
144 | BLOCK_CSDM, | ||
145 | BLOCK_CSEM, | ||
146 | BLOCK_DBG, | ||
147 | BLOCK_DMAE, | ||
148 | BLOCK_DORQ, | ||
149 | BLOCK_HC, | ||
150 | BLOCK_IGU, | ||
151 | BLOCK_MISC, | ||
152 | BLOCK_NIG, | ||
153 | BLOCK_PBF, | ||
154 | BLOCK_PGLUE_B, | ||
155 | BLOCK_PRS, | ||
156 | BLOCK_PXP2, | ||
157 | BLOCK_PXP, | ||
158 | BLOCK_QM, | ||
159 | BLOCK_SRC, | ||
160 | BLOCK_TCM, | ||
161 | BLOCK_TM, | ||
162 | BLOCK_TSDM, | ||
163 | BLOCK_TSEM, | ||
164 | BLOCK_UCM, | ||
165 | BLOCK_UPB, | ||
166 | BLOCK_USDM, | ||
167 | BLOCK_USEM, | ||
168 | BLOCK_XCM, | ||
169 | BLOCK_XPB, | ||
170 | BLOCK_XSDM, | ||
171 | BLOCK_XSEM, | ||
172 | BLOCK_MISC_AEU, | ||
173 | NUM_OF_INIT_BLOCKS | ||
174 | }; | ||
175 | |||
176 | /* QM queue numbers */ | ||
177 | #define BNX2X_ETH_Q 0 | ||
178 | #define BNX2X_TOE_Q 3 | ||
179 | #define BNX2X_TOE_ACK_Q 6 | ||
180 | #define BNX2X_ISCSI_Q 9 | ||
181 | #define BNX2X_ISCSI_ACK_Q 11 | ||
182 | #define BNX2X_FCOE_Q 10 | ||
183 | |||
184 | /* Vnics per mode */ | ||
185 | #define BNX2X_PORT2_MODE_NUM_VNICS 4 | ||
186 | #define BNX2X_PORT4_MODE_NUM_VNICS 2 | ||
187 | |||
188 | /* COS offset for port1 in E3 B0 4port mode */ | ||
189 | #define BNX2X_E3B0_PORT1_COS_OFFSET 3 | ||
190 | |||
191 | /* QM Register addresses */ | ||
192 | #define BNX2X_Q_VOQ_REG_ADDR(pf_q_num)\ | ||
193 | (QM_REG_QVOQIDX_0 + 4 * (pf_q_num)) | ||
194 | #define BNX2X_VOQ_Q_REG_ADDR(cos, pf_q_num)\ | ||
195 | (QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5))) | ||
196 | #define BNX2X_Q_CMDQ_REG_ADDR(pf_q_num)\ | ||
197 | (QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4)) | ||
198 | |||
199 | /* extracts the QM queue number for the specified port and vnic */ | ||
200 | #define BNX2X_PF_Q_NUM(q_num, port, vnic)\ | ||
201 | ((((port) << 1) | (vnic)) * 16 + (q_num)) | ||
202 | |||
203 | |||
204 | /* Maps the specified queue to the specified COS */ | ||
205 | static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos) | ||
206 | { | ||
207 | /* find current COS mapping */ | ||
208 | u32 curr_cos = REG_RD(bp, QM_REG_QVOQIDX_0 + q_num * 4); | ||
209 | |||
210 | /* check if queue->COS mapping has changed */ | ||
211 | if (curr_cos != new_cos) { | ||
212 | u32 num_vnics = BNX2X_PORT2_MODE_NUM_VNICS; | ||
213 | u32 reg_addr, reg_bit_map, vnic; | ||
214 | |||
215 | /* update parameters for 4port mode */ | ||
216 | if (INIT_MODE_FLAGS(bp) & MODE_PORT4) { | ||
217 | num_vnics = BNX2X_PORT4_MODE_NUM_VNICS; | ||
218 | if (BP_PORT(bp)) { | ||
219 | curr_cos += BNX2X_E3B0_PORT1_COS_OFFSET; | ||
220 | new_cos += BNX2X_E3B0_PORT1_COS_OFFSET; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | /* change queue mapping for each VNIC */ | ||
225 | for (vnic = 0; vnic < num_vnics; vnic++) { | ||
226 | u32 pf_q_num = | ||
227 | BNX2X_PF_Q_NUM(q_num, BP_PORT(bp), vnic); | ||
228 | u32 q_bit_map = 1 << (pf_q_num & 0x1f); | ||
229 | |||
230 | /* overwrite queue->VOQ mapping */ | ||
231 | REG_WR(bp, BNX2X_Q_VOQ_REG_ADDR(pf_q_num), new_cos); | ||
232 | |||
233 | /* clear queue bit from current COS bit map */ | ||
234 | reg_addr = BNX2X_VOQ_Q_REG_ADDR(curr_cos, pf_q_num); | ||
235 | reg_bit_map = REG_RD(bp, reg_addr); | ||
236 | REG_WR(bp, reg_addr, reg_bit_map & (~q_bit_map)); | ||
237 | |||
238 | /* set queue bit in new COS bit map */ | ||
239 | reg_addr = BNX2X_VOQ_Q_REG_ADDR(new_cos, pf_q_num); | ||
240 | reg_bit_map = REG_RD(bp, reg_addr); | ||
241 | REG_WR(bp, reg_addr, reg_bit_map | q_bit_map); | ||
242 | |||
243 | /* set/clear queue bit in command-queue bit map | ||
244 | (E2/E3A0 only, valid COS values are 0/1) */ | ||
245 | if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) { | ||
246 | reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num); | ||
247 | reg_bit_map = REG_RD(bp, reg_addr); | ||
248 | q_bit_map = 1 << (2 * (pf_q_num & 0xf)); | ||
249 | reg_bit_map = new_cos ? | ||
250 | (reg_bit_map | q_bit_map) : | ||
251 | (reg_bit_map & (~q_bit_map)); | ||
252 | REG_WR(bp, reg_addr, reg_bit_map); | ||
253 | } | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | |||
258 | /* Configures the QM according to the specified per-traffic-type COSes */ | ||
259 | static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode, | ||
260 | struct priority_cos *traffic_cos) | ||
261 | { | ||
262 | bnx2x_map_q_cos(bp, BNX2X_FCOE_Q, | ||
263 | traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos); | ||
264 | bnx2x_map_q_cos(bp, BNX2X_ISCSI_Q, | ||
265 | traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); | ||
266 | bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q, | ||
267 | traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); | ||
268 | if (mode != STATIC_COS) { | ||
269 | /* required only in backward compatible COS mode */ | ||
270 | bnx2x_map_q_cos(bp, BNX2X_ETH_Q, | ||
271 | traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); | ||
272 | bnx2x_map_q_cos(bp, BNX2X_TOE_Q, | ||
273 | traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); | ||
274 | bnx2x_map_q_cos(bp, BNX2X_TOE_ACK_Q, | ||
275 | traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | |||
280 | /* Returns the index of start or end of a specific block stage in ops array*/ | ||
281 | #define BLOCK_OPS_IDX(block, stage, end) \ | ||
282 | (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end)) | ||
283 | |||
284 | |||
285 | #define INITOP_SET 0 /* set the HW directly */ | ||
286 | #define INITOP_CLEAR 1 /* clear the HW directly */ | ||
287 | #define INITOP_INIT 2 /* set the init-value array */ | ||
288 | |||
289 | /**************************************************************************** | ||
290 | * ILT management | ||
291 | ****************************************************************************/ | ||
292 | struct ilt_line { | ||
293 | dma_addr_t page_mapping; | ||
294 | void *page; | ||
295 | u32 size; | ||
296 | }; | ||
297 | |||
298 | struct ilt_client_info { | ||
299 | u32 page_size; | ||
300 | u16 start; | ||
301 | u16 end; | ||
302 | u16 client_num; | ||
303 | u16 flags; | ||
304 | #define ILT_CLIENT_SKIP_INIT 0x1 | ||
305 | #define ILT_CLIENT_SKIP_MEM 0x2 | ||
306 | }; | ||
307 | |||
308 | struct bnx2x_ilt { | ||
309 | u32 start_line; | ||
310 | struct ilt_line *lines; | ||
311 | struct ilt_client_info clients[4]; | ||
312 | #define ILT_CLIENT_CDU 0 | ||
313 | #define ILT_CLIENT_QM 1 | ||
314 | #define ILT_CLIENT_SRC 2 | ||
315 | #define ILT_CLIENT_TM 3 | ||
316 | }; | ||
317 | |||
318 | /**************************************************************************** | ||
319 | * SRC configuration | ||
320 | ****************************************************************************/ | ||
321 | struct src_ent { | ||
322 | u8 opaque[56]; | ||
323 | u64 next; | ||
324 | }; | ||
325 | |||
326 | /**************************************************************************** | ||
327 | * Parity configuration | ||
328 | ****************************************************************************/ | ||
329 | #define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2, m3) \ | ||
330 | { \ | ||
331 | block##_REG_##block##_PRTY_MASK, \ | ||
332 | block##_REG_##block##_PRTY_STS_CLR, \ | ||
333 | en_mask, {m1, m1h, m2, m3}, #block \ | ||
334 | } | ||
335 | |||
336 | #define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2, m3) \ | ||
337 | { \ | ||
338 | block##_REG_##block##_PRTY_MASK_0, \ | ||
339 | block##_REG_##block##_PRTY_STS_CLR_0, \ | ||
340 | en_mask, {m1, m1h, m2, m3}, #block"_0" \ | ||
341 | } | ||
342 | |||
343 | #define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2, m3) \ | ||
344 | { \ | ||
345 | block##_REG_##block##_PRTY_MASK_1, \ | ||
346 | block##_REG_##block##_PRTY_STS_CLR_1, \ | ||
347 | en_mask, {m1, m1h, m2, m3}, #block"_1" \ | ||
348 | } | ||
349 | |||
350 | static const struct { | ||
351 | u32 mask_addr; | ||
352 | u32 sts_clr_addr; | ||
353 | u32 en_mask; /* Mask to enable parity attentions */ | ||
354 | struct { | ||
355 | u32 e1; /* 57710 */ | ||
356 | u32 e1h; /* 57711 */ | ||
357 | u32 e2; /* 57712 */ | ||
358 | u32 e3; /* 578xx */ | ||
359 | } reg_mask; /* Register mask (all valid bits) */ | ||
360 | char name[7]; /* Block's longest name is 6 characters long | ||
361 | * (name + suffix) | ||
362 | */ | ||
363 | } bnx2x_blocks_parity_data[] = { | ||
364 | /* bit 19 masked */ | ||
365 | /* REG_WR(bp, PXP_REG_PXP_PRTY_MASK, 0x80000); */ | ||
366 | /* bit 5,18,20-31 */ | ||
367 | /* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_0, 0xfff40020); */ | ||
368 | /* bit 5 */ | ||
369 | /* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_1, 0x20); */ | ||
370 | /* REG_WR(bp, HC_REG_HC_PRTY_MASK, 0x0); */ | ||
371 | /* REG_WR(bp, MISC_REG_MISC_PRTY_MASK, 0x0); */ | ||
372 | |||
373 | /* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't | ||
374 | * want to handle "system kill" flow at the moment. | ||
375 | */ | ||
376 | BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff, | ||
377 | 0x7ffffff), | ||
378 | BLOCK_PRTY_INFO_0(PXP2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
379 | 0xffffffff), | ||
380 | BLOCK_PRTY_INFO_1(PXP2, 0x1ffffff, 0x7f, 0x7f, 0x7ff, 0x1ffffff), | ||
381 | BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0, 0), | ||
382 | BLOCK_PRTY_INFO(NIG, 0xffffffff, 0x3fffffff, 0xffffffff, 0, 0), | ||
383 | BLOCK_PRTY_INFO_0(NIG, 0xffffffff, 0, 0, 0xffffffff, 0xffffffff), | ||
384 | BLOCK_PRTY_INFO_1(NIG, 0xffff, 0, 0, 0xff, 0xffff), | ||
385 | BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff, 0x7ff), | ||
386 | BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1, 0x1), | ||
387 | BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff, 0xfff), | ||
388 | BLOCK_PRTY_INFO(ATC, 0x1f, 0, 0, 0x1f, 0x1f), | ||
389 | BLOCK_PRTY_INFO(PGLUE_B, 0x3, 0, 0, 0x3, 0x3), | ||
390 | BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3, 0x3), | ||
391 | {GRCBASE_UPB + PB_REG_PB_PRTY_MASK, | ||
392 | GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf, | ||
393 | {0xf, 0xf, 0xf, 0xf}, "UPB"}, | ||
394 | {GRCBASE_XPB + PB_REG_PB_PRTY_MASK, | ||
395 | GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0, | ||
396 | {0xf, 0xf, 0xf, 0xf}, "XPB"}, | ||
397 | BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7, 0x7), | ||
398 | BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f, 0x1f), | ||
399 | BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf, 0x3f), | ||
400 | BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1, 0x1), | ||
401 | BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf, 0xf), | ||
402 | BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf, 0xf), | ||
403 | BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff, 0xff), | ||
404 | BLOCK_PRTY_INFO(PBF, 0, 0, 0x3ffff, 0xfffff, 0xfffffff), | ||
405 | BLOCK_PRTY_INFO(TM, 0, 0, 0x7f, 0x7f, 0x7f), | ||
406 | BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff, 0x7ff), | ||
407 | BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff), | ||
408 | BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff, 0x7ff), | ||
409 | BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff), | ||
410 | BLOCK_PRTY_INFO(TCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), | ||
411 | BLOCK_PRTY_INFO(CCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), | ||
412 | BLOCK_PRTY_INFO(UCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), | ||
413 | BLOCK_PRTY_INFO(XCM, 0, 0, 0x3fffffff, 0x3fffffff, 0x3fffffff), | ||
414 | BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff, | ||
415 | 0xffffffff), | ||
416 | BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f, 0x3f), | ||
417 | BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff, | ||
418 | 0xffffffff), | ||
419 | BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f, 0x1f), | ||
420 | BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff, | ||
421 | 0xffffffff), | ||
422 | BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f, 0x1f), | ||
423 | BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff, | ||
424 | 0xffffffff), | ||
425 | BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f, 0x3f), | ||
426 | }; | ||
427 | |||
428 | |||
429 | /* [28] MCP Latched rom_parity | ||
430 | * [29] MCP Latched ump_rx_parity | ||
431 | * [30] MCP Latched ump_tx_parity | ||
432 | * [31] MCP Latched scpad_parity | ||
433 | */ | ||
434 | #define MISC_AEU_ENABLE_MCP_PRTY_BITS \ | ||
435 | (AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \ | ||
436 | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \ | ||
437 | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \ | ||
438 | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY) | ||
439 | |||
440 | /* Below registers control the MCP parity attention output. When | ||
441 | * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are | ||
442 | * enabled, when cleared - disabled. | ||
443 | */ | ||
444 | static const u32 mcp_attn_ctl_regs[] = { | ||
445 | MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, | ||
446 | MISC_REG_AEU_ENABLE4_NIG_0, | ||
447 | MISC_REG_AEU_ENABLE4_PXP_0, | ||
448 | MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, | ||
449 | MISC_REG_AEU_ENABLE4_NIG_1, | ||
450 | MISC_REG_AEU_ENABLE4_PXP_1 | ||
451 | }; | ||
452 | |||
453 | static inline void bnx2x_set_mcp_parity(struct bnx2x *bp, u8 enable) | ||
454 | { | ||
455 | int i; | ||
456 | u32 reg_val; | ||
457 | |||
458 | for (i = 0; i < ARRAY_SIZE(mcp_attn_ctl_regs); i++) { | ||
459 | reg_val = REG_RD(bp, mcp_attn_ctl_regs[i]); | ||
460 | |||
461 | if (enable) | ||
462 | reg_val |= MISC_AEU_ENABLE_MCP_PRTY_BITS; | ||
463 | else | ||
464 | reg_val &= ~MISC_AEU_ENABLE_MCP_PRTY_BITS; | ||
465 | |||
466 | REG_WR(bp, mcp_attn_ctl_regs[i], reg_val); | ||
467 | } | ||
468 | } | ||
469 | |||
470 | static inline u32 bnx2x_parity_reg_mask(struct bnx2x *bp, int idx) | ||
471 | { | ||
472 | if (CHIP_IS_E1(bp)) | ||
473 | return bnx2x_blocks_parity_data[idx].reg_mask.e1; | ||
474 | else if (CHIP_IS_E1H(bp)) | ||
475 | return bnx2x_blocks_parity_data[idx].reg_mask.e1h; | ||
476 | else if (CHIP_IS_E2(bp)) | ||
477 | return bnx2x_blocks_parity_data[idx].reg_mask.e2; | ||
478 | else /* CHIP_IS_E3 */ | ||
479 | return bnx2x_blocks_parity_data[idx].reg_mask.e3; | ||
480 | } | ||
481 | |||
482 | static inline void bnx2x_disable_blocks_parity(struct bnx2x *bp) | ||
483 | { | ||
484 | int i; | ||
485 | |||
486 | for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) { | ||
487 | u32 dis_mask = bnx2x_parity_reg_mask(bp, i); | ||
488 | |||
489 | if (dis_mask) { | ||
490 | REG_WR(bp, bnx2x_blocks_parity_data[i].mask_addr, | ||
491 | dis_mask); | ||
492 | DP(NETIF_MSG_HW, "Setting parity mask " | ||
493 | "for %s to\t\t0x%x\n", | ||
494 | bnx2x_blocks_parity_data[i].name, dis_mask); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | /* Disable MCP parity attentions */ | ||
499 | bnx2x_set_mcp_parity(bp, false); | ||
500 | } | ||
501 | |||
502 | /** | ||
503 | * Clear the parity error status registers. | ||
504 | */ | ||
505 | static inline void bnx2x_clear_blocks_parity(struct bnx2x *bp) | ||
506 | { | ||
507 | int i; | ||
508 | u32 reg_val, mcp_aeu_bits = | ||
509 | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | | ||
510 | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY | | ||
511 | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | | ||
512 | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY; | ||
513 | |||
514 | /* Clear SEM_FAST parities */ | ||
515 | REG_WR(bp, XSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); | ||
516 | REG_WR(bp, TSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); | ||
517 | REG_WR(bp, USEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); | ||
518 | REG_WR(bp, CSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); | ||
519 | |||
520 | for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) { | ||
521 | u32 reg_mask = bnx2x_parity_reg_mask(bp, i); | ||
522 | |||
523 | if (reg_mask) { | ||
524 | reg_val = REG_RD(bp, bnx2x_blocks_parity_data[i]. | ||
525 | sts_clr_addr); | ||
526 | if (reg_val & reg_mask) | ||
527 | DP(NETIF_MSG_HW, | ||
528 | "Parity errors in %s: 0x%x\n", | ||
529 | bnx2x_blocks_parity_data[i].name, | ||
530 | reg_val & reg_mask); | ||
531 | } | ||
532 | } | ||
533 | |||
534 | /* Check if there were parity attentions in MCP */ | ||
535 | reg_val = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_MCP); | ||
536 | if (reg_val & mcp_aeu_bits) | ||
537 | DP(NETIF_MSG_HW, "Parity error in MCP: 0x%x\n", | ||
538 | reg_val & mcp_aeu_bits); | ||
539 | |||
540 | /* Clear parity attentions in MCP: | ||
541 | * [7] clears Latched rom_parity | ||
542 | * [8] clears Latched ump_rx_parity | ||
543 | * [9] clears Latched ump_tx_parity | ||
544 | * [10] clears Latched scpad_parity (both ports) | ||
545 | */ | ||
546 | REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x780); | ||
547 | } | ||
548 | |||
549 | static inline void bnx2x_enable_blocks_parity(struct bnx2x *bp) | ||
550 | { | ||
551 | int i; | ||
552 | |||
553 | for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) { | ||
554 | u32 reg_mask = bnx2x_parity_reg_mask(bp, i); | ||
555 | |||
556 | if (reg_mask) | ||
557 | REG_WR(bp, bnx2x_blocks_parity_data[i].mask_addr, | ||
558 | bnx2x_blocks_parity_data[i].en_mask & reg_mask); | ||
559 | } | ||
560 | |||
561 | /* Enable MCP parity attentions */ | ||
562 | bnx2x_set_mcp_parity(bp, true); | ||
563 | } | ||
564 | |||
565 | |||
566 | #endif /* BNX2X_INIT_H */ | ||
567 | |||