4873c40a7766b34a39263fdcaa0f75068923ed10
[openwrt/staging/ansuel.git] /
1 From 684818189b04b095b34964ed4a3ea5249a840eab Mon Sep 17 00:00:00 2001
2 From: Andrew Lunn <andrew@lunn.ch>
3 Date: Mon, 17 Apr 2023 17:17:28 +0200
4 Subject: [PATCH 6/9] net: phy: phy_device: Call into the PHY driver to set LED
5 brightness
6
7 Linux LEDs can be software controlled via the brightness file in /sys.
8 LED drivers need to implement a brightness_set function which the core
9 will call. Implement an intermediary in phy_device, which will call
10 into the phy driver if it implements the necessary function.
11
12 Signed-off-by: Andrew Lunn <andrew@lunn.ch>
13 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
14 Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
15 Signed-off-by: David S. Miller <davem@davemloft.net>
16 ---
17 drivers/net/phy/phy_device.c | 15 ++++++++++++---
18 include/linux/phy.h | 13 +++++++++++++
19 2 files changed, 25 insertions(+), 3 deletions(-)
20
21 --- a/drivers/net/phy/phy_device.c
22 +++ b/drivers/net/phy/phy_device.c
23 @@ -3038,11 +3038,18 @@ static bool phy_drv_supports_irq(struct
24 return phydrv->config_intr && phydrv->handle_interrupt;
25 }
26
27 -/* Dummy implementation until calls into PHY driver are added */
28 static int phy_led_set_brightness(struct led_classdev *led_cdev,
29 enum led_brightness value)
30 {
31 - return 0;
32 + struct phy_led *phyled = to_phy_led(led_cdev);
33 + struct phy_device *phydev = phyled->phydev;
34 + int err;
35 +
36 + mutex_lock(&phydev->lock);
37 + err = phydev->drv->led_brightness_set(phydev, phyled->index, value);
38 + mutex_unlock(&phydev->lock);
39 +
40 + return err;
41 }
42
43 static int of_phy_led(struct phy_device *phydev,
44 @@ -3059,12 +3066,14 @@ static int of_phy_led(struct phy_device
45 return -ENOMEM;
46
47 cdev = &phyled->led_cdev;
48 + phyled->phydev = phydev;
49
50 err = of_property_read_u8(led, "reg", &phyled->index);
51 if (err)
52 return err;
53
54 - cdev->brightness_set_blocking = phy_led_set_brightness;
55 + if (phydev->drv->led_brightness_set)
56 + cdev->brightness_set_blocking = phy_led_set_brightness;
57 cdev->max_brightness = 1;
58 init_data.devicename = dev_name(&phydev->mdio.dev);
59 init_data.fwnode = of_fwnode_handle(led);
60 --- a/include/linux/phy.h
61 +++ b/include/linux/phy.h
62 @@ -778,15 +778,19 @@ struct phy_tdr_config {
63 * struct phy_led: An LED driven by the PHY
64 *
65 * @list: List of LEDs
66 + * @phydev: PHY this LED is attached to
67 * @led_cdev: Standard LED class structure
68 * @index: Number of the LED
69 */
70 struct phy_led {
71 struct list_head list;
72 + struct phy_device *phydev;
73 struct led_classdev led_cdev;
74 u8 index;
75 };
76
77 +#define to_phy_led(d) container_of(d, struct phy_led, led_cdev)
78 +
79 /**
80 * struct phy_driver - Driver structure for a particular PHY type
81 *
82 @@ -1001,6 +1005,15 @@ struct phy_driver {
83 int (*get_sqi)(struct phy_device *dev);
84 /** @get_sqi_max: Get the maximum signal quality indication */
85 int (*get_sqi_max)(struct phy_device *dev);
86 +
87 + /**
88 + * @led_brightness_set: Set a PHY LED brightness. Index
89 + * indicates which of the PHYs led should be set. Value
90 + * follows the standard LED class meaning, e.g. LED_OFF,
91 + * LED_HALF, LED_FULL.
92 + */
93 + int (*led_brightness_set)(struct phy_device *dev,
94 + u8 index, enum led_brightness value);
95 };
96 #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
97 struct phy_driver, mdiodrv)