aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/via-velocity.c
diff options
context:
space:
mode:
authorfrançois romieu <romieu@fr.zoreil.com>2010-10-13 05:26:05 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-16 14:13:23 -0400
commit15419227f773b6c1b5fae44bde876078a9204caa (patch)
tree0e0c50fee62dfbc7934bf389367aae87e6fd626c /drivers/net/via-velocity.c
parent10da66f7552b3c7966c2f4f1f72009fb0b5539ec (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.c82
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, &regs->CHIPGCR); 941 BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
937 942
938 CHIPGCR = readb(&regs->CHIPGCR); 943 CHIPGCR = readb(&regs->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, &regs->TCR); 961 BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->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, &regs->TESTCFG); 973 BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->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}