Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: realtek: add hwmon support for temp sensor on RTL822x

This adds hwmon support for the temperature sensor on RTL822x.
It's available on the standalone versions of the PHY's, and on
the integrated PHY's in RTL8125B/RTL8125D/RTL8126.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/ad6bfe9f-6375-4a00-84b4-bfb38a21bd71@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Heiner Kallweit and committed by
Jakub Kicinski
33700ca4 1416a9b2

+108
+6
drivers/net/phy/realtek/Kconfig
··· 3 3 tristate "Realtek PHYs" 4 4 help 5 5 Currently supports RTL821x/RTL822x and fast ethernet PHYs 6 + 7 + config REALTEK_PHY_HWMON 8 + def_bool REALTEK_PHY && HWMON 9 + depends on !(REALTEK_PHY=y && HWMON=m) 10 + help 11 + Optional hwmon support for the temperature sensor
+1
drivers/net/phy/realtek/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 realtek-y += realtek_main.o 3 + realtek-$(CONFIG_REALTEK_PHY_HWMON) += realtek_hwmon.o 3 4 obj-$(CONFIG_REALTEK_PHY) += realtek.o
+10
drivers/net/phy/realtek/realtek.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #ifndef REALTEK_H 4 + #define REALTEK_H 5 + 6 + #include <linux/phy.h> 7 + 8 + int rtl822x_hwmon_init(struct phy_device *phydev); 9 + 10 + #endif /* REALTEK_H */
+79
drivers/net/phy/realtek/realtek_hwmon.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * HWMON support for Realtek PHY's 4 + * 5 + * Author: Heiner Kallweit <hkallweit1@gmail.com> 6 + */ 7 + 8 + #include <linux/hwmon.h> 9 + #include <linux/phy.h> 10 + 11 + #include "realtek.h" 12 + 13 + #define RTL822X_VND2_TSALRM 0xa662 14 + #define RTL822X_VND2_TSRR 0xbd84 15 + #define RTL822X_VND2_TSSR 0xb54c 16 + 17 + static int rtl822x_hwmon_get_temp(int raw) 18 + { 19 + if (raw >= 512) 20 + raw -= 1024; 21 + 22 + return 1000 * raw / 2; 23 + } 24 + 25 + static int rtl822x_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 26 + u32 attr, int channel, long *val) 27 + { 28 + struct phy_device *phydev = dev_get_drvdata(dev); 29 + int raw; 30 + 31 + switch (attr) { 32 + case hwmon_temp_input: 33 + raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSRR) & 0x3ff; 34 + *val = rtl822x_hwmon_get_temp(raw); 35 + break; 36 + case hwmon_temp_max: 37 + /* Chip reduces speed to 1G if threshold is exceeded */ 38 + raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSSR) >> 6; 39 + *val = rtl822x_hwmon_get_temp(raw); 40 + break; 41 + default: 42 + return -EINVAL; 43 + } 44 + 45 + return 0; 46 + } 47 + 48 + static const struct hwmon_ops rtl822x_hwmon_ops = { 49 + .visible = 0444, 50 + .read = rtl822x_hwmon_read, 51 + }; 52 + 53 + static const struct hwmon_channel_info * const rtl822x_hwmon_info[] = { 54 + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX), 55 + NULL 56 + }; 57 + 58 + static const struct hwmon_chip_info rtl822x_hwmon_chip_info = { 59 + .ops = &rtl822x_hwmon_ops, 60 + .info = rtl822x_hwmon_info, 61 + }; 62 + 63 + int rtl822x_hwmon_init(struct phy_device *phydev) 64 + { 65 + struct device *hwdev, *dev = &phydev->mdio.dev; 66 + const char *name; 67 + 68 + /* Ensure over-temp alarm is reset. */ 69 + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSALRM, 3); 70 + 71 + name = devm_hwmon_sanitize_name(dev, dev_name(dev)); 72 + if (IS_ERR(name)) 73 + return PTR_ERR(name); 74 + 75 + hwdev = devm_hwmon_device_register_with_info(dev, name, phydev, 76 + &rtl822x_hwmon_chip_info, 77 + NULL); 78 + return PTR_ERR_OR_ZERO(hwdev); 79 + }
+12
drivers/net/phy/realtek/realtek_main.c
··· 14 14 #include <linux/delay.h> 15 15 #include <linux/clk.h> 16 16 17 + #include "realtek.h" 18 + 17 19 #define RTL821x_PHYSR 0x11 18 20 #define RTL821x_PHYSR_DUPLEX BIT(13) 19 21 #define RTL821x_PHYSR_SPEED GENMASK(15, 14) ··· 822 820 return ret; 823 821 } 824 822 823 + static int rtl822x_probe(struct phy_device *phydev) 824 + { 825 + if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) && 826 + phydev->phy_id != RTL_GENERIC_PHYID) 827 + return rtl822x_hwmon_init(phydev); 828 + 829 + return 0; 830 + } 831 + 825 832 static int rtl822xb_config_init(struct phy_device *phydev) 826 833 { 827 834 bool has_2500, has_sgmii; ··· 1530 1519 .match_phy_device = rtl_internal_nbaset_match_phy_device, 1531 1520 .name = "Realtek Internal NBASE-T PHY", 1532 1521 .flags = PHY_IS_INTERNAL, 1522 + .probe = rtl822x_probe, 1533 1523 .get_features = rtl822x_get_features, 1534 1524 .config_aneg = rtl822x_config_aneg, 1535 1525 .read_status = rtl822x_read_status,