drivers/hwmon/tmp108.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/tmp108.c
Extension
.c
Size
16351 bytes
Lines
601
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 tmp108 {
	struct regmap *regmap;
	u16 orig_config;
	unsigned long ready_time;
	const struct tmp108_params *params;
};

struct tmp108_params {
	bool config_reg_16bits;
	const u16 *sample_times;
	size_t n_sample_times;
};

static const u16 p3t1035_sample_times[] = {4000, 1000, 250, 125};
static const u16 tmp108_sample_times[] = {4000, 1000, 250, 63};

static const struct tmp108_params p3t1035_data = {
	.sample_times = p3t1035_sample_times,
	.n_sample_times  = ARRAY_SIZE(p3t1035_sample_times),
	.config_reg_16bits = false,
};

static const struct tmp108_params tmp108_data = {
	.sample_times = tmp108_sample_times,
	.n_sample_times  = ARRAY_SIZE(tmp108_sample_times),
	.config_reg_16bits = true,
};

/* convert 12-bit TMP108 register value to milliCelsius */
static inline int tmp108_temp_reg_to_mC(s16 val)
{
	return (val & ~0x0f) * 1000 / 256;
}

/* convert milliCelsius to left adjusted 12-bit TMP108 register value */
static inline u16 tmp108_mC_to_temp_reg(int val)
{
	return (val * 256) / 1000;
}

static int tmp108_read(struct device *dev, enum hwmon_sensor_types type,
		       u32 attr, int channel, long *temp)
{
	struct tmp108 *tmp108 = dev_get_drvdata(dev);
	unsigned int regval;
	int err, hyst;

	if (type == hwmon_chip) {
		if (attr == hwmon_chip_update_interval) {
			err = regmap_read(tmp108->regmap, TMP108_REG_CONF,
					  &regval);
			if (err < 0)
				return err;
			*temp = tmp108->params->sample_times[FIELD_GET(TMP108_CONF_CONVRATE_FLD,
								       regval)];
			return 0;
		}
		return -EOPNOTSUPP;
	}

	switch (attr) {
	case hwmon_temp_input:
		/* Is it too early to return a conversion ? */
		if (time_before(jiffies, tmp108->ready_time)) {
			dev_dbg(dev, "%s: Conversion not ready yet..\n",
				__func__);
			return -EAGAIN;
		}
		err = regmap_read(tmp108->regmap, TMP108_REG_TEMP, &regval);
		if (err < 0)
			return err;
		*temp = tmp108_temp_reg_to_mC(regval);
		break;
	case hwmon_temp_min:
	case hwmon_temp_max:
		err = regmap_read(tmp108->regmap, attr == hwmon_temp_min ?
				  TMP108_REG_TLOW : TMP108_REG_THIGH, &regval);
		if (err < 0)
			return err;
		*temp = tmp108_temp_reg_to_mC(regval);
		break;
	case hwmon_temp_min_alarm:
	case hwmon_temp_max_alarm:
		err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &regval);
		if (err < 0)
			return err;
		*temp = !!(regval & (attr == hwmon_temp_min_alarm ?
				     TMP108_CONF_FL : TMP108_CONF_FH));
		break;
	case hwmon_temp_min_hyst:

Annotation

Implementation Notes