diff options
author | Ron Mercer <ron.mercer@qlogic.com> | 2007-03-26 15:43:52 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 11:01:02 -0400 |
commit | 3efedf2e5b814f3edd99e4f4ca47a604871ebe0e (patch) | |
tree | 2cc59d55ca90b1ca4bcff89e227529584a6b35fd | |
parent | ec8263839aa8bc6eeee608a045e8f51738d7e436 (diff) |
qla3xxx: Adding support for the Agere PHY (ET1011C)
This PHY support patch was written by Benjamin Li.
Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rwxr-xr-x | drivers/net/qla3xxx.c | 347 | ||||
-rwxr-xr-x | drivers/net/qla3xxx.h | 33 |
2 files changed, 335 insertions, 45 deletions
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index c2eb2c93803b..4061f7de48af 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c | |||
@@ -72,6 +72,30 @@ static struct pci_device_id ql3xxx_pci_tbl[] __devinitdata = { | |||
72 | MODULE_DEVICE_TABLE(pci, ql3xxx_pci_tbl); | 72 | MODULE_DEVICE_TABLE(pci, ql3xxx_pci_tbl); |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * These are the known PHY's which are used | ||
76 | */ | ||
77 | typedef enum { | ||
78 | PHY_TYPE_UNKNOWN = 0, | ||
79 | PHY_VITESSE_VSC8211, | ||
80 | PHY_AGERE_ET1011C, | ||
81 | MAX_PHY_DEV_TYPES | ||
82 | } PHY_DEVICE_et; | ||
83 | |||
84 | typedef struct { | ||
85 | PHY_DEVICE_et phyDevice; | ||
86 | u32 phyIdOUI; | ||
87 | u16 phyIdModel; | ||
88 | char *name; | ||
89 | } PHY_DEVICE_INFO_t; | ||
90 | |||
91 | const PHY_DEVICE_INFO_t PHY_DEVICES[] = | ||
92 | {{PHY_TYPE_UNKNOWN, 0x000000, 0x0, "PHY_TYPE_UNKNOWN"}, | ||
93 | {PHY_VITESSE_VSC8211, 0x0003f1, 0xb, "PHY_VITESSE_VSC8211"}, | ||
94 | {PHY_AGERE_ET1011C, 0x00a0bc, 0x1, "PHY_AGERE_ET1011C"}, | ||
95 | }; | ||
96 | |||
97 | |||
98 | /* | ||
75 | * Caller must take hw_lock. | 99 | * Caller must take hw_lock. |
76 | */ | 100 | */ |
77 | static int ql_sem_spinlock(struct ql3_adapter *qdev, | 101 | static int ql_sem_spinlock(struct ql3_adapter *qdev, |
@@ -662,7 +686,7 @@ static u8 ql_mii_disable_scan_mode(struct ql3_adapter *qdev) | |||
662 | } | 686 | } |
663 | 687 | ||
664 | static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, | 688 | static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, |
665 | u16 regAddr, u16 value, u32 mac_index) | 689 | u16 regAddr, u16 value, u32 phyAddr) |
666 | { | 690 | { |
667 | struct ql3xxx_port_registers __iomem *port_regs = | 691 | struct ql3xxx_port_registers __iomem *port_regs = |
668 | qdev->mem_map_registers; | 692 | qdev->mem_map_registers; |
@@ -680,7 +704,7 @@ static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, | |||
680 | } | 704 | } |
681 | 705 | ||
682 | ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, | 706 | ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, |
683 | PHYAddr[mac_index] | regAddr); | 707 | phyAddr | regAddr); |
684 | 708 | ||
685 | ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value); | 709 | ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value); |
686 | 710 | ||
@@ -701,7 +725,7 @@ static int ql_mii_write_reg_ex(struct ql3_adapter *qdev, | |||
701 | } | 725 | } |
702 | 726 | ||
703 | static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, | 727 | static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, |
704 | u16 * value, u32 mac_index) | 728 | u16 * value, u32 phyAddr) |
705 | { | 729 | { |
706 | struct ql3xxx_port_registers __iomem *port_regs = | 730 | struct ql3xxx_port_registers __iomem *port_regs = |
707 | qdev->mem_map_registers; | 731 | qdev->mem_map_registers; |
@@ -720,7 +744,7 @@ static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr, | |||
720 | } | 744 | } |
721 | 745 | ||
722 | ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, | 746 | ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg, |
723 | PHYAddr[mac_index] | regAddr); | 747 | phyAddr | regAddr); |
724 | 748 | ||
725 | ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, | 749 | ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg, |
726 | (MAC_MII_CONTROL_RC << 16)); | 750 | (MAC_MII_CONTROL_RC << 16)); |
@@ -850,28 +874,31 @@ static void ql_petbi_start_neg(struct ql3_adapter *qdev) | |||
850 | 874 | ||
851 | } | 875 | } |
852 | 876 | ||
853 | static void ql_petbi_reset_ex(struct ql3_adapter *qdev, u32 mac_index) | 877 | static void ql_petbi_reset_ex(struct ql3_adapter *qdev) |
854 | { | 878 | { |
855 | ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET, | 879 | ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET, |
856 | mac_index); | 880 | PHYAddr[qdev->mac_index]); |
857 | } | 881 | } |
858 | 882 | ||
859 | static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev, u32 mac_index) | 883 | static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev) |
860 | { | 884 | { |
861 | u16 reg; | 885 | u16 reg; |
862 | 886 | ||
863 | /* Enable Auto-negotiation sense */ | 887 | /* Enable Auto-negotiation sense */ |
864 | ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, ®, mac_index); | 888 | ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, ®, |
889 | PHYAddr[qdev->mac_index]); | ||
865 | reg |= PETBI_TBI_AUTO_SENSE; | 890 | reg |= PETBI_TBI_AUTO_SENSE; |
866 | ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, mac_index); | 891 | ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, |
892 | PHYAddr[qdev->mac_index]); | ||
867 | 893 | ||
868 | ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER, | 894 | ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER, |
869 | PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, mac_index); | 895 | PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, |
896 | PHYAddr[qdev->mac_index]); | ||
870 | 897 | ||
871 | ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, | 898 | ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, |
872 | PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG | | 899 | PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG | |
873 | PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000, | 900 | PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000, |
874 | mac_index); | 901 | PHYAddr[qdev->mac_index]); |
875 | } | 902 | } |
876 | 903 | ||
877 | static void ql_petbi_init(struct ql3_adapter *qdev) | 904 | static void ql_petbi_init(struct ql3_adapter *qdev) |
@@ -880,10 +907,10 @@ static void ql_petbi_init(struct ql3_adapter *qdev) | |||
880 | ql_petbi_start_neg(qdev); | 907 | ql_petbi_start_neg(qdev); |
881 | } | 908 | } |
882 | 909 | ||
883 | static void ql_petbi_init_ex(struct ql3_adapter *qdev, u32 mac_index) | 910 | static void ql_petbi_init_ex(struct ql3_adapter *qdev) |
884 | { | 911 | { |
885 | ql_petbi_reset_ex(qdev, mac_index); | 912 | ql_petbi_reset_ex(qdev); |
886 | ql_petbi_start_neg_ex(qdev, mac_index); | 913 | ql_petbi_start_neg_ex(qdev); |
887 | } | 914 | } |
888 | 915 | ||
889 | static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev) | 916 | static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev) |
@@ -896,33 +923,128 @@ static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev) | |||
896 | return (reg & PETBI_NEG_PAUSE_MASK) == PETBI_NEG_PAUSE; | 923 | return (reg & PETBI_NEG_PAUSE_MASK) == PETBI_NEG_PAUSE; |
897 | } | 924 | } |
898 | 925 | ||
926 | static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr) | ||
927 | { | ||
928 | printk(KERN_INFO "%s: enabling Agere specific PHY\n", qdev->ndev->name); | ||
929 | /* power down device bit 11 = 1 */ | ||
930 | ql_mii_write_reg_ex(qdev, 0x00, 0x1940, miiAddr); | ||
931 | /* enable diagnostic mode bit 2 = 1 */ | ||
932 | ql_mii_write_reg_ex(qdev, 0x12, 0x840e, miiAddr); | ||
933 | /* 1000MB amplitude adjust (see Agere errata) */ | ||
934 | ql_mii_write_reg_ex(qdev, 0x10, 0x8805, miiAddr); | ||
935 | /* 1000MB amplitude adjust (see Agere errata) */ | ||
936 | ql_mii_write_reg_ex(qdev, 0x11, 0xf03e, miiAddr); | ||
937 | /* 100MB amplitude adjust (see Agere errata) */ | ||
938 | ql_mii_write_reg_ex(qdev, 0x10, 0x8806, miiAddr); | ||
939 | /* 100MB amplitude adjust (see Agere errata) */ | ||
940 | ql_mii_write_reg_ex(qdev, 0x11, 0x003e, miiAddr); | ||
941 | /* 10MB amplitude adjust (see Agere errata) */ | ||
942 | ql_mii_write_reg_ex(qdev, 0x10, 0x8807, miiAddr); | ||
943 | /* 10MB amplitude adjust (see Agere errata) */ | ||
944 | ql_mii_write_reg_ex(qdev, 0x11, 0x1f00, miiAddr); | ||
945 | /* point to hidden reg 0x2806 */ | ||
946 | ql_mii_write_reg_ex(qdev, 0x10, 0x2806, miiAddr); | ||
947 | /* Write new PHYAD w/bit 5 set */ | ||
948 | ql_mii_write_reg_ex(qdev, 0x11, 0x0020 | (PHYAddr[qdev->mac_index] >> 8), miiAddr); | ||
949 | /* | ||
950 | * Disable diagnostic mode bit 2 = 0 | ||
951 | * Power up device bit 11 = 0 | ||
952 | * Link up (on) and activity (blink) | ||
953 | */ | ||
954 | ql_mii_write_reg(qdev, 0x12, 0x840a); | ||
955 | ql_mii_write_reg(qdev, 0x00, 0x1140); | ||
956 | ql_mii_write_reg(qdev, 0x1c, 0xfaf0); | ||
957 | } | ||
958 | |||
959 | static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev, | ||
960 | u16 phyIdReg0, u16 phyIdReg1) | ||
961 | { | ||
962 | PHY_DEVICE_et result = PHY_TYPE_UNKNOWN; | ||
963 | u32 oui; | ||
964 | u16 model; | ||
965 | int i; | ||
966 | |||
967 | if (phyIdReg0 == 0xffff) { | ||
968 | return result; | ||
969 | } | ||
970 | |||
971 | if (phyIdReg1 == 0xffff) { | ||
972 | return result; | ||
973 | } | ||
974 | |||
975 | /* oui is split between two registers */ | ||
976 | oui = (phyIdReg0 << 6) | ((phyIdReg1 & PHY_OUI_1_MASK) >> 10); | ||
977 | |||
978 | model = (phyIdReg1 & PHY_MODEL_MASK) >> 4; | ||
979 | |||
980 | /* Scan table for this PHY */ | ||
981 | for(i = 0; i < MAX_PHY_DEV_TYPES; i++) { | ||
982 | if ((oui == PHY_DEVICES[i].phyIdOUI) && (model == PHY_DEVICES[i].phyIdModel)) | ||
983 | { | ||
984 | result = PHY_DEVICES[i].phyDevice; | ||
985 | |||
986 | printk(KERN_INFO "%s: Phy: %s\n", | ||
987 | qdev->ndev->name, PHY_DEVICES[i].name); | ||
988 | |||
989 | break; | ||
990 | } | ||
991 | } | ||
992 | |||
993 | return result; | ||
994 | } | ||
995 | |||
899 | static int ql_phy_get_speed(struct ql3_adapter *qdev) | 996 | static int ql_phy_get_speed(struct ql3_adapter *qdev) |
900 | { | 997 | { |
901 | u16 reg; | 998 | u16 reg; |
902 | 999 | ||
1000 | switch(qdev->phyType) { | ||
1001 | case PHY_AGERE_ET1011C: | ||
1002 | { | ||
1003 | if (ql_mii_read_reg(qdev, 0x1A, ®) < 0) | ||
1004 | return 0; | ||
1005 | |||
1006 | reg = (reg >> 8) & 3; | ||
1007 | break; | ||
1008 | } | ||
1009 | default: | ||
903 | if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) | 1010 | if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) |
904 | return 0; | 1011 | return 0; |
905 | 1012 | ||
906 | reg = (((reg & 0x18) >> 3) & 3); | 1013 | reg = (((reg & 0x18) >> 3) & 3); |
1014 | } | ||
907 | 1015 | ||
908 | if (reg == 2) | 1016 | switch(reg) { |
1017 | case 2: | ||
909 | return SPEED_1000; | 1018 | return SPEED_1000; |
910 | else if (reg == 1) | 1019 | case 1: |
911 | return SPEED_100; | 1020 | return SPEED_100; |
912 | else if (reg == 0) | 1021 | case 0: |
913 | return SPEED_10; | 1022 | return SPEED_10; |
914 | else | 1023 | default: |
915 | return -1; | 1024 | return -1; |
1025 | } | ||
916 | } | 1026 | } |
917 | 1027 | ||
918 | static int ql_is_full_dup(struct ql3_adapter *qdev) | 1028 | static int ql_is_full_dup(struct ql3_adapter *qdev) |
919 | { | 1029 | { |
920 | u16 reg; | 1030 | u16 reg; |
921 | 1031 | ||
922 | if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) | 1032 | switch(qdev->phyType) { |
923 | return 0; | 1033 | case PHY_AGERE_ET1011C: |
924 | 1034 | { | |
925 | return (reg & PHY_AUX_DUPLEX_STAT) != 0; | 1035 | if (ql_mii_read_reg(qdev, 0x1A, ®)) |
1036 | return 0; | ||
1037 | |||
1038 | return ((reg & 0x0080) && (reg & 0x1000)) != 0; | ||
1039 | } | ||
1040 | case PHY_VITESSE_VSC8211: | ||
1041 | default: | ||
1042 | { | ||
1043 | if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, ®) < 0) | ||
1044 | return 0; | ||
1045 | return (reg & PHY_AUX_DUPLEX_STAT) != 0; | ||
1046 | } | ||
1047 | } | ||
926 | } | 1048 | } |
927 | 1049 | ||
928 | static int ql_is_phy_neg_pause(struct ql3_adapter *qdev) | 1050 | static int ql_is_phy_neg_pause(struct ql3_adapter *qdev) |
@@ -935,6 +1057,73 @@ static int ql_is_phy_neg_pause(struct ql3_adapter *qdev) | |||
935 | return (reg & PHY_NEG_PAUSE) != 0; | 1057 | return (reg & PHY_NEG_PAUSE) != 0; |
936 | } | 1058 | } |
937 | 1059 | ||
1060 | static int PHY_Setup(struct ql3_adapter *qdev) | ||
1061 | { | ||
1062 | u16 reg1; | ||
1063 | u16 reg2; | ||
1064 | bool agereAddrChangeNeeded = false; | ||
1065 | u32 miiAddr = 0; | ||
1066 | int err; | ||
1067 | |||
1068 | /* Determine the PHY we are using by reading the ID's */ | ||
1069 | err = ql_mii_read_reg(qdev, PHY_ID_0_REG, ®1); | ||
1070 | if(err != 0) { | ||
1071 | printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n", | ||
1072 | qdev->ndev->name); | ||
1073 | return err; | ||
1074 | } | ||
1075 | |||
1076 | err = ql_mii_read_reg(qdev, PHY_ID_1_REG, ®2); | ||
1077 | if(err != 0) { | ||
1078 | printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG\n", | ||
1079 | qdev->ndev->name); | ||
1080 | return err; | ||
1081 | } | ||
1082 | |||
1083 | /* Check if we have a Agere PHY */ | ||
1084 | if ((reg1 == 0xffff) || (reg2 == 0xffff)) { | ||
1085 | |||
1086 | /* Determine which MII address we should be using | ||
1087 | determined by the index of the card */ | ||
1088 | if (qdev->mac_index == 0) { | ||
1089 | miiAddr = MII_AGERE_ADDR_1; | ||
1090 | } else { | ||
1091 | miiAddr = MII_AGERE_ADDR_2; | ||
1092 | } | ||
1093 | |||
1094 | err =ql_mii_read_reg_ex(qdev, PHY_ID_0_REG, ®1, miiAddr); | ||
1095 | if(err != 0) { | ||
1096 | printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n", | ||
1097 | qdev->ndev->name); | ||
1098 | return err; | ||
1099 | } | ||
1100 | |||
1101 | err = ql_mii_read_reg_ex(qdev, PHY_ID_1_REG, ®2, miiAddr); | ||
1102 | if(err != 0) { | ||
1103 | printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n", | ||
1104 | qdev->ndev->name); | ||
1105 | return err; | ||
1106 | } | ||
1107 | |||
1108 | /* We need to remember to initialize the Agere PHY */ | ||
1109 | agereAddrChangeNeeded = true; | ||
1110 | } | ||
1111 | |||
1112 | /* Determine the particular PHY we have on board to apply | ||
1113 | PHY specific initializations */ | ||
1114 | qdev->phyType = getPhyType(qdev, reg1, reg2); | ||
1115 | |||
1116 | if ((qdev->phyType == PHY_AGERE_ET1011C) && agereAddrChangeNeeded) { | ||
1117 | /* need this here so address gets changed */ | ||
1118 | phyAgereSpecificInit(qdev, miiAddr); | ||
1119 | } else if (qdev->phyType == PHY_TYPE_UNKNOWN) { | ||
1120 | printk(KERN_ERR "%s: PHY is unknown\n", qdev->ndev->name); | ||
1121 | return -EIO; | ||
1122 | } | ||
1123 | |||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
938 | /* | 1127 | /* |
939 | * Caller holds hw_lock. | 1128 | * Caller holds hw_lock. |
940 | */ | 1129 | */ |
@@ -1205,15 +1394,14 @@ static int ql_link_down_detect_clear(struct ql3_adapter *qdev) | |||
1205 | /* | 1394 | /* |
1206 | * Caller holds hw_lock. | 1395 | * Caller holds hw_lock. |
1207 | */ | 1396 | */ |
1208 | static int ql_this_adapter_controls_port(struct ql3_adapter *qdev, | 1397 | static int ql_this_adapter_controls_port(struct ql3_adapter *qdev) |
1209 | u32 mac_index) | ||
1210 | { | 1398 | { |
1211 | struct ql3xxx_port_registers __iomem *port_regs = | 1399 | struct ql3xxx_port_registers __iomem *port_regs = |
1212 | qdev->mem_map_registers; | 1400 | qdev->mem_map_registers; |
1213 | u32 bitToCheck = 0; | 1401 | u32 bitToCheck = 0; |
1214 | u32 temp; | 1402 | u32 temp; |
1215 | 1403 | ||
1216 | switch (mac_index) { | 1404 | switch (qdev->mac_index) { |
1217 | case 0: | 1405 | case 0: |
1218 | bitToCheck = PORT_STATUS_F1_ENABLED; | 1406 | bitToCheck = PORT_STATUS_F1_ENABLED; |
1219 | break; | 1407 | break; |
@@ -1238,27 +1426,96 @@ static int ql_this_adapter_controls_port(struct ql3_adapter *qdev, | |||
1238 | } | 1426 | } |
1239 | } | 1427 | } |
1240 | 1428 | ||
1241 | static void ql_phy_reset_ex(struct ql3_adapter *qdev, u32 mac_index) | 1429 | static void ql_phy_reset_ex(struct ql3_adapter *qdev) |
1242 | { | 1430 | { |
1243 | ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, mac_index); | 1431 | ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, |
1432 | PHYAddr[qdev->mac_index]); | ||
1244 | } | 1433 | } |
1245 | 1434 | ||
1246 | static void ql_phy_start_neg_ex(struct ql3_adapter *qdev, u32 mac_index) | 1435 | static void ql_phy_start_neg_ex(struct ql3_adapter *qdev) |
1247 | { | 1436 | { |
1248 | u16 reg; | 1437 | u16 reg; |
1438 | u16 portConfiguration; | ||
1249 | 1439 | ||
1250 | ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, | 1440 | if(qdev->phyType == PHY_AGERE_ET1011C) { |
1251 | PHY_NEG_PAUSE | PHY_NEG_ADV_SPEED | 1, mac_index); | 1441 | /* turn off external loopback */ |
1442 | ql_mii_write_reg(qdev, 0x13, 0x0000); | ||
1443 | } | ||
1444 | |||
1445 | if(qdev->mac_index == 0) | ||
1446 | portConfiguration = qdev->nvram_data.macCfg_port0.portConfiguration; | ||
1447 | else | ||
1448 | portConfiguration = qdev->nvram_data.macCfg_port1.portConfiguration; | ||
1449 | |||
1450 | /* Some HBA's in the field are set to 0 and they need to | ||
1451 | be reinterpreted with a default value */ | ||
1452 | if(portConfiguration == 0) | ||
1453 | portConfiguration = PORT_CONFIG_DEFAULT; | ||
1454 | |||
1455 | /* Set the 1000 advertisements */ | ||
1456 | ql_mii_read_reg_ex(qdev, PHY_GIG_CONTROL, ®, | ||
1457 | PHYAddr[qdev->mac_index]); | ||
1458 | reg &= ~PHY_GIG_ALL_PARAMS; | ||
1459 | |||
1460 | if(portConfiguration & | ||
1461 | PORT_CONFIG_FULL_DUPLEX_ENABLED & | ||
1462 | PORT_CONFIG_1000MB_SPEED) { | ||
1463 | reg |= PHY_GIG_ADV_1000F; | ||
1464 | } | ||
1465 | |||
1466 | if(portConfiguration & | ||
1467 | PORT_CONFIG_HALF_DUPLEX_ENABLED & | ||
1468 | PORT_CONFIG_1000MB_SPEED) { | ||
1469 | reg |= PHY_GIG_ADV_1000H; | ||
1470 | } | ||
1471 | |||
1472 | ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg, | ||
1473 | PHYAddr[qdev->mac_index]); | ||
1474 | |||
1475 | /* Set the 10/100 & pause negotiation advertisements */ | ||
1476 | ql_mii_read_reg_ex(qdev, PHY_NEG_ADVER, ®, | ||
1477 | PHYAddr[qdev->mac_index]); | ||
1478 | reg &= ~PHY_NEG_ALL_PARAMS; | ||
1479 | |||
1480 | if(portConfiguration & PORT_CONFIG_SYM_PAUSE_ENABLED) | ||
1481 | reg |= PHY_NEG_ASY_PAUSE | PHY_NEG_SYM_PAUSE; | ||
1482 | |||
1483 | if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) { | ||
1484 | if(portConfiguration & PORT_CONFIG_100MB_SPEED) | ||
1485 | reg |= PHY_NEG_ADV_100F; | ||
1486 | |||
1487 | if(portConfiguration & PORT_CONFIG_10MB_SPEED) | ||
1488 | reg |= PHY_NEG_ADV_10F; | ||
1489 | } | ||
1252 | 1490 | ||
1253 | ql_mii_read_reg_ex(qdev, CONTROL_REG, ®, mac_index); | 1491 | if(portConfiguration & PORT_CONFIG_HALF_DUPLEX_ENABLED) { |
1254 | ql_mii_write_reg_ex(qdev, CONTROL_REG, reg | PHY_CTRL_RESTART_NEG, | 1492 | if(portConfiguration & PORT_CONFIG_100MB_SPEED) |
1255 | mac_index); | 1493 | reg |= PHY_NEG_ADV_100H; |
1494 | |||
1495 | if(portConfiguration & PORT_CONFIG_10MB_SPEED) | ||
1496 | reg |= PHY_NEG_ADV_10H; | ||
1497 | } | ||
1498 | |||
1499 | if(portConfiguration & | ||
1500 | PORT_CONFIG_1000MB_SPEED) { | ||
1501 | reg |= 1; | ||
1502 | } | ||
1503 | |||
1504 | ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg, | ||
1505 | PHYAddr[qdev->mac_index]); | ||
1506 | |||
1507 | ql_mii_read_reg_ex(qdev, CONTROL_REG, ®, PHYAddr[qdev->mac_index]); | ||
1508 | |||
1509 | ql_mii_write_reg_ex(qdev, CONTROL_REG, | ||
1510 | reg | PHY_CTRL_RESTART_NEG | PHY_CTRL_AUTO_NEG, | ||
1511 | PHYAddr[qdev->mac_index]); | ||
1256 | } | 1512 | } |
1257 | 1513 | ||
1258 | static void ql_phy_init_ex(struct ql3_adapter *qdev, u32 mac_index) | 1514 | static void ql_phy_init_ex(struct ql3_adapter *qdev) |
1259 | { | 1515 | { |
1260 | ql_phy_reset_ex(qdev, mac_index); | 1516 | ql_phy_reset_ex(qdev); |
1261 | ql_phy_start_neg_ex(qdev, mac_index); | 1517 | PHY_Setup(qdev); |
1518 | ql_phy_start_neg_ex(qdev); | ||
1262 | } | 1519 | } |
1263 | 1520 | ||
1264 | /* | 1521 | /* |
@@ -1295,14 +1552,17 @@ static int ql_port_start(struct ql3_adapter *qdev) | |||
1295 | { | 1552 | { |
1296 | if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, | 1553 | if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK, |
1297 | (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * | 1554 | (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) * |
1298 | 2) << 7)) | 1555 | 2) << 7)) { |
1556 | printk(KERN_ERR "%s: Could not get hw lock for GIO\n", | ||
1557 | qdev->ndev->name); | ||
1299 | return -1; | 1558 | return -1; |
1559 | } | ||
1300 | 1560 | ||
1301 | if (ql_is_fiber(qdev)) { | 1561 | if (ql_is_fiber(qdev)) { |
1302 | ql_petbi_init(qdev); | 1562 | ql_petbi_init(qdev); |
1303 | } else { | 1563 | } else { |
1304 | /* Copper port */ | 1564 | /* Copper port */ |
1305 | ql_phy_init_ex(qdev, qdev->mac_index); | 1565 | ql_phy_init_ex(qdev); |
1306 | } | 1566 | } |
1307 | 1567 | ||
1308 | ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK); | 1568 | ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK); |
@@ -1453,7 +1713,7 @@ static void ql_link_state_machine(struct ql3_adapter *qdev) | |||
1453 | */ | 1713 | */ |
1454 | static void ql_get_phy_owner(struct ql3_adapter *qdev) | 1714 | static void ql_get_phy_owner(struct ql3_adapter *qdev) |
1455 | { | 1715 | { |
1456 | if (ql_this_adapter_controls_port(qdev, qdev->mac_index)) | 1716 | if (ql_this_adapter_controls_port(qdev)) |
1457 | set_bit(QL_LINK_MASTER,&qdev->flags); | 1717 | set_bit(QL_LINK_MASTER,&qdev->flags); |
1458 | else | 1718 | else |
1459 | clear_bit(QL_LINK_MASTER,&qdev->flags); | 1719 | clear_bit(QL_LINK_MASTER,&qdev->flags); |
@@ -1467,11 +1727,11 @@ static void ql_init_scan_mode(struct ql3_adapter *qdev) | |||
1467 | ql_mii_enable_scan_mode(qdev); | 1727 | ql_mii_enable_scan_mode(qdev); |
1468 | 1728 | ||
1469 | if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) { | 1729 | if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) { |
1470 | if (ql_this_adapter_controls_port(qdev, qdev->mac_index)) | 1730 | if (ql_this_adapter_controls_port(qdev)) |
1471 | ql_petbi_init_ex(qdev, qdev->mac_index); | 1731 | ql_petbi_init_ex(qdev); |
1472 | } else { | 1732 | } else { |
1473 | if (ql_this_adapter_controls_port(qdev, qdev->mac_index)) | 1733 | if (ql_this_adapter_controls_port(qdev)) |
1474 | ql_phy_init_ex(qdev, qdev->mac_index); | 1734 | ql_phy_init_ex(qdev); |
1475 | } | 1735 | } |
1476 | } | 1736 | } |
1477 | 1737 | ||
@@ -3092,6 +3352,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) | |||
3092 | goto out; | 3352 | goto out; |
3093 | } | 3353 | } |
3094 | 3354 | ||
3355 | PHY_Setup(qdev); | ||
3095 | ql_init_scan_mode(qdev); | 3356 | ql_init_scan_mode(qdev); |
3096 | ql_get_phy_owner(qdev); | 3357 | ql_get_phy_owner(qdev); |
3097 | 3358 | ||
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h index 0203f88f0544..4a832c46c274 100755 --- a/drivers/net/qla3xxx.h +++ b/drivers/net/qla3xxx.h | |||
@@ -293,6 +293,16 @@ struct net_rsp_iocb { | |||
293 | 293 | ||
294 | #define MII_SCAN_REGISTER 0x00000001 | 294 | #define MII_SCAN_REGISTER 0x00000001 |
295 | 295 | ||
296 | #define PHY_ID_0_REG 2 | ||
297 | #define PHY_ID_1_REG 3 | ||
298 | |||
299 | #define PHY_OUI_1_MASK 0xfc00 | ||
300 | #define PHY_MODEL_MASK 0x03f0 | ||
301 | |||
302 | /* Address for the Agere Phy */ | ||
303 | #define MII_AGERE_ADDR_1 0x00001000 | ||
304 | #define MII_AGERE_ADDR_2 0x00001100 | ||
305 | |||
296 | /* 32-bit ispControlStatus */ | 306 | /* 32-bit ispControlStatus */ |
297 | enum { | 307 | enum { |
298 | ISP_CONTROL_NP_MASK = 0x0003, | 308 | ISP_CONTROL_NP_MASK = 0x0003, |
@@ -789,6 +799,7 @@ enum { | |||
789 | PHY_CTRL_LOOPBACK = 0x4000, | 799 | PHY_CTRL_LOOPBACK = 0x4000, |
790 | 800 | ||
791 | PETBI_CONTROL_REG = 0x00, | 801 | PETBI_CONTROL_REG = 0x00, |
802 | PETBI_CTRL_ALL_PARAMS = 0x7140, | ||
792 | PETBI_CTRL_SOFT_RESET = 0x8000, | 803 | PETBI_CTRL_SOFT_RESET = 0x8000, |
793 | PETBI_CTRL_AUTO_NEG = 0x1000, | 804 | PETBI_CTRL_AUTO_NEG = 0x1000, |
794 | PETBI_CTRL_RESTART_NEG = 0x0200, | 805 | PETBI_CTRL_RESTART_NEG = 0x0200, |
@@ -811,6 +822,23 @@ enum { | |||
811 | PETBI_EXPANSION_REG = 0x06, | 822 | PETBI_EXPANSION_REG = 0x06, |
812 | PETBI_EXP_PAGE_RX = 0x0002, | 823 | PETBI_EXP_PAGE_RX = 0x0002, |
813 | 824 | ||
825 | PHY_GIG_CONTROL = 9, | ||
826 | PHY_GIG_ENABLE_MAN = 0x1000, /* Enable Master/Slave Manual Config*/ | ||
827 | PHY_GIG_SET_MASTER = 0x0800, /* Set Master (slave if clear)*/ | ||
828 | PHY_GIG_ALL_PARAMS = 0x0300, | ||
829 | PHY_GIG_ADV_1000F = 0x0200, | ||
830 | PHY_GIG_ADV_1000H = 0x0100, | ||
831 | |||
832 | PHY_NEG_ADVER = 4, | ||
833 | PHY_NEG_ALL_PARAMS = 0x0fe0, | ||
834 | PHY_NEG_ASY_PAUSE = 0x0800, | ||
835 | PHY_NEG_SYM_PAUSE = 0x0400, | ||
836 | PHY_NEG_ADV_SPEED = 0x01e0, | ||
837 | PHY_NEG_ADV_100F = 0x0100, | ||
838 | PHY_NEG_ADV_100H = 0x0080, | ||
839 | PHY_NEG_ADV_10F = 0x0040, | ||
840 | PHY_NEG_ADV_10H = 0x0020, | ||
841 | |||
814 | PETBI_TBI_CTRL = 0x11, | 842 | PETBI_TBI_CTRL = 0x11, |
815 | PETBI_TBI_RESET = 0x8000, | 843 | PETBI_TBI_RESET = 0x8000, |
816 | PETBI_TBI_AUTO_SENSE = 0x0100, | 844 | PETBI_TBI_AUTO_SENSE = 0x0100, |
@@ -826,8 +854,7 @@ enum { | |||
826 | PHY_AUX_RESET_STICK = 0x0002, | 854 | PHY_AUX_RESET_STICK = 0x0002, |
827 | PHY_NEG_PAUSE = 0x0400, | 855 | PHY_NEG_PAUSE = 0x0400, |
828 | PHY_CTRL_SOFT_RESET = 0x8000, | 856 | PHY_CTRL_SOFT_RESET = 0x8000, |
829 | PHY_NEG_ADVER = 4, | 857 | PHY_CTRL_AUTO_NEG = 0x1000, |
830 | PHY_NEG_ADV_SPEED = 0x01e0, | ||
831 | PHY_CTRL_RESTART_NEG = 0x0200, | 858 | PHY_CTRL_RESTART_NEG = 0x0200, |
832 | }; | 859 | }; |
833 | enum { | 860 | enum { |
@@ -892,6 +919,7 @@ enum {EEPROM_SIZE = FM93C86A_SIZE_16, | |||
892 | u16 pauseThreshold_mac; | 919 | u16 pauseThreshold_mac; |
893 | u16 resumeThreshold_mac; | 920 | u16 resumeThreshold_mac; |
894 | u16 portConfiguration; | 921 | u16 portConfiguration; |
922 | #define PORT_CONFIG_DEFAULT 0xf700 | ||
895 | #define PORT_CONFIG_AUTO_NEG_ENABLED 0x8000 | 923 | #define PORT_CONFIG_AUTO_NEG_ENABLED 0x8000 |
896 | #define PORT_CONFIG_SYM_PAUSE_ENABLED 0x4000 | 924 | #define PORT_CONFIG_SYM_PAUSE_ENABLED 0x4000 |
897 | #define PORT_CONFIG_FULL_DUPLEX_ENABLED 0x2000 | 925 | #define PORT_CONFIG_FULL_DUPLEX_ENABLED 0x2000 |
@@ -1259,6 +1287,7 @@ struct ql3_adapter { | |||
1259 | struct delayed_work tx_timeout_work; | 1287 | struct delayed_work tx_timeout_work; |
1260 | u32 max_frame_size; | 1288 | u32 max_frame_size; |
1261 | u32 device_id; | 1289 | u32 device_id; |
1290 | u16 phyType; | ||
1262 | }; | 1291 | }; |
1263 | 1292 | ||
1264 | #endif /* _QLA3XXX_H_ */ | 1293 | #endif /* _QLA3XXX_H_ */ |