Skip to content

Commit

Permalink
Merge branch 'net-phy-realtek-add-hwmon-support'
Browse files Browse the repository at this point in the history
Heiner Kallweit says:

====================
net: phy: realtek: add hwmon support

This adds hwmon support for the temperature sensor on RTL822x.
It's available on the standalone versions of the PHY's, and on the
internal PHY's of RTL8125B(P)/RTL8125D/RTL8126.
====================

Link: https://patch.msgid.link/7319d8f9-2d6f-4522-92e8-a8a4990042fb@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Jan 14, 2025
2 parents b56e4d6 + 33700ca commit 7211672
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 7 deletions.
5 changes: 1 addition & 4 deletions drivers/net/phy/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/phy/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions drivers/net/phy/realtek/Kconfig
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions drivers/net/phy/realtek/Makefile
Original file line number Diff line number Diff line change
@@ -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
10 changes: 10 additions & 0 deletions drivers/net/phy/realtek/realtek.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */

#ifndef REALTEK_H
#define REALTEK_H

#include <linux/phy.h>

int rtl822x_hwmon_init(struct phy_device *phydev);

#endif /* REALTEK_H */
79 changes: 79 additions & 0 deletions drivers/net/phy/realtek/realtek_hwmon.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* HWMON support for Realtek PHY's
*
* Author: Heiner Kallweit <hkallweit1@gmail.com>
*/

#include <linux/hwmon.h>
#include <linux/phy.h>

#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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <linux/delay.h>
#include <linux/clk.h>

#include "realtek.h"

#define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX BIT(13)
#define RTL821x_PHYSR_SPEED GENMASK(15, 14)
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 7211672

Please sign in to comment.