From patchwork Thu May 10 20:17:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Fainelli X-Patchwork-Id: 911540 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="IzRVaqyn"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40hl0H3PGGz9s0w for ; Fri, 11 May 2018 06:18:07 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752274AbeEJUSA (ORCPT ); Thu, 10 May 2018 16:18:00 -0400 Received: from mail-pl0-f68.google.com ([209.85.160.68]:40701 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751878AbeEJURz (ORCPT ); Thu, 10 May 2018 16:17:55 -0400 Received: by mail-pl0-f68.google.com with SMTP id t12-v6so1929180plo.7 for ; Thu, 10 May 2018 13:17:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GQROOop9y1hXcA03JJZ/ODZuEG+Y8ZtImoC5sxJTjyU=; b=IzRVaqynQ6YB5K21Knm9CQXpJBvd9vfBRY/mAjMKxwUYADdZw7qQZJW8x5MgClXc/j Ax5LOUUG70sogi0iWdoOWR8+FQ2j3OoK16aQW/QKm1aBBXUIUi0Nq2/GgQG9dkd/dmrZ Np7iCNjbvKSivj73xaadArlBaPbzUNF+r+b8EAE67M3eE+9zwD+Fs6zQCBlmk84f3Ml7 SnVCbwewRcg84A7kV17+dFqosK8cj35MUIcuInlRzXdZhcDHLeJYGk/JnqOSp/nj1Q8r e5IgpSC7KpK6P5eQUXTQtqBpiFhikt9PaypvFx5jgl38IuwX/tEiHebbBIksN3V7ecBp 7wtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GQROOop9y1hXcA03JJZ/ODZuEG+Y8ZtImoC5sxJTjyU=; b=ckHToC/aBLVIfoPdyNpKqjCaVSDoPo1/5JjppNnly/DmtH3xJ1uzsdsxoQlQr/uwo0 aDl0vYqRvRoEBtsDUQnc9hgtvv8RSpxiZgQr+2yRzLw1ON5RnOzoyf8MdQG2w/77Pju7 fz9GnfEdNwQdQQNWcTJ07khc9cbXuaTLrRD9IYcI9VkPxuyZkB3jL/uxA8sfJ9yuvCrI ozDszla+XiZsdV5DwqNd1TgJt/W6yU5HlKYDudXy7ZsPtkC3uf7GElRyhGFDdeW6d5Y3 cKBpRDI3LcNP7btox84gcATstCBvHM3jJ1isMwfZNF28GHxXgO4CPRAZVdIsrzA/mp3M foZA== X-Gm-Message-State: ALKqPwfe+UlVUoCEYCPGS4o51N1cUmMZgXC9Shmu4Xs82bktDoWNs/6E 6HjD4g5jvHVjUdNf7CBXg7FZdHVi X-Google-Smtp-Source: AB8JxZocdKeMmtxhyU0MI8Wv6VMAmrdfJf9Qv53uwmhBu2omkK6VRbreCHrnOL0eByLogb0eAO3jbg== X-Received: by 2002:a17:902:59ce:: with SMTP id d14-v6mr2714907plj.253.1525983474076; Thu, 10 May 2018 13:17:54 -0700 (PDT) Received: from cox.net ([192.19.223.250]) by smtp.gmail.com with ESMTPSA id f78-v6sm3895297pfk.138.2018.05.10.13.17.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 10 May 2018 13:17:53 -0700 (PDT) From: Florian Fainelli To: netdev@vger.kernel.org Cc: Russell King , Andrew Lunn , Florian Fainelli , privat@egil-hjelmeland.no, vivien.didelot@savoirfairelinux.com, davem@davemloft.net, sean.wang@mediatek.com, Woojung.Huh@microchip.com, john@phrozen.org, cphealy@gmail.com Subject: [PATCH net-next v2 7/9] net: dsa: mv88e6xxx: add PHYLINK support Date: Thu, 10 May 2018 13:17:35 -0700 Message-Id: <20180510201737.13887-8-f.fainelli@gmail.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180510201737.13887-1-f.fainelli@gmail.com> References: <20180510201737.13887-1-f.fainelli@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Russell King Add rudimentary phylink support to mv88e6xxx. This allows the driver using user ports with fixed links to keep operating normally. User ports with normal PHYs are not affected since the switch automatically manages their link parameters. User facing ports which use a SFP/SFF with a non-fixed link mode might require a call to phylink_mac_change() to operate properly. Signed-off-by: Russell King [Andrew: fixed link setting after adding link polling] Signed-off-by: Andrew Lunn [florian: expand commit message] Signed-off-by: Florian Fainelli --- drivers/net/dsa/mv88e6xxx/chip.c | 83 ++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.c | 39 +++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 3 ++ 3 files changed, 125 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index e7e079b1888c..1d20e9445199 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "chip.h" @@ -580,6 +581,83 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, dev_err(ds->dev, "p%d: failed to configure MAC\n", port); } +static void mv88e6xxx_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) +{ +} + +static int mv88e6xxx_link_state(struct dsa_switch *ds, int port, + struct phylink_link_state *state) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_port_link_state(chip, port, state); + mutex_unlock(&chip->reg_lock); + + return err; +} + +static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int speed, duplex, link, err; + + if (mode == MLO_AN_PHY) + return; + + if (mode == MLO_AN_FIXED) { + link = LINK_FORCED_UP; + speed = state->speed; + duplex = state->duplex; + } else { + speed = SPEED_UNFORCED; + duplex = DUPLEX_UNFORCED; + link = LINK_UNFORCED; + } + + mutex_lock(&chip->reg_lock); + err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, + state->interface); + mutex_unlock(&chip->reg_lock); + + if (err && err != -EOPNOTSUPP) + dev_err(ds->dev, "p%d: failed to configure MAC\n", port); +} + +static void mv88e6xxx_mac_link_force(struct dsa_switch *ds, int port, int link) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + mutex_lock(&chip->reg_lock); + err = chip->info->ops->port_set_link(chip, port, link); + mutex_unlock(&chip->reg_lock); + + if (err) + dev_err(chip->dev, "p%d: failed to force MAC link\n", port); +} + +static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) +{ + if (mode == MLO_AN_FIXED) + mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_DOWN); +} + +static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface, + struct phy_device *phydev) +{ + if (mode == MLO_AN_FIXED) + mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP); +} + static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port) { if (!chip->info->ops->stats_snapshot) @@ -4140,6 +4218,11 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .get_tag_protocol = mv88e6xxx_get_tag_protocol, .setup = mv88e6xxx_setup, .adjust_link = mv88e6xxx_adjust_link, + .phylink_validate = mv88e6xxx_validate, + .phylink_mac_link_state = mv88e6xxx_link_state, + .phylink_mac_config = mv88e6xxx_mac_config, + .phylink_mac_link_down = mv88e6xxx_mac_link_down, + .phylink_mac_link_up = mv88e6xxx_mac_link_up, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 6315774d72b3..429d0ebcd5b1 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "chip.h" #include "port.h" @@ -378,6 +379,44 @@ int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode) return 0; } +int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port, + struct phylink_link_state *state) +{ + int err; + u16 reg; + + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); + if (err) + return err; + + switch (reg & MV88E6XXX_PORT_STS_SPEED_MASK) { + case MV88E6XXX_PORT_STS_SPEED_10: + state->speed = SPEED_10; + break; + case MV88E6XXX_PORT_STS_SPEED_100: + state->speed = SPEED_100; + break; + case MV88E6XXX_PORT_STS_SPEED_1000: + state->speed = SPEED_1000; + break; + case MV88E6XXX_PORT_STS_SPEED_10000: + if ((reg &MV88E6XXX_PORT_STS_CMODE_MASK) == + MV88E6XXX_PORT_STS_CMODE_2500BASEX) + state->speed = SPEED_2500; + else + state->speed = SPEED_10000; + break; + } + + state->duplex = reg & MV88E6XXX_PORT_STS_DUPLEX ? + DUPLEX_FULL : DUPLEX_HALF; + state->link = !!(reg & MV88E6XXX_PORT_STS_LINK); + state->an_enabled = 1; + state->an_complete = state->link; + + return 0; +} + /* Offset 0x02: Jamming Control * * Do not limit the period of time that this port can be paused for by diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index b16d5f0e6e9c..5e1db1b221ca 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -29,6 +29,7 @@ #define MV88E6XXX_PORT_STS_SPEED_10 0x0000 #define MV88E6XXX_PORT_STS_SPEED_100 0x0100 #define MV88E6XXX_PORT_STS_SPEED_1000 0x0200 +#define MV88E6XXX_PORT_STS_SPEED_10000 0x0300 #define MV88E6352_PORT_STS_EEE 0x0040 #define MV88E6165_PORT_STS_AM_DIS 0x0040 #define MV88E6185_PORT_STS_MGMII 0x0040 @@ -295,6 +296,8 @@ int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in, int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, phy_interface_t mode); int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); +int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port, + struct phylink_link_state *state); int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, int upstream_port);