Source
x
// SPDX-License-Identifier: GPL-2.0
/*
* System Control and Management Interface(SCMI) based hwmon sensor driver
*
* Copyright (C) 2018 ARM Ltd.
* Sudeep Holla <sudeep.holla@arm.com>
*/
struct scmi_sensors {
const struct scmi_handle *handle;
const struct scmi_sensor_info **info[hwmon_max];
};
static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
int ret;
u64 value;
const struct scmi_sensor_info *sensor;
struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
const struct scmi_handle *h = scmi_sensors->handle;
sensor = *(scmi_sensors->info[type] + channel);
ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
if (!ret)
*val = value;
return ret;
}
static int
scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, const char **str)
{
const struct scmi_sensor_info *sensor;
struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
sensor = *(scmi_sensors->info[type] + channel);
*str = sensor->name;
return 0;
}
static umode_t
scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
u32 attr, int channel)
{
const struct scmi_sensor_info *sensor;
const struct scmi_sensors *scmi_sensors = drvdata;
sensor = *(scmi_sensors->info[type] + channel);
if (sensor)
return 0444;
return 0;
}
static const struct hwmon_ops scmi_hwmon_ops = {
.is_visible = scmi_hwmon_is_visible,
.read = scmi_hwmon_read,
.read_string = scmi_hwmon_read_string,
};
static struct hwmon_chip_info scmi_chip_info = {
.ops = &scmi_hwmon_ops,
.info = NULL,
};
static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan,
struct device *dev, int num,
enum hwmon_sensor_types type, u32 config)
{
int i;
u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
if (!cfg)
return -ENOMEM;
scmi_hwmon_chan->type = type;
scmi_hwmon_chan->config = cfg;
for (i = 0; i < num; i++, cfg++)
*cfg = config;
return 0;
}