[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210930125747.2511954-1-frieder@fris.de>
Date: Thu, 30 Sep 2021 14:57:43 +0200
From: Frieder Schrempf <frieder@...s.de>
To: Andrew Lunn <andrew@...n.ch>,
"David S. Miller" <davem@...emloft.net>,
Heiner Kallweit <hkallweit1@...il.com>,
Jakub Kicinski <kuba@...nel.org>, linux-kernel@...r.kernel.org,
netdev@...r.kernel.org
Cc: Frieder Schrempf <frieder.schrempf@...tron.de>,
Bjarni Jonasson <bjarni.jonasson@...rochip.com>,
Ioana Ciornei <ioana.ciornei@....com>,
Russell King <linux@...linux.org.uk>,
Steen Hegelund <steen.hegelund@...rochip.com>
Subject: [PATCH 1/3] net: phy: mscc: Add possibilty to disable combined LED mode
From: Frieder Schrempf <frieder.schrempf@...tron.de>
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@...tron.de>
---
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
Powered by blists - more mailing lists