aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/igb/e1000_nvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/igb/e1000_nvm.c')
-rw-r--r--drivers/net/igb/e1000_nvm.c157
1 files changed, 150 insertions, 7 deletions
diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c
index d83b77fa4038..75bf36a4baee 100644
--- a/drivers/net/igb/e1000_nvm.c
+++ b/drivers/net/igb/e1000_nvm.c
@@ -318,6 +318,68 @@ out:
318} 318}
319 319
320/** 320/**
321 * igb_read_nvm_spi - Read EEPROM's using SPI
322 * @hw: pointer to the HW structure
323 * @offset: offset of word in the EEPROM to read
324 * @words: number of words to read
325 * @data: word read from the EEPROM
326 *
327 * Reads a 16 bit word from the EEPROM.
328 **/
329s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
330{
331 struct e1000_nvm_info *nvm = &hw->nvm;
332 u32 i = 0;
333 s32 ret_val;
334 u16 word_in;
335 u8 read_opcode = NVM_READ_OPCODE_SPI;
336
337 /*
338 * A check for invalid values: offset too large, too many words,
339 * and not enough words.
340 */
341 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
342 (words == 0)) {
343 hw_dbg("nvm parameter(s) out of bounds\n");
344 ret_val = -E1000_ERR_NVM;
345 goto out;
346 }
347
348 ret_val = nvm->ops.acquire(hw);
349 if (ret_val)
350 goto out;
351
352 ret_val = igb_ready_nvm_eeprom(hw);
353 if (ret_val)
354 goto release;
355
356 igb_standby_nvm(hw);
357
358 if ((nvm->address_bits == 8) && (offset >= 128))
359 read_opcode |= NVM_A8_OPCODE_SPI;
360
361 /* Send the READ command (opcode + addr) */
362 igb_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
363 igb_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
364
365 /*
366 * Read the data. SPI NVMs increment the address with each byte
367 * read and will roll over if reading beyond the end. This allows
368 * us to read the whole NVM from any offset
369 */
370 for (i = 0; i < words; i++) {
371 word_in = igb_shift_in_eec_bits(hw, 16);
372 data[i] = (word_in >> 8) | (word_in << 8);
373 }
374
375release:
376 nvm->ops.release(hw);
377
378out:
379 return ret_val;
380}
381
382/**
321 * igb_read_nvm_eerd - Reads EEPROM using EERD register 383 * igb_read_nvm_eerd - Reads EEPROM using EERD register
322 * @hw: pointer to the HW structure 384 * @hw: pointer to the HW structure
323 * @offset: offset of word in the EEPROM to read 385 * @offset: offset of word in the EEPROM to read
@@ -353,7 +415,7 @@ s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
353 break; 415 break;
354 416
355 data[i] = (rd32(E1000_EERD) >> 417 data[i] = (rd32(E1000_EERD) >>
356 E1000_NVM_RW_REG_DATA); 418 E1000_NVM_RW_REG_DATA);
357 } 419 }
358 420
359out: 421out:
@@ -445,31 +507,112 @@ out:
445} 507}
446 508
447/** 509/**
448 * igb_read_part_num - Read device part number 510 * igb_read_part_string - Read device part number
449 * @hw: pointer to the HW structure 511 * @hw: pointer to the HW structure
450 * @part_num: pointer to device part number 512 * @part_num: pointer to device part number
513 * @part_num_size: size of part number buffer
451 * 514 *
452 * Reads the product board assembly (PBA) number from the EEPROM and stores 515 * Reads the product board assembly (PBA) number from the EEPROM and stores
453 * the value in part_num. 516 * the value in part_num.
454 **/ 517 **/
455s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num) 518s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size)
456{ 519{
457 s32 ret_val; 520 s32 ret_val;
458 u16 nvm_data; 521 u16 nvm_data;
522 u16 pointer;
523 u16 offset;
524 u16 length;
525
526 if (part_num == NULL) {
527 hw_dbg("PBA string buffer was null\n");
528 ret_val = E1000_ERR_INVALID_ARGUMENT;
529 goto out;
530 }
459 531
460 ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); 532 ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
461 if (ret_val) { 533 if (ret_val) {
462 hw_dbg("NVM Read Error\n"); 534 hw_dbg("NVM Read Error\n");
463 goto out; 535 goto out;
464 } 536 }
465 *part_num = (u32)(nvm_data << 16);
466 537
467 ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); 538 ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pointer);
539 if (ret_val) {
540 hw_dbg("NVM Read Error\n");
541 goto out;
542 }
543
544 /*
545 * if nvm_data is not ptr guard the PBA must be in legacy format which
546 * means pointer is actually our second data word for the PBA number
547 * and we can decode it into an ascii string
548 */
549 if (nvm_data != NVM_PBA_PTR_GUARD) {
550 hw_dbg("NVM PBA number is not stored as string\n");
551
552 /* we will need 11 characters to store the PBA */
553 if (part_num_size < 11) {
554 hw_dbg("PBA string buffer too small\n");
555 return E1000_ERR_NO_SPACE;
556 }
557
558 /* extract hex string from data and pointer */
559 part_num[0] = (nvm_data >> 12) & 0xF;
560 part_num[1] = (nvm_data >> 8) & 0xF;
561 part_num[2] = (nvm_data >> 4) & 0xF;
562 part_num[3] = nvm_data & 0xF;
563 part_num[4] = (pointer >> 12) & 0xF;
564 part_num[5] = (pointer >> 8) & 0xF;
565 part_num[6] = '-';
566 part_num[7] = 0;
567 part_num[8] = (pointer >> 4) & 0xF;
568 part_num[9] = pointer & 0xF;
569
570 /* put a null character on the end of our string */
571 part_num[10] = '\0';
572
573 /* switch all the data but the '-' to hex char */
574 for (offset = 0; offset < 10; offset++) {
575 if (part_num[offset] < 0xA)
576 part_num[offset] += '0';
577 else if (part_num[offset] < 0x10)
578 part_num[offset] += 'A' - 0xA;
579 }
580
581 goto out;
582 }
583
584 ret_val = hw->nvm.ops.read(hw, pointer, 1, &length);
468 if (ret_val) { 585 if (ret_val) {
469 hw_dbg("NVM Read Error\n"); 586 hw_dbg("NVM Read Error\n");
470 goto out; 587 goto out;
471 } 588 }
472 *part_num |= nvm_data; 589
590 if (length == 0xFFFF || length == 0) {
591 hw_dbg("NVM PBA number section invalid length\n");
592 ret_val = E1000_ERR_NVM_PBA_SECTION;
593 goto out;
594 }
595 /* check if part_num buffer is big enough */
596 if (part_num_size < (((u32)length * 2) - 1)) {
597 hw_dbg("PBA string buffer too small\n");
598 ret_val = E1000_ERR_NO_SPACE;
599 goto out;
600 }
601
602 /* trim pba length from start of string */
603 pointer++;
604 length--;
605
606 for (offset = 0; offset < length; offset++) {
607 ret_val = hw->nvm.ops.read(hw, pointer + offset, 1, &nvm_data);
608 if (ret_val) {
609 hw_dbg("NVM Read Error\n");
610 goto out;
611 }
612 part_num[offset * 2] = (u8)(nvm_data >> 8);
613 part_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
614 }
615 part_num[offset * 2] = '\0';
473 616
474out: 617out:
475 return ret_val; 618 return ret_val;