drivers/hwmon/adt7x10.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/adt7x10.c
Extension
.c
Size
10172 bytes
Lines
397
Domain
Driver Families
Bucket
drivers/hwmon
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 adt7x10_data {
	struct regmap		*regmap;
	u8			config;
	u8			oldconfig;
	bool			valid;		/* true if temperature valid */
};

enum {
	adt7x10_temperature = 0,
	adt7x10_t_alarm_high,
	adt7x10_t_alarm_low,
	adt7x10_t_crit,
};

static const u8 ADT7X10_REG_TEMP[] = {
	[adt7x10_temperature] = ADT7X10_TEMPERATURE,		/* input */
	[adt7x10_t_alarm_high] = ADT7X10_T_ALARM_HIGH,		/* high */
	[adt7x10_t_alarm_low] = ADT7X10_T_ALARM_LOW,		/* low */
	[adt7x10_t_crit] = ADT7X10_T_CRIT,			/* critical */
};

static irqreturn_t adt7x10_irq_handler(int irq, void *private)
{
	struct device *dev = private;
	struct adt7x10_data *d = dev_get_drvdata(dev);
	unsigned int status;
	int ret;

	ret = regmap_read(d->regmap, ADT7X10_STATUS, &status);
	if (ret < 0)
		return IRQ_HANDLED;

	if (status & ADT7X10_STAT_T_HIGH)
		hwmon_notify_event(dev, hwmon_temp, hwmon_temp_max_alarm, 0);
	if (status & ADT7X10_STAT_T_LOW)
		hwmon_notify_event(dev, hwmon_temp, hwmon_temp_min_alarm, 0);
	if (status & ADT7X10_STAT_T_CRIT)
		hwmon_notify_event(dev, hwmon_temp, hwmon_temp_crit_alarm, 0);

	return IRQ_HANDLED;
}

static int adt7x10_temp_ready(struct regmap *regmap)
{
	unsigned int status;
	int i, ret;

	for (i = 0; i < 6; i++) {
		ret = regmap_read(regmap, ADT7X10_STATUS, &status);
		if (ret < 0)
			return ret;
		if (!(status & ADT7X10_STAT_NOT_RDY))
			return 0;
		msleep(60);
	}
	return -ETIMEDOUT;
}

static s16 ADT7X10_TEMP_TO_REG(long temp)
{
	return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7X10_TEMP_MIN,
					   ADT7X10_TEMP_MAX) * 128, 1000);
}

static int ADT7X10_REG_TO_TEMP(struct adt7x10_data *data, s16 reg)
{
	/* in 13 bit mode, bits 0-2 are status flags - mask them out */
	if (!(data->config & ADT7X10_RESOLUTION))
		reg &= ADT7X10_T13_VALUE_MASK;
	/*
	 * temperature is stored in twos complement format, in steps of
	 * 1/128°C
	 */
	return DIV_ROUND_CLOSEST(reg * 1000, 128);
}

/*-----------------------------------------------------------------------*/

static int adt7x10_temp_read(struct adt7x10_data *data, int index, long *val)
{
	unsigned int regval;
	int ret;

	if (index == adt7x10_temperature && !data->valid) {
		/* wait for valid temperature */
		ret = adt7x10_temp_ready(data->regmap);
		if (ret)
			return ret;
		data->valid = true;
	}

Annotation

Implementation Notes