Commit | Line | Data |
---|---|---|
94a78b79 VZ |
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. | |
4 | * | |
5 | * Copyright (c) 2007-2009 Broadcom Corporation | |
6 | * | |
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. | |
10 | * | |
11 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | |
12 | * Written by: Vladislav Zolotarov <vladz@broadcom.com> | |
13 | */ | |
573f2035 | 14 | |
94a78b79 VZ |
15 | #ifndef BNX2X_INIT_OPS_H |
16 | #define BNX2X_INIT_OPS_H | |
17 | ||
94a78b79 VZ |
18 | static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len); |
19 | ||
573f2035 | 20 | |
94a78b79 VZ |
21 | static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data, |
22 | u32 len) | |
23 | { | |
573f2035 | 24 | u32 i; |
94a78b79 | 25 | |
573f2035 | 26 | for (i = 0; i < len; i++) |
94a78b79 | 27 | REG_WR(bp, addr + i*4, data[i]); |
94a78b79 VZ |
28 | } |
29 | ||
30 | static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data, | |
573f2035 | 31 | u32 len) |
94a78b79 | 32 | { |
573f2035 | 33 | u32 i; |
94a78b79 | 34 | |
573f2035 | 35 | for (i = 0; i < len; i++) |
94a78b79 | 36 | REG_WR_IND(bp, addr + i*4, data[i]); |
94a78b79 VZ |
37 | } |
38 | ||
39 | static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) | |
40 | { | |
573f2035 EG |
41 | if (bp->dmae_ready) |
42 | bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len); | |
43 | else | |
44 | bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len); | |
94a78b79 VZ |
45 | } |
46 | ||
47 | static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len) | |
48 | { | |
573f2035 EG |
49 | u32 buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4)); |
50 | u32 buf_len32 = buf_len/4; | |
51 | u32 i; | |
94a78b79 | 52 | |
573f2035 | 53 | memset(GUNZIP_BUF(bp), (u8)fill, buf_len); |
94a78b79 VZ |
54 | |
55 | for (i = 0; i < len; i += buf_len32) { | |
56 | u32 cur_len = min(buf_len32, len - i); | |
57 | ||
573f2035 | 58 | bnx2x_write_big_buf(bp, addr + i*4, cur_len); |
94a78b79 VZ |
59 | } |
60 | } | |
61 | ||
62 | static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data, | |
63 | u32 len64) | |
64 | { | |
573f2035 EG |
65 | u32 buf_len32 = FW_BUF_SIZE/4; |
66 | u32 len = len64*2; | |
94a78b79 | 67 | u64 data64 = 0; |
573f2035 | 68 | u32 i; |
94a78b79 VZ |
69 | |
70 | /* 64 bit value is in a blob: first low DWORD, then high DWORD */ | |
71 | data64 = HILO_U64((*(data + 1)), (*data)); | |
573f2035 | 72 | |
94a78b79 VZ |
73 | len64 = min((u32)(FW_BUF_SIZE/8), len64); |
74 | for (i = 0; i < len64; i++) { | |
573f2035 | 75 | u64 *pdata = ((u64 *)(GUNZIP_BUF(bp))) + i; |
94a78b79 VZ |
76 | |
77 | *pdata = data64; | |
78 | } | |
79 | ||
80 | for (i = 0; i < len; i += buf_len32) { | |
81 | u32 cur_len = min(buf_len32, len - i); | |
82 | ||
573f2035 | 83 | bnx2x_write_big_buf(bp, addr + i*4, cur_len); |
94a78b79 VZ |
84 | } |
85 | } | |
86 | ||
87 | /********************************************************* | |
88 | There are different blobs for each PRAM section. | |
89 | In addition, each blob write operation is divided into a few operations | |
90 | in order to decrease the amount of phys. contiguous buffer needed. | |
91 | Thus, when we select a blob the address may be with some offset | |
92 | from the beginning of PRAM section. | |
93 | The same holds for the INT_TABLE sections. | |
94 | **********************************************************/ | |
95 | #define IF_IS_INT_TABLE_ADDR(base, addr) \ | |
96 | if (((base) <= (addr)) && ((base) + 0x400 >= (addr))) | |
97 | ||
98 | #define IF_IS_PRAM_ADDR(base, addr) \ | |
99 | if (((base) <= (addr)) && ((base) + 0x40000 >= (addr))) | |
100 | ||
101 | static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data) | |
102 | { | |
103 | IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr) | |
573f2035 EG |
104 | data = INIT_TSEM_INT_TABLE_DATA(bp); |
105 | else | |
106 | IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr) | |
107 | data = INIT_CSEM_INT_TABLE_DATA(bp); | |
108 | else | |
109 | IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr) | |
110 | data = INIT_USEM_INT_TABLE_DATA(bp); | |
111 | else | |
112 | IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr) | |
113 | data = INIT_XSEM_INT_TABLE_DATA(bp); | |
114 | else | |
115 | IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr) | |
116 | data = INIT_TSEM_PRAM_DATA(bp); | |
117 | else | |
118 | IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr) | |
119 | data = INIT_CSEM_PRAM_DATA(bp); | |
120 | else | |
121 | IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr) | |
122 | data = INIT_USEM_PRAM_DATA(bp); | |
123 | else | |
124 | IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr) | |
125 | data = INIT_XSEM_PRAM_DATA(bp); | |
94a78b79 VZ |
126 | |
127 | return data; | |
128 | } | |
129 | ||
130 | static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len) | |
131 | { | |
573f2035 EG |
132 | if (bp->dmae_ready) |
133 | bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len); | |
134 | else | |
135 | bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len); | |
94a78b79 VZ |
136 | } |
137 | ||
138 | static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data, | |
139 | u32 len) | |
140 | { | |
573f2035 | 141 | data = (const u32 *)bnx2x_sel_blob(bp, addr, (const u8 *)data); |
94a78b79 | 142 | |
573f2035 EG |
143 | if (bp->dmae_ready) |
144 | VIRT_WR_DMAE_LEN(bp, data, addr, len); | |
145 | else | |
146 | bnx2x_init_ind_wr(bp, addr, data, len); | |
94a78b79 VZ |
147 | } |
148 | ||
573f2035 | 149 | static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off) |
94a78b79 | 150 | { |
573f2035 EG |
151 | const u8 *data = NULL; |
152 | int rc; | |
153 | u32 i; | |
94a78b79 | 154 | |
573f2035 | 155 | data = bnx2x_sel_blob(bp, addr, data) + blob_off*4; |
94a78b79 VZ |
156 | |
157 | rc = bnx2x_gunzip(bp, data, len); | |
573f2035 | 158 | if (rc) |
94a78b79 | 159 | return; |
94a78b79 VZ |
160 | |
161 | /* gunzip_outlen is in dwords */ | |
573f2035 | 162 | len = GUNZIP_OUTLEN(bp); |
94a78b79 | 163 | for (i = 0; i < len; i++) |
573f2035 EG |
164 | ((u32 *)GUNZIP_BUF(bp))[i] = |
165 | cpu_to_le32(((u32 *)GUNZIP_BUF(bp))[i]); | |
94a78b79 VZ |
166 | |
167 | bnx2x_write_big_buf_wb(bp, addr, len); | |
168 | } | |
169 | ||
170 | static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage) | |
171 | { | |
94a78b79 | 172 | u16 op_start = |
573f2035 | 173 | INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_START)]; |
94a78b79 | 174 | u16 op_end = |
573f2035 | 175 | INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_END)]; |
94a78b79 | 176 | union init_op *op; |
573f2035 EG |
177 | int hw_wr; |
178 | u32 i, op_type, addr, len; | |
94a78b79 VZ |
179 | const u32 *data, *data_base; |
180 | ||
181 | /* If empty block */ | |
182 | if (op_start == op_end) | |
183 | return; | |
184 | ||
185 | if (CHIP_REV_IS_FPGA(bp)) | |
186 | hw_wr = OP_WR_FPGA; | |
187 | else if (CHIP_REV_IS_EMUL(bp)) | |
188 | hw_wr = OP_WR_EMUL; | |
189 | else | |
190 | hw_wr = OP_WR_ASIC; | |
191 | ||
573f2035 | 192 | data_base = INIT_DATA(bp); |
94a78b79 VZ |
193 | |
194 | for (i = op_start; i < op_end; i++) { | |
195 | ||
573f2035 | 196 | op = (union init_op *)&(INIT_OPS(bp)[i]); |
94a78b79 VZ |
197 | |
198 | op_type = op->str_wr.op; | |
199 | addr = op->str_wr.offset; | |
200 | len = op->str_wr.data_len; | |
201 | data = data_base + op->str_wr.data_off; | |
202 | ||
203 | /* HW/EMUL specific */ | |
573f2035 | 204 | if ((op_type > OP_WB) && (op_type == hw_wr)) |
94a78b79 VZ |
205 | op_type = OP_WR; |
206 | ||
207 | switch (op_type) { | |
208 | case OP_RD: | |
209 | REG_RD(bp, addr); | |
210 | break; | |
211 | case OP_WR: | |
212 | REG_WR(bp, addr, op->write.val); | |
213 | break; | |
214 | case OP_SW: | |
215 | bnx2x_init_str_wr(bp, addr, data, len); | |
216 | break; | |
217 | case OP_WB: | |
218 | bnx2x_init_wr_wb(bp, addr, data, len); | |
219 | break; | |
220 | case OP_SI: | |
221 | bnx2x_init_ind_wr(bp, addr, data, len); | |
222 | break; | |
223 | case OP_ZR: | |
224 | bnx2x_init_fill(bp, addr, 0, op->zero.len); | |
225 | break; | |
226 | case OP_ZP: | |
227 | bnx2x_init_wr_zp(bp, addr, len, | |
228 | op->str_wr.data_off); | |
229 | break; | |
230 | case OP_WR_64: | |
231 | bnx2x_init_wr_64(bp, addr, data, len); | |
232 | break; | |
233 | default: | |
234 | /* happens whenever an op is of a diff HW */ | |
94a78b79 VZ |
235 | break; |
236 | } | |
237 | } | |
238 | } | |
239 | ||
573f2035 EG |
240 | |
241 | /**************************************************************************** | |
242 | * PXP Arbiter | |
243 | ****************************************************************************/ | |
244 | /* | |
245 | * This code configures the PCI read/write arbiter | |
246 | * which implements a weighted round robin | |
247 | * between the virtual queues in the chip. | |
248 | * | |
249 | * The values were derived for each PCI max payload and max request size. | |
250 | * since max payload and max request size are only known at run time, | |
251 | * this is done as a separate init stage. | |
252 | */ | |
253 | ||
254 | #define NUM_WR_Q 13 | |
255 | #define NUM_RD_Q 29 | |
256 | #define MAX_RD_ORD 3 | |
257 | #define MAX_WR_ORD 2 | |
258 | ||
259 | /* configuration for one arbiter queue */ | |
260 | struct arb_line { | |
261 | int l; | |
262 | int add; | |
263 | int ubound; | |
264 | }; | |
265 | ||
266 | /* derived configuration for each read queue for each max request size */ | |
267 | static const struct arb_line read_arb_data[NUM_RD_Q][MAX_RD_ORD + 1] = { | |
268 | /* 1 */ { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} }, | |
269 | { {4, 8, 4}, {4, 8, 4}, {4, 8, 4}, {4, 8, 4} }, | |
270 | { {4, 3, 3}, {4, 3, 3}, {4, 3, 3}, {4, 3, 3} }, | |
271 | { {8, 3, 6}, {16, 3, 11}, {16, 3, 11}, {16, 3, 11} }, | |
272 | { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} }, | |
273 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, | |
274 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, | |
275 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, | |
276 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, | |
277 | /* 10 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
278 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
279 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
280 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
281 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
282 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
283 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
284 | { {8, 64, 6}, {16, 64, 11}, {32, 64, 21}, {32, 64, 21} }, | |
285 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
286 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
287 | /* 20 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
288 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
289 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
290 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
291 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
292 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
293 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
294 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
295 | { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, | |
296 | { {8, 64, 25}, {16, 64, 41}, {32, 64, 81}, {64, 64, 120} } | |
297 | }; | |
298 | ||
299 | /* derived configuration for each write queue for each max request size */ | |
300 | static const struct arb_line write_arb_data[NUM_WR_Q][MAX_WR_ORD + 1] = { | |
301 | /* 1 */ { {4, 6, 3}, {4, 6, 3}, {4, 6, 3} }, | |
302 | { {4, 2, 3}, {4, 2, 3}, {4, 2, 3} }, | |
303 | { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, | |
304 | { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, | |
305 | { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, | |
306 | { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, | |
307 | { {8, 64, 25}, {16, 64, 25}, {32, 64, 25} }, | |
308 | { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, | |
309 | { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, | |
310 | /* 10 */{ {8, 9, 6}, {16, 9, 11}, {32, 9, 21} }, | |
311 | { {8, 47, 19}, {16, 47, 19}, {32, 47, 21} }, | |
312 | { {8, 9, 6}, {16, 9, 11}, {16, 9, 11} }, | |
313 | { {8, 64, 25}, {16, 64, 41}, {32, 64, 81} } | |
314 | }; | |
315 | ||
316 | /* register addresses for read queues */ | |
317 | static const struct arb_line read_arb_addr[NUM_RD_Q-1] = { | |
318 | /* 1 */ {PXP2_REG_RQ_BW_RD_L0, PXP2_REG_RQ_BW_RD_ADD0, | |
319 | PXP2_REG_RQ_BW_RD_UBOUND0}, | |
320 | {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1, | |
321 | PXP2_REG_PSWRQ_BW_UB1}, | |
322 | {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2, | |
323 | PXP2_REG_PSWRQ_BW_UB2}, | |
324 | {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3, | |
325 | PXP2_REG_PSWRQ_BW_UB3}, | |
326 | {PXP2_REG_RQ_BW_RD_L4, PXP2_REG_RQ_BW_RD_ADD4, | |
327 | PXP2_REG_RQ_BW_RD_UBOUND4}, | |
328 | {PXP2_REG_RQ_BW_RD_L5, PXP2_REG_RQ_BW_RD_ADD5, | |
329 | PXP2_REG_RQ_BW_RD_UBOUND5}, | |
330 | {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6, | |
331 | PXP2_REG_PSWRQ_BW_UB6}, | |
332 | {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7, | |
333 | PXP2_REG_PSWRQ_BW_UB7}, | |
334 | {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8, | |
335 | PXP2_REG_PSWRQ_BW_UB8}, | |
336 | /* 10 */{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9, | |
337 | PXP2_REG_PSWRQ_BW_UB9}, | |
338 | {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10, | |
339 | PXP2_REG_PSWRQ_BW_UB10}, | |
340 | {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11, | |
341 | PXP2_REG_PSWRQ_BW_UB11}, | |
342 | {PXP2_REG_RQ_BW_RD_L12, PXP2_REG_RQ_BW_RD_ADD12, | |
343 | PXP2_REG_RQ_BW_RD_UBOUND12}, | |
344 | {PXP2_REG_RQ_BW_RD_L13, PXP2_REG_RQ_BW_RD_ADD13, | |
345 | PXP2_REG_RQ_BW_RD_UBOUND13}, | |
346 | {PXP2_REG_RQ_BW_RD_L14, PXP2_REG_RQ_BW_RD_ADD14, | |
347 | PXP2_REG_RQ_BW_RD_UBOUND14}, | |
348 | {PXP2_REG_RQ_BW_RD_L15, PXP2_REG_RQ_BW_RD_ADD15, | |
349 | PXP2_REG_RQ_BW_RD_UBOUND15}, | |
350 | {PXP2_REG_RQ_BW_RD_L16, PXP2_REG_RQ_BW_RD_ADD16, | |
351 | PXP2_REG_RQ_BW_RD_UBOUND16}, | |
352 | {PXP2_REG_RQ_BW_RD_L17, PXP2_REG_RQ_BW_RD_ADD17, | |
353 | PXP2_REG_RQ_BW_RD_UBOUND17}, | |
354 | {PXP2_REG_RQ_BW_RD_L18, PXP2_REG_RQ_BW_RD_ADD18, | |
355 | PXP2_REG_RQ_BW_RD_UBOUND18}, | |
356 | /* 20 */{PXP2_REG_RQ_BW_RD_L19, PXP2_REG_RQ_BW_RD_ADD19, | |
357 | PXP2_REG_RQ_BW_RD_UBOUND19}, | |
358 | {PXP2_REG_RQ_BW_RD_L20, PXP2_REG_RQ_BW_RD_ADD20, | |
359 | PXP2_REG_RQ_BW_RD_UBOUND20}, | |
360 | {PXP2_REG_RQ_BW_RD_L22, PXP2_REG_RQ_BW_RD_ADD22, | |
361 | PXP2_REG_RQ_BW_RD_UBOUND22}, | |
362 | {PXP2_REG_RQ_BW_RD_L23, PXP2_REG_RQ_BW_RD_ADD23, | |
363 | PXP2_REG_RQ_BW_RD_UBOUND23}, | |
364 | {PXP2_REG_RQ_BW_RD_L24, PXP2_REG_RQ_BW_RD_ADD24, | |
365 | PXP2_REG_RQ_BW_RD_UBOUND24}, | |
366 | {PXP2_REG_RQ_BW_RD_L25, PXP2_REG_RQ_BW_RD_ADD25, | |
367 | PXP2_REG_RQ_BW_RD_UBOUND25}, | |
368 | {PXP2_REG_RQ_BW_RD_L26, PXP2_REG_RQ_BW_RD_ADD26, | |
369 | PXP2_REG_RQ_BW_RD_UBOUND26}, | |
370 | {PXP2_REG_RQ_BW_RD_L27, PXP2_REG_RQ_BW_RD_ADD27, | |
371 | PXP2_REG_RQ_BW_RD_UBOUND27}, | |
372 | {PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28, | |
373 | PXP2_REG_PSWRQ_BW_UB28} | |
374 | }; | |
375 | ||
376 | /* register addresses for write queues */ | |
377 | static const struct arb_line write_arb_addr[NUM_WR_Q-1] = { | |
378 | /* 1 */ {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1, | |
379 | PXP2_REG_PSWRQ_BW_UB1}, | |
380 | {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2, | |
381 | PXP2_REG_PSWRQ_BW_UB2}, | |
382 | {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3, | |
383 | PXP2_REG_PSWRQ_BW_UB3}, | |
384 | {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6, | |
385 | PXP2_REG_PSWRQ_BW_UB6}, | |
386 | {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7, | |
387 | PXP2_REG_PSWRQ_BW_UB7}, | |
388 | {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8, | |
389 | PXP2_REG_PSWRQ_BW_UB8}, | |
390 | {PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9, | |
391 | PXP2_REG_PSWRQ_BW_UB9}, | |
392 | {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10, | |
393 | PXP2_REG_PSWRQ_BW_UB10}, | |
394 | {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11, | |
395 | PXP2_REG_PSWRQ_BW_UB11}, | |
396 | /* 10 */{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28, | |
397 | PXP2_REG_PSWRQ_BW_UB28}, | |
398 | {PXP2_REG_RQ_BW_WR_L29, PXP2_REG_RQ_BW_WR_ADD29, | |
399 | PXP2_REG_RQ_BW_WR_UBOUND29}, | |
400 | {PXP2_REG_RQ_BW_WR_L30, PXP2_REG_RQ_BW_WR_ADD30, | |
401 | PXP2_REG_RQ_BW_WR_UBOUND30} | |
402 | }; | |
403 | ||
404 | static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order) | |
94a78b79 | 405 | { |
94a78b79 VZ |
406 | u32 val, i; |
407 | ||
94a78b79 VZ |
408 | if (r_order > MAX_RD_ORD) { |
409 | DP(NETIF_MSG_HW, "read order of %d order adjusted to %d\n", | |
410 | r_order, MAX_RD_ORD); | |
411 | r_order = MAX_RD_ORD; | |
412 | } | |
413 | if (w_order > MAX_WR_ORD) { | |
414 | DP(NETIF_MSG_HW, "write order of %d order adjusted to %d\n", | |
415 | w_order, MAX_WR_ORD); | |
416 | w_order = MAX_WR_ORD; | |
417 | } | |
418 | if (CHIP_REV_IS_FPGA(bp)) { | |
419 | DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n"); | |
420 | w_order = 0; | |
421 | } | |
422 | DP(NETIF_MSG_HW, "read order %d write order %d\n", r_order, w_order); | |
423 | ||
424 | for (i = 0; i < NUM_RD_Q-1; i++) { | |
425 | REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l); | |
426 | REG_WR(bp, read_arb_addr[i].add, | |
427 | read_arb_data[i][r_order].add); | |
428 | REG_WR(bp, read_arb_addr[i].ubound, | |
429 | read_arb_data[i][r_order].ubound); | |
430 | } | |
431 | ||
432 | for (i = 0; i < NUM_WR_Q-1; i++) { | |
433 | if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) || | |
434 | (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) { | |
435 | ||
436 | REG_WR(bp, write_arb_addr[i].l, | |
437 | write_arb_data[i][w_order].l); | |
438 | ||
439 | REG_WR(bp, write_arb_addr[i].add, | |
440 | write_arb_data[i][w_order].add); | |
441 | ||
442 | REG_WR(bp, write_arb_addr[i].ubound, | |
443 | write_arb_data[i][w_order].ubound); | |
444 | } else { | |
445 | ||
446 | val = REG_RD(bp, write_arb_addr[i].l); | |
447 | REG_WR(bp, write_arb_addr[i].l, | |
448 | val | (write_arb_data[i][w_order].l << 10)); | |
449 | ||
450 | val = REG_RD(bp, write_arb_addr[i].add); | |
451 | REG_WR(bp, write_arb_addr[i].add, | |
452 | val | (write_arb_data[i][w_order].add << 10)); | |
453 | ||
454 | val = REG_RD(bp, write_arb_addr[i].ubound); | |
455 | REG_WR(bp, write_arb_addr[i].ubound, | |
456 | val | (write_arb_data[i][w_order].ubound << 7)); | |
457 | } | |
458 | } | |
459 | ||
460 | val = write_arb_data[NUM_WR_Q-1][w_order].add; | |
461 | val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10; | |
462 | val += write_arb_data[NUM_WR_Q-1][w_order].l << 17; | |
463 | REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val); | |
464 | ||
465 | val = read_arb_data[NUM_RD_Q-1][r_order].add; | |
466 | val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10; | |
467 | val += read_arb_data[NUM_RD_Q-1][r_order].l << 17; | |
468 | REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val); | |
469 | ||
470 | REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order); | |
471 | REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order); | |
472 | REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order); | |
473 | REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order); | |
474 | ||
475 | if (r_order == MAX_RD_ORD) | |
476 | REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00); | |
477 | ||
478 | REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); | |
479 | ||
480 | if (CHIP_IS_E1H(bp)) { | |
573f2035 EG |
481 | /* MPS w_order optimal TH presently TH |
482 | * 128 0 0 2 | |
483 | * 256 1 1 3 | |
484 | * >=512 2 2 3 | |
485 | */ | |
94a78b79 VZ |
486 | val = ((w_order == 0) ? 2 : 3); |
487 | REG_WR(bp, PXP2_REG_WR_HC_MPS, val); | |
488 | REG_WR(bp, PXP2_REG_WR_USDM_MPS, val); | |
489 | REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val); | |
490 | REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val); | |
491 | REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val); | |
492 | REG_WR(bp, PXP2_REG_WR_QM_MPS, val); | |
493 | REG_WR(bp, PXP2_REG_WR_TM_MPS, val); | |
494 | REG_WR(bp, PXP2_REG_WR_SRC_MPS, val); | |
495 | REG_WR(bp, PXP2_REG_WR_DBG_MPS, val); | |
496 | REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */ | |
497 | REG_WR(bp, PXP2_REG_WR_CDU_MPS, val); | |
498 | } | |
499 | } | |
500 | ||
94a78b79 | 501 | #endif /* BNX2X_INIT_OPS_H */ |