Commit | Line | Data |
---|---|---|
a2fbb9ea | 1 | /* bnx2x_init.h: Broadcom Everest network driver. |
94a78b79 | 2 | * Structures and macroes needed during the initialization. |
a2fbb9ea | 3 | * |
5de92408 | 4 | * Copyright (c) 2007-2011 Broadcom Corporation |
a2fbb9ea ET |
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 | * | |
24e3fcef EG |
10 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> |
11 | * Written by: Eliezer Tamir | |
94a78b79 | 12 | * Modified by: Vladislav Zolotarov <vladz@broadcom.com> |
a2fbb9ea ET |
13 | */ |
14 | ||
15 | #ifndef BNX2X_INIT_H | |
16 | #define BNX2X_INIT_H | |
17 | ||
a2fbb9ea | 18 | /* Init operation types and structures */ |
619c5cb6 VZ |
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 | }; | |
573f2035 | 34 | |
619c5cb6 VZ |
35 | enum { |
36 | STAGE_START, | |
37 | STAGE_END, | |
38 | }; | |
94a78b79 VZ |
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) \ | |
619c5cb6 | 42 | (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end)) |
ad8d3948 | 43 | |
a2fbb9ea | 44 | |
619c5cb6 | 45 | /* structs for the various opcodes */ |
a2fbb9ea | 46 | struct raw_op { |
6378c025 EG |
47 | u32 op:8; |
48 | u32 offset:24; | |
a2fbb9ea ET |
49 | u32 raw_data; |
50 | }; | |
51 | ||
52 | struct op_read { | |
6378c025 EG |
53 | u32 op:8; |
54 | u32 offset:24; | |
619c5cb6 | 55 | u32 val; |
a2fbb9ea ET |
56 | }; |
57 | ||
58 | struct op_write { | |
6378c025 EG |
59 | u32 op:8; |
60 | u32 offset:24; | |
a2fbb9ea ET |
61 | u32 val; |
62 | }; | |
63 | ||
619c5cb6 | 64 | struct op_arr_write { |
6378c025 EG |
65 | u32 op:8; |
66 | u32 offset:24; | |
619c5cb6 | 67 | #ifdef __BIG_ENDIAN |
a2fbb9ea ET |
68 | u16 data_len; |
69 | u16 data_off; | |
619c5cb6 VZ |
70 | #else /* __LITTLE_ENDIAN */ |
71 | u16 data_off; | |
72 | u16 data_len; | |
a2fbb9ea ET |
73 | #endif |
74 | }; | |
75 | ||
76 | struct op_zero { | |
6378c025 EG |
77 | u32 op:8; |
78 | u32 offset:24; | |
a2fbb9ea ET |
79 | u32 len; |
80 | }; | |
81 | ||
619c5cb6 VZ |
82 | struct op_if_mode { |
83 | u32 op:8; | |
84 | u32 cmd_offset:24; | |
85 | u32 mode_bit_map; | |
86 | }; | |
87 | ||
88 | ||
a2fbb9ea ET |
89 | union init_op { |
90 | struct op_read read; | |
91 | struct op_write write; | |
619c5cb6 | 92 | struct op_arr_write arr_wr; |
a2fbb9ea ET |
93 | struct op_zero zero; |
94 | struct raw_op raw; | |
619c5cb6 VZ |
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, | |
6383c0b3 AE |
131 | MODE_COS3 = 0x00004000, |
132 | MODE_COS6 = 0x00008000, | |
133 | MODE_LITTLE_ENDIAN = 0x00010000, | |
134 | MODE_BIG_ENDIAN = 0x00020000, | |
619c5cb6 VZ |
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 | |
a2fbb9ea ET |
174 | }; |
175 | ||
619c5cb6 VZ |
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 | |
6383c0b3 | 181 | #define BNX2X_ISCSI_ACK_Q 11 |
619c5cb6 VZ |
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 */ | |
6383c0b3 | 259 | static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode, |
619c5cb6 VZ |
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); | |
6383c0b3 AE |
266 | bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q, |
267 | traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); | |
268 | if (mode != STATIC_COS) { | |
619c5cb6 VZ |
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); | |
619c5cb6 VZ |
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 | ||
523224a3 DK |
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 | ||
4a33bc03 VZ |
326 | /**************************************************************************** |
327 | * Parity configuration | |
328 | ****************************************************************************/ | |
8736c826 | 329 | #define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2, m3) \ |
4a33bc03 VZ |
330 | { \ |
331 | block##_REG_##block##_PRTY_MASK, \ | |
332 | block##_REG_##block##_PRTY_STS_CLR, \ | |
8736c826 | 333 | en_mask, {m1, m1h, m2, m3}, #block \ |
4a33bc03 VZ |
334 | } |
335 | ||
8736c826 | 336 | #define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2, m3) \ |
4a33bc03 VZ |
337 | { \ |
338 | block##_REG_##block##_PRTY_MASK_0, \ | |
339 | block##_REG_##block##_PRTY_STS_CLR_0, \ | |
8736c826 | 340 | en_mask, {m1, m1h, m2, m3}, #block"_0" \ |
4a33bc03 VZ |
341 | } |
342 | ||
8736c826 | 343 | #define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2, m3) \ |
4a33bc03 VZ |
344 | { \ |
345 | block##_REG_##block##_PRTY_MASK_1, \ | |
346 | block##_REG_##block##_PRTY_STS_CLR_1, \ | |
8736c826 | 347 | en_mask, {m1, m1h, m2, m3}, #block"_1" \ |
4a33bc03 VZ |
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 */ | |
8736c826 | 358 | u32 e3; /* 578xx */ |
4a33bc03 VZ |
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 | */ | |
8736c826 VZ |
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), | |
4a33bc03 | 391 | {GRCBASE_UPB + PB_REG_PB_PRTY_MASK, |
c9ee9206 | 392 | GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf, |
8736c826 | 393 | {0xf, 0xf, 0xf, 0xf}, "UPB"}, |
4a33bc03 VZ |
394 | {GRCBASE_XPB + PB_REG_PB_PRTY_MASK, |
395 | GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0, | |
8736c826 VZ |
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), | |
4a33bc03 VZ |
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; | |
8736c826 | 476 | else if (CHIP_IS_E2(bp)) |
4a33bc03 | 477 | return bnx2x_blocks_parity_data[idx].reg_mask.e2; |
8736c826 VZ |
478 | else /* CHIP_IS_E3 */ |
479 | return bnx2x_blocks_parity_data[idx].reg_mask.e3; | |
4a33bc03 VZ |
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 | ||
a2fbb9ea ET |
566 | #endif /* BNX2X_INIT_H */ |
567 |