mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-20 14:13:16 +00:00
90fbec89be
Add downstream DT property to setup the PHY LEDs of the MaxLinear GPY211 PHY in such way that the VDD of the LED is driven by the SoC pin rather than the GND (which is the default). Signed-off-by: Daniel Golle <daniel@makrotopia.org>
106 lines
2.9 KiB
Diff
106 lines
2.9 KiB
Diff
From 94b90966095f3fa625897e8f53d215882f6e19b3 Mon Sep 17 00:00:00 2001
|
|
From: David Bauer <mail@david-bauer.net>
|
|
Date: Sat, 11 Mar 2023 17:00:01 +0100
|
|
Subject: [PATCH] mxl-gpy: control LED reg from DT
|
|
|
|
Add dynamic configuration for the LED control registers on MXL PHYs.
|
|
|
|
This patch has been tested with MaxLinear GPY211C. It is unlikely to be
|
|
accepted upstream, as upstream plans on integrating their own framework
|
|
for handling these LEDs.
|
|
|
|
For the time being, use this hack to configure PHY driven device-LEDs to
|
|
show the correct state.
|
|
|
|
A possible alternative might be to expose the LEDs using the kernel LED
|
|
framework and bind it to the netdevice. This might also be upstreamable,
|
|
although it is a considerable extra amount of work.
|
|
|
|
Signed-off-by: David Bauer <mail@david-bauer.net>
|
|
---
|
|
drivers/net/phy/mxl-gpy.c | 37 ++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 36 insertions(+), 1 deletion(-)
|
|
|
|
--- a/drivers/net/phy/mxl-gpy.c
|
|
+++ b/drivers/net/phy/mxl-gpy.c
|
|
@@ -10,6 +10,7 @@
|
|
#include <linux/bitfield.h>
|
|
#include <linux/hwmon.h>
|
|
#include <linux/mutex.h>
|
|
+#include <linux/of.h>
|
|
#include <linux/phy.h>
|
|
#include <linux/polynomial.h>
|
|
#include <linux/netdevice.h>
|
|
@@ -33,6 +34,7 @@
|
|
#define PHY_MIISTAT 0x18 /* MII state */
|
|
#define PHY_IMASK 0x19 /* interrupt mask */
|
|
#define PHY_ISTAT 0x1A /* interrupt status */
|
|
+#define PHY_LED 0x1B /* LED control */
|
|
#define PHY_FWV 0x1E /* firmware version */
|
|
|
|
#define PHY_MIISTAT_SPD_MASK GENMASK(2, 0)
|
|
@@ -56,10 +58,15 @@
|
|
PHY_IMASK_ADSC | \
|
|
PHY_IMASK_ANC)
|
|
|
|
+#define PHY_LED_NUM_LEDS 4
|
|
+
|
|
#define PHY_FWV_REL_MASK BIT(15)
|
|
#define PHY_FWV_MAJOR_MASK GENMASK(11, 8)
|
|
#define PHY_FWV_MINOR_MASK GENMASK(7, 0)
|
|
|
|
+/* LED */
|
|
+#define VSPEC1_LED(x) (0x1 + x)
|
|
+
|
|
/* SGMII */
|
|
#define VSPEC1_SGMII_CTRL 0x08
|
|
#define VSPEC1_SGMII_CTRL_ANEN BIT(12) /* Aneg enable */
|
|
@@ -241,6 +248,35 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+static int gpy_led_write(struct phy_device *phydev)
|
|
+{
|
|
+ struct device_node *node = phydev->mdio.dev.of_node;
|
|
+ u32 led_regs[PHY_LED_NUM_LEDS];
|
|
+ int i, ret;
|
|
+ u16 val = 0xff00;
|
|
+
|
|
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
|
|
+ return 0;
|
|
+
|
|
+ if (of_property_read_u32_array(node, "mxl,led-config", led_regs, PHY_LED_NUM_LEDS))
|
|
+ return 0;
|
|
+
|
|
+ if (of_property_read_bool(node, "mxl,led-drive-vdd"))
|
|
+ val &= 0x0fff;
|
|
+
|
|
+ /* Enable LED function handling on all ports*/
|
|
+ phy_write(phydev, PHY_LED, val);
|
|
+
|
|
+ /* Write LED register values */
|
|
+ for (i = 0; i < PHY_LED_NUM_LEDS; i++) {
|
|
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(i), (u16)led_regs[i]);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int gpy_config_init(struct phy_device *phydev)
|
|
{
|
|
int ret;
|
|
@@ -252,7 +288,10 @@ static int gpy_config_init(struct phy_de
|
|
|
|
/* Clear all pending interrupts */
|
|
ret = phy_read(phydev, PHY_ISTAT);
|
|
- return ret < 0 ? ret : 0;
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ return gpy_led_write(phydev);
|
|
}
|
|
|
|
static bool gpy_has_broken_mdint(struct phy_device *phydev)
|