drivers/hwmon/max6620.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/max6620.c
Extension
.c
Size
11230 bytes
Lines
496
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 max6620_data {
	struct i2c_client *client;
	bool valid; /* false until following fields are valid */
	unsigned long last_updated; /* in jiffies */

	/* register values */
	u8 fancfg[4];
	u8 fandyn[4];
	u8 fault;
	u16 tach[4];
	u16 target[4];
};

static u8 max6620_fan_div_from_reg(u8 val)
{
	return BIT((val & 0xE0) >> 5);
}

static u16 max6620_fan_rpm_to_tach(u8 div, int rpm)
{
	return (60 * div * MAX6620_CLOCK_FREQ) / (rpm * MAX6620_PULSE_PER_REV);
}

static int max6620_fan_tach_to_rpm(u8 div, u16 tach)
{
	return (60 * div * MAX6620_CLOCK_FREQ) / (tach * MAX6620_PULSE_PER_REV);
}

static int max6620_update_device(struct device *dev)
{
	struct max6620_data *data = dev_get_drvdata(dev);
	struct i2c_client *client = data->client;
	int i, ret;

	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
		for (i = 0; i < 4; i++) {
			ret = i2c_smbus_read_byte_data(client, config_reg[i]);
			if (ret < 0)
				return ret;
			data->fancfg[i] = ret;

			ret = i2c_smbus_read_byte_data(client, dyn_reg[i]);
			if (ret < 0)
				return ret;
			data->fandyn[i] = ret;

			ret = i2c_smbus_read_byte_data(client, tach_reg[i]);
			if (ret < 0)
				return ret;
			data->tach[i] = (ret << 3) & 0x7f8;
			ret = i2c_smbus_read_byte_data(client, tach_reg[i] + 1);
			if (ret < 0)
				return ret;
			data->tach[i] |= (ret >> 5) & 0x7;

			ret = i2c_smbus_read_byte_data(client, target_reg[i]);
			if (ret < 0)
				return ret;
			data->target[i] = (ret << 3) & 0x7f8;
			ret = i2c_smbus_read_byte_data(client, target_reg[i] + 1);
			if (ret < 0)
				return ret;
			data->target[i] |= (ret >> 5) & 0x7;
		}

		/*
		 * Alarms are cleared on read in case the condition that
		 * caused the alarm is removed. Keep the value latched here
		 * for providing the register through different alarm files.
		 */
		ret = i2c_smbus_read_byte_data(client, MAX6620_REG_FAULT);
		if (ret < 0)
			return ret;
		data->fault |= (ret >> 4) & (ret & 0x0F);

		data->last_updated = jiffies;
		data->valid = true;
	}
	return 0;
}

static umode_t
max6620_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
		   int channel)
{
	switch (type) {
	case hwmon_fan:
		switch (attr) {
		case hwmon_fan_alarm:
		case hwmon_fan_input:

Annotation

Implementation Notes