mirror of
https://github.com/openwrt/openwrt.git
synced 2025-02-20 09:26:28 +00:00
generic: net: phy: mxl-gpy: add support for PHY LEDs
Add driver support for PHY LEDs for MaxLinear/Intel GPY Ethernet PHYs. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
parent
45bad8ba98
commit
5fd518b6e3
@ -0,0 +1,332 @@
|
||||
From 78997e9a5e4d8a4df561e083a92c91ae23010e07 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Tue, 1 Oct 2024 01:17:18 +0100
|
||||
Subject: [PATCH] net: phy: mxl-gpy: add basic LED support
|
||||
|
||||
Add basic support for LEDs connected to MaxLinear GPY2xx and GPY115 PHYs.
|
||||
The PHYs allow up to 4 LEDs to be connected.
|
||||
Implement controlling LEDs in software as well as netdev trigger offloading
|
||||
and LED polarity setup.
|
||||
|
||||
The hardware claims to support 16 PWM brightness levels but there is no
|
||||
documentation on how to use that feature, hence this is not supported.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://patch.msgid.link/b6ec9050339f8244ff898898a1cecc33b13a48fc.1727741563.git.daniel@makrotopia.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/mxl-gpy.c | 218 ++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 218 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/mxl-gpy.c
|
||||
+++ b/drivers/net/phy/mxl-gpy.c
|
||||
@@ -38,6 +38,7 @@
|
||||
#define PHY_MIISTAT 0x18 /* MII state */
|
||||
#define PHY_IMASK 0x19 /* interrupt mask */
|
||||
#define PHY_ISTAT 0x1A /* interrupt status */
|
||||
+#define PHY_LED 0x1B /* LEDs */
|
||||
#define PHY_FWV 0x1E /* firmware version */
|
||||
|
||||
#define PHY_MIISTAT_SPD_MASK GENMASK(2, 0)
|
||||
@@ -61,6 +62,11 @@
|
||||
PHY_IMASK_ADSC | \
|
||||
PHY_IMASK_ANC)
|
||||
|
||||
+#define GPY_MAX_LEDS 4
|
||||
+#define PHY_LED_POLARITY(idx) BIT(12 + (idx))
|
||||
+#define PHY_LED_HWCONTROL(idx) BIT(8 + (idx))
|
||||
+#define PHY_LED_ON(idx) BIT(idx)
|
||||
+
|
||||
#define PHY_FWV_REL_MASK BIT(15)
|
||||
#define PHY_FWV_MAJOR_MASK GENMASK(11, 8)
|
||||
#define PHY_FWV_MINOR_MASK GENMASK(7, 0)
|
||||
@@ -72,6 +78,23 @@
|
||||
#define PHY_MDI_MDI_X_CD 0x1
|
||||
#define PHY_MDI_MDI_X_CROSS 0x0
|
||||
|
||||
+/* LED */
|
||||
+#define VSPEC1_LED(idx) (1 + (idx))
|
||||
+#define VSPEC1_LED_BLINKS GENMASK(15, 12)
|
||||
+#define VSPEC1_LED_PULSE GENMASK(11, 8)
|
||||
+#define VSPEC1_LED_CON GENMASK(7, 4)
|
||||
+#define VSPEC1_LED_BLINKF GENMASK(3, 0)
|
||||
+
|
||||
+#define VSPEC1_LED_LINK10 BIT(0)
|
||||
+#define VSPEC1_LED_LINK100 BIT(1)
|
||||
+#define VSPEC1_LED_LINK1000 BIT(2)
|
||||
+#define VSPEC1_LED_LINK2500 BIT(3)
|
||||
+
|
||||
+#define VSPEC1_LED_TXACT BIT(0)
|
||||
+#define VSPEC1_LED_RXACT BIT(1)
|
||||
+#define VSPEC1_LED_COL BIT(2)
|
||||
+#define VSPEC1_LED_NO_CON BIT(3)
|
||||
+
|
||||
/* SGMII */
|
||||
#define VSPEC1_SGMII_CTRL 0x08
|
||||
#define VSPEC1_SGMII_CTRL_ANEN BIT(12) /* Aneg enable */
|
||||
@@ -827,6 +850,156 @@ static int gpy115_loopback(struct phy_de
|
||||
return genphy_soft_reset(phydev);
|
||||
}
|
||||
|
||||
+static int gpy_led_brightness_set(struct phy_device *phydev,
|
||||
+ u8 index, enum led_brightness value)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (index >= GPY_MAX_LEDS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* clear HWCONTROL and set manual LED state */
|
||||
+ ret = phy_modify(phydev, PHY_LED,
|
||||
+ ((value == LED_OFF) ? PHY_LED_HWCONTROL(index) : 0) |
|
||||
+ PHY_LED_ON(index),
|
||||
+ (value == LED_OFF) ? 0 : PHY_LED_ON(index));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* ToDo: set PWM brightness */
|
||||
+
|
||||
+ /* clear HW LED setup */
|
||||
+ if (value == LED_OFF)
|
||||
+ return phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index), 0);
|
||||
+ else
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) |
|
||||
+ BIT(TRIGGER_NETDEV_LINK_100) |
|
||||
+ BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||
+ BIT(TRIGGER_NETDEV_LINK_2500) |
|
||||
+ BIT(TRIGGER_NETDEV_RX) |
|
||||
+ BIT(TRIGGER_NETDEV_TX));
|
||||
+
|
||||
+static int gpy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||
+ unsigned long rules)
|
||||
+{
|
||||
+ if (index >= GPY_MAX_LEDS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* All combinations of the supported triggers are allowed */
|
||||
+ if (rules & ~supported_triggers)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int gpy_led_hw_control_get(struct phy_device *phydev, u8 index,
|
||||
+ unsigned long *rules)
|
||||
+{
|
||||
+ int val;
|
||||
+
|
||||
+ if (index >= GPY_MAX_LEDS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index));
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK10)
|
||||
+ *rules |= BIT(TRIGGER_NETDEV_LINK_10);
|
||||
+
|
||||
+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK100)
|
||||
+ *rules |= BIT(TRIGGER_NETDEV_LINK_100);
|
||||
+
|
||||
+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK1000)
|
||||
+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
|
||||
+
|
||||
+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK2500)
|
||||
+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
|
||||
+
|
||||
+ if (FIELD_GET(VSPEC1_LED_CON, val) == (VSPEC1_LED_LINK10 |
|
||||
+ VSPEC1_LED_LINK100 |
|
||||
+ VSPEC1_LED_LINK1000 |
|
||||
+ VSPEC1_LED_LINK2500))
|
||||
+ *rules |= BIT(TRIGGER_NETDEV_LINK);
|
||||
+
|
||||
+ if (FIELD_GET(VSPEC1_LED_PULSE, val) & VSPEC1_LED_TXACT)
|
||||
+ *rules |= BIT(TRIGGER_NETDEV_TX);
|
||||
+
|
||||
+ if (FIELD_GET(VSPEC1_LED_PULSE, val) & VSPEC1_LED_RXACT)
|
||||
+ *rules |= BIT(TRIGGER_NETDEV_RX);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int gpy_led_hw_control_set(struct phy_device *phydev, u8 index,
|
||||
+ unsigned long rules)
|
||||
+{
|
||||
+ u16 val = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (index >= GPY_MAX_LEDS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
|
||||
+ rules & BIT(TRIGGER_NETDEV_LINK_10))
|
||||
+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK10);
|
||||
+
|
||||
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
|
||||
+ rules & BIT(TRIGGER_NETDEV_LINK_100))
|
||||
+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK100);
|
||||
+
|
||||
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
|
||||
+ rules & BIT(TRIGGER_NETDEV_LINK_1000))
|
||||
+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK1000);
|
||||
+
|
||||
+ if (rules & BIT(TRIGGER_NETDEV_LINK) ||
|
||||
+ rules & BIT(TRIGGER_NETDEV_LINK_2500))
|
||||
+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK2500);
|
||||
+
|
||||
+ if (rules & BIT(TRIGGER_NETDEV_TX))
|
||||
+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_TXACT);
|
||||
+
|
||||
+ if (rules & BIT(TRIGGER_NETDEV_RX))
|
||||
+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_RXACT);
|
||||
+
|
||||
+ /* allow RX/TX pulse without link indication */
|
||||
+ if ((rules & BIT(TRIGGER_NETDEV_TX) || rules & BIT(TRIGGER_NETDEV_RX)) &&
|
||||
+ !(val & VSPEC1_LED_CON))
|
||||
+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_NO_CON) | VSPEC1_LED_CON;
|
||||
+
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index), val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return phy_set_bits(phydev, PHY_LED, PHY_LED_HWCONTROL(index));
|
||||
+}
|
||||
+
|
||||
+static int gpy_led_polarity_set(struct phy_device *phydev, int index,
|
||||
+ unsigned long modes)
|
||||
+{
|
||||
+ bool active_low = false;
|
||||
+ u32 mode;
|
||||
+
|
||||
+ if (index >= GPY_MAX_LEDS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
|
||||
+ switch (mode) {
|
||||
+ case PHY_LED_ACTIVE_LOW:
|
||||
+ active_low = true;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return phy_modify(phydev, PHY_LED, PHY_LED_POLARITY(index),
|
||||
+ active_low ? 0 : PHY_LED_POLARITY(index));
|
||||
+}
|
||||
+
|
||||
static struct phy_driver gpy_drivers[] = {
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx),
|
||||
@@ -844,6 +1017,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_GPY115B,
|
||||
@@ -862,6 +1040,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy115_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY115C),
|
||||
@@ -879,6 +1062,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy115_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_GPY211B,
|
||||
@@ -897,6 +1085,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY211C),
|
||||
@@ -914,6 +1107,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_GPY212B,
|
||||
@@ -932,6 +1130,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY212C),
|
||||
@@ -949,6 +1152,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_GPY215B,
|
||||
@@ -967,6 +1175,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY215C),
|
||||
@@ -984,6 +1197,11 @@ static struct phy_driver gpy_drivers[] =
|
||||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
+ .led_brightness_set = gpy_led_brightness_set,
|
||||
+ .led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
+ .led_hw_control_get = gpy_led_hw_control_get,
|
||||
+ .led_hw_control_set = gpy_led_hw_control_set,
|
||||
+ .led_polarity_set = gpy_led_polarity_set,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY241B),
|
@ -0,0 +1,28 @@
|
||||
From f95b4725e796b12e5f347a0d161e1d3843142aa8 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Fri, 4 Oct 2024 16:56:35 +0100
|
||||
Subject: [PATCH] net: phy: mxl-gpy: add missing support for
|
||||
TRIGGER_NETDEV_LINK_10
|
||||
|
||||
The PHY also support 10MBit/s links as well as the corresponding link
|
||||
indication trigger to be offloaded. Add TRIGGER_NETDEV_LINK_10 to the
|
||||
supported triggers.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://patch.msgid.link/cc5da0a989af8b0d49d823656d88053c4de2ab98.1728057367.git.daniel@makrotopia.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/mxl-gpy.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/phy/mxl-gpy.c
|
||||
+++ b/drivers/net/phy/mxl-gpy.c
|
||||
@@ -876,6 +876,7 @@ static int gpy_led_brightness_set(struct
|
||||
}
|
||||
|
||||
static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) |
|
||||
+ BIT(TRIGGER_NETDEV_LINK_10) |
|
||||
BIT(TRIGGER_NETDEV_LINK_100) |
|
||||
BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||
BIT(TRIGGER_NETDEV_LINK_2500) |
|
@ -0,0 +1,58 @@
|
||||
From eb89c79c1b8f17fc1611540768678e60df89ac42 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Thu, 10 Oct 2024 13:55:17 +0100
|
||||
Subject: [PATCH 3/4] net: phy: mxl-gpy: correctly describe LED polarity
|
||||
|
||||
According the datasheet covering the LED (0x1b) register:
|
||||
0B Active High LEDx pin driven high when activated
|
||||
1B Active Low LEDx pin driven low when activated
|
||||
|
||||
Make use of the now available 'active-high' property and correctly
|
||||
reflect the polarity setting which was previously inverted.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://patch.msgid.link/180ccafa837f09908b852a8a874a3808c5ecd2d0.1728558223.git.daniel@makrotopia.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/phy/mxl-gpy.c | 16 ++++++++++++----
|
||||
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/mxl-gpy.c
|
||||
+++ b/drivers/net/phy/mxl-gpy.c
|
||||
@@ -981,7 +981,7 @@ static int gpy_led_hw_control_set(struct
|
||||
static int gpy_led_polarity_set(struct phy_device *phydev, int index,
|
||||
unsigned long modes)
|
||||
{
|
||||
- bool active_low = false;
|
||||
+ bool force_active_low = false, force_active_high = false;
|
||||
u32 mode;
|
||||
|
||||
if (index >= GPY_MAX_LEDS)
|
||||
@@ -990,15 +990,23 @@ static int gpy_led_polarity_set(struct p
|
||||
for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
|
||||
switch (mode) {
|
||||
case PHY_LED_ACTIVE_LOW:
|
||||
- active_low = true;
|
||||
+ force_active_low = true;
|
||||
+ break;
|
||||
+ case PHY_LED_ACTIVE_HIGH:
|
||||
+ force_active_high = true;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
- return phy_modify(phydev, PHY_LED, PHY_LED_POLARITY(index),
|
||||
- active_low ? 0 : PHY_LED_POLARITY(index));
|
||||
+ if (force_active_low)
|
||||
+ return phy_set_bits(phydev, PHY_LED, PHY_LED_POLARITY(index));
|
||||
+
|
||||
+ if (force_active_high)
|
||||
+ return phy_clear_bits(phydev, PHY_LED, PHY_LED_POLARITY(index));
|
||||
+
|
||||
+ unreachable();
|
||||
}
|
||||
|
||||
static struct phy_driver gpy_drivers[] = {
|
@ -31,45 +31,21 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/polynomial.h>
|
||||
#include <linux/property.h>
|
||||
@@ -38,6 +39,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)
|
||||
@@ -61,10 +63,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)
|
||||
+
|
||||
#define PHY_PMA_MGBT_POLARITY 0x82
|
||||
#define PHY_MDI_MDI_X_MASK GENMASK(1, 0)
|
||||
#define PHY_MDI_MDI_X_NORMAL 0x3
|
||||
@@ -270,10 +277,39 @@ out:
|
||||
@@ -293,10 +294,39 @@ 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];
|
||||
+ u32 led_regs[GPY_MAX_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))
|
||||
+ if (of_property_read_u32_array(node, "mxl,led-config", led_regs, GPY_MAX_LEDS))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (of_property_read_bool(node, "mxl,led-drive-vdd"))
|
||||
@ -79,7 +55,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
+ phy_write(phydev, PHY_LED, val);
|
||||
+
|
||||
+ /* Write LED register values */
|
||||
+ for (i = 0; i < PHY_LED_NUM_LEDS; i++) {
|
||||
+ for (i = 0; i < GPY_MAX_LEDS; i++) {
|
||||
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(i), (u16)led_regs[i]);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
--- a/drivers/net/phy/mxl-gpy.c
|
||||
+++ b/drivers/net/phy/mxl-gpy.c
|
||||
@@ -385,8 +385,11 @@ static bool gpy_2500basex_chk(struct phy
|
||||
@@ -402,8 +402,11 @@ static bool gpy_2500basex_chk(struct phy
|
||||
|
||||
phydev->speed = SPEED_2500;
|
||||
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
|
||||
@ -28,7 +28,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -437,6 +440,14 @@ static int gpy_config_aneg(struct phy_de
|
||||
@@ -454,6 +457,14 @@ static int gpy_config_aneg(struct phy_de
|
||||
u32 adv;
|
||||
int ret;
|
||||
|
||||
@ -43,7 +43,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
if (phydev->autoneg == AUTONEG_DISABLE) {
|
||||
/* Configure half duplex with genphy_setup_forced,
|
||||
* because genphy_c45_pma_setup_forced does not support.
|
||||
@@ -559,6 +570,8 @@ static int gpy_update_interface(struct p
|
||||
@@ -576,6 +587,8 @@ static int gpy_update_interface(struct p
|
||||
switch (phydev->speed) {
|
||||
case SPEED_2500:
|
||||
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
|
||||
@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
|
||||
VSPEC1_SGMII_CTRL_ANEN, 0);
|
||||
if (ret < 0) {
|
||||
@@ -572,7 +585,7 @@ static int gpy_update_interface(struct p
|
||||
@@ -589,7 +602,7 @@ static int gpy_update_interface(struct p
|
||||
case SPEED_100:
|
||||
case SPEED_10:
|
||||
phydev->interface = PHY_INTERFACE_MODE_SGMII;
|
||||
|
Loading…
x
Reference in New Issue
Block a user