1 From 33700ca45b7d2e1655d4cad95e25671e8a94e2f0 Mon Sep 17 00:00:00 2001
2 From: Heiner Kallweit <hkallweit1@gmail.com>
3 Date: Sat, 11 Jan 2025 21:51:24 +0100
4 Subject: [PATCH] net: phy: realtek: add hwmon support for temp sensor on
7 This adds hwmon support for the temperature sensor on RTL822x.
8 It's available on the standalone versions of the PHY's, and on
9 the integrated PHY's in RTL8125B/RTL8125D/RTL8126.
11 Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
12 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
13 Link: https://patch.msgid.link/ad6bfe9f-6375-4a00-84b4-bfb38a21bd71@gmail.com
14 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
16 drivers/net/phy/realtek/Kconfig | 6 ++
17 drivers/net/phy/realtek/Makefile | 1 +
18 drivers/net/phy/realtek/realtek.h | 10 ++++
19 drivers/net/phy/realtek/realtek_hwmon.c | 79 +++++++++++++++++++++++++
20 drivers/net/phy/realtek/realtek_main.c | 12 ++++
21 5 files changed, 108 insertions(+)
22 create mode 100644 drivers/net/phy/realtek/realtek.h
23 create mode 100644 drivers/net/phy/realtek/realtek_hwmon.c
25 --- a/drivers/net/phy/realtek/Kconfig
26 +++ b/drivers/net/phy/realtek/Kconfig
27 @@ -3,3 +3,9 @@ config REALTEK_PHY
28 tristate "Realtek PHYs"
30 Currently supports RTL821x/RTL822x and fast ethernet PHYs
32 +config REALTEK_PHY_HWMON
33 + def_bool REALTEK_PHY && HWMON
34 + depends on !(REALTEK_PHY=y && HWMON=m)
36 + Optional hwmon support for the temperature sensor
37 --- a/drivers/net/phy/realtek/Makefile
38 +++ b/drivers/net/phy/realtek/Makefile
40 # SPDX-License-Identifier: GPL-2.0
41 realtek-y += realtek_main.o
42 +realtek-$(CONFIG_REALTEK_PHY_HWMON) += realtek_hwmon.o
43 obj-$(CONFIG_REALTEK_PHY) += realtek.o
45 +++ b/drivers/net/phy/realtek/realtek.h
47 +/* SPDX-License-Identifier: GPL-2.0 */
52 +#include <linux/phy.h>
54 +int rtl822x_hwmon_init(struct phy_device *phydev);
56 +#endif /* REALTEK_H */
58 +++ b/drivers/net/phy/realtek/realtek_hwmon.c
60 +// SPDX-License-Identifier: GPL-2.0+
62 + * HWMON support for Realtek PHY's
64 + * Author: Heiner Kallweit <hkallweit1@gmail.com>
67 +#include <linux/hwmon.h>
68 +#include <linux/phy.h>
72 +#define RTL822X_VND2_TSALRM 0xa662
73 +#define RTL822X_VND2_TSRR 0xbd84
74 +#define RTL822X_VND2_TSSR 0xb54c
76 +static umode_t rtl822x_hwmon_is_visible(const void *drvdata,
77 + enum hwmon_sensor_types type,
78 + u32 attr, int channel)
83 +static int rtl822x_hwmon_get_temp(int raw)
88 + return 1000 * raw / 2;
91 +static int rtl822x_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
92 + u32 attr, int channel, long *val)
94 + struct phy_device *phydev = dev_get_drvdata(dev);
98 + case hwmon_temp_input:
99 + raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSRR) & 0x3ff;
100 + *val = rtl822x_hwmon_get_temp(raw);
102 + case hwmon_temp_max:
103 + /* Chip reduces speed to 1G if threshold is exceeded */
104 + raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSSR) >> 6;
105 + *val = rtl822x_hwmon_get_temp(raw);
114 +static const struct hwmon_ops rtl822x_hwmon_ops = {
115 + .is_visible = rtl822x_hwmon_is_visible,
116 + .read = rtl822x_hwmon_read,
119 +static const struct hwmon_channel_info * const rtl822x_hwmon_info[] = {
120 + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX),
124 +static const struct hwmon_chip_info rtl822x_hwmon_chip_info = {
125 + .ops = &rtl822x_hwmon_ops,
126 + .info = rtl822x_hwmon_info,
129 +int rtl822x_hwmon_init(struct phy_device *phydev)
131 + struct device *hwdev, *dev = &phydev->mdio.dev;
134 + /* Ensure over-temp alarm is reset. */
135 + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSALRM, 3);
137 + name = devm_hwmon_sanitize_name(dev, dev_name(dev));
139 + return PTR_ERR(name);
141 + hwdev = devm_hwmon_device_register_with_info(dev, name, phydev,
142 + &rtl822x_hwmon_chip_info,
144 + return PTR_ERR_OR_ZERO(hwdev);
146 --- a/drivers/net/phy/realtek/realtek_main.c
147 +++ b/drivers/net/phy/realtek/realtek_main.c
149 #include <linux/delay.h>
150 #include <linux/clk.h>
152 +#include "realtek.h"
154 #define RTL821x_PHYSR 0x11
155 #define RTL821x_PHYSR_DUPLEX BIT(13)
156 #define RTL821x_PHYSR_SPEED GENMASK(15, 14)
157 @@ -820,6 +822,15 @@ static int rtl822x_write_mmd(struct phy_
161 +static int rtl822x_probe(struct phy_device *phydev)
163 + if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) &&
164 + phydev->phy_id != RTL_GENERIC_PHYID)
165 + return rtl822x_hwmon_init(phydev);
170 static int rtl822xb_config_init(struct phy_device *phydev)
172 bool has_2500, has_sgmii;
173 @@ -1519,6 +1530,7 @@ static struct phy_driver realtek_drvs[]
174 .match_phy_device = rtl_internal_nbaset_match_phy_device,
175 .name = "Realtek Internal NBASE-T PHY",
176 .flags = PHY_IS_INTERNAL,
177 + .probe = rtl822x_probe,
178 .get_features = rtl822x_get_features,
179 .config_aneg = rtl822x_config_aneg,
180 .read_status = rtl822x_read_status,