Commit 13c83cf8 authored by Trent Piepho's avatar Trent Piepho Committed by David S. Miller
Browse files

net: phy: dp83867: Add ability to disable output clock



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@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: default avatarTrent Piepho <tpiepho@impinj.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 980066e6
Loading
Loading
Loading
Loading
+28 −9
Original line number Diff line number Diff line
@@ -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;
}