From patchwork Sun Aug 23 09:46:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 509804 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 75B401402B7 for ; Sun, 23 Aug 2015 19:54:53 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752078AbbHWJys (ORCPT ); Sun, 23 Aug 2015 05:54:48 -0400 Received: from vps0.lunn.ch ([178.209.37.122]:38069 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751971AbbHWJyp (ORCPT ); Sun, 23 Aug 2015 05:54:45 -0400 Received: from andrew by vps0.lunn.ch with local (Exim 4.80) (envelope-from ) id 1ZTRrj-0005KI-Q4; Sun, 23 Aug 2015 11:47:03 +0200 From: Andrew Lunn To: David Miller Cc: Florian Fainelli , netdev , Andrew Lunn Subject: [PATCH net-next 2/9] dsa: mv88e6xxx: Allow speed/duplex of port to be configured Date: Sun, 23 Aug 2015 11:46:53 +0200 Message-Id: <1440323220-20438-3-git-send-email-andrew@lunn.ch> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1440323220-20438-1-git-send-email-andrew@lunn.ch> References: <1440323220-20438-1-git-send-email-andrew@lunn.ch> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The current code sets user ports to perform auto negotiation using the phy. CPU and DSA ports are configured to full duplex and maximum speed the switch supports. There are however use cases where the CPU has a slower port, and when user ports have SFP modules with fixed speed. In these cases, port settings to be read from a fixed_phy devices. The switch driver then needs to implement the adjust_link op, so the port settings can be set. Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli --- drivers/net/dsa/mv88e6123_61_65.c | 1 + drivers/net/dsa/mv88e6131.c | 1 + drivers/net/dsa/mv88e6171.c | 1 + drivers/net/dsa/mv88e6352.c | 1 + drivers/net/dsa/mv88e6xxx.c | 58 +++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx.h | 2 ++ 6 files changed, 64 insertions(+) diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c index 71a29a7ce538..3de2a6d73fdc 100644 --- a/drivers/net/dsa/mv88e6123_61_65.c +++ b/drivers/net/dsa/mv88e6123_61_65.c @@ -129,6 +129,7 @@ struct dsa_switch_driver mv88e6123_61_65_switch_driver = { .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, + .adjust_link = mv88e6xxx_adjust_link, #ifdef CONFIG_NET_DSA_HWMON .get_temp = mv88e6xxx_get_temp, #endif diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 32f4a08e9bc9..3e8386529965 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -182,6 +182,7 @@ struct dsa_switch_driver mv88e6131_switch_driver = { .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, + .adjust_link = mv88e6xxx_adjust_link, }; MODULE_ALIAS("platform:mv88e6085"); diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 735f04cd83ee..d54b7400e8d8 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -108,6 +108,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, + .adjust_link = mv88e6xxx_adjust_link, #ifdef CONFIG_NET_DSA_HWMON .get_temp = mv88e6xxx_get_temp, #endif diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 14b71779df99..1f5129c105fb 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -328,6 +328,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, + .adjust_link = mv88e6xxx_adjust_link, .set_eee = mv88e6xxx_set_eee, .get_eee = mv88e6xxx_get_eee, #ifdef CONFIG_NET_DSA_HWMON diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 2ab3f9810593..7901db6503b4 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -560,6 +561,63 @@ static bool mv88e6xxx_6352_family(struct dsa_switch *ds) return false; } +/* We expect the switch to perform auto negotiation if there is a real + * phy. However, in the case of a fixed link phy, we force the port + * settings from the fixed link settings. + */ +void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, + struct phy_device *phydev) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + u32 ret, reg; + + if (!phy_is_pseudo_fixed_link(phydev)) + return; + + mutex_lock(&ps->smi_mutex); + + ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL); + if (ret < 0) + goto out; + + reg = ret & ~(PORT_PCS_CTRL_LINK_UP | + PORT_PCS_CTRL_FORCE_LINK | + PORT_PCS_CTRL_DUPLEX_FULL | + PORT_PCS_CTRL_FORCE_DUPLEX | + PORT_PCS_CTRL_UNFORCED); + + reg |= PORT_PCS_CTRL_FORCE_LINK; + if (phydev->link) + reg |= PORT_PCS_CTRL_LINK_UP; + + if (mv88e6xxx_6065_family(ds) && phydev->speed > SPEED_100) + goto out; + + switch (phydev->speed) { + case SPEED_1000: + reg |= PORT_PCS_CTRL_1000; + break; + case SPEED_100: + reg |= PORT_PCS_CTRL_100; + break; + case SPEED_10: + reg |= PORT_PCS_CTRL_10; + break; + default: + pr_info("Unknown speed"); + goto out; + } + + reg |= PORT_PCS_CTRL_FORCE_DUPLEX; + if (phydev->duplex == DUPLEX_FULL) + reg |= PORT_PCS_CTRL_DUPLEX_FULL; + + _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_PCS_CTRL, reg); + +out: + mutex_unlock(&ps->smi_mutex); +} + /* Must be called with SMI mutex held */ static int _mv88e6xxx_stats_wait(struct dsa_switch *ds) { diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 72ca887feb0d..79003c55fe62 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -446,6 +446,8 @@ void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data); int mv88e6xxx_get_sset_count(struct dsa_switch *ds); int mv88e6xxx_get_sset_count_basic(struct dsa_switch *ds); +void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, + struct phy_device *phydev); int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port); void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, struct ethtool_regs *regs, void *_p);