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

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>

authored by

Daniel Golle and committed by
Jakub Kicinski
29c10aeb b8844aab

+66 -1
+66 -1
drivers/net/phy/mxl-86110.c
··· 71 71 72 72 #define MXL86110_MAX_LEDS 3 73 73 /* LED registers and defines */ 74 + #define MXL86110_COM_EXT_LED_GEN_CFG 0xA00B 75 + # define MXL86110_COM_EXT_LED_GEN_CFG_LFM(x) ((BIT(0) | BIT(1)) << (3 * (x))) 76 + # define MXL86110_COM_EXT_LED_GEN_CFG_LFME(x) (BIT(0) << (3 * (x))) 77 + # define MXL86110_COM_EXT_LED_GEN_CFG_LFE(x) (BIT(2) << (3 * (x))) 78 + 74 79 #define MXL86110_LED0_CFG_REG 0xA00C 75 80 #define MXL86110_LED1_CFG_REG 0xA00D 76 81 #define MXL86110_LED2_CFG_REG 0xA00E ··· 241 236 } 242 237 243 238 /** 239 + * mxl86110_modify_extended_reg() - modify bits of a PHY's extended register 240 + * @phydev: pointer to the PHY device structure 241 + * @regnum: register number to write 242 + * @mask: bit mask of bits to clear 243 + * @set: bit mask of bits to set 244 + * 245 + * Note: register value = (old register value & ~mask) | set. 246 + * 247 + * Return: 0 or negative error code 248 + */ 249 + static int mxl86110_modify_extended_reg(struct phy_device *phydev, 250 + u16 regnum, u16 mask, u16 set) 251 + { 252 + int ret; 253 + 254 + phy_lock_mdio_bus(phydev); 255 + ret = __mxl86110_modify_extended_reg(phydev, regnum, mask, set); 256 + phy_unlock_mdio_bus(phydev); 257 + 258 + return ret; 259 + } 260 + 261 + /** 244 262 * mxl86110_get_wol() - report if wake-on-lan is enabled 245 263 * @phydev: pointer to the phy_device 246 264 * @wol: a pointer to a &struct ethtool_wolinfo ··· 422 394 unsigned long rules) 423 395 { 424 396 u16 val = 0; 397 + int ret; 425 398 426 399 if (index >= MXL86110_MAX_LEDS) 427 400 return -EINVAL; ··· 452 423 rules & BIT(TRIGGER_NETDEV_RX)) 453 424 val |= MXL86110_LEDX_CFG_BLINK; 454 425 455 - return mxl86110_write_extended_reg(phydev, 426 + ret = mxl86110_write_extended_reg(phydev, 456 427 MXL86110_LED0_CFG_REG + index, val); 428 + if (ret) 429 + return ret; 430 + 431 + /* clear manual control bit */ 432 + ret = mxl86110_modify_extended_reg(phydev, 433 + MXL86110_COM_EXT_LED_GEN_CFG, 434 + MXL86110_COM_EXT_LED_GEN_CFG_LFE(index), 435 + 0); 436 + 437 + return ret; 438 + } 439 + 440 + static int mxl86110_led_brightness_set(struct phy_device *phydev, 441 + u8 index, enum led_brightness value) 442 + { 443 + u16 mask, set; 444 + int ret; 445 + 446 + if (index >= MXL86110_MAX_LEDS) 447 + return -EINVAL; 448 + 449 + /* force manual control */ 450 + set = MXL86110_COM_EXT_LED_GEN_CFG_LFE(index); 451 + /* clear previous force mode */ 452 + mask = MXL86110_COM_EXT_LED_GEN_CFG_LFM(index); 453 + 454 + /* force LED to be permanently on */ 455 + if (value != LED_OFF) 456 + set |= MXL86110_COM_EXT_LED_GEN_CFG_LFME(index); 457 + 458 + ret = mxl86110_modify_extended_reg(phydev, 459 + MXL86110_COM_EXT_LED_GEN_CFG, 460 + mask, set); 461 + 462 + return ret; 457 463 } 458 464 459 465 /** ··· 660 596 .config_init = mxl86110_config_init, 661 597 .get_wol = mxl86110_get_wol, 662 598 .set_wol = mxl86110_set_wol, 599 + .led_brightness_set = mxl86110_led_brightness_set, 663 600 .led_hw_is_supported = mxl86110_led_hw_is_supported, 664 601 .led_hw_control_get = mxl86110_led_hw_control_get, 665 602 .led_hw_control_set = mxl86110_led_hw_control_set,