DORMANTno replies

[PATCH 2/3] net: phy: dp83867: Add ability to configure LEDs

From: Markus Moll <hidden>
Date: 2020-03-04 10:59:31
Subsystem: ethernet phy library, networking drivers, the rest · Maintainers: Andrew Lunn, Heiner Kallweit, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

The DP83867 PHY has configurable LED outputs. This code adds the
devicetree property ti,led-modes as an array of four LED mode
values corresponding to LED_0 through LED_3. Accepted values can be
found in dt-bindings/net/ti-dp83867.h.

Signed-off-by: Markus Moll <redacted>
---
 drivers/net/phy/dp83867.c | 57 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 13f7f2d5a2e..ddf1ec8390e 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -26,6 +26,7 @@
 #define MII_DP83867_MICR	0x12
 #define MII_DP83867_ISR		0x13
 #define DP83867_CFG2		0x14
+#define DP83867_LEDCR1		0x18
 #define DP83867_CFG3		0x1e
 #define DP83867_CTRL		0x1f
 
@@ -145,6 +146,16 @@
 /* CFG4 bits */
 #define DP83867_CFG4_PORT_MIRROR_EN              BIT(0)
 
+/* LEDCR1 bits */
+#define DP83867_LED_RESERVED			0xC
+#define DP83867_LED_MAX				0xE
+#define DP83867_LED_3_SHIFT			12
+#define DP83867_LED_2_SHIFT			8
+#define DP83867_LED_1_SHIFT			4
+#define DP83867_LED_0_SHIFT			0
+
+#define NUM_LEDS				4
+
 enum {
 	DP83867_PORT_MIRROING_KEEP,
 	DP83867_PORT_MIRROING_EN,
@@ -162,6 +173,7 @@ struct dp83867_private {
 	bool set_clk_output;
 	u32 clk_output_sel;
 	bool sgmii_ref_clk_en;
+	u32 led_modes[NUM_LEDS];
 };
 
 static int dp83867_ack_interrupt(struct phy_device *phydev)
@@ -483,6 +495,30 @@ static int dp83867_verify_rgmii_cfg(struct phy_device *phydev)
 	return 0;
 }
 
+static int dp83867_validate_led_modes(struct phy_device *phydev)
+{
+	struct dp83867_private *dp83867 = phydev->priv;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dp83867->led_modes); i++) {
+		if (dp83867->led_modes[i] == DP83867_LED_RESERVED) {
+			phydev_err(phydev,
+				   "ti,led-modes value %u invalid\n",
+				   dp83867->led_modes[i]);
+			return -EINVAL;
+		}
+
+		if (dp83867->led_modes[i] > DP83867_LED_MAX) {
+			phydev_err(phydev,
+				   "ti,led-modes value %u out of range\n",
+				   dp83867->led_modes[i]);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_OF_MDIO
 static int dp83867_of_init(struct phy_device *phydev)
 {
@@ -578,6 +614,17 @@ static int dp83867_of_init(struct phy_device *phydev)
 		return -EINVAL;
 	}
 
+	/* default LED modes according to data sheet */
+	dp83867->led_modes[0] = DP83867_LED_LINK;
+	dp83867->led_modes[1] = DP83867_LED_LINK_1000_BT;
+	dp83867->led_modes[2] = DP83867_LED_ACT_RX_TX;
+	dp83867->led_modes[3] = DP83867_LED_LINK_100_BTX;
+
+	ret = of_property_read_u32_array(of_node, "ti,led-modes",
+					 &dp83867->led_modes[0], NUM_LEDS);
+	if (!ret && dp83867_validate_led_modes(phydev))
+		return -EINVAL;
+
 	return 0;
 }
 #else
@@ -617,6 +664,16 @@ static int dp83867_config_init(struct phy_device *phydev)
 	if (ret)
 		return ret;
 
+	/* Set LED modes */
+	val = 0;
+	val |= (dp83867->led_modes[0] << DP83867_LED_0_SHIFT);
+	val |= (dp83867->led_modes[1] << DP83867_LED_1_SHIFT);
+	val |= (dp83867->led_modes[2] << DP83867_LED_2_SHIFT);
+	val |= (dp83867->led_modes[3] << DP83867_LED_3_SHIFT);
+	ret = phy_write(phydev, DP83867_LEDCR1, val);
+	if (ret)
+		return ret;
+
 	/* RX_DV/RX_CTRL strapped in mode 1 or mode 2 workaround */
 	if (dp83867->rxctrl_strap_quirk)
 		phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
-- 
2.25.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help