diff mbox series

[RFC,net-next,8/8] dsa: qca8k: Use DSA common code for LEDs

Message ID 20231128232135.358638-9-andrew@lunn.ch (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series DSA LED infrastructure, mv88e6xxx and QCA8K | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/codegen success Generated files up to date
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1115 this patch: 1115
netdev/cc_maintainers warning 3 maintainers not CCed: kuba@kernel.org pabeni@redhat.com edumazet@google.com
netdev/build_clang success Errors and warnings before: 1142 this patch: 1142
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1142 this patch: 1142
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 300 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Andrew Lunn Nov. 28, 2023, 11:21 p.m. UTC
Rather than parse the device tree in the qca8k driver, make use of the
common code in the DSA core.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/qca/qca8k-8xxx.c |  11 +-
 drivers/net/dsa/qca/qca8k-leds.c | 255 +++++--------------------------
 drivers/net/dsa/qca/qca8k.h      |   9 --
 drivers/net/dsa/qca/qca8k_leds.h |  21 ++-
 4 files changed, 56 insertions(+), 240 deletions(-)

Comments

Christian Marangi Nov. 29, 2023, 1:55 a.m. UTC | #1
On Wed, Nov 29, 2023 at 12:21:35AM +0100, Andrew Lunn wrote:
> Rather than parse the device tree in the qca8k driver, make use of the
> common code in the DSA core.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Hi,

I attached a fixup patch for this to correctly work. Since we are using
port_num the thing needs to be decrememted by one.
Andrew Lunn Nov. 29, 2023, 2:16 a.m. UTC | #2
> Hi,
> 
> I attached a fixup patch for this to correctly work. Since we are using
> port_num the thing needs to be decrememted by one.

I thought this might happen.

How about this fix instead? It fits better with the naming of
parameters, and just does the offset once for each API function.

	    Andrew

>From 0789b95345bfa5086365051f95531fdb3d053e3e Mon Sep 17 00:00:00 2001
From: Andrew Lunn <andrew@lunn.ch>
Date: Tue, 28 Nov 2023 20:11:42 -0600
Subject: [PATCH] dsa: qca8k: Fix off-by-one for LEDs.

---
 drivers/net/dsa/qca/qca8k-leds.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c
index febae23b65a9..0aa209b84251 100644
--- a/drivers/net/dsa/qca/qca8k-leds.c
+++ b/drivers/net/dsa/qca/qca8k-leds.c
@@ -80,9 +80,10 @@ qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger)
 }
 
 int
-qca8k_led_brightness_set(struct dsa_switch *ds, int port_num,
+qca8k_led_brightness_set(struct dsa_switch *ds, int port,
 			 u8 led_num, enum led_brightness brightness)
 {
+	int port_num = qca8k_port_to_phy(port);
 	struct qca8k_led_pattern_en reg_info;
 	struct qca8k_priv *priv = ds->priv;
 	u32 mask, val;
@@ -140,11 +141,12 @@ qca8k_led_brightness_set(struct dsa_switch *ds, int port_num,
 }
 
 int
-qca8k_led_blink_set(struct dsa_switch *ds, int port_num, u8 led_num,
+qca8k_led_blink_set(struct dsa_switch *ds, int port, u8 led_num,
 		    unsigned long *delay_on,
 		    unsigned long *delay_off)
 {
 	u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ;
+	int port_num = qca8k_port_to_phy(port);
 	struct qca8k_led_pattern_en reg_info;
 	struct qca8k_priv *priv = ds->priv;
 
@@ -231,9 +233,10 @@ qca8k_led_hw_control_is_supported(struct dsa_switch *ds,
 }
 
 int
-qca8k_led_hw_control_set(struct dsa_switch *ds, int port_num, u8 led_num,
+qca8k_led_hw_control_set(struct dsa_switch *ds, int port, u8 led_num,
 			 unsigned long rules)
 {
+	int port_num = qca8k_port_to_phy(port);
 	struct qca8k_led_pattern_en reg_info;
 	struct qca8k_priv *priv = ds->priv;
 	u32 offload_trigger = 0;
@@ -255,9 +258,10 @@ qca8k_led_hw_control_set(struct dsa_switch *ds, int port_num, u8 led_num,
 }
 
 int
-qca8k_led_hw_control_get(struct dsa_switch *ds, int port_num, u8 led_num,
+qca8k_led_hw_control_get(struct dsa_switch *ds, int port, u8 led_num,
 			 unsigned long *rules)
 {
+	int port_num = qca8k_port_to_phy(port);
 	struct qca8k_led_pattern_en reg_info;
 	struct qca8k_priv *priv = ds->priv;
 	u32 val;
Christian Marangi Nov. 29, 2023, 2:23 a.m. UTC | #3
On Wed, Nov 29, 2023 at 03:16:16AM +0100, Andrew Lunn wrote:
> > Hi,
> > 
> > I attached a fixup patch for this to correctly work. Since we are using
> > port_num the thing needs to be decrememted by one.
> 
> I thought this might happen.
> 
> How about this fix instead? It fits better with the naming of
> parameters, and just does the offset once for each API function.
>

Yep also works. My idea was to act on the function that parse the
port_num and gives regs and mask to prevent problem in the future but I
don't think it will change that much.

With your proposed fix,

Reviewed-by: Christian Marangi <ansuelsmth@gmail.com>

> 
> From 0789b95345bfa5086365051f95531fdb3d053e3e Mon Sep 17 00:00:00 2001
> From: Andrew Lunn <andrew@lunn.ch>
> Date: Tue, 28 Nov 2023 20:11:42 -0600
> Subject: [PATCH] dsa: qca8k: Fix off-by-one for LEDs.
> 
> ---
>  drivers/net/dsa/qca/qca8k-leds.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c
> index febae23b65a9..0aa209b84251 100644
> --- a/drivers/net/dsa/qca/qca8k-leds.c
> +++ b/drivers/net/dsa/qca/qca8k-leds.c
> @@ -80,9 +80,10 @@ qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger)
>  }
>  
>  int
> -qca8k_led_brightness_set(struct dsa_switch *ds, int port_num,
> +qca8k_led_brightness_set(struct dsa_switch *ds, int port,
>  			 u8 led_num, enum led_brightness brightness)
>  {
> +	int port_num = qca8k_port_to_phy(port);
>  	struct qca8k_led_pattern_en reg_info;
>  	struct qca8k_priv *priv = ds->priv;
>  	u32 mask, val;
> @@ -140,11 +141,12 @@ qca8k_led_brightness_set(struct dsa_switch *ds, int port_num,
>  }
>  
>  int
> -qca8k_led_blink_set(struct dsa_switch *ds, int port_num, u8 led_num,
> +qca8k_led_blink_set(struct dsa_switch *ds, int port, u8 led_num,
>  		    unsigned long *delay_on,
>  		    unsigned long *delay_off)
>  {
>  	u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ;
> +	int port_num = qca8k_port_to_phy(port);
>  	struct qca8k_led_pattern_en reg_info;
>  	struct qca8k_priv *priv = ds->priv;
>  
> @@ -231,9 +233,10 @@ qca8k_led_hw_control_is_supported(struct dsa_switch *ds,
>  }
>  
>  int
> -qca8k_led_hw_control_set(struct dsa_switch *ds, int port_num, u8 led_num,
> +qca8k_led_hw_control_set(struct dsa_switch *ds, int port, u8 led_num,
>  			 unsigned long rules)
>  {
> +	int port_num = qca8k_port_to_phy(port);
>  	struct qca8k_led_pattern_en reg_info;
>  	struct qca8k_priv *priv = ds->priv;
>  	u32 offload_trigger = 0;
> @@ -255,9 +258,10 @@ qca8k_led_hw_control_set(struct dsa_switch *ds, int port_num, u8 led_num,
>  }
>  
>  int
> -qca8k_led_hw_control_get(struct dsa_switch *ds, int port_num, u8 led_num,
> +qca8k_led_hw_control_get(struct dsa_switch *ds, int port, u8 led_num,
>  			 unsigned long *rules)
>  {
> +	int port_num = qca8k_port_to_phy(port);
>  	struct qca8k_led_pattern_en reg_info;
>  	struct qca8k_priv *priv = ds->priv;
>  	u32 val;
> -- 
> 2.42.0
>
diff mbox series

Patch

diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index ec57d9d52072..4929894a2b5d 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -1838,10 +1838,6 @@  qca8k_setup(struct dsa_switch *ds)
 	if (ret)
 		return ret;
 
-	ret = qca8k_setup_led_ctrl(priv);
-	if (ret)
-		return ret;
-
 	qca8k_setup_pcs(priv, &priv->pcs_port_0, 0);
 	qca8k_setup_pcs(priv, &priv->pcs_port_6, 6);
 
@@ -2018,6 +2014,13 @@  static const struct dsa_switch_ops qca8k_switch_ops = {
 	.port_lag_leave		= qca8k_port_lag_leave,
 	.conduit_state_change	= qca8k_conduit_change,
 	.connect_tag_protocol	= qca8k_connect_tag_protocol,
+#ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT
+	.led_brightness_set	= qca8k_led_brightness_set,
+	.led_blink_set		= qca8k_led_blink_set,
+	.led_hw_control_is_supported = qca8k_led_hw_control_is_supported,
+	.led_hw_control_set	= qca8k_led_hw_control_set,
+	.led_hw_control_get	= qca8k_led_hw_control_get,
+#endif
 };
 
 static int
diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c
index 90e30c2909e4..febae23b65a9 100644
--- a/drivers/net/dsa/qca/qca8k-leds.c
+++ b/drivers/net/dsa/qca/qca8k-leds.c
@@ -6,18 +6,6 @@ 
 #include "qca8k.h"
 #include "qca8k_leds.h"
 
-static u32 qca8k_phy_to_port(int phy)
-{
-	/* Internal PHY 0 has port at index 1.
-	 * Internal PHY 1 has port at index 2.
-	 * Internal PHY 2 has port at index 3.
-	 * Internal PHY 3 has port at index 4.
-	 * Internal PHY 4 has port at index 5.
-	 */
-
-	return phy + 1;
-}
-
 static int
 qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
 {
@@ -91,15 +79,15 @@  qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger)
 	return 0;
 }
 
-static int
-qca8k_led_brightness_set(struct qca8k_led *led,
-			 enum led_brightness brightness)
+int
+qca8k_led_brightness_set(struct dsa_switch *ds, int port_num,
+			 u8 led_num, enum led_brightness brightness)
 {
 	struct qca8k_led_pattern_en reg_info;
-	struct qca8k_priv *priv = led->priv;
+	struct qca8k_priv *priv = ds->priv;
 	u32 mask, val;
 
-	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+	qca8k_get_enable_led_reg(port_num, led_num, &reg_info);
 
 	val = QCA8K_LED_ALWAYS_OFF;
 	if (brightness)
@@ -139,7 +127,7 @@  qca8k_led_brightness_set(struct qca8k_led *led,
 	 * to calculate the shift and the correct reg due to this problem of
 	 * not having a 1:1 map of LED with the regs.
 	 */
-	if (led->port_num == 0 || led->port_num == 4) {
+	if (port_num == 0 || port_num == 4) {
 		mask = QCA8K_LED_PATTERN_EN_MASK;
 		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
 	} else {
@@ -151,51 +139,14 @@  qca8k_led_brightness_set(struct qca8k_led *led,
 				  val << reg_info.shift);
 }
 
-static int
-qca8k_cled_brightness_set_blocking(struct led_classdev *ldev,
-				   enum led_brightness brightness)
-{
-	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
-
-	return qca8k_led_brightness_set(led, brightness);
-}
-
-static enum led_brightness
-qca8k_led_brightness_get(struct qca8k_led *led)
-{
-	struct qca8k_led_pattern_en reg_info;
-	struct qca8k_priv *priv = led->priv;
-	u32 val;
-	int ret;
-
-	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
-
-	ret = regmap_read(priv->regmap, reg_info.reg, &val);
-	if (ret)
-		return 0;
-
-	val >>= reg_info.shift;
-
-	if (led->port_num == 0 || led->port_num == 4) {
-		val &= QCA8K_LED_PATTERN_EN_MASK;
-		val >>= QCA8K_LED_PATTERN_EN_SHIFT;
-	} else {
-		val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
-	}
-
-	/* Assume brightness ON only when the LED is set to always ON */
-	return val == QCA8K_LED_ALWAYS_ON;
-}
-
-static int
-qca8k_cled_blink_set(struct led_classdev *ldev,
-		     unsigned long *delay_on,
-		     unsigned long *delay_off)
+int
+qca8k_led_blink_set(struct dsa_switch *ds, int port_num, u8 led_num,
+		    unsigned long *delay_on,
+		    unsigned long *delay_off)
 {
-	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
 	u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ;
 	struct qca8k_led_pattern_en reg_info;
-	struct qca8k_priv *priv = led->priv;
+	struct qca8k_priv *priv = ds->priv;
 
 	if (*delay_on == 0 && *delay_off == 0) {
 		*delay_on = 125;
@@ -209,9 +160,9 @@  qca8k_cled_blink_set(struct led_classdev *ldev,
 		return -EINVAL;
 	}
 
-	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+	qca8k_get_enable_led_reg(port_num, led_num, &reg_info);
 
-	if (led->port_num == 0 || led->port_num == 4) {
+	if (port_num == 0 || port_num == 4) {
 		mask = QCA8K_LED_PATTERN_EN_MASK;
 		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
 	} else {
@@ -225,20 +176,18 @@  qca8k_cled_blink_set(struct led_classdev *ldev,
 }
 
 static int
-qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable)
+qca8k_led_trigger_offload(struct qca8k_priv *priv, int port_num, u8 led_num,
+			  bool enable)
 {
-	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
-
 	struct qca8k_led_pattern_en reg_info;
-	struct qca8k_priv *priv = led->priv;
 	u32 mask, val = QCA8K_LED_ALWAYS_OFF;
 
-	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+	qca8k_get_enable_led_reg(port_num, led_num, &reg_info);
 
 	if (enable)
 		val = QCA8K_LED_RULE_CONTROLLED;
 
-	if (led->port_num == 0 || led->port_num == 4) {
+	if (port_num == 0 || port_num == 4) {
 		mask = QCA8K_LED_PATTERN_EN_MASK;
 		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
 	} else {
@@ -250,21 +199,18 @@  qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable)
 }
 
 static bool
-qca8k_cled_hw_control_status(struct led_classdev *ldev)
+qca8k_led_hw_control_status(struct qca8k_priv *priv, int port_num, u8 led_num)
 {
-	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
-
 	struct qca8k_led_pattern_en reg_info;
-	struct qca8k_priv *priv = led->priv;
 	u32 val;
 
-	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+	qca8k_get_enable_led_reg(port_num, led_num, &reg_info);
 
 	regmap_read(priv->regmap, reg_info.reg, &val);
 
 	val >>= reg_info.shift;
 
-	if (led->port_num == 0 || led->port_num == 4) {
+	if (port_num == 0 || port_num == 4) {
 		val &= QCA8K_LED_PATTERN_EN_MASK;
 		val >>= QCA8K_LED_PATTERN_EN_SHIFT;
 	} else {
@@ -274,20 +220,22 @@  qca8k_cled_hw_control_status(struct led_classdev *ldev)
 	return val == QCA8K_LED_RULE_CONTROLLED;
 }
 
-static int
-qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
+int
+qca8k_led_hw_control_is_supported(struct dsa_switch *ds,
+				  int port, u8 led,
+				  unsigned long rules)
 {
 	u32 offload_trigger = 0;
 
 	return qca8k_parse_netdev(rules, &offload_trigger);
 }
 
-static int
-qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules)
+int
+qca8k_led_hw_control_set(struct dsa_switch *ds, int port_num, u8 led_num,
+			 unsigned long rules)
 {
-	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
 	struct qca8k_led_pattern_en reg_info;
-	struct qca8k_priv *priv = led->priv;
+	struct qca8k_priv *priv = ds->priv;
 	u32 offload_trigger = 0;
 	int ret;
 
@@ -295,31 +243,31 @@  qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules)
 	if (ret)
 		return ret;
 
-	ret = qca8k_cled_trigger_offload(ldev, true);
+	ret = qca8k_led_trigger_offload(priv, port_num, led_num, true);
 	if (ret)
 		return ret;
 
-	qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
+	qca8k_get_control_led_reg(port_num, led_num, &reg_info);
 
 	return regmap_update_bits(priv->regmap, reg_info.reg,
 				  QCA8K_LED_RULE_MASK << reg_info.shift,
 				  offload_trigger << reg_info.shift);
 }
 
-static int
-qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
+int
+qca8k_led_hw_control_get(struct dsa_switch *ds, int port_num, u8 led_num,
+			 unsigned long *rules)
 {
-	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
 	struct qca8k_led_pattern_en reg_info;
-	struct qca8k_priv *priv = led->priv;
+	struct qca8k_priv *priv = ds->priv;
 	u32 val;
 	int ret;
 
 	/* With hw control not active return err */
-	if (!qca8k_cled_hw_control_status(ldev))
+	if (!qca8k_led_hw_control_status(priv, port_num, led_num))
 		return -EINVAL;
 
-	qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
+	qca8k_get_control_led_reg(port_num, led_num, &reg_info);
 
 	ret = regmap_read(priv->regmap, reg_info.reg, &val);
 	if (ret)
@@ -346,134 +294,3 @@  qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
 
 	return 0;
 }
-
-static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev)
-{
-	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
-	struct qca8k_priv *priv = led->priv;
-	struct dsa_port *dp;
-
-	dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num));
-	if (!dp)
-		return NULL;
-	if (dp->user)
-		return &dp->user->dev;
-	return NULL;
-}
-
-static int
-qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
-{
-	struct fwnode_handle *led = NULL, *leds = NULL;
-	struct led_init_data init_data = { };
-	struct dsa_switch *ds = priv->ds;
-	enum led_default_state state;
-	struct qca8k_led *port_led;
-	int led_num, led_index;
-	int ret;
-
-	leds = fwnode_get_named_child_node(port, "leds");
-	if (!leds) {
-		dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n",
-			port_num);
-		return 0;
-	}
-
-	fwnode_for_each_child_node(leds, led) {
-		/* Reg represent the led number of the port.
-		 * Each port can have at most 3 leds attached
-		 * Commonly:
-		 * 1. is gigabit led
-		 * 2. is mbit led
-		 * 3. additional status led
-		 */
-		if (fwnode_property_read_u32(led, "reg", &led_num))
-			continue;
-
-		if (led_num >= QCA8K_LED_PORT_COUNT) {
-			dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
-				 led_num, port_num);
-			continue;
-		}
-
-		led_index = QCA8K_LED_PORT_INDEX(port_num, led_num);
-
-		port_led = &priv->ports_led[led_index];
-		port_led->port_num = port_num;
-		port_led->led_num = led_num;
-		port_led->priv = priv;
-
-		state = led_init_default_state_get(led);
-		switch (state) {
-		case LEDS_DEFSTATE_ON:
-			port_led->cdev.brightness = 1;
-			qca8k_led_brightness_set(port_led, 1);
-			break;
-		case LEDS_DEFSTATE_KEEP:
-			port_led->cdev.brightness =
-					qca8k_led_brightness_get(port_led);
-			break;
-		default:
-			port_led->cdev.brightness = 0;
-			qca8k_led_brightness_set(port_led, 0);
-		}
-
-		port_led->cdev.max_brightness = 1;
-		port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
-		port_led->cdev.blink_set = qca8k_cled_blink_set;
-		port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported;
-		port_led->cdev.hw_control_set = qca8k_cled_hw_control_set;
-		port_led->cdev.hw_control_get = qca8k_cled_hw_control_get;
-		port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device;
-		port_led->cdev.hw_control_trigger = "netdev";
-		init_data.default_label = ":port";
-		init_data.fwnode = led;
-		init_data.devname_mandatory = true;
-		init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d", ds->user_mii_bus->id,
-						 port_num);
-		if (!init_data.devicename)
-			return -ENOMEM;
-
-		ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data);
-		if (ret)
-			dev_warn(priv->dev, "Failed to init LED %d for port %d", led_num, port_num);
-
-		kfree(init_data.devicename);
-	}
-
-	return 0;
-}
-
-int
-qca8k_setup_led_ctrl(struct qca8k_priv *priv)
-{
-	struct fwnode_handle *ports, *port;
-	int port_num;
-	int ret;
-
-	ports = device_get_named_child_node(priv->dev, "ports");
-	if (!ports) {
-		dev_info(priv->dev, "No ports node specified in device tree!");
-		return 0;
-	}
-
-	fwnode_for_each_child_node(ports, port) {
-		if (fwnode_property_read_u32(port, "reg", &port_num))
-			continue;
-
-		/* Skip checking for CPU port 0 and CPU port 6 as not supported */
-		if (port_num == 0 || port_num == 6)
-			continue;
-
-		/* Each port can have at most 3 different leds attached.
-		 * Switch port starts from 0 to 6, but port 0 and 6 are CPU
-		 * port. The port index needs to be decreased by one to identify
-		 * the correct port for LED setup.
-		 */
-		ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num));
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h
index 2ac7e88f8da5..bf0f78f5390d 100644
--- a/drivers/net/dsa/qca/qca8k.h
+++ b/drivers/net/dsa/qca/qca8k.h
@@ -433,14 +433,6 @@  struct qca8k_led_pattern_en {
 	u8 shift;
 };
 
-struct qca8k_led {
-	u8 port_num;
-	u8 led_num;
-	u16 old_rule;
-	struct qca8k_priv *priv;
-	struct led_classdev cdev;
-};
-
 struct qca8k_priv {
 	u8 switch_id;
 	u8 switch_revision;
@@ -465,7 +457,6 @@  struct qca8k_priv {
 	struct qca8k_pcs pcs_port_0;
 	struct qca8k_pcs pcs_port_6;
 	const struct qca8k_match_data *info;
-	struct qca8k_led ports_led[QCA8K_LED_COUNT];
 };
 
 struct qca8k_mib_desc {
diff --git a/drivers/net/dsa/qca/qca8k_leds.h b/drivers/net/dsa/qca/qca8k_leds.h
index ab367f05b173..1c020d0f2fdc 100644
--- a/drivers/net/dsa/qca/qca8k_leds.h
+++ b/drivers/net/dsa/qca/qca8k_leds.h
@@ -5,12 +5,17 @@ 
 
 /* Leds Support function */
 #ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT
-int qca8k_setup_led_ctrl(struct qca8k_priv *priv);
-#else
-static inline int qca8k_setup_led_ctrl(struct qca8k_priv *priv)
-{
-	return 0;
-}
-#endif
-
+int qca8k_led_brightness_set(struct dsa_switch *ds, int port_num,
+			     u8 led_num, enum led_brightness brightness);
+int qca8k_led_blink_set(struct dsa_switch *ds, int port_num, u8 led_num,
+			unsigned long *delay_on,
+			unsigned long *delay_off);
+int qca8k_led_hw_control_is_supported(struct dsa_switch *ds,
+				      int port, u8 led,
+				      unsigned long rules);
+int qca8k_led_hw_control_set(struct dsa_switch *ds, int port_num, u8 led_num,
+			     unsigned long rules);
+int qca8k_led_hw_control_get(struct dsa_switch *ds, int port_num, u8 led_num,
+			     unsigned long *rules);
+#endif /* CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT */
 #endif /* __QCA8K_LEDS_H */