From patchwork Thu Jun 18 12:11:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiko Stuebner X-Patchwork-Id: 1312043 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=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sntech.de Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49ngm953wBz9sTP for ; Thu, 18 Jun 2020 22:12:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729670AbgFRMMF (ORCPT ); Thu, 18 Jun 2020 08:12:05 -0400 Received: from gloria.sntech.de ([185.11.138.130]:53386 "EHLO gloria.sntech.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728255AbgFRMLu (ORCPT ); Thu, 18 Jun 2020 08:11:50 -0400 Received: from ip5f5aa64a.dynamic.kabel-deutschland.de ([95.90.166.74] helo=phil.lan) by gloria.sntech.de with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jltOP-0007op-VG; Thu, 18 Jun 2020 14:11:42 +0200 From: Heiko Stuebner To: davem@davemloft.net, kuba@kernel.org Cc: robh+dt@kernel.org, andrew@lunn.ch, f.fainelli@gmail.com, hkallweit1@gmail.com, linux@armlinux.org.uk, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, heiko@sntech.de, christoph.muellner@theobroma-systems.com, Heiko Stuebner Subject: [PATCH v5 1/3] net: phy: mscc: move shared probe code into a helper Date: Thu, 18 Jun 2020 14:11:37 +0200 Message-Id: <20200618121139.1703762-2-heiko@sntech.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200618121139.1703762-1-heiko@sntech.de> References: <20200618121139.1703762-1-heiko@sntech.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Heiko Stuebner The different probe functions share a lot of code, so move the common parts into a helper to reduce duplication. This moves the devm_phy_package_join below the general allocation but as all components just allocate things, this should be ok. Suggested-by: Andrew Lunn Signed-off-by: Heiko Stuebner Reviewed-by: Andrew Lunn --- drivers/net/phy/mscc/mscc_main.c | 124 +++++++++++++++---------------- 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 5ddc44f87eaf..5d2777522fb4 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -1935,12 +1935,11 @@ static int vsc85xx_read_status(struct phy_device *phydev) return genphy_read_status(phydev); } -static int vsc8514_probe(struct phy_device *phydev) +static int vsc85xx_probe_helper(struct phy_device *phydev, + u32 *leds, int num_leds, u16 led_modes, + const struct vsc85xx_hw_stat *stats, int nstats) { struct vsc8531_private *vsc8531; - u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY, - VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY, - VSC8531_DUPLEX_COLLISION}; vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); if (!vsc8531) @@ -1948,54 +1947,66 @@ static int vsc8514_probe(struct phy_device *phydev) phydev->priv = vsc8531; - vsc8584_get_base_addr(phydev); - devm_phy_package_join(&phydev->mdio.dev, phydev, - vsc8531->base_addr, 0); - - vsc8531->nleds = 4; - vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES; - vsc8531->hw_stats = vsc85xx_hw_stats; - vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats); + vsc8531->nleds = num_leds; + vsc8531->supp_led_modes = led_modes; + vsc8531->hw_stats = stats; + vsc8531->nstats = nstats; vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats, sizeof(u64), GFP_KERNEL); if (!vsc8531->stats) return -ENOMEM; - return vsc85xx_dt_led_modes_get(phydev, default_mode); + return vsc85xx_dt_led_modes_get(phydev, leds); } -static int vsc8574_probe(struct phy_device *phydev) +static int vsc8514_probe(struct phy_device *phydev) { struct vsc8531_private *vsc8531; + int rc; u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY, VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY, VSC8531_DUPLEX_COLLISION}; - vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); - if (!vsc8531) - return -ENOMEM; - - phydev->priv = vsc8531; + rc = vsc85xx_probe_helper(phydev, default_mode, + ARRAY_SIZE(default_mode), + VSC85XX_SUPP_LED_MODES, + vsc85xx_hw_stats, + ARRAY_SIZE(vsc85xx_hw_stats)); + if (rc < 0) + return rc; + vsc8531 = phydev->priv; vsc8584_get_base_addr(phydev); - devm_phy_package_join(&phydev->mdio.dev, phydev, - vsc8531->base_addr, 0); + return devm_phy_package_join(&phydev->mdio.dev, phydev, + vsc8531->base_addr, 0); +} - vsc8531->nleds = 4; - vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES; - vsc8531->hw_stats = vsc8584_hw_stats; - vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats); - vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats, - sizeof(u64), GFP_KERNEL); - if (!vsc8531->stats) - return -ENOMEM; +static int vsc8574_probe(struct phy_device *phydev) +{ + struct vsc8531_private *vsc8531; + int rc; + u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY, + VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY, + VSC8531_DUPLEX_COLLISION}; + + rc = vsc85xx_probe_helper(phydev, default_mode, + ARRAY_SIZE(default_mode), + VSC8584_SUPP_LED_MODES, + vsc8584_hw_stats, + ARRAY_SIZE(vsc8584_hw_stats)); + if (rc < 0) + return rc; - return vsc85xx_dt_led_modes_get(phydev, default_mode); + vsc8531 = phydev->priv; + vsc8584_get_base_addr(phydev); + return devm_phy_package_join(&phydev->mdio.dev, phydev, + vsc8531->base_addr, 0); } static int vsc8584_probe(struct phy_device *phydev) { struct vsc8531_private *vsc8531; + int rc; u32 default_mode[4] = {VSC8531_LINK_1000_ACTIVITY, VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY, VSC8531_DUPLEX_COLLISION}; @@ -2005,32 +2016,24 @@ static int vsc8584_probe(struct phy_device *phydev) return -ENOTSUPP; } - vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); - if (!vsc8531) - return -ENOMEM; - - phydev->priv = vsc8531; + rc = vsc85xx_probe_helper(phydev, default_mode, + ARRAY_SIZE(default_mode), + VSC8584_SUPP_LED_MODES, + vsc8584_hw_stats, + ARRAY_SIZE(vsc8584_hw_stats)); + if (rc < 0) + return rc; + vsc8531 = phydev->priv; vsc8584_get_base_addr(phydev); - devm_phy_package_join(&phydev->mdio.dev, phydev, - vsc8531->base_addr, 0); - - vsc8531->nleds = 4; - vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES; - vsc8531->hw_stats = vsc8584_hw_stats; - vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats); - vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats, - sizeof(u64), GFP_KERNEL); - if (!vsc8531->stats) - return -ENOMEM; - - return vsc85xx_dt_led_modes_get(phydev, default_mode); + return devm_phy_package_join(&phydev->mdio.dev, phydev, + vsc8531->base_addr, 0); } static int vsc85xx_probe(struct phy_device *phydev) { struct vsc8531_private *vsc8531; - int rate_magic; + int rate_magic, rc; u32 default_mode[2] = {VSC8531_LINK_1000_ACTIVITY, VSC8531_LINK_100_ACTIVITY}; @@ -2038,23 +2041,18 @@ static int vsc85xx_probe(struct phy_device *phydev) if (rate_magic < 0) return rate_magic; - vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); - if (!vsc8531) - return -ENOMEM; - - phydev->priv = vsc8531; + rc = vsc85xx_probe_helper(phydev, default_mode, + ARRAY_SIZE(default_mode), + VSC85XX_SUPP_LED_MODES, + vsc85xx_hw_stats, + ARRAY_SIZE(vsc85xx_hw_stats)); + if (rc < 0) + return rc; + vsc8531 = phydev->priv; vsc8531->rate_magic = rate_magic; - vsc8531->nleds = 2; - vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES; - vsc8531->hw_stats = vsc85xx_hw_stats; - vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats); - vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats, - sizeof(u64), GFP_KERNEL); - if (!vsc8531->stats) - return -ENOMEM; - return vsc85xx_dt_led_modes_get(phydev, default_mode); + return 0; } /* Microsemi VSC85xx PHYs */ From patchwork Thu Jun 18 12:11:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiko Stuebner X-Patchwork-Id: 1312042 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=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sntech.de Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49ngm46K1mz9sSF for ; Thu, 18 Jun 2020 22:12:04 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729615AbgFRMME (ORCPT ); Thu, 18 Jun 2020 08:12:04 -0400 Received: from gloria.sntech.de ([185.11.138.130]:53400 "EHLO gloria.sntech.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729503AbgFRMLu (ORCPT ); Thu, 18 Jun 2020 08:11:50 -0400 Received: from ip5f5aa64a.dynamic.kabel-deutschland.de ([95.90.166.74] helo=phil.lan) by gloria.sntech.de with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jltOQ-0007op-CH; Thu, 18 Jun 2020 14:11:42 +0200 From: Heiko Stuebner To: davem@davemloft.net, kuba@kernel.org Cc: robh+dt@kernel.org, andrew@lunn.ch, f.fainelli@gmail.com, hkallweit1@gmail.com, linux@armlinux.org.uk, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, heiko@sntech.de, christoph.muellner@theobroma-systems.com, Heiko Stuebner Subject: [PATCH v5 2/3] dt-bindings: net: mscc-vsc8531: add optional clock properties Date: Thu, 18 Jun 2020 14:11:38 +0200 Message-Id: <20200618121139.1703762-3-heiko@sntech.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200618121139.1703762-1-heiko@sntech.de> References: <20200618121139.1703762-1-heiko@sntech.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Heiko Stuebner Some mscc ethernet phys have a configurable clock output, so describe the generic properties to access them in devicetrees. Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt b/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt index 5ff37c68c941..67625ba27f53 100644 --- a/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt +++ b/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt @@ -1,6 +1,8 @@ * Microsemi - vsc8531 Giga bit ethernet phy Optional properties: +- clock-output-names : Name for the exposed clock output +- #clock-cells : should be 0 - vsc8531,vddmac : The vddmac in mV. Allowed values is listed in the first row of Table 1 (below). This property is only used in combination From patchwork Thu Jun 18 12:11:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiko Stuebner X-Patchwork-Id: 1312041 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=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sntech.de Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49ngm02Vymz9sSd for ; Thu, 18 Jun 2020 22:12:00 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729583AbgFRML4 (ORCPT ); Thu, 18 Jun 2020 08:11:56 -0400 Received: from gloria.sntech.de ([185.11.138.130]:53388 "EHLO gloria.sntech.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725955AbgFRMLv (ORCPT ); Thu, 18 Jun 2020 08:11:51 -0400 Received: from ip5f5aa64a.dynamic.kabel-deutschland.de ([95.90.166.74] helo=phil.lan) by gloria.sntech.de with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jltOQ-0007op-Ph; Thu, 18 Jun 2020 14:11:42 +0200 From: Heiko Stuebner To: davem@davemloft.net, kuba@kernel.org Cc: robh+dt@kernel.org, andrew@lunn.ch, f.fainelli@gmail.com, hkallweit1@gmail.com, linux@armlinux.org.uk, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, heiko@sntech.de, christoph.muellner@theobroma-systems.com, Heiko Stuebner Subject: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants Date: Thu, 18 Jun 2020 14:11:39 +0200 Message-Id: <20200618121139.1703762-4-heiko@sntech.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200618121139.1703762-1-heiko@sntech.de> References: <20200618121139.1703762-1-heiko@sntech.de> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Heiko Stuebner At least VSC8530/8531/8540/8541 contain a clock output that can emit a predefined rate of 25, 50 or 125MHz. This may then feed back into the network interface as source clock. So expose a clock-provider from the phy using the common clock framework to allow setting the rate. Signed-off-by: Heiko Stuebner Reported-by: kernel test robot --- drivers/net/phy/mscc/mscc.h | 13 +++ drivers/net/phy/mscc/mscc_main.c | 182 +++++++++++++++++++++++++++++-- 2 files changed, 187 insertions(+), 8 deletions(-) diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index fbcee5fce7b2..94883dab5cc1 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -218,6 +218,13 @@ enum rgmii_clock_delay { #define INT_MEM_DATA_M 0x00ff #define INT_MEM_DATA(x) (INT_MEM_DATA_M & (x)) +#define MSCC_CLKOUT_CNTL 13 +#define CLKOUT_ENABLE BIT(15) +#define CLKOUT_FREQ_MASK GENMASK(14, 13) +#define CLKOUT_FREQ_25M (0x0 << 13) +#define CLKOUT_FREQ_50M (0x1 << 13) +#define CLKOUT_FREQ_125M (0x2 << 13) + #define MSCC_PHY_PROC_CMD 18 #define PROC_CMD_NCOMPLETED 0x8000 #define PROC_CMD_FAILED 0x4000 @@ -360,6 +367,12 @@ struct vsc8531_private { */ unsigned int base_addr; +#ifdef CONFIG_COMMON_CLK + struct clk_hw clkout_hw; +#endif + u32 clkout_rate; + int clkout_enabled; + #if IS_ENABLED(CONFIG_MACSEC) /* MACsec fields: * - One SecY per device (enforced at the s/w implementation level) diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 5d2777522fb4..727a9dd58403 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -7,6 +7,7 @@ * Copyright (c) 2016 Microsemi Corporation */ +#include #include #include #include @@ -431,7 +432,6 @@ static int vsc85xx_dt_led_mode_get(struct phy_device *phydev, return led_mode; } - #else static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev) { @@ -1508,6 +1508,43 @@ static int vsc85xx_config_init(struct phy_device *phydev) return 0; } +static int vsc8531_config_init(struct phy_device *phydev) +{ + struct vsc8531_private *vsc8531 = phydev->priv; + u16 val; + int rc; + + rc = vsc85xx_config_init(phydev); + if (rc) + return rc; + +#ifdef CONFIG_COMMON_CLK + switch (vsc8531->clkout_rate) { + case 25000000: + val = CLKOUT_FREQ_25M; + break; + case 50000000: + val = CLKOUT_FREQ_50M; + break; + case 125000000: + val = CLKOUT_FREQ_125M; + break; + default: + return -EINVAL; + } + + if (vsc8531->clkout_enabled) + val |= CLKOUT_ENABLE; + + rc = phy_write_paged(phydev, MSCC_PHY_PAGE_EXTENDED_GPIO, + MSCC_CLKOUT_CNTL, val); + if (rc) + return rc; +#endif + + return 0; +} + static int vsc8584_did_interrupt(struct phy_device *phydev) { int rc = 0; @@ -1935,6 +1972,107 @@ static int vsc85xx_read_status(struct phy_device *phydev) return genphy_read_status(phydev); } +#ifdef CONFIG_COMMON_CLK +#define clkout_hw_to_vsc8531(_hw) container_of(_hw, struct vsc8531_private, clkout_hw) + +static int clkout_rates[] = { + 125000000, + 50000000, + 25000000, +}; + +static unsigned long vsc8531_clkout_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct vsc8531_private *vsc8531 = clkout_hw_to_vsc8531(hw); + + return vsc8531->clkout_rate; +} + +static long vsc8531_clkout_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) + if (clkout_rates[i] <= rate) + return clkout_rates[i]; + return 0; +} + +static int vsc8531_clkout_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct vsc8531_private *vsc8531 = clkout_hw_to_vsc8531(hw); + + vsc8531->clkout_rate = rate; + return 0; +} + +static int vsc8531_clkout_prepare(struct clk_hw *hw) +{ + struct vsc8531_private *vsc8531 = clkout_hw_to_vsc8531(hw); + + vsc8531->clkout_enabled = true; + return 0; +} + +static void vsc8531_clkout_unprepare(struct clk_hw *hw) +{ + struct vsc8531_private *vsc8531 = clkout_hw_to_vsc8531(hw); + + vsc8531->clkout_enabled = false; +} + +static int vsc8531_clkout_is_prepared(struct clk_hw *hw) +{ + struct vsc8531_private *vsc8531 = clkout_hw_to_vsc8531(hw); + + return vsc8531->clkout_enabled; +} + +static const struct clk_ops vsc8531_clkout_ops = { + .prepare = vsc8531_clkout_prepare, + .unprepare = vsc8531_clkout_unprepare, + .is_prepared = vsc8531_clkout_is_prepared, + .recalc_rate = vsc8531_clkout_recalc_rate, + .round_rate = vsc8531_clkout_round_rate, + .set_rate = vsc8531_clkout_set_rate, +}; + +static int vsc8531_register_clkout(struct phy_device *phydev) +{ + struct vsc8531_private *vsc8531 = phydev->priv; + struct device *dev = &phydev->mdio.dev; + struct device_node *of_node = dev->of_node; + struct clk_init_data init; + int ret; + + init.name = "vsc8531-clkout"; + init.ops = &vsc8531_clkout_ops; + init.flags = 0; + init.parent_names = NULL; + init.num_parents = 0; + vsc8531->clkout_hw.init = &init; + + /* optional override of the clockname */ + of_property_read_string(of_node, "clock-output-names", &init.name); + + /* register the clock */ + ret = devm_clk_hw_register(dev, &vsc8531->clkout_hw); + if (!ret) + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + &vsc8531->clkout_hw); + + return ret; +} +#else +static int vsc8531_register_clkout(struct phy_device *phydev) +{ + return 0; +} +#endif + static int vsc85xx_probe_helper(struct phy_device *phydev, u32 *leds, int num_leds, u16 led_modes, const struct vsc85xx_hw_stat *stats, int nstats) @@ -1981,6 +2119,34 @@ static int vsc8514_probe(struct phy_device *phydev) vsc8531->base_addr, 0); } +static int vsc8531_probe(struct phy_device *phydev) +{ + struct vsc8531_private *vsc8531; + int rate_magic, rc; + u32 default_mode[2] = {VSC8531_LINK_1000_ACTIVITY, + VSC8531_LINK_100_ACTIVITY}; + + rate_magic = vsc85xx_edge_rate_magic_get(phydev); + if (rate_magic < 0) + return rate_magic; + + rc = vsc85xx_probe_helper(phydev, default_mode, + ARRAY_SIZE(default_mode), + VSC85XX_SUPP_LED_MODES, + vsc85xx_hw_stats, + ARRAY_SIZE(vsc85xx_hw_stats)); + if (rc < 0) + return rc; + + vsc8531 = phydev->priv; + vsc8531->rate_magic = rate_magic; + rc = vsc8531_register_clkout(phydev); + if (rc < 0) + return rc; + + return 0; +} + static int vsc8574_probe(struct phy_device *phydev) { struct vsc8531_private *vsc8531; @@ -2136,14 +2302,14 @@ static struct phy_driver vsc85xx_driver[] = { .phy_id_mask = 0xfffffff0, /* PHY_BASIC_FEATURES */ .soft_reset = &genphy_soft_reset, - .config_init = &vsc85xx_config_init, + .config_init = &vsc8531_config_init, .config_aneg = &vsc85xx_config_aneg, .read_status = &vsc85xx_read_status, .ack_interrupt = &vsc85xx_ack_interrupt, .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, - .probe = &vsc85xx_probe, + .probe = &vsc8531_probe, .set_wol = &vsc85xx_wol_set, .get_wol = &vsc85xx_wol_get, .get_tunable = &vsc85xx_get_tunable, @@ -2160,14 +2326,14 @@ static struct phy_driver vsc85xx_driver[] = { .phy_id_mask = 0xfffffff0, /* PHY_GBIT_FEATURES */ .soft_reset = &genphy_soft_reset, - .config_init = &vsc85xx_config_init, + .config_init = &vsc8531_config_init, .config_aneg = &vsc85xx_config_aneg, .read_status = &vsc85xx_read_status, .ack_interrupt = &vsc85xx_ack_interrupt, .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, - .probe = &vsc85xx_probe, + .probe = &vsc8531_probe, .set_wol = &vsc85xx_wol_set, .get_wol = &vsc85xx_wol_get, .get_tunable = &vsc85xx_get_tunable, @@ -2184,14 +2350,14 @@ static struct phy_driver vsc85xx_driver[] = { .phy_id_mask = 0xfffffff0, /* PHY_BASIC_FEATURES */ .soft_reset = &genphy_soft_reset, - .config_init = &vsc85xx_config_init, + .config_init = &vsc8531_config_init, .config_aneg = &vsc85xx_config_aneg, .read_status = &vsc85xx_read_status, .ack_interrupt = &vsc85xx_ack_interrupt, .config_intr = &vsc85xx_config_intr, .suspend = &genphy_suspend, .resume = &genphy_resume, - .probe = &vsc85xx_probe, + .probe = &vsc8531_probe, .set_wol = &vsc85xx_wol_set, .get_wol = &vsc85xx_wol_get, .get_tunable = &vsc85xx_get_tunable, @@ -2208,7 +2374,7 @@ static struct phy_driver vsc85xx_driver[] = { .phy_id_mask = 0xfffffff0, /* PHY_GBIT_FEATURES */ .soft_reset = &genphy_soft_reset, - .config_init = &vsc85xx_config_init, + .config_init = &vsc8531_config_init, .config_aneg = &vsc85xx_config_aneg, .read_status = &vsc85xx_read_status, .ack_interrupt = &vsc85xx_ack_interrupt,