drivers/hwmon/scmi-hwmon.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/scmi-hwmon.c
Extension
.c
Size
8808 bytes
Lines
384
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 scmi_sensors {
	const struct scmi_protocol_handle *ph;
	const struct scmi_sensor_info **info[hwmon_max];
};

struct scmi_thermal_sensor {
	const struct scmi_protocol_handle *ph;
	const struct scmi_sensor_info *info;
};

static inline u64 __pow10(u8 x)
{
	u64 r = 1;

	while (x--)
		r *= 10;

	return r;
}

static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value)
{
	int scale = sensor->scale;
	u64 f;

	switch (sensor->type) {
	case TEMPERATURE_C:
	case VOLTAGE:
	case CURRENT:
		scale += 3;
		break;
	case POWER:
	case ENERGY:
		scale += 6;
		break;
	default:
		break;
	}

	if (scale == 0)
		return 0;

	if (abs(scale) > 19)
		return -E2BIG;

	f = __pow10(abs(scale));
	if (scale > 0)
		*value *= f;
	else
		*value = div64_u64(*value, f);

	return 0;
}

static int scmi_hwmon_read_scaled_value(const struct scmi_protocol_handle *ph,
					const struct scmi_sensor_info *sensor,
					long *val)
{
	int ret;
	u64 value;

	ret = sensor_ops->reading_get(ph, sensor->id, &value);
	if (ret)
		return ret;

	ret = scmi_hwmon_scale(sensor, &value);
	if (!ret)
		*val = value;

	return ret;
}

static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
			   u32 attr, int channel, long *val)
{
	const struct scmi_sensor_info *sensor;
	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);

	sensor = *(scmi_sensors->info[type] + channel);

	return scmi_hwmon_read_scaled_value(scmi_sensors->ph, sensor, val);
}

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);

Annotation

Implementation Notes