aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--target/linux/generic/hack-5.15/765-mxl-gpy-control-LED-reg-from-DT.patch106
1 files changed, 106 insertions, 0 deletions
diff --git a/target/linux/generic/hack-5.15/765-mxl-gpy-control-LED-reg-from-DT.patch b/target/linux/generic/hack-5.15/765-mxl-gpy-control-LED-reg-from-DT.patch
new file mode 100644
index 0000000000..75014c0528
--- /dev/null
+++ b/target/linux/generic/hack-5.15/765-mxl-gpy-control-LED-reg-from-DT.patch
@@ -0,0 +1,106 @@
+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(-)
+
+diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c
+index 5ce1bf03bbd7..ec10ad5ccad6 100644
+--- a/drivers/net/phy/mxl-gpy.c
++++ b/drivers/net/phy/mxl-gpy.c
+@@ -8,6 +8,7 @@
+
+ #include <linux/module.h>
+ #include <linux/bitfield.h>
++#include <linux/of.h>
+ #include <linux/phy.h>
+ #include <linux/netdevice.h>
+
+@@ -30,6 +31,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)
+@@ -53,10 +55,15 @@
+ PHY_IMASK_ADSC | \
+ PHY_IMASK_ANC)
+
++#define PHY_LED_NUM_LEDS 4
++
+ #define PHY_FWV_REL_MASK BIT(15)
+ #define PHY_FWV_TYPE_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 */
+@@ -80,6 +87,31 @@ static const struct {
+ {9, 0x73},
+ };
+
++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;
++
++ 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;
++
++ /* Enable LED function handling on all ports*/
++ phy_write(phydev, PHY_LED, 0xFF00);
++
++ /* 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;
+@@ -91,7 +123,10 @@ static int gpy_config_init(struct phy_device *phydev)
+
+ /* 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 int gpy_probe(struct phy_device *phydev)
+--
+2.39.2
+