drivers/iio/light/veml6070.c

Source file repositories/reference/linux-study-clean/drivers/iio/light/veml6070.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/light/veml6070.c
Extension
.c
Size
7927 bytes
Lines
318
Domain
Driver Families
Bucket
drivers/iio
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 veml6070_data {
	struct i2c_client *client1;
	struct i2c_client *client2;
	u8 config;
	struct mutex lock;
	u32 rset;
	int it[4][2];
};

static int veml6070_calc_it(struct device *dev, struct veml6070_data *data)
{
	int i, tmp_it;

	data->rset = 270000;
	device_property_read_u32(dev, "vishay,rset-ohms", &data->rset);

	if (data->rset < 75000 || data->rset > 1200000)
		return dev_err_probe(dev, -EINVAL, "Rset out of range\n");

	/*
	 * convert to kohm to avoid overflows and work with the same units as
	 * in the datasheet and simplify UVI operations.
	 */
	data->rset /= KILO;

	tmp_it = VEML6070_MIN_IT_US * data->rset / VEML6070_MIN_RSET_KOHM;
	for (i = 0; i < ARRAY_SIZE(data->it); i++) {
		data->it[i][0] = (tmp_it << i) / MICRO;
		data->it[i][1] = (tmp_it << i) % MICRO;
	}

	return 0;
}

static int veml6070_get_it(struct veml6070_data *data, int *val, int *val2)
{
	int it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config);

	*val = data->it[it_idx][0];
	*val2 = data->it[it_idx][1];

	return IIO_VAL_INT_PLUS_MICRO;
}

static int veml6070_set_it(struct veml6070_data *data, int val, int val2)
{
	int it_idx;

	for (it_idx = 0; it_idx < ARRAY_SIZE(data->it); it_idx++) {
		if (data->it[it_idx][0] == val && data->it[it_idx][1] == val2)
			break;
	}

	if (it_idx >= ARRAY_SIZE(data->it))
		return -EINVAL;

	data->config = (data->config & ~VEML6070_COMMAND_IT) |
		FIELD_PREP(VEML6070_COMMAND_IT, it_idx);

	return i2c_smbus_write_byte(data->client1, data->config);
}

static int veml6070_read(struct veml6070_data *data)
{
	int ret, it_ms, val, val2;
	u8 msb, lsb;

	guard(mutex)(&data->lock);

	/* disable shutdown */
	ret = i2c_smbus_write_byte(data->client1,
	    data->config & ~VEML6070_COMMAND_SD);
	if (ret < 0)
		return ret;

	veml6070_get_it(data, &val, &val2);
	it_ms = val * MILLI + val2 / (MICRO / MILLI);
	msleep(it_ms + 10);

	ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */
	if (ret < 0)
		return ret;

	msb = ret;

	ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */
	if (ret < 0)
		return ret;

	lsb = ret;

Annotation

Implementation Notes