mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 15:32:33 +00:00
cf08db988b
Backport initial LEDs hw control support. Currently this is limited to
only rx/tx and link events for the netdev trigger but the API got
accepted and the additional modes are working on and will be backported
later.
Refresh every patch and add the additional config flag for QCA8K new
LEDs support.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
(cherry picked from commit 0a4b309f41
)
192 lines
5.3 KiB
Diff
192 lines
5.3 KiB
Diff
From 01e5b728e9e43ae444e0369695a5f72209906464 Mon Sep 17 00:00:00 2001
|
|
From: Andrew Lunn <andrew@lunn.ch>
|
|
Date: Mon, 17 Apr 2023 17:17:27 +0200
|
|
Subject: [PATCH 5/9] net: phy: Add a binding for PHY LEDs
|
|
|
|
Define common binding parsing for all PHY drivers with LEDs using
|
|
phylib. Parse the DT as part of the phy_probe and add LEDs to the
|
|
linux LED class infrastructure. For the moment, provide a dummy
|
|
brightness function, which will later be replaced with a call into the
|
|
PHY driver. This allows testing since the LED core might otherwise
|
|
reject an LED whose brightness cannot be set.
|
|
|
|
Add a dependency on LED_CLASS. It either needs to be built in, or not
|
|
enabled, since a modular build can result in linker errors.
|
|
|
|
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
|
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
---
|
|
drivers/net/phy/Kconfig | 1 +
|
|
drivers/net/phy/phy_device.c | 76 ++++++++++++++++++++++++++++++++++++
|
|
include/linux/phy.h | 16 ++++++++
|
|
3 files changed, 93 insertions(+)
|
|
|
|
--- a/drivers/net/phy/Kconfig
|
|
+++ b/drivers/net/phy/Kconfig
|
|
@@ -18,6 +18,7 @@ menuconfig PHYLIB
|
|
depends on NETDEVICES
|
|
select MDIO_DEVICE
|
|
select MDIO_DEVRES
|
|
+ depends on LEDS_CLASS || LEDS_CLASS=n
|
|
help
|
|
Ethernet controllers are usually attached to PHY
|
|
devices. This option provides infrastructure for
|
|
--- a/drivers/net/phy/phy_device.c
|
|
+++ b/drivers/net/phy/phy_device.c
|
|
@@ -19,10 +19,12 @@
|
|
#include <linux/interrupt.h>
|
|
#include <linux/io.h>
|
|
#include <linux/kernel.h>
|
|
+#include <linux/list.h>
|
|
#include <linux/mdio.h>
|
|
#include <linux/mii.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/module.h>
|
|
+#include <linux/of.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/phy.h>
|
|
#include <linux/phy_led_triggers.h>
|
|
@@ -641,6 +643,7 @@ struct phy_device *phy_device_create(str
|
|
device_initialize(&mdiodev->dev);
|
|
|
|
dev->state = PHY_DOWN;
|
|
+ INIT_LIST_HEAD(&dev->leds);
|
|
|
|
mutex_init(&dev->lock);
|
|
INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
|
|
@@ -2942,6 +2945,74 @@ static bool phy_drv_supports_irq(struct
|
|
return phydrv->config_intr && phydrv->handle_interrupt;
|
|
}
|
|
|
|
+/* Dummy implementation until calls into PHY driver are added */
|
|
+static int phy_led_set_brightness(struct led_classdev *led_cdev,
|
|
+ enum led_brightness value)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int of_phy_led(struct phy_device *phydev,
|
|
+ struct device_node *led)
|
|
+{
|
|
+ struct device *dev = &phydev->mdio.dev;
|
|
+ struct led_init_data init_data = {};
|
|
+ struct led_classdev *cdev;
|
|
+ struct phy_led *phyled;
|
|
+ int err;
|
|
+
|
|
+ phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL);
|
|
+ if (!phyled)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ cdev = &phyled->led_cdev;
|
|
+
|
|
+ err = of_property_read_u8(led, "reg", &phyled->index);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ cdev->brightness_set_blocking = phy_led_set_brightness;
|
|
+ cdev->max_brightness = 1;
|
|
+ init_data.devicename = dev_name(&phydev->mdio.dev);
|
|
+ init_data.fwnode = of_fwnode_handle(led);
|
|
+ init_data.devname_mandatory = true;
|
|
+
|
|
+ err = devm_led_classdev_register_ext(dev, cdev, &init_data);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ list_add(&phyled->list, &phydev->leds);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int of_phy_leds(struct phy_device *phydev)
|
|
+{
|
|
+ struct device_node *node = phydev->mdio.dev.of_node;
|
|
+ struct device_node *leds, *led;
|
|
+ int err;
|
|
+
|
|
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
|
|
+ return 0;
|
|
+
|
|
+ if (!node)
|
|
+ return 0;
|
|
+
|
|
+ leds = of_get_child_by_name(node, "leds");
|
|
+ if (!leds)
|
|
+ return 0;
|
|
+
|
|
+ for_each_available_child_of_node(leds, led) {
|
|
+ err = of_phy_led(phydev, led);
|
|
+ if (err) {
|
|
+ of_node_put(led);
|
|
+ return err;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/**
|
|
* fwnode_mdio_find_device - Given a fwnode, find the mdio_device
|
|
* @fwnode: pointer to the mdio_device's fwnode
|
|
@@ -3120,6 +3191,11 @@ static int phy_probe(struct device *dev)
|
|
/* Set the state to READY by default */
|
|
phydev->state = PHY_READY;
|
|
|
|
+ /* Get the LEDs from the device tree, and instantiate standard
|
|
+ * LEDs for them.
|
|
+ */
|
|
+ err = of_phy_leds(phydev);
|
|
+
|
|
out:
|
|
/* Re-assert the reset signal on error */
|
|
if (err)
|
|
--- a/include/linux/phy.h
|
|
+++ b/include/linux/phy.h
|
|
@@ -14,6 +14,7 @@
|
|
#include <linux/compiler.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/ethtool.h>
|
|
+#include <linux/leds.h>
|
|
#include <linux/linkmode.h>
|
|
#include <linux/netlink.h>
|
|
#include <linux/mdio.h>
|
|
@@ -582,6 +583,7 @@ struct macsec_ops;
|
|
* @phy_num_led_triggers: Number of triggers in @phy_led_triggers
|
|
* @led_link_trigger: LED trigger for link up/down
|
|
* @last_triggered: last LED trigger for link speed
|
|
+ * @leds: list of PHY LED structures
|
|
* @master_slave_set: User requested master/slave configuration
|
|
* @master_slave_get: Current master/slave advertisement
|
|
* @master_slave_state: Current master/slave configuration
|
|
@@ -668,6 +670,7 @@ struct phy_device {
|
|
|
|
struct phy_led_trigger *led_link_trigger;
|
|
#endif
|
|
+ struct list_head leds;
|
|
|
|
/*
|
|
* Interrupt number for this PHY
|
|
@@ -739,6 +742,19 @@ struct phy_tdr_config {
|
|
#define PHY_PAIR_ALL -1
|
|
|
|
/**
|
|
+ * struct phy_led: An LED driven by the PHY
|
|
+ *
|
|
+ * @list: List of LEDs
|
|
+ * @led_cdev: Standard LED class structure
|
|
+ * @index: Number of the LED
|
|
+ */
|
|
+struct phy_led {
|
|
+ struct list_head list;
|
|
+ struct led_classdev led_cdev;
|
|
+ u8 index;
|
|
+};
|
|
+
|
|
+/**
|
|
* struct phy_driver - Driver structure for a particular PHY type
|
|
*
|
|
* @mdiodrv: Data common to all MDIO devices
|