diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2008-06-23 23:29:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-23 23:29:02 -0400 |
commit | ad8d394804b355bc623decc50748cd01dbc0783b (patch) | |
tree | be2d1c7fc15fc6e1bd17a7d87c697254407fa865 /drivers/net/bnx2x_main.c | |
parent | c18487ee24381b40df3b8b4f54dd13ee9367a1ce (diff) |
bnx2x: New init infrastructure
This new initialization code supports the 57711 HW. It also supports
the emulation and FPGA for the 57711 and 57710 initializations values
(very small amount of code which is very helpful in the lab - less
than 30 lines).
The initialization is done via DMAE after the DMAE block is ready -
before it is ready, some of the initialization is done via PCI
configuration transactions (referred to as indirect write). A mutex
to protect the DMAE from being overlapped was added. There are few
new registers which needs to be initialized by SW - the full comment
for those registers is added to the register file. A place holder for
the 57711 (referred to as E1H) microcode was added- the microcode
itself is too big and it is split over the following 4 patches
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x_main.c')
-rw-r--r-- | drivers/net/bnx2x_main.c | 166 |
1 files changed, 103 insertions, 63 deletions
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7b547f03b565..efa942688f84 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c | |||
@@ -137,7 +137,6 @@ static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val) | |||
137 | PCICFG_VENDOR_ID_OFFSET); | 137 | PCICFG_VENDOR_ID_OFFSET); |
138 | } | 138 | } |
139 | 139 | ||
140 | #ifdef BNX2X_IND_RD | ||
141 | static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr) | 140 | static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr) |
142 | { | 141 | { |
143 | u32 val; | 142 | u32 val; |
@@ -149,7 +148,6 @@ static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr) | |||
149 | 148 | ||
150 | return val; | 149 | return val; |
151 | } | 150 | } |
152 | #endif | ||
153 | 151 | ||
154 | static const u32 dmae_reg_go_c[] = { | 152 | static const u32 dmae_reg_go_c[] = { |
155 | DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3, | 153 | DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3, |
@@ -169,19 +167,29 @@ static void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, | |||
169 | for (i = 0; i < (sizeof(struct dmae_command)/4); i++) { | 167 | for (i = 0; i < (sizeof(struct dmae_command)/4); i++) { |
170 | REG_WR(bp, cmd_offset + i*4, *(((u32 *)dmae) + i)); | 168 | REG_WR(bp, cmd_offset + i*4, *(((u32 *)dmae) + i)); |
171 | 169 | ||
172 | /* DP(NETIF_MSG_DMAE, "DMAE cmd[%d].%d (0x%08x) : 0x%08x\n", | 170 | DP(BNX2X_MSG_OFF, "DMAE cmd[%d].%d (0x%08x) : 0x%08x\n", |
173 | idx, i, cmd_offset + i*4, *(((u32 *)dmae) + i)); */ | 171 | idx, i, cmd_offset + i*4, *(((u32 *)dmae) + i)); |
174 | } | 172 | } |
175 | REG_WR(bp, dmae_reg_go_c[idx], 1); | 173 | REG_WR(bp, dmae_reg_go_c[idx], 1); |
176 | } | 174 | } |
177 | 175 | ||
178 | void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, | 176 | void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, |
179 | u32 dst_addr, u32 len32) | 177 | u32 len32) |
180 | { | 178 | { |
181 | struct dmae_command *dmae = &bp->dmae; | 179 | struct dmae_command *dmae = &bp->init_dmae; |
182 | int port = bp->port; | ||
183 | u32 *wb_comp = bnx2x_sp(bp, wb_comp); | 180 | u32 *wb_comp = bnx2x_sp(bp, wb_comp); |
184 | int timeout = 200; | 181 | int cnt = 200; |
182 | |||
183 | if (!bp->dmae_ready) { | ||
184 | u32 *data = bnx2x_sp(bp, wb_data[0]); | ||
185 | |||
186 | DP(BNX2X_MSG_OFF, "DMAE is not ready (dst_addr %08x len32 %d)" | ||
187 | " using indirect\n", dst_addr, len32); | ||
188 | bnx2x_init_ind_wr(bp, dst_addr, data, len32); | ||
189 | return; | ||
190 | } | ||
191 | |||
192 | mutex_lock(&bp->dmae_mutex); | ||
185 | 193 | ||
186 | memset(dmae, 0, sizeof(struct dmae_command)); | 194 | memset(dmae, 0, sizeof(struct dmae_command)); |
187 | 195 | ||
@@ -193,7 +201,7 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, | |||
193 | #else | 201 | #else |
194 | DMAE_CMD_ENDIANITY_DW_SWAP | | 202 | DMAE_CMD_ENDIANITY_DW_SWAP | |
195 | #endif | 203 | #endif |
196 | (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0)); | 204 | (bp->port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0)); |
197 | dmae->src_addr_lo = U64_LO(dma_addr); | 205 | dmae->src_addr_lo = U64_LO(dma_addr); |
198 | dmae->src_addr_hi = U64_HI(dma_addr); | 206 | dmae->src_addr_hi = U64_HI(dma_addr); |
199 | dmae->dst_addr_lo = dst_addr >> 2; | 207 | dmae->dst_addr_lo = dst_addr >> 2; |
@@ -201,48 +209,62 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, | |||
201 | dmae->len = len32; | 209 | dmae->len = len32; |
202 | dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp)); | 210 | dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp)); |
203 | dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp)); | 211 | dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp)); |
204 | dmae->comp_val = BNX2X_WB_COMP_VAL; | 212 | dmae->comp_val = DMAE_COMP_VAL; |
205 | 213 | ||
206 | /* | 214 | DP(BNX2X_MSG_OFF, "dmae: opcode 0x%08x\n" |
207 | DP(NETIF_MSG_DMAE, "dmae: opcode 0x%08x\n" | ||
208 | DP_LEVEL "src_addr [%x:%08x] len [%d *4] " | 215 | DP_LEVEL "src_addr [%x:%08x] len [%d *4] " |
209 | "dst_addr [%x:%08x (%08x)]\n" | 216 | "dst_addr [%x:%08x (%08x)]\n" |
210 | DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n", | 217 | DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n", |
211 | dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo, | 218 | dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo, |
212 | dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo, dst_addr, | 219 | dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo, dst_addr, |
213 | dmae->comp_addr_hi, dmae->comp_addr_lo, dmae->comp_val); | 220 | dmae->comp_addr_hi, dmae->comp_addr_lo, dmae->comp_val); |
214 | */ | 221 | DP(BNX2X_MSG_OFF, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n", |
215 | /* | ||
216 | DP(NETIF_MSG_DMAE, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n", | ||
217 | bp->slowpath->wb_data[0], bp->slowpath->wb_data[1], | 222 | bp->slowpath->wb_data[0], bp->slowpath->wb_data[1], |
218 | bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]); | 223 | bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]); |
219 | */ | ||
220 | 224 | ||
221 | *wb_comp = 0; | 225 | *wb_comp = 0; |
222 | 226 | ||
223 | bnx2x_post_dmae(bp, dmae, port * 8); | 227 | bnx2x_post_dmae(bp, dmae, (bp->port)*MAX_DMAE_C_PER_PORT); |
224 | 228 | ||
225 | udelay(5); | 229 | udelay(5); |
226 | /* adjust timeout for emulation/FPGA */ | 230 | |
227 | if (CHIP_REV_IS_SLOW(bp)) | 231 | while (*wb_comp != DMAE_COMP_VAL) { |
228 | timeout *= 100; | 232 | DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp); |
229 | while (*wb_comp != BNX2X_WB_COMP_VAL) { | 233 | |
230 | /* DP(NETIF_MSG_DMAE, "wb_comp 0x%08x\n", *wb_comp); */ | 234 | /* adjust delay for emulation/FPGA */ |
231 | udelay(5); | 235 | if (CHIP_REV_IS_SLOW(bp)) |
232 | if (!timeout) { | 236 | msleep(100); |
237 | else | ||
238 | udelay(5); | ||
239 | |||
240 | if (!cnt) { | ||
233 | BNX2X_ERR("dmae timeout!\n"); | 241 | BNX2X_ERR("dmae timeout!\n"); |
234 | break; | 242 | break; |
235 | } | 243 | } |
236 | timeout--; | 244 | cnt--; |
237 | } | 245 | } |
246 | |||
247 | mutex_unlock(&bp->dmae_mutex); | ||
238 | } | 248 | } |
239 | 249 | ||
240 | void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) | 250 | void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) |
241 | { | 251 | { |
242 | struct dmae_command *dmae = &bp->dmae; | 252 | struct dmae_command *dmae = &bp->init_dmae; |
243 | int port = bp->port; | ||
244 | u32 *wb_comp = bnx2x_sp(bp, wb_comp); | 253 | u32 *wb_comp = bnx2x_sp(bp, wb_comp); |
245 | int timeout = 200; | 254 | int cnt = 200; |
255 | |||
256 | if (!bp->dmae_ready) { | ||
257 | u32 *data = bnx2x_sp(bp, wb_data[0]); | ||
258 | int i; | ||
259 | |||
260 | DP(BNX2X_MSG_OFF, "DMAE is not ready (src_addr %08x len32 %d)" | ||
261 | " using indirect\n", src_addr, len32); | ||
262 | for (i = 0; i < len32; i++) | ||
263 | data[i] = bnx2x_reg_rd_ind(bp, src_addr + i*4); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | mutex_lock(&bp->dmae_mutex); | ||
246 | 268 | ||
247 | memset(bnx2x_sp(bp, wb_data[0]), 0, sizeof(u32) * 4); | 269 | memset(bnx2x_sp(bp, wb_data[0]), 0, sizeof(u32) * 4); |
248 | memset(dmae, 0, sizeof(struct dmae_command)); | 270 | memset(dmae, 0, sizeof(struct dmae_command)); |
@@ -255,7 +277,7 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) | |||
255 | #else | 277 | #else |
256 | DMAE_CMD_ENDIANITY_DW_SWAP | | 278 | DMAE_CMD_ENDIANITY_DW_SWAP | |
257 | #endif | 279 | #endif |
258 | (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0)); | 280 | (bp->port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0)); |
259 | dmae->src_addr_lo = src_addr >> 2; | 281 | dmae->src_addr_lo = src_addr >> 2; |
260 | dmae->src_addr_hi = 0; | 282 | dmae->src_addr_hi = 0; |
261 | dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data)); | 283 | dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data)); |
@@ -263,38 +285,64 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) | |||
263 | dmae->len = len32; | 285 | dmae->len = len32; |
264 | dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp)); | 286 | dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp)); |
265 | dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp)); | 287 | dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp)); |
266 | dmae->comp_val = BNX2X_WB_COMP_VAL; | 288 | dmae->comp_val = DMAE_COMP_VAL; |
267 | 289 | ||
268 | /* | 290 | DP(BNX2X_MSG_OFF, "dmae: opcode 0x%08x\n" |
269 | DP(NETIF_MSG_DMAE, "dmae: opcode 0x%08x\n" | ||
270 | DP_LEVEL "src_addr [%x:%08x] len [%d *4] " | 291 | DP_LEVEL "src_addr [%x:%08x] len [%d *4] " |
271 | "dst_addr [%x:%08x (%08x)]\n" | 292 | "dst_addr [%x:%08x (%08x)]\n" |
272 | DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n", | 293 | DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n", |
273 | dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo, | 294 | dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo, |
274 | dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo, src_addr, | 295 | dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo, src_addr, |
275 | dmae->comp_addr_hi, dmae->comp_addr_lo, dmae->comp_val); | 296 | dmae->comp_addr_hi, dmae->comp_addr_lo, dmae->comp_val); |
276 | */ | ||
277 | 297 | ||
278 | *wb_comp = 0; | 298 | *wb_comp = 0; |
279 | 299 | ||
280 | bnx2x_post_dmae(bp, dmae, port * 8); | 300 | bnx2x_post_dmae(bp, dmae, (bp->port)*MAX_DMAE_C_PER_PORT); |
281 | 301 | ||
282 | udelay(5); | 302 | udelay(5); |
283 | while (*wb_comp != BNX2X_WB_COMP_VAL) { | 303 | |
284 | udelay(5); | 304 | while (*wb_comp != DMAE_COMP_VAL) { |
285 | if (!timeout) { | 305 | |
306 | /* adjust delay for emulation/FPGA */ | ||
307 | if (CHIP_REV_IS_SLOW(bp)) | ||
308 | msleep(100); | ||
309 | else | ||
310 | udelay(5); | ||
311 | |||
312 | if (!cnt) { | ||
286 | BNX2X_ERR("dmae timeout!\n"); | 313 | BNX2X_ERR("dmae timeout!\n"); |
287 | break; | 314 | break; |
288 | } | 315 | } |
289 | timeout--; | 316 | cnt--; |
290 | } | 317 | } |
291 | /* | 318 | DP(BNX2X_MSG_OFF, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n", |
292 | DP(NETIF_MSG_DMAE, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n", | ||
293 | bp->slowpath->wb_data[0], bp->slowpath->wb_data[1], | 319 | bp->slowpath->wb_data[0], bp->slowpath->wb_data[1], |
294 | bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]); | 320 | bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]); |
295 | */ | 321 | |
322 | mutex_unlock(&bp->dmae_mutex); | ||
323 | } | ||
324 | |||
325 | /* used only for slowpath so not inlined */ | ||
326 | static void bnx2x_wb_wr(struct bnx2x *bp, int reg, u32 val_hi, u32 val_lo) | ||
327 | { | ||
328 | u32 wb_write[2]; | ||
329 | |||
330 | wb_write[0] = val_hi; | ||
331 | wb_write[1] = val_lo; | ||
332 | REG_WR_DMAE(bp, reg, wb_write, 2); | ||
296 | } | 333 | } |
297 | 334 | ||
335 | #ifdef USE_WB_RD | ||
336 | static u64 bnx2x_wb_rd(struct bnx2x *bp, int reg) | ||
337 | { | ||
338 | u32 wb_data[2]; | ||
339 | |||
340 | REG_RD_DMAE(bp, reg, wb_data, 2); | ||
341 | |||
342 | return HILO_U64(wb_data[0], wb_data[1]); | ||
343 | } | ||
344 | #endif | ||
345 | |||
298 | static int bnx2x_mc_assert(struct bnx2x *bp) | 346 | static int bnx2x_mc_assert(struct bnx2x *bp) |
299 | { | 347 | { |
300 | int i, j, rc = 0; | 348 | int i, j, rc = 0; |
@@ -3438,17 +3486,12 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) | |||
3438 | int count, i; | 3486 | int count, i; |
3439 | u32 val = 0; | 3487 | u32 val = 0; |
3440 | 3488 | ||
3441 | switch (CHIP_REV(bp)) { | 3489 | if (CHIP_REV_IS_FPGA(bp)) |
3442 | case CHIP_REV_EMUL: | ||
3443 | factor = 200; | ||
3444 | break; | ||
3445 | case CHIP_REV_FPGA: | ||
3446 | factor = 120; | 3490 | factor = 120; |
3447 | break; | 3491 | else if (CHIP_REV_IS_EMUL(bp)) |
3448 | default: | 3492 | factor = 200; |
3493 | else | ||
3449 | factor = 1; | 3494 | factor = 1; |
3450 | break; | ||
3451 | } | ||
3452 | 3495 | ||
3453 | DP(NETIF_MSG_HW, "start part1\n"); | 3496 | DP(NETIF_MSG_HW, "start part1\n"); |
3454 | 3497 | ||
@@ -3777,10 +3820,14 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) | |||
3777 | bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END); | 3820 | bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END); |
3778 | bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END); | 3821 | bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END); |
3779 | 3822 | ||
3780 | bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE); | 3823 | bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0, |
3781 | bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE); | 3824 | STORM_INTMEM_SIZE_E1); |
3782 | bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE); | 3825 | bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0, |
3783 | bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE); | 3826 | STORM_INTMEM_SIZE_E1); |
3827 | bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR, 0, | ||
3828 | STORM_INTMEM_SIZE_E1); | ||
3829 | bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0, | ||
3830 | STORM_INTMEM_SIZE_E1); | ||
3784 | 3831 | ||
3785 | bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END); | 3832 | bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END); |
3786 | bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END); | 3833 | bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END); |
@@ -3990,8 +4037,7 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) | |||
3990 | #endif | 4037 | #endif |
3991 | /* Port DQ comes here */ | 4038 | /* Port DQ comes here */ |
3992 | /* Port BRB1 comes here */ | 4039 | /* Port BRB1 comes here */ |
3993 | bnx2x_init_block(bp, func ? PRS_PORT1_START : PRS_PORT0_START, | 4040 | /* Port PRS comes here */ |
3994 | func ? PRS_PORT1_END : PRS_PORT0_END); | ||
3995 | /* Port TSDM comes here */ | 4041 | /* Port TSDM comes here */ |
3996 | /* Port CSDM comes here */ | 4042 | /* Port CSDM comes here */ |
3997 | /* Port USDM comes here */ | 4043 | /* Port USDM comes here */ |
@@ -7264,12 +7310,6 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev, | |||
7264 | 7310 | ||
7265 | bnx2x_get_hwinfo(bp); | 7311 | bnx2x_get_hwinfo(bp); |
7266 | 7312 | ||
7267 | if (CHIP_REV(bp) == CHIP_REV_FPGA) { | ||
7268 | printk(KERN_ERR PFX "FPGA detected. MCP disabled," | ||
7269 | " will only init first device\n"); | ||
7270 | onefunc = 1; | ||
7271 | nomcp = 1; | ||
7272 | } | ||
7273 | 7313 | ||
7274 | if (nomcp) { | 7314 | if (nomcp) { |
7275 | printk(KERN_ERR PFX "MCP disabled, will only" | 7315 | printk(KERN_ERR PFX "MCP disabled, will only" |