Commit 3682c317 authored by Vaibhav Gupta's avatar Vaibhav Gupta

software: kernel: Use HWMON API to expose Temperature

Information from sensors like temperature, which are useful for
user-space, can be exposed via sysfs.

Earlier, the driver developers had to take care of defining the attributes,
initiating them, and perform other related jobs.

But since a long time, the HWMON framework in Linux has developed
significantly. And, utilizing it will reduce lot of maintainence work
for the developers.

All the sysfs related part is handled by the framework which also allows
user-space tools, like lm-sensors, to provide the data to the user in a
simplified manner.
Signed-off-by: 's avatarVaibhav Gupta <vaibhav.gupta@cern.ch>
parent 0e1a7ecd
......@@ -51,6 +51,7 @@ fmc-tdc-objs += ft-fifo.o
fmc-tdc-objs += ft-time.o
fmc-tdc-objs += ft-zio.o
fmc-tdc-objs += ft-debug.o
fmc-tdc-objs += ft-hwmon.o
fmc-tdc-spec-objs := fmc-tdc-spec-core.o
fmc-tdc-svec-objs := fmc-tdc-svec-core.o
......@@ -254,6 +254,7 @@ struct fmctdc_dev {
/* next temperature measurement pending? */
unsigned long next_t;
/* temperature, degrees Celsius scaled by 16 and its ready flag */
struct device *hwmon_dev;
int temp;
int temp_ready;
/* output lots of debug stuff? */
......@@ -385,6 +386,10 @@ static inline void ft_disable(struct fmctdc_dev *ft, unsigned int chan)
extern int ft_temperature_get(struct fmctdc_dev *ft);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
extern int ft_hwmon_init(struct fmctdc_dev *fd);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) */
#endif // __KERNEL__
#endif // __FMC_TDC_H__
......@@ -491,6 +491,13 @@ int ft_probe(struct platform_device *pdev)
ft_writel(ft, TDC_CTRL_EN_ACQ, TDC_REG_CTRL);
platform_set_drvdata(pdev, ft);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
ret = ft_hwmon_init(ft);
if(ret != 0)
dev_err(dev, "Could not create HWMON device: %d", ret);
#endif
return 0;
err:
......
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2023 CERN (home.cern)
/*
* Author: Vaibhav Gupta <vaibhav.gupta@cern.ch>
*/
#include <linux/hwmon.h>
#include "fmc-tdc.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
static umode_t ft_hwmon_temp_is_visible(const void *_data,
enum hwmon_sensor_types type, u32 attr,
int channel)
{
return 0444;
}
static int ft_hwmon_temp_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct fmctdc_dev *ft = dev_get_drvdata(dev);
*val = ft_temperature_get(ft);
if(*val < 0)
dev_err(dev, "Could not read temperature: %d", -EIO);
return 0;
}
static char *ft_hwmon_temp_sensor_id;
static int ft_hwmon_temp_sensor_id_read(struct device *dev,
enum hwmon_sensor_types type,
u32 attr, int channel, const char **str)
{
int size;
char device_type[] = "Temperature - FMC TDC - ";
struct fmctdc_dev *ft = dev_get_drvdata(dev);
size = strlen(dev_name(&ft->slot->dev));
size += strlen(device_type);
size++;
ft_hwmon_temp_sensor_id = kzalloc(size, GFP_KERNEL);
if(!ft_hwmon_temp_sensor_id)
return -ENOMEM;
snprintf(ft_hwmon_temp_sensor_id, size, "%s%s",
device_type, dev_name(&ft->slot->dev));
*str = ft_hwmon_temp_sensor_id;
return 0;
}
static const struct hwmon_channel_info *ft_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL),
NULL
};
static const struct hwmon_ops ft_hwmon_temp_ops = {
.is_visible = ft_hwmon_temp_is_visible,
.read = ft_hwmon_temp_read,
.read_string = ft_hwmon_temp_sensor_id_read
};
static const struct hwmon_chip_info ft_hwmon_temp_chip_info = {
.ops = &ft_hwmon_temp_ops,
.info = ft_hwmon_info,
};
int ft_hwmon_init(struct fmctdc_dev *ft)
{
struct device *dev = &ft->pdev->dev;
ft->hwmon_dev = devm_hwmon_device_register_with_info(dev,
"ft_temperature",
ft,
&ft_hwmon_temp_chip_info,
NULL);
return PTR_ERR_OR_ZERO(ft->hwmon_dev);
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment