Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'net-phy-dp83822-add-support-for-changing-the-transmit-amplitude-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>

+83 -18
+6
Documentation/devicetree/bindings/net/ethernet-phy.yaml
··· 232 232 PHY's that have configurable TX internal delays. If this property is 233 233 present then the PHY applies the TX delay. 234 234 235 + tx-amplitude-100base-tx-percent: 236 + description: 237 + Transmit amplitude gain applied for 100BASE-TX. 100% matches 2V 238 + peak-to-peak specified in ANSI X3.263. When omitted, the PHYs default 239 + will be left as is. 240 + 235 241 leds: 236 242 type: object 237 243
+38
drivers/net/phy/dp83822.c
··· 31 31 #define MII_DP83822_RCSR 0x17 32 32 #define MII_DP83822_RESET_CTRL 0x1f 33 33 #define MII_DP83822_MLEDCR 0x25 34 + #define MII_DP83822_LDCTRL 0x403 34 35 #define MII_DP83822_LEDCFG1 0x460 35 36 #define MII_DP83822_IOCTRL1 0x462 36 37 #define MII_DP83822_IOCTRL2 0x463 ··· 124 123 #define DP83822_IOCTRL1_GPIO1_CTRL GENMASK(2, 0) 125 124 #define DP83822_IOCTRL1_GPIO1_CTRL_LED_1 BIT(0) 126 125 126 + /* LDCTRL bits */ 127 + #define DP83822_100BASE_TX_LINE_DRIVER_SWING GENMASK(7, 4) 128 + 127 129 /* IOCTRL2 bits */ 128 130 #define DP83822_IOCTRL2_GPIO2_CLK_SRC GENMASK(6, 4) 129 131 #define DP83822_IOCTRL2_GPIO2_CTRL GENMASK(2, 0) ··· 201 197 bool set_gpio2_clk_out; 202 198 u32 gpio2_clk_out; 203 199 bool led_pin_enable[DP83822_MAX_LED_PINS]; 200 + int tx_amplitude_100base_tx_index; 204 201 }; 205 202 206 203 static int dp83822_config_wol(struct phy_device *phydev, ··· 527 522 FIELD_PREP(DP83822_IOCTRL2_GPIO2_CLK_SRC, 528 523 dp83822->gpio2_clk_out)); 529 524 525 + if (dp83822->tx_amplitude_100base_tx_index >= 0) 526 + phy_modify_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_LDCTRL, 527 + DP83822_100BASE_TX_LINE_DRIVER_SWING, 528 + FIELD_PREP(DP83822_100BASE_TX_LINE_DRIVER_SWING, 529 + dp83822->tx_amplitude_100base_tx_index)); 530 + 530 531 err = dp83822_config_init_leds(phydev); 531 532 if (err) 532 533 return err; ··· 731 720 } 732 721 733 722 #ifdef CONFIG_OF_MDIO 723 + static const u32 tx_amplitude_100base_tx_gain[] = { 724 + 80, 82, 83, 85, 87, 88, 90, 92, 725 + 93, 95, 97, 98, 100, 102, 103, 105, 726 + }; 727 + 734 728 static int dp83822_of_init_leds(struct phy_device *phydev) 735 729 { 736 730 struct device_node *node = phydev->mdio.dev.of_node; ··· 796 780 struct dp83822_private *dp83822 = phydev->priv; 797 781 struct device *dev = &phydev->mdio.dev; 798 782 const char *of_val; 783 + int i, ret; 784 + u32 val; 799 785 800 786 /* Signal detection for the PHY is only enabled if the FX_EN and the 801 787 * SD_EN pins are strapped. Signal detection can only enabled if FX_EN ··· 831 813 } 832 814 833 815 dp83822->set_gpio2_clk_out = true; 816 + } 817 + 818 + dp83822->tx_amplitude_100base_tx_index = -1; 819 + ret = phy_get_tx_amplitude_gain(phydev, dev, 820 + ETHTOOL_LINK_MODE_100baseT_Full_BIT, 821 + &val); 822 + if (!ret) { 823 + for (i = 0; i < ARRAY_SIZE(tx_amplitude_100base_tx_gain); i++) { 824 + if (tx_amplitude_100base_tx_gain[i] == val) { 825 + dp83822->tx_amplitude_100base_tx_index = i; 826 + break; 827 + } 828 + } 829 + 830 + if (dp83822->tx_amplitude_100base_tx_index < 0) { 831 + phydev_err(phydev, 832 + "Invalid value for tx-amplitude-100base-tx-percent property (%u)\n", 833 + val); 834 + return -EINVAL; 835 + } 834 836 } 835 837 836 838 return dp83822_of_init_leds(phydev);
+35 -18
drivers/net/phy/phy_device.c
··· 3096 3096 EXPORT_SYMBOL(phy_get_pause); 3097 3097 3098 3098 #if IS_ENABLED(CONFIG_OF_MDIO) 3099 - static int phy_get_int_delay_property(struct device *dev, const char *name) 3099 + static int phy_get_u32_property(struct device *dev, const char *name, u32 *val) 3100 3100 { 3101 - s32 int_delay; 3102 - int ret; 3103 - 3104 - ret = device_property_read_u32(dev, name, &int_delay); 3105 - if (ret) 3106 - return ret; 3107 - 3108 - return int_delay; 3101 + return device_property_read_u32(dev, name, val); 3109 3102 } 3110 3103 #else 3111 - static int phy_get_int_delay_property(struct device *dev, const char *name) 3104 + static int phy_get_u32_property(struct device *dev, const char *name, u32 *val) 3112 3105 { 3113 3106 return -EINVAL; 3114 3107 } ··· 3126 3133 s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev, 3127 3134 const int *delay_values, int size, bool is_rx) 3128 3135 { 3129 - s32 delay; 3130 - int i; 3136 + int i, ret; 3137 + u32 delay; 3131 3138 3132 3139 if (is_rx) { 3133 - delay = phy_get_int_delay_property(dev, "rx-internal-delay-ps"); 3134 - if (delay < 0 && size == 0) { 3140 + ret = phy_get_u32_property(dev, "rx-internal-delay-ps", &delay); 3141 + if (ret < 0 && size == 0) { 3135 3142 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 3136 3143 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 3137 3144 return 1; ··· 3140 3147 } 3141 3148 3142 3149 } else { 3143 - delay = phy_get_int_delay_property(dev, "tx-internal-delay-ps"); 3144 - if (delay < 0 && size == 0) { 3150 + ret = phy_get_u32_property(dev, "tx-internal-delay-ps", &delay); 3151 + if (ret < 0 && size == 0) { 3145 3152 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 3146 3153 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 3147 3154 return 1; ··· 3150 3157 } 3151 3158 } 3152 3159 3153 - if (delay < 0) 3154 - return delay; 3160 + if (ret < 0) 3161 + return ret; 3155 3162 3156 3163 if (size == 0) 3157 3164 return delay; ··· 3185 3192 return -EINVAL; 3186 3193 } 3187 3194 EXPORT_SYMBOL(phy_get_internal_delay); 3195 + 3196 + /** 3197 + * phy_get_tx_amplitude_gain - stores tx amplitude gain in @val 3198 + * @phydev: phy_device struct 3199 + * @dev: pointer to the devices device struct 3200 + * @linkmode: linkmode for which the tx amplitude gain should be retrieved 3201 + * @val: tx amplitude gain 3202 + * 3203 + * Returns: 0 on success, < 0 on failure 3204 + */ 3205 + int phy_get_tx_amplitude_gain(struct phy_device *phydev, struct device *dev, 3206 + enum ethtool_link_mode_bit_indices linkmode, 3207 + u32 *val) 3208 + { 3209 + switch (linkmode) { 3210 + case ETHTOOL_LINK_MODE_100baseT_Full_BIT: 3211 + return phy_get_u32_property(dev, 3212 + "tx-amplitude-100base-tx-percent", 3213 + val); 3214 + default: 3215 + return -EINVAL; 3216 + } 3217 + } 3218 + EXPORT_SYMBOL_GPL(phy_get_tx_amplitude_gain); 3188 3219 3189 3220 static int phy_led_set_brightness(struct led_classdev *led_cdev, 3190 3221 enum led_brightness value)
+4
include/linux/phy.h
··· 2097 2097 s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev, 2098 2098 const int *delay_values, int size, bool is_rx); 2099 2099 2100 + int phy_get_tx_amplitude_gain(struct phy_device *phydev, struct device *dev, 2101 + enum ethtool_link_mode_bit_indices linkmode, 2102 + u32 *val); 2103 + 2100 2104 void phy_resolve_pause(unsigned long *local_adv, unsigned long *partner_adv, 2101 2105 bool *tx_pause, bool *rx_pause); 2102 2106