aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorGrygorii Strashko <grygorii.strashko@ti.com>2019-11-18 23:04:43 +0200
committerJoe Hershberger <joe.hershberger@ni.com>2019-12-09 09:47:42 -0600
commitb3b9b128d5432f7b17ed4afeffa1dad04eefec0a (patch)
tree3315b9fdca13228a9739ff45457837e33bd08003 /drivers
parentfb6038390ebe8717a66dd3a4e37bffb96e50c07a (diff)
downloadu-boot-b3b9b128d5432f7b17ed4afeffa1dad04eefec0a.zip
u-boot-b3b9b128d5432f7b17ed4afeffa1dad04eefec0a.tar.gz
u-boot-b3b9b128d5432f7b17ed4afeffa1dad04eefec0a.tar.bz2
net: phy: dp83867: Add ability to disable output clock
Based on commit 13c83cf8af0d ("net: phy: dp83867: Add ability to disable output clock") of mainline linux kernel. 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. Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/dp83867.c53
1 files changed, 36 insertions, 17 deletions
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 8dc2163..cd3c1c5 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;