diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 9ad3dbfd2f99a..41c15a2c20379 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -350,10 +350,7 @@ config QSEMI_PHY help Currently supports the qs6612 -config REALTEK_PHY - tristate "Realtek PHYs" - help - Supports the Realtek 821x PHY. +source "drivers/net/phy/realtek/Kconfig" config RENESAS_PHY tristate "Renesas PHYs" diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 39b72b4642873..c8dac6e922780 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -95,7 +95,7 @@ obj-$(CONFIG_NXP_CBTX_PHY) += nxp-cbtx.o obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o obj-y += qcom/ obj-$(CONFIG_QSEMI_PHY) += qsemi.o -obj-$(CONFIG_REALTEK_PHY) += realtek.o +obj-$(CONFIG_REALTEK_PHY) += realtek/ obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o obj-$(CONFIG_SMSC_PHY) += smsc.o diff --git a/drivers/net/phy/realtek/Kconfig b/drivers/net/phy/realtek/Kconfig new file mode 100644 index 0000000000000..31935f147d879 --- /dev/null +++ b/drivers/net/phy/realtek/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +config REALTEK_PHY + tristate "Realtek PHYs" + help + Currently supports RTL821x/RTL822x and fast ethernet PHYs + +config REALTEK_PHY_HWMON + def_bool REALTEK_PHY && HWMON + depends on !(REALTEK_PHY=y && HWMON=m) + help + Optional hwmon support for the temperature sensor diff --git a/drivers/net/phy/realtek/Makefile b/drivers/net/phy/realtek/Makefile new file mode 100644 index 0000000000000..dd21cf87f2f18 --- /dev/null +++ b/drivers/net/phy/realtek/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +realtek-y += realtek_main.o +realtek-$(CONFIG_REALTEK_PHY_HWMON) += realtek_hwmon.o +obj-$(CONFIG_REALTEK_PHY) += realtek.o diff --git a/drivers/net/phy/realtek/realtek.h b/drivers/net/phy/realtek/realtek.h new file mode 100644 index 0000000000000..a39b44fa18a09 --- /dev/null +++ b/drivers/net/phy/realtek/realtek.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef REALTEK_H +#define REALTEK_H + +#include + +int rtl822x_hwmon_init(struct phy_device *phydev); + +#endif /* REALTEK_H */ diff --git a/drivers/net/phy/realtek/realtek_hwmon.c b/drivers/net/phy/realtek/realtek_hwmon.c new file mode 100644 index 0000000000000..1ecb410bb9418 --- /dev/null +++ b/drivers/net/phy/realtek/realtek_hwmon.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * HWMON support for Realtek PHY's + * + * Author: Heiner Kallweit + */ + +#include +#include + +#include "realtek.h" + +#define RTL822X_VND2_TSALRM 0xa662 +#define RTL822X_VND2_TSRR 0xbd84 +#define RTL822X_VND2_TSSR 0xb54c + +static int rtl822x_hwmon_get_temp(int raw) +{ + if (raw >= 512) + raw -= 1024; + + return 1000 * raw / 2; +} + +static int rtl822x_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct phy_device *phydev = dev_get_drvdata(dev); + int raw; + + switch (attr) { + case hwmon_temp_input: + raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSRR) & 0x3ff; + *val = rtl822x_hwmon_get_temp(raw); + break; + case hwmon_temp_max: + /* Chip reduces speed to 1G if threshold is exceeded */ + raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSSR) >> 6; + *val = rtl822x_hwmon_get_temp(raw); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct hwmon_ops rtl822x_hwmon_ops = { + .visible = 0444, + .read = rtl822x_hwmon_read, +}; + +static const struct hwmon_channel_info * const rtl822x_hwmon_info[] = { + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX), + NULL +}; + +static const struct hwmon_chip_info rtl822x_hwmon_chip_info = { + .ops = &rtl822x_hwmon_ops, + .info = rtl822x_hwmon_info, +}; + +int rtl822x_hwmon_init(struct phy_device *phydev) +{ + struct device *hwdev, *dev = &phydev->mdio.dev; + const char *name; + + /* Ensure over-temp alarm is reset. */ + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSALRM, 3); + + name = devm_hwmon_sanitize_name(dev, dev_name(dev)); + if (IS_ERR(name)) + return PTR_ERR(name); + + hwdev = devm_hwmon_device_register_with_info(dev, name, phydev, + &rtl822x_hwmon_chip_info, + NULL); + return PTR_ERR_OR_ZERO(hwdev); +} diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek/realtek_main.c similarity index 98% rename from drivers/net/phy/realtek.c rename to drivers/net/phy/realtek/realtek_main.c index f65d7f1f348e7..38149958d95b2 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -14,6 +14,8 @@ #include #include +#include "realtek.h" + #define RTL821x_PHYSR 0x11 #define RTL821x_PHYSR_DUPLEX BIT(13) #define RTL821x_PHYSR_SPEED GENMASK(15, 14) @@ -736,7 +738,11 @@ static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) { int ret; - if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { + if (devnum == MDIO_MMD_VEND2) { + rtl821x_write_page(phydev, regnum >> 4); + ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1)); + rtl821x_write_page(phydev, 0); + } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { rtl821x_write_page(phydev, 0xa5c); ret = __phy_read(phydev, 0x12); rtl821x_write_page(phydev, 0); @@ -760,7 +766,11 @@ static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, { int ret; - if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { + if (devnum == MDIO_MMD_VEND2) { + rtl821x_write_page(phydev, regnum >> 4); + ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val); + rtl821x_write_page(phydev, 0); + } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { rtl821x_write_page(phydev, 0xa5d); ret = __phy_write(phydev, 0x10, val); rtl821x_write_page(phydev, 0); @@ -812,6 +822,15 @@ static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, return ret; } +static int rtl822x_probe(struct phy_device *phydev) +{ + if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) && + phydev->phy_id != RTL_GENERIC_PHYID) + return rtl822x_hwmon_init(phydev); + + return 0; +} + static int rtl822xb_config_init(struct phy_device *phydev) { bool has_2500, has_sgmii; @@ -1511,6 +1530,7 @@ static struct phy_driver realtek_drvs[] = { .match_phy_device = rtl_internal_nbaset_match_phy_device, .name = "Realtek Internal NBASE-T PHY", .flags = PHY_IS_INTERNAL, + .probe = rtl822x_probe, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .read_status = rtl822x_read_status,