net: phy: mxl-86110: add basic support for led_brightness_set op

Add support for forcing each connected LED to be always on or always off
by implementing the led_brightness_set() op.
This is done by modifying the COM_EXT_LED_GEN_CFG register to enable
force-mode and forcing the LED either on or off.
When calling the led_hw_control_set() force-mode is again disabled for
that LED.
Implement mxl86110_modify_extended_reg() locked helper instead of
manually acquiring and releasing the MDIO bus lock for single
__mxl86110_modify_extended_reg() calls.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/58eeefc8c24e06cd2110d3cefbd4236b1a4f44a2.1755884175.git.daniel@makrotopia.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Daniel Golle 2025-08-22 18:38:27 +01:00 committed by Jakub Kicinski
parent b8844aab51
commit 29c10aeb31

View File

@ -71,6 +71,11 @@
#define MXL86110_MAX_LEDS 3
/* LED registers and defines */
#define MXL86110_COM_EXT_LED_GEN_CFG 0xA00B
# define MXL86110_COM_EXT_LED_GEN_CFG_LFM(x) ((BIT(0) | BIT(1)) << (3 * (x)))
# define MXL86110_COM_EXT_LED_GEN_CFG_LFME(x) (BIT(0) << (3 * (x)))
# define MXL86110_COM_EXT_LED_GEN_CFG_LFE(x) (BIT(2) << (3 * (x)))
#define MXL86110_LED0_CFG_REG 0xA00C
#define MXL86110_LED1_CFG_REG 0xA00D
#define MXL86110_LED2_CFG_REG 0xA00E
@ -235,6 +240,29 @@ static int mxl86110_read_extended_reg(struct phy_device *phydev, u16 regnum)
return ret;
}
/**
* mxl86110_modify_extended_reg() - modify bits of a PHY's extended register
* @phydev: pointer to the PHY device structure
* @regnum: register number to write
* @mask: bit mask of bits to clear
* @set: bit mask of bits to set
*
* Note: register value = (old register value & ~mask) | set.
*
* Return: 0 or negative error code
*/
static int mxl86110_modify_extended_reg(struct phy_device *phydev,
u16 regnum, u16 mask, u16 set)
{
int ret;
phy_lock_mdio_bus(phydev);
ret = __mxl86110_modify_extended_reg(phydev, regnum, mask, set);
phy_unlock_mdio_bus(phydev);
return ret;
}
/**
* mxl86110_get_wol() - report if wake-on-lan is enabled
* @phydev: pointer to the phy_device
@ -394,6 +422,7 @@ static int mxl86110_led_hw_control_set(struct phy_device *phydev, u8 index,
unsigned long rules)
{
u16 val = 0;
int ret;
if (index >= MXL86110_MAX_LEDS)
return -EINVAL;
@ -423,8 +452,43 @@ static int mxl86110_led_hw_control_set(struct phy_device *phydev, u8 index,
rules & BIT(TRIGGER_NETDEV_RX))
val |= MXL86110_LEDX_CFG_BLINK;
return mxl86110_write_extended_reg(phydev,
ret = mxl86110_write_extended_reg(phydev,
MXL86110_LED0_CFG_REG + index, val);
if (ret)
return ret;
/* clear manual control bit */
ret = mxl86110_modify_extended_reg(phydev,
MXL86110_COM_EXT_LED_GEN_CFG,
MXL86110_COM_EXT_LED_GEN_CFG_LFE(index),
0);
return ret;
}
static int mxl86110_led_brightness_set(struct phy_device *phydev,
u8 index, enum led_brightness value)
{
u16 mask, set;
int ret;
if (index >= MXL86110_MAX_LEDS)
return -EINVAL;
/* force manual control */
set = MXL86110_COM_EXT_LED_GEN_CFG_LFE(index);
/* clear previous force mode */
mask = MXL86110_COM_EXT_LED_GEN_CFG_LFM(index);
/* force LED to be permanently on */
if (value != LED_OFF)
set |= MXL86110_COM_EXT_LED_GEN_CFG_LFME(index);
ret = mxl86110_modify_extended_reg(phydev,
MXL86110_COM_EXT_LED_GEN_CFG,
mask, set);
return ret;
}
/**
@ -596,6 +660,7 @@ static struct phy_driver mxl_phy_drvs[] = {
.config_init = mxl86110_config_init,
.get_wol = mxl86110_get_wol,
.set_wol = mxl86110_set_wol,
.led_brightness_set = mxl86110_led_brightness_set,
.led_hw_is_supported = mxl86110_led_hw_is_supported,
.led_hw_control_get = mxl86110_led_hw_control_get,
.led_hw_control_set = mxl86110_led_hw_control_set,