drivers/hwmon/ds620.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/ds620.c
Extension
.c
Size
6714 bytes
Lines
256
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 ds620_data {
	struct i2c_client *client;
	struct mutex update_lock;
	bool valid;		/* true if following fields are valid */
	unsigned long last_updated;	/* In jiffies */

	s16 temp[3];		/* Register values, word */
};

static void ds620_init_client(struct i2c_client *client)
{
	struct ds620_platform_data *ds620_info = dev_get_platdata(&client->dev);
	u16 conf, new_conf;

	new_conf = conf =
	    i2c_smbus_read_word_swapped(client, DS620_REG_CONF);

	/* switch to continuous conversion mode */
	new_conf &= ~DS620_REG_CONFIG_1SHOT;
	/* already high at power-on, but don't trust the BIOS! */
	new_conf |= DS620_REG_CONFIG_PO2;
	/* thermostat mode according to platform data */
	if (ds620_info && ds620_info->pomode == 1)
		new_conf &= ~DS620_REG_CONFIG_PO1; /* PO_LOW */
	else if (ds620_info && ds620_info->pomode == 2)
		new_conf |= DS620_REG_CONFIG_PO1; /* PO_HIGH */
	else
		new_conf &= ~DS620_REG_CONFIG_PO2; /* always low */
	/* with highest precision */
	new_conf |= DS620_REG_CONFIG_R1 | DS620_REG_CONFIG_R0;

	if (conf != new_conf)
		i2c_smbus_write_word_swapped(client, DS620_REG_CONF, new_conf);

	/* start conversion */
	i2c_smbus_write_byte(client, DS620_COM_START);
}

static struct ds620_data *ds620_update_client(struct device *dev)
{
	struct ds620_data *data = dev_get_drvdata(dev);
	struct i2c_client *client = data->client;
	struct ds620_data *ret = data;

	mutex_lock(&data->update_lock);

	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
	    || !data->valid) {
		int i;
		int res;

		dev_dbg(&client->dev, "Starting ds620 update\n");

		for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
			res = i2c_smbus_read_word_swapped(client,
							  DS620_REG_TEMP[i]);
			if (res < 0) {
				ret = ERR_PTR(res);
				goto abort;
			}

			data->temp[i] = res;
		}

		data->last_updated = jiffies;
		data->valid = true;
	}
abort:
	mutex_unlock(&data->update_lock);

	return ret;
}

static ssize_t temp_show(struct device *dev, struct device_attribute *da,
			 char *buf)
{
	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
	struct ds620_data *data = ds620_update_client(dev);

	if (IS_ERR(data))
		return PTR_ERR(data);

	return sprintf(buf, "%d\n", ((data->temp[attr->index] / 8) * 625) / 10);
}

static ssize_t temp_store(struct device *dev, struct device_attribute *da,
			  const char *buf, size_t count)
{
	int res;
	long val;

Annotation

Implementation Notes