nixos/spec/reimaden/ac71/hwmon_fan.c

153 lines
3 KiB
C

// SPDX-License-Identifier: GPL-2.0
#include "pr.h"
#include <linux/device.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/init.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include "ec.h"
#include "fan.h"
#include "pdev.h"
/* ========================================================================== */
static struct device *ac71_hwmon_fan_dev;
/* ========================================================================== */
static umode_t ac71_hwmon_fan_is_visible(const void *data, enum hwmon_sensor_types type,
u32 attr, int channel)
{
switch (type) {
case hwmon_fan:
switch (attr) {
case hwmon_fan_input:
case hwmon_fan_fault:
return 0444;
}
break;
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
case hwmon_temp_label:
return 0444;
}
default:
break;
}
return 0;
}
static int ac71_hwmon_fan_read(struct device *device, enum hwmon_sensor_types type,
u32 attr, int channel, long *value)
{
int err;
switch (type) {
case hwmon_fan:
switch (attr) {
case hwmon_fan_input:
err = ac71_fan_get_rpm(channel);
if (err < 0)
return err;
*value = err;
break;
default:
return -EOPNOTSUPP;
}
break;
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
err = ac71_fan_get_temp(channel);
if (err < 0)
return err;
*value = err * 1000;
break;
default:
return -EOPNOTSUPP;
}
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
static int ac71_hwmon_fan_read_string(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, const char **str)
{
static const char * const temp_labels[] = {
"fan1_temp",
"fan2_temp",
};
switch (type) {
case hwmon_temp:
switch (attr) {
case hwmon_temp_label:
*str = temp_labels[channel];
break;
default:
return -EOPNOTSUPP;
}
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
/* ========================================================================== */
static const struct hwmon_channel_info *ac71_hwmon_fan_ch_info[] = {
HWMON_CHANNEL_INFO(fan,
HWMON_F_INPUT,
HWMON_F_INPUT),
HWMON_CHANNEL_INFO(temp,
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL),
NULL
};
static const struct hwmon_ops ac71_hwmon_fan_ops = {
.is_visible = ac71_hwmon_fan_is_visible,
.read = ac71_hwmon_fan_read,
.read_string = ac71_hwmon_fan_read_string,
};
static const struct hwmon_chip_info ac71_hwmon_fan_chip_info = {
.ops = &ac71_hwmon_fan_ops,
.info = ac71_hwmon_fan_ch_info,
};
/* ========================================================================== */
int __init ac71_hwmon_fan_setup(void)
{
int err = 0;
ac71_hwmon_fan_dev = hwmon_device_register_with_info(
&ac71_platform_dev->dev, KBUILD_MODNAME ".hwmon.fan", NULL,
&ac71_hwmon_fan_chip_info, NULL);
if (IS_ERR(ac71_hwmon_fan_dev))
err = PTR_ERR(ac71_hwmon_fan_dev);
return err;
}
void ac71_hwmon_fan_cleanup(void)
{
if (!IS_ERR_OR_NULL(ac71_hwmon_fan_dev))
hwmon_device_unregister(ac71_hwmon_fan_dev);
}