[PATCH 1/3] net: phy: mscc: Add possibilty to disable combined LED mode

From: Frieder Schrempf
Date: Thu Sep 30 2021 - 08:58:20 EST


From: Frieder Schrempf <frieder.schrempf@xxxxxxxxxx>

By default the LED modes offer to combine two indicators like speed/link
and activity in one LED. In order to use a LED only for the first of the
two modes, the combined feature needs to be disabled.

In order to do this we introduce a boolean devicetree property
'vsc8531,led-[N]-combine-disable' and wire it up to the matching
bits in the LED behavior register.

Signed-off-by: Frieder Schrempf <frieder.schrempf@xxxxxxxxxx>
---
drivers/net/phy/mscc/mscc.h | 5 ++++
drivers/net/phy/mscc/mscc_main.c | 47 ++++++++++++++++++++++++++++----
2 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h
index a50235fdf7d9..114b087fc89a 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_MODE_SEL_MASK(x))

+#define MSCC_PHY_LED_BEHAVIOR 30
+#define LED_COMBINE_DIS_MASK(x) (1 << (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

@@ -363,6 +367,7 @@ struct vsc8531_private {
int rate_magic;
u16 supp_led_modes;
u32 leds_mode[MAX_LEDS];
+ bool leds_combine[MAX_LEDS];
u8 nleds;
const struct vsc85xx_hw_stat *hw_stats;
u64 *stats;
diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
index 6e32da28e138..d42723e04c98 100644
--- a/drivers/net/phy/mscc/mscc_main.c
+++ b/drivers/net/phy/mscc/mscc_main.c
@@ -171,7 +171,8 @@ static void vsc85xx_get_stats(struct phy_device *phydev,

static int vsc85xx_led_cntl_set(struct phy_device *phydev,
u8 led_num,
- u8 mode)
+ u8 mode,
+ bool combine_disable)
{
int rc;
u16 reg_val;
@@ -181,6 +182,10 @@ static int vsc85xx_led_cntl_set(struct phy_device *phydev,
reg_val &= ~LED_MODE_SEL_MASK(led_num);
reg_val |= LED_MODE_SEL(led_num, (u16)mode);
rc = phy_write(phydev, MSCC_PHY_LED_MODE_SEL, reg_val);
+ reg_val = phy_read(phydev, MSCC_PHY_LED_BEHAVIOR);
+ reg_val &= ~LED_COMBINE_DIS_MASK(led_num);
+ reg_val |= LED_COMBINE_DIS(led_num, combine_disable);
+ rc = phy_write(phydev, MSCC_PHY_LED_BEHAVIOR, reg_val);
mutex_unlock(&phydev->lock);

return rc;
@@ -432,6 +437,21 @@ static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
return led_mode;
}

+static bool vsc85xx_dt_led_combine_get(struct phy_device *phydev,
+ char *led)
+{
+ struct vsc8531_private *priv = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
+ struct device_node *of_node = dev->of_node;
+ bool led_combine = false;
+ int err;
+
+ if (!of_node)
+ return false;
+
+ return of_property_read_bool(of_node, led);
+}
+
#else
static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
{
@@ -444,13 +464,19 @@ static int vsc85xx_dt_led_mode_get(struct phy_device *phydev,
{
return default_mode;
}
+
+static bool vsc85xx_dt_led_combine_get(struct phy_device *phydev,
+ char *led)
+{
+ return false;
+}
#endif /* CONFIG_OF_MDIO */

static int vsc85xx_dt_led_modes_get(struct phy_device *phydev,
u32 *default_mode)
{
struct vsc8531_private *priv = phydev->priv;
- char led_dt_prop[28];
+ char led_dt_prop[32];
int i, ret;

for (i = 0; i < priv->nleds; i++) {
@@ -463,6 +489,14 @@ static int vsc85xx_dt_led_modes_get(struct phy_device *phydev,
if (ret < 0)
return ret;
priv->leds_mode[i] = ret;
+
+ ret = sprintf(led_dt_prop,
+ "vsc8531,led-%d-combine-disable", i);
+ if (ret < 0)
+ return ret;
+
+ priv->leds_combine[i] =
+ vsc85xx_dt_led_combine_get(phydev, led_dt_prop);
}

return 0;
@@ -1779,7 +1813,8 @@ static int vsc8584_config_init(struct phy_device *phydev)
return ret;

for (i = 0; i < vsc8531->nleds; i++) {
- ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
+ ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i],
+ vsc8531->leds_combine[i]);
if (ret)
return ret;
}
@@ -1846,7 +1881,8 @@ static int vsc85xx_config_init(struct phy_device *phydev)
return rc;

for (i = 0; i < vsc8531->nleds; i++) {
- rc = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
+ rc = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i],
+ vsc8531->leds_combine[i]);
if (rc)
return rc;
}
@@ -2099,7 +2135,8 @@ static int vsc8514_config_init(struct phy_device *phydev)
return ret;

for (i = 0; i < vsc8531->nleds; i++) {
- ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
+ ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i],
+ vsc8531->leds_combine[i]);
if (ret)
return ret;
}
--
2.33.0