Skip to content

Commit

Permalink
net: phy: phy_device: Call into the PHY driver to set LED offload
Browse files Browse the repository at this point in the history
Linux LEDs can be requested to perform hardware accelerated blinking
to indicate link, RX, TX etc. Pass the rules for blinking to the PHY
driver, if it implements the ops needed to determine if a given
pattern can be offloaded, to offload it, and what the current offload
is.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
  • Loading branch information
lunn committed Mar 17, 2023
1 parent 2ce033c commit bbade5c
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
37 changes: 37 additions & 0 deletions drivers/net/phy/phy_device.c
Expand Up @@ -3021,6 +3021,39 @@ static int phy_led_blink_set(struct led_classdev *led_cdev,
return err;
}

static int phy_led_hw_control_configure(struct led_classdev *led_cdev,
unsigned long rules,
enum led_blink_hw_cmd cmd)
{
struct phy_led *phyled = to_phy_led(led_cdev);
struct phy_device *phydev = phyled->phydev;
unsigned long active_rules;
int err;

mutex_lock(&phydev->lock);
switch (cmd) {
case LED_BLINK_HW_SUPPORTED:
err = phydev->drv->led_hw_is_supported(phydev, phyled->index,
rules);
break;
case LED_BLINK_HW_ENABLE:
err = phydev->drv->led_hw_control_set(phydev, phyled->index,
rules);
break;
case LED_BLINK_HW_STATUS:
err = phydev->drv->led_hw_control_get(phydev, phyled->index,
&active_rules);
if (!err)
err = active_rules;
break;
default:
err = -EOPNOTSUPP;
}
mutex_unlock(&phydev->lock);

return err;
}

static int of_phy_led(struct phy_device *phydev,
struct device_node *led)
{
Expand All @@ -3045,6 +3078,10 @@ static int of_phy_led(struct phy_device *phydev,
cdev->brightness_set_blocking = phy_led_set_brightness;
if (phydev->drv->led_blink_set)
cdev->blink_set = phy_led_blink_set;
if (phydev->drv->led_hw_is_supported &&
phydev->drv->led_hw_control_set &&
phydev->drv->led_hw_control_get)
cdev->hw_control_configure = phy_led_hw_control_configure;
cdev->max_brightness = 1;
init_data.devicename = dev_name(&phydev->mdio.dev);
init_data.fwnode = of_fwnode_handle(led);
Expand Down
14 changes: 14 additions & 0 deletions include/linux/phy.h
Expand Up @@ -1091,6 +1091,20 @@ struct phy_driver {
int (*led_blink_set)(struct phy_device *dev, u32 index,
unsigned long *delay_on,
unsigned long *delay_off);
/* Can the HW support the given rules. Return 0 if yes,
* -EOPNOTSUPP if not, or an error code.
*/
int (*led_hw_is_supported)(struct phy_device *dev, u32 index,
unsigned long rules);
/* Set the HW to control the LED as described by rules. */
int (*led_hw_control_set)(struct phy_device *dev, u32 index,
unsigned long rules);
/* Get the rules used to describe how the HW is currently
* configure.
*/
int (*led_hw_control_get)(struct phy_device *dev, u32 index,
unsigned long *rules);

};
#define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
struct phy_driver, mdiodrv)
Expand Down

0 comments on commit bbade5c

Please sign in to comment.