drivers/hwmon/lineage-pem.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/lineage-pem.c
Extension
.c
Size
14191 bytes
Lines
523
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 pem_data {
	struct i2c_client *client;
	const struct attribute_group *groups[4];

	struct mutex update_lock;
	bool valid;
	bool fans_supported;
	int input_length;
	unsigned long last_updated;	/* in jiffies */

	u8 firmware_rev[FIRMWARE_REV_LEN];
	u8 data_string[DATA_STRING_LEN];
	u8 input_string[INPUT_STRING_LEN];
	u8 fan_speed[FAN_SPEED_LEN];
};

static int pem_read_block(struct i2c_client *client, u8 command, u8 *data,
			  int data_len)
{
	u8 block_buffer[I2C_SMBUS_BLOCK_MAX];
	int result;

	result = i2c_smbus_read_block_data(client, command, block_buffer);
	if (unlikely(result < 0))
		goto abort;
	if (unlikely(result == 0xff || result != data_len)) {
		result = -EIO;
		goto abort;
	}
	memcpy(data, block_buffer, data_len);
	result = 0;
abort:
	return result;
}

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

	mutex_lock(&data->update_lock);

	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
		int result;

		/* Read data string */
		result = pem_read_block(client, PEM_READ_DATA_STRING,
					data->data_string,
					sizeof(data->data_string));
		if (unlikely(result < 0)) {
			ret = ERR_PTR(result);
			goto abort;
		}

		/* Read input string */
		if (data->input_length) {
			result = pem_read_block(client, PEM_READ_INPUT_STRING,
						data->input_string,
						data->input_length);
			if (unlikely(result < 0)) {
				ret = ERR_PTR(result);
				goto abort;
			}
		}

		/* Read fan speeds */
		if (data->fans_supported) {
			result = pem_read_block(client, PEM_READ_FAN_SPEED,
						data->fan_speed,
						sizeof(data->fan_speed));
			if (unlikely(result < 0)) {
				ret = ERR_PTR(result);
				goto abort;
			}
		}

		i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS);

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

static long pem_get_data(u8 *data, int len, int index)
{
	long val;

Annotation

Implementation Notes