]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: mdio-mux-meson-g12a: force internal PHY off on mux switch
authorJerome Brunet <jbrunet@baylibre.com>
Tue, 24 Jan 2023 10:11:57 +0000 (11:11 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Feb 2023 06:52:47 +0000 (07:52 +0100)
[ Upstream commit 7083df59abbc2b7500db312cac706493be0273ff ]

Force the internal PHY off then on when switching to the internal path.
This fixes problems where the PHY ID is not properly set.

Fixes: f503f381995e ("net: phy: add amlogic g12a mdio mux support")
Suggested-by: Qi Duan <qi.duan@amlogic.com>
Co-developed-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Link: https://lore.kernel.org/r/20230124101157.232234-1-jbrunet@baylibre.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/phy/mdio-mux-meson-g12a.c

index 7a9ad54582e191517a04f82c3ae8a477471f771c..aa3ad38e37d7b15c804d79881887211f8a878c11 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
@@ -148,6 +149,7 @@ static const struct clk_ops g12a_ephy_pll_ops = {
 
 static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv)
 {
+       u32 value;
        int ret;
 
        /* Enable the phy clock */
@@ -161,18 +163,25 @@ static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv)
 
        /* Initialize ephy control */
        writel(EPHY_G12A_ID, priv->regs + ETH_PHY_CNTL0);
-       writel(FIELD_PREP(PHY_CNTL1_ST_MODE, 3) |
-              FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) |
-              FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) |
-              PHY_CNTL1_CLK_EN |
-              PHY_CNTL1_CLKFREQ |
-              PHY_CNTL1_PHY_ENB,
-              priv->regs + ETH_PHY_CNTL1);
+
+       /* Make sure we get a 0 -> 1 transition on the enable bit */
+       value = FIELD_PREP(PHY_CNTL1_ST_MODE, 3) |
+               FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) |
+               FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) |
+               PHY_CNTL1_CLK_EN |
+               PHY_CNTL1_CLKFREQ;
+       writel(value, priv->regs + ETH_PHY_CNTL1);
        writel(PHY_CNTL2_USE_INTERNAL |
               PHY_CNTL2_SMI_SRC_MAC |
               PHY_CNTL2_RX_CLK_EPHY,
               priv->regs + ETH_PHY_CNTL2);
 
+       value |= PHY_CNTL1_PHY_ENB;
+       writel(value, priv->regs + ETH_PHY_CNTL1);
+
+       /* The phy needs a bit of time to power up */
+       mdelay(10);
+
        return 0;
 }