From nobody Mon Feb 9 07:26:12 2026 Received: from mail-pf1-f172.google.com (mail-pf1-f172.google.com [209.85.210.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C9B230C60B for ; Fri, 7 Nov 2025 20:12:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762546377; cv=none; b=Y9YhfynZb/ELTRIYWxfhDxs65T3GvDUatKxo2YasclrJiHAru7uy5XetEeUtqlf0JfFVBQp209Js4SECh46qH+WRHDMS0fkipEcXUFF+67mLkzn+VSuBJejPQIL/bIY/eIq9+8wIjbi/GSC94NJVGCeGks5Ao6Z+OUW6y9bNy6s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762546377; c=relaxed/simple; bh=v8yHUl2VCCuFa3tLr/Bqru4Xwe8KeevfdbbJgX94SXE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XAQGMcImwXKf30LbNgKFifxNtkcF0qJuKDs6nscOduPS48N9gC4Xu+RWIJpHi4P3MmKzWSp+19KSVVSJDPJmEITVf4sDUt+yacohIot2k2icvQtyf6ETneM1KrJ78leyTARx5S7f3EAyFlbFEa3ZXkX/6NXx+RXnXT336QdxWG0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=THw0g3s9; arc=none smtp.client-ip=209.85.210.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="THw0g3s9" Received: by mail-pf1-f172.google.com with SMTP id d2e1a72fcca58-7acd9a03ba9so972189b3a.1 for ; Fri, 07 Nov 2025 12:12:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762546375; x=1763151175; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+2jIm/CZCkZaBbDnD9nBZsgOURxlF1+5kGMORETVnug=; b=THw0g3s9UQva+8taWcK6ba8UJMs1DBvHYodryLlafUTTYVlRjvXFotDRAYOFQqqrMN o07BobtetTsBgomyv0rTGFj10qRzehQhgjx4WuidbnpnuHpVs5DgLILTAJN1yaUME6Qz 3odAEfZt0QaZlfDMsBffUw1VaxFWUhSfI8gQYXIct8w90k77lVKfpyjL3ARFZoVI8hVO 5P+FgtDt5eVg6fxGZPpAJA/OX3UKPLA1X9ATCPixKjLa3TfiLue2yopk23DwUdBlLMlW 5sZN+X6NfD6p9Xdb21GdPcnDNZJhRH5XxrFkVLvpEQjfbmevtWdxcv4TI3uzfLXojGnk IfRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762546375; x=1763151175; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=+2jIm/CZCkZaBbDnD9nBZsgOURxlF1+5kGMORETVnug=; b=uDWU55krZhIQXM7nboDqq+2nb/JYkqmMUqfz+j5KjnCfPJGhy5osg8d4bTPqc88+be jYaRz3c6OQ29ZFVhVGtQZiU2IbsY1Wnec6RTousEVvPvN0KhVVnYb6g5qkgVvnhZMSn5 Ie6Q2eTRybnVHDmF4Jyi1OFcxQr6jsh3lw78W1O7riq4IiErhFzT3RIykof8HdgJqocj O6l7jK49FyJnS3VI3dFPSf8TErZka5/mIT4A/5ADHK9rCJRw/IBsggsB1mOKcyrAy7Gv cRvxPW/D7Xx3vfFYpWywv/44ZGGhqlvNBZeSj5JVuVdxi4xL+y9tKFE+qeRfZ6eOeE+5 Ksow== X-Forwarded-Encrypted: i=1; AJvYcCWhj30lO/gZa8M8pgQCYKUfpiPSrEhlKg37CAgEE7+21yqutRosewMr8e3YtNT1S4VbOwXlkbJfG8jhAH0=@vger.kernel.org X-Gm-Message-State: AOJu0YxnknyWpUbBLx67rVvlRQz2/JxcZLP6f95JJ1pTx6se1fQ57BH5 4Jy2gFfFaj1QAkkYjpoqgtpiK1GcO/Kqy2JU0oB7666lqBUr1J4DM4ZY X-Gm-Gg: ASbGncvjZMrKjPC+kdkvuto74nrAvUaqw+pfJ3FGQaigU1upx+I25AAzv0XJUDEbMMO s6UIVma06X5NuBL6CVoMQwos3w56cn3FeYiS41a+3g6LdXhVVq3CfyPxSt9n3ETI6xkYfJk1BjI 9RNJ+KviMmr5MHD+WnZysPOJfJWStLdAvDbafBkDWaeCMQXEXcnJfmTKFIad18s2MgGbRQ4nhuR dVzeqediS+uMyeSOfi7iD8qLucXUsTL0k2zPkE1zNb+Tloc7dU+xc1THuudYgpjYZJNJ2hIZVRP 9nu9pw/ndakqXGRWQFJo/91Vxvmss/kcZvD25slJH7b68fbrjsyj1y4m/J86/mBpI7Etq4aEZgP KSZKFRsFNcpgcdCw9nuzgDzM3ndIM9Fz02q+h9rHwhX5ZlZtIPLnxbVNgGRv2ukjs6bnB1vZwA4 KR9MQcbUfX5d4xH1OuFZEHaA== X-Google-Smtp-Source: AGHT+IH8khfZJBhTJpXLTO5Gb4RSM+k9uIEQChjCn5mDLXBQUnyR83c66GjH4StNfJo9F5kUwk9slw== X-Received: by 2002:a05:6a00:1892:b0:7ac:6c3e:e918 with SMTP id d2e1a72fcca58-7b225b50453mr562311b3a.11.1762546374902; Fri, 07 Nov 2025 12:12:54 -0800 (PST) Received: from iku.. ([2401:4900:1c07:5fe8:9724:b1da:3d06:ab48]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7b0cc17784bsm3828553b3a.47.2025.11.07.12.12.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Nov 2025 12:12:54 -0800 (PST) From: Prabhakar X-Google-Original-From: Prabhakar To: Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Horatiu Vultur , Geert Uytterhoeven , Vladimir Oltean , Vadim Fedorenko , Maxime Chevallier Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Prabhakar , Biju Das , Fabrizio Castro , Lad Prabhakar Subject: [PATCH net-next v2 1/3] net: phy: mscc: Simplify LED mode update using phy_modify() Date: Fri, 7 Nov 2025 20:12:30 +0000 Message-ID: <20251107201232.282152-2-prabhakar.mahadev-lad.rj@bp.renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251107201232.282152-1-prabhakar.mahadev-lad.rj@bp.renesas.com> References: <20251107201232.282152-1-prabhakar.mahadev-lad.rj@bp.renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Lad Prabhakar The vsc85xx_led_cntl_set() function currently performs a manual read-modify-write sequence protected by the PHY lock to update the LED mode register (MSCC_PHY_LED_MODE_SEL). Replace this sequence with a call to phy_modify(), which already handles read-modify-write operations with proper locking inside the PHY core. Signed-off-by: Lad Prabhakar Reviewed-by: Andrew Lunn --- v1->v2: - New patch --- drivers/net/phy/mscc/mscc_main.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_m= ain.c index 8678ebf89cca..032050ec0bc9 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -177,17 +177,10 @@ static int vsc85xx_led_cntl_set(struct phy_device *ph= ydev, u8 led_num, u8 mode) { - int rc; - u16 reg_val; - - mutex_lock(&phydev->lock); - reg_val =3D phy_read(phydev, MSCC_PHY_LED_MODE_SEL); - reg_val &=3D ~LED_MODE_SEL_MASK(led_num); - reg_val |=3D LED_MODE_SEL(led_num, (u16)mode); - rc =3D phy_write(phydev, MSCC_PHY_LED_MODE_SEL, reg_val); - mutex_unlock(&phydev->lock); + u16 mask =3D LED_MODE_SEL_MASK(led_num); + u16 val =3D LED_MODE_SEL(led_num, mode); =20 - return rc; + return phy_modify(phydev, MSCC_PHY_LED_MODE_SEL, mask, val); } =20 static int vsc85xx_mdix_get(struct phy_device *phydev, u8 *mdix) --=20 2.43.0 From nobody Mon Feb 9 07:26:12 2026 Received: from mail-pf1-f181.google.com (mail-pf1-f181.google.com [209.85.210.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B575320391 for ; Fri, 7 Nov 2025 20:13:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762546384; cv=none; b=FdAiFQ7vY+NLCdNnT2zi61kEmtLGIUbRiuh8tobtvmIG+t8W3oUDT5mFQcyGTRLEi9SodupcEHLbEfNsAA0xV4m9bLMctN+BT+8dDguVYMQbEt3U5wDgjaJGGAaVS1T9aOj0nF5WqXeqTJhYqGJTa1R/1R3Q3aM36GsW32miBIE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762546384; c=relaxed/simple; bh=OJO2xSgxar2IxgfmRA7vKrNBBYE2vrWHFsE1Ua95Rbw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jo6DFolzSj3iej/8mcBkaXHKheArtc5Nbhzy4aosmGSlR7Su8f7XuoZvNTJq1UC+hUHc0rwoMFafhBelpA++Z/WHPuQp94T8ezgpZ+KWlZO9WY+GqOfKQ0QiLFHK2OYqT0pgquURdgQRLzk8PknG6cDglBslY+Is02wFURE+VVE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=l5yxZYMW; arc=none smtp.client-ip=209.85.210.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="l5yxZYMW" Received: by mail-pf1-f181.google.com with SMTP id d2e1a72fcca58-7afd7789ccdso1165693b3a.2 for ; Fri, 07 Nov 2025 12:13:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762546381; x=1763151181; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7WSv8Aw/7fkJYwtWG+mu3XdUcZ3be7F0tZpqyDku934=; b=l5yxZYMWjOJ7021+gKorLrYXTsSmD9ZQQtHwPLMddB5DkCXsXy6m8ekWZ/Axyq7iN/ XBikO4aXvLtCinLi46T2fPE6g6pK1cmdqkpLgvnLMJ93TAIKm4w/RjtqUoJZwPizbGvO hLLpdWZ0989s9ZMsb32DpyVK82FF0i2Enn3piD4ZSjyR+W935uOjMv3eTJxy+UqpFZlh 1C5gfNOm35qzYgkxXIgtkPx73MHBhcH9H2rFUxYsb/zafv3r3+9CQRBEkXmGEYvvqbvh fYW4Jn5IEax2NqNisa+2bq9XK0VX9GWE3yclot106Q5pGDY2gJOIopwNm2IQf93X6Ujb 038A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762546381; x=1763151181; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=7WSv8Aw/7fkJYwtWG+mu3XdUcZ3be7F0tZpqyDku934=; b=EAb78FzHrEjsGIG4W2smvyeB9enDanZgLcDZa2IOf7rA3mQghoZZ23hXyafeBzS0Fh p1bNv4ZjxjalFHALBxmhl5Fy7Iw4mbqjsH0J50hakjD3Q0bT/rbadMK2I5foc79YatIe nsqjI3gkmEbtijvDn5fwgLsmxw8v8ndwgqUP8UCRJJ8SlSwSVP1z5b33aYLTBIzzFJ9I i1WhZoiUg3AhPz7fNMx6ACpUX6lUJcuRay+RG5oaDT0qv2HMpwX9ghpBmonPv385bcdz F8kByH5uUPKwiD5tGXWUr45w/MLUBYZ8m+6U3GHDdR2tbtrAXvSVrHBW0a3kqoKNOclU OgCQ== X-Forwarded-Encrypted: i=1; AJvYcCU9MTYaNlWNQr5MF7dUkzSSShFaoZt3DO8RJnRN3m5H3eJQyRL0B+q8j7p7XiWZ1lDt6uLBRxq2dJQP+C4=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/eR1QheK4FT4Vm2EsCg6NNIyqHyoKRY+WiH4X3JnKJGFoXk1c a/guOZRK0UDA818mZJ620+OkVY/wqpPxJNQTJBY6rDQxWNgonNw5/VaL X-Gm-Gg: ASbGncsy1SsKKdmE6WVbuncVGz0giurjkx3zPJKPHLxY0L5rRP02MnL6Bb1JJPF7SBG v8yiM5ADTSw9neS7WZKG9wKuZH52RZ6Bo+OT6PgZDth3INFWk3sRvIg8qPInx0L+W6N7kodisOc LjmtL9+nJJ0GGdyB43oLgTqGfk4ohIBjoI2RXR6BNHifw0fCUuSG7Fh+bHWUoBGn5YchkkzP7b5 tE/Y3iy5HNSREbkcLLr+77Tjwocm+dtxXnbojKiYRrV40hEXOCqJHak6Kd8NziDMyxqfnxeJXV4 xsqcBH+Ct9LiYUWZnqw9wUjYLE+I7LyA3oCG9GlNxuDFngJlu12iowDG6cMXAaz8G9EfeqTuz+N /1cmOqXwqGq4acgTSxLCLqf6xHQItIQ3XJ1uzSXn27MdRUAxCibrnVVIFsxY4R1B+u/83oBLfzr Cmq11SGp/hqNUwa2ehC20cxg== X-Google-Smtp-Source: AGHT+IE+5yFYqM5mDxRsnnBXUa+vUiRM7ZVmLo9HA3291G0opu0viMVqZfKTydYEwq5VYS1zEOjqKA== X-Received: by 2002:a05:6a21:3298:b0:342:15d3:eed8 with SMTP id adf61e73a8af0-353a426f0a6mr417893637.58.1762546381442; Fri, 07 Nov 2025 12:13:01 -0800 (PST) Received: from iku.. ([2401:4900:1c07:5fe8:9724:b1da:3d06:ab48]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7b0cc17784bsm3828553b3a.47.2025.11.07.12.12.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Nov 2025 12:13:00 -0800 (PST) From: Prabhakar X-Google-Original-From: Prabhakar To: Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Horatiu Vultur , Geert Uytterhoeven , Vladimir Oltean , Vadim Fedorenko , Maxime Chevallier Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Prabhakar , Biju Das , Fabrizio Castro , Lad Prabhakar Subject: [PATCH net-next v2 2/3] net: phy: mscc: Consolidate probe functions into a common helper Date: Fri, 7 Nov 2025 20:12:31 +0000 Message-ID: <20251107201232.282152-3-prabhakar.mahadev-lad.rj@bp.renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251107201232.282152-1-prabhakar.mahadev-lad.rj@bp.renesas.com> References: <20251107201232.282152-1-prabhakar.mahadev-lad.rj@bp.renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Lad Prabhakar Unify the probe implementations of the VSC85xx PHY family into a single vsc85xx_probe_common() helper. The existing probe functions for the vsc85xx, vsc8514, vsc8574, and vsc8584 variants contained almost identical initialization logic, differing only in configuration parameters such as the number of LEDs, supported LED modes, hardware statistics, and PTP support. Introduce a vsc85xx_probe_config structure to describe the per-variant parameters, and move all common setup code into the shared helper. Each variant's probe function now defines a constant configuration instance and calls vsc85xx_probe_common(). Also mark the default LED mode array parameter as const to match its usage. Signed-off-by: Lad Prabhakar --- v1->v2: - New patch --- drivers/net/phy/mscc/mscc_main.c | 205 ++++++++++++++++--------------- 1 file changed, 109 insertions(+), 96 deletions(-) diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_m= ain.c index 032050ec0bc9..788344b7eb38 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -22,6 +22,24 @@ #include "mscc_serdes.h" #include "mscc.h" =20 +struct vsc85xx_probe_config { + const struct vsc85xx_hw_stat *hw_stats; + u8 nleds; + u16 supp_led_modes; + size_t nstats; + bool use_package; + size_t shared_size; + bool has_ptp; + bool check_rate_magic; +}; + +static const u32 vsc85xx_default_led_modes_4[] =3D { + VSC8531_LINK_1000_ACTIVITY, + VSC8531_LINK_100_ACTIVITY, + VSC8531_LINK_ACTIVITY, + VSC8531_DUPLEX_COLLISION +}; + static const struct vsc85xx_hw_stat vsc85xx_hw_stats[] =3D { { .string =3D "phy_receive_errors", @@ -436,7 +454,7 @@ static int vsc85xx_dt_led_mode_get(struct phy_device *p= hydev, #endif /* CONFIG_OF_MDIO */ =20 static int vsc85xx_dt_led_modes_get(struct phy_device *phydev, - u32 *default_mode) + const u32 *default_mode) { struct vsc8531_private *priv =3D phydev->priv; char led_dt_prop[28]; @@ -2211,41 +2229,19 @@ static int vsc85xx_config_inband(struct phy_device = *phydev, unsigned int modes) reg_val); } =20 -static int vsc8514_probe(struct phy_device *phydev) +static int vsc85xx_probe_common(struct phy_device *phydev, + const struct vsc85xx_probe_config *cfg, + const u32 *default_led_mode) { struct vsc8531_private *vsc8531; - u32 default_mode[4] =3D {VSC8531_LINK_1000_ACTIVITY, - VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY, - VSC8531_DUPLEX_COLLISION}; - - vsc8531 =3D devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); - if (!vsc8531) - return -ENOMEM; - - phydev->priv =3D vsc8531; - - vsc8584_get_base_addr(phydev); - devm_phy_package_join(&phydev->mdio.dev, phydev, - vsc8531->base_addr, 0); - - vsc8531->nleds =3D 4; - vsc8531->supp_led_modes =3D VSC85XX_SUPP_LED_MODES; - vsc8531->hw_stats =3D vsc85xx_hw_stats; - vsc8531->nstats =3D ARRAY_SIZE(vsc85xx_hw_stats); - vsc8531->stats =3D devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats, - sizeof(u64), GFP_KERNEL); - if (!vsc8531->stats) - return -ENOMEM; - - return vsc85xx_dt_led_modes_get(phydev, default_mode); -} + int ret; =20 -static int vsc8574_probe(struct phy_device *phydev) -{ - struct vsc8531_private *vsc8531; - u32 default_mode[4] =3D {VSC8531_LINK_1000_ACTIVITY, - VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY, - VSC8531_DUPLEX_COLLISION}; + /* Check rate magic if needed (only for non-package PHYs) */ + if (cfg->check_rate_magic) { + ret =3D vsc85xx_edge_rate_magic_get(phydev); + if (ret < 0) + return ret; + } =20 vsc8531 =3D devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); if (!vsc8531) @@ -2253,90 +2249,107 @@ static int vsc8574_probe(struct phy_device *phydev) =20 phydev->priv =3D vsc8531; =20 - vsc8584_get_base_addr(phydev); - devm_phy_package_join(&phydev->mdio.dev, phydev, - vsc8531->base_addr, 0); - - vsc8531->nleds =3D 4; - vsc8531->supp_led_modes =3D VSC8584_SUPP_LED_MODES; - vsc8531->hw_stats =3D vsc8584_hw_stats; - vsc8531->nstats =3D ARRAY_SIZE(vsc8584_hw_stats); - vsc8531->stats =3D devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats, - sizeof(u64), GFP_KERNEL); - if (!vsc8531->stats) - return -ENOMEM; - - return vsc85xx_dt_led_modes_get(phydev, default_mode); -} - -static int vsc8584_probe(struct phy_device *phydev) -{ - struct vsc8531_private *vsc8531; - u32 default_mode[4] =3D {VSC8531_LINK_1000_ACTIVITY, - VSC8531_LINK_100_ACTIVITY, VSC8531_LINK_ACTIVITY, - VSC8531_DUPLEX_COLLISION}; - int ret; - - vsc8531 =3D devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); - if (!vsc8531) - return -ENOMEM; + /* Store rate magic if it was checked */ + if (cfg->check_rate_magic) + vsc8531->rate_magic =3D ret; =20 - phydev->priv =3D vsc8531; + /* Set up package if needed */ + if (cfg->use_package) { + vsc8584_get_base_addr(phydev); + devm_phy_package_join(&phydev->mdio.dev, phydev, + vsc8531->base_addr, cfg->shared_size); + } =20 - vsc8584_get_base_addr(phydev); - devm_phy_package_join(&phydev->mdio.dev, phydev, vsc8531->base_addr, - sizeof(struct vsc85xx_shared_private)); + /* Configure LED settings */ + vsc8531->nleds =3D cfg->nleds; + vsc8531->supp_led_modes =3D cfg->supp_led_modes; =20 - vsc8531->nleds =3D 4; - vsc8531->supp_led_modes =3D VSC8584_SUPP_LED_MODES; - vsc8531->hw_stats =3D vsc8584_hw_stats; - vsc8531->nstats =3D ARRAY_SIZE(vsc8584_hw_stats); + /* Configure hardware stats */ + vsc8531->hw_stats =3D cfg->hw_stats; + vsc8531->nstats =3D cfg->nstats; vsc8531->stats =3D devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats, sizeof(u64), GFP_KERNEL); if (!vsc8531->stats) return -ENOMEM; =20 - if (phy_package_probe_once(phydev)) { - ret =3D vsc8584_ptp_probe_once(phydev); + /* PTP setup for VSC8584 */ + if (cfg->has_ptp) { + if (phy_package_probe_once(phydev)) { + ret =3D vsc8584_ptp_probe_once(phydev); + if (ret) + return ret; + } + + ret =3D vsc8584_ptp_probe(phydev); if (ret) return ret; } =20 - ret =3D vsc8584_ptp_probe(phydev); - if (ret) - return ret; + /* Parse LED modes from device tree */ + return vsc85xx_dt_led_modes_get(phydev, default_led_mode); +} =20 - return vsc85xx_dt_led_modes_get(phydev, default_mode); +static int vsc8514_probe(struct phy_device *phydev) +{ + static const struct vsc85xx_probe_config vsc8514_cfg =3D { + .nleds =3D 4, + .supp_led_modes =3D VSC85XX_SUPP_LED_MODES, + .hw_stats =3D vsc85xx_hw_stats, + .nstats =3D ARRAY_SIZE(vsc85xx_hw_stats), + .use_package =3D true, + .shared_size =3D 0, + .has_ptp =3D false, + .check_rate_magic =3D false, + }; + + return vsc85xx_probe_common(phydev, &vsc8514_cfg, vsc85xx_default_led_mod= es_4); } =20 -static int vsc85xx_probe(struct phy_device *phydev) +static int vsc8574_probe(struct phy_device *phydev) { - struct vsc8531_private *vsc8531; - int rate_magic; - u32 default_mode[2] =3D {VSC8531_LINK_1000_ACTIVITY, - VSC8531_LINK_100_ACTIVITY}; + static const struct vsc85xx_probe_config vsc8574_cfg =3D { + .nleds =3D 4, + .supp_led_modes =3D VSC8584_SUPP_LED_MODES, + .hw_stats =3D vsc8584_hw_stats, + .nstats =3D ARRAY_SIZE(vsc8584_hw_stats), + .use_package =3D true, + .shared_size =3D 0, + .has_ptp =3D false, + .check_rate_magic =3D false, + }; =20 - rate_magic =3D vsc85xx_edge_rate_magic_get(phydev); - if (rate_magic < 0) - return rate_magic; + return vsc85xx_probe_common(phydev, &vsc8574_cfg, vsc85xx_default_led_mod= es_4); +} =20 - vsc8531 =3D devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL); - if (!vsc8531) - return -ENOMEM; +static int vsc8584_probe(struct phy_device *phydev) +{ + static const struct vsc85xx_probe_config vsc8584_cfg =3D { + .nleds =3D 4, + .supp_led_modes =3D VSC8584_SUPP_LED_MODES, + .hw_stats =3D vsc8584_hw_stats, + .nstats =3D ARRAY_SIZE(vsc8584_hw_stats), + .use_package =3D true, + .shared_size =3D sizeof(struct vsc85xx_shared_private), + .has_ptp =3D true, + .check_rate_magic =3D false, + }; =20 - phydev->priv =3D vsc8531; + return vsc85xx_probe_common(phydev, &vsc8584_cfg, vsc85xx_default_led_mod= es_4); +} =20 - vsc8531->rate_magic =3D rate_magic; - vsc8531->nleds =3D 2; - vsc8531->supp_led_modes =3D VSC85XX_SUPP_LED_MODES; - vsc8531->hw_stats =3D vsc85xx_hw_stats; - vsc8531->nstats =3D ARRAY_SIZE(vsc85xx_hw_stats); - vsc8531->stats =3D devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats, - sizeof(u64), GFP_KERNEL); - if (!vsc8531->stats) - return -ENOMEM; +static int vsc85xx_probe(struct phy_device *phydev) +{ + static const struct vsc85xx_probe_config vsc85xx_cfg =3D { + .nleds =3D 2, + .supp_led_modes =3D VSC85XX_SUPP_LED_MODES, + .hw_stats =3D vsc85xx_hw_stats, + .nstats =3D ARRAY_SIZE(vsc85xx_hw_stats), + .use_package =3D false, + .has_ptp =3D false, + .check_rate_magic =3D true, + }; =20 - return vsc85xx_dt_led_modes_get(phydev, default_mode); + return vsc85xx_probe_common(phydev, &vsc85xx_cfg, vsc85xx_default_led_mod= es_4); } =20 static void vsc85xx_remove(struct phy_device *phydev) --=20 2.43.0 From nobody Mon Feb 9 07:26:12 2026 Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71A5530DEAD for ; Fri, 7 Nov 2025 20:13:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762546391; cv=none; b=LTQIHaAFBVmuhAWo0lNd9gfLwyYwFlqyH+HHORnkrkrnUjdIvK7cpxJHDYFfAvVlpNzbW7/1HqnyFnNSBF/KuNdrMF02YXVJRrABbtnx0cw8dfHL6NFecndDkxW9f0w0OIck+77Lug/tqGkKLd7fnSevaPuW1Mj74zG8pSAfq1E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762546391; c=relaxed/simple; bh=VeXxys7M6WNFVWFMzdXiinidVLDPeQLbM6MrcPzRPdY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EHU028S/XyxpUiqVoCR9U/PoZQWgpEtNLXBTixp/+gMAb6iguXqpx/ptTdgDD+S6gDwSdRRJaj/LtULkqf8rZeOGNON324NYg0d7JSnCbm3zf3c607QbbJPba+E+AwHG7hYmoDPyFIAi1iDFa7FBPWH0RCxwN3Qx/c1L2kV+la4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=m+E6OKr+; arc=none smtp.client-ip=209.85.210.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="m+E6OKr+" Received: by mail-pf1-f177.google.com with SMTP id d2e1a72fcca58-7afd7789ccdso1165773b3a.2 for ; Fri, 07 Nov 2025 12:13:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762546388; x=1763151188; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gUHXoobgkPy98MRo13yjlOPEv6tlNuTLwaeoWTXAfig=; b=m+E6OKr+pBbrSGROtFAhy3Ok3JFca24Z1XEIHaftxy84ntnr+jC36kBvM+UgHgIezG gY28InMEkhK0nTQT5dFIl2Kn+7kUjlhv42KYtj6Ho+zAdrisnfeqI73Br5IGvPVqvSX4 L7s++ozN8myAA39Dyc73gp9va8Q8iIS8SJLpU1ZzF5VPwPn8525iYPnSyzeOo62WlQFY 0tkkwCSPS2oX0hNWq3jFMTT8PxqzQEEEsFZpoF0eRqG5JdszoGMxmHLF9mFsKj+KpkYP tRLuEg90kXQEJnzub8bhkOA54F83ZBGUBPQCurgxzH+quCDonV6mrNIA+l6YDOvKxiur QKMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762546388; x=1763151188; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=gUHXoobgkPy98MRo13yjlOPEv6tlNuTLwaeoWTXAfig=; b=LpQ6odDeRn9y5YRvV8ht8sQ+AeaisaBBpkHwaYueyzEw/ghRPhNqZlpHo+8BYKtXiK USkqZgZHBFHpksou3NzaVO/gxXhRs3QEs2qMQR5Rb4i5Kp1JM1JDQr27tTVMmAsQKiJB Btj9WaMhhHv4nKIN4lQXFInS8xw+HQifzziIGvkhHRep2f9ZPxbO1XJrid9E/AdRZ9no cy2NOjUuz/A3ONjsZFHiBfoBzr7R5YRyLhMDK98HrXBWlxgtzIXArwJBF8AAOmw9ZhP9 hL4so6C6uakusnzOtVoDtMhpp++vjmhPU9EO/brJABFg28T2IkGneTJe6FevIqa7ct5l 9uvg== X-Forwarded-Encrypted: i=1; AJvYcCVCAZd9kuSAsuofgxFfUqF/PBM9Ll64YiQM/jBQHFhNVvZeFOZu7vgnwd1fR33wAnWwivsRbreXUsZysJ4=@vger.kernel.org X-Gm-Message-State: AOJu0YxAZz9on0d8kaUpZnrp7cb1pqrmb9jAWBh7KvhX/fXQ5k4zI6Gu d5tfFcLNf+kMvXOq3Os4wyws9b+HLnrNQZUu6grN84D4fpBEVocZlWha X-Gm-Gg: ASbGncsobve2RHVX+CxTnMBU/fSYW1EqW8hNry+uY+X2WkeTdfVhkmKApNQGbTG5VRh t99tZ7I7qWxLfRizi5YVHMBDUCs/n0oJ5RJAQZUrpRNp8j1kCc4Y+yoXkzBEQis0KiS6ayolP9O ZWNxlJlWn275GeKvUeDrVCwIS6vzgp2dOtWrNBsVusrZJfgDHDSvf+PhvBil4gs1v9Yr+a03vOf xuBCdL4zjO1t3eYF8kcsATkkSOajdVJHOM7a9X6lSALaLpIMS3O19m7QeHQJhs5XtPv0GAHEnFG c/FmfWpM+KAHkEq5zMsema3rTxbhxwp31V26n0Uf9N61ZpF2VFG2u3rZX5hMcZkWd7bM9EcrQnz ql6IsEvRsdtJYBagOZ9urU/AUO23aiD2kzAluOUQL066q2QOb2+16kaodwWjQipZZMf4IllL2mT 9No9ub8M3sZY9b0RZLTli1rg== X-Google-Smtp-Source: AGHT+IHwObHoVf6Gov0hlem78+t1JM6KaFPQCh/l+JXUg2EE7397e/1bJ/JWHYsVMex4bJf06v2npA== X-Received: by 2002:a05:6a21:e097:b0:33e:561b:fb22 with SMTP id adf61e73a8af0-353a405e5f5mr475309637.50.1762546388215; Fri, 07 Nov 2025 12:13:08 -0800 (PST) Received: from iku.. ([2401:4900:1c07:5fe8:9724:b1da:3d06:ab48]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7b0cc17784bsm3828553b3a.47.2025.11.07.12.13.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Nov 2025 12:13:07 -0800 (PST) From: Prabhakar X-Google-Original-From: Prabhakar To: Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Horatiu Vultur , Geert Uytterhoeven , Vladimir Oltean , Vadim Fedorenko , Maxime Chevallier Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Prabhakar , Biju Das , Fabrizio Castro , Lad Prabhakar Subject: [PATCH net-next v2 3/3] net: phy: mscc: Add support for PHY LED control Date: Fri, 7 Nov 2025 20:12:32 +0000 Message-ID: <20251107201232.282152-4-prabhakar.mahadev-lad.rj@bp.renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251107201232.282152-1-prabhakar.mahadev-lad.rj@bp.renesas.com> References: <20251107201232.282152-1-prabhakar.mahadev-lad.rj@bp.renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Lad Prabhakar Add support for the PHY LED controller in the MSCC VSC85xx driver. The implementation provides LED brightness and hardware control through the LED subsystem and integrates with the standard 'netdev' trigger. Introduce new register definitions for the LED behavior register (MSCC_PHY_LED_BEHAVIOR =3D 30) and the LED combine disable bits, which control whether LEDs indicate link-only or combined link and activity status. Implement a helper, vsc8541_led_combine_disable_set(), to update these bits safely using phy_modify(). Add support for LED brightness control and hardware mode configuration. The new callbacks implement the standard LED class operations, allowing user control through sysfs. The brightness control maps to PHY LED force on/off modes. The hardware control get and set functions translate between the PHY-specific LED mode encodings and the LED subsystem TRIGGER_NETDEV_* rules. The combine feature is managed automatically based on the selected rules. When both RX and TX activity are disabled, the combine feature is turned off, causing LEDs to indicate link-only status. When either RX or TX activity is enabled, the combine feature remains active and LEDs indicate combined link and activity. Register the LED callbacks for all VSC85xx PHY variants so that the LED subsystem can manage their indicators consistently. Existing device tree LED configuration and default behavior are preserved. Signed-off-by: Lad Prabhakar Reviewed-by: Andrew Lunn --- v1->v2: - Added LED control support to all VSC85xx PHY variants. - Renamed led callbacks to vsc85xx_* for consistency. - Defaulted the LEDs on probe to the default array before parsing DT. - Used phy_modify() in vsc85xx_led_brightness_set() - Return value of phy_read() checked in vsc85xx_led_hw_control_get() - Reverse Christmas tree in vsc85xx_led_hw_is_supported() - Updated the commit message to clarify the LED combine feature behavior. --- drivers/net/phy/mscc/mscc.h | 4 + drivers/net/phy/mscc/mscc_main.c | 246 +++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 2eef5956b9cc..65c9d7bd9315 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -85,6 +85,10 @@ enum rgmii_clock_delay { #define LED_MODE_SEL_MASK(x) (GENMASK(3, 0) << LED_MODE_SEL_POS(x)) #define LED_MODE_SEL(x, mode) (((mode) << LED_MODE_SEL_POS(x)) & LED_MO= DE_SEL_MASK(x)) =20 +#define MSCC_PHY_LED_BEHAVIOR 30 +#define LED_COMBINE_DIS_MASK(x) BIT(x) +#define LED_COMBINE_DIS(x, dis) (((dis) ? 1 : 0) << (x)) + #define MSCC_EXT_PAGE_CSR_CNTL_17 17 #define MSCC_EXT_PAGE_CSR_CNTL_18 18 =20 diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_m= ain.c index 788344b7eb38..550671fba8b6 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -201,6 +201,15 @@ static int vsc85xx_led_cntl_set(struct phy_device *phy= dev, return phy_modify(phydev, MSCC_PHY_LED_MODE_SEL, mask, val); } =20 +static int vsc85xx_led_combine_disable_set(struct phy_device *phydev, + u8 led_num, bool combine_disable) +{ + u16 mask =3D LED_COMBINE_DIS_MASK(led_num); + u16 val =3D LED_COMBINE_DIS(led_num, combine_disable); + + return phy_modify(phydev, MSCC_PHY_LED_BEHAVIOR, mask, val); +} + static int vsc85xx_mdix_get(struct phy_device *phydev, u8 *mdix) { u16 reg_val; @@ -2234,6 +2243,7 @@ static int vsc85xx_probe_common(struct phy_device *ph= ydev, const u32 *default_led_mode) { struct vsc8531_private *vsc8531; + struct device_node *np; int ret; =20 /* Check rate magic if needed (only for non-package PHYs) */ @@ -2285,10 +2295,186 @@ static int vsc85xx_probe_common(struct phy_device = *phydev, return ret; } =20 + /* + * Check for LED configuration in device tree if available + * or fall back to default `vsc8531,led-x-mode` DT properties. + */ + np =3D of_get_child_by_name(phydev->mdio.dev.of_node, "leds"); + if (np) { + of_node_put(np); + + /* Force to defaults */ + for (unsigned int i =3D 0; i < vsc8531->nleds; i++) + vsc8531->leds_mode[i] =3D default_led_mode[i]; + + return 0; + } + /* Parse LED modes from device tree */ return vsc85xx_dt_led_modes_get(phydev, default_led_mode); } =20 +static int vsc85xx_led_brightness_set(struct phy_device *phydev, + u8 index, enum led_brightness value) +{ + struct vsc8531_private *vsc8531 =3D phydev->priv; + + if (index >=3D vsc8531->nleds) + return -EINVAL; + + return vsc85xx_led_cntl_set(phydev, index, value =3D=3D LED_OFF ? + VSC8531_FORCE_LED_OFF : VSC8531_FORCE_LED_ON); +} + +static int vsc85xx_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + static const unsigned long supported =3D BIT(TRIGGER_NETDEV_LINK_1000) | + BIT(TRIGGER_NETDEV_LINK_100) | + BIT(TRIGGER_NETDEV_LINK_10) | + BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_RX) | + BIT(TRIGGER_NETDEV_TX); + struct vsc8531_private *vsc8531 =3D phydev->priv; + + if (index >=3D vsc8531->nleds) + return -EINVAL; + + if (rules & ~supported) + return -EOPNOTSUPP; + + return 0; +} + +static int vsc85xx_led_hw_control_get(struct phy_device *phydev, u8 index, + unsigned long *rules) +{ + struct vsc8531_private *vsc8531 =3D phydev->priv; + u8 mode, behavior; + int rc; + + if (index >=3D vsc8531->nleds) + return -EINVAL; + + rc =3D phy_read(phydev, MSCC_PHY_LED_MODE_SEL); + if (rc < 0) + return rc; + mode =3D (rc & LED_MODE_SEL_MASK(index)) >> LED_MODE_SEL_POS(index); + + rc =3D phy_read(phydev, MSCC_PHY_LED_BEHAVIOR); + if (rc < 0) + return rc; + behavior =3D (rc & LED_COMBINE_DIS_MASK(index)) >> index; + + switch (mode) { + case VSC8531_LINK_ACTIVITY: + case VSC8531_ACTIVITY: + *rules =3D BIT(TRIGGER_NETDEV_LINK); + break; + + case VSC8531_LINK_1000_ACTIVITY: + *rules =3D BIT(TRIGGER_NETDEV_LINK_1000) | + BIT(TRIGGER_NETDEV_LINK); + break; + + case VSC8531_LINK_100_ACTIVITY: + *rules =3D BIT(TRIGGER_NETDEV_LINK_100) | + BIT(TRIGGER_NETDEV_LINK); + break; + + case VSC8531_LINK_10_ACTIVITY: + *rules =3D BIT(TRIGGER_NETDEV_LINK_10) | + BIT(TRIGGER_NETDEV_LINK); + break; + + case VSC8531_LINK_100_1000_ACTIVITY: + *rules =3D BIT(TRIGGER_NETDEV_LINK_1000) | + BIT(TRIGGER_NETDEV_LINK_100) | + BIT(TRIGGER_NETDEV_LINK); + break; + + case VSC8531_LINK_10_1000_ACTIVITY: + *rules =3D BIT(TRIGGER_NETDEV_LINK_1000) | + BIT(TRIGGER_NETDEV_LINK_10) | + BIT(TRIGGER_NETDEV_LINK); + break; + + case VSC8531_LINK_10_100_ACTIVITY: + *rules =3D BIT(TRIGGER_NETDEV_LINK_100) | + BIT(TRIGGER_NETDEV_LINK_10) | + BIT(TRIGGER_NETDEV_LINK); + break; + + default: + *rules =3D 0; + break; + } + + if (!behavior && *rules) + *rules |=3D BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX); + + return 0; +} + +static int vsc85xx_led_hw_control_set(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + struct vsc8531_private *vsc8531 =3D phydev->priv; + u8 mode =3D VSC8531_FORCE_LED_ON; + bool combine_disable =3D false; + bool has_rx, has_tx; + int ret; + + if (index >=3D vsc8531->nleds) + return -EINVAL; + + if (rules & BIT(TRIGGER_NETDEV_LINK)) + mode =3D VSC8531_LINK_ACTIVITY; + + if (rules & BIT(TRIGGER_NETDEV_LINK_10)) + mode =3D VSC8531_LINK_10_ACTIVITY; + + if (rules & BIT(TRIGGER_NETDEV_LINK_100)) + mode =3D VSC8531_LINK_100_ACTIVITY; + + if (rules & BIT(TRIGGER_NETDEV_LINK_1000)) + mode =3D VSC8531_LINK_1000_ACTIVITY; + + if (rules & BIT(TRIGGER_NETDEV_LINK_100) && + rules & BIT(TRIGGER_NETDEV_LINK_1000)) + mode =3D VSC8531_LINK_100_1000_ACTIVITY; + + if (rules & BIT(TRIGGER_NETDEV_LINK_10) && + rules & BIT(TRIGGER_NETDEV_LINK_1000)) + mode =3D VSC8531_LINK_10_1000_ACTIVITY; + + if (rules & BIT(TRIGGER_NETDEV_LINK_10) && + rules & BIT(TRIGGER_NETDEV_LINK_100)) + mode =3D VSC8531_LINK_10_100_ACTIVITY; + + /* + * The VSC85xx PHYs provides an option to control LED behavior. By + * default, the LEDx combine function is enabled, meaning the LED + * will be on when there is link/activity or duplex/collision. If + * the combine function is disabled, the LED will be on only for + * link or duplex. + * + * To control this behavior, we check the selected rules. If both + * RX and TX activity are not selected, the LED combine function + * is disabled; otherwise, it remains enabled. + */ + has_rx =3D !!(rules & BIT(TRIGGER_NETDEV_RX)); + has_tx =3D !!(rules & BIT(TRIGGER_NETDEV_TX)); + if (!has_rx && !has_tx) + combine_disable =3D true; + + ret =3D vsc85xx_led_combine_disable_set(phydev, index, combine_disable); + if (ret < 0) + return ret; + + return vsc85xx_led_cntl_set(phydev, index, mode); +} + static int vsc8514_probe(struct phy_device *phydev) { static const struct vsc85xx_probe_config vsc8514_cfg =3D { @@ -2382,6 +2568,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_sset_count =3D &vsc85xx_get_sset_count, .get_strings =3D &vsc85xx_get_strings, .get_stats =3D &vsc85xx_get_stats, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8502, @@ -2406,6 +2596,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_sset_count =3D &vsc85xx_get_sset_count, .get_strings =3D &vsc85xx_get_strings, .get_stats =3D &vsc85xx_get_stats, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8504, @@ -2433,6 +2627,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_stats =3D &vsc85xx_get_stats, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8514, @@ -2458,6 +2656,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_stats =3D &vsc85xx_get_stats, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8530, @@ -2482,6 +2684,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_sset_count =3D &vsc85xx_get_sset_count, .get_strings =3D &vsc85xx_get_strings, .get_stats =3D &vsc85xx_get_stats, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8531, @@ -2506,6 +2712,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_sset_count =3D &vsc85xx_get_sset_count, .get_strings =3D &vsc85xx_get_strings, .get_stats =3D &vsc85xx_get_stats, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8540, @@ -2530,6 +2740,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_sset_count =3D &vsc85xx_get_sset_count, .get_strings =3D &vsc85xx_get_strings, .get_stats =3D &vsc85xx_get_stats, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8541, @@ -2554,6 +2768,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_sset_count =3D &vsc85xx_get_sset_count, .get_strings =3D &vsc85xx_get_strings, .get_stats =3D &vsc85xx_get_stats, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8552, @@ -2580,6 +2798,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_stats =3D &vsc85xx_get_stats, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { PHY_ID_MATCH_EXACT(PHY_ID_VSC856X), @@ -2603,6 +2825,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_stats =3D &vsc85xx_get_stats, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8572, @@ -2631,6 +2857,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_stats =3D &vsc85xx_get_stats, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { .phy_id =3D PHY_ID_VSC8574, @@ -2659,6 +2889,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_stats =3D &vsc85xx_get_stats, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { PHY_ID_MATCH_EXACT(PHY_ID_VSC8575), @@ -2684,6 +2918,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_stats =3D &vsc85xx_get_stats, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { PHY_ID_MATCH_EXACT(PHY_ID_VSC8582), @@ -2709,6 +2947,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .get_stats =3D &vsc85xx_get_stats, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, }, { PHY_ID_MATCH_EXACT(PHY_ID_VSC8584), @@ -2735,6 +2977,10 @@ static struct phy_driver vsc85xx_driver[] =3D { .link_change_notify =3D &vsc85xx_link_change_notify, .inband_caps =3D vsc85xx_inband_caps, .config_inband =3D vsc85xx_config_inband, + .led_brightness_set =3D vsc85xx_led_brightness_set, + .led_hw_is_supported =3D vsc85xx_led_hw_is_supported, + .led_hw_control_get =3D vsc85xx_led_hw_control_get, + .led_hw_control_set =3D vsc85xx_led_hw_control_set, } =20 }; --=20 2.43.0