--- /dev/null
+From 9e42a2ea7f6703e2092c39171c2bf1fd7eec0bd3 Mon Sep 17 00:00:00 2001
+From: Chris Packham <chris.packham@alliedtelesis.co.nz>
+Date: Tue, 11 Jun 2024 17:34:14 +1200
+Subject: [PATCH] net: phy: realtek: add support for rtl8224 2.5Gbps PHY
+
+The Realtek RTL8224 PHY is a 2.5Gbps capable PHY. It only uses the
+clause 45 MDIO interface and can leverage the support that has already
+been added for the other 822x PHYs.
+
+Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
+Link: https://lore.kernel.org/r/20240611053415.2111723-1-chris.packham@alliedtelesis.co.nz
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/realtek.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/net/phy/realtek.c
++++ b/drivers/net/phy/realtek.c
+@@ -1318,6 +1318,14 @@ static struct phy_driver realtek_drvs[]
+ .read_page = rtl821x_read_page,
+ .write_page = rtl821x_write_page,
+ }, {
++ PHY_ID_MATCH_EXACT(0x001ccad0),
++ .name = "RTL8224 2.5Gbps PHY",
++ .get_features = rtl822x_c45_get_features,
++ .config_aneg = rtl822x_c45_config_aneg,
++ .read_status = rtl822x_c45_read_status,
++ .suspend = genphy_c45_pma_suspend,
++ .resume = rtlgen_c45_resume,
++ }, {
+ PHY_ID_MATCH_EXACT(0x001cc961),
+ .name = "RTL8366RB Gigabit Ethernet",
+ .config_init = &rtl8366rb_config_init,
--- /dev/null
+From 17784801d888238571a0c4101b9ac4401fffeaa0 Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marex@denx.de>
+Date: Tue, 25 Jun 2024 22:42:17 +0200
+Subject: [PATCH] net: phy: realtek: Add support for PHY LEDs on RTL8211F
+
+Realtek RTL8211F Ethernet PHY supports 3 LED pins which are used to
+indicate link status and activity. Add minimal LED controller driver
+supporting the most common uses with the 'netdev' trigger.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/realtek.c | 106 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 106 insertions(+)
+
+--- a/drivers/net/phy/realtek.c
++++ b/drivers/net/phy/realtek.c
+@@ -32,6 +32,15 @@
+ #define RTL8211F_PHYCR2 0x19
+ #define RTL8211F_INSR 0x1d
+
++#define RTL8211F_LEDCR 0x10
++#define RTL8211F_LEDCR_MODE BIT(15)
++#define RTL8211F_LEDCR_ACT_TXRX BIT(4)
++#define RTL8211F_LEDCR_LINK_1000 BIT(3)
++#define RTL8211F_LEDCR_LINK_100 BIT(1)
++#define RTL8211F_LEDCR_LINK_10 BIT(0)
++#define RTL8211F_LEDCR_MASK GENMASK(4, 0)
++#define RTL8211F_LEDCR_SHIFT 5
++
+ #define RTL8211F_TX_DELAY BIT(8)
+ #define RTL8211F_RX_DELAY BIT(3)
+
+@@ -87,6 +96,8 @@
+ #define RTL_8221B_VN_CG 0x001cc84a
+ #define RTL_8251B 0x001cc862
+
++#define RTL8211F_LED_COUNT 3
++
+ MODULE_DESCRIPTION("Realtek PHY driver");
+ MODULE_AUTHOR("Johnson Leung");
+ MODULE_LICENSE("GPL");
+@@ -476,6 +487,98 @@ static int rtl821x_resume(struct phy_dev
+ return 0;
+ }
+
++static int rtl8211f_led_hw_is_supported(struct phy_device *phydev, u8 index,
++ unsigned long rules)
++{
++ const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) |
++ BIT(TRIGGER_NETDEV_LINK_100) |
++ BIT(TRIGGER_NETDEV_LINK_1000) |
++ BIT(TRIGGER_NETDEV_RX) |
++ BIT(TRIGGER_NETDEV_TX);
++
++ /* The RTL8211F PHY supports these LED settings on up to three LEDs:
++ * - Link: Configurable subset of 10/100/1000 link rates
++ * - Active: Blink on activity, RX or TX is not differentiated
++ * The Active option has two modes, A and B:
++ * - A: Link and Active indication at configurable, but matching,
++ * subset of 10/100/1000 link rates
++ * - B: Link indication at configurable subset of 10/100/1000 link
++ * rates and Active indication always at all three 10+100+1000
++ * link rates.
++ * This code currently uses mode B only.
++ */
++
++ if (index >= RTL8211F_LED_COUNT)
++ return -EINVAL;
++
++ /* Filter out any other unsupported triggers. */
++ if (rules & ~mask)
++ return -EOPNOTSUPP;
++
++ /* RX and TX are not differentiated, either both are set or not set. */
++ if (!(rules & BIT(TRIGGER_NETDEV_RX)) ^ !(rules & BIT(TRIGGER_NETDEV_TX)))
++ return -EOPNOTSUPP;
++
++ return 0;
++}
++
++static int rtl8211f_led_hw_control_get(struct phy_device *phydev, u8 index,
++ unsigned long *rules)
++{
++ int val;
++
++ val = phy_read_paged(phydev, 0xd04, RTL8211F_LEDCR);
++ if (val < 0)
++ return val;
++
++ val >>= RTL8211F_LEDCR_SHIFT * index;
++ val &= RTL8211F_LEDCR_MASK;
++
++ if (val & RTL8211F_LEDCR_LINK_10)
++ set_bit(TRIGGER_NETDEV_LINK_10, rules);
++
++ if (val & RTL8211F_LEDCR_LINK_100)
++ set_bit(TRIGGER_NETDEV_LINK_100, rules);
++
++ if (val & RTL8211F_LEDCR_LINK_1000)
++ set_bit(TRIGGER_NETDEV_LINK_1000, rules);
++
++ if (val & RTL8211F_LEDCR_ACT_TXRX) {
++ set_bit(TRIGGER_NETDEV_RX, rules);
++ set_bit(TRIGGER_NETDEV_TX, rules);
++ }
++
++ return 0;
++}
++
++static int rtl8211f_led_hw_control_set(struct phy_device *phydev, u8 index,
++ unsigned long rules)
++{
++ const u16 mask = RTL8211F_LEDCR_MASK << (RTL8211F_LEDCR_SHIFT * index);
++ u16 reg = RTL8211F_LEDCR_MODE; /* Mode B */
++
++ if (index >= RTL8211F_LED_COUNT)
++ return -EINVAL;
++
++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules))
++ reg |= RTL8211F_LEDCR_LINK_10;
++
++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules))
++ reg |= RTL8211F_LEDCR_LINK_100;
++
++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules))
++ reg |= RTL8211F_LEDCR_LINK_1000;
++
++ if (test_bit(TRIGGER_NETDEV_RX, &rules) ||
++ test_bit(TRIGGER_NETDEV_TX, &rules)) {
++ reg |= RTL8211F_LEDCR_ACT_TXRX;
++ }
++
++ reg <<= RTL8211F_LEDCR_SHIFT * index;
++
++ return phy_modify_paged(phydev, 0xd04, RTL8211F_LEDCR, mask, reg);
++}
++
+ static int rtl8211e_config_init(struct phy_device *phydev)
+ {
+ int ret = 0, oldpage;
+@@ -1192,6 +1295,9 @@ static struct phy_driver realtek_drvs[]
+ .read_page = rtl821x_read_page,
+ .write_page = rtl821x_write_page,
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
++ .led_hw_is_supported = rtl8211f_led_hw_is_supported,
++ .led_hw_control_get = rtl8211f_led_hw_control_get,
++ .led_hw_control_set = rtl8211f_led_hw_control_set,
+ }, {
+ PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID),
+ .name = "RTL8211F-VD Gigabit Ethernet",
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
-@@ -1218,6 +1218,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1324,6 +1324,7 @@ static struct phy_driver realtek_drvs[]
}, {
.name = "RTL8226 2.5Gbps PHY",
.match_phy_device = rtl8226_match_phy_device,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,
-@@ -1230,6 +1231,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1336,6 +1337,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc840),
.name = "RTL8226B_RTL8221B 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
-@@ -1244,6 +1246,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1350,6 +1352,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc838),
.name = "RTL8226-CG 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.read_status = rtl822x_read_status,
-@@ -1254,6 +1257,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1360,6 +1363,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc848),
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
-@@ -1266,6 +1270,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1372,6 +1376,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
-@@ -1278,6 +1283,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1384,6 +1389,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
.config_init = rtl822xb_config_init,
.get_rate_matching = rtl822xb_get_rate_matching,
.get_features = rtl822x_c45_get_features,
-@@ -1288,6 +1294,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1394,6 +1400,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
.config_init = rtl822xb_config_init,
-@@ -1300,6 +1307,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1406,6 +1413,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
-@@ -682,8 +682,8 @@ static int rtl822x_write_mmd(struct phy_
+@@ -785,8 +785,8 @@ static int rtl822x_write_mmd(struct phy_
static int rtl822xb_config_init(struct phy_device *phydev)
{
bool has_2500, has_sgmii;
has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX,
phydev->host_interfaces) ||
-@@ -733,7 +733,29 @@ static int rtl822xb_config_init(struct p
+@@ -836,7 +836,29 @@ static int rtl822xb_config_init(struct p
if (ret < 0)
return ret;
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
-@@ -948,9 +948,11 @@ static bool rtlgen_supports_2_5gbps(stru
+@@ -1051,9 +1051,11 @@ static bool rtlgen_supports_2_5gbps(stru
{
int val;
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
-@@ -806,7 +806,8 @@ static int rtl822x_config_aneg(struct ph
+@@ -909,7 +909,8 @@ static int rtl822x_config_aneg(struct ph
ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12,
MDIO_AN_10GBT_CTRL_ADV2_5G |
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
-@@ -846,6 +846,10 @@ static int rtl822x_read_status(struct ph
+@@ -949,6 +949,10 @@ static int rtl822x_read_status(struct ph
if (lpadv < 0)
return lpadv;
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
-@@ -73,6 +73,10 @@
+@@ -82,6 +82,10 @@
#define RTL822X_VND2_PHYSR 0xa434
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
-@@ -1003,6 +1007,25 @@ static int rtl8221b_vn_cg_c45_match_phy_
+@@ -1106,6 +1110,25 @@ static int rtl8221b_vn_cg_c45_match_phy_
return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true);
}
static int rtlgen_resume(struct phy_device *phydev)
{
int ret = genphy_resume(phydev);
-@@ -1275,6 +1298,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1381,6 +1404,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc838),
.name = "RTL8226-CG 2.5Gbps PHY",
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
-@@ -1286,6 +1310,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1392,6 +1416,7 @@ static struct phy_driver realtek_drvs[]
}, {
PHY_ID_MATCH_EXACT(0x001cc848),
.name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY",
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
-@@ -1299,6 +1324,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1405,6 +1430,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
-@@ -1312,6 +1338,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1418,6 +1444,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
.soft_reset = genphy_soft_reset,
.config_init = rtl822xb_config_init,
.get_rate_matching = rtl822xb_get_rate_matching,
-@@ -1323,6 +1350,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1429,6 +1456,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
.config_aneg = rtl822x_config_aneg,
-@@ -1336,6 +1364,7 @@ static struct phy_driver realtek_drvs[]
+@@ -1442,6 +1470,7 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
-@@ -1161,6 +1161,51 @@ static irqreturn_t rtl9000a_handle_inter
+@@ -1264,6 +1264,51 @@ static irqreturn_t rtl9000a_handle_inter
return IRQ_HANDLED;
}
static struct phy_driver realtek_drvs[] = {
{
PHY_ID_MATCH_EXACT(0x00008201),
-@@ -1324,6 +1369,8 @@ static struct phy_driver realtek_drvs[]
+@@ -1430,6 +1475,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c22_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)",
.probe = rtl822x_probe,
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
-@@ -1338,6 +1385,8 @@ static struct phy_driver realtek_drvs[]
+@@ -1444,6 +1491,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vb_cg_c45_match_phy_device,
.name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)",
.probe = rtl822x_probe,
.soft_reset = genphy_soft_reset,
.config_init = rtl822xb_config_init,
-@@ -1350,6 +1399,8 @@ static struct phy_driver realtek_drvs[]
+@@ -1456,6 +1505,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c22_match_phy_device,
.name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)",
.probe = rtl822x_probe,
.soft_reset = genphy_soft_reset,
.get_features = rtl822x_get_features,
-@@ -1364,6 +1415,8 @@ static struct phy_driver realtek_drvs[]
+@@ -1470,6 +1521,8 @@ static struct phy_driver realtek_drvs[]
}, {
.match_phy_device = rtl8221b_vn_cg_c45_match_phy_device,
.name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)",