Skip to content

Commit

Permalink
Merge branch 'net-phy-dp83822-add-support-for-changing-the-transmit-a…
Browse files Browse the repository at this point in the history
…mplitude-voltage'

Dimitri Fedrau via says:

====================
net: phy: dp83822: Add support for changing the transmit amplitude voltage

Add support for changing the transmit amplitude voltage in 100BASE-TX mode.
Add support for configuration via DT.

v4: https://lore.kernel.org/20250211-dp83822-tx-swing-v4-0-1e8ebd71ad54@liebherr.com
v3: https://lore.kernel.org/20250204-dp83822-tx-swing-v3-0-9798e96500d9@liebherr.com
v2: https://lore.kernel.org/20250120-dp83822-tx-swing-v2-0-07c99dc42627@liebherr.com
v1: https://lore.kernel.org/20250113-dp83822-tx-swing-v1-0-7ed5a9d80010@liebherr.com
====================

Link: https://patch.msgid.link/20250214-dp83822-tx-swing-v5-0-02ca72620599@liebherr.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Feb 18, 2025
2 parents dbcbec8 + 4f3735e commit b706d9f
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 18 deletions.
6 changes: 6 additions & 0 deletions Documentation/devicetree/bindings/net/ethernet-phy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ properties:
PHY's that have configurable TX internal delays. If this property is
present then the PHY applies the TX delay.
tx-amplitude-100base-tx-percent:
description:
Transmit amplitude gain applied for 100BASE-TX. 100% matches 2V
peak-to-peak specified in ANSI X3.263. When omitted, the PHYs default
will be left as is.

leds:
type: object

Expand Down
38 changes: 38 additions & 0 deletions drivers/net/phy/dp83822.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#define MII_DP83822_RCSR 0x17
#define MII_DP83822_RESET_CTRL 0x1f
#define MII_DP83822_MLEDCR 0x25
#define MII_DP83822_LDCTRL 0x403
#define MII_DP83822_LEDCFG1 0x460
#define MII_DP83822_IOCTRL1 0x462
#define MII_DP83822_IOCTRL2 0x463
Expand Down Expand Up @@ -123,6 +124,9 @@
#define DP83822_IOCTRL1_GPIO1_CTRL GENMASK(2, 0)
#define DP83822_IOCTRL1_GPIO1_CTRL_LED_1 BIT(0)

/* LDCTRL bits */
#define DP83822_100BASE_TX_LINE_DRIVER_SWING GENMASK(7, 4)

/* IOCTRL2 bits */
#define DP83822_IOCTRL2_GPIO2_CLK_SRC GENMASK(6, 4)
#define DP83822_IOCTRL2_GPIO2_CTRL GENMASK(2, 0)
Expand Down Expand Up @@ -197,6 +201,7 @@ struct dp83822_private {
bool set_gpio2_clk_out;
u32 gpio2_clk_out;
bool led_pin_enable[DP83822_MAX_LED_PINS];
int tx_amplitude_100base_tx_index;
};

static int dp83822_config_wol(struct phy_device *phydev,
Expand Down Expand Up @@ -522,6 +527,12 @@ static int dp83822_config_init(struct phy_device *phydev)
FIELD_PREP(DP83822_IOCTRL2_GPIO2_CLK_SRC,
dp83822->gpio2_clk_out));

if (dp83822->tx_amplitude_100base_tx_index >= 0)
phy_modify_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_LDCTRL,
DP83822_100BASE_TX_LINE_DRIVER_SWING,
FIELD_PREP(DP83822_100BASE_TX_LINE_DRIVER_SWING,
dp83822->tx_amplitude_100base_tx_index));

err = dp83822_config_init_leds(phydev);
if (err)
return err;
Expand Down Expand Up @@ -720,6 +731,11 @@ static int dp83822_phy_reset(struct phy_device *phydev)
}

#ifdef CONFIG_OF_MDIO
static const u32 tx_amplitude_100base_tx_gain[] = {
80, 82, 83, 85, 87, 88, 90, 92,
93, 95, 97, 98, 100, 102, 103, 105,
};

static int dp83822_of_init_leds(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
Expand Down Expand Up @@ -780,6 +796,8 @@ static int dp83822_of_init(struct phy_device *phydev)
struct dp83822_private *dp83822 = phydev->priv;
struct device *dev = &phydev->mdio.dev;
const char *of_val;
int i, ret;
u32 val;

/* Signal detection for the PHY is only enabled if the FX_EN and the
* SD_EN pins are strapped. Signal detection can only enabled if FX_EN
Expand Down Expand Up @@ -815,6 +833,26 @@ static int dp83822_of_init(struct phy_device *phydev)
dp83822->set_gpio2_clk_out = true;
}

dp83822->tx_amplitude_100base_tx_index = -1;
ret = phy_get_tx_amplitude_gain(phydev, dev,
ETHTOOL_LINK_MODE_100baseT_Full_BIT,
&val);
if (!ret) {
for (i = 0; i < ARRAY_SIZE(tx_amplitude_100base_tx_gain); i++) {
if (tx_amplitude_100base_tx_gain[i] == val) {
dp83822->tx_amplitude_100base_tx_index = i;
break;
}
}

if (dp83822->tx_amplitude_100base_tx_index < 0) {
phydev_err(phydev,
"Invalid value for tx-amplitude-100base-tx-percent property (%u)\n",
val);
return -EINVAL;
}
}

return dp83822_of_init_leds(phydev);
}

Expand Down
53 changes: 35 additions & 18 deletions drivers/net/phy/phy_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -3096,19 +3096,12 @@ void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause)
EXPORT_SYMBOL(phy_get_pause);

#if IS_ENABLED(CONFIG_OF_MDIO)
static int phy_get_int_delay_property(struct device *dev, const char *name)
static int phy_get_u32_property(struct device *dev, const char *name, u32 *val)
{
s32 int_delay;
int ret;

ret = device_property_read_u32(dev, name, &int_delay);
if (ret)
return ret;

return int_delay;
return device_property_read_u32(dev, name, val);
}
#else
static int phy_get_int_delay_property(struct device *dev, const char *name)
static int phy_get_u32_property(struct device *dev, const char *name, u32 *val)
{
return -EINVAL;
}
Expand All @@ -3133,12 +3126,12 @@ static int phy_get_int_delay_property(struct device *dev, const char *name)
s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
const int *delay_values, int size, bool is_rx)
{
s32 delay;
int i;
int i, ret;
u32 delay;

if (is_rx) {
delay = phy_get_int_delay_property(dev, "rx-internal-delay-ps");
if (delay < 0 && size == 0) {
ret = phy_get_u32_property(dev, "rx-internal-delay-ps", &delay);
if (ret < 0 && size == 0) {
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
return 1;
Expand All @@ -3147,8 +3140,8 @@ s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
}

} else {
delay = phy_get_int_delay_property(dev, "tx-internal-delay-ps");
if (delay < 0 && size == 0) {
ret = phy_get_u32_property(dev, "tx-internal-delay-ps", &delay);
if (ret < 0 && size == 0) {
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
return 1;
Expand All @@ -3157,8 +3150,8 @@ s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
}
}

if (delay < 0)
return delay;
if (ret < 0)
return ret;

if (size == 0)
return delay;
Expand Down Expand Up @@ -3193,6 +3186,30 @@ s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
}
EXPORT_SYMBOL(phy_get_internal_delay);

/**
* phy_get_tx_amplitude_gain - stores tx amplitude gain in @val
* @phydev: phy_device struct
* @dev: pointer to the devices device struct
* @linkmode: linkmode for which the tx amplitude gain should be retrieved
* @val: tx amplitude gain
*
* Returns: 0 on success, < 0 on failure
*/
int phy_get_tx_amplitude_gain(struct phy_device *phydev, struct device *dev,
enum ethtool_link_mode_bit_indices linkmode,
u32 *val)
{
switch (linkmode) {
case ETHTOOL_LINK_MODE_100baseT_Full_BIT:
return phy_get_u32_property(dev,
"tx-amplitude-100base-tx-percent",
val);
default:
return -EINVAL;
}
}
EXPORT_SYMBOL_GPL(phy_get_tx_amplitude_gain);

static int phy_led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness value)
{
Expand Down
4 changes: 4 additions & 0 deletions include/linux/phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -2097,6 +2097,10 @@ void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause);
s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
const int *delay_values, int size, bool is_rx);

int phy_get_tx_amplitude_gain(struct phy_device *phydev, struct device *dev,
enum ethtool_link_mode_bit_indices linkmode,
u32 *val);

void phy_resolve_pause(unsigned long *local_adv, unsigned long *partner_adv,
bool *tx_pause, bool *rx_pause);

Expand Down

0 comments on commit b706d9f

Please sign in to comment.