Commit d0bb7817 authored by Vaibhav Gupta's avatar Vaibhav Gupta Committed by Federico Vaga

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 6160f63b
......@@ -61,6 +61,7 @@ fmc-adc-100m14b4ch-y += fa-irq.o
fmc-adc-100m14b4ch-y += fa-debug.o
fmc-adc-100m14b4ch-y += fa-dma.o
fmc-adc-100m14b4ch-y += spi.o
fmc-adc-100m14b4ch-y += fa-hwmon.o
fmc-adc-100m14b4ch-spec-objs := fmc-adc-100m14b4ch-spec-core.o
fmc-adc-100m14b4ch-svec-objs := fmc-adc-100m14b4ch-svec-core.o
......@@ -880,6 +880,12 @@ int fa_probe(struct platform_device *pdev)
if (err < 0)
goto out_irq;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
err = fa_hwmon_init(fa);
if(err != 0)
dev_err(fa->msgdev, "Could not create HWMON device: %d", err);
#endif
return 0;
out_irq:
......
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2023 CERN (home.cern)
/*
* Author: Vaibhav Gupta <vaibhav.gupta@cern.ch>
*
* Hardware Monitoring for fa-dev
*/
#include <linux/hwmon.h>
#include "fmc-adc-100m14b4cha-private.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
static umode_t fa_hwmon_temp_is_visible(const void *_data,
enum hwmon_sensor_types type, u32 attr,
int channel)
{
return 0444;
}
static int fa_hwmon_temp_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct fa_dev *fa = dev_get_drvdata(dev);
*val = fa_temperature_read(fa);
return 0;
}
static int fa_hwmon_temp_sensor_id_read(struct device *dev,
enum hwmon_sensor_types type,
u32 attr, int channel, const char **str)
{
struct fa_dev *fa = dev_get_drvdata(dev);
*str = fa->hwmon_temp_sensor_id;
return 0;
}
static const struct hwmon_channel_info *fa_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL),
NULL
};
static const struct hwmon_ops fa_hwmon_temp_ops = {
.is_visible = fa_hwmon_temp_is_visible,
.read = fa_hwmon_temp_read,
.read_string = fa_hwmon_temp_sensor_id_read
};
static const struct hwmon_chip_info fa_hwmon_temp_chip_info = {
.ops = &fa_hwmon_temp_ops,
.info = fa_hwmon_info,
};
int fa_hwmon_init(struct fa_dev *fa)
{
int size;
char device_type[] = "Temperature - FMC ADC 100M14B4C - ";
struct device *dev = &fa->pdev->dev;
fa->hwmon_dev = devm_hwmon_device_register_with_info(dev,
"fa_temperature",
fa,
&fa_hwmon_temp_chip_info,
NULL);
if(!IS_ERR(fa->hwmon_dev)) {
size = strlen(dev_name(&fa->slot->dev));
size += strlen(device_type);
size++;
fa->hwmon_temp_sensor_id = devm_kzalloc(fa->hwmon_dev,
size, GFP_KERNEL);
if(!fa->hwmon_temp_sensor_id) {
devm_hwmon_device_unregister(dev);
return -ENOMEM;
}
snprintf(fa->hwmon_temp_sensor_id, size, "%s%s",
device_type, dev_name(&fa->slot->dev));
return 0;
}
return PTR_ERR(fa->hwmon_dev);
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) */
......@@ -347,6 +347,10 @@ struct fa_dev {
unsigned long next_t;
int temp; /* temperature: scaled by 4 bits */
/* HWMON */
char *hwmon_temp_sensor_id;
struct device *hwmon_dev;
/* Calibration Data */
struct fa_calib calib;
int32_t range[FA100M14B4C_NCHAN];
......@@ -567,4 +571,8 @@ extern void fa_calib_config_chan(struct fa_dev *fa, unsigned int chan,
extern int fa_debug_init(struct fa_dev *fa);
extern void fa_debug_exit(struct fa_dev *fa);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
extern int fa_hwmon_init(struct fa_dev *fa);
#endif
#endif /* FMC_ADC_H_ */
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