summaryrefslogtreecommitdiff
path: root/drivers/net/phy/micrel.c
diff options
context:
space:
mode:
authorPhilippe Schenker <philippe.schenker@toradex.com>2020-03-25 18:34:24 +0100
committerPhilippe Schenker <philippe.schenker@toradex.com>2020-08-13 16:05:10 +0200
commit440b2abcf1bfc874137dc0cd60e2be66646befd4 (patch)
tree036d5158d2c78e2140a99eda47df6b15046f0a8b /drivers/net/phy/micrel.c
parentb8bb320d44bb45186475cc06d151d100f34e243b (diff)
net: phy: micrel.c: add rgmii interface delay possibility to ksz9131
The KSZ9131 provides DLL controlled delays on RXC and TXC lines. This patch makes use of those delays. The information which delays should be enabled or disabled comes from the interface names, documented in ethernet-controller.yaml: rgmii: Disable RXC and TXC delays rgmii-id: Enable RXC and TXC delays rgmii-txid: Enable only TXC delay, disable RXC delay rgmii-rxid: Enable onlx RXC delay, disable TXC delay Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com> Signed-off-by: David S. Miller <davem@davemloft.net> (cherry picked from commit bd734a742d5533fb9190ecd8cf25befc1f759a5b) Replace phy_modify_mmd with phy_read_mmd and phy_write_mmd. Related-to: ELB-2581 Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com> (cherry picked from commit 33cb0c09aeb3dff6f64075eaf16239349ff60128)
Diffstat (limited to 'drivers/net/phy/micrel.c')
-rw-r--r--drivers/net/phy/micrel.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 523c83043131..2ba914d9d68d 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -705,6 +705,70 @@ static int ksz9131_of_load_skew_values(struct phy_device *phydev,
return phy_write_mmd(phydev, 2, reg, newval);
}
+#define KSZ9131RN_MMD_COMMON_CTRL_REG 2
+#define KSZ9131RN_RXC_DLL_CTRL 76
+#define KSZ9131RN_TXC_DLL_CTRL 77
+#define KSZ9131RN_DLL_CTRL_BYPASS BIT_MASK(12)
+#define KSZ9131RN_DLL_ENABLE_DELAY 0
+#define KSZ9131RN_DLL_DISABLE_DELAY BIT(12)
+
+static int ksz9131_config_rgmii_delay(struct phy_device *phydev)
+{
+ u16 rxcdll_val, txcdll_val;
+ int new, ret;
+
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ rxcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
+ txcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ rxcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
+ txcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ rxcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
+ txcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ rxcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
+ txcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
+ break;
+ default:
+ return 0;
+ }
+
+ ret = phy_read_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ KSZ9131RN_RXC_DLL_CTRL);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~KSZ9131RN_DLL_CTRL_BYPASS) | rxcdll_val;
+
+ if (new != ret) {
+ ret = phy_write_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ KSZ9131RN_RXC_DLL_CTRL, new);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = phy_read_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ KSZ9131RN_TXC_DLL_CTRL);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~KSZ9131RN_DLL_CTRL_BYPASS) | txcdll_val;
+
+ if (new != ret) {
+ ret = phy_write_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ KSZ9131RN_TXC_DLL_CTRL, new);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int ksz9131_config_init(struct phy_device *phydev)
{
const struct device *dev = &phydev->mdio.dev;
@@ -731,6 +795,12 @@ static int ksz9131_config_init(struct phy_device *phydev)
if (!of_node)
return 0;
+ if (phy_interface_is_rgmii(phydev)) {
+ ret = ksz9131_config_rgmii_delay(phydev);
+ if (ret < 0)
+ return ret;
+ }
+
ret = ksz9131_of_load_skew_values(phydev, of_node,
MII_KSZ9031RN_CLK_PAD_SKEW, 5,
clk_skews, 2);