mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 23:23:03 +00:00
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: 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>
This commit is contained in:
parent
cf53b1da73
commit
4f58e6dceb
@ -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>;
|
||||
};
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
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} },
|
||||
};
|
||||
#define MSCC_VDDMAC_1500 1500
|
||||
#define MSCC_VDDMAC_1800 1800
|
||||
#define MSCC_VDDMAC_2500 2500
|
||||
#define MSCC_VDDMAC_3300 3300
|
||||
|
||||
struct vsc8531_private {
|
||||
u8 edge_slowdown;
|
||||
u16 vddmac;
|
||||
int rate_magic;
|
||||
};
|
||||
|
||||
#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,
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user