drivers/iio/proximity/vl53l0x-i2c.c

Source file repositories/reference/linux-study-clean/drivers/iio/proximity/vl53l0x-i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/proximity/vl53l0x-i2c.c
Extension
.c
Size
10373 bytes
Lines
420
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 vl53l0x_data {
	struct i2c_client *client;
	struct completion completion;
	struct regulator *vdd_supply;
	struct gpio_desc *reset_gpio;
	struct iio_trigger *trig;
};

static int vl53l0x_clear_irq(struct vl53l0x_data *data)
{	int ret;

	ret = i2c_smbus_write_byte_data(data->client,
					VL_REG_SYSTEM_INTERRUPT_CLEAR, 1);
	if (ret < 0) {
		dev_err(&data->client->dev, "failed to clear irq: %d\n", ret);
		return -EINVAL;
	}

	return 0;
}

static irqreturn_t vl53l0x_trigger_handler(int irq, void *priv)
{
	struct iio_poll_func *pf = priv;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct vl53l0x_data *data = iio_priv(indio_dev);
	u8 buffer[12];
	int ret;
	struct {
		u16 chan;
		aligned_s64 timestamp;
	} scan = { };

	ret = i2c_smbus_read_i2c_block_data(data->client,
					VL_REG_RESULT_RANGE_STATUS,
					sizeof(buffer), buffer);
	if (ret < 0)
		return ret;
	else if (ret != 12)
		return -EREMOTEIO;

	scan.chan = get_unaligned_be16(&buffer[10]);
	iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan),
				    iio_get_time_ns(indio_dev));

	iio_trigger_notify_done(indio_dev->trig);
	vl53l0x_clear_irq(data);

	return IRQ_HANDLED;
}

static irqreturn_t vl53l0x_threaded_irq(int irq, void *priv)
{
	struct iio_dev *indio_dev = priv;
	struct vl53l0x_data *data = iio_priv(indio_dev);

	if (iio_buffer_enabled(indio_dev))
		iio_trigger_poll_nested(indio_dev->trig);
	else
		complete(&data->completion);

	return IRQ_HANDLED;
}

static int vl53l0x_configure_irq(struct i2c_client *client,
				 struct iio_dev *indio_dev)
{
	int irq_flags = irq_get_trigger_type(client->irq);
	struct vl53l0x_data *data = iio_priv(indio_dev);
	int ret;

	if (!irq_flags)
		irq_flags = IRQF_TRIGGER_FALLING;

	ret = devm_request_threaded_irq(&client->dev, client->irq,
			NULL, vl53l0x_threaded_irq,
			irq_flags | IRQF_ONESHOT, indio_dev->name, indio_dev);
	if (ret) {
		dev_err(&client->dev, "devm_request_irq error: %d\n", ret);
		return ret;
	}

	ret = i2c_smbus_write_byte_data(data->client,
			VL_REG_SYSTEM_INTERRUPT_CONFIG_GPIO,
			VL_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY);
	if (ret < 0)
		dev_err(&client->dev, "failed to configure IRQ: %d\n", ret);

	return ret;
}

Annotation

Implementation Notes