net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs.
authorAllan W. Nielsen <allan.nielsen@microsemi.com>
Wed, 12 Oct 2016 13:47:51 +0000 (15:47 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 14 Oct 2016 14:06:13 +0000 (10:06 -0400)
Edge-Rate cleanup include the following:
- Updated device tree bindings documentation for edge-rate
- The edge-rate is now specified as a "slowdown", meaning that it is now
  being specified as positive values instead of negative (both
  documentation and implementation wise).
- Only explicitly documented values for "vsc8531,vddmac" and
  "vsc8531,edge-slowdown" are accepted by the device driver.
- Deleted include/dt-bindings/net/mscc-phy-vsc8531.h as it was not needed.
- Read/validate devicetree settings in probe instead of init

Signed-off-by: Allan W. Nielsen <allan.nielsen@microsemi.com>
Signed-off-by: Raju Lakkaraju <raju.lakkaraju@microsemi.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
drivers/net/phy/mscc.c
include/dt-bindings/net/mscc-phy-vsc8531.h [deleted file]

index 99c7eb0a00c8f3d07542284e1df4af094d158aee..bdefefc665949225d77e4c5c22cde5dd6b678069 100644 (file)
@@ -6,22 +6,27 @@ Required properties:
                  Documentation/devicetree/bindings/net/phy.txt
 
 Optional properties:
-- vsc8531,vddmac       : The vddmac in mV.
+- vsc8531,vddmac       : The vddmac in mV. Allowed values is listed
+                         in the first row of Table 1 (below).
+                         This property is only used in combination
+                         with the 'edge-slowdown' property.
+                         Default value is 3300.
 - vsc8531,edge-slowdown        : % the edge should be slowed down relative to
-                         the fastest possible edge time. Native sign
-                         need not enter.
+                         the fastest possible edge time.
                          Edge rate sets the drive strength of the MAC
-                         interface output signals.  Changing the drive
-                         strength will affect the edge rate of the output
-                         signal.  The goal of this setting is to help
-                         reduce electrical emission (EMI) by being able
-                         to reprogram drive strength and in effect slow
-                         down the edge rate if desired.  Table 1 shows the
-                         impact to the edge rate per VDDMAC supply for each
-                         drive strength setting.
-                         Ref: Table:1 - Edge rate change below.
-
-Note: see dt-bindings/net/mscc-phy-vsc8531.h for applicable values
+                         interface output signals.  Changing the
+                         drive strength will affect the edge rate of
+                         the output signal.  The goal of this setting
+                         is to help reduce electrical emission (EMI)
+                         by being able to reprogram drive strength
+                         and in effect slow down the edge rate if
+                         desired.
+                         To adjust the edge-slowdown, the 'vddmac'
+                         must be specified. Table 1 lists the
+                         supported edge-slowdown values for a given
+                         'vddmac'.
+                         Default value is 0%.
+                         Ref: Table:1 - Edge rate change (below).
 
 Table: 1 - Edge rate change
 ----------------------------------------------------------------|
@@ -29,23 +34,23 @@ Table: 1 - Edge rate change
 |                                                              |
 | 3300 mV      2500 mV         1800 mV         1500 mV         |
 |---------------------------------------------------------------|
-| Default      Deafult         Default         Default         |
+| 0%           0%              0%              0%              |
 | (Fastest)                    (recommended)   (recommended)   |
 |---------------------------------------------------------------|
-| -2%          -3%             -5%             -6%             |
+| 2%           3%              5%              6%              |
 |---------------------------------------------------------------|
-| -4%          -6%             -9%             -14%            |
+| 4%           6%              9%              14%             |
 |---------------------------------------------------------------|
-| -7%          -10%            -16%            -21%            |
+| 7%           10%             16%             21%             |
 |(recommended) (recommended)                                   |
 |---------------------------------------------------------------|
-| -10%         -14%            -23%            -29%            |
+| 10%          14%             23%             29%             |
 |---------------------------------------------------------------|
-| -17%         -23%            -35%            -42%            |
+| 17%          23%             35%             42%             |
 |---------------------------------------------------------------|
-| -29%         -37%            -52%            -58%            |
+| 29%          37%             52%             58%             |
 |---------------------------------------------------------------|
-| -53%         -63%            -76%            -77%            |
+| 53%          63%             76%             77%             |
 | (slowest)                                                    |
 |---------------------------------------------------------------|
 
@@ -54,5 +59,5 @@ Example:
         vsc8531_0: ethernet-phy@0 {
                 compatible = "ethernet-phy-id0007.0570";
                 vsc8531,vddmac         = <3300>;
-                vsc8531,edge-slowdown  = <21>;
+                vsc8531,edge-slowdown  = <7>;
         };
index 77a6671d572e38372e3c4c1a22248e4c48099bc9..113616b92abbbdf551c1d738605210ba80bb8022 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/of.h>
-#include <dt-bindings/net/mscc-phy-vsc8531.h>
 #include <linux/netdevice.h>
 
 enum rgmii_rx_clock_delay {
@@ -69,23 +68,29 @@ enum rgmii_rx_clock_delay {
 #define PHY_ID_VSC8531                   0x00070570
 #define PHY_ID_VSC8541                   0x00070770
 
-struct edge_rate_table {
-       u16 vddmac;
-       int slowdown[MSCC_SLOWDOWN_MAX];
-};
+#define MSCC_VDDMAC_1500                 1500
+#define MSCC_VDDMAC_1800                 1800
+#define MSCC_VDDMAC_2500                 2500
+#define MSCC_VDDMAC_3300                 3300
 
-struct edge_rate_table edge_table[MSCC_VDDMAC_MAX] = {
-       {3300, { 0, -2, -4,  -7,  -10, -17, -29, -53} },
-       {2500, { 0, -3, -6,  -10, -14, -23, -37, -63} },
-       {1800, { 0, -5, -9,  -16, -23, -35, -52, -76} },
-       {1500, { 0, -6, -14, -21, -29, -42, -58, -77} },
+struct vsc8531_private {
+       int rate_magic;
 };
 
-struct vsc8531_private {
-       u8 edge_slowdown;
+#ifdef CONFIG_OF_MDIO
+struct vsc8531_edge_rate_table {
        u16 vddmac;
+       u8 slowdown[8];
 };
 
+static const struct vsc8531_edge_rate_table edge_table[] = {
+       {MSCC_VDDMAC_3300, { 0, 2,  4,  7, 10, 17, 29, 53} },
+       {MSCC_VDDMAC_2500, { 0, 3,  6, 10, 14, 23, 37, 63} },
+       {MSCC_VDDMAC_1800, { 0, 5,  9, 16, 23, 35, 52, 76} },
+       {MSCC_VDDMAC_1500, { 0, 6, 14, 21, 29, 42, 58, 77} },
+};
+#endif /* CONFIG_OF_MDIO */
+
 static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)
 {
        int rc;
@@ -205,29 +210,43 @@ out_unlock:
        mutex_unlock(&phydev->lock);
 }
 
-static u8 edge_rate_magic_get(u16 vddmac,
-                             int slowdown)
+#ifdef CONFIG_OF_MDIO
+static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
 {
-       int rc = (MSCC_SLOWDOWN_MAX - 1);
-       u8 vdd;
        u8 sd;
+       u16 vdd;
+       int rc, i, j;
+       struct device *dev = &phydev->mdio.dev;
+       struct device_node *of_node = dev->of_node;
+       u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
 
-       for (vdd = 0; vdd < MSCC_VDDMAC_MAX; vdd++) {
-               if (edge_table[vdd].vddmac == vddmac) {
-                       for (sd = 0; sd < MSCC_SLOWDOWN_MAX; sd++) {
-                               if (edge_table[vdd].slowdown[sd] <= slowdown) {
-                                       rc = (MSCC_SLOWDOWN_MAX - sd - 1);
-                                       break;
-                               }
-                       }
-               }
-       }
+       if (!of_node)
+               return -ENODEV;
 
-       return rc;
+       rc = of_property_read_u16(of_node, "vsc8531,vddmac", &vdd);
+       if (rc != 0)
+               vdd = MSCC_VDDMAC_3300;
+
+       rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown", &sd);
+       if (rc != 0)
+               sd = 0;
+
+       for (i = 0; i < ARRAY_SIZE(edge_table); i++)
+               if (edge_table[i].vddmac == vdd)
+                       for (j = 0; j < sd_array_size; j++)
+                               if (edge_table[i].slowdown[j] == sd)
+                                       return (sd_array_size - j - 1);
+
+       return -EINVAL;
+}
+#else
+static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
+{
+       return 0;
 }
+#endif /* CONFIG_OF_MDIO */
 
-static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev,
-                                     u8 edge_rate)
+static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
 {
        int rc;
        u16 reg_val;
@@ -308,45 +327,10 @@ out_unlock:
        return rc;
 }
 
-#ifdef CONFIG_OF_MDIO
-static int vsc8531_of_init(struct phy_device *phydev)
-{
-       int rc;
-       struct vsc8531_private *vsc8531 = phydev->priv;
-       struct device *dev = &phydev->mdio.dev;
-       struct device_node *of_node = dev->of_node;
-
-       if (!of_node)
-               return -ENODEV;
-
-       rc = of_property_read_u16(of_node, "vsc8531,vddmac",
-                                 &vsc8531->vddmac);
-       if (rc == -EINVAL)
-               vsc8531->vddmac = MSCC_VDDMAC_3300;
-       rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown",
-                                &vsc8531->edge_slowdown);
-       if (rc == -EINVAL)
-               vsc8531->edge_slowdown = 0;
-
-       rc = 0;
-       return rc;
-}
-#else
-static int vsc8531_of_init(struct phy_device *phydev)
-{
-       return 0;
-}
-#endif /* CONFIG_OF_MDIO */
-
 static int vsc85xx_config_init(struct phy_device *phydev)
 {
        int rc;
        struct vsc8531_private *vsc8531 = phydev->priv;
-       u8 edge_rate;
-
-       rc = vsc8531_of_init(phydev);
-       if (rc)
-               return rc;
 
        rc = vsc85xx_default_config(phydev);
        if (rc)
@@ -356,9 +340,7 @@ static int vsc85xx_config_init(struct phy_device *phydev)
        if (rc)
                return rc;
 
-       edge_rate = edge_rate_magic_get(vsc8531->vddmac,
-                                       -(int)vsc8531->edge_slowdown);
-       rc = vsc85xx_edge_rate_cntl_set(phydev, edge_rate);
+       rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
        if (rc)
                return rc;
 
@@ -396,14 +378,21 @@ static int vsc85xx_config_intr(struct phy_device *phydev)
 
 static int vsc85xx_probe(struct phy_device *phydev)
 {
+       int rate_magic;
        struct vsc8531_private *vsc8531;
 
+       rate_magic = vsc85xx_edge_rate_magic_get(phydev);
+       if (rate_magic < 0)
+               return rate_magic;
+
        vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
        if (!vsc8531)
                return -ENOMEM;
 
        phydev->priv = vsc8531;
 
+       vsc8531->rate_magic = rate_magic;
+
        return 0;
 }
 
@@ -424,9 +413,9 @@ static struct phy_driver vsc85xx_driver[] = {
        .config_intr    = &vsc85xx_config_intr,
        .suspend        = &genphy_suspend,
        .resume         = &genphy_resume,
-       .probe          = &vsc85xx_probe,
-       .set_wol        = &vsc85xx_wol_set,
-       .get_wol        = &vsc85xx_wol_get,
+       .probe          = &vsc85xx_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
 },
 {
        .phy_id         = PHY_ID_VSC8541,
@@ -443,9 +432,9 @@ static struct phy_driver vsc85xx_driver[] = {
        .config_intr    = &vsc85xx_config_intr,
        .suspend        = &genphy_suspend,
        .resume         = &genphy_resume,
-       .probe          = &vsc85xx_probe,
-       .set_wol        = &vsc85xx_wol_set,
-       .get_wol        = &vsc85xx_wol_get,
+       .probe          = &vsc85xx_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
 }
 
 };
diff --git a/include/dt-bindings/net/mscc-phy-vsc8531.h b/include/dt-bindings/net/mscc-phy-vsc8531.h
deleted file mode 100644 (file)
index 2383dd2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Device Tree constants for Microsemi VSC8531 PHY
- *
- * Author: Nagaraju Lakkaraju
- *
- * License: Dual MIT/GPL
- * Copyright (c) 2016 Microsemi Corporation
- */
-
-#ifndef _DT_BINDINGS_MSCC_VSC8531_H
-#define _DT_BINDINGS_MSCC_VSC8531_H
-
-/* MAC interface Edge rate control VDDMAC in milli Volts */
-#define MSCC_VDDMAC_3300                3300
-#define MSCC_VDDMAC_2500                2500
-#define MSCC_VDDMAC_1800                1800
-#define MSCC_VDDMAC_1500                1500
-#define MSCC_VDDMAC_MAX                         4
-#define MSCC_SLOWDOWN_MAX               8
-
-#endif