1 /* bnx2x_init_ops.h: Broadcom Everest network driver.
2 * Static functions needed during the initialization.
3 * This file is "included" in bnx2x_main.c.
5 * Copyright (c) 2007-2009 Broadcom Corporation
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation.
11 * Maintained by: Eilon Greenstein <eilong@broadcom.com>
12 * Written by: Vladislav Zolotarov <vladz@broadcom.com>
14 #ifndef BNX2X_INIT_OPS_H
15 #define BNX2X_INIT_OPS_H
17 static void bnx2x_reg_wr_ind(struct bnx2x
*bp
, u32 addr
, u32 val
);
18 static int bnx2x_gunzip(struct bnx2x
*bp
, const u8
*zbuf
, int len
);
20 static void bnx2x_init_str_wr(struct bnx2x
*bp
, u32 addr
, const u32
*data
,
25 for (i
= 0; i
< len
; i
++) {
26 REG_WR(bp
, addr
+ i
*4, data
[i
]);
28 touch_softlockup_watchdog();
34 static void bnx2x_init_ind_wr(struct bnx2x
*bp
, u32 addr
, const u32
*data
,
39 for (i
= 0; i
< len
; i
++) {
40 REG_WR_IND(bp
, addr
+ i
*4, data
[i
]);
42 touch_softlockup_watchdog();
48 static void bnx2x_write_big_buf(struct bnx2x
*bp
, u32 addr
, u32 len
)
53 while (len
> DMAE_LEN32_WR_MAX
) {
54 bnx2x_write_dmae(bp
, bp
->gunzip_mapping
+ offset
,
55 addr
+ offset
, DMAE_LEN32_WR_MAX
);
56 offset
+= DMAE_LEN32_WR_MAX
* 4;
57 len
-= DMAE_LEN32_WR_MAX
;
59 bnx2x_write_dmae(bp
, bp
->gunzip_mapping
+ offset
,
62 bnx2x_init_str_wr(bp
, addr
, bp
->gunzip_buf
, len
);
65 static void bnx2x_init_fill(struct bnx2x
*bp
, u32 addr
, int fill
, u32 len
)
67 u32 buf_len
= (((len
* 4) > FW_BUF_SIZE
) ? FW_BUF_SIZE
: (len
* 4));
68 u32 buf_len32
= buf_len
/ 4;
71 memset(bp
->gunzip_buf
, fill
, buf_len
);
73 for (i
= 0; i
< len
; i
+= buf_len32
) {
74 u32 cur_len
= min(buf_len32
, len
- i
);
76 bnx2x_write_big_buf(bp
, addr
+ i
* 4, cur_len
);
80 static void bnx2x_init_wr_64(struct bnx2x
*bp
, u32 addr
, const u32
*data
,
83 u32 buf_len32
= FW_BUF_SIZE
/ 4;
88 /* 64 bit value is in a blob: first low DWORD, then high DWORD */
89 data64
= HILO_U64((*(data
+ 1)), (*data
));
90 len64
= min((u32
)(FW_BUF_SIZE
/8), len64
);
91 for (i
= 0; i
< len64
; i
++) {
92 u64
*pdata
= ((u64
*)(bp
->gunzip_buf
)) + i
;
97 for (i
= 0; i
< len
; i
+= buf_len32
) {
98 u32 cur_len
= min(buf_len32
, len
- i
);
100 bnx2x_write_big_buf(bp
, addr
+ i
* 4, cur_len
);
104 /*********************************************************
105 There are different blobs for each PRAM section.
106 In addition, each blob write operation is divided into a few operations
107 in order to decrease the amount of phys. contiguous buffer needed.
108 Thus, when we select a blob the address may be with some offset
109 from the beginning of PRAM section.
110 The same holds for the INT_TABLE sections.
111 **********************************************************/
112 #define IF_IS_INT_TABLE_ADDR(base, addr) \
113 if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))
115 #define IF_IS_PRAM_ADDR(base, addr) \
116 if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
118 static const u8
*bnx2x_sel_blob(struct bnx2x
*bp
, u32 addr
, const u8
*data
)
120 IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE
, addr
)
121 data
= bp
->tsem_int_table_data
;
122 else IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE
, addr
)
123 data
= bp
->csem_int_table_data
;
124 else IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE
, addr
)
125 data
= bp
->usem_int_table_data
;
126 else IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE
, addr
)
127 data
= bp
->xsem_int_table_data
;
128 else IF_IS_PRAM_ADDR(TSEM_REG_PRAM
, addr
)
129 data
= bp
->tsem_pram_data
;
130 else IF_IS_PRAM_ADDR(CSEM_REG_PRAM
, addr
)
131 data
= bp
->csem_pram_data
;
132 else IF_IS_PRAM_ADDR(USEM_REG_PRAM
, addr
)
133 data
= bp
->usem_pram_data
;
134 else IF_IS_PRAM_ADDR(XSEM_REG_PRAM
, addr
)
135 data
= bp
->xsem_pram_data
;
140 static void bnx2x_write_big_buf_wb(struct bnx2x
*bp
, u32 addr
, u32 len
)
144 if (bp
->dmae_ready
) {
145 while (len
> DMAE_LEN32_WR_MAX
) {
146 bnx2x_write_dmae(bp
, bp
->gunzip_mapping
+ offset
,
147 addr
+ offset
, DMAE_LEN32_WR_MAX
);
148 offset
+= DMAE_LEN32_WR_MAX
* 4;
149 len
-= DMAE_LEN32_WR_MAX
;
151 bnx2x_write_dmae(bp
, bp
->gunzip_mapping
+ offset
,
154 bnx2x_init_ind_wr(bp
, addr
, bp
->gunzip_buf
, len
);
157 static void bnx2x_init_wr_wb(struct bnx2x
*bp
, u32 addr
, const u32
*data
,
160 /* This is needed for NO_ZIP mode, currently supported
161 in little endian mode only */
162 data
= (const u32
*)bnx2x_sel_blob(bp
, addr
, (const u8
*)data
);
164 if ((len
* 4) > FW_BUF_SIZE
) {
165 BNX2X_ERR("LARGE DMAE OPERATION ! "
166 "addr 0x%x len 0x%x\n", addr
, len
*4);
169 memcpy(bp
->gunzip_buf
, data
, len
* 4);
171 bnx2x_write_big_buf_wb(bp
, addr
, len
);
174 static void bnx2x_init_wr_zp(struct bnx2x
*bp
, u32 addr
,
175 u32 len
, u32 blob_off
)
178 const u8
*data
= NULL
;
180 data
= bnx2x_sel_blob(bp
, addr
, data
) + 4*blob_off
;
183 panic("Blob not found for addr 0x%x\n", addr
);
187 rc
= bnx2x_gunzip(bp
, data
, len
);
189 BNX2X_ERR("gunzip failed ! addr 0x%x rc %d\n", addr
, rc
);
190 BNX2X_ERR("blob_offset=0x%x\n", blob_off
);
194 /* gunzip_outlen is in dwords */
195 len
= bp
->gunzip_outlen
;
196 for (i
= 0; i
< len
; i
++)
197 ((u32
*)bp
->gunzip_buf
)[i
] =
198 cpu_to_le32(((u32
*)bp
->gunzip_buf
)[i
]);
200 bnx2x_write_big_buf_wb(bp
, addr
, len
);
203 static void bnx2x_init_block(struct bnx2x
*bp
, u32 block
, u32 stage
)
207 bp
->init_ops_offsets
[BLOCK_OPS_IDX(block
,stage
,STAGE_START
)];
209 bp
->init_ops_offsets
[BLOCK_OPS_IDX(block
,stage
,STAGE_END
)];
211 u32 op_type
, addr
, len
;
212 const u32
*data
, *data_base
;
215 if (op_start
== op_end
)
218 if (CHIP_REV_IS_FPGA(bp
))
220 else if (CHIP_REV_IS_EMUL(bp
))
225 data_base
= bp
->init_data
;
227 for (i
= op_start
; i
< op_end
; i
++) {
229 op
= (union init_op
*)&(bp
->init_ops
[i
]);
231 op_type
= op
->str_wr
.op
;
232 addr
= op
->str_wr
.offset
;
233 len
= op
->str_wr
.data_len
;
234 data
= data_base
+ op
->str_wr
.data_off
;
236 /* HW/EMUL specific */
237 if (unlikely((op_type
> OP_WB
) && (op_type
== hw_wr
)))
245 REG_WR(bp
, addr
, op
->write
.val
);
248 bnx2x_init_str_wr(bp
, addr
, data
, len
);
251 bnx2x_init_wr_wb(bp
, addr
, data
, len
);
254 bnx2x_init_ind_wr(bp
, addr
, data
, len
);
257 bnx2x_init_fill(bp
, addr
, 0, op
->zero
.len
);
260 bnx2x_init_wr_zp(bp
, addr
, len
,
261 op
->str_wr
.data_off
);
264 bnx2x_init_wr_64(bp
, addr
, data
, len
);
267 /* happens whenever an op is of a diff HW */
269 DP(NETIF_MSG_HW
, "skipping init operation "
270 "index %d[%d:%d]: type %d addr 0x%x "
272 i
, op_start
, op_end
, op_type
, addr
, len
, len
);
280 static void bnx2x_init_pxp(struct bnx2x
*bp
)
283 int r_order
, w_order
;
286 pci_read_config_word(bp
->pdev
,
287 bp
->pcie_cap
+ PCI_EXP_DEVCTL
, &devctl
);
288 DP(NETIF_MSG_HW
, "read 0x%x from devctl\n", devctl
);
289 w_order
= ((devctl
& PCI_EXP_DEVCTL_PAYLOAD
) >> 5);
291 r_order
= ((devctl
& PCI_EXP_DEVCTL_READRQ
) >> 12);
293 DP(NETIF_MSG_HW
, "force read order to %d\n", bp
->mrrs
);
297 if (r_order
> MAX_RD_ORD
) {
298 DP(NETIF_MSG_HW
, "read order of %d order adjusted to %d\n",
299 r_order
, MAX_RD_ORD
);
300 r_order
= MAX_RD_ORD
;
302 if (w_order
> MAX_WR_ORD
) {
303 DP(NETIF_MSG_HW
, "write order of %d order adjusted to %d\n",
304 w_order
, MAX_WR_ORD
);
305 w_order
= MAX_WR_ORD
;
307 if (CHIP_REV_IS_FPGA(bp
)) {
308 DP(NETIF_MSG_HW
, "write order adjusted to 1 for FPGA\n");
311 DP(NETIF_MSG_HW
, "read order %d write order %d\n", r_order
, w_order
);
313 for (i
= 0; i
< NUM_RD_Q
-1; i
++) {
314 REG_WR(bp
, read_arb_addr
[i
].l
, read_arb_data
[i
][r_order
].l
);
315 REG_WR(bp
, read_arb_addr
[i
].add
,
316 read_arb_data
[i
][r_order
].add
);
317 REG_WR(bp
, read_arb_addr
[i
].ubound
,
318 read_arb_data
[i
][r_order
].ubound
);
321 for (i
= 0; i
< NUM_WR_Q
-1; i
++) {
322 if ((write_arb_addr
[i
].l
== PXP2_REG_RQ_BW_WR_L29
) ||
323 (write_arb_addr
[i
].l
== PXP2_REG_RQ_BW_WR_L30
)) {
325 REG_WR(bp
, write_arb_addr
[i
].l
,
326 write_arb_data
[i
][w_order
].l
);
328 REG_WR(bp
, write_arb_addr
[i
].add
,
329 write_arb_data
[i
][w_order
].add
);
331 REG_WR(bp
, write_arb_addr
[i
].ubound
,
332 write_arb_data
[i
][w_order
].ubound
);
335 val
= REG_RD(bp
, write_arb_addr
[i
].l
);
336 REG_WR(bp
, write_arb_addr
[i
].l
,
337 val
| (write_arb_data
[i
][w_order
].l
<< 10));
339 val
= REG_RD(bp
, write_arb_addr
[i
].add
);
340 REG_WR(bp
, write_arb_addr
[i
].add
,
341 val
| (write_arb_data
[i
][w_order
].add
<< 10));
343 val
= REG_RD(bp
, write_arb_addr
[i
].ubound
);
344 REG_WR(bp
, write_arb_addr
[i
].ubound
,
345 val
| (write_arb_data
[i
][w_order
].ubound
<< 7));
349 val
= write_arb_data
[NUM_WR_Q
-1][w_order
].add
;
350 val
+= write_arb_data
[NUM_WR_Q
-1][w_order
].ubound
<< 10;
351 val
+= write_arb_data
[NUM_WR_Q
-1][w_order
].l
<< 17;
352 REG_WR(bp
, PXP2_REG_PSWRQ_BW_RD
, val
);
354 val
= read_arb_data
[NUM_RD_Q
-1][r_order
].add
;
355 val
+= read_arb_data
[NUM_RD_Q
-1][r_order
].ubound
<< 10;
356 val
+= read_arb_data
[NUM_RD_Q
-1][r_order
].l
<< 17;
357 REG_WR(bp
, PXP2_REG_PSWRQ_BW_WR
, val
);
359 REG_WR(bp
, PXP2_REG_RQ_WR_MBS0
, w_order
);
360 REG_WR(bp
, PXP2_REG_RQ_WR_MBS1
, w_order
);
361 REG_WR(bp
, PXP2_REG_RQ_RD_MBS0
, r_order
);
362 REG_WR(bp
, PXP2_REG_RQ_RD_MBS1
, r_order
);
364 if (r_order
== MAX_RD_ORD
)
365 REG_WR(bp
, PXP2_REG_RQ_PDR_LIMIT
, 0xe00);
367 REG_WR(bp
, PXP2_REG_WR_USDMDP_TH
, (0x18 << w_order
));
369 if (CHIP_IS_E1H(bp
)) {
370 val
= ((w_order
== 0) ? 2 : 3);
371 REG_WR(bp
, PXP2_REG_WR_HC_MPS
, val
);
372 REG_WR(bp
, PXP2_REG_WR_USDM_MPS
, val
);
373 REG_WR(bp
, PXP2_REG_WR_CSDM_MPS
, val
);
374 REG_WR(bp
, PXP2_REG_WR_TSDM_MPS
, val
);
375 REG_WR(bp
, PXP2_REG_WR_XSDM_MPS
, val
);
376 REG_WR(bp
, PXP2_REG_WR_QM_MPS
, val
);
377 REG_WR(bp
, PXP2_REG_WR_TM_MPS
, val
);
378 REG_WR(bp
, PXP2_REG_WR_SRC_MPS
, val
);
379 REG_WR(bp
, PXP2_REG_WR_DBG_MPS
, val
);
380 REG_WR(bp
, PXP2_REG_WR_DMAE_MPS
, 2); /* DMAE is special */
381 REG_WR(bp
, PXP2_REG_WR_CDU_MPS
, val
);
385 /*****************************************************************************
387 * Calculates crc 8 on a word value: polynomial 0-1-2-8
388 * Code was translated from Verilog.
389 ****************************************************************************/
390 static u8
calc_crc8(u32 data
, u8 crc
)
398 /* split the data into 31 bits */
399 for (i
= 0; i
< 32; i
++) {
404 /* split the crc into 8 bits */
405 for (i
= 0; i
< 8; i
++) {
410 NewCRC
[0] = D
[31] ^ D
[30] ^ D
[28] ^ D
[23] ^ D
[21] ^ D
[19] ^ D
[18] ^
411 D
[16] ^ D
[14] ^ D
[12] ^ D
[8] ^ D
[7] ^ D
[6] ^ D
[0] ^ C
[4] ^
413 NewCRC
[1] = D
[30] ^ D
[29] ^ D
[28] ^ D
[24] ^ D
[23] ^ D
[22] ^ D
[21] ^
414 D
[20] ^ D
[18] ^ D
[17] ^ D
[16] ^ D
[15] ^ D
[14] ^ D
[13] ^
415 D
[12] ^ D
[9] ^ D
[6] ^ D
[1] ^ D
[0] ^ C
[0] ^ C
[4] ^ C
[5] ^ C
[6];
416 NewCRC
[2] = D
[29] ^ D
[28] ^ D
[25] ^ D
[24] ^ D
[22] ^ D
[17] ^ D
[15] ^
417 D
[13] ^ D
[12] ^ D
[10] ^ D
[8] ^ D
[6] ^ D
[2] ^ D
[1] ^ D
[0] ^
418 C
[0] ^ C
[1] ^ C
[4] ^ C
[5];
419 NewCRC
[3] = D
[30] ^ D
[29] ^ D
[26] ^ D
[25] ^ D
[23] ^ D
[18] ^ D
[16] ^
420 D
[14] ^ D
[13] ^ D
[11] ^ D
[9] ^ D
[7] ^ D
[3] ^ D
[2] ^ D
[1] ^
421 C
[1] ^ C
[2] ^ C
[5] ^ C
[6];
422 NewCRC
[4] = D
[31] ^ D
[30] ^ D
[27] ^ D
[26] ^ D
[24] ^ D
[19] ^ D
[17] ^
423 D
[15] ^ D
[14] ^ D
[12] ^ D
[10] ^ D
[8] ^ D
[4] ^ D
[3] ^ D
[2] ^
424 C
[0] ^ C
[2] ^ C
[3] ^ C
[6] ^ C
[7];
425 NewCRC
[5] = D
[31] ^ D
[28] ^ D
[27] ^ D
[25] ^ D
[20] ^ D
[18] ^ D
[16] ^
426 D
[15] ^ D
[13] ^ D
[11] ^ D
[9] ^ D
[5] ^ D
[4] ^ D
[3] ^ C
[1] ^
428 NewCRC
[6] = D
[29] ^ D
[28] ^ D
[26] ^ D
[21] ^ D
[19] ^ D
[17] ^ D
[16] ^
429 D
[14] ^ D
[12] ^ D
[10] ^ D
[6] ^ D
[5] ^ D
[4] ^ C
[2] ^ C
[4] ^
431 NewCRC
[7] = D
[30] ^ D
[29] ^ D
[27] ^ D
[22] ^ D
[20] ^ D
[18] ^ D
[17] ^
432 D
[15] ^ D
[13] ^ D
[11] ^ D
[7] ^ D
[6] ^ D
[5] ^ C
[3] ^ C
[5] ^
436 for (i
= 0; i
< 8; i
++)
437 crc_res
|= (NewCRC
[i
] << i
);
442 #endif /* BNX2X_INIT_OPS_H */