drivers/iio/light/vcnl4035.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iio/light/vcnl4035.c
Extension
.c
Size
17473 bytes
Lines
692
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 vcnl4035_data {
	struct i2c_client *client;
	struct regmap *regmap;
	unsigned int als_it_val;
	unsigned int als_persistence;
	unsigned int als_thresh_low;
	unsigned int als_thresh_high;
	struct iio_trigger *drdy_trigger0;
};

static inline bool vcnl4035_is_triggered(struct vcnl4035_data *data)
{
	int ret;
	int reg;

	ret = regmap_read(data->regmap, VCNL4035_INT_FLAG, &reg);
	if (ret < 0)
		return false;

	return !!(reg &
		(VCNL4035_INT_ALS_IF_H_MASK | VCNL4035_INT_ALS_IF_L_MASK));
}

static irqreturn_t vcnl4035_drdy_irq_thread(int irq, void *private)
{
	struct iio_dev *indio_dev = private;
	struct vcnl4035_data *data = iio_priv(indio_dev);

	if (vcnl4035_is_triggered(data)) {
		iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
							0,
							IIO_EV_TYPE_THRESH,
							IIO_EV_DIR_EITHER),
				iio_get_time_ns(indio_dev));
		iio_trigger_poll_nested(data->drdy_trigger0);
		return IRQ_HANDLED;
	}

	return IRQ_NONE;
}

/* Triggered buffer */
static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p)
{
	struct iio_poll_func *pf = p;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct vcnl4035_data *data = iio_priv(indio_dev);
	/* Ensure naturally aligned timestamp */
	struct {
		u16 als_data;
		aligned_s64 timestamp;
	} buffer = { };
	unsigned int val;
	int ret;

	ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, &val);
	if (ret < 0) {
		dev_err(&data->client->dev,
			"Trigger consumer can't read from sensor.\n");
		goto fail_read;
	}

	buffer.als_data = val;
	iio_push_to_buffers_with_timestamp(indio_dev, &buffer,
					   iio_get_time_ns(indio_dev));

fail_read:
	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;
}

static int vcnl4035_als_drdy_set_state(struct iio_trigger *trigger,
					bool enable_drdy)
{
	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trigger);
	struct vcnl4035_data *data = iio_priv(indio_dev);
	int val = enable_drdy ? VCNL4035_MODE_ALS_INT_ENABLE :
					VCNL4035_MODE_ALS_INT_DISABLE;

	return regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
				 VCNL4035_MODE_ALS_INT_MASK,
				 val);
}

static const struct iio_trigger_ops vcnl4035_trigger_ops = {
	.validate_device = iio_trigger_validate_own_device,
	.set_trigger_state = vcnl4035_als_drdy_set_state,
};

Annotation

Implementation Notes