Commit 269e67b2 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 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>
*/
#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 char *fa_hwmon_temp_sensor_id;
static int fa_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 ADC 100M14B4C - ";
struct fa_dev *fa = dev_get_drvdata(dev);
size = strlen(dev_name(&fa->slot->dev));
size += strlen(device_type);
size++;
fa_hwmon_temp_sensor_id = kzalloc(size, GFP_KERNEL);
if(!fa_hwmon_temp_sensor_id)
return -ENOMEM;
snprintf(fa_hwmon_temp_sensor_id, size, "%s%s",
device_type, dev_name(&fa->slot->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)
{
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);
return PTR_ERR_OR_ZERO(fa->hwmon_dev);
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) */
......@@ -345,6 +345,7 @@ struct fa_dev {
/* one-wire */
uint8_t ds18_id[8];
unsigned long next_t;
struct device *hwmon_dev;
int temp; /* temperature: scaled by 4 bits */
/* Calibration Data */
......@@ -567,4 +568,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