mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 09:12:39 +00:00
7d256aff7b
The previous iteration of MediaTek's PHY patches caused various weird bugs. Drop culprit patch 733-10-net-phy-mediatek-Extend-1G-TX-RX-link-pulse-time.patch and use the most recent iteration of the patchset which has been posted to the netdev mailing list. Link: https://patchwork.kernel.org/project/netdevbpf/list/?series=895513&state=* Fixes: #16448 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
743 lines
22 KiB
Diff
743 lines
22 KiB
Diff
From 16bbd4ecb67ec1899ad8aa1eb1219a6d576cbaaf Mon Sep 17 00:00:00 2001
|
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
|
Date: Fri, 4 Oct 2024 18:24:07 +0800
|
|
Subject: [PATCH 3/9] net: phy: mediatek: Move LED helper functions into mtk
|
|
phy lib
|
|
|
|
This patch creates mtk-phy-lib.c & mtk-phy.h and integrates mtk-ge-soc.c's
|
|
LED helper functions so that we can use those helper functions in other
|
|
MTK's ethernet phy driver.
|
|
|
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
|
---
|
|
drivers/net/phy/mediatek/Kconfig | 5 +
|
|
drivers/net/phy/mediatek/Makefile | 1 +
|
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 262 +++----------------------
|
|
drivers/net/phy/mediatek/mtk-phy-lib.c | 251 +++++++++++++++++++++++
|
|
drivers/net/phy/mediatek/mtk.h | 82 ++++++++
|
|
5 files changed, 366 insertions(+), 235 deletions(-)
|
|
create mode 100644 drivers/net/phy/mediatek/mtk-phy-lib.c
|
|
create mode 100644 drivers/net/phy/mediatek/mtk.h
|
|
|
|
--- a/drivers/net/phy/mediatek/Kconfig
|
|
+++ b/drivers/net/phy/mediatek/Kconfig
|
|
@@ -1,6 +1,10 @@
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
+config MTK_NET_PHYLIB
|
|
+ tristate
|
|
+
|
|
config MEDIATEK_GE_PHY
|
|
tristate "MediaTek Gigabit Ethernet PHYs"
|
|
+ select MTK_NET_PHYLIB
|
|
help
|
|
Supports the MediaTek non-built-in Gigabit Ethernet PHYs.
|
|
|
|
@@ -13,6 +17,7 @@ config MEDIATEK_GE_SOC_PHY
|
|
tristate "MediaTek SoC Ethernet PHYs"
|
|
depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
|
|
select NVMEM_MTK_EFUSE
|
|
+ select MTK_NET_PHYLIB
|
|
help
|
|
Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
|
|
|
|
--- a/drivers/net/phy/mediatek/Makefile
|
|
+++ b/drivers/net/phy/mediatek/Makefile
|
|
@@ -1,3 +1,4 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
+obj-$(CONFIG_MTK_NET_PHYLIB) += mtk-phy-lib.o
|
|
obj-$(CONFIG_MEDIATEK_GE_PHY) += mtk-ge.o
|
|
obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mtk-ge-soc.o
|
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
|
@@ -8,6 +8,8 @@
|
|
#include <linux/phy.h>
|
|
#include <linux/regmap.h>
|
|
|
|
+#include "mtk.h"
|
|
+
|
|
#define MTK_GPHY_ID_MT7981 0x03a29461
|
|
#define MTK_GPHY_ID_MT7988 0x03a29481
|
|
|
|
@@ -210,41 +212,6 @@
|
|
#define MTK_PHY_DA_TX_R50_PAIR_D 0x540
|
|
|
|
/* Registers on MDIO_MMD_VEND2 */
|
|
-#define MTK_PHY_LED0_ON_CTRL 0x24
|
|
-#define MTK_PHY_LED1_ON_CTRL 0x26
|
|
-#define MTK_PHY_LED_ON_MASK GENMASK(6, 0)
|
|
-#define MTK_PHY_LED_ON_LINK1000 BIT(0)
|
|
-#define MTK_PHY_LED_ON_LINK100 BIT(1)
|
|
-#define MTK_PHY_LED_ON_LINK10 BIT(2)
|
|
-#define MTK_PHY_LED_ON_LINK (MTK_PHY_LED_ON_LINK10 |\
|
|
- MTK_PHY_LED_ON_LINK100 |\
|
|
- MTK_PHY_LED_ON_LINK1000)
|
|
-#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
|
|
-#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
|
|
-#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
|
|
-#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
|
|
-#define MTK_PHY_LED_ON_POLARITY BIT(14)
|
|
-#define MTK_PHY_LED_ON_ENABLE BIT(15)
|
|
-
|
|
-#define MTK_PHY_LED0_BLINK_CTRL 0x25
|
|
-#define MTK_PHY_LED1_BLINK_CTRL 0x27
|
|
-#define MTK_PHY_LED_BLINK_1000TX BIT(0)
|
|
-#define MTK_PHY_LED_BLINK_1000RX BIT(1)
|
|
-#define MTK_PHY_LED_BLINK_100TX BIT(2)
|
|
-#define MTK_PHY_LED_BLINK_100RX BIT(3)
|
|
-#define MTK_PHY_LED_BLINK_10TX BIT(4)
|
|
-#define MTK_PHY_LED_BLINK_10RX BIT(5)
|
|
-#define MTK_PHY_LED_BLINK_RX (MTK_PHY_LED_BLINK_10RX |\
|
|
- MTK_PHY_LED_BLINK_100RX |\
|
|
- MTK_PHY_LED_BLINK_1000RX)
|
|
-#define MTK_PHY_LED_BLINK_TX (MTK_PHY_LED_BLINK_10TX |\
|
|
- MTK_PHY_LED_BLINK_100TX |\
|
|
- MTK_PHY_LED_BLINK_1000TX)
|
|
-#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
|
|
-#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
|
|
-#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
|
|
-#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
|
|
-
|
|
#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1)
|
|
|
|
#define MTK_PHY_RG_BG_RASEL 0x115
|
|
@@ -299,10 +266,6 @@ enum CAL_MODE {
|
|
SW_M
|
|
};
|
|
|
|
-#define MTK_PHY_LED_STATE_FORCE_ON 0
|
|
-#define MTK_PHY_LED_STATE_FORCE_BLINK 1
|
|
-#define MTK_PHY_LED_STATE_NETDEV 2
|
|
-
|
|
struct mtk_socphy_priv {
|
|
unsigned long led_state;
|
|
};
|
|
@@ -1131,84 +1094,39 @@ static int mt798x_phy_config_init(struct
|
|
return mt798x_phy_calibration(phydev);
|
|
}
|
|
|
|
-static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
|
|
- bool on)
|
|
-{
|
|
- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
|
|
- struct mtk_socphy_priv *priv = phydev->priv;
|
|
- bool changed;
|
|
-
|
|
- if (on)
|
|
- changed = !test_and_set_bit(bit_on, &priv->led_state);
|
|
- else
|
|
- changed = !!test_and_clear_bit(bit_on, &priv->led_state);
|
|
-
|
|
- changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
|
|
- (index ? 16 : 0), &priv->led_state);
|
|
- if (changed)
|
|
- return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
|
- MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
|
|
- MTK_PHY_LED_ON_MASK,
|
|
- on ? MTK_PHY_LED_ON_FORCE_ON : 0);
|
|
- else
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
|
|
- bool blinking)
|
|
-{
|
|
- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
|
|
- struct mtk_socphy_priv *priv = phydev->priv;
|
|
- bool changed;
|
|
-
|
|
- if (blinking)
|
|
- changed = !test_and_set_bit(bit_blink, &priv->led_state);
|
|
- else
|
|
- changed = !!test_and_clear_bit(bit_blink, &priv->led_state);
|
|
-
|
|
- changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
|
|
- (index ? 16 : 0), &priv->led_state);
|
|
- if (changed)
|
|
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
|
|
- MTK_PHY_LED1_BLINK_CTRL : MTK_PHY_LED0_BLINK_CTRL,
|
|
- blinking ? MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
|
|
- else
|
|
- return 0;
|
|
-}
|
|
-
|
|
static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,
|
|
unsigned long *delay_on,
|
|
unsigned long *delay_off)
|
|
{
|
|
+ struct mtk_socphy_priv *priv = phydev->priv;
|
|
bool blinking = false;
|
|
int err = 0;
|
|
|
|
- if (index > 1)
|
|
- return -EINVAL;
|
|
-
|
|
- if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
|
|
- blinking = true;
|
|
- *delay_on = 50;
|
|
- *delay_off = 50;
|
|
- }
|
|
+ err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
|
|
- err = mt798x_phy_hw_led_blink_set(phydev, index, blinking);
|
|
+ err = mtk_phy_hw_led_blink_set(phydev, index, &priv->led_state,
|
|
+ blinking);
|
|
if (err)
|
|
return err;
|
|
|
|
- return mt798x_phy_hw_led_on_set(phydev, index, false);
|
|
+ return mtk_phy_hw_led_on_set(phydev, index, &priv->led_state,
|
|
+ MTK_GPHY_LED_ON_MASK, false);
|
|
}
|
|
|
|
static int mt798x_phy_led_brightness_set(struct phy_device *phydev,
|
|
u8 index, enum led_brightness value)
|
|
{
|
|
+ struct mtk_socphy_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
- err = mt798x_phy_hw_led_blink_set(phydev, index, false);
|
|
+ err = mtk_phy_hw_led_blink_set(phydev, index, &priv->led_state, false);
|
|
if (err)
|
|
return err;
|
|
|
|
- return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF));
|
|
+ return mtk_phy_hw_led_on_set(phydev, index, &priv->led_state,
|
|
+ MTK_GPHY_LED_ON_MASK, (value != LED_OFF));
|
|
}
|
|
|
|
static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
|
@@ -1223,148 +1141,30 @@ static const unsigned long supported_tri
|
|
static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
|
unsigned long rules)
|
|
{
|
|
- if (index > 1)
|
|
- return -EINVAL;
|
|
-
|
|
- /* All combinations of the supported triggers are allowed */
|
|
- if (rules & ~supported_triggers)
|
|
- return -EOPNOTSUPP;
|
|
-
|
|
- return 0;
|
|
-};
|
|
+ return mtk_phy_led_hw_is_supported(phydev, index, rules,
|
|
+ supported_triggers);
|
|
+}
|
|
|
|
static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
|
|
unsigned long *rules)
|
|
{
|
|
- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
|
|
- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
|
|
- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
|
|
struct mtk_socphy_priv *priv = phydev->priv;
|
|
- int on, blink;
|
|
-
|
|
- if (index > 1)
|
|
- return -EINVAL;
|
|
-
|
|
- on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
|
- index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
|
|
-
|
|
- if (on < 0)
|
|
- return -EIO;
|
|
-
|
|
- blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
|
- index ? MTK_PHY_LED1_BLINK_CTRL :
|
|
- MTK_PHY_LED0_BLINK_CTRL);
|
|
- if (blink < 0)
|
|
- return -EIO;
|
|
-
|
|
- if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
|
|
- MTK_PHY_LED_ON_LINKDOWN)) ||
|
|
- (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
|
|
- set_bit(bit_netdev, &priv->led_state);
|
|
- else
|
|
- clear_bit(bit_netdev, &priv->led_state);
|
|
-
|
|
- if (on & MTK_PHY_LED_ON_FORCE_ON)
|
|
- set_bit(bit_on, &priv->led_state);
|
|
- else
|
|
- clear_bit(bit_on, &priv->led_state);
|
|
-
|
|
- if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
|
|
- set_bit(bit_blink, &priv->led_state);
|
|
- else
|
|
- clear_bit(bit_blink, &priv->led_state);
|
|
-
|
|
- if (!rules)
|
|
- return 0;
|
|
-
|
|
- if (on & MTK_PHY_LED_ON_LINK)
|
|
- *rules |= BIT(TRIGGER_NETDEV_LINK);
|
|
|
|
- if (on & MTK_PHY_LED_ON_LINK10)
|
|
- *rules |= BIT(TRIGGER_NETDEV_LINK_10);
|
|
-
|
|
- if (on & MTK_PHY_LED_ON_LINK100)
|
|
- *rules |= BIT(TRIGGER_NETDEV_LINK_100);
|
|
-
|
|
- if (on & MTK_PHY_LED_ON_LINK1000)
|
|
- *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
|
|
-
|
|
- if (on & MTK_PHY_LED_ON_FDX)
|
|
- *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
|
|
-
|
|
- if (on & MTK_PHY_LED_ON_HDX)
|
|
- *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
|
|
-
|
|
- if (blink & MTK_PHY_LED_BLINK_RX)
|
|
- *rules |= BIT(TRIGGER_NETDEV_RX);
|
|
-
|
|
- if (blink & MTK_PHY_LED_BLINK_TX)
|
|
- *rules |= BIT(TRIGGER_NETDEV_TX);
|
|
-
|
|
- return 0;
|
|
+ return mtk_phy_led_hw_ctrl_get(phydev, index, rules, &priv->led_state,
|
|
+ MTK_GPHY_LED_ON_SET,
|
|
+ MTK_GPHY_LED_RX_BLINK_SET,
|
|
+ MTK_GPHY_LED_TX_BLINK_SET);
|
|
};
|
|
|
|
static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
|
|
unsigned long rules)
|
|
{
|
|
- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
|
|
struct mtk_socphy_priv *priv = phydev->priv;
|
|
- u16 on = 0, blink = 0;
|
|
- int ret;
|
|
|
|
- if (index > 1)
|
|
- return -EINVAL;
|
|
-
|
|
- if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
|
|
- on |= MTK_PHY_LED_ON_FDX;
|
|
-
|
|
- if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
|
|
- on |= MTK_PHY_LED_ON_HDX;
|
|
-
|
|
- if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
|
|
- on |= MTK_PHY_LED_ON_LINK10;
|
|
-
|
|
- if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
|
|
- on |= MTK_PHY_LED_ON_LINK100;
|
|
-
|
|
- if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
|
|
- on |= MTK_PHY_LED_ON_LINK1000;
|
|
-
|
|
- if (rules & BIT(TRIGGER_NETDEV_RX)) {
|
|
- blink |= (on & MTK_PHY_LED_ON_LINK) ?
|
|
- (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
|
|
- ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
|
|
- ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
|
|
- MTK_PHY_LED_BLINK_RX;
|
|
- }
|
|
-
|
|
- if (rules & BIT(TRIGGER_NETDEV_TX)) {
|
|
- blink |= (on & MTK_PHY_LED_ON_LINK) ?
|
|
- (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
|
|
- ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
|
|
- ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
|
|
- MTK_PHY_LED_BLINK_TX;
|
|
- }
|
|
-
|
|
- if (blink || on)
|
|
- set_bit(bit_netdev, &priv->led_state);
|
|
- else
|
|
- clear_bit(bit_netdev, &priv->led_state);
|
|
-
|
|
- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
|
- MTK_PHY_LED1_ON_CTRL :
|
|
- MTK_PHY_LED0_ON_CTRL,
|
|
- MTK_PHY_LED_ON_FDX |
|
|
- MTK_PHY_LED_ON_HDX |
|
|
- MTK_PHY_LED_ON_LINK,
|
|
- on);
|
|
-
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
|
|
- MTK_PHY_LED1_BLINK_CTRL :
|
|
- MTK_PHY_LED0_BLINK_CTRL, blink);
|
|
+ return mtk_phy_led_hw_ctrl_set(phydev, index, rules, &priv->led_state,
|
|
+ MTK_GPHY_LED_ON_SET,
|
|
+ MTK_GPHY_LED_RX_BLINK_SET,
|
|
+ MTK_GPHY_LED_TX_BLINK_SET);
|
|
};
|
|
|
|
static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)
|
|
@@ -1438,14 +1238,6 @@ static int mt7988_phy_probe_shared(struc
|
|
return 0;
|
|
}
|
|
|
|
-static void mt798x_phy_leds_state_init(struct phy_device *phydev)
|
|
-{
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < 2; ++i)
|
|
- mt798x_phy_led_hw_control_get(phydev, i, NULL);
|
|
-}
|
|
-
|
|
static int mt7988_phy_probe(struct phy_device *phydev)
|
|
{
|
|
struct mtk_socphy_shared *shared;
|
|
@@ -1471,7 +1263,7 @@ static int mt7988_phy_probe(struct phy_d
|
|
|
|
phydev->priv = priv;
|
|
|
|
- mt798x_phy_leds_state_init(phydev);
|
|
+ mtk_phy_leds_state_init(phydev);
|
|
|
|
err = mt7988_phy_fix_leds_polarities(phydev);
|
|
if (err)
|
|
@@ -1498,7 +1290,7 @@ static int mt7981_phy_probe(struct phy_d
|
|
|
|
phydev->priv = priv;
|
|
|
|
- mt798x_phy_leds_state_init(phydev);
|
|
+ mtk_phy_leds_state_init(phydev);
|
|
|
|
return mt798x_phy_calibration(phydev);
|
|
}
|
|
--- /dev/null
|
|
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
|
|
@@ -0,0 +1,251 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+#include <linux/phy.h>
|
|
+#include <linux/module.h>
|
|
+
|
|
+#include <linux/netdevice.h>
|
|
+
|
|
+#include "mtk.h"
|
|
+
|
|
+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
|
+ unsigned long rules,
|
|
+ unsigned long supported_triggers)
|
|
+{
|
|
+ if (index > 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* All combinations of the supported triggers are allowed */
|
|
+ if (rules & ~supported_triggers)
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_is_supported);
|
|
+
|
|
+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
|
|
+ unsigned long *rules, unsigned long *led_state,
|
|
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set)
|
|
+{
|
|
+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
|
|
+ (index ? 16 : 0);
|
|
+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
|
|
+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
|
|
+ int on, blink;
|
|
+
|
|
+ if (index > 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
|
+ index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
|
|
+
|
|
+ if (on < 0)
|
|
+ return -EIO;
|
|
+
|
|
+ blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
|
+ index ? MTK_PHY_LED1_BLINK_CTRL :
|
|
+ MTK_PHY_LED0_BLINK_CTRL);
|
|
+ if (blink < 0)
|
|
+ return -EIO;
|
|
+
|
|
+ if ((on & (on_set | MTK_PHY_LED_ON_FDX |
|
|
+ MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
|
|
+ (blink & (rx_blink_set | tx_blink_set)))
|
|
+ set_bit(bit_netdev, led_state);
|
|
+ else
|
|
+ clear_bit(bit_netdev, led_state);
|
|
+
|
|
+ if (on & MTK_PHY_LED_ON_FORCE_ON)
|
|
+ set_bit(bit_on, led_state);
|
|
+ else
|
|
+ clear_bit(bit_on, led_state);
|
|
+
|
|
+ if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
|
|
+ set_bit(bit_blink, led_state);
|
|
+ else
|
|
+ clear_bit(bit_blink, led_state);
|
|
+
|
|
+ if (!rules)
|
|
+ return 0;
|
|
+
|
|
+ if (on & on_set)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK);
|
|
+
|
|
+ if (on & MTK_PHY_LED_ON_LINK10)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK_10);
|
|
+
|
|
+ if (on & MTK_PHY_LED_ON_LINK100)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK_100);
|
|
+
|
|
+ if (on & MTK_PHY_LED_ON_LINK1000)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
|
|
+
|
|
+ if (on & MTK_PHY_LED_ON_LINK2500)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
|
|
+
|
|
+ if (on & MTK_PHY_LED_ON_FDX)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
|
|
+
|
|
+ if (on & MTK_PHY_LED_ON_HDX)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
|
|
+
|
|
+ if (blink & rx_blink_set)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_RX);
|
|
+
|
|
+ if (blink & tx_blink_set)
|
|
+ *rules |= BIT(TRIGGER_NETDEV_TX);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_get);
|
|
+
|
|
+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
|
|
+ unsigned long rules, unsigned long *led_state,
|
|
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set)
|
|
+{
|
|
+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
|
|
+ u16 on = 0, blink = 0;
|
|
+ int ret;
|
|
+
|
|
+ if (index > 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
|
|
+ on |= MTK_PHY_LED_ON_FDX;
|
|
+
|
|
+ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
|
|
+ on |= MTK_PHY_LED_ON_HDX;
|
|
+
|
|
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
|
|
+ on |= MTK_PHY_LED_ON_LINK10;
|
|
+
|
|
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
|
|
+ on |= MTK_PHY_LED_ON_LINK100;
|
|
+
|
|
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
|
|
+ on |= MTK_PHY_LED_ON_LINK1000;
|
|
+
|
|
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
|
|
+ on |= MTK_PHY_LED_ON_LINK2500;
|
|
+
|
|
+ if (rules & BIT(TRIGGER_NETDEV_RX)) {
|
|
+ blink |= (on & on_set) ?
|
|
+ (((on & MTK_PHY_LED_ON_LINK10) ?
|
|
+ MTK_PHY_LED_BLINK_10RX : 0) |
|
|
+ ((on & MTK_PHY_LED_ON_LINK100) ?
|
|
+ MTK_PHY_LED_BLINK_100RX : 0) |
|
|
+ ((on & MTK_PHY_LED_ON_LINK1000) ?
|
|
+ MTK_PHY_LED_BLINK_1000RX : 0) |
|
|
+ ((on & MTK_PHY_LED_ON_LINK2500) ?
|
|
+ MTK_PHY_LED_BLINK_2500RX : 0)) :
|
|
+ rx_blink_set;
|
|
+ }
|
|
+
|
|
+ if (rules & BIT(TRIGGER_NETDEV_TX)) {
|
|
+ blink |= (on & on_set) ?
|
|
+ (((on & MTK_PHY_LED_ON_LINK10) ?
|
|
+ MTK_PHY_LED_BLINK_10TX : 0) |
|
|
+ ((on & MTK_PHY_LED_ON_LINK100) ?
|
|
+ MTK_PHY_LED_BLINK_100TX : 0) |
|
|
+ ((on & MTK_PHY_LED_ON_LINK1000) ?
|
|
+ MTK_PHY_LED_BLINK_1000TX : 0) |
|
|
+ ((on & MTK_PHY_LED_ON_LINK2500) ?
|
|
+ MTK_PHY_LED_BLINK_2500TX : 0)) :
|
|
+ tx_blink_set;
|
|
+ }
|
|
+
|
|
+ if (blink || on)
|
|
+ set_bit(bit_netdev, led_state);
|
|
+ else
|
|
+ clear_bit(bit_netdev, led_state);
|
|
+
|
|
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
|
+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
|
|
+ MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | on_set,
|
|
+ on);
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
|
|
+ MTK_PHY_LED1_BLINK_CTRL :
|
|
+ MTK_PHY_LED0_BLINK_CTRL, blink);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_set);
|
|
+
|
|
+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
|
|
+ unsigned long *delay_off, bool *blinking)
|
|
+{
|
|
+ if (index > 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
|
|
+ *blinking = true;
|
|
+ *delay_on = 50;
|
|
+ *delay_off = 50;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(mtk_phy_led_num_dly_cfg);
|
|
+
|
|
+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
|
|
+ unsigned long *led_state, u16 led_on_mask, bool on)
|
|
+{
|
|
+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
|
|
+ bool changed;
|
|
+
|
|
+ if (on)
|
|
+ changed = !test_and_set_bit(bit_on, led_state);
|
|
+ else
|
|
+ changed = !!test_and_clear_bit(bit_on, led_state);
|
|
+
|
|
+ changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
|
|
+ (index ? 16 : 0), led_state);
|
|
+ if (changed)
|
|
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
|
+ MTK_PHY_LED1_ON_CTRL :
|
|
+ MTK_PHY_LED0_ON_CTRL,
|
|
+ led_on_mask,
|
|
+ on ? MTK_PHY_LED_ON_FORCE_ON : 0);
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_on_set);
|
|
+
|
|
+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
|
|
+ unsigned long *led_state, bool blinking)
|
|
+{
|
|
+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
|
|
+ (index ? 16 : 0);
|
|
+ bool changed;
|
|
+
|
|
+ if (blinking)
|
|
+ changed = !test_and_set_bit(bit_blink, led_state);
|
|
+ else
|
|
+ changed = !!test_and_clear_bit(bit_blink, led_state);
|
|
+
|
|
+ changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
|
|
+ (index ? 16 : 0), led_state);
|
|
+ if (changed)
|
|
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
|
|
+ MTK_PHY_LED1_BLINK_CTRL :
|
|
+ MTK_PHY_LED0_BLINK_CTRL,
|
|
+ blinking ?
|
|
+ MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_blink_set);
|
|
+
|
|
+void mtk_phy_leds_state_init(struct phy_device *phydev)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < 2; ++i)
|
|
+ phydev->drv->led_hw_control_get(phydev, i, NULL);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init);
|
|
+
|
|
+MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common");
|
|
+MODULE_AUTHOR("Sky Huang <SkyLake.Huang@mediatek.com>");
|
|
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
|
|
+MODULE_LICENSE("GPL");
|
|
--- /dev/null
|
|
+++ b/drivers/net/phy/mediatek/mtk.h
|
|
@@ -0,0 +1,82 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0
|
|
+ *
|
|
+ * Common definition for Mediatek Ethernet PHYs
|
|
+ * Author: SkyLake Huang <SkyLake.Huang@mediatek.com>
|
|
+ * Copyright (c) 2024 MediaTek Inc.
|
|
+ */
|
|
+
|
|
+#ifndef _MTK_EPHY_H_
|
|
+#define _MTK_EPHY_H_
|
|
+
|
|
+#define MTK_EXT_PAGE_ACCESS 0x1f
|
|
+
|
|
+/* Registers on MDIO_MMD_VEND2 */
|
|
+#define MTK_PHY_LED0_ON_CTRL 0x24
|
|
+#define MTK_PHY_LED1_ON_CTRL 0x26
|
|
+#define MTK_GPHY_LED_ON_MASK GENMASK(6, 0)
|
|
+#define MTK_2P5GPHY_LED_ON_MASK GENMASK(7, 0)
|
|
+#define MTK_PHY_LED_ON_LINK1000 BIT(0)
|
|
+#define MTK_PHY_LED_ON_LINK100 BIT(1)
|
|
+#define MTK_PHY_LED_ON_LINK10 BIT(2)
|
|
+#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
|
|
+#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
|
|
+#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
|
|
+#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
|
|
+#define MTK_PHY_LED_ON_LINK2500 BIT(7)
|
|
+#define MTK_PHY_LED_ON_POLARITY BIT(14)
|
|
+#define MTK_PHY_LED_ON_ENABLE BIT(15)
|
|
+
|
|
+#define MTK_PHY_LED0_BLINK_CTRL 0x25
|
|
+#define MTK_PHY_LED1_BLINK_CTRL 0x27
|
|
+#define MTK_PHY_LED_BLINK_1000TX BIT(0)
|
|
+#define MTK_PHY_LED_BLINK_1000RX BIT(1)
|
|
+#define MTK_PHY_LED_BLINK_100TX BIT(2)
|
|
+#define MTK_PHY_LED_BLINK_100RX BIT(3)
|
|
+#define MTK_PHY_LED_BLINK_10TX BIT(4)
|
|
+#define MTK_PHY_LED_BLINK_10RX BIT(5)
|
|
+#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
|
|
+#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
|
|
+#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
|
|
+#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
|
|
+#define MTK_PHY_LED_BLINK_2500TX BIT(10)
|
|
+#define MTK_PHY_LED_BLINK_2500RX BIT(11)
|
|
+
|
|
+#define MTK_GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK1000 | \
|
|
+ MTK_PHY_LED_ON_LINK100 | \
|
|
+ MTK_PHY_LED_ON_LINK10)
|
|
+#define MTK_GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
|
|
+ MTK_PHY_LED_BLINK_100RX | \
|
|
+ MTK_PHY_LED_BLINK_10RX)
|
|
+#define MTK_GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
|
|
+ MTK_PHY_LED_BLINK_100RX | \
|
|
+ MTK_PHY_LED_BLINK_10RX)
|
|
+
|
|
+#define MTK_2P5GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK2500 | \
|
|
+ MTK_GPHY_LED_ON_SET)
|
|
+#define MTK_2P5GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
|
|
+ MTK_GPHY_LED_RX_BLINK_SET)
|
|
+#define MTK_2P5GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
|
|
+ MTK_GPHY_LED_TX_BLINK_SET)
|
|
+
|
|
+#define MTK_PHY_LED_STATE_FORCE_ON 0
|
|
+#define MTK_PHY_LED_STATE_FORCE_BLINK 1
|
|
+#define MTK_PHY_LED_STATE_NETDEV 2
|
|
+
|
|
+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
|
+ unsigned long rules,
|
|
+ unsigned long supported_triggers);
|
|
+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
|
|
+ unsigned long rules, unsigned long *led_state,
|
|
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set);
|
|
+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
|
|
+ unsigned long *rules, unsigned long *led_state,
|
|
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set);
|
|
+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
|
|
+ unsigned long *delay_off, bool *blinking);
|
|
+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
|
|
+ unsigned long *led_state, u16 led_on_mask, bool on);
|
|
+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
|
|
+ unsigned long *led_state, bool blinking);
|
|
+void mtk_phy_leds_state_init(struct phy_device *phydev);
|
|
+
|
|
+#endif /* _MTK_EPHY_H_ */
|