Deleted Added
full compact
ixgbe_phy.c (181003) ixgbe_phy.c (185352)
1/******************************************************************************
2
3 Copyright (c) 2001-2008, Intel Corporation
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8

--- 16 unchanged lines hidden (view full) ---

25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
31
32******************************************************************************/
1/******************************************************************************
2
3 Copyright (c) 2001-2008, Intel Corporation
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8

--- 16 unchanged lines hidden (view full) ---

25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
31
32******************************************************************************/
33/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_phy.c 181003 2008-07-30 18:15:18Z jfv $*/
33/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_phy.c 185352 2008-11-26 23:41:18Z jfv $*/
34
35#include "ixgbe_api.h"
36#include "ixgbe_common.h"
37#include "ixgbe_phy.h"
38
39/**
40 * ixgbe_init_phy_ops_generic - Inits PHY function ptrs
41 * @hw: pointer to the hardware structure

--- 8 unchanged lines hidden (view full) ---

50 phy->ops.identify = &ixgbe_identify_phy_generic;
51 phy->ops.reset = &ixgbe_reset_phy_generic;
52 phy->ops.read_reg = &ixgbe_read_phy_reg_generic;
53 phy->ops.write_reg = &ixgbe_write_phy_reg_generic;
54 phy->ops.setup_link = &ixgbe_setup_phy_link_generic;
55 phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic;
56 phy->ops.check_link = NULL;
57 phy->ops.get_firmware_version = NULL;
34
35#include "ixgbe_api.h"
36#include "ixgbe_common.h"
37#include "ixgbe_phy.h"
38
39/**
40 * ixgbe_init_phy_ops_generic - Inits PHY function ptrs
41 * @hw: pointer to the hardware structure

--- 8 unchanged lines hidden (view full) ---

50 phy->ops.identify = &ixgbe_identify_phy_generic;
51 phy->ops.reset = &ixgbe_reset_phy_generic;
52 phy->ops.read_reg = &ixgbe_read_phy_reg_generic;
53 phy->ops.write_reg = &ixgbe_write_phy_reg_generic;
54 phy->ops.setup_link = &ixgbe_setup_phy_link_generic;
55 phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic;
56 phy->ops.check_link = NULL;
57 phy->ops.get_firmware_version = NULL;
58 phy->ops.identify_sfp = &ixgbe_identify_sfp_module_generic;
59 phy->sfp_type = ixgbe_sfp_type_unknown;
58
59 return IXGBE_SUCCESS;
60}
61
62/**
63 * ixgbe_identify_phy_generic - Get physical layer module
64 * @hw: pointer to hardware structure
65 *

--- 60 unchanged lines hidden (view full) ---

126 if (status == IXGBE_SUCCESS) {
127 hw->phy.id = (u32)(phy_id_high << 16);
128 status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW,
129 IXGBE_MDIO_PMA_PMD_DEV_TYPE,
130 &phy_id_low);
131 hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK);
132 hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK);
133 }
60
61 return IXGBE_SUCCESS;
62}
63
64/**
65 * ixgbe_identify_phy_generic - Get physical layer module
66 * @hw: pointer to hardware structure
67 *

--- 60 unchanged lines hidden (view full) ---

128 if (status == IXGBE_SUCCESS) {
129 hw->phy.id = (u32)(phy_id_high << 16);
130 status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW,
131 IXGBE_MDIO_PMA_PMD_DEV_TYPE,
132 &phy_id_low);
133 hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK);
134 hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK);
135 }
134
135 return status;
136}
137
138/**
139 * ixgbe_get_phy_type_from_id - Get the phy type
140 * @hw: pointer to hardware structure
141 *
142 **/
143enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
144{
145 enum ixgbe_phy_type phy_type;
146
147 switch (phy_id) {
148 case TN1010_PHY_ID:
149 phy_type = ixgbe_phy_tn;
150 break;
151 case QT2022_PHY_ID:
152 phy_type = ixgbe_phy_qt;
153 break;
136 return status;
137}
138
139/**
140 * ixgbe_get_phy_type_from_id - Get the phy type
141 * @hw: pointer to hardware structure
142 *
143 **/
144enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
145{
146 enum ixgbe_phy_type phy_type;
147
148 switch (phy_id) {
149 case TN1010_PHY_ID:
150 phy_type = ixgbe_phy_tn;
151 break;
152 case QT2022_PHY_ID:
153 phy_type = ixgbe_phy_qt;
154 break;
155 case ATH_PHY_ID:
156 phy_type = ixgbe_phy_nl;
157 break;
154 default:
155 phy_type = ixgbe_phy_unknown;
156 break;
157 }
158
159 DEBUGOUT1("phy type found is %d\n", phy_type);
160 return phy_type;
161}

--- 50 unchanged lines hidden (view full) ---

212 * The MDI Command bit will clear when the operation is
213 * complete
214 */
215 for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
216 usec_delay(10);
217
218 command = IXGBE_READ_REG(hw, IXGBE_MSCA);
219
158 default:
159 phy_type = ixgbe_phy_unknown;
160 break;
161 }
162
163 DEBUGOUT1("phy type found is %d\n", phy_type);
164 return phy_type;
165}

--- 50 unchanged lines hidden (view full) ---

216 * The MDI Command bit will clear when the operation is
217 * complete
218 */
219 for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
220 usec_delay(10);
221
222 command = IXGBE_READ_REG(hw, IXGBE_MSCA);
223
220 if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
224 if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
221 break;
225 break;
222 }
223 }
224
225 if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
226 DEBUGOUT("PHY address command did not complete.\n");
227 status = IXGBE_ERR_PHY;
228 }
229
230 if (status == IXGBE_SUCCESS) {

--- 209 unchanged lines hidden (view full) ---

440 UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
441
442 /*
443 * Clear autoneg_advertised and set new values based on input link
444 * speed.
445 */
446 hw->phy.autoneg_advertised = 0;
447
226 }
227
228 if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
229 DEBUGOUT("PHY address command did not complete.\n");
230 status = IXGBE_ERR_PHY;
231 }
232
233 if (status == IXGBE_SUCCESS) {

--- 209 unchanged lines hidden (view full) ---

443 UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
444
445 /*
446 * Clear autoneg_advertised and set new values based on input link
447 * speed.
448 */
449 hw->phy.autoneg_advertised = 0;
450
448 if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
451 if (speed & IXGBE_LINK_SPEED_10GB_FULL)
449 hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
452 hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
450 }
451 if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
453
454 if (speed & IXGBE_LINK_SPEED_1GB_FULL)
452 hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
455 hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
453 }
454
455 /* Setup link based on the new speed settings */
456 hw->phy.ops.setup_link(hw);
457
458 return IXGBE_SUCCESS;
459}
460
461/**

--- 56 unchanged lines hidden (view full) ---

518
519 status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
520 IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
521 firmware_version);
522
523 return status;
524}
525
456
457 /* Setup link based on the new speed settings */
458 hw->phy.ops.setup_link(hw);
459
460 return IXGBE_SUCCESS;
461}
462
463/**

--- 56 unchanged lines hidden (view full) ---

520
521 status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
522 IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
523 firmware_version);
524
525 return status;
526}
527
528/**
529 * ixgbe_reset_phy_nl - Performs a PHY reset
530 * @hw: pointer to hardware structure
531 **/
532s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
533{
534 u16 phy_offset, control, eword, edata, block_crc;
535 bool end_data = FALSE;
536 u16 list_offset, data_offset;
537 u16 phy_data = 0;
538 s32 ret_val = IXGBE_SUCCESS;
539 u32 i;
540
541 hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
542 IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
543
544 /* reset the PHY and poll for completion */
545 hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
546 IXGBE_MDIO_PHY_XS_DEV_TYPE,
547 (phy_data | IXGBE_MDIO_PHY_XS_RESET));
548
549 for (i = 0; i < 100; i++) {
550 hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
551 IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
552 if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0)
553 break;
554 msec_delay(10);
555 }
556
557 if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) {
558 DEBUGOUT("PHY reset did not complete.\n");
559 ret_val = IXGBE_ERR_PHY;
560 goto out;
561 }
562
563 /* Get init offsets */
564 ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
565 &data_offset);
566 if (ret_val != IXGBE_SUCCESS)
567 goto out;
568
569 ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc);
570 data_offset++;
571 while (!end_data) {
572 /*
573 * Read control word from PHY init contents offset
574 */
575 ret_val = hw->eeprom.ops.read(hw, data_offset, &eword);
576 control = (eword & IXGBE_CONTROL_MASK_NL) >>
577 IXGBE_CONTROL_SHIFT_NL;
578 edata = eword & IXGBE_DATA_MASK_NL;
579 switch (control) {
580 case IXGBE_DELAY_NL:
581 data_offset++;
582 DEBUGOUT1("DELAY: %d MS\n", edata);
583 msec_delay(edata);
584 break;
585 case IXGBE_DATA_NL:
586 DEBUGOUT("DATA: \n");
587 data_offset++;
588 hw->eeprom.ops.read(hw, data_offset++,
589 &phy_offset);
590 for (i = 0; i < edata; i++) {
591 hw->eeprom.ops.read(hw, data_offset, &eword);
592 hw->phy.ops.write_reg(hw, phy_offset,
593 IXGBE_TWINAX_DEV, eword);
594 DEBUGOUT2("Wrote %4.4x to %4.4x\n", eword,
595 phy_offset);
596 data_offset++;
597 phy_offset++;
598 }
599 break;
600 case IXGBE_CONTROL_NL:
601 data_offset++;
602 DEBUGOUT("CONTROL: \n");
603 if (edata == IXGBE_CONTROL_EOL_NL) {
604 DEBUGOUT("EOL\n");
605 end_data = TRUE;
606 } else if (edata == IXGBE_CONTROL_SOL_NL) {
607 DEBUGOUT("SOL\n");
608 } else {
609 DEBUGOUT("Bad control value\n");
610 ret_val = IXGBE_ERR_PHY;
611 goto out;
612 }
613 break;
614 default:
615 DEBUGOUT("Bad control type\n");
616 ret_val = IXGBE_ERR_PHY;
617 goto out;
618 }
619 }
620
621out:
622 return ret_val;
623}
624
625/**
626 * ixgbe_identify_sfp_module_generic - Identifies SFP modules
627 * @hw: pointer to hardware structure
628 *
629 * Searches for and identifies the SFP module and assigns appropriate PHY type.
630 **/
631s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
632{
633 s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
634 u32 vendor_oui = 0;
635 u8 identifier = 0;
636 u8 comp_codes_1g = 0;
637 u8 comp_codes_10g = 0;
638 u8 oui_bytes[4] = {0, 0, 0, 0};
639 u8 transmission_media = 0;
640
641 status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
642 &identifier);
643
644 if (status == IXGBE_ERR_SFP_NOT_PRESENT) {
645 hw->phy.sfp_type = ixgbe_sfp_type_not_present;
646 goto out;
647 }
648
649 if (identifier == IXGBE_SFF_IDENTIFIER_SFP) {
650 hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES,
651 &comp_codes_1g);
652 hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES,
653 &comp_codes_10g);
654 hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_TRANSMISSION_MEDIA,
655 &transmission_media);
656
657 /* ID Module
658 * =========
659 * 0 SFP_DA_CU
660 * 1 SFP_SR
661 * 2 SFP_LR
662 */
663 if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
664 hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
665 else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
666 hw->phy.sfp_type = ixgbe_sfp_type_sr;
667 else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
668 hw->phy.sfp_type = ixgbe_sfp_type_lr;
669 else
670 hw->phy.sfp_type = ixgbe_sfp_type_unknown;
671
672 /* Determine if the SFP+ PHY is dual speed or not. */
673 if ((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
674 (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE))
675 hw->phy.multispeed_fiber = TRUE;
676 /* Determine PHY vendor */
677 if (hw->phy.type == ixgbe_phy_unknown) {
678 hw->phy.id = identifier;
679 hw->phy.ops.read_i2c_eeprom(hw,
680 IXGBE_SFF_VENDOR_OUI_BYTE0,
681 &oui_bytes[0]);
682 hw->phy.ops.read_i2c_eeprom(hw,
683 IXGBE_SFF_VENDOR_OUI_BYTE1,
684 &oui_bytes[1]);
685 hw->phy.ops.read_i2c_eeprom(hw,
686 IXGBE_SFF_VENDOR_OUI_BYTE2,
687 &oui_bytes[2]);
688
689 vendor_oui =
690 ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
691 (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
692 (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
693
694 switch (vendor_oui) {
695 case IXGBE_SFF_VENDOR_OUI_TYCO:
696 if (transmission_media &
697 IXGBE_SFF_TWIN_AX_CAPABLE)
698 hw->phy.type = ixgbe_phy_tw_tyco;
699 break;
700 case IXGBE_SFF_VENDOR_OUI_FTL:
701 hw->phy.type = ixgbe_phy_sfp_ftl;
702 break;
703 case IXGBE_SFF_VENDOR_OUI_AVAGO:
704 hw->phy.type = ixgbe_phy_sfp_avago;
705 break;
706 default:
707 if (transmission_media &
708 IXGBE_SFF_TWIN_AX_CAPABLE)
709 hw->phy.type = ixgbe_phy_tw_unknown;
710 else
711 hw->phy.type = ixgbe_phy_sfp_unknown;
712 break;
713 }
714 }
715 status = IXGBE_SUCCESS;
716 }
717
718out:
719 return status;
720}
721
722/**
723 * ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence
724 * @hw: pointer to hardware structure
725 * @list_offset: offset to the SFP ID list
726 * @data_offset: offset to the SFP data block
727 *
728 * Checks the MAC's EEPROM to see if it supports a given SFP+ module type, if
729 * so it returns the offsets to the phy init sequence block.
730 **/
731s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
732 u16 *list_offset,
733 u16 *data_offset)
734{
735 u16 sfp_id;
736
737 if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
738 return IXGBE_ERR_SFP_NOT_SUPPORTED;
739
740 if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
741 return IXGBE_ERR_SFP_NOT_PRESENT;
742
743 if ((hw->device_id == IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) &&
744 (hw->phy.sfp_type == ixgbe_sfp_type_da_cu))
745 return IXGBE_ERR_SFP_NOT_SUPPORTED;
746
747 /* Read offset to PHY init contents */
748 hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset);
749
750 if ((!*list_offset) || (*list_offset == 0xFFFF))
751 return IXGBE_ERR_PHY;
752
753 /* Shift offset to first ID word */
754 (*list_offset)++;
755
756 /*
757 * Find the matching SFP ID in the EEPROM
758 * and program the init sequence
759 */
760 hw->eeprom.ops.read(hw, *list_offset, &sfp_id);
761
762 while (sfp_id != IXGBE_PHY_INIT_END_NL) {
763 if (sfp_id == hw->phy.sfp_type) {
764 (*list_offset)++;
765 hw->eeprom.ops.read(hw, *list_offset, data_offset);
766 if ((!*data_offset) || (*data_offset == 0xFFFF)) {
767 DEBUGOUT("SFP+ module not supported\n");
768 return IXGBE_ERR_SFP_NOT_SUPPORTED;
769 } else {
770 break;
771 }
772 } else {
773 (*list_offset) += 2;
774 if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id))
775 return IXGBE_ERR_PHY;
776 }
777 }
778
779 if (sfp_id == IXGBE_PHY_INIT_END_NL) {
780 DEBUGOUT("No matching SFP+ module found\n");
781 return IXGBE_ERR_SFP_NOT_SUPPORTED;
782 }
783
784 return IXGBE_SUCCESS;
785}
786