Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.31-rc2 442 lines 12 kB view raw
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 */ 14#ifndef BNX2X_INIT_OPS_H 15#define BNX2X_INIT_OPS_H 16 17static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); 18static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len); 19 20static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data, 21 u32 len) 22{ 23 int i; 24 25 for (i = 0; i < len; i++) { 26 REG_WR(bp, addr + i*4, data[i]); 27 if (!(i % 10000)) { 28 touch_softlockup_watchdog(); 29 cpu_relax(); 30 } 31 } 32} 33 34static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data, 35 u16 len) 36{ 37 int i; 38 39 for (i = 0; i < len; i++) { 40 REG_WR_IND(bp, addr + i*4, data[i]); 41 if (!(i % 10000)) { 42 touch_softlockup_watchdog(); 43 cpu_relax(); 44 } 45 } 46} 47 48static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) 49{ 50 int offset = 0; 51 52 if (bp->dmae_ready) { 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; 58 } 59 bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, 60 addr + offset, len); 61 } else 62 bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); 63} 64 65static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len) 66{ 67 u32 buf_len = (((len * 4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len * 4)); 68 u32 buf_len32 = buf_len / 4; 69 int i; 70 71 memset(bp->gunzip_buf, fill, buf_len); 72 73 for (i = 0; i < len; i += buf_len32) { 74 u32 cur_len = min(buf_len32, len - i); 75 76 bnx2x_write_big_buf(bp, addr + i * 4, cur_len); 77 } 78} 79 80static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data, 81 u32 len64) 82{ 83 u32 buf_len32 = FW_BUF_SIZE / 4; 84 u32 len = len64 * 2; 85 u64 data64 = 0; 86 int i; 87 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; 93 94 *pdata = data64; 95 } 96 97 for (i = 0; i < len; i += buf_len32) { 98 u32 cur_len = min(buf_len32, len - i); 99 100 bnx2x_write_big_buf(bp, addr + i * 4, cur_len); 101 } 102} 103 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))) 114 115#define IF_IS_PRAM_ADDR(base, addr) \ 116 if (((base) <= (addr)) && ((base) + 0x40000 >= (addr))) 117 118static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data) 119{ 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; 136 137 return data; 138} 139 140static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len) 141{ 142 int offset = 0; 143 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; 150 } 151 bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, 152 addr + offset, len); 153 } else 154 bnx2x_init_ind_wr(bp, addr, bp->gunzip_buf, len); 155} 156 157static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data, 158 u32 len) 159{ 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); 163 164 if ((len * 4) > FW_BUF_SIZE) { 165 BNX2X_ERR("LARGE DMAE OPERATION ! " 166 "addr 0x%x len 0x%x\n", addr, len*4); 167 return; 168 } 169 memcpy(bp->gunzip_buf, data, len * 4); 170 171 bnx2x_write_big_buf_wb(bp, addr, len); 172} 173 174static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, 175 u32 len, u32 blob_off) 176{ 177 int rc, i; 178 const u8 *data = NULL; 179 180 data = bnx2x_sel_blob(bp, addr, data) + 4*blob_off; 181 182 if (data == NULL) { 183 panic("Blob not found for addr 0x%x\n", addr); 184 return; 185 } 186 187 rc = bnx2x_gunzip(bp, data, len); 188 if (rc) { 189 BNX2X_ERR("gunzip failed ! addr 0x%x rc %d\n", addr, rc); 190 BNX2X_ERR("blob_offset=0x%x\n", blob_off); 191 return; 192 } 193 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]); 199 200 bnx2x_write_big_buf_wb(bp, addr, len); 201} 202 203static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage) 204{ 205 int hw_wr, i; 206 u16 op_start = 207 bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_START)]; 208 u16 op_end = 209 bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_END)]; 210 union init_op *op; 211 u32 op_type, addr, len; 212 const u32 *data, *data_base; 213 214 /* If empty block */ 215 if (op_start == op_end) 216 return; 217 218 if (CHIP_REV_IS_FPGA(bp)) 219 hw_wr = OP_WR_FPGA; 220 else if (CHIP_REV_IS_EMUL(bp)) 221 hw_wr = OP_WR_EMUL; 222 else 223 hw_wr = OP_WR_ASIC; 224 225 data_base = bp->init_data; 226 227 for (i = op_start; i < op_end; i++) { 228 229 op = (union init_op *)&(bp->init_ops[i]); 230 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; 235 236 /* HW/EMUL specific */ 237 if (unlikely((op_type > OP_WB) && (op_type == hw_wr))) 238 op_type = OP_WR; 239 240 switch (op_type) { 241 case OP_RD: 242 REG_RD(bp, addr); 243 break; 244 case OP_WR: 245 REG_WR(bp, addr, op->write.val); 246 break; 247 case OP_SW: 248 bnx2x_init_str_wr(bp, addr, data, len); 249 break; 250 case OP_WB: 251 bnx2x_init_wr_wb(bp, addr, data, len); 252 break; 253 case OP_SI: 254 bnx2x_init_ind_wr(bp, addr, data, len); 255 break; 256 case OP_ZR: 257 bnx2x_init_fill(bp, addr, 0, op->zero.len); 258 break; 259 case OP_ZP: 260 bnx2x_init_wr_zp(bp, addr, len, 261 op->str_wr.data_off); 262 break; 263 case OP_WR_64: 264 bnx2x_init_wr_64(bp, addr, data, len); 265 break; 266 default: 267 /* happens whenever an op is of a diff HW */ 268#if 0 269 DP(NETIF_MSG_HW, "skipping init operation " 270 "index %d[%d:%d]: type %d addr 0x%x " 271 "len %d(0x%x)\n", 272 i, op_start, op_end, op_type, addr, len, len); 273#endif 274 break; 275 } 276 } 277} 278 279/* PXP */ 280static void bnx2x_init_pxp(struct bnx2x *bp) 281{ 282 u16 devctl; 283 int r_order, w_order; 284 u32 val, i; 285 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); 290 if (bp->mrrs == -1) 291 r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12); 292 else { 293 DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs); 294 r_order = bp->mrrs; 295 } 296 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; 301 } 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; 306 } 307 if (CHIP_REV_IS_FPGA(bp)) { 308 DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n"); 309 w_order = 0; 310 } 311 DP(NETIF_MSG_HW, "read order %d write order %d\n", r_order, w_order); 312 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); 319 } 320 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)) { 324 325 REG_WR(bp, write_arb_addr[i].l, 326 write_arb_data[i][w_order].l); 327 328 REG_WR(bp, write_arb_addr[i].add, 329 write_arb_data[i][w_order].add); 330 331 REG_WR(bp, write_arb_addr[i].ubound, 332 write_arb_data[i][w_order].ubound); 333 } else { 334 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)); 338 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)); 342 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)); 346 } 347 } 348 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); 353 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); 358 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); 363 364 if (r_order == MAX_RD_ORD) 365 REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00); 366 367 REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); 368 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); 382 } 383} 384 385/***************************************************************************** 386 * Description: 387 * Calculates crc 8 on a word value: polynomial 0-1-2-8 388 * Code was translated from Verilog. 389 ****************************************************************************/ 390static u8 calc_crc8(u32 data, u8 crc) 391{ 392 u8 D[32]; 393 u8 NewCRC[8]; 394 u8 C[8]; 395 u8 crc_res; 396 u8 i; 397 398 /* split the data into 31 bits */ 399 for (i = 0; i < 32; i++) { 400 D[i] = data & 1; 401 data = data >> 1; 402 } 403 404 /* split the crc into 8 bits */ 405 for (i = 0; i < 8; i++) { 406 C[i] = crc & 1; 407 crc = crc >> 1; 408 } 409 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] ^ 412 C[6] ^ C[7]; 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] ^ 427 C[3] ^ C[4] ^ C[7]; 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] ^ 430 C[5]; 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] ^ 433 C[6]; 434 435 crc_res = 0; 436 for (i = 0; i < 8; i++) 437 crc_res |= (NewCRC[i] << i); 438 439 return crc_res; 440} 441 442#endif /* BNX2X_INIT_OPS_H */