diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/phy/dp83867.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 8dc21633424..cd3c1c596ae 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -83,6 +83,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_SHIFT 8 #define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK \ GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT) @@ -103,6 +104,7 @@ struct dp83867_private { int io_impedance; bool rxctrl_strap_quirk; int port_mirroring; + bool set_clk_output; unsigned int clk_output_sel; }; @@ -134,16 +136,28 @@ static int dp83867_of_init(struct phy_device *phydev) { struct dp83867_private *dp83867 = phydev->priv; ofnode node; - u16 val; + int ret; node = phy_get_ofnode(phydev); if (!ofnode_valid(node)) return -EINVAL; - /* Keep the default value if ti,clk-output-sel is not set */ - dp83867->clk_output_sel = - ofnode_read_u32_default(node, "ti,clk-output-sel", - DP83867_CLK_O_SEL_REF_CLK); + /* Optional configuration */ + ret = ofnode_read_u32(node, "ti,clk-output-sel", + &dp83867->clk_output_sel); + /* 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. + */ + if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK && + dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) { + pr_debug("ti,clk-output-sel value %u out of range\n", + dp83867->clk_output_sel); + return -EINVAL; + } + } if (ofnode_read_bool(node, "ti,max-output-impedance")) dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX; @@ -170,18 +184,6 @@ static int dp83867_of_init(struct phy_device *phydev) if (ofnode_read_bool(node, "enet-phy-lane-no-swap")) dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS; - - /* Clock output selection if muxing property is set */ - if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) { - val = phy_read_mmd(phydev, DP83867_DEVADDR, - DP83867_IO_MUX_CFG); - val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; - val |= (dp83867->clk_output_sel << - DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT); - phy_write_mmd(phydev, DP83867_DEVADDR, - DP83867_IO_MUX_CFG, val); - } - return 0; } #else @@ -313,6 +315,23 @@ static int dp83867_config(struct phy_device *phydev) if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP) dp83867_config_port_mirroring(phydev); + /* Clock output selection if muxing property is set */ + if (dp83867->set_clk_output) { + val = phy_read_mmd(phydev, DP83867_DEVADDR, + DP83867_IO_MUX_CFG); + + if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) { + val |= DP83867_IO_MUX_CFG_CLK_O_DISABLE; + } else { + val &= ~(DP83867_IO_MUX_CFG_CLK_O_SEL_MASK | + DP83867_IO_MUX_CFG_CLK_O_DISABLE); + val |= dp83867->clk_output_sel << + DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT; + } + phy_write_mmd(phydev, DP83867_DEVADDR, + DP83867_IO_MUX_CFG, val); + } + genphy_config_aneg(phydev); return 0; |