drivers/hwmon/scpi-hwmon.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/scpi-hwmon.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/scpi-hwmon.c
Extension
.c
Size
8235 bytes
Lines
307
Domain
Driver Families
Bucket
drivers/hwmon
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sensor_data {
	unsigned int scale;
	struct scpi_sensor_info info;
	struct device_attribute dev_attr_input;
	struct device_attribute dev_attr_label;
	char input[20];
	char label[20];
};

struct scpi_thermal_zone {
	int sensor_id;
	struct scpi_sensors *scpi_sensors;
};

struct scpi_sensors {
	struct scpi_ops *scpi_ops;
	struct sensor_data *data;
	struct list_head thermal_zones;
	struct attribute **attrs;
	struct attribute_group group;
	const struct attribute_group *groups[2];
};

static const u32 gxbb_scpi_scale[] = {
	[TEMPERATURE]	= 1,		/* (celsius)		*/
	[VOLTAGE]	= 1000,		/* (millivolts)		*/
	[CURRENT]	= 1000,		/* (milliamperes)	*/
	[POWER]		= 1000000,	/* (microwatts)		*/
	[ENERGY]	= 1000000,	/* (microjoules)	*/
};

static const u32 scpi_scale[] = {
	[TEMPERATURE]	= 1000,		/* (millicelsius)	*/
	[VOLTAGE]	= 1000,		/* (millivolts)		*/
	[CURRENT]	= 1000,		/* (milliamperes)	*/
	[POWER]		= 1000000,	/* (microwatts)		*/
	[ENERGY]	= 1000000,	/* (microjoules)	*/
};

static void scpi_scale_reading(u64 *value, struct sensor_data *sensor)
{
	if (scpi_scale[sensor->info.class] != sensor->scale) {
		*value *= scpi_scale[sensor->info.class];
		do_div(*value, sensor->scale);
	}
}

static int scpi_read_temp(struct thermal_zone_device *tz, int *temp)
{
	struct scpi_thermal_zone *zone = thermal_zone_device_priv(tz);
	struct scpi_sensors *scpi_sensors = zone->scpi_sensors;
	struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops;
	struct sensor_data *sensor = &scpi_sensors->data[zone->sensor_id];
	u64 value;
	int ret;

	ret = scpi_ops->sensor_get_value(sensor->info.sensor_id, &value);
	if (ret)
		return ret;

	scpi_scale_reading(&value, sensor);

	*temp = value;
	return 0;
}

/* hwmon callback functions */
static ssize_t
scpi_show_sensor(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct scpi_sensors *scpi_sensors = dev_get_drvdata(dev);
	struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops;
	struct sensor_data *sensor;
	u64 value;
	int ret;

	sensor = container_of(attr, struct sensor_data, dev_attr_input);

	ret = scpi_ops->sensor_get_value(sensor->info.sensor_id, &value);
	if (ret)
		return ret;

	scpi_scale_reading(&value, sensor);

	/*
	 * Temperature sensor values are treated as signed values based on
	 * observation even though that is not explicitly specified, and
	 * because an unsigned u64 temperature does not really make practical
	 * sense especially when the temperature is below zero degrees Celsius.
	 */

Annotation

Implementation Notes