Generally, the output clock pin is only used for testing and only serves as a source of RF noise after this. It could be used to daisy-chain PHYs, but this is uncommon. Since the PHY can disable the output, make doing so an option. I do this by adding another enumeration to the allowed values of ti,clk-output-sel. The code was not using the value DP83867_CLK_O_SEL_REF_CLK as one might expect: to select the REF_CLK as the output. Rather it meant "keep clock output setting as is", which, depending on PHY strapping, might not be outputting REF_CLK. Change this so DP83867_CLK_O_SEL_REF_CLK means enable REF_CLK output. Omitting the property will leave the setting as is (which was the previous behavior in this case). Out of range values were silently converted into DP83867_CLK_O_SEL_REF_CLK. Change this so they generate an error. Cc: Andrew Lunn <andrew@xxxxxxx> Cc: Florian Fainelli <f.fainelli@xxxxxxxxx> Cc: Heiner Kallweit <hkallweit1@xxxxxxxxx> Signed-off-by: Trent Piepho <tpiepho@xxxxxxxxxx> --- drivers/net/phy/dp83867.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index fd35131a0c39..54fbc833bf5d 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -68,6 +68,7 @@ #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f +#define DP83867_IO_MUX_CFG_CLK_O_DISABLE BIT(6) #define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK (0x1f << 8) #define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8 @@ -87,7 +88,8 @@ struct dp83867_private { int io_impedance; int port_mirroring; bool rxctrl_strap_quirk; - int clk_output_sel; + bool set_clk_output; + u32 clk_output_sel; }; static int dp83867_ack_interrupt(struct phy_device *phydev) @@ -154,11 +156,19 @@ static int dp83867_of_init(struct phy_device *phydev) /* Optional configuration */ ret = of_property_read_u32(of_node, "ti,clk-output-sel", &dp83867->clk_output_sel); - if (ret || dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK) - /* Keep the default value if ti,clk-output-sel is not set - * or too high + /* If not set, keep default */ + if (!ret) { + dp83867->set_clk_output = true; + /* Valid values are 0 to DP83867_CLK_O_SEL_REF_CLK or + * DP83867_CLK_O_SEL_OFF. */ - dp83867->clk_output_sel = DP83867_CLK_O_SEL_REF_CLK; + if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK && + dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) { + phydev_err(phydev, "ti,clk-output-sel value %u out of range\n", + dp83867->clk_output_sel); + return -EINVAL; + } + } if (of_property_read_bool(of_node, "ti,max-output-impedance")) dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; @@ -288,11 +298,20 @@ static int dp83867_config_init(struct phy_device *phydev) dp83867_config_port_mirroring(phydev); /* Clock output selection if muxing property is set */ - if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) + if (dp83867->set_clk_output) { + u16 mask = DP83867_IO_MUX_CFG_CLK_O_DISABLE; + + if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) { + val = DP83867_IO_MUX_CFG_CLK_O_DISABLE; + } else { + mask |= DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; + val = dp83867->clk_output_sel << + DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT; + } + phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG, - DP83867_IO_MUX_CFG_CLK_O_SEL_MASK, - dp83867->clk_output_sel << - DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT); + mask, val); + } return 0; } -- 2.14.5