Commit 4f58e6dc authored by Allan W. Nielsen's avatar Allan W. Nielsen Committed by David S. Miller

net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs.

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: default avatarAllan W. Nielsen <allan.nielsen@microsemi.com>
Signed-off-by: default avatarRaju Lakkaraju <raju.lakkaraju@microsemi.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cf53b1da
...@@ -6,22 +6,27 @@ Required properties: ...@@ -6,22 +6,27 @@ Required properties:
Documentation/devicetree/bindings/net/phy.txt Documentation/devicetree/bindings/net/phy.txt
Optional properties: 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 - vsc8531,edge-slowdown : % the edge should be slowed down relative to
the fastest possible edge time. Native sign the fastest possible edge time.
need not enter.
Edge rate sets the drive strength of the MAC Edge rate sets the drive strength of the MAC
interface output signals. Changing the drive interface output signals. Changing the
strength will affect the edge rate of the output drive strength will affect the edge rate of
signal. The goal of this setting is to help the output signal. The goal of this setting
reduce electrical emission (EMI) by being able is to help reduce electrical emission (EMI)
to reprogram drive strength and in effect slow by being able to reprogram drive strength
down the edge rate if desired. Table 1 shows the and in effect slow down the edge rate if
impact to the edge rate per VDDMAC supply for each desired.
drive strength setting. To adjust the edge-slowdown, the 'vddmac'
Ref: Table:1 - Edge rate change below. must be specified. Table 1 lists the
supported edge-slowdown values for a given
Note: see dt-bindings/net/mscc-phy-vsc8531.h for applicable values 'vddmac'.
Default value is 0%.
Ref: Table:1 - Edge rate change (below).
Table: 1 - Edge rate change Table: 1 - Edge rate change
----------------------------------------------------------------| ----------------------------------------------------------------|
...@@ -29,23 +34,23 @@ Table: 1 - Edge rate change ...@@ -29,23 +34,23 @@ Table: 1 - Edge rate change
| | | |
| 3300 mV 2500 mV 1800 mV 1500 mV | | 3300 mV 2500 mV 1800 mV 1500 mV |
|---------------------------------------------------------------| |---------------------------------------------------------------|
| Default Deafult Default Default | | 0% 0% 0% 0% |
| (Fastest) (recommended) (recommended) | | (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) | |(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) | | (slowest) |
|---------------------------------------------------------------| |---------------------------------------------------------------|
...@@ -54,5 +59,5 @@ Example: ...@@ -54,5 +59,5 @@ Example:
vsc8531_0: ethernet-phy@0 { vsc8531_0: ethernet-phy@0 {
compatible = "ethernet-phy-id0007.0570"; compatible = "ethernet-phy-id0007.0570";
vsc8531,vddmac = <3300>; vsc8531,vddmac = <3300>;
vsc8531,edge-slowdown = <21>; vsc8531,edge-slowdown = <7>;
}; };
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/mii.h> #include <linux/mii.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/of.h> #include <linux/of.h>
#include <dt-bindings/net/mscc-phy-vsc8531.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
enum rgmii_rx_clock_delay { enum rgmii_rx_clock_delay {
...@@ -69,22 +68,28 @@ enum rgmii_rx_clock_delay { ...@@ -69,22 +68,28 @@ enum rgmii_rx_clock_delay {
#define PHY_ID_VSC8531 0x00070570 #define PHY_ID_VSC8531 0x00070570
#define PHY_ID_VSC8541 0x00070770 #define PHY_ID_VSC8541 0x00070770
struct edge_rate_table { #define MSCC_VDDMAC_1500 1500
u16 vddmac; #define MSCC_VDDMAC_1800 1800
int slowdown[MSCC_SLOWDOWN_MAX]; #define MSCC_VDDMAC_2500 2500
}; #define MSCC_VDDMAC_3300 3300
struct edge_rate_table edge_table[MSCC_VDDMAC_MAX] = { struct vsc8531_private {
{3300, { 0, -2, -4, -7, -10, -17, -29, -53} }, int rate_magic;
{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 { #ifdef CONFIG_OF_MDIO
u8 edge_slowdown; struct vsc8531_edge_rate_table {
u16 vddmac; 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) static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)
{ {
...@@ -205,29 +210,43 @@ static void vsc85xx_wol_get(struct phy_device *phydev, ...@@ -205,29 +210,43 @@ static void vsc85xx_wol_get(struct phy_device *phydev,
mutex_unlock(&phydev->lock); mutex_unlock(&phydev->lock);
} }
static u8 edge_rate_magic_get(u16 vddmac, #ifdef CONFIG_OF_MDIO
int slowdown) static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
{ {
int rc = (MSCC_SLOWDOWN_MAX - 1);
u8 vdd;
u8 sd; 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 (!of_node)
if (edge_table[vdd].vddmac == vddmac) { return -ENODEV;
for (sd = 0; sd < MSCC_SLOWDOWN_MAX; sd++) {
if (edge_table[vdd].slowdown[sd] <= slowdown) {
rc = (MSCC_SLOWDOWN_MAX - sd - 1);
break;
}
}
}
}
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, static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
u8 edge_rate)
{ {
int rc; int rc;
u16 reg_val; u16 reg_val;
...@@ -308,45 +327,10 @@ static int vsc85xx_default_config(struct phy_device *phydev) ...@@ -308,45 +327,10 @@ static int vsc85xx_default_config(struct phy_device *phydev)
return rc; 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) static int vsc85xx_config_init(struct phy_device *phydev)
{ {
int rc; int rc;
struct vsc8531_private *vsc8531 = phydev->priv; struct vsc8531_private *vsc8531 = phydev->priv;
u8 edge_rate;
rc = vsc8531_of_init(phydev);
if (rc)
return rc;
rc = vsc85xx_default_config(phydev); rc = vsc85xx_default_config(phydev);
if (rc) if (rc)
...@@ -356,9 +340,7 @@ static int vsc85xx_config_init(struct phy_device *phydev) ...@@ -356,9 +340,7 @@ static int vsc85xx_config_init(struct phy_device *phydev)
if (rc) if (rc)
return rc; return rc;
edge_rate = edge_rate_magic_get(vsc8531->vddmac, rc = vsc85xx_edge_rate_cntl_set(phydev, vsc8531->rate_magic);
-(int)vsc8531->edge_slowdown);
rc = vsc85xx_edge_rate_cntl_set(phydev, edge_rate);
if (rc) if (rc)
return rc; return rc;
...@@ -396,14 +378,21 @@ static int vsc85xx_config_intr(struct phy_device *phydev) ...@@ -396,14 +378,21 @@ static int vsc85xx_config_intr(struct phy_device *phydev)
static int vsc85xx_probe(struct phy_device *phydev) static int vsc85xx_probe(struct phy_device *phydev)
{ {
int rate_magic;
struct vsc8531_private *vsc8531; 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); vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
if (!vsc8531) if (!vsc8531)
return -ENOMEM; return -ENOMEM;
phydev->priv = vsc8531; phydev->priv = vsc8531;
vsc8531->rate_magic = rate_magic;
return 0; return 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment