826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. From 1dcc03c9a7a824a31eaaecdfaa03542fb25feb6c Mon Sep 17 00:00:00 2001
  2. From: Andrew Lunn <[email protected]>
  3. Date: Tue, 8 Aug 2023 23:04:34 +0200
  4. Subject: [PATCH 2/4] net: phy: phy_device: Call into the PHY driver to set LED
  5. offload
  6. Linux LEDs can be requested to perform hardware accelerated blinking
  7. to indicate link, RX, TX etc. Pass the rules for blinking to the PHY
  8. driver, if it implements the ops needed to determine if a given
  9. pattern can be offloaded, to offload it, and what the current offload
  10. is. Additionally implement the op needed to get what device the LED is
  11. for.
  12. Reviewed-by: Simon Horman <[email protected]>
  13. Signed-off-by: Andrew Lunn <[email protected]>
  14. Tested-by: Daniel Golle <[email protected]>
  15. Link: https://lore.kernel.org/r/[email protected]
  16. Signed-off-by: Jakub Kicinski <[email protected]>
  17. ---
  18. drivers/net/phy/phy_device.c | 68 ++++++++++++++++++++++++++++++++++++
  19. include/linux/phy.h | 33 +++++++++++++++++
  20. 2 files changed, 101 insertions(+)
  21. --- a/drivers/net/phy/phy_device.c
  22. +++ b/drivers/net/phy/phy_device.c
  23. @@ -2964,6 +2964,61 @@ static int phy_led_blink_set(struct led_
  24. return err;
  25. }
  26. +static __maybe_unused struct device *
  27. +phy_led_hw_control_get_device(struct led_classdev *led_cdev)
  28. +{
  29. + struct phy_led *phyled = to_phy_led(led_cdev);
  30. + struct phy_device *phydev = phyled->phydev;
  31. +
  32. + if (phydev->attached_dev)
  33. + return &phydev->attached_dev->dev;
  34. + return NULL;
  35. +}
  36. +
  37. +static int __maybe_unused
  38. +phy_led_hw_control_get(struct led_classdev *led_cdev,
  39. + unsigned long *rules)
  40. +{
  41. + struct phy_led *phyled = to_phy_led(led_cdev);
  42. + struct phy_device *phydev = phyled->phydev;
  43. + int err;
  44. +
  45. + mutex_lock(&phydev->lock);
  46. + err = phydev->drv->led_hw_control_get(phydev, phyled->index, rules);
  47. + mutex_unlock(&phydev->lock);
  48. +
  49. + return err;
  50. +}
  51. +
  52. +static int __maybe_unused
  53. +phy_led_hw_control_set(struct led_classdev *led_cdev,
  54. + unsigned long rules)
  55. +{
  56. + struct phy_led *phyled = to_phy_led(led_cdev);
  57. + struct phy_device *phydev = phyled->phydev;
  58. + int err;
  59. +
  60. + mutex_lock(&phydev->lock);
  61. + err = phydev->drv->led_hw_control_set(phydev, phyled->index, rules);
  62. + mutex_unlock(&phydev->lock);
  63. +
  64. + return err;
  65. +}
  66. +
  67. +static __maybe_unused int phy_led_hw_is_supported(struct led_classdev *led_cdev,
  68. + unsigned long rules)
  69. +{
  70. + struct phy_led *phyled = to_phy_led(led_cdev);
  71. + struct phy_device *phydev = phyled->phydev;
  72. + int err;
  73. +
  74. + mutex_lock(&phydev->lock);
  75. + err = phydev->drv->led_hw_is_supported(phydev, phyled->index, rules);
  76. + mutex_unlock(&phydev->lock);
  77. +
  78. + return err;
  79. +}
  80. +
  81. static void phy_leds_unregister(struct phy_device *phydev)
  82. {
  83. struct phy_led *phyled;
  84. @@ -3001,6 +3056,19 @@ static int of_phy_led(struct phy_device
  85. cdev->brightness_set_blocking = phy_led_set_brightness;
  86. if (phydev->drv->led_blink_set)
  87. cdev->blink_set = phy_led_blink_set;
  88. +
  89. +#ifdef CONFIG_LEDS_TRIGGERS
  90. + if (phydev->drv->led_hw_is_supported &&
  91. + phydev->drv->led_hw_control_set &&
  92. + phydev->drv->led_hw_control_get) {
  93. + cdev->hw_control_is_supported = phy_led_hw_is_supported;
  94. + cdev->hw_control_set = phy_led_hw_control_set;
  95. + cdev->hw_control_get = phy_led_hw_control_get;
  96. + cdev->hw_control_trigger = "netdev";
  97. + }
  98. +
  99. + cdev->hw_control_get_device = phy_led_hw_control_get_device;
  100. +#endif
  101. cdev->max_brightness = 1;
  102. init_data.devicename = dev_name(&phydev->mdio.dev);
  103. init_data.fwnode = of_fwnode_handle(led);
  104. --- a/include/linux/phy.h
  105. +++ b/include/linux/phy.h
  106. @@ -1022,6 +1022,39 @@ struct phy_driver {
  107. int (*led_blink_set)(struct phy_device *dev, u8 index,
  108. unsigned long *delay_on,
  109. unsigned long *delay_off);
  110. + /**
  111. + * @led_hw_is_supported: Can the HW support the given rules.
  112. + * @dev: PHY device which has the LED
  113. + * @index: Which LED of the PHY device
  114. + * @rules The core is interested in these rules
  115. + *
  116. + * Return 0 if yes, -EOPNOTSUPP if not, or an error code.
  117. + */
  118. + int (*led_hw_is_supported)(struct phy_device *dev, u8 index,
  119. + unsigned long rules);
  120. + /**
  121. + * @led_hw_control_set: Set the HW to control the LED
  122. + * @dev: PHY device which has the LED
  123. + * @index: Which LED of the PHY device
  124. + * @rules The rules used to control the LED
  125. + *
  126. + * Returns 0, or a an error code.
  127. + */
  128. + int (*led_hw_control_set)(struct phy_device *dev, u8 index,
  129. + unsigned long rules);
  130. + /**
  131. + * @led_hw_control_get: Get how the HW is controlling the LED
  132. + * @dev: PHY device which has the LED
  133. + * @index: Which LED of the PHY device
  134. + * @rules Pointer to the rules used to control the LED
  135. + *
  136. + * Set *@rules to how the HW is currently blinking. Returns 0
  137. + * on success, or a error code if the current blinking cannot
  138. + * be represented in rules, or some other error happens.
  139. + */
  140. + int (*led_hw_control_get)(struct phy_device *dev, u8 index,
  141. + unsigned long *rules);
  142. +
  143. };
  144. #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
  145. struct phy_driver, mdiodrv)