* [PATCH v5 0/3] add clkout support to mscc phys
@ 2020-06-18 12:11 Heiko Stuebner
2020-06-18 12:11 ` [PATCH v5 1/3] net: phy: mscc: move shared probe code into a helper Heiko Stuebner
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Heiko Stuebner @ 2020-06-18 12:11 UTC (permalink / raw)
To: davem, kuba
Cc: robh+dt, andrew, f.fainelli, hkallweit1, linux, netdev,
devicetree, linux-kernel, heiko, christoph.muellner
The main part of this series is adding handling of the clkout
controls some of the mscc phys have and while at it Andrew
asked for some of the duplicated probe functionality to be
factored out into a common function.
A working config on rockchip/rk3368-lion for example now looks like:
&gmac {
status = "okay";
mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
phy0: phy@0 {
compatible = "ethernet-phy-id0007.0570";
reg = <0>;
assigned-clocks = <&phy0>, <&cru SCLK_MAC>;
assigned-clock-rates = <125000000>, <125000000>;
assigned-clock-parents = <0>, <&phy0>;
clock-output-names = "ext_gmac";
#clock-cells = <0>;
vsc8531,edge-slowdown = <7>;
vsc8531,led-0-mode = <1>;
vsc8531,led-1-mode = <2>;
};
};
};
changes in v5:
- added Andrew's Rb for patch 1
- modified clkout handling to be a clock-provider
to fit into the existing clock structures
changes in v4:
- fix missing variable initialization in one probe function
changes in v3:
- adapt to 5.8 merge-window results
- introduce a more generic enet-phy-property instead of
using a vsc8531,* one - suggested by Andrew
changes in v2:
- new probe factoring patch as suggested by Andrew
Heiko Stuebner (3):
net: phy: mscc: move shared probe code into a helper
dt-bindings: net: mscc-vsc8531: add optional clock properties
net: phy: mscc: handle the clkout control on some phy variants
.../bindings/net/mscc-phy-vsc8531.txt | 2 +
drivers/net/phy/mscc/mscc.h | 13 +
drivers/net/phy/mscc/mscc_main.c | 306 ++++++++++++++----
3 files changed, 250 insertions(+), 71 deletions(-)
--
2.26.2
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v5 1/3] net: phy: mscc: move shared probe code into a helper 2020-06-18 12:11 [PATCH v5 0/3] add clkout support to mscc phys Heiko Stuebner @ 2020-06-18 12:11 ` Heiko Stuebner 2020-06-18 12:11 ` [PATCH v5 2/3] dt-bindings: net: mscc-vsc8531: add optional clock properties Heiko Stuebner 2020-06-18 12:11 ` [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants Heiko Stuebner 2 siblings, 0 replies; 15+ messages in thread From: Heiko Stuebner @ 2020-06-18 12:11 UTC (permalink / raw) To: davem, kuba Cc: robh+dt, andrew, f.fainelli, hkallweit1, linux, netdev, devicetree, linux-kernel, heiko, christoph.muellner, Heiko Stuebner From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> 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 <andrew@lunn.ch> Signed-off-by: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> --- 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 */ -- 2.26.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v5 2/3] dt-bindings: net: mscc-vsc8531: add optional clock properties 2020-06-18 12:11 [PATCH v5 0/3] add clkout support to mscc phys Heiko Stuebner 2020-06-18 12:11 ` [PATCH v5 1/3] net: phy: mscc: move shared probe code into a helper Heiko Stuebner @ 2020-06-18 12:11 ` Heiko Stuebner 2020-06-19 5:01 ` Florian Fainelli 2020-06-18 12:11 ` [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants Heiko Stuebner 2 siblings, 1 reply; 15+ messages in thread From: Heiko Stuebner @ 2020-06-18 12:11 UTC (permalink / raw) To: davem, kuba Cc: robh+dt, andrew, f.fainelli, hkallweit1, linux, netdev, devicetree, linux-kernel, heiko, christoph.muellner, Heiko Stuebner From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> Some mscc ethernet phys have a configurable clock output, so describe the generic properties to access them in devicetrees. Signed-off-by: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> --- 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 -- 2.26.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v5 2/3] dt-bindings: net: mscc-vsc8531: add optional clock properties 2020-06-18 12:11 ` [PATCH v5 2/3] dt-bindings: net: mscc-vsc8531: add optional clock properties Heiko Stuebner @ 2020-06-19 5:01 ` Florian Fainelli 2020-06-19 6:46 ` Heiko Stuebner 0 siblings, 1 reply; 15+ messages in thread From: Florian Fainelli @ 2020-06-19 5:01 UTC (permalink / raw) To: Heiko Stuebner, davem, kuba Cc: robh+dt, andrew, hkallweit1, linux, netdev, devicetree, linux-kernel, christoph.muellner, Heiko Stuebner On 6/18/2020 5:11 AM, Heiko Stuebner wrote: > From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > Some mscc ethernet phys have a configurable clock output, so describe the > generic properties to access them in devicetrees. > > Signed-off-by: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > --- > 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 > With that approach, you also need to be careful as a driver writer to ensure that you have at least probed the MDIO bus to ensure that the PHY device has been created (and therefore it is available as a clock provider) if that same Ethernet MAC is a consumer of that clock (which it appears to be). Otherwise you may just never probe and be trapped in a circular dependency. -- Florian ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 2/3] dt-bindings: net: mscc-vsc8531: add optional clock properties 2020-06-19 5:01 ` Florian Fainelli @ 2020-06-19 6:46 ` Heiko Stuebner 0 siblings, 0 replies; 15+ messages in thread From: Heiko Stuebner @ 2020-06-19 6:46 UTC (permalink / raw) To: Florian Fainelli Cc: davem, kuba, robh+dt, andrew, hkallweit1, linux, netdev, devicetree, linux-kernel, christoph.muellner Am Freitag, 19. Juni 2020, 07:01:58 CEST schrieb Florian Fainelli: > > On 6/18/2020 5:11 AM, Heiko Stuebner wrote: > > From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > > > Some mscc ethernet phys have a configurable clock output, so describe the > > generic properties to access them in devicetrees. > > > > Signed-off-by: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > --- > > 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 > > > > With that approach, you also need to be careful as a driver writer to > ensure that you have at least probed the MDIO bus to ensure that the PHY > device has been created (and therefore it is available as a clock > provider) if that same Ethernet MAC is a consumer of that clock (which > it appears to be). Otherwise you may just never probe and be trapped in > a circular dependency. Yep - although without anything like this, the phy won't emit any clock at all. Even when enabling the clock output in u-boot already, when the kernel starts that config is lost, so no existing board should break. As you can see in the discussion about patch 3/3 the wanted solution is not so clear cut as well. With Rob suggesting this clock-provider way and Russell strongly encouraging taking a second look. [My first iteration (till v4) was doing it like other phys by specifying a property to just tell the phy what frequency to output] I don't really have a preference for one or the other, so maybe you can also give a vote over there ;-) Heiko ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 12:11 [PATCH v5 0/3] add clkout support to mscc phys Heiko Stuebner 2020-06-18 12:11 ` [PATCH v5 1/3] net: phy: mscc: move shared probe code into a helper Heiko Stuebner 2020-06-18 12:11 ` [PATCH v5 2/3] dt-bindings: net: mscc-vsc8531: add optional clock properties Heiko Stuebner @ 2020-06-18 12:11 ` Heiko Stuebner 2020-06-18 13:28 ` Andrew Lunn ` (2 more replies) 2 siblings, 3 replies; 15+ messages in thread From: Heiko Stuebner @ 2020-06-18 12:11 UTC (permalink / raw) To: davem, kuba Cc: robh+dt, andrew, f.fainelli, hkallweit1, linux, netdev, devicetree, linux-kernel, heiko, christoph.muellner, Heiko Stuebner From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> 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 <heiko.stuebner@theobroma-systems.com> --- 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 <linux/clk-provider.h> #include <linux/firmware.h> #include <linux/jiffies.h> #include <linux/kernel.h> @@ -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, -- 2.26.2 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 12:11 ` [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants Heiko Stuebner @ 2020-06-18 13:28 ` Andrew Lunn 2020-06-18 13:41 ` Russell King - ARM Linux admin 2020-06-18 15:49 ` Jakub Kicinski 2020-06-19 0:50 ` kernel test robot 2 siblings, 1 reply; 15+ messages in thread From: Andrew Lunn @ 2020-06-18 13:28 UTC (permalink / raw) To: Heiko Stuebner Cc: davem, kuba, robh+dt, f.fainelli, hkallweit1, linux, netdev, devicetree, linux-kernel, christoph.muellner, Heiko Stuebner On Thu, Jun 18, 2020 at 02:11:39PM +0200, Heiko Stuebner wrote: > From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > 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 <heiko.stuebner@theobroma-systems.com> > --- > 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 <linux/clk-provider.h> > #include <linux/firmware.h> > #include <linux/jiffies.h> > #include <linux/kernel.h> > @@ -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 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 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, I'm not sure this is the expected behaviour. The clk itself should only start ticking when the enable callback is called. But this code will enable the clock when config_init() is called. I think you should implement the enable and disable methods. Andrew ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 13:28 ` Andrew Lunn @ 2020-06-18 13:41 ` Russell King - ARM Linux admin 2020-06-18 15:41 ` Heiko Stübner 0 siblings, 1 reply; 15+ messages in thread From: Russell King - ARM Linux admin @ 2020-06-18 13:41 UTC (permalink / raw) To: Andrew Lunn Cc: Heiko Stuebner, davem, kuba, robh+dt, f.fainelli, hkallweit1, netdev, devicetree, linux-kernel, christoph.muellner, Heiko Stuebner On Thu, Jun 18, 2020 at 03:28:22PM +0200, Andrew Lunn wrote: > On Thu, Jun 18, 2020 at 02:11:39PM +0200, Heiko Stuebner wrote: > > From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > > > 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 <heiko.stuebner@theobroma-systems.com> > > --- > > 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 <linux/clk-provider.h> > > #include <linux/firmware.h> > > #include <linux/jiffies.h> > > #include <linux/kernel.h> > > @@ -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 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 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, > > I'm not sure this is the expected behaviour. The clk itself should > only start ticking when the enable callback is called. But this code > will enable the clock when config_init() is called. I think you should > implement the enable and disable methods. That is actually incorrect. The whole "prepare" vs "enable" difference is that prepare can schedule, enable isn't permitted. So, if you need to sleep to enable the clock, then enabling the clock in the prepare callback is the right thing to do. However, the above driver just sets a flag, which only gets used when the PHY's config_init method is called; that really doesn't seem to be sane - the clock is available from the point that the PHY has been probed, and it'll be expected that once the clock is published, it can be made functional. -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last! ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 13:41 ` Russell King - ARM Linux admin @ 2020-06-18 15:41 ` Heiko Stübner 2020-06-18 15:47 ` Russell King - ARM Linux admin 0 siblings, 1 reply; 15+ messages in thread From: Heiko Stübner @ 2020-06-18 15:41 UTC (permalink / raw) To: Russell King - ARM Linux admin Cc: Andrew Lunn, davem, kuba, robh+dt, f.fainelli, hkallweit1, netdev, devicetree, linux-kernel, christoph.muellner Am Donnerstag, 18. Juni 2020, 15:41:02 CEST schrieb Russell King - ARM Linux admin: > On Thu, Jun 18, 2020 at 03:28:22PM +0200, Andrew Lunn wrote: > > On Thu, Jun 18, 2020 at 02:11:39PM +0200, Heiko Stuebner wrote: > > > From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > > > > > 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 <heiko.stuebner@theobroma-systems.com> > > > --- > > > 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 <linux/clk-provider.h> > > > #include <linux/firmware.h> > > > #include <linux/jiffies.h> > > > #include <linux/kernel.h> > > > @@ -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 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 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, > > > > I'm not sure this is the expected behaviour. The clk itself should > > only start ticking when the enable callback is called. But this code > > will enable the clock when config_init() is called. I think you should > > implement the enable and disable methods. > > That is actually incorrect. The whole "prepare" vs "enable" difference > is that prepare can schedule, enable isn't permitted. So, if you need > to sleep to enable the clock, then enabling the clock in the prepare > callback is the right thing to do. > > However, the above driver just sets a flag, which only gets used when > the PHY's config_init method is called; that really doesn't seem to be > sane - the clock is available from the point that the PHY has been > probed, and it'll be expected that once the clock is published, it can > be made functional. Though I'm not sure how this fits in the whole bringup of ethernet phys. Like the phy is dependent on the underlying ethernet controller to actually turn it on. I guess we should check the phy-state and if it's not accessible, just keep the values and if it's in a suitable state do the configuration. Calling a vsc8531_config_clkout() from both the vsc8531_config_init() as well as the clk_(un-)prepare and clk_set_rate functions and being protected by a check against phy_is_started() ? Heiko ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 15:41 ` Heiko Stübner @ 2020-06-18 15:47 ` Russell King - ARM Linux admin 2020-06-18 16:01 ` Heiko Stübner 0 siblings, 1 reply; 15+ messages in thread From: Russell King - ARM Linux admin @ 2020-06-18 15:47 UTC (permalink / raw) To: Heiko Stübner Cc: Andrew Lunn, davem, kuba, robh+dt, f.fainelli, hkallweit1, netdev, devicetree, linux-kernel, christoph.muellner On Thu, Jun 18, 2020 at 05:41:54PM +0200, Heiko Stübner wrote: > Am Donnerstag, 18. Juni 2020, 15:41:02 CEST schrieb Russell King - ARM Linux admin: > > On Thu, Jun 18, 2020 at 03:28:22PM +0200, Andrew Lunn wrote: > > > On Thu, Jun 18, 2020 at 02:11:39PM +0200, Heiko Stuebner wrote: > > > > From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > > > > > > > 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 <heiko.stuebner@theobroma-systems.com> > > > > --- > > > > 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 <linux/clk-provider.h> > > > > #include <linux/firmware.h> > > > > #include <linux/jiffies.h> > > > > #include <linux/kernel.h> > > > > @@ -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 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 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, > > > > > > I'm not sure this is the expected behaviour. The clk itself should > > > only start ticking when the enable callback is called. But this code > > > will enable the clock when config_init() is called. I think you should > > > implement the enable and disable methods. > > > > That is actually incorrect. The whole "prepare" vs "enable" difference > > is that prepare can schedule, enable isn't permitted. So, if you need > > to sleep to enable the clock, then enabling the clock in the prepare > > callback is the right thing to do. > > > > However, the above driver just sets a flag, which only gets used when > > the PHY's config_init method is called; that really doesn't seem to be > > sane - the clock is available from the point that the PHY has been > > probed, and it'll be expected that once the clock is published, it can > > be made functional. > > Though I'm not sure how this fits in the whole bringup of ethernet phys. > Like the phy is dependent on the underlying ethernet controller to > actually turn it on. > > I guess we should check the phy-state and if it's not accessible, just > keep the values and if it's in a suitable state do the configuration. > > Calling a vsc8531_config_clkout() from both the vsc8531_config_init() > as well as the clk_(un-)prepare and clk_set_rate functions and being > protected by a check against phy_is_started() ? It sounds like it doesn't actually fit the clk API paradym then. I see that Rob suggested it, and from the DT point of view, it makes complete sense, but then if the hardware can't actually be used in the way the clk API expects it to be used, then there's a semantic problem. What is this clock used for? -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last! ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 15:47 ` Russell King - ARM Linux admin @ 2020-06-18 16:01 ` Heiko Stübner 2020-06-18 16:40 ` Russell King - ARM Linux admin 0 siblings, 1 reply; 15+ messages in thread From: Heiko Stübner @ 2020-06-18 16:01 UTC (permalink / raw) To: Russell King - ARM Linux admin Cc: Andrew Lunn, davem, kuba, robh+dt, f.fainelli, hkallweit1, netdev, devicetree, linux-kernel, christoph.muellner Am Donnerstag, 18. Juni 2020, 17:47:48 CEST schrieb Russell King - ARM Linux admin: > On Thu, Jun 18, 2020 at 05:41:54PM +0200, Heiko Stübner wrote: > > Am Donnerstag, 18. Juni 2020, 15:41:02 CEST schrieb Russell King - ARM Linux admin: > > > On Thu, Jun 18, 2020 at 03:28:22PM +0200, Andrew Lunn wrote: > > > > On Thu, Jun 18, 2020 at 02:11:39PM +0200, Heiko Stuebner wrote: > > > > > From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > > > > > > > > > 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 <heiko.stuebner@theobroma-systems.com> > > > > > --- > > > > > 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 <linux/clk-provider.h> > > > > > #include <linux/firmware.h> > > > > > #include <linux/jiffies.h> > > > > > #include <linux/kernel.h> > > > > > @@ -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 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 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, > > > > > > > > I'm not sure this is the expected behaviour. The clk itself should > > > > only start ticking when the enable callback is called. But this code > > > > will enable the clock when config_init() is called. I think you should > > > > implement the enable and disable methods. > > > > > > That is actually incorrect. The whole "prepare" vs "enable" difference > > > is that prepare can schedule, enable isn't permitted. So, if you need > > > to sleep to enable the clock, then enabling the clock in the prepare > > > callback is the right thing to do. > > > > > > However, the above driver just sets a flag, which only gets used when > > > the PHY's config_init method is called; that really doesn't seem to be > > > sane - the clock is available from the point that the PHY has been > > > probed, and it'll be expected that once the clock is published, it can > > > be made functional. > > > > Though I'm not sure how this fits in the whole bringup of ethernet phys. > > Like the phy is dependent on the underlying ethernet controller to > > actually turn it on. > > > > I guess we should check the phy-state and if it's not accessible, just > > keep the values and if it's in a suitable state do the configuration. > > > > Calling a vsc8531_config_clkout() from both the vsc8531_config_init() > > as well as the clk_(un-)prepare and clk_set_rate functions and being > > protected by a check against phy_is_started() ? > > It sounds like it doesn't actually fit the clk API paradym then. I > see that Rob suggested it, and from the DT point of view, it makes > complete sense, but then if the hardware can't actually be used in > the way the clk API expects it to be used, then there's a semantic > problem. > > What is this clock used for? It provides a source for the mac-clk for the actual transfers, here to provide the 125MHz clock needed for the RGMII interface . So right now the old rk3368-lion devicetree just declares a stub fixed-clock and instructs the soc's clock controller to use it [0] . And in the cover-letter here, I show the update variant with using the clock defined here. I've added the idea from my previous mail like shown below [1]. which would take into account the phy-state. But I guess I'll wait for more input before spamming people with v6. Thanks Heiko [0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi#n150 [1] @@ -1508,6 +1508,157 @@ static int vsc85xx_config_init(struct phy_device *phydev) return 0; } +#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 int vsc8531_config_clkout(struct phy_device *phydev) +{ + struct vsc8531_private *vsc8531 = phydev->priv; + u16 val; + + /* when called from clk functions, make sure phy is running */ + if (phy_is_started(phydev)) + return 0; + + 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; + + return phy_write_paged(phydev, MSCC_PHY_PAGE_EXTENDED_GPIO, + MSCC_CLKOUT_CNTL, val); +} + +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); + struct phy_device *phydev = vsc8531->phydev; + + vsc8531->clkout_rate = rate; + return vsc8531_config_clkout(phydev); +} + +static int vsc8531_clkout_prepare(struct clk_hw *hw) +{ + struct vsc8531_private *vsc8531 = clkout_hw_to_vsc8531(hw); + struct phy_device *phydev = vsc8531->phydev; + + vsc8531->clkout_enabled = true; + return vsc8531_config_clkout(phydev); +} + +static void vsc8531_clkout_unprepare(struct clk_hw *hw) +{ + struct vsc8531_private *vsc8531 = clkout_hw_to_vsc8531(hw); + struct phy_device *phydev = vsc8531->phydev; + + vsc8531->clkout_enabled = false; + vsc8531_config_clkout(phydev); +} + +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; +} + +static int vsc8531_config_clkout(struct phy_device *phydev) +{ + return 0; +} +#endif + +static int vsc8531_config_init(struct phy_device *phydev) +{ + int rc; + + rc = vsc85xx_config_init(phydev); + if (rc) + return rc; + + return vsc8531_config_clkout(phydev); +} + ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 16:01 ` Heiko Stübner @ 2020-06-18 16:40 ` Russell King - ARM Linux admin 2020-06-22 9:19 ` Heiko Stübner 0 siblings, 1 reply; 15+ messages in thread From: Russell King - ARM Linux admin @ 2020-06-18 16:40 UTC (permalink / raw) To: Heiko Stübner Cc: Andrew Lunn, davem, kuba, robh+dt, f.fainelli, hkallweit1, netdev, devicetree, linux-kernel, christoph.muellner On Thu, Jun 18, 2020 at 06:01:29PM +0200, Heiko Stübner wrote: > Am Donnerstag, 18. Juni 2020, 17:47:48 CEST schrieb Russell King - ARM Linux admin: > > On Thu, Jun 18, 2020 at 05:41:54PM +0200, Heiko Stübner wrote: > > > Though I'm not sure how this fits in the whole bringup of ethernet phys. > > > Like the phy is dependent on the underlying ethernet controller to > > > actually turn it on. > > > > > > I guess we should check the phy-state and if it's not accessible, just > > > keep the values and if it's in a suitable state do the configuration. > > > > > > Calling a vsc8531_config_clkout() from both the vsc8531_config_init() > > > as well as the clk_(un-)prepare and clk_set_rate functions and being > > > protected by a check against phy_is_started() ? > > > > It sounds like it doesn't actually fit the clk API paradym then. I > > see that Rob suggested it, and from the DT point of view, it makes > > complete sense, but then if the hardware can't actually be used in > > the way the clk API expects it to be used, then there's a semantic > > problem. > > > > What is this clock used for? > > It provides a source for the mac-clk for the actual transfers, here to > provide the 125MHz clock needed for the RGMII interface . > > So right now the old rk3368-lion devicetree just declares a stub > fixed-clock and instructs the soc's clock controller to use it [0] . > And in the cover-letter here, I show the update variant with using > the clock defined here. > > > I've added the idea from my previous mail like shown below [1]. > which would take into account the phy-state. > > But I guess I'll wait for more input before spamming people with v6. Let's get a handle on exactly what this is. The RGMII bus has two clocks: RXC and TXC, which are clocked at one of 125MHz, 25MHz or 2.5MHz depending on the RGMII data rate. Some PHYs replace TXC with GTX clock, which always runs at 125MHz. These clocks are not what you're referring to. You are referring to another commonly provided clock between the MAC and the PHY, something which is not unique to your PHY. We seem to be heading down a path where different PHYs end up doing different things in DT for what is basically the same hardware setup, which really isn't good. :( We have at803x using: qca,clk-out-frequency qca,clk-out-strength qca,keep-pll-enabled which are used to control the CLK_25M output pin on the device, which may be used to provide a reference clock for the MAC side, selecting between 25M, 50M, 62.5M and 125MHz. This was introduced in November 2019, so not that long ago. Broadcom PHYs configure their 125MHz clock through the PHY device flags passed from the MAC at attach/connect time. There's the dp83867 and dp83869 configuration (I'm not sure I can make sense of it from reading the code) using ti,clk-output-sel - but it looks like it's the same kind of thing. Introduced February 2018 into one driver, and November 2019 in the other. It seems the Micrel PHYs produce a 125MHz clock irrespective of any configuration (maybe configured by firmware, or hardware strapping?) So it seems we have four ways of doing the same thing today, and now the suggestion is to implement a fifth different way. I think there needs to be some consolidation here, maybe choosing one approach and sticking with it. Hence, I disagree with Rob - we don't need a fifth approach, we need to choose one approach and decide that's our policy for this and apply it evenly across the board, rather than making up something different each time a new PHY comes along. -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last! ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 16:40 ` Russell King - ARM Linux admin @ 2020-06-22 9:19 ` Heiko Stübner 0 siblings, 0 replies; 15+ messages in thread From: Heiko Stübner @ 2020-06-22 9:19 UTC (permalink / raw) To: Russell King - ARM Linux admin, Andrew Lunn, davem Cc: kuba, robh+dt, f.fainelli, hkallweit1, netdev, devicetree, linux-kernel, christoph.muellner, Florian Fainelli Am Donnerstag, 18. Juni 2020, 18:40:15 CEST schrieb Russell King - ARM Linux admin: > On Thu, Jun 18, 2020 at 06:01:29PM +0200, Heiko Stübner wrote: > > Am Donnerstag, 18. Juni 2020, 17:47:48 CEST schrieb Russell King - ARM Linux admin: > > > On Thu, Jun 18, 2020 at 05:41:54PM +0200, Heiko Stübner wrote: > > > > Though I'm not sure how this fits in the whole bringup of ethernet phys. > > > > Like the phy is dependent on the underlying ethernet controller to > > > > actually turn it on. > > > > > > > > I guess we should check the phy-state and if it's not accessible, just > > > > keep the values and if it's in a suitable state do the configuration. > > > > > > > > Calling a vsc8531_config_clkout() from both the vsc8531_config_init() > > > > as well as the clk_(un-)prepare and clk_set_rate functions and being > > > > protected by a check against phy_is_started() ? > > > > > > It sounds like it doesn't actually fit the clk API paradym then. I > > > see that Rob suggested it, and from the DT point of view, it makes > > > complete sense, but then if the hardware can't actually be used in > > > the way the clk API expects it to be used, then there's a semantic > > > problem. > > > > > > What is this clock used for? > > > > It provides a source for the mac-clk for the actual transfers, here to > > provide the 125MHz clock needed for the RGMII interface . > > > > So right now the old rk3368-lion devicetree just declares a stub > > fixed-clock and instructs the soc's clock controller to use it [0] . > > And in the cover-letter here, I show the update variant with using > > the clock defined here. > > > > > > I've added the idea from my previous mail like shown below [1]. > > which would take into account the phy-state. > > > > But I guess I'll wait for more input before spamming people with v6. > > Let's get a handle on exactly what this is. > > The RGMII bus has two clocks: RXC and TXC, which are clocked at one > of 125MHz, 25MHz or 2.5MHz depending on the RGMII data rate. Some > PHYs replace TXC with GTX clock, which always runs at 125MHz. These > clocks are not what you're referring to. > > You are referring to another commonly provided clock between the MAC > and the PHY, something which is not unique to your PHY. > > We seem to be heading down a path where different PHYs end up doing > different things in DT for what is basically the same hardware setup, > which really isn't good. :( > > We have at803x using: > > qca,clk-out-frequency > qca,clk-out-strength > qca,keep-pll-enabled > > which are used to control the CLK_25M output pin on the device, which > may be used to provide a reference clock for the MAC side, selecting > between 25M, 50M, 62.5M and 125MHz. This was introduced in November > 2019, so not that long ago. Because it was not that old, was the reason I followed that example in my v1 :-) And Andrew then suggested to at least try to use a common property for the target frequency that other phys could migrate to. > Broadcom PHYs configure their 125MHz clock through the PHY device > flags passed from the MAC at attach/connect time. > > There's the dp83867 and dp83869 configuration (I'm not sure I can > make sense of it from reading the code) using ti,clk-output-sel - > but it looks like it's the same kind of thing. Introduced February > 2018 into one driver, and November 2019 in the other. > > It seems the Micrel PHYs produce a 125MHz clock irrespective of any > configuration (maybe configured by firmware, or hardware strapping?) > > So it seems we have four ways of doing the same thing today, and now > the suggestion is to implement a fifth different way. I think there > needs to be some consolidation here, maybe choosing one approach and > sticking with it. > > Hence, I disagree with Rob - we don't need a fifth approach, we need > to choose one approach and decide that's our policy for this and > apply it evenly across the board, rather than making up something > different each time a new PHY comes along. @Dave, @Andrew: what's you opinion here? As Russell above (and Florian in the binding patch) pointed out, integrating this into the clock-framework may prove difficult not only for consistency but also for dependency reasons. Personally I'm fine with either solution, I just want to achieve a working ethernet on my board :-D . Thanks Heiko ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 12:11 ` [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants Heiko Stuebner 2020-06-18 13:28 ` Andrew Lunn @ 2020-06-18 15:49 ` Jakub Kicinski 2020-06-19 0:50 ` kernel test robot 2 siblings, 0 replies; 15+ messages in thread From: Jakub Kicinski @ 2020-06-18 15:49 UTC (permalink / raw) To: Heiko Stuebner Cc: davem, robh+dt, andrew, f.fainelli, hkallweit1, linux, netdev, devicetree, linux-kernel, christoph.muellner, Heiko Stuebner On Thu, 18 Jun 2020 14:11:39 +0200 Heiko Stuebner wrote: > From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com> > > 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 <heiko.stuebner@theobroma-systems.com> Doesn't build with allmodconfig: ../drivers/net/phy/mscc/mscc_macsec.c:391:42: warning: cast from restricted sci_t ../drivers/net/phy/mscc/mscc_macsec.c:393:42: warning: restricted sci_t degrades to integer ../drivers/net/phy/mscc/mscc_macsec.c:400:42: warning: restricted __be16 degrades to integer ../drivers/net/phy/mscc/mscc_macsec.c:606:34: warning: cast from restricted sci_t ../drivers/net/phy/mscc/mscc_macsec.c:608:34: warning: restricted sci_t degrades to integer ../drivers/net/phy/mscc/mscc_macsec.c:391:42: warning: cast from restricted sci_t ../drivers/net/phy/mscc/mscc_macsec.c:393:42: warning: restricted sci_t degrades to integer ../drivers/net/phy/mscc/mscc_macsec.c:400:42: warning: restricted __be16 degrades to integer ../drivers/net/phy/mscc/mscc_macsec.c:606:34: warning: cast from restricted sci_t ../drivers/net/phy/mscc/mscc_macsec.c:608:34: warning: restricted sci_t degrades to integer In file included from ../drivers/net/phy/mscc/mscc_macsec.c:17: ../drivers/net/phy/mscc/mscc.h:371:16: error: field ‘clkout_hw’ has incomplete type 371 | struct clk_hw clkout_hw; | ^~~~~~~~~ make[5]: *** [drivers/net/phy/mscc/mscc_macsec.o] Error 1 make[5]: *** Waiting for unfinished jobs.... make[4]: *** [drivers/net/phy/mscc] Error 2 make[3]: *** [drivers/net/phy] Error 2 make[3]: *** Waiting for unfinished jobs.... make[2]: *** [drivers/net] Error 2 make[2]: *** Waiting for unfinished jobs.... make[1]: *** [drivers] Error 2 make: *** [__sub-make] Error 2 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants 2020-06-18 12:11 ` [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants Heiko Stuebner 2020-06-18 13:28 ` Andrew Lunn 2020-06-18 15:49 ` Jakub Kicinski @ 2020-06-19 0:50 ` kernel test robot 2 siblings, 0 replies; 15+ messages in thread From: kernel test robot @ 2020-06-19 0:50 UTC (permalink / raw) To: Heiko Stuebner, davem, kuba Cc: kbuild-all, clang-built-linux, robh+dt, andrew, f.fainelli, hkallweit1, linux, netdev, devicetree, linux-kernel [-- Attachment #1: Type: text/plain, Size: 2421 bytes --] Hi Heiko, I love your patch! Yet something to improve: [auto build test ERROR on robh/for-next] [also build test ERROR on sparc-next/master net-next/master net/master linus/master v5.8-rc1 next-20200618] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Heiko-Stuebner/add-clkout-support-to-mscc-phys/20200618-201732 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next config: x86_64-allyesconfig (attached as .config) compiler: clang version 11.0.0 (https://github.com/llvm/llvm-project 487ca07fcc75d52755c9fe2ee05bcb3b6eeeec44) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install x86_64 cross compiling tool for clang build # apt-get install binutils-x86-64-linux-gnu # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from drivers/net/phy/mscc/mscc_macsec.c:17: >> drivers/net/phy/mscc/mscc.h:371:16: error: field has incomplete type 'struct clk_hw' struct clk_hw clkout_hw; ^ drivers/net/phy/mscc/mscc.h:371:9: note: forward declaration of 'struct clk_hw' struct clk_hw clkout_hw; ^ 1 error generated. vim +371 drivers/net/phy/mscc/mscc.h 354 355 struct vsc8531_private { 356 int rate_magic; 357 u16 supp_led_modes; 358 u32 leds_mode[MAX_LEDS]; 359 u8 nleds; 360 const struct vsc85xx_hw_stat *hw_stats; 361 u64 *stats; 362 int nstats; 363 /* PHY address within the package. */ 364 u8 addr; 365 /* For multiple port PHYs; the MDIO address of the base PHY in the 366 * package. 367 */ 368 unsigned int base_addr; 369 370 #ifdef CONFIG_COMMON_CLK > 371 struct clk_hw clkout_hw; 372 #endif 373 u32 clkout_rate; 374 int clkout_enabled; 375 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 75292 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2020-06-22 9:19 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-06-18 12:11 [PATCH v5 0/3] add clkout support to mscc phys Heiko Stuebner 2020-06-18 12:11 ` [PATCH v5 1/3] net: phy: mscc: move shared probe code into a helper Heiko Stuebner 2020-06-18 12:11 ` [PATCH v5 2/3] dt-bindings: net: mscc-vsc8531: add optional clock properties Heiko Stuebner 2020-06-19 5:01 ` Florian Fainelli 2020-06-19 6:46 ` Heiko Stuebner 2020-06-18 12:11 ` [PATCH v5 3/3] net: phy: mscc: handle the clkout control on some phy variants Heiko Stuebner 2020-06-18 13:28 ` Andrew Lunn 2020-06-18 13:41 ` Russell King - ARM Linux admin 2020-06-18 15:41 ` Heiko Stübner 2020-06-18 15:47 ` Russell King - ARM Linux admin 2020-06-18 16:01 ` Heiko Stübner 2020-06-18 16:40 ` Russell King - ARM Linux admin 2020-06-22 9:19 ` Heiko Stübner 2020-06-18 15:49 ` Jakub Kicinski 2020-06-19 0:50 ` kernel test robot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).