Commit 0dea3ea7 authored by Federico Vaga's avatar Federico Vaga

Merge branch '38-expose-sensor-output-via-linux-hwmon-api' into 'master'

Resolve "Expose sensor output via Linux-HWMON API"

Closes #38

See merge request be-cem-edl/fec/hardware-modules/fmc-tdc-1ns-5cha!19
parents 4c7db064 59021248
......@@ -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
......@@ -253,9 +253,9 @@ struct fmctdc_dev {
uint8_t ds18_id[8];
/* next temperature measurement pending? */
unsigned long next_t;
/* temperature, degrees Celsius scaled by 16 and its ready flag */
int temp;
int temp_ready;
/* Hardware Monitoring */
char *hwmon_temp_sensor_id;
struct device *hwmon_dev;
/* output lots of debug stuff? */
struct ft_channel_state channels[FT_NUM_CHANNELS];
int wr_mode;
......@@ -383,6 +383,12 @@ static inline void ft_disable(struct fmctdc_dev *ft, unsigned int chan)
ft_writel(ft, ien, TDC_REG_INPUT_ENABLE);
}
extern int ft_temperature_get(struct fmctdc_dev *ft, int *temp);
#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>
*
* Hardware Monitoring for ft-dev
*/
#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)
{
int value, ret;
struct fmctdc_dev *ft = dev_get_drvdata(dev);
switch(attr) {
case hwmon_temp_min:
*val = -25*1000;
return 0;
case hwmon_temp_max:
*val = 60*1000;
return 0;
case hwmon_temp_crit:
*val = 65*1000;
return 0;
}
ret = ft_temperature_get(ft, &value);
if(ret < 0) {
dev_err(dev, "Could not read temperature: %d", ret);
return ret;
}
*val = (long)value * 1000 / 16;
return 0;
}
static int ft_hwmon_temp_sensor_id_read(struct device *dev,
enum hwmon_sensor_types type,
u32 attr, int channel, const char **str)
{
struct fmctdc_dev *ft = dev_get_drvdata(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 | HWMON_T_MIN |
HWMON_T_MAX | HWMON_T_CRIT),
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,
"FMC_TDC_1NS_5CHA",
ft,
&ft_hwmon_temp_chip_info,
NULL);
if(!IS_ERR(ft->hwmon_dev)) {
ft->hwmon_temp_sensor_id = devm_kasprintf(ft->hwmon_dev,
GFP_KERNEL,
"Temperature [%s]",
dev_name(&ft->slot->dev));
if(!ft->hwmon_temp_sensor_id) {
devm_hwmon_device_unregister(dev);
return -ENOMEM;
}
return 0;
}
return PTR_ERR(ft->hwmon_dev);
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) */
......@@ -124,7 +124,7 @@ static int ft_raw_mode_get(struct fmctdc_dev *ft,
static int ft_temperature_get(struct fmctdc_dev *ft, int *temp)
int ft_temperature_get(struct fmctdc_dev *ft, int *temp)
{
int stat = ft_ioread(ft, ft->ft_owregs_base + TDC_OW_REG_CSR);
......@@ -198,7 +198,7 @@ static int ft_zio_info_get(struct device *dev, struct zio_attribute *zattr,
struct zio_device *zdev;
struct fmctdc_dev *ft;
struct zio_attribute *attr;
int ret;
int ret, val;
if (__ft_get_type(dev) == FT_TYPE_INPUT)
return ft_zio_info_channel(dev, zattr, usr_val);
......@@ -212,10 +212,10 @@ static int ft_zio_info_get(struct device *dev, struct zio_attribute *zattr,
*usr_val = ft->mode;
break;
case FT_ATTR_PARAM_TEMP:
ret = ft_temperature_get(ft, &ft->temp);
ret = ft_temperature_get(ft, &val);
if (ret < 0)
return ret;
*usr_val = ft->temp;
*usr_val = val;
break;
case FT_ATTR_DEV_COARSE:
case FT_ATTR_DEV_SECONDS:
......
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