drivers/thermal/thermal-generic-adc.c

Source file repositories/reference/linux-study-clean/drivers/thermal/thermal-generic-adc.c

File Facts

System
Linux kernel
Corpus path
drivers/thermal/thermal-generic-adc.c
Extension
.c
Size
5448 bytes
Lines
231
Domain
Driver Families
Bucket
drivers/thermal
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 gadc_thermal_info {
	struct device *dev;
	struct thermal_zone_device *tz_dev;
	struct iio_channel *channel;
	s32 *lookup_table;
	int nlookup_table;
};

static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
{
	int temp, temp_hi, temp_lo, adc_hi, adc_lo;
	int i;

	if (!gti->lookup_table)
		return val;

	for (i = 0; i < gti->nlookup_table; i++) {
		if (val >= gti->lookup_table[2 * i + 1])
			break;
	}

	if (i == 0) {
		temp = gti->lookup_table[0];
	} else if (i >= gti->nlookup_table) {
		temp = gti->lookup_table[2 * (gti->nlookup_table - 1)];
	} else {
		adc_hi = gti->lookup_table[2 * i - 1];
		adc_lo = gti->lookup_table[2 * i + 1];

		temp_hi = gti->lookup_table[2 * i - 2];
		temp_lo = gti->lookup_table[2 * i];

		temp = temp_hi + mult_frac(temp_lo - temp_hi, val - adc_hi,
					   adc_lo - adc_hi);
	}

	return temp;
}

static int gadc_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
{
	struct gadc_thermal_info *gti = thermal_zone_device_priv(tz);
	int val;
	int ret;

	ret = iio_read_channel_processed(gti->channel, &val);
	if (ret < 0)
		return ret;

	*temp = gadc_thermal_adc_to_temp(gti, val);

	return 0;
}

static const struct thermal_zone_device_ops gadc_thermal_ops = {
	.get_temp = gadc_thermal_get_temp,
};

static const struct iio_chan_spec gadc_thermal_iio_channels[] = {
	{
		.type = IIO_TEMP,
		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
	}
};

static int gadc_thermal_read_raw(struct iio_dev *indio_dev,
				 struct iio_chan_spec const *chan,
				 int *val, int *val2, long mask)
{
	struct gadc_thermal_info *gtinfo = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_PROCESSED:
		ret = gadc_thermal_get_temp(gtinfo->tz_dev, val);
		if (ret)
			return ret;

		return IIO_VAL_INT;

	default:
		return -EINVAL;
	}
}

static const struct iio_info gadc_thermal_iio_info = {
	.read_raw = gadc_thermal_read_raw,
};

static int gadc_iio_register(struct device *dev, struct gadc_thermal_info *gti)

Annotation

Implementation Notes