Merge branch 'mvneta-ethtool-autoneg'
Stas Sergeev says: ==================== mvneta: implement ethtool autonegotiation control These 2 patches add an ability to control the autonegotiation via ethtool. For example: ethtool -s eth0 autoneg off ethtool -s eth0 autoneg on This is needed if you want to connect the mvneta's MII to different switches or PHYs: the ones the do support the in-band status, and the ones that do not. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b69e3c6f71
@ -369,7 +369,7 @@ struct mvneta_port {
|
||||
unsigned int duplex;
|
||||
unsigned int speed;
|
||||
unsigned int tx_csum_limit;
|
||||
int use_inband_status:1;
|
||||
unsigned int use_inband_status:1;
|
||||
|
||||
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
|
||||
};
|
||||
@ -971,6 +971,44 @@ static void mvneta_set_other_mcast_table(struct mvneta_port *pp, int queue)
|
||||
mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val);
|
||||
}
|
||||
|
||||
static void mvneta_set_autoneg(struct mvneta_port *pp, int enable)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (enable) {
|
||||
val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
val &= ~(MVNETA_GMAC_FORCE_LINK_PASS |
|
||||
MVNETA_GMAC_FORCE_LINK_DOWN |
|
||||
MVNETA_GMAC_AN_FLOW_CTRL_EN);
|
||||
val |= MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
MVNETA_GMAC_AN_SPEED_EN |
|
||||
MVNETA_GMAC_AN_DUPLEX_EN;
|
||||
mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
|
||||
val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
|
||||
val |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
|
||||
mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
|
||||
|
||||
val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
|
||||
val |= MVNETA_GMAC2_INBAND_AN_ENABLE;
|
||||
mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
|
||||
} else {
|
||||
val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
MVNETA_GMAC_AN_SPEED_EN |
|
||||
MVNETA_GMAC_AN_DUPLEX_EN);
|
||||
mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
|
||||
val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
|
||||
val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE;
|
||||
mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
|
||||
|
||||
val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
|
||||
val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE;
|
||||
mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
|
||||
}
|
||||
}
|
||||
|
||||
/* This method sets defaults to the NETA port:
|
||||
* Clears interrupt Cause and Mask registers.
|
||||
* Clears all MAC tables.
|
||||
@ -1056,26 +1094,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
|
||||
val &= ~MVNETA_PHY_POLLING_ENABLE;
|
||||
mvreg_write(pp, MVNETA_UNIT_CONTROL, val);
|
||||
|
||||
if (pp->use_inband_status) {
|
||||
val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
val &= ~(MVNETA_GMAC_FORCE_LINK_PASS |
|
||||
MVNETA_GMAC_FORCE_LINK_DOWN |
|
||||
MVNETA_GMAC_AN_FLOW_CTRL_EN);
|
||||
val |= MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
MVNETA_GMAC_AN_SPEED_EN |
|
||||
MVNETA_GMAC_AN_DUPLEX_EN;
|
||||
mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
|
||||
val |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
|
||||
mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
|
||||
} else {
|
||||
val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
MVNETA_GMAC_AN_SPEED_EN |
|
||||
MVNETA_GMAC_AN_DUPLEX_EN);
|
||||
mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
}
|
||||
|
||||
mvneta_set_autoneg(pp, pp->use_inband_status);
|
||||
mvneta_set_ucast_table(pp, -1);
|
||||
mvneta_set_special_mcast_table(pp, -1);
|
||||
mvneta_set_other_mcast_table(pp, -1);
|
||||
@ -2937,10 +2956,43 @@ int mvneta_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
int mvneta_ethtool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct mvneta_port *pp = netdev_priv(dev);
|
||||
struct phy_device *phydev = pp->phy_dev;
|
||||
|
||||
if (!pp->phy_dev)
|
||||
if (!phydev)
|
||||
return -ENODEV;
|
||||
|
||||
if ((cmd->autoneg == AUTONEG_ENABLE) != pp->use_inband_status) {
|
||||
u32 val;
|
||||
|
||||
mvneta_set_autoneg(pp, cmd->autoneg == AUTONEG_ENABLE);
|
||||
|
||||
if (cmd->autoneg == AUTONEG_DISABLE) {
|
||||
val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
|
||||
MVNETA_GMAC_CONFIG_GMII_SPEED |
|
||||
MVNETA_GMAC_CONFIG_FULL_DUPLEX);
|
||||
|
||||
if (phydev->duplex)
|
||||
val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
|
||||
|
||||
if (phydev->speed == SPEED_1000)
|
||||
val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
|
||||
else if (phydev->speed == SPEED_100)
|
||||
val |= MVNETA_GMAC_CONFIG_MII_SPEED;
|
||||
|
||||
mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
}
|
||||
|
||||
pp->use_inband_status = (cmd->autoneg == AUTONEG_ENABLE);
|
||||
netdev_info(pp->dev, "autoneg status set to %i\n",
|
||||
pp->use_inband_status);
|
||||
|
||||
if (netif_running(dev)) {
|
||||
mvneta_port_down(pp);
|
||||
mvneta_port_up(pp);
|
||||
}
|
||||
}
|
||||
|
||||
return phy_ethtool_sset(pp->phy_dev, cmd);
|
||||
}
|
||||
|
||||
@ -3223,9 +3275,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pp->use_inband_status)
|
||||
ctrl |= MVNETA_GMAC2_INBAND_AN_ENABLE;
|
||||
|
||||
/* Cancel Port Reset */
|
||||
ctrl &= ~MVNETA_GMAC2_PORT_RESET;
|
||||
mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl);
|
||||
|
Loading…
x
Reference in New Issue
Block a user