diff options
author | françois romieu <romieu@fr.zoreil.com> | 2010-10-13 05:26:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-16 14:13:23 -0400 |
commit | 15419227f773b6c1b5fae44bde876078a9204caa (patch) | |
tree | 0e0c50fee62dfbc7934bf389367aae87e6fd626c /drivers/net/via-velocity.c | |
parent | 10da66f7552b3c7966c2f4f1f72009fb0b5539ec (diff) |
via-velocity: forced 1000 Mbps mode support.
Full duplex only. Half duplex 1000 Mbps is not supported.
Signed-off-by: David Lv <DavidLv@viatech.com.cn>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Tested-by: Seguier Regis <rseguier@e-teleport.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/via-velocity.c')
-rw-r--r-- | drivers/net/via-velocity.c | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 6884813b809c..f1995615dc84 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
@@ -312,13 +312,14 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability"); | |||
312 | 312 | ||
313 | #define MED_LNK_DEF 0 | 313 | #define MED_LNK_DEF 0 |
314 | #define MED_LNK_MIN 0 | 314 | #define MED_LNK_MIN 0 |
315 | #define MED_LNK_MAX 4 | 315 | #define MED_LNK_MAX 5 |
316 | /* speed_duplex[] is used for setting the speed and duplex mode of NIC. | 316 | /* speed_duplex[] is used for setting the speed and duplex mode of NIC. |
317 | 0: indicate autonegotiation for both speed and duplex mode | 317 | 0: indicate autonegotiation for both speed and duplex mode |
318 | 1: indicate 100Mbps half duplex mode | 318 | 1: indicate 100Mbps half duplex mode |
319 | 2: indicate 100Mbps full duplex mode | 319 | 2: indicate 100Mbps full duplex mode |
320 | 3: indicate 10Mbps half duplex mode | 320 | 3: indicate 10Mbps half duplex mode |
321 | 4: indicate 10Mbps full duplex mode | 321 | 4: indicate 10Mbps full duplex mode |
322 | 5: indicate 1000Mbps full duplex mode | ||
322 | 323 | ||
323 | Note: | 324 | Note: |
324 | if EEPROM have been set to the force mode, this option is ignored | 325 | if EEPROM have been set to the force mode, this option is ignored |
@@ -617,6 +618,9 @@ static u32 velocity_get_opt_media_mode(struct velocity_info *vptr) | |||
617 | case SPD_DPX_10_HALF: | 618 | case SPD_DPX_10_HALF: |
618 | status = VELOCITY_SPEED_10; | 619 | status = VELOCITY_SPEED_10; |
619 | break; | 620 | break; |
621 | case SPD_DPX_1000_FULL: | ||
622 | status = VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL; | ||
623 | break; | ||
620 | } | 624 | } |
621 | vptr->mii_status = status; | 625 | vptr->mii_status = status; |
622 | return status; | 626 | return status; |
@@ -922,6 +926,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) | |||
922 | /* enable AUTO-NEGO mode */ | 926 | /* enable AUTO-NEGO mode */ |
923 | mii_set_auto_on(vptr); | 927 | mii_set_auto_on(vptr); |
924 | } else { | 928 | } else { |
929 | u16 CTRL1000; | ||
925 | u16 ANAR; | 930 | u16 ANAR; |
926 | u8 CHIPGCR; | 931 | u8 CHIPGCR; |
927 | 932 | ||
@@ -936,7 +941,11 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) | |||
936 | BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR); | 941 | BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR); |
937 | 942 | ||
938 | CHIPGCR = readb(®s->CHIPGCR); | 943 | CHIPGCR = readb(®s->CHIPGCR); |
939 | CHIPGCR &= ~CHIPGCR_FCGMII; | 944 | |
945 | if (mii_status & VELOCITY_SPEED_1000) | ||
946 | CHIPGCR |= CHIPGCR_FCGMII; | ||
947 | else | ||
948 | CHIPGCR &= ~CHIPGCR_FCGMII; | ||
940 | 949 | ||
941 | if (mii_status & VELOCITY_DUPLEX_FULL) { | 950 | if (mii_status & VELOCITY_DUPLEX_FULL) { |
942 | CHIPGCR |= CHIPGCR_FCFDX; | 951 | CHIPGCR |= CHIPGCR_FCFDX; |
@@ -952,7 +961,13 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) | |||
952 | BYTE_REG_BITS_ON(TCR_TB2BDIS, ®s->TCR); | 961 | BYTE_REG_BITS_ON(TCR_TB2BDIS, ®s->TCR); |
953 | } | 962 | } |
954 | 963 | ||
955 | MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs); | 964 | velocity_mii_read(vptr->mac_regs, MII_CTRL1000, &CTRL1000); |
965 | CTRL1000 &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); | ||
966 | if ((mii_status & VELOCITY_SPEED_1000) && | ||
967 | (mii_status & VELOCITY_DUPLEX_FULL)) { | ||
968 | CTRL1000 |= ADVERTISE_1000FULL; | ||
969 | } | ||
970 | velocity_mii_write(vptr->mac_regs, MII_CTRL1000, CTRL1000); | ||
956 | 971 | ||
957 | if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10)) | 972 | if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10)) |
958 | BYTE_REG_BITS_OFF(TESTCFG_HBDIS, ®s->TESTCFG); | 973 | BYTE_REG_BITS_OFF(TESTCFG_HBDIS, ®s->TESTCFG); |
@@ -967,7 +982,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) | |||
967 | ANAR |= ADVERTISE_100FULL; | 982 | ANAR |= ADVERTISE_100FULL; |
968 | else | 983 | else |
969 | ANAR |= ADVERTISE_100HALF; | 984 | ANAR |= ADVERTISE_100HALF; |
970 | } else { | 985 | } else if (mii_status & VELOCITY_SPEED_10) { |
971 | if (mii_status & VELOCITY_DUPLEX_FULL) | 986 | if (mii_status & VELOCITY_DUPLEX_FULL) |
972 | ANAR |= ADVERTISE_10FULL; | 987 | ANAR |= ADVERTISE_10FULL; |
973 | else | 988 | else |
@@ -1013,6 +1028,9 @@ static void velocity_print_link_status(struct velocity_info *vptr) | |||
1013 | } else { | 1028 | } else { |
1014 | VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name); | 1029 | VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name); |
1015 | switch (vptr->options.spd_dpx) { | 1030 | switch (vptr->options.spd_dpx) { |
1031 | case SPD_DPX_1000_FULL: | ||
1032 | VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n"); | ||
1033 | break; | ||
1016 | case SPD_DPX_100_HALF: | 1034 | case SPD_DPX_100_HALF: |
1017 | VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n"); | 1035 | VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n"); |
1018 | break; | 1036 | break; |
@@ -3170,6 +3188,37 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd | |||
3170 | SUPPORTED_100baseT_Full | | 3188 | SUPPORTED_100baseT_Full | |
3171 | SUPPORTED_1000baseT_Half | | 3189 | SUPPORTED_1000baseT_Half | |
3172 | SUPPORTED_1000baseT_Full; | 3190 | SUPPORTED_1000baseT_Full; |
3191 | |||
3192 | cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; | ||
3193 | if (vptr->options.spd_dpx == SPD_DPX_AUTO) { | ||
3194 | cmd->advertising |= | ||
3195 | ADVERTISED_10baseT_Half | | ||
3196 | ADVERTISED_10baseT_Full | | ||
3197 | ADVERTISED_100baseT_Half | | ||
3198 | ADVERTISED_100baseT_Full | | ||
3199 | ADVERTISED_1000baseT_Half | | ||
3200 | ADVERTISED_1000baseT_Full; | ||
3201 | } else { | ||
3202 | switch (vptr->options.spd_dpx) { | ||
3203 | case SPD_DPX_1000_FULL: | ||
3204 | cmd->advertising |= ADVERTISED_1000baseT_Full; | ||
3205 | break; | ||
3206 | case SPD_DPX_100_HALF: | ||
3207 | cmd->advertising |= ADVERTISED_100baseT_Half; | ||
3208 | break; | ||
3209 | case SPD_DPX_100_FULL: | ||
3210 | cmd->advertising |= ADVERTISED_100baseT_Full; | ||
3211 | break; | ||
3212 | case SPD_DPX_10_HALF: | ||
3213 | cmd->advertising |= ADVERTISED_10baseT_Half; | ||
3214 | break; | ||
3215 | case SPD_DPX_10_FULL: | ||
3216 | cmd->advertising |= ADVERTISED_10baseT_Full; | ||
3217 | break; | ||
3218 | default: | ||
3219 | break; | ||
3220 | } | ||
3221 | } | ||
3173 | if (status & VELOCITY_SPEED_1000) | 3222 | if (status & VELOCITY_SPEED_1000) |
3174 | cmd->speed = SPEED_1000; | 3223 | cmd->speed = SPEED_1000; |
3175 | else if (status & VELOCITY_SPEED_100) | 3224 | else if (status & VELOCITY_SPEED_100) |
@@ -3200,14 +3249,35 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd | |||
3200 | curr_status &= (~VELOCITY_LINK_FAIL); | 3249 | curr_status &= (~VELOCITY_LINK_FAIL); |
3201 | 3250 | ||
3202 | new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0); | 3251 | new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0); |
3252 | new_status |= ((cmd->speed == SPEED_1000) ? VELOCITY_SPEED_1000 : 0); | ||
3203 | new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0); | 3253 | new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0); |
3204 | new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0); | 3254 | new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0); |
3205 | new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0); | 3255 | new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0); |
3206 | 3256 | ||
3207 | if ((new_status & VELOCITY_AUTONEG_ENABLE) && (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) | 3257 | if ((new_status & VELOCITY_AUTONEG_ENABLE) && |
3258 | (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) { | ||
3208 | ret = -EINVAL; | 3259 | ret = -EINVAL; |
3209 | else | 3260 | } else { |
3261 | enum speed_opt spd_dpx; | ||
3262 | |||
3263 | if (new_status & VELOCITY_AUTONEG_ENABLE) | ||
3264 | spd_dpx = SPD_DPX_AUTO; | ||
3265 | else if ((new_status & VELOCITY_SPEED_1000) && | ||
3266 | (new_status & VELOCITY_DUPLEX_FULL)) { | ||
3267 | spd_dpx = SPD_DPX_1000_FULL; | ||
3268 | } else if (new_status & VELOCITY_SPEED_100) | ||
3269 | spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ? | ||
3270 | SPD_DPX_100_FULL : SPD_DPX_100_HALF; | ||
3271 | else if (new_status & VELOCITY_SPEED_10) | ||
3272 | spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ? | ||
3273 | SPD_DPX_10_FULL : SPD_DPX_10_HALF; | ||
3274 | else | ||
3275 | return -EOPNOTSUPP; | ||
3276 | |||
3277 | vptr->options.spd_dpx = spd_dpx; | ||
3278 | |||
3210 | velocity_set_media_mode(vptr, new_status); | 3279 | velocity_set_media_mode(vptr, new_status); |
3280 | } | ||
3211 | 3281 | ||
3212 | return ret; | 3282 | return ret; |
3213 | } | 3283 | } |